source: protocols/jabber/xmlparse.c @ cdca30b

Last change on this file since cdca30b was 5d6c178, checked in by Jelmer Vernooij <jelmer@…>, at 2006-05-10T12:47:55Z

Fix compilation with tcc

  • Property mode set to 100644
File size: 90.5 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(&initEncoding, &encoding, s) : 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(isGeneralTextEntity,
1478                               encoding,
1479                               s,
1480                               next,
1481                               &eventPtr,
1482                               &version,
1483                               &encodingName,
1484                               &newEncoding,
1485                               &standalone)
1486            : XmlParseXmlDecl(isGeneralTextEntity,
1487                               encoding,
1488                               s,
1489                               next,
1490                               &eventPtr,
1491                               &version,
1492                               &encodingName,
1493                               &newEncoding,
1494                               &standalone)))
1495        return XML_ERROR_SYNTAX;
1496    if (!isGeneralTextEntity && standalone == 1)
1497        dtd.standalone = 1;
1498    if (defaultHandler)
1499        reportDefault(parser, encoding, s, next);
1500    if (!protocolEncodingName) {
1501        if (newEncoding) {
1502            if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
1503                eventPtr = encodingName;
1504                return XML_ERROR_INCORRECT_ENCODING;
1505            }
1506            encoding = newEncoding;
1507        }
1508        else if (encodingName) {
1509            enum XML_Error result;
1510            const XML_Char *s = poolStoreString(&tempPool,
1511                                                encoding,
1512                                                encodingName,
1513                                                encodingName
1514                                                + XmlNameLength(encoding, encodingName));
1515            if (!s)
1516                return XML_ERROR_NO_MEMORY;
1517            result = handleUnknownEncoding(parser, s);
1518            poolDiscard(&tempPool);
1519            if (result == XML_ERROR_UNKNOWN_ENCODING)
1520                eventPtr = encodingName;
1521            return result;
1522        }
1523    }
1524    return XML_ERROR_NONE;
1525}
1526
1527static enum XML_Error
1528handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
1529{
1530    if (unknownEncodingHandler) {
1531        XML_Encoding info;
1532        int i;
1533        for (i = 0; i < 256; i++)
1534            info.map[i] = -1;
1535        info.convert = 0;
1536        info.data = 0;
1537        info.release = 0;
1538        if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
1539            ENCODING *enc;
1540            unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
1541            if (!unknownEncodingMem) {
1542                if (info.release)
1543                    info.release(info.data);
1544                return XML_ERROR_NO_MEMORY;
1545            }
1546            enc = (ns
1547                   ? XmlInitUnknownEncodingNS(unknownEncodingMem,
1548                                             info.map,
1549                                             info.convert,
1550                                             info.data)
1551                   : XmlInitUnknownEncoding(unknownEncodingMem,
1552                                             info.map,
1553                                             info.convert,
1554                                             info.data));
1555            if (enc) {
1556                unknownEncodingData = info.data;
1557                unknownEncodingRelease = info.release;
1558                encoding = enc;
1559                return XML_ERROR_NONE;
1560            }
1561        }
1562        if (info.release)
1563            info.release(info.data);
1564    }
1565    return XML_ERROR_UNKNOWN_ENCODING;
1566}
1567
1568static enum XML_Error
1569prologInitProcessor(XML_Parser parser,
1570                    const char *s,
1571                    const char *end,
1572                    const char **nextPtr)
1573{
1574    enum XML_Error result = initializeEncoding(parser);
1575    if (result != XML_ERROR_NONE)
1576        return result;
1577    processor = prologProcessor;
1578    return prologProcessor(parser, s, end, nextPtr);
1579}
1580
1581static enum XML_Error
1582prologProcessor(XML_Parser parser,
1583                const char *s,
1584                const char *end,
1585                const char **nextPtr)
1586{
1587    for (;;) {
1588        const char *next;
1589        int tok = XmlPrologTok(encoding, s, end, &next);
1590        if (tok <= 0) {
1591            if (nextPtr != 0 && tok != XML_TOK_INVALID) {
1592                *nextPtr = s;
1593                return XML_ERROR_NONE;
1594            }
1595            switch (tok) {
1596            case XML_TOK_INVALID:
1597                eventPtr = next;
1598                return XML_ERROR_INVALID_TOKEN;
1599            case XML_TOK_NONE:
1600                return XML_ERROR_NO_ELEMENTS;
1601            case XML_TOK_PARTIAL:
1602                return XML_ERROR_UNCLOSED_TOKEN;
1603            case XML_TOK_PARTIAL_CHAR:
1604                return XML_ERROR_PARTIAL_CHAR;
1605            case XML_TOK_TRAILING_CR:
1606                eventPtr = s + encoding->minBytesPerChar;
1607                return XML_ERROR_NO_ELEMENTS;
1608            default:
1609                abort();
1610            }
1611        }
1612        switch (XmlTokenRole(&prologState, tok, s, next, encoding)) {
1613        case XML_ROLE_XML_DECL:
1614            {
1615                enum XML_Error result = processXmlDecl(parser, 0, s, next);
1616                if (result != XML_ERROR_NONE)
1617                    return result;
1618            }
1619            break;
1620        case XML_ROLE_DOCTYPE_SYSTEM_ID:
1621            if (!dtd.standalone
1622                    && notStandaloneHandler
1623                    && !notStandaloneHandler(handlerArg))
1624                return XML_ERROR_NOT_STANDALONE;
1625            hadExternalDoctype = 1;
1626            break;
1627        case XML_ROLE_DOCTYPE_PUBLIC_ID:
1628        case XML_ROLE_ENTITY_PUBLIC_ID:
1629            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
1630                return XML_ERROR_SYNTAX;
1631            if (declEntity) {
1632                XML_Char *tem = poolStoreString(&dtd.pool,
1633                                                encoding,
1634                                                s + encoding->minBytesPerChar,
1635                                                next - encoding->minBytesPerChar);
1636                if (!tem)
1637                    return XML_ERROR_NO_MEMORY;
1638                normalizePublicId(tem);
1639                declEntity->publicId = tem;
1640                poolFinish(&dtd.pool);
1641            }
1642            break;
1643        case XML_ROLE_INSTANCE_START:
1644            processor = contentProcessor;
1645            if (hadExternalDoctype)
1646                dtd.complete = 0;
1647            return contentProcessor(parser, s, end, nextPtr);
1648        case XML_ROLE_ATTLIST_ELEMENT_NAME:
1649            {
1650                const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
1651                if (!name)
1652                    return XML_ERROR_NO_MEMORY;
1653                declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
1654                if (!declElementType)
1655                    return XML_ERROR_NO_MEMORY;
1656                if (declElementType->name != name)
1657                    poolDiscard(&dtd.pool);
1658                else {
1659                    poolFinish(&dtd.pool);
1660                    if (!setElementTypePrefix(parser, declElementType))
1661                        return XML_ERROR_NO_MEMORY;
1662                }
1663                break;
1664            }
1665        case XML_ROLE_ATTRIBUTE_NAME:
1666            declAttributeId = getAttributeId(parser, encoding, s, next);
1667            if (!declAttributeId)
1668                return XML_ERROR_NO_MEMORY;
1669            declAttributeIsCdata = 0;
1670            break;
1671        case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
1672            declAttributeIsCdata = 1;
1673            break;
1674        case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
1675        case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
1676            if (dtd.complete
1677                    && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0))
1678                return XML_ERROR_NO_MEMORY;
1679            break;
1680        case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
1681        case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
1682            {
1683                const XML_Char *attVal;
1684                enum XML_Error result
1685                = storeAttributeValue(parser, encoding, declAttributeIsCdata,
1686                                      s + encoding->minBytesPerChar,
1687                                      next - encoding->minBytesPerChar,
1688                                      &dtd.pool);
1689                if (result)
1690                    return result;
1691                attVal = poolStart(&dtd.pool);
1692                poolFinish(&dtd.pool);
1693                if (dtd.complete
1694                        && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal))
1695                    return XML_ERROR_NO_MEMORY;
1696                break;
1697            }
1698        case XML_ROLE_ENTITY_VALUE:
1699            {
1700                enum XML_Error result = storeEntityValue(parser, s, next);
1701                if (result != XML_ERROR_NONE)
1702                    return result;
1703            }
1704            break;
1705        case XML_ROLE_ENTITY_SYSTEM_ID:
1706            if (declEntity) {
1707                declEntity->systemId = poolStoreString(&dtd.pool, encoding,
1708                                                       s + encoding->minBytesPerChar,
1709                                                       next - encoding->minBytesPerChar);
1710                if (!declEntity->systemId)
1711                    return XML_ERROR_NO_MEMORY;
1712                declEntity->base = dtd.base;
1713                poolFinish(&dtd.pool);
1714            }
1715            break;
1716        case XML_ROLE_ENTITY_NOTATION_NAME:
1717            if (declEntity) {
1718                declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next);
1719                if (!declEntity->notation)
1720                    return XML_ERROR_NO_MEMORY;
1721                poolFinish(&dtd.pool);
1722                if (unparsedEntityDeclHandler) {
1723                    eventPtr = eventEndPtr = s;
1724                    unparsedEntityDeclHandler(handlerArg,
1725                                              declEntity->name,
1726                                              declEntity->base,
1727                                              declEntity->systemId,
1728                                              declEntity->publicId,
1729                                              declEntity->notation);
1730                }
1731
1732            }
1733            break;
1734        case XML_ROLE_GENERAL_ENTITY_NAME:
1735            {
1736                const XML_Char *name;
1737                if (XmlPredefinedEntityName(encoding, s, next)) {
1738                    declEntity = 0;
1739                    break;
1740                }
1741                name = poolStoreString(&dtd.pool, encoding, s, next);
1742                if (!name)
1743                    return XML_ERROR_NO_MEMORY;
1744                if (dtd.complete) {
1745                    declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
1746                    if (!declEntity)
1747                        return XML_ERROR_NO_MEMORY;
1748                    if (declEntity->name != name) {
1749                        poolDiscard(&dtd.pool);
1750                        declEntity = 0;
1751                    }
1752                    else
1753                        poolFinish(&dtd.pool);
1754                }
1755                else {
1756                    poolDiscard(&dtd.pool);
1757                    declEntity = 0;
1758                }
1759            }
1760            break;
1761        case XML_ROLE_PARAM_ENTITY_NAME:
1762            declEntity = 0;
1763            break;
1764        case XML_ROLE_NOTATION_NAME:
1765            declNotationPublicId = 0;
1766            declNotationName = 0;
1767            if (notationDeclHandler) {
1768                declNotationName = poolStoreString(&tempPool, encoding, s, next);
1769                if (!declNotationName)
1770                    return XML_ERROR_NO_MEMORY;
1771                poolFinish(&tempPool);
1772            }
1773            break;
1774        case XML_ROLE_NOTATION_PUBLIC_ID:
1775            if (!XmlIsPublicId(encoding, s, next, &eventPtr))
1776                return XML_ERROR_SYNTAX;
1777            if (declNotationName) {
1778                XML_Char *tem = poolStoreString(&tempPool,
1779                                                encoding,
1780                                                s + encoding->minBytesPerChar,
1781                                                next - encoding->minBytesPerChar);
1782                if (!tem)
1783                    return XML_ERROR_NO_MEMORY;
1784                normalizePublicId(tem);
1785                declNotationPublicId = tem;
1786                poolFinish(&tempPool);
1787            }
1788            break;
1789        case XML_ROLE_NOTATION_SYSTEM_ID:
1790            if (declNotationName && notationDeclHandler) {
1791                const XML_Char *systemId
1792                = poolStoreString(&tempPool, encoding,
1793                                  s + encoding->minBytesPerChar,
1794                                  next - encoding->minBytesPerChar);
1795                if (!systemId)
1796                    return XML_ERROR_NO_MEMORY;
1797                eventPtr = eventEndPtr = s;
1798                notationDeclHandler(handlerArg,
1799                                    declNotationName,
1800                                    dtd.base,
1801                                    systemId,
1802                                    declNotationPublicId);
1803            }
1804            poolClear(&tempPool);
1805            break;
1806        case XML_ROLE_NOTATION_NO_SYSTEM_ID:
1807            if (declNotationPublicId && notationDeclHandler) {
1808                eventPtr = eventEndPtr = s;
1809                notationDeclHandler(handlerArg,
1810                                    declNotationName,
1811                                    dtd.base,
1812                                    0,
1813                                    declNotationPublicId);
1814            }
1815            poolClear(&tempPool);
1816            break;
1817        case XML_ROLE_ERROR:
1818            eventPtr = s;
1819            switch (tok) {
1820            case XML_TOK_PARAM_ENTITY_REF:
1821                return XML_ERROR_PARAM_ENTITY_REF;
1822            case XML_TOK_XML_DECL:
1823                return XML_ERROR_MISPLACED_XML_PI;
1824            default:
1825                return XML_ERROR_SYNTAX;
1826            }
1827        case XML_ROLE_GROUP_OPEN:
1828            if (prologState.level >= groupSize) {
1829                if (groupSize)
1830                    groupConnector = realloc(groupConnector, groupSize *= 2);
1831                else
1832                    groupConnector = malloc(groupSize = 32);
1833                if (!groupConnector)
1834                    return XML_ERROR_NO_MEMORY;
1835            }
1836            groupConnector[prologState.level] = 0;
1837            break;
1838        case XML_ROLE_GROUP_SEQUENCE:
1839            if (groupConnector[prologState.level] == '|') {
1840                eventPtr = s;
1841                return XML_ERROR_SYNTAX;
1842            }
1843            groupConnector[prologState.level] = ',';
1844            break;
1845        case XML_ROLE_GROUP_CHOICE:
1846            if (groupConnector[prologState.level] == ',') {
1847                eventPtr = s;
1848                return XML_ERROR_SYNTAX;
1849            }
1850            groupConnector[prologState.level] = '|';
1851            break;
1852        case XML_ROLE_PARAM_ENTITY_REF:
1853            if (!dtd.standalone
1854                    && notStandaloneHandler
1855                    && !notStandaloneHandler(handlerArg))
1856                return XML_ERROR_NOT_STANDALONE;
1857            dtd.complete = 0;
1858            break;
1859        case XML_ROLE_NONE:
1860            switch (tok) {
1861            case XML_TOK_PI:
1862                eventPtr = s;
1863                eventEndPtr = next;
1864                if (!reportProcessingInstruction(parser, encoding, s, next))
1865                    return XML_ERROR_NO_MEMORY;
1866                break;
1867            case XML_TOK_COMMENT:
1868                eventPtr = s;
1869                eventEndPtr = next;
1870                if (!reportComment(parser, encoding, s, next))
1871                    return XML_ERROR_NO_MEMORY;
1872                break;
1873            }
1874            break;
1875        }
1876        if (defaultHandler) {
1877            switch (tok) {
1878            case XML_TOK_PI:
1879            case XML_TOK_COMMENT:
1880            case XML_TOK_BOM:
1881            case XML_TOK_XML_DECL:
1882                break;
1883            default:
1884                eventPtr = s;
1885                eventEndPtr = next;
1886                reportDefault(parser, encoding, s, next);
1887            }
1888        }
1889        s = next;
1890    }
1891    /* not reached */
1892}
1893
1894static
1895enum XML_Error epilogProcessor(XML_Parser parser,
1896                               const char *s,
1897                               const char *end,
1898                               const char **nextPtr)
1899{
1900    processor = epilogProcessor;
1901    eventPtr = s;
1902    for (;;) {
1903        const char *next;
1904        int tok = XmlPrologTok(encoding, s, end, &next);
1905        eventEndPtr = next;
1906        switch (tok) {
1907        case XML_TOK_TRAILING_CR:
1908            if (defaultHandler) {
1909                eventEndPtr = end;
1910                reportDefault(parser, encoding, s, end);
1911            }
1912            /* fall through */
1913        case XML_TOK_NONE:
1914            if (nextPtr)
1915                *nextPtr = end;
1916            return XML_ERROR_NONE;
1917        case XML_TOK_PROLOG_S:
1918            if (defaultHandler)
1919                reportDefault(parser, encoding, s, next);
1920            break;
1921        case XML_TOK_PI:
1922            if (!reportProcessingInstruction(parser, encoding, s, next))
1923                return XML_ERROR_NO_MEMORY;
1924            break;
1925        case XML_TOK_COMMENT:
1926            if (!reportComment(parser, encoding, s, next))
1927                return XML_ERROR_NO_MEMORY;
1928            break;
1929        case XML_TOK_INVALID:
1930            eventPtr = next;
1931            return XML_ERROR_INVALID_TOKEN;
1932        case XML_TOK_PARTIAL:
1933            if (nextPtr) {
1934                *nextPtr = s;
1935                return XML_ERROR_NONE;
1936            }
1937            return XML_ERROR_UNCLOSED_TOKEN;
1938        case XML_TOK_PARTIAL_CHAR:
1939            if (nextPtr) {
1940                *nextPtr = s;
1941                return XML_ERROR_NONE;
1942            }
1943            return XML_ERROR_PARTIAL_CHAR;
1944        default:
1945            return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
1946        }
1947        eventPtr = s = next;
1948    }
1949}
1950
1951static enum XML_Error
1952storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
1953                    const char *ptr, const char *end,
1954                    STRING_POOL *pool)
1955{
1956    enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
1957    if (result)
1958        return result;
1959    if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
1960        poolChop(pool);
1961    if (!poolAppendChar(pool, XML_T('\0')))
1962        return XML_ERROR_NO_MEMORY;
1963    return XML_ERROR_NONE;
1964}
1965
1966static enum XML_Error
1967appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
1968                     const char *ptr, const char *end,
1969                     STRING_POOL *pool)
1970{
1971    const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
1972    for (;;) {
1973        const char *next;
1974        int tok = XmlAttributeValueTok(enc, ptr, end, &next);
1975        switch (tok) {
1976        case XML_TOK_NONE:
1977            return XML_ERROR_NONE;
1978        case XML_TOK_INVALID:
1979            if (enc == encoding)
1980                eventPtr = next;
1981            return XML_ERROR_INVALID_TOKEN;
1982        case XML_TOK_PARTIAL:
1983            if (enc == encoding)
1984                eventPtr = ptr;
1985            return XML_ERROR_INVALID_TOKEN;
1986        case XML_TOK_CHAR_REF:
1987            {
1988                XML_Char buf[XML_ENCODE_MAX];
1989                int i;
1990                int n = XmlCharRefNumber(enc, ptr);
1991                if (n < 0) {
1992                    if (enc == encoding)
1993                        eventPtr = ptr;
1994                    return XML_ERROR_BAD_CHAR_REF;
1995                }
1996                if (!isCdata
1997                        && n == 0x20 /* space */
1998                        && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
1999                    break;
2000                n = XmlEncode(n, (ICHAR *)buf);
2001                if (!n) {
2002                    if (enc == encoding)
2003                        eventPtr = ptr;
2004                    return XML_ERROR_BAD_CHAR_REF;
2005                }
2006                for (i = 0; i < n; i++) {
2007                    if (!poolAppendChar(pool, buf[i]))
2008                        return XML_ERROR_NO_MEMORY;
2009                }
2010            }
2011            break;
2012        case XML_TOK_DATA_CHARS:
2013            if (!poolAppend(pool, enc, ptr, next))
2014                return XML_ERROR_NO_MEMORY;
2015            break;
2016            break;
2017        case XML_TOK_TRAILING_CR:
2018            next = ptr + enc->minBytesPerChar;
2019            /* fall through */
2020        case XML_TOK_ATTRIBUTE_VALUE_S:
2021        case XML_TOK_DATA_NEWLINE:
2022            if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
2023                break;
2024            if (!poolAppendChar(pool, 0x20))
2025                return XML_ERROR_NO_MEMORY;
2026            break;
2027        case XML_TOK_ENTITY_REF:
2028            {
2029                const XML_Char *name;
2030                ENTITY *entity;
2031                XML_Char ch = XmlPredefinedEntityName(enc,
2032                                                      ptr + enc->minBytesPerChar,
2033                                                      next - enc->minBytesPerChar);
2034                if (ch) {
2035                    if (!poolAppendChar(pool, ch))
2036                        return XML_ERROR_NO_MEMORY;
2037                    break;
2038                }
2039                name = poolStoreString(&temp2Pool, enc,
2040                                       ptr + enc->minBytesPerChar,
2041                                       next - enc->minBytesPerChar);
2042                if (!name)
2043                    return XML_ERROR_NO_MEMORY;
2044                entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
2045                poolDiscard(&temp2Pool);
2046                if (!entity) {
2047                    if (dtd.complete) {
2048                        if (enc == encoding)
2049                            eventPtr = ptr;
2050                        return XML_ERROR_UNDEFINED_ENTITY;
2051                    }
2052                }
2053                else if (entity->open) {
2054                    if (enc == encoding)
2055                        eventPtr = ptr;
2056                    return XML_ERROR_RECURSIVE_ENTITY_REF;
2057                }
2058                else if (entity->notation) {
2059                    if (enc == encoding)
2060                        eventPtr = ptr;
2061                    return XML_ERROR_BINARY_ENTITY_REF;
2062                }
2063                else if (!entity->textPtr) {
2064                    if (enc == encoding)
2065                        eventPtr = ptr;
2066                    return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
2067                }
2068                else {
2069                    enum XML_Error result;
2070                    const XML_Char *textEnd = entity->textPtr + entity->textLen;
2071                    entity->open = 1;
2072                    result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
2073                    entity->open = 0;
2074                    if (result)
2075                        return result;
2076                }
2077            }
2078            break;
2079        default:
2080            abort();
2081        }
2082        ptr = next;
2083    }
2084    /* not reached */
2085}
2086
2087static
2088enum XML_Error storeEntityValue(XML_Parser parser,
2089                                const char *entityTextPtr,
2090                                const char *entityTextEnd)
2091{
2092    const ENCODING *internalEnc;
2093    STRING_POOL *pool = &(dtd.pool);
2094    entityTextPtr += encoding->minBytesPerChar;
2095    entityTextEnd -= encoding->minBytesPerChar;
2096    internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding();
2097    for (;;) {
2098        const char *next;
2099        int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next);
2100        switch (tok) {
2101        case XML_TOK_PARAM_ENTITY_REF:
2102            eventPtr = entityTextPtr;
2103            return XML_ERROR_SYNTAX;
2104        case XML_TOK_NONE:
2105            if (declEntity) {
2106                declEntity->textPtr = pool->start;
2107                declEntity->textLen = pool->ptr - pool->start;
2108                poolFinish(pool);
2109            }
2110            else
2111                poolDiscard(pool);
2112            return XML_ERROR_NONE;
2113        case XML_TOK_ENTITY_REF:
2114        case XML_TOK_DATA_CHARS:
2115            if (!poolAppend(pool, encoding, entityTextPtr, next))
2116                return XML_ERROR_NO_MEMORY;
2117            break;
2118        case XML_TOK_TRAILING_CR:
2119            next = entityTextPtr + encoding->minBytesPerChar;
2120            /* fall through */
2121        case XML_TOK_DATA_NEWLINE:
2122            if (pool->end == pool->ptr && !poolGrow(pool))
2123                return XML_ERROR_NO_MEMORY;
2124            *(pool->ptr)++ = 0xA;
2125            break;
2126        case XML_TOK_CHAR_REF:
2127            {
2128                XML_Char buf[XML_ENCODE_MAX];
2129                int i;
2130                int n = XmlCharRefNumber(encoding, entityTextPtr);
2131                if (n < 0) {
2132                    eventPtr = entityTextPtr;
2133                    return XML_ERROR_BAD_CHAR_REF;
2134                }
2135                n = XmlEncode(n, (ICHAR *)buf);
2136                if (!n) {
2137                    eventPtr = entityTextPtr;
2138                    return XML_ERROR_BAD_CHAR_REF;
2139                }
2140                for (i = 0; i < n; i++) {
2141                    if (pool->end == pool->ptr && !poolGrow(pool))
2142                        return XML_ERROR_NO_MEMORY;
2143                    *(pool->ptr)++ = buf[i];
2144                }
2145            }
2146            break;
2147        case XML_TOK_PARTIAL:
2148            eventPtr = entityTextPtr;
2149            return XML_ERROR_INVALID_TOKEN;
2150        case XML_TOK_INVALID:
2151            eventPtr = next;
2152            return XML_ERROR_INVALID_TOKEN;
2153        default:
2154            abort();
2155        }
2156        entityTextPtr = next;
2157    }
2158    /* not reached */
2159}
2160
2161static void
2162normalizeLines(XML_Char *s)
2163{
2164    XML_Char *p;
2165    for (;; s++) {
2166        if (*s == XML_T('\0'))
2167            return;
2168        if (*s == 0xD)
2169            break;
2170    }
2171    p = s;
2172    do {
2173        if (*s == 0xD) {
2174            *p++ = 0xA;
2175            if (*++s == 0xA)
2176                s++;
2177        }
2178        else
2179            *p++ = *s++;
2180    } while (*s);
2181    *p = XML_T('\0');
2182}
2183
2184static int
2185reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2186{
2187    const XML_Char *target;
2188    XML_Char *data;
2189    const char *tem;
2190    if (!processingInstructionHandler) {
2191        if (defaultHandler)
2192            reportDefault(parser, enc, start, end);
2193        return 1;
2194    }
2195    start += enc->minBytesPerChar * 2;
2196    tem = start + XmlNameLength(enc, start);
2197    target = poolStoreString(&tempPool, enc, start, tem);
2198    if (!target)
2199        return 0;
2200    poolFinish(&tempPool);
2201    data = poolStoreString(&tempPool, enc,
2202                           XmlSkipS(enc, tem),
2203                           end - enc->minBytesPerChar*2);
2204    if (!data)
2205        return 0;
2206    normalizeLines(data);
2207    processingInstructionHandler(handlerArg, target, data);
2208    poolClear(&tempPool);
2209    return 1;
2210}
2211
2212static int
2213reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2214{
2215    XML_Char *data;
2216    if (!commentHandler) {
2217        if (defaultHandler)
2218            reportDefault(parser, enc, start, end);
2219        return 1;
2220    }
2221    data = poolStoreString(&tempPool,
2222                           enc,
2223                           start + enc->minBytesPerChar * 4,
2224                           end - enc->minBytesPerChar * 3);
2225    if (!data)
2226        return 0;
2227    normalizeLines(data);
2228    commentHandler(handlerArg, data);
2229    poolClear(&tempPool);
2230    return 1;
2231}
2232
2233static void
2234reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
2235{
2236    if (MUST_CONVERT(enc, s)) {
2237        const char **eventPP;
2238        const char **eventEndPP;
2239        if (enc == encoding) {
2240            eventPP = &eventPtr;
2241            eventEndPP = &eventEndPtr;
2242        }
2243        else {
2244            eventPP = &(openInternalEntities->internalEventPtr);
2245            eventEndPP = &(openInternalEntities->internalEventEndPtr);
2246        }
2247        do {
2248            ICHAR *dataPtr = (ICHAR *)dataBuf;
2249            XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
2250            *eventEndPP = s;
2251            defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
2252            *eventPP = s;
2253        } while (s != end);
2254    }
2255    else
2256        defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
2257}
2258
2259
2260static int
2261defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value)
2262{
2263    DEFAULT_ATTRIBUTE *att;
2264    if (type->nDefaultAtts == type->allocDefaultAtts) {
2265        if (type->allocDefaultAtts == 0) {
2266            type->allocDefaultAtts = 8;
2267            type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
2268        }
2269        else {
2270            type->allocDefaultAtts *= 2;
2271            type->defaultAtts = realloc(type->defaultAtts,
2272                                        type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
2273        }
2274        if (!type->defaultAtts)
2275            return 0;
2276    }
2277    att = type->defaultAtts + type->nDefaultAtts;
2278    att->id = attId;
2279    att->value = value;
2280    att->isCdata = isCdata;
2281    if (!isCdata)
2282        attId->maybeTokenized = 1;
2283    type->nDefaultAtts += 1;
2284    return 1;
2285}
2286
2287static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
2288{
2289    const XML_Char *name;
2290    for (name = elementType->name; *name; name++) {
2291        if (*name == XML_T(':')) {
2292            PREFIX *prefix;
2293            const XML_Char *s;
2294            for (s = elementType->name; s != name; s++) {
2295                if (!poolAppendChar(&dtd.pool, *s))
2296                    return 0;
2297            }
2298            if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2299                return 0;
2300            prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
2301            if (!prefix)
2302                return 0;
2303            if (prefix->name == poolStart(&dtd.pool))
2304                poolFinish(&dtd.pool);
2305            else
2306                poolDiscard(&dtd.pool);
2307            elementType->prefix = prefix;
2308
2309        }
2310    }
2311    return 1;
2312}
2313
2314static ATTRIBUTE_ID *
2315getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
2316{
2317    ATTRIBUTE_ID *id;
2318    const XML_Char *name;
2319    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2320        return 0;
2321    name = poolStoreString(&dtd.pool, enc, start, end);
2322    if (!name)
2323        return 0;
2324    ++name;
2325    id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
2326    if (!id)
2327        return 0;
2328    if (id->name != name)
2329        poolDiscard(&dtd.pool);
2330    else {
2331        poolFinish(&dtd.pool);
2332        if (!ns)
2333            ;
2334        else if (name[0] == 'x'
2335                 && name[1] == 'm'
2336                 && name[2] == 'l'
2337                 && name[3] == 'n'
2338                 && name[4] == 's'
2339                 && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
2340            if (name[5] == '\0')
2341                id->prefix = &dtd.defaultPrefix;
2342            else
2343                id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
2344            id->xmlns = 1;
2345        }
2346        else {
2347            int i;
2348            for (i = 0; name[i]; i++) {
2349                if (name[i] == XML_T(':')) {
2350                    int j;
2351                    for (j = 0; j < i; j++) {
2352                        if (!poolAppendChar(&dtd.pool, name[j]))
2353                            return 0;
2354                    }
2355                    if (!poolAppendChar(&dtd.pool, XML_T('\0')))
2356                        return 0;
2357                    id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
2358                    if (id->prefix->name == poolStart(&dtd.pool))
2359                        poolFinish(&dtd.pool);
2360                    else
2361                        poolDiscard(&dtd.pool);
2362                    break;
2363                }
2364            }
2365        }
2366    }
2367    return id;
2368}
2369
2370#define CONTEXT_SEP XML_T('\f')
2371
2372static
2373const XML_Char *getContext(XML_Parser parser)
2374{
2375    HASH_TABLE_ITER iter;
2376    int needSep = 0;
2377
2378    if (dtd.defaultPrefix.binding) {
2379        int i;
2380        int len;
2381        if (!poolAppendChar(&tempPool, XML_T('=')))
2382            return 0;
2383        len = dtd.defaultPrefix.binding->uriLen;
2384        if (namespaceSeparator != XML_T('\0'))
2385            len--;
2386        for (i = 0; i < len; i++)
2387            if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
2388                return 0;
2389        needSep = 1;
2390    }
2391
2392    hashTableIterInit(&iter, &(dtd.prefixes));
2393    for (;;) {
2394        int i;
2395        int len;
2396        const XML_Char *s;
2397        PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
2398        if (!prefix)
2399            break;
2400        if (!prefix->binding)
2401            continue;
2402        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
2403            return 0;
2404        for (s = prefix->name; *s; s++)
2405            if (!poolAppendChar(&tempPool, *s))
2406                return 0;
2407        if (!poolAppendChar(&tempPool, XML_T('=')))
2408            return 0;
2409        len = prefix->binding->uriLen;
2410        if (namespaceSeparator != XML_T('\0'))
2411            len--;
2412        for (i = 0; i < len; i++)
2413            if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
2414                return 0;
2415        needSep = 1;
2416    }
2417
2418
2419    hashTableIterInit(&iter, &(dtd.generalEntities));
2420    for (;;) {
2421        const XML_Char *s;
2422        ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
2423        if (!e)
2424            break;
2425        if (!e->open)
2426            continue;
2427        if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
2428            return 0;
2429        for (s = e->name; *s; s++)
2430            if (!poolAppendChar(&tempPool, *s))
2431                return 0;
2432        needSep = 1;
2433    }
2434
2435    if (!poolAppendChar(&tempPool, XML_T('\0')))
2436        return 0;
2437    return tempPool.start;
2438}
2439
2440static
2441void normalizePublicId(XML_Char *publicId)
2442{
2443    XML_Char *p = publicId;
2444    XML_Char *s;
2445    for (s = publicId; *s; s++) {
2446        switch (*s) {
2447        case 0x20:
2448        case 0xD:
2449        case 0xA:
2450            if (p != publicId && p[-1] != 0x20)
2451                *p++ = 0x20;
2452            break;
2453        default:
2454            *p++ = *s;
2455        }
2456    }
2457    if (p != publicId && p[-1] == 0x20)
2458        --p;
2459    *p = XML_T('\0');
2460}
2461
2462static int dtdInit(DTD *p)
2463{
2464    poolInit(&(p->pool));
2465    hashTableInit(&(p->generalEntities));
2466    hashTableInit(&(p->elementTypes));
2467    hashTableInit(&(p->attributeIds));
2468    hashTableInit(&(p->prefixes));
2469    p->complete = 1;
2470    p->standalone = 0;
2471    p->base = 0;
2472    p->defaultPrefix.name = 0;
2473    p->defaultPrefix.binding = 0;
2474    return 1;
2475}
2476
2477static void dtdDestroy(DTD *p)
2478{
2479    HASH_TABLE_ITER iter;
2480    hashTableIterInit(&iter, &(p->elementTypes));
2481    for (;;) {
2482        ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
2483        if (!e)
2484            break;
2485        if (e->allocDefaultAtts != 0)
2486            g_free(e->defaultAtts);
2487    }
2488    hashTableDestroy(&(p->generalEntities));
2489    hashTableDestroy(&(p->elementTypes));
2490    hashTableDestroy(&(p->attributeIds));
2491    hashTableDestroy(&(p->prefixes));
2492    poolDestroy(&(p->pool));
2493}
2494
2495static
2496void poolInit(STRING_POOL *pool)
2497{
2498    pool->blocks = 0;
2499    pool->freeBlocks = 0;
2500    pool->start = 0;
2501    pool->ptr = 0;
2502    pool->end = 0;
2503}
2504
2505static
2506void poolClear(STRING_POOL *pool)
2507{
2508    if (!pool->freeBlocks)
2509        pool->freeBlocks = pool->blocks;
2510    else {
2511        BLOCK *p = pool->blocks;
2512        while (p) {
2513            BLOCK *tem = p->next;
2514            p->next = pool->freeBlocks;
2515            pool->freeBlocks = p;
2516            p = tem;
2517        }
2518    }
2519    pool->blocks = 0;
2520    pool->start = 0;
2521    pool->ptr = 0;
2522    pool->end = 0;
2523}
2524
2525static
2526void poolDestroy(STRING_POOL *pool)
2527{
2528    BLOCK *p = pool->blocks;
2529    while (p) {
2530        BLOCK *tem = p->next;
2531        g_free(p);
2532        p = tem;
2533    }
2534    pool->blocks = 0;
2535    p = pool->freeBlocks;
2536    while (p) {
2537        BLOCK *tem = p->next;
2538        g_free(p);
2539        p = tem;
2540    }
2541    pool->freeBlocks = 0;
2542    pool->ptr = 0;
2543    pool->start = 0;
2544    pool->end = 0;
2545}
2546
2547static
2548XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
2549                     const char *ptr, const char *end)
2550{
2551    if (!pool->ptr && !poolGrow(pool))
2552        return 0;
2553    for (;;) {
2554        XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
2555        if (ptr == end)
2556            break;
2557        if (!poolGrow(pool))
2558            return 0;
2559    }
2560    return pool->start;
2561}
2562
2563static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
2564{
2565    do {
2566        if (!poolAppendChar(pool, *s))
2567            return 0;
2568    } while (*s++);
2569    s = pool->start;
2570    poolFinish(pool);
2571    return s;
2572}
2573
2574static
2575XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
2576                          const char *ptr, const char *end)
2577{
2578    if (!poolAppend(pool, enc, ptr, end))
2579        return 0;
2580    if (pool->ptr == pool->end && !poolGrow(pool))
2581        return 0;
2582    *(pool->ptr)++ = 0;
2583    return pool->start;
2584}
2585
2586static
2587int poolGrow(STRING_POOL *pool)
2588{
2589    if (pool->freeBlocks) {
2590        if (pool->start == 0) {
2591            pool->blocks = pool->freeBlocks;
2592            pool->freeBlocks = pool->freeBlocks->next;
2593            pool->blocks->next = 0;
2594            pool->start = pool->blocks->s;
2595            pool->end = pool->start + pool->blocks->size;
2596            pool->ptr = pool->start;
2597            return 1;
2598        }
2599        if (pool->end - pool->start < pool->freeBlocks->size) {
2600            BLOCK *tem = pool->freeBlocks->next;
2601            pool->freeBlocks->next = pool->blocks;
2602            pool->blocks = pool->freeBlocks;
2603            pool->freeBlocks = tem;
2604            memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
2605            pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
2606            pool->start = pool->blocks->s;
2607            pool->end = pool->start + pool->blocks->size;
2608            return 1;
2609        }
2610    }
2611    if (pool->blocks && pool->start == pool->blocks->s) {
2612        int blockSize = (pool->end - pool->start)*2;
2613        pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
2614        if (!pool->blocks)
2615            return 0;
2616        pool->blocks->size = blockSize;
2617        pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
2618        pool->start = pool->blocks->s;
2619        pool->end = pool->start + blockSize;
2620    }
2621    else {
2622        BLOCK *tem;
2623        int blockSize = pool->end - pool->start;
2624        if (blockSize < INIT_BLOCK_SIZE)
2625            blockSize = INIT_BLOCK_SIZE;
2626        else
2627            blockSize *= 2;
2628        tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
2629        if (!tem)
2630            return 0;
2631        tem->size = blockSize;
2632        tem->next = pool->blocks;
2633        pool->blocks = tem;
2634        memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
2635        pool->ptr = tem->s + (pool->ptr - pool->start);
2636        pool->start = tem->s;
2637        pool->end = tem->s + blockSize;
2638    }
2639    return 1;
2640}
Note: See TracBrowser for help on using the repository browser.