Annotation of libwww/modules/expat/xmlparse/xmlparse.c, revision 1.1

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

Webmaster