diff options
author | kwaclaw <kwaclaw> | 2004-01-07 17:10:52 +0000 |
---|---|---|
committer | kwaclaw <kwaclaw> | 2004-01-07 17:10:52 +0000 |
commit | e4bde9ba4ede31dc5431d3ee5763876a169ea2d8 (patch) | |
tree | 2a84a7aba5156ac7c015d7699d7b2844389a63bf /lib/xmlparse.c | |
parent | 7f7fb10bd689df1403273c2464f54fccfa36f27c (diff) | |
download | libexpat-e4bde9ba4ede31dc5431d3ee5763876a169ea2d8.tar.gz |
Applied patch #835123: Suspend/Resume functionality.
For details check the patch description.
Diffstat (limited to 'lib/xmlparse.c')
-rw-r--r-- | lib/xmlparse.c | 661 |
1 files changed, 491 insertions, 170 deletions
diff --git a/lib/xmlparse.c b/lib/xmlparse.c index bc92d90..14d7ce3 100644 --- a/lib/xmlparse.c +++ b/lib/xmlparse.c @@ -182,7 +182,8 @@ typedef struct tag { typedef struct { const XML_Char *name; const XML_Char *textPtr; - int textLen; + int textLen; /* length in XML_Chars */ + int processed; /* # of processed bytes - when suspended */ const XML_Char *systemId; const XML_Char *base; const XML_Char *publicId; @@ -307,29 +308,32 @@ static Processor externalEntityInitProcessor; static Processor externalEntityInitProcessor2; static Processor externalEntityInitProcessor3; static Processor externalEntityContentProcessor; +static Processor internalEntityProcessor; static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, - const char *, const char *); + const char *s, const char *next); static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error -doProlog(XML_Parser parser, const ENCODING *enc, const char *s, - const char *end, int tok, const char *next, const char **nextPtr); +doProlog(XML_Parser parser, const ENCODING *enc, const char *s, + const char *end, int tok, const char *next, const char **nextPtr, + XML_Bool haveMore); static enum XML_Error -processInternalParamEntity(XML_Parser parser, ENTITY *entity); +processInternalEntity(XML_Parser parser, ENTITY *entity); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, - const char *start, const char *end, const char **endPtr); + const char *start, const char *end, const char **endPtr, + XML_Bool haveMore); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, - const char *end, const char **nextPtr); + const char *end, const char **nextPtr, XML_Bool haveMore); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, - const char *end, const char **nextPtr); + const char *end, const char **nextPtr, XML_Bool haveMore); #endif /* XML_DTD */ static enum XML_Error @@ -339,9 +343,8 @@ static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, - XML_Bool isCdata, XML_Bool isId, const XML_Char *dfltValue, - XML_Parser parser); +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, + XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, const char *, STRING_POOL *); @@ -493,6 +496,7 @@ struct XML_ParserStruct { const char *m_eventEndPtr; const char *m_positionPtr; OPEN_INTERNAL_ENTITY *m_openInternalEntities; + OPEN_INTERNAL_ENTITY *m_freeInternalEntities; XML_Bool m_defaultExpandInternalEntities; int m_tagLevel; ENTITY *m_declEntity; @@ -526,6 +530,7 @@ struct XML_ParserStruct { unsigned int m_groupSize; XML_Char m_namespaceSeparator; XML_Parser m_parentParser; + XML_ParsingStatus m_parsingStatus; #ifdef XML_DTD XML_Bool m_isParamEntity; XML_Bool m_useForeignDTD; @@ -589,6 +594,7 @@ struct XML_ParserStruct { #define positionPtr (parser->m_positionPtr) #define position (parser->m_position) #define openInternalEntities (parser->m_openInternalEntities) +#define freeInternalEntities (parser->m_freeInternalEntities) #define defaultExpandInternalEntities \ (parser->m_defaultExpandInternalEntities) #define tagLevel (parser->m_tagLevel) @@ -630,32 +636,14 @@ struct XML_ParserStruct { #define groupSize (parser->m_groupSize) #define namespaceSeparator (parser->m_namespaceSeparator) #define parentParser (parser->m_parentParser) +#define parsing (parser->m_parsingStatus.parsing) +#define finalBuffer (parser->m_parsingStatus.finalBuffer) #ifdef XML_DTD #define isParamEntity (parser->m_isParamEntity) #define useForeignDTD (parser->m_useForeignDTD) #define paramEntityParsing (parser->m_paramEntityParsing) #endif /* XML_DTD */ -#ifdef XML_DTD -#define parsing \ - (parentParser \ - ? \ - (isParamEntity \ - ? \ - (processor != externalParEntInitProcessor) \ - : \ - (processor != externalEntityInitProcessor)) \ - : \ - (processor != prologInitProcessor)) -#else -#define parsing \ - (parentParser \ - ? \ - (processor != externalEntityInitProcessor) \ - : \ - (processor != prologInitProcessor)) -#endif /* XML_DTD */ - XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName) { @@ -759,6 +747,7 @@ parserCreate(const XML_Char *encodingName, freeBindingList = NULL; freeTagList = NULL; + freeInternalEntities = NULL; groupSize = 0; groupConnector = NULL; @@ -849,7 +838,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) eventPtr = NULL; eventEndPtr = NULL; positionPtr = NULL; - openInternalEntities = 0; + openInternalEntities = NULL; defaultExpandInternalEntities = XML_TRUE; tagLevel = 0; tagStack = NULL; @@ -859,6 +848,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) unknownEncodingRelease = NULL; unknownEncodingData = NULL; parentParser = NULL; + parsing = XML_INITIALIZED; #ifdef XML_DTD isParamEntity = XML_FALSE; useForeignDTD = XML_FALSE; @@ -882,6 +872,7 @@ XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; + OPEN_INTERNAL_ENTITY *openEntityList; if (parentParser) return XML_FALSE; /* move tagStack to freeTagList */ @@ -894,6 +885,14 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) tag->bindings = NULL; freeTagList = tag; } + /* move openInternalEntities to freeInternalEntities */ + openEntityList = openInternalEntities; + while (openEntityList) { + OPEN_INTERNAL_ENTITY *openEntity = openEntityList; + openEntityList = openEntity->next; + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } moveToFreeBindingList(parser, inheritedBindings); FREE(unknownEncodingMem); if (unknownEncodingRelease) @@ -912,7 +911,7 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) XXX There's no way for the caller to determine which of the XXX possible error cases caused the XML_STATUS_ERROR return. */ - if (parsing) + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) return XML_STATUS_ERROR; if (encodingName == NULL) protocolEncodingName = NULL; @@ -1070,22 +1069,41 @@ destroyBindings(BINDING *bindings, XML_Parser parser) void XMLCALL XML_ParserFree(XML_Parser parser) { + TAG *tagList; + OPEN_INTERNAL_ENTITY *entityList; if (parser == NULL) return; + /* free tagStack and freeTagList */ + tagList = tagStack; for (;;) { TAG *p; - if (tagStack == NULL) { + if (tagList == NULL) { if (freeTagList == NULL) break; - tagStack = freeTagList; + tagList = freeTagList; freeTagList = NULL; } - p = tagStack; - tagStack = tagStack->parent; + p = tagList; + tagList = tagList->parent; FREE(p->buf); destroyBindings(p->bindings, parser); FREE(p); } + /* free openInternalEntities and freeInternalEntities */ + entityList = openInternalEntities; + for (;;) { + OPEN_INTERNAL_ENTITY *openEntity; + if (entityList == NULL) { + if (freeInternalEntities == NULL) + break; + entityList = freeInternalEntities; + freeInternalEntities = NULL; + } + openEntity = entityList; + entityList = entityList->next; + FREE(openEntity); + } + destroyBindings(freeBindingList, parser); destroyBindings(inheritedBindings, parser); poolDestroy(&tempPool); @@ -1121,7 +1139,7 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { #ifdef XML_DTD /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing) + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; useForeignDTD = useDTD; return XML_ERROR_NONE; @@ -1134,7 +1152,7 @@ void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing) + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) return; ns_triplets = do_nst ? XML_TRUE : XML_FALSE; } @@ -1386,7 +1404,7 @@ XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { /* block after XML_Parse()/XML_ParseBuffer() has been called */ - if (parsing) + if (parsing == XML_PARSING || parsing == XML_SUSPENDED) return 0; #ifdef XML_DTD paramEntityParsing = peParsing; @@ -1399,13 +1417,41 @@ XML_SetParamEntityParsing(XML_Parser parser, enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + } + parsing = XML_PARSING; + if (len == 0) { + finalBuffer = (XML_Bool)isFinal; if (!isFinal) return XML_STATUS_OK; positionPtr = bufferPtr; - errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); - if (errorCode == XML_ERROR_NONE) + parseEndPtr = bufferEnd; + + /* If data are left over from last buffer, and we now know that these + data are the final chunk of input, then we have to check them again + to detect errors based on this information. + */ + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode == XML_ERROR_NONE) { + switch (parsing) { + case XML_SUSPENDED: + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return XML_STATUS_SUSPENDED; + case XML_INITIALIZED: + case XML_PARSING: + parsing = XML_FINISHED; + } return XML_STATUS_OK; + } eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; @@ -1416,20 +1462,30 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) int nLeftOver; parseEndByteIndex += len; positionPtr = s; - if (isFinal) { - errorCode = processor(parser, s, parseEndPtr = s + len, 0); - if (errorCode == XML_ERROR_NONE) - return XML_STATUS_OK; - eventEndPtr = eventPtr; - processor = errorProcessor; - return XML_STATUS_ERROR; - } + finalBuffer = (XML_Bool)isFinal; + enum XML_Error result; + errorCode = processor(parser, s, parseEndPtr = s + len, &end); + if (errorCode != XML_ERROR_NONE) { eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } + else { + switch (parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED, XML_PARSING: + result = XML_STATUS_OK; + if (isFinal) { + parsing = XML_FINISHED; + return result; + } + } + } + XmlUpdatePosition(encoding, positionPtr, end, &position); positionPtr = end; nLeftOver = s + len - end; @@ -1457,7 +1513,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) bufferPtr = buffer; bufferEnd = buffer + nLeftOver; } - return XML_STATUS_OK; + return result; } #endif /* not defined XML_CONTEXT_BYTES */ else { @@ -1474,29 +1530,64 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) enum XML_Status XMLCALL XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { - const char *start = bufferPtr; + const char *start; + enum XML_Error result; + + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + } + parsing = XML_PARSING; + + start = bufferPtr; positionPtr = start; bufferEnd += len; + parseEndPtr = bufferEnd; parseEndByteIndex += len; - errorCode = processor(parser, start, parseEndPtr = bufferEnd, - isFinal ? (const char **)NULL : &bufferPtr); - if (errorCode == XML_ERROR_NONE) { - if (!isFinal) { - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - positionPtr = bufferPtr; - } - return XML_STATUS_OK; - } - else { + finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, start, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { eventEndPtr = eventPtr; processor = errorProcessor; return XML_STATUS_ERROR; } + else { + switch (parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + result = XML_STATUS_OK; + if (isFinal) { + parsing = XML_FINISHED; + return result; + } + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; } void * XMLCALL XML_GetBuffer(XML_Parser parser, int len) { + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return NULL; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return NULL; + } if (len > bufferLim - bufferEnd) { /* FIXME avoid integer overflow */ int neededSize = len + (bufferEnd - bufferPtr); @@ -1563,6 +1654,65 @@ XML_GetBuffer(XML_Parser parser, int len) return bufferEnd; } +enum XML_Status XMLCALL +XML_StopParser(XML_Parser parser, XML_Bool resumable) +{ + switch (parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + } + parsing = resumable ? XML_SUSPENDED : XML_FINISHED; + return XML_STATUS_OK; +} + +enum XML_Status XMLCALL +XML_ResumeParser(XML_Parser parser) +{ + enum XML_Error result; + + if (parsing != XML_SUSPENDED) { + errorCode = XML_ERROR_NOT_SUSPENDED; + return XML_STATUS_ERROR; + } + parsing = XML_PARSING; + + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + result = XML_STATUS_OK; + if (finalBuffer) { + parsing = XML_FINISHED; + return result; + } + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; +} + +XML_ParsingStatus XMLCALL +XML_GetParsingStatus(XML_Parser parser) +{ + return parser->m_parsingStatus; +} + enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser) { @@ -1687,7 +1837,11 @@ XML_ErrorString(enum XML_Error code) XML_L("entity declared in parameter entity"), XML_L("requested feature requires XML_DTD support in Expat"), XML_L("cannot change setting once parsing has begun"), - XML_L("unbound prefix") + XML_L("unbound prefix"), + XML_L("parser suspended"), + XML_L("parser not suspended"), + XML_L("parsing aborted"), + XML_L("parsing finished") }; if (code > 0 && code < sizeof(message)/sizeof(message[0])) return message[code]; @@ -1812,12 +1966,12 @@ contentProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = - doContent(parser, 0, encoding, start, end, endPtr); - if (result != XML_ERROR_NONE) - return result; - if (!storeRawNames(parser)) - return XML_ERROR_NO_MEMORY; + enum XML_Error result = doContent(parser, 0, encoding, start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } return result; } @@ -1849,21 +2003,21 @@ externalEntityInitProcessor2(XML_Parser parser, doContent (by detecting XML_TOK_NONE) without processing any xml text declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. */ - if (next == end && endPtr) { + if (next == end && !finalBuffer) { *endPtr = next; return XML_ERROR_NONE; } start = next; break; case XML_TOK_PARTIAL: - if (endPtr) { + if (!finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (endPtr) { + if (!finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } @@ -1885,21 +2039,29 @@ externalEntityInitProcessor3(XML_Parser parser, switch (tok) { case XML_TOK_XML_DECL: { - enum XML_Error result = processXmlDecl(parser, 1, start, next); + enum XML_Error result; + result = processXmlDecl(parser, 1, start, next); if (result != XML_ERROR_NONE) return result; + switch (parsing) { + case XML_SUSPENDED: + *endPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } start = next; } break; case XML_TOK_PARTIAL: - if (endPtr) { + if (!finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (endPtr) { + if (!finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } @@ -1917,12 +2079,12 @@ externalEntityContentProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = - doContent(parser, 1, encoding, start, end, endPtr); - if (result != XML_ERROR_NONE) - return result; - if (!storeRawNames(parser)) - return XML_ERROR_NO_MEMORY; + enum XML_Error result = doContent(parser, 1, encoding, start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } return result; } @@ -1932,9 +2094,12 @@ doContent(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, - const char **nextPtr) + const char **nextPtr, + XML_Bool haveMore) { - DTD * const dtd = _dtd; /* save one level of indirection */ + /* save one level of indirection */ + DTD * const dtd = _dtd; + const char **eventPP; const char **eventEndPP; if (enc == encoding) { @@ -1946,13 +2111,14 @@ doContent(XML_Parser parser, eventEndPP = &(openInternalEntities->internalEventEndPtr); } *eventPP = s; + for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } @@ -1963,19 +2129,24 @@ doContent(XML_Parser parser, } else if (defaultHandler) reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ if (startTagLevel == 0) return XML_ERROR_NO_ELEMENTS; if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; + *nextPtr = end; return XML_ERROR_NONE; case XML_TOK_NONE: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } if (startTagLevel > 0) { if (tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; + *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_NO_ELEMENTS; @@ -1983,13 +2154,13 @@ doContent(XML_Parser parser, *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } @@ -2038,7 +2209,6 @@ doContent(XML_Parser parser, return XML_ERROR_BINARY_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; - OPEN_INTERNAL_ENTITY openEntity; if (!defaultExpandInternalEntities) { if (skippedEntityHandler) skippedEntityHandler(handlerArg, entity->name, 0); @@ -2046,21 +2216,8 @@ doContent(XML_Parser parser, reportDefault(parser, enc, s, next); break; } - entity->open = XML_TRUE; - openEntity.next = openInternalEntities; - openInternalEntities = &openEntity; - openEntity.entity = entity; - openEntity.internalEventPtr = NULL; - openEntity.internalEventEndPtr = NULL; - result = doContent(parser, - tagLevel, - internalEncoding, - (char *)entity->textPtr, - (char *)(entity->textPtr + entity->textLen), - 0); - entity->open = XML_FALSE; - openInternalEntities = openEntity.next; - if (result) + result = processInternalEntity(parser, entity); + if (result != XML_ERROR_NONE) return result; } else if (externalEntityRefHandler) { @@ -2296,15 +2453,17 @@ doContent(XML_Parser parser, #endif else if (defaultHandler) reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr); - if (!next) { + result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { processor = cdataSectionProcessor; return result; } } break; case XML_TOK_TRAILING_RSQB: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } @@ -2322,6 +2481,9 @@ doContent(XML_Parser parser, } else if (defaultHandler) reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ if (startTagLevel == 0) { *eventPP = end; return XML_ERROR_NO_ELEMENTS; @@ -2330,6 +2492,7 @@ doContent(XML_Parser parser, *eventPP = end; return XML_ERROR_ASYNC_ENTITY; } + *nextPtr = end; return XML_ERROR_NONE; case XML_TOK_DATA_CHARS: if (characterDataHandler) { @@ -2367,6 +2530,13 @@ doContent(XML_Parser parser, break; } *eventPP = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } } /* not reached */ } @@ -2776,8 +2946,10 @@ cdataSectionProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doCdataSection(parser, encoding, &start, - end, endPtr); + enum XML_Error result = doCdataSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result != XML_ERROR_NONE) + return result; if (start) { if (parentParser) { /* we are parsing an external entity */ processor = externalEntityContentProcessor; @@ -2791,7 +2963,7 @@ cdataSectionProcessor(XML_Parser parser, return result; } -/* startPtr gets set to non-null is the section is closed, and to null if +/* startPtr gets set to non-null if the section is closed, and to null if the section is not yet closed. */ static enum XML_Error @@ -2799,7 +2971,8 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, - const char **nextPtr) + const char **nextPtr, + XML_Bool haveMore) { const char *s = *startPtr; const char **eventPP; @@ -2815,6 +2988,7 @@ doCdataSection(XML_Parser parser, } *eventPP = s; *startPtr = NULL; + for (;;) { const char *next; int tok = XmlCdataSectionTok(enc, s, end, &next); @@ -2831,7 +3005,11 @@ doCdataSection(XML_Parser parser, else if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; - return XML_ERROR_NONE; + *nextPtr = next; + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; case XML_TOK_DATA_NEWLINE: if (characterDataHandler) { XML_Char c = 0xA; @@ -2866,14 +3044,14 @@ doCdataSection(XML_Parser parser, *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } @@ -2882,7 +3060,15 @@ doCdataSection(XML_Parser parser, *eventPP = next; return XML_ERROR_UNEXPECTED_STATE; } + *eventPP = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } } /* not reached */ } @@ -2898,8 +3084,10 @@ ignoreSectionProcessor(XML_Parser parser, const char *end, const char **endPtr) { - enum XML_Error result = doIgnoreSection(parser, encoding, &start, - end, endPtr); + enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!finalBuffer); + if (result != XML_ERROR_NONE) + return result; if (start) { processor = prologProcessor; return prologProcessor(parser, start, end, endPtr); @@ -2915,7 +3103,8 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, - const char **nextPtr) + const char **nextPtr, + XML_Bool haveMore) { const char *next; int tok; @@ -2940,19 +3129,23 @@ doIgnoreSection(XML_Parser parser, if (defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; - return XML_ERROR_NONE; + *nextPtr = next; + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: - if (nextPtr) { + if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } @@ -3168,31 +3361,40 @@ entityValueInitProcessor(XML_Parser parser, const char *next = s; int tok; - for (;;) { + for (;;) { tok = XmlPrologTok(encoding, start, end, &next); if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { - *nextPtr = s; - return XML_ERROR_NONE; + if (!finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: - return XML_ERROR_INVALID_TOKEN; + return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; + return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; + return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } + /* found end of entity value - can store it now */ return storeEntityValue(parser, encoding, s, end); } else if (tok == XML_TOK_XML_DECL) { - enum XML_Error result = processXmlDecl(parser, 0, start, next); - if (result != XML_ERROR_NONE) - return result; - if (nextPtr) *nextPtr = next; + enum XML_Error result; + result = processXmlDecl(parser, 0, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } + *nextPtr = next; /* stop scanning for text declaration - we found one */ processor = entityValueProcessor; return entityValueProcessor(parser, next, end, nextPtr); @@ -3204,7 +3406,7 @@ entityValueInitProcessor(XML_Parser parser, then, when this routine is entered the next time, XmlPrologTok will return XML_TOK_INVALID, since the BOM is still in the buffer */ - else if (tok == XML_TOK_BOM && next == end && nextPtr) { + else if (tok == XML_TOK_BOM && next == end && !finalBuffer) { *nextPtr = next; return XML_ERROR_NONE; } @@ -3218,13 +3420,12 @@ externalParEntProcessor(XML_Parser parser, const char *end, const char **nextPtr) { - const char *start = s; const char *next = s; int tok; - tok = XmlPrologTok(encoding, start, end, &next); + tok = XmlPrologTok(encoding, s, end, &next); if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { + if (!finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } @@ -3250,7 +3451,8 @@ externalParEntProcessor(XML_Parser parser, } processor = prologProcessor; - return doProlog(parser, encoding, s, end, tok, next, nextPtr); + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!finalBuffer); } static enum XML_Error PTRCALL @@ -3267,21 +3469,22 @@ entityValueProcessor(XML_Parser parser, for (;;) { tok = XmlPrologTok(enc, start, end, &next); if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { + if (!finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: - return XML_ERROR_INVALID_TOKEN; + return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; + return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; + return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } + /* found end of entity value - can store it now */ return storeEntityValue(parser, enc, s, end); } start = next; @@ -3298,7 +3501,8 @@ prologProcessor(XML_Parser parser, { const char *next = s; int tok = XmlPrologTok(encoding, s, end, &next); - return doProlog(parser, encoding, s, end, tok, next, nextPtr); + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!finalBuffer); } static enum XML_Error @@ -3308,7 +3512,8 @@ doProlog(XML_Parser parser, const char *end, int tok, const char *next, - const char **nextPtr) + const char **nextPtr, + XML_Bool haveMore) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = { '#' , '\0' }; @@ -3329,7 +3534,8 @@ doProlog(XML_Parser parser, static const XML_Char enumValueSep[] = { '|', '\0' }; static const XML_Char enumValueStart[] = { '(', '\0' }; - DTD * const dtd = _dtd; /* save one level of indirection */ + /* save one level of indirection */ + DTD * const dtd = _dtd; const char **eventPP; const char **eventEndPP; @@ -3343,13 +3549,14 @@ doProlog(XML_Parser parser, eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } + for (;;) { int role; XML_Bool handleDefault = XML_TRUE; *eventPP = s; *eventEndPP = next; if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { + if (haveMore && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } @@ -3363,12 +3570,15 @@ doProlog(XML_Parser parser, return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: #ifdef XML_DTD - if (enc != encoding) + if (enc != encoding) { + *nextPtr = s; return XML_ERROR_NONE; + } if (isParamEntity) { if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) == XML_ROLE_ERROR) return XML_ERROR_SYNTAX; + *nextPtr = s; return XML_ERROR_NONE; } #endif /* XML_DTD */ @@ -3928,8 +4138,10 @@ doProlog(XML_Parser parser, if (defaultHandler) reportDefault(parser, enc, s, next); handleDefault = XML_FALSE; - result = doIgnoreSection(parser, enc, &next, end, nextPtr); - if (!next) { + result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { processor = ignoreSectionProcessor; return result; } @@ -4038,7 +4250,7 @@ doProlog(XML_Parser parser, return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; - result = processInternalParamEntity(parser, entity); + result = processInternalEntity(parser, entity); if (result != XML_ERROR_NONE) return result; handleDefault = XML_FALSE; @@ -4230,6 +4442,14 @@ doProlog(XML_Parser parser, if (handleDefault && defaultHandler) reportDefault(parser, enc, s, next); + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } + s = next; tok = XmlPrologTok(enc, s, end, &next); } @@ -4254,13 +4474,13 @@ epilogProcessor(XML_Parser parser, if (defaultHandler) { eventEndPtr = next; reportDefault(parser, encoding, s, next); + if (parsing == XML_FINISHED) + return XML_ERROR_ABORTED; } - if (nextPtr) - *nextPtr = next; + *nextPtr = next; return XML_ERROR_NONE; case XML_TOK_NONE: - if (nextPtr) - *nextPtr = s; + *nextPtr = s; return XML_ERROR_NONE; case XML_TOK_PROLOG_S: if (defaultHandler) @@ -4278,13 +4498,13 @@ epilogProcessor(XML_Parser parser, eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: - if (nextPtr) { + if (!finalBuffer) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { + if (!finalBuffer) { *nextPtr = s; return XML_ERROR_NONE; } @@ -4293,34 +4513,135 @@ epilogProcessor(XML_Parser parser, return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; } eventPtr = s = next; + switch (parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + } } } -#ifdef XML_DTD - static enum XML_Error -processInternalParamEntity(XML_Parser parser, ENTITY *entity) +processInternalEntity(XML_Parser parser, ENTITY *entity) { - const char *s, *end, *next; - int tok; + const char *textStart, *textEnd; + char *next; enum XML_Error result; - OPEN_INTERNAL_ENTITY openEntity; + OPEN_INTERNAL_ENTITY *openEntity; + + if (freeInternalEntities) { + openEntity = freeInternalEntities; + freeInternalEntities = openEntity->next; + } + else { + openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); + if (!openEntity) + return XML_ERROR_NO_MEMORY; + } entity->open = XML_TRUE; - openEntity.next = openInternalEntities; - openInternalEntities = &openEntity; - openEntity.entity = entity; - openEntity.internalEventPtr = NULL; - openEntity.internalEventEndPtr = NULL; - s = (char *)entity->textPtr; - end = (char *)(entity->textPtr + entity->textLen); - tok = XmlPrologTok(internalEncoding, s, end, &next); - result = doProlog(parser, internalEncoding, s, end, tok, next, 0); - entity->open = XML_FALSE; - openInternalEntities = openEntity.next; + entity->processed = 0; + openEntity->next = openInternalEntities; + openInternalEntities = openEntity; + openEntity->entity = entity; + openEntity->internalEventPtr = NULL; + openEntity->internalEventEndPtr = NULL; + textStart = (char *)entity->textPtr; + textEnd = (char *)(entity->textPtr + entity->textLen); + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, tagLevel, internalEncoding, textStart, + textEnd, &next, XML_FALSE); + + if (result == XML_ERROR_NONE) { + if (textEnd != next && parsing == XML_SUSPENDED) { + entity->processed = next - textStart; + processor = internalEntityProcessor; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + } return result; } +static enum XML_Error PTRCALL +internalEntityProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + ENTITY *entity; + const char *textStart, *textEnd; + char *next; + int processorTagLevel; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; + if (!openEntity) + return XML_ERROR_UNEXPECTED_STATE; + + entity = openEntity->entity; + textStart = ((char *)entity->textPtr) + entity->processed; + textEnd = (char *)(entity->textPtr + entity->textLen); + /* compare with cdataSectionProcessor */ + if (parentParser) + processorTagLevel = 1; + else + processorTagLevel = 0; + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, processorTagLevel, internalEncoding, + textStart, textEnd, &next, XML_FALSE); + + if (result != XML_ERROR_NONE) + return result; + else if (textEnd != next && parsing == XML_SUSPENDED) { + entity->processed = next - (char *)entity->textPtr; + return result; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + +#ifdef XML_DTD + if (entity->is_param) { + int tok; + processor = prologProcessor; + tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, nextPtr, + (XML_Bool)!finalBuffer); + } + else #endif /* XML_DTD */ + { + processor = contentProcessor; + return doContent(parser, processorTagLevel, encoding, s, end, nextPtr, + (XML_Bool)!finalBuffer); + } +} static enum XML_Error PTRCALL errorProcessor(XML_Parser parser, |