diff --git a/Copyright b/Copyright index c058f02..f76a86d 100644 --- a/Copyright +++ b/Copyright @@ -1,6 +1,6 @@ -Except where otherwise noted in the source code (e.g. the files dict.c, -list.c and the trio files, which are covered by a similar licence but -with different Copyright notices) all the files are: +Except where otherwise noted in the source code (e.g. the files dict.c and +list.c, which are covered by a similar licence but with different Copyright +notices) all the files are: Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. diff --git a/HTMLparser.c b/HTMLparser.c index ea6a4f2..3be7464 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -58,25 +58,9 @@ static void htmlParseComment(htmlParserCtxtPtr ctxt); * Handle a redefinition of attribute error */ static void -htmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra) +htmlErrMemory(xmlParserCtxtPtr ctxt) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - } - if (extra) - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); + xmlCtxtErrMemory(ctxt); } /** @@ -93,18 +77,8 @@ static void LIBXML_ATTR_FORMAT(3,0) htmlParseErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error, - XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, - NULL, 0, 0, - msg, str1, str2); - if (ctxt != NULL) - ctxt->wellFormed = 0; + xmlCtxtErr(ctxt, NULL, XML_FROM_HTML, error, XML_ERR_ERROR, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -120,16 +94,8 @@ static void LIBXML_ATTR_FORMAT(3,0) htmlParseErrInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, int val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_HTML, error, - XML_ERR_ERROR, NULL, 0, NULL, NULL, - NULL, val, 0, msg, val); - if (ctxt != NULL) - ctxt->wellFormed = 0; + xmlCtxtErr(ctxt, NULL, XML_FROM_HTML, error, XML_ERR_ERROR, + NULL, NULL, NULL, val, msg, val); } /************************************************************************ @@ -161,7 +127,7 @@ htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value) tmp = xmlRealloc((xmlChar **) ctxt->nameTab, newSize * sizeof(ctxt->nameTab[0])); if (tmp == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); return (-1); } ctxt->nameTab = tmp; @@ -219,7 +185,7 @@ htmlNodeInfoPush(htmlParserCtxtPtr ctxt, htmlParserNodeInfo *value) ctxt->nodeInfoMax * sizeof(ctxt->nodeInfoTab[0])); if (ctxt->nodeInfoTab == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); return (0); } } @@ -289,13 +255,16 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt) #define CUR_PTR ctxt->input->cur #define BASE_PTR ctxt->input->base -#define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ - (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ - xmlParserShrink(ctxt) +#define SHRINK \ + if ((!PARSER_PROGRESSIVE(ctxt)) && \ + (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ + (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ + xmlParserShrink(ctxt); -#define GROW if ((ctxt->progressive == 0) && \ - (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ - xmlParserGrow(ctxt) +#define GROW \ + if ((!PARSER_PROGRESSIVE(ctxt)) && \ + (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ + xmlParserGrow(ctxt); #define SKIP_BLANKS htmlSkipBlankChars(ctxt) @@ -304,14 +273,14 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt) #define CUR (*ctxt->input->cur) #define NEXT xmlNextChar(ctxt) -#define RAW (ctxt->token ? -1 : (*ctxt->input->cur)) +#define RAW (*ctxt->input->cur) #define NEXTL(l) do { \ if (*(ctxt->input->cur) == '\n') { \ ctxt->input->line++; ctxt->input->col = 1; \ } else ctxt->input->col++; \ - ctxt->token = 0; ctxt->input->cur += l; \ + ctxt->input->cur += l; \ } while (0) /************ @@ -343,6 +312,7 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt) static xmlChar * htmlFindEncoding(xmlParserCtxtPtr ctxt) { const xmlChar *start, *cur, *end; + xmlChar *ret; if ((ctxt == NULL) || (ctxt->input == NULL) || (ctxt->input->flags & XML_INPUT_HAS_ENCODING)) @@ -374,7 +344,10 @@ htmlFindEncoding(xmlParserCtxtPtr ctxt) { cur++; if (cur == start) return(NULL); - return(xmlStrndup(start, cur - start)); + ret = xmlStrndup(start, cur - start); + if (ret == NULL) + htmlErrMemory(ctxt); + return(ret); } /** @@ -397,23 +370,11 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { unsigned char c; unsigned int val; - if (ctxt->instate == XML_PARSER_EOF) - return(0); - - if (ctxt->token != 0) { - *len = 0; - return(ctxt->token); - } - - if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) { + if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) xmlParserGrow(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - return(0); - } if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) { xmlChar * guess; - xmlCharEncodingHandlerPtr handler; /* * Assume it's a fixed length encoding (1) with @@ -421,13 +382,18 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { * HTML constructs only use < 128 chars */ if (*ctxt->input->cur < 0x80) { - *len = 1; - if ((*ctxt->input->cur == 0) && - (ctxt->input->cur < ctxt->input->end)) { - htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x%X out of allowed range\n", 0); - return(' '); + if (*ctxt->input->cur == 0) { + if (ctxt->input->cur < ctxt->input->end) { + htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, + "Char 0x%X out of allowed range\n", 0); + *len = 1; + return(' '); + } else { + *len = 0; + return(0); + } } + *len = 1; return(*ctxt->input->cur); } @@ -438,18 +404,7 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { if (guess == NULL) { xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); } else { - handler = xmlFindCharEncodingHandler((const char *) guess); - if (handler != NULL) { - /* - * Don't use UTF-8 encoder which isn't required and - * can produce invalid UTF-8. - */ - if (!xmlStrEqual(BAD_CAST handler->name, BAD_CAST "UTF-8")) - xmlSwitchToEncoding(ctxt, handler); - } else { - htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, - "Unsupported encoding %s", guess, NULL); - } + xmlSwitchEncodingName(ctxt, (const char *) guess); xmlFree(guess); } ctxt->input->flags |= XML_INPUT_HAS_ENCODING; @@ -516,12 +471,16 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { } return(val); } else { - if ((*ctxt->input->cur == 0) && - (ctxt->input->cur < ctxt->input->end)) { - htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x%X out of allowed range\n", 0); - *len = 1; - return(' '); + if (*ctxt->input->cur == 0) { + if (ctxt->input->cur < ctxt->input->end) { + htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, + "Char 0x%X out of allowed range\n", 0); + *len = 1; + return(' '); + } else { + *len = 0; + return(0); + } } /* 1-byte code */ *len = 1; @@ -529,20 +488,7 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { } encoding_error: - { - char buffer[150]; - - if (ctxt->input->end - ctxt->input->cur >= 4) { - snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - } else { - snprintf(buffer, 149, "Bytes: 0x%02X\n", ctxt->input->cur[0]); - } - htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, - "Input is not proper UTF-8, indicate encoding !\n", - BAD_CAST buffer, NULL); - } + xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL); if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); @@ -2035,7 +1981,7 @@ static const htmlEntityDesc html40EntitiesTable[] = { buffer##_size *= 2; \ tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size); \ if (tmp == NULL) { \ - htmlErrMemory(ctxt, "growing buffer\n"); \ + htmlErrMemory(ctxt); \ xmlFree(buffer); \ return(NULL); \ } \ @@ -2065,6 +2011,14 @@ htmlEntityLookup(const xmlChar *name) { return(NULL); } +static int +htmlCompareEntityDesc(const void *vkey, const void *vdesc) { + const unsigned *key = vkey; + const htmlEntityDesc *desc = vdesc; + + return((int) *key - (int) desc->value); +} + /** * htmlEntityValueLookup: * @value: the entity's unicode value @@ -2077,17 +2031,14 @@ htmlEntityLookup(const xmlChar *name) { */ const htmlEntityDesc * htmlEntityValueLookup(unsigned int value) { - unsigned int i; + const htmlEntityDesc *desc; + size_t nmemb; - for (i = 0;i < (sizeof(html40EntitiesTable)/ - sizeof(html40EntitiesTable[0]));i++) { - if (html40EntitiesTable[i].value >= value) { - if (html40EntitiesTable[i].value > value) - break; - return((htmlEntityDescPtr) &html40EntitiesTable[i]); - } - } - return(NULL); + nmemb = sizeof(html40EntitiesTable) / sizeof(html40EntitiesTable[0]); + desc = bsearch(&value, html40EntitiesTable, nmemb, sizeof(htmlEntityDesc), + htmlCompareEntityDesc); + + return(desc); } /** @@ -2292,47 +2243,6 @@ htmlEncodeEntities(unsigned char* out, int *outlen, return(0); } -/************************************************************************ - * * - * Commodity functions to handle streams * - * * - ************************************************************************/ - -#ifdef LIBXML_PUSH_ENABLED -/** - * htmlNewInputStream: - * @ctxt: an HTML parser context - * - * Create a new input stream structure - * Returns the new input stream or NULL - */ -static htmlParserInputPtr -htmlNewInputStream(htmlParserCtxtPtr ctxt) { - htmlParserInputPtr input; - - input = (xmlParserInputPtr) xmlMalloc(sizeof(htmlParserInput)); - if (input == NULL) { - htmlErrMemory(ctxt, "couldn't allocate a new input stream\n"); - return(NULL); - } - memset(input, 0, sizeof(htmlParserInput)); - input->filename = NULL; - input->directory = NULL; - input->base = NULL; - input->cur = NULL; - input->buf = NULL; - input->line = 1; - input->col = 1; - input->buf = NULL; - input->free = NULL; - input->version = NULL; - input->consumed = 0; - input->length = 0; - return(input); -} -#endif - - /************************************************************************ * * * Commodity functions, cleanup needed ? * @@ -2438,10 +2348,8 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) { * Allocate a new document and fill the fields. */ cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); - if (cur == NULL) { - htmlErrMemory(NULL, "HTML document creation failed\n"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlDoc)); cur->type = XML_HTML_DOCUMENT_NODE; @@ -2461,8 +2369,15 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) { cur->charset = XML_CHAR_ENCODING_UTF8; cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT; if ((ExternalID != NULL) || - (URI != NULL)) - xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI); + (URI != NULL)) { + xmlDtdPtr intSubset; + + intSubset = xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI); + if (intSubset == NULL) { + xmlFree(cur); + return(NULL); + } + } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); @@ -2510,12 +2425,14 @@ htmlSkipBogusComment(htmlParserCtxtPtr ctxt) { htmlParseErr(ctxt, XML_HTML_INCORRECTLY_OPENED_COMMENT, "Incorrectly opened comment\n", NULL, NULL); - do { + while (PARSER_STOPPED(ctxt) == 0) { c = CUR; if (c == 0) break; NEXT; - } while (c != '>'); + if (c == '>') + break; + } } /** @@ -2550,7 +2467,7 @@ htmlParseHTMLName(htmlParserCtxtPtr ctxt) { ret = xmlDictLookup(ctxt->dict, loc, i); if (ret == NULL) - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); return(ret); } @@ -2571,6 +2488,7 @@ static const xmlChar * htmlParseHTMLName_nonInvasive(htmlParserCtxtPtr ctxt) { int i = 0; xmlChar loc[HTML_PARSER_BUFFER_SIZE]; + const xmlChar *ret; if (!IS_ASCII_LETTER(NXT(1)) && (NXT(1) != '_') && (NXT(1) != ':')) return(NULL); @@ -2583,7 +2501,11 @@ htmlParseHTMLName_nonInvasive(htmlParserCtxtPtr ctxt) { i++; } - return(xmlDictLookup(ctxt->dict, loc, i)); + ret = xmlDictLookup(ctxt->dict, loc, i); + if (ret == NULL) + htmlErrMemory(ctxt); + + return(ret); } @@ -2625,6 +2547,8 @@ htmlParseName(htmlParserCtxtPtr ctxt) { if ((*in > 0) && (*in < 0x80)) { count = in - ctxt->input->cur; ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); + if (ret == NULL) + htmlErrMemory(ctxt); ctxt->input->cur = in; ctxt->input->col += count; return(ret); @@ -2641,6 +2565,7 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) { XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH; const xmlChar *base = ctxt->input->base; + const xmlChar *ret; /* * Handler for more complex cases @@ -2673,8 +2598,6 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) { return(htmlParseNameComplex(ctxt)); } } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); if (ctxt->input->cur - ctxt->input->base < len) { /* Sanity check */ @@ -2683,7 +2606,11 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) { return (NULL); } - return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len); + if (ret == NULL) + htmlErrMemory(ctxt); + + return(ret); } @@ -2716,7 +2643,7 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) { buffer_size = HTML_PARSER_BUFFER_SIZE; buffer = (xmlChar *) xmlMallocAtomic(buffer_size); if (buffer == NULL) { - htmlErrMemory(ctxt, "buffer allocation failed\n"); + htmlErrMemory(ctxt); return(NULL); } out = buffer; @@ -2724,7 +2651,8 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) { /* * Ok loop until we reach one of the ending chars */ - while ((CUR != 0) && (CUR != stop)) { + while ((PARSER_STOPPED(ctxt) == 0) && + (CUR != 0) && (CUR != stop)) { if ((stop == 0) && (CUR == '>')) break; if ((stop == 0) && (IS_BLANK_CH(CUR))) break; if (CUR == '&') { @@ -2810,10 +2738,6 @@ htmlParseHTMLAttribute(htmlParserCtxtPtr ctxt, const xmlChar stop) { out = &buffer[indx]; } c = CUR_CHAR(l); - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buffer); - return(NULL); - } if (c < 0x80) { *out++ = c; bits= -6; } else if (c < 0x800) @@ -2966,7 +2890,8 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) { return(ret); startPosition = CUR_PTR - BASE_PTR; - while ((CUR != 0) && (CUR != quote)) { + while ((PARSER_STOPPED(ctxt) == 0) && + (CUR != 0) && (CUR != quote)) { /* TODO: Handle UTF-8 */ if (!IS_CHAR_CH(CUR)) { htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, @@ -2980,8 +2905,13 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished SystemLiteral\n", NULL, NULL); } else { - if (err == 0) + if (err == 0) { ret = xmlStrndup((BASE_PTR+startPosition), len); + if (ret == NULL) { + htmlErrMemory(ctxt); + return(NULL); + } + } NEXT; } @@ -3021,7 +2951,8 @@ htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) { return(ret); startPosition = CUR_PTR - BASE_PTR; - while ((CUR != 0) && (CUR != quote)) { + while ((PARSER_STOPPED(ctxt) == 0) && + (CUR != 0) && (CUR != quote)) { if (!IS_PUBIDCHAR_CH(CUR)) { htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, "Invalid char in PubidLiteral 0x%X\n", CUR); @@ -3035,8 +2966,13 @@ htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) { htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, "Unfinished PubidLiteral\n", NULL, NULL); } else { - if (err == 0) + if (err == 0) { ret = xmlStrndup((BASE_PTR + startPosition), len); + if (ret == NULL) { + htmlErrMemory(ctxt); + return(NULL); + } + } NEXT; } @@ -3125,9 +3061,6 @@ htmlParseScript(htmlParserCtxtPtr ctxt) { cur = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return; - if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) { buf[nbchar] = 0; if (ctxt->sax->cdataBlock!= NULL) { @@ -3163,9 +3096,10 @@ htmlParseCharDataInternal(htmlParserCtxtPtr ctxt, int readahead) { buf[nbchar++] = readahead; cur = CUR_CHAR(l); - while (((cur != '<') || (ctxt->token == '<')) && - ((cur != '&') || (ctxt->token == '&')) && - (cur != 0)) { + while ((cur != '<') && + (cur != '&') && + (cur != 0) && + (!PARSER_STOPPED(ctxt))) { if (!(IS_CHAR(cur))) { htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR, "Invalid char in CDATA 0x%X\n", cur); @@ -3200,8 +3134,6 @@ htmlParseCharDataInternal(htmlParserCtxtPtr ctxt, int readahead) { } cur = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return; if (nbchar != 0) { buf[nbchar] = 0; @@ -3301,12 +3233,11 @@ htmlParseExternalID(htmlParserCtxtPtr ctxt, xmlChar **publicID) { } /** - * xmlParsePI: - * @ctxt: an XML parser context - * - * parse an XML Processing Instruction. + * htmlParsePI: + * @ctxt: an HTML parser context * - * [16] PI ::= '' Char*)))? '?>' + * Parse an XML Processing Instruction. HTML5 doesn't allow processing + * instructions, so this will be removed at some point. */ static void htmlParsePI(htmlParserCtxtPtr ctxt) { @@ -3344,13 +3275,11 @@ htmlParsePI(htmlParserCtxtPtr ctxt) { (ctxt->sax->processingInstruction != NULL)) ctxt->sax->processingInstruction(ctxt->userData, target, NULL); - ctxt->instate = state; - return; + goto done; } buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - htmlErrMemory(ctxt, NULL); - ctxt->instate = state; + htmlErrMemory(ctxt); return; } cur = CUR; @@ -3367,9 +3296,8 @@ htmlParsePI(htmlParserCtxtPtr ctxt) { size *= 2; tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); xmlFree(buf); - ctxt->instate = state; return; } buf = tmp; @@ -3385,17 +3313,12 @@ htmlParsePI(htmlParserCtxtPtr ctxt) { htmlParseErr(ctxt, XML_ERR_PI_NOT_FINISHED, "PI %s too long", target, NULL); xmlFree(buf); - ctxt->instate = state; - return; + goto done; } NEXTL(l); cur = CUR_CHAR(l); } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return; - } if (cur != '>') { htmlParseErr(ctxt, XML_ERR_PI_NOT_FINISHED, "ParsePI: PI %s never end ...\n", target, NULL); @@ -3415,6 +3338,8 @@ htmlParsePI(htmlParserCtxtPtr ctxt) { htmlParseErr(ctxt, XML_ERR_PI_NOT_STARTED, "PI is not started correctly", NULL, NULL); } + +done: ctxt->instate = state; } } @@ -3423,9 +3348,7 @@ htmlParsePI(htmlParserCtxtPtr ctxt) { * htmlParseComment: * @ctxt: an HTML parser context * - * Parse an XML (SGML) comment - * - * [15] Comment ::= '' + * Parse an HTML comment */ static void htmlParseComment(htmlParserCtxtPtr ctxt) { @@ -3452,8 +3375,7 @@ htmlParseComment(htmlParserCtxtPtr ctxt) { SKIP(4); buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - htmlErrMemory(ctxt, "buffer allocation failed\n"); - ctxt->instate = state; + htmlErrMemory(ctxt); return; } len = 0; @@ -3497,8 +3419,7 @@ htmlParseComment(htmlParserCtxtPtr ctxt) { tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { xmlFree(buf); - htmlErrMemory(ctxt, "growing buffer failed\n"); - ctxt->instate = state; + htmlErrMemory(ctxt); return; } buf = tmp; @@ -3526,10 +3447,6 @@ htmlParseComment(htmlParserCtxtPtr ctxt) { } finished: buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return; - } if (cur == '>') { NEXT; if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) && @@ -3563,12 +3480,8 @@ int htmlParseCharRef(htmlParserCtxtPtr ctxt) { int val = 0; - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseCharRef: context error\n", - NULL, NULL); + if ((ctxt == NULL) || (ctxt->input == NULL)) return(0); - } if ((CUR == '&') && (NXT(1) == '#') && ((NXT(2) == 'x') || NXT(2) == 'X')) { SKIP(3); @@ -3681,7 +3594,7 @@ htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) { "DOCTYPE improperly terminated\n", NULL, NULL); /* Ignore bogus content */ while ((CUR != 0) && (CUR != '>') && - (ctxt->instate != XML_PARSER_EOF)) + (PARSER_STOPPED(ctxt) == 0)) NEXT; } if (CUR == '>') @@ -3762,6 +3675,7 @@ htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) { static void htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { const xmlChar *encoding; + xmlChar *copy; if (!attvalue) return; @@ -3777,7 +3691,10 @@ htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { encoding = xmlStrcasestr(attvalue, BAD_CAST"="); if (encoding && *encoding == '=') { encoding ++; - xmlSetDeclaredEncoding(ctxt, xmlStrdup(encoding)); + copy = xmlStrdup(encoding); + if (copy == NULL) + htmlErrMemory(ctxt); + xmlSetDeclaredEncoding(ctxt, copy); } } @@ -3802,13 +3719,21 @@ htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) { att = atts[i++]; while (att != NULL) { value = atts[i++]; - if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"http-equiv")) - && (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) - http = 1; - else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"charset"))) - xmlSetDeclaredEncoding(ctxt, xmlStrdup(value)); - else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content"))) - content = value; + if (value != NULL) { + if ((!xmlStrcasecmp(att, BAD_CAST "http-equiv")) && + (!xmlStrcasecmp(value, BAD_CAST "Content-Type"))) { + http = 1; + } else if (!xmlStrcasecmp(att, BAD_CAST "charset")) { + xmlChar *copy; + + copy = xmlStrdup(value); + if (copy == NULL) + htmlErrMemory(ctxt); + xmlSetDeclaredEncoding(ctxt, copy); + } else if (!xmlStrcasecmp(att, BAD_CAST "content")) { + content = value; + } + } att = atts[i++]; } if ((http) && (content != NULL)) @@ -3848,13 +3773,8 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { int i; int discardtag = 0; - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseStartTag: context error\n", NULL, NULL); + if ((ctxt == NULL) || (ctxt->input == NULL)) return -1; - } - if (ctxt->instate == XML_PARSER_EOF) - return(-1); if (CUR != '<') return -1; NEXT; @@ -3869,7 +3789,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { NULL, NULL); /* Dump the bogus tag like browsers do */ while ((CUR != 0) && (CUR != '>') && - (ctxt->instate != XML_PARSER_EOF)) + (PARSER_STOPPED(ctxt) == 0)) NEXT; return -1; } @@ -3927,7 +3847,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { while ((CUR != 0) && (CUR != '>') && ((CUR != '/') || (NXT(1) != '>')) && - (ctxt->instate != XML_PARSER_EOF)) { + (PARSER_STOPPED(ctxt) == 0)) { GROW; attname = htmlParseAttribute(ctxt, &attvalue); if (attname != NULL) { @@ -3953,7 +3873,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *)); if (atts == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); if (attvalue != NULL) xmlFree(attvalue); goto failed; @@ -3967,7 +3887,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { n = (const xmlChar **) xmlRealloc((void *) atts, maxatts * sizeof(const xmlChar *)); if (n == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); if (attvalue != NULL) xmlFree(attvalue); goto failed; @@ -3989,7 +3909,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { while ((CUR != 0) && !(IS_BLANK_CH(CUR)) && (CUR != '>') && ((CUR != '/') || (NXT(1) != '>')) && - (ctxt->instate != XML_PARSER_EOF)) + (PARSER_STOPPED(ctxt) == 0)) NEXT; } @@ -4066,7 +3986,8 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt) htmlParseErr(ctxt, XML_ERR_GT_REQUIRED, "End tag : expected '>'\n", NULL, NULL); /* Skip to next '>' */ - while ((CUR != 0) && (CUR != '>')) + while ((PARSER_STOPPED(ctxt) == 0) && + (CUR != 0) && (CUR != '>')) NEXT; } if (CUR == '>') @@ -4227,12 +4148,9 @@ htmlParseContent(htmlParserCtxtPtr ctxt) { currentNode = xmlStrdup(ctxt->name); depth = ctxt->nameNr; - while (1) { + while (!PARSER_STOPPED(ctxt)) { GROW; - if (ctxt->instate == XML_PARSER_EOF) - break; - /* * Our tag or one of it's parent or children is ending. */ @@ -4387,14 +4305,8 @@ htmlParseElement(htmlParserCtxtPtr ctxt) { int depth; const xmlChar *oldptr; - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseElement: context error\n", NULL, NULL); + if ((ctxt == NULL) || (ctxt->input == NULL)) return; - } - - if (ctxt->instate == XML_PARSER_EOF) - return; /* Capture start position */ if (ctxt->record_info) { @@ -4534,14 +4446,8 @@ htmlParseElementInternal(htmlParserCtxtPtr ctxt) { htmlParserNodeInfo node_info = { NULL, 0, 0, 0, 0 }; int failed; - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseElementInternal: context error\n", NULL, NULL); + if ((ctxt == NULL) || (ctxt->input == NULL)) return; - } - - if (ctxt->instate == XML_PARSER_EOF) - return; /* Capture start position */ if (ctxt->record_info) { @@ -4632,16 +4538,13 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) { } else { currentNode = xmlStrdup(ctxt->name); if (currentNode == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); return; } } - while (1) { + while (PARSER_STOPPED(ctxt) == 0) { GROW; - if (ctxt->instate == XML_PARSER_EOF) - break; - /* * Our tag or one of it's parent or children is ending. */ @@ -4657,7 +4560,7 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) { } else { currentNode = xmlStrdup(ctxt->name); if (currentNode == NULL) { - htmlErrMemory(ctxt, NULL); + htmlErrMemory(ctxt); break; } } @@ -4681,10 +4584,14 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) { if (currentNode != NULL) xmlFree(currentNode); - currentNode = xmlStrdup(ctxt->name); - if (currentNode == NULL) { - htmlErrMemory(ctxt, NULL); - break; + if (ctxt->name == NULL) { + currentNode = NULL; + } else { + currentNode = xmlStrdup(ctxt->name); + if (currentNode == NULL) { + htmlErrMemory(ctxt); + break; + } } depth = ctxt->nameNr; continue; @@ -4708,10 +4615,14 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) { htmlParserFinishElementParsing(ctxt); if (currentNode != NULL) xmlFree(currentNode); - currentNode = xmlStrdup(ctxt->name); - if (currentNode == NULL) { - htmlErrMemory(ctxt, NULL); - break; + if (ctxt->name == NULL) { + currentNode = NULL; + } else { + currentNode = xmlStrdup(ctxt->name); + if (currentNode == NULL) { + htmlErrMemory(ctxt); + break; + } } depth = ctxt->nameNr; continue; @@ -4763,10 +4674,14 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) { htmlParseElementInternal(ctxt); if (currentNode != NULL) xmlFree(currentNode); - currentNode = xmlStrdup(ctxt->name); - if (currentNode == NULL) { - htmlErrMemory(ctxt, NULL); - break; + if (ctxt->name == NULL) { + currentNode = NULL; + } else { + currentNode = xmlStrdup(ctxt->name); + if (currentNode == NULL) { + htmlErrMemory(ctxt); + break; + } } depth = ctxt->nameNr; } @@ -4824,30 +4739,27 @@ __htmlParseContent(void *ctxt) { * htmlParseDocument: * @ctxt: an HTML parser context * - * parse an HTML document (and build a tree if using the standard SAX - * interface). + * Parse an HTML document and invoke the SAX handlers. This is useful + * if you're only interested in custom SAX callbacks. If you want a + * document tree, use htmlCtxtParseDocument. * - * Returns 0, -1 in case of error. the parser context is augmented - * as a result of the parsing. + * Returns 0, -1 in case of error. */ int htmlParseDocument(htmlParserCtxtPtr ctxt) { xmlDtdPtr dtd; - xmlInitParser(); - - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseDocument: context error\n", NULL, NULL); - return(XML_ERR_INTERNAL_ERROR); - } + if ((ctxt == NULL) || (ctxt->input == NULL)) + return(-1); /* - * SAX: beginning of the document processing. + * Document locator is unused. Only for backward compatibility. */ - if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) - ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator); + if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) { + xmlSAXLocator copy = xmlDefaultSAXLocator; + ctxt->sax->setDocumentLocator(ctxt->userData, ©); + } xmlDetectEncoding(ctxt); @@ -4871,7 +4783,6 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) { if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); - /* * Parse possible comments and PIs before any content */ @@ -4900,9 +4811,10 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) { /* * Parse possible comments and PIs before any content */ - while (((CUR == '<') && (NXT(1) == '!') && - (NXT(2) == '-') && (NXT(3) == '-')) || - ((CUR == '<') && (NXT(1) == '?'))) { + while ((PARSER_STOPPED(ctxt) == 0) && + (((CUR == '<') && (NXT(1) == '!') && + (NXT(2) == '-') && (NXT(3) == '-')) || + ((CUR == '<') && (NXT(1) == '?')))) { htmlParseComment(ctxt); htmlParsePI(ctxt); SKIP_BLANKS; @@ -4928,11 +4840,14 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) { if ((!(ctxt->options & HTML_PARSE_NODEFDTD)) && (ctxt->myDoc != NULL)) { dtd = xmlGetIntSubset(ctxt->myDoc); - if (dtd == NULL) + if (dtd == NULL) { ctxt->myDoc->intSubset = xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html", BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN", BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd"); + if (ctxt->myDoc->intSubset == NULL) + htmlErrMemory(ctxt); + } } if (! ctxt->wellFormed) return(-1); return(0); @@ -4964,17 +4879,13 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax, memset(ctxt, 0, sizeof(htmlParserCtxt)); ctxt->dict = xmlDictCreate(); - if (ctxt->dict == NULL) { - htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n"); + if (ctxt->dict == NULL) return(-1); - } if (ctxt->sax == NULL) ctxt->sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler)); - if (ctxt->sax == NULL) { - htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n"); + if (ctxt->sax == NULL) return(-1); - } if (sax == NULL) { memset(ctxt->sax, 0, sizeof(htmlSAXHandler)); xmlSAX2InitHtmlDefaultSAXHandler(ctxt->sax); @@ -4987,13 +4898,8 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax, /* Allocate the Input stack */ ctxt->inputTab = (htmlParserInputPtr *) xmlMalloc(5 * sizeof(htmlParserInputPtr)); - if (ctxt->inputTab == NULL) { - htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n"); - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->inputTab == NULL) return(-1); - } ctxt->inputNr = 0; ctxt->inputMax = 5; ctxt->input = NULL; @@ -5004,35 +4910,16 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax, /* Allocate the Node stack */ ctxt->nodeTab = (htmlNodePtr *) xmlMalloc(10 * sizeof(htmlNodePtr)); - if (ctxt->nodeTab == NULL) { - htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->nodeTab == NULL) return(-1); - } ctxt->nodeNr = 0; ctxt->nodeMax = 10; ctxt->node = NULL; /* Allocate the Name stack */ ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *)); - if (ctxt->nameTab == NULL) { - htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n"); - ctxt->nameNr = 0; - ctxt->nameMax = 0; - ctxt->name = NULL; - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->nameTab == NULL) return(-1); - } ctxt->nameNr = 0; ctxt->nameMax = 10; ctxt->name = NULL; @@ -5076,7 +4963,19 @@ htmlFreeParserCtxt(htmlParserCtxtPtr ctxt) /** * htmlNewParserCtxt: * - * Allocate and initialize a new parser context. + * Allocate and initialize a new HTML parser context. + * + * This can be used to parse HTML documents into DOM trees with + * functions like xmlCtxtReadFile or xmlCtxtReadMemory. + * + * See htmlCtxtUseOptions for parser options. + * + * See xmlCtxtSetErrorHandler for advanced error handling. + * + * See xmlNewInputURL, xmlNewInputMemory, xmlNewInputIO and similar + * functions for advanced input control. + * + * See htmlNewSAXParserCtxt for custom SAX parsers. * * Returns the htmlParserCtxtPtr or NULL in case of allocation error */ @@ -5092,8 +4991,14 @@ htmlNewParserCtxt(void) * @sax: SAX handler * @userData: user data * - * Allocate and initialize a new SAX parser context. If userData is NULL, - * the parser context will be passed as user data. + * Allocate and initialize a new HTML SAX parser context. If userData + * is NULL, the parser context will be passed as user data. + * + * Available since 2.11.0. If you want support older versions, + * it's best to invoke htmlNewParserCtxt and set ctxt->sax with + * struct assignment. + * + * Also see htmlNewParserCtxt. * * Returns the htmlParserCtxtPtr or NULL in case of allocation error */ @@ -5103,11 +5008,11 @@ htmlNewSAXParserCtxt(const htmlSAXHandler *sax, void *userData) { xmlParserCtxtPtr ctxt; + xmlInitParser(); + ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt)); - if (ctxt == NULL) { - htmlErrMemory(NULL, "NewParserCtxt: out of memory\n"); + if (ctxt == NULL) return(NULL); - } memset(ctxt, 0, sizeof(xmlParserCtxt)); if (htmlInitParserCtxt(ctxt, sax, userData) < 0) { htmlFreeParserCtxt(ctxt); @@ -5116,67 +5021,65 @@ htmlNewSAXParserCtxt(const htmlSAXHandler *sax, void *userData) return(ctxt); } -/** - * htmlCreateMemoryParserCtxt: - * @buffer: a pointer to a char array - * @size: the size of the array - * - * Create a parser context for an HTML in-memory document. - * - * Returns the new parser context or NULL - */ -htmlParserCtxtPtr -htmlCreateMemoryParserCtxt(const char *buffer, int size) { +static htmlParserCtxtPtr +htmlCreateMemoryParserCtxtInternal(const char *url, + const char *buffer, size_t size, + const char *encoding) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; if (buffer == NULL) return(NULL); - if (size <= 0) - return(NULL); ctxt = htmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); - return(NULL); + return(NULL); } - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } /** - * htmlCreateDocParserCtxt: - * @str: a pointer to an array of xmlChar - * @encoding: a free form C string describing the HTML document encoding, or NULL + * htmlCreateMemoryParserCtxt: + * @buffer: a pointer to a char array + * @size: the size of the array * - * Create a parser context for an HTML document. + * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadMemory. * - * TODO: check the need to add encoding handling there + * Create a parser context for an HTML in-memory document. The input + * buffer must not contain any terminating null bytes. * * Returns the new parser context or NULL */ +htmlParserCtxtPtr +htmlCreateMemoryParserCtxt(const char *buffer, int size) { + if (size <= 0) + return(NULL); + + return(htmlCreateMemoryParserCtxtInternal(NULL, buffer, size, NULL)); +} + +/** + * htmlCreateDocParserCtxt: + * @str: a pointer to an array of xmlChar + * @encoding: encoding (optional) + * + * Create a parser context for a null-terminated string. + * + * Returns the new parser context or NULL if a memory allocation failed. + */ static htmlParserCtxtPtr -htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) { +htmlCreateDocParserCtxt(const xmlChar *str, const char *url, + const char *encoding) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; if (str == NULL) return(NULL); @@ -5185,55 +5088,14 @@ htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) { if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateString(str); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputString(ctxt, url, (const char *) str, encoding, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(buf->buffer, input); - inputPush(ctxt, input); - if (encoding != NULL) { - xmlCharEncoding enc; - xmlCharEncodingHandlerPtr handler; - - enc = xmlParseCharEncoding(encoding); - /* - * registered set of known encodings - */ - if (enc != XML_CHAR_ENCODING_ERROR) { - xmlSwitchEncoding(ctxt, enc); - if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { - htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding %s\n", - (const xmlChar *) encoding, NULL); - } - } else { - /* - * fallback for unknown encodings - */ - handler = xmlFindCharEncodingHandler((const char *) encoding); - if (handler != NULL) { - xmlSwitchToEncoding(ctxt, handler); - } else { - htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding %s\n", - (const xmlChar *) encoding, NULL); - } - } - } - return(ctxt); } @@ -5379,7 +5241,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { htmlParserNodeInfo node_info; - while (1) { + while (PARSER_STOPPED(ctxt) == 0) { in = ctxt->input; if (in == NULL) break; @@ -5434,14 +5296,13 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { SKIP_BLANKS; avail = in->end - in->cur; } - if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) - ctxt->sax->setDocumentLocator(ctxt->userData, - &xmlDefaultSAXLocator); + if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) { + xmlSAXLocator copy = xmlDefaultSAXLocator; + ctxt->sax->setDocumentLocator(ctxt->userData, ©); + } if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); - if (ctxt->instate == XML_PARSER_EOF) - goto done; cur = in->cur[0]; next = in->cur[1]; @@ -5454,8 +5315,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0)) goto done; htmlParseDocTypeDecl(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } else { ctxt->instate = XML_PARSER_MISC; @@ -5486,16 +5345,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; htmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_MISC; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_MISC; } else if ((cur == '<') && (next == '!') && (UPP(2) == 'D') && (UPP(3) == 'O') && @@ -5506,8 +5361,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0)) goto done; htmlParseDocTypeDecl(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } else if ((cur == '<') && (next == '!') && (avail < 9)) { @@ -5528,16 +5381,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; htmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } else if ((cur == '<') && (next == '!') && (avail < 4)) { @@ -5563,16 +5412,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; htmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_EPILOG; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_EPILOG; } else if ((cur == '<') && (next == '!') && (avail < 4)) { @@ -5655,8 +5500,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) ctxt->sax->endElement(ctxt->userData, name); htmlnamePop(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; break; } @@ -5679,8 +5522,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (ctxt->record_info) htmlNodeInfoPush(ctxt, &node_info); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; break; } @@ -5697,8 +5538,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (ctxt->record_info) htmlNodeInfoPush(ctxt, &node_info); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; break; } @@ -5708,14 +5547,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { /* * Handle preparsed entities and charRef */ - if (ctxt->token != 0) { - chr[0] = ctxt->token; - htmlCheckParagraph(ctxt); - if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) - ctxt->sax->characters(ctxt->userData, chr, 1); - ctxt->token = 0; - ctxt->checkIndex = 0; - } if ((avail == 1) && (terminate)) { cur = in->cur[0]; if ((cur != '<') && (cur != '&')) { @@ -5738,7 +5569,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { ctxt->userData, chr, 1); } } - ctxt->token = 0; ctxt->checkIndex = 0; in->cur++; break; @@ -5771,8 +5601,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { } } htmlParseScript(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; if ((cur == '<') && (next == '/')) { ctxt->instate = XML_PARSER_END_TAG; ctxt->checkIndex = 0; @@ -5800,8 +5628,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; htmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; } else { if ((!terminate) && @@ -5814,8 +5640,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; } else if ((cur == '<') && (next == '/')) { ctxt->instate = XML_PARSER_END_TAG; @@ -5844,7 +5668,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0)) goto done; ctxt->checkIndex = 0; - while ((ctxt->instate != XML_PARSER_EOF) && + while ((PARSER_STOPPED(ctxt) == 0) && (cur != '<') && (in->cur < in->end)) { if (cur == '&') { htmlParseReference(ctxt); @@ -5864,8 +5688,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParseEndTag(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; } else { @@ -5897,11 +5719,14 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (ctxt->instate == XML_PARSER_EPILOG))) { xmlDtdPtr dtd; dtd = xmlGetIntSubset(ctxt->myDoc); - if (dtd == NULL) + if (dtd == NULL) { ctxt->myDoc->intSubset = xmlCreateIntSubset(ctxt->myDoc, BAD_CAST "html", BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN", BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd"); + if (ctxt->myDoc->intSubset == NULL) + htmlErrMemory(ctxt); + } } return(ret); } @@ -5909,24 +5734,33 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { /** * htmlParseChunk: * @ctxt: an HTML parser context - * @chunk: an char array - * @size: the size in byte of the chunk + * @chunk: chunk of memory + * @size: size of chunk in bytes * @terminate: last chunk indicator * - * Parse a Chunk of memory + * Parse a chunk of memory in push parser mode. + * + * Assumes that the parser context was initialized with + * htmlCreatePushParserCtxt. * - * Returns zero if no error, the xmlParserErrors otherwise. + * The last chunk, which will often be empty, must be marked with + * the @terminate flag. With the default SAX callbacks, the resulting + * document will be available in ctxt->myDoc. This pointer will not + * be freed by the library. + * + * If the document isn't well-formed, ctxt->myDoc is set to NULL. + * + * Returns an xmlParserErrors code (0 on success). */ int htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, int terminate) { - if ((ctxt == NULL) || (ctxt->input == NULL)) { - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "htmlParseChunk: context error\n", NULL, NULL); - return(XML_ERR_INTERNAL_ERROR); - } + if ((ctxt == NULL) || (ctxt->input == NULL)) + return(XML_ERR_ARGUMENT); + if (PARSER_STOPPED(ctxt) != 0) + return(ctxt->errNo); if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { + (ctxt->input->buf != NULL)) { size_t pos = ctxt->input->cur - ctxt->input->base; int res; @@ -5941,12 +5775,6 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, } htmlParseTryOrFinish(ctxt, terminate); if (terminate) { - if ((ctxt->instate != XML_PARSER_EOF) && - (ctxt->instate != XML_PARSER_EPILOG) && - (ctxt->instate != XML_PARSER_MISC)) { - ctxt->errNo = XML_ERR_DOCUMENT_END; - ctxt->wellFormed = 0; - } if (ctxt->instate != XML_PARSER_EOF) { if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt->userData); @@ -5964,77 +5792,37 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, /** * htmlCreatePushParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks - * @chunk: a pointer to an array of chars + * @sax: a SAX handler (optional) + * @user_data: The user data returned on SAX callbacks (optional) + * @chunk: a pointer to an array of chars (optional) * @size: number of chars in the array - * @filename: an optional file name or URI - * @enc: an optional encoding + * @filename: only used for error reporting (optional) + * @enc: encoding (deprecated, pass XML_CHAR_ENCODING_NONE) * - * Create a parser context for using the HTML parser in push mode - * The value of @filename is used for fetching external entities - * and error/warning reports. + * Create a parser context for using the HTML parser in push mode. * - * Returns the new parser context or NULL + * Returns the new parser context or NULL if a memory allocation + * failed. */ htmlParserCtxtPtr htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename, xmlCharEncoding enc) { htmlParserCtxtPtr ctxt; - htmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; - - xmlInitParser(); - - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) return(NULL); + htmlParserInputPtr input; + const char *encoding; ctxt = htmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); + if (ctxt == NULL) return(NULL); - } - if (filename == NULL) { - ctxt->directory = NULL; - } else { - ctxt->directory = xmlParserGetDirectory(filename); - } - inputStream = htmlNewInputStream(ctxt); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); + encoding = xmlGetCharEncodingName(enc); + input = xmlNewInputPush(ctxt, filename, chunk, size, encoding); + if (input == NULL) { + htmlFreeParserCtxt(ctxt); return(NULL); } - - if (filename == NULL) - inputStream->filename = NULL; - else - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - inputStream->buf = buf; - xmlBufResetInput(buf->buffer, inputStream); - - inputPush(ctxt, inputStream); - - if (enc != XML_CHAR_ENCODING_NONE) - xmlSwitchEncoding(ctxt, enc); - - if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; - - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - htmlParseErr(ctxt, ctxt->input->buf->error, - "xmlParserInputBufferPush failed\n", NULL, NULL); - xmlHaltParser(ctxt); - } - } - ctxt->progressive = 1; + inputPush(ctxt, input); return(ctxt); } @@ -6063,25 +5851,20 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding, htmlDocPtr ret; htmlParserCtxtPtr ctxt; - xmlInitParser(); - - if (cur == NULL) return(NULL); + if (cur == NULL) + return(NULL); + ctxt = htmlCreateDocParserCtxt(cur, NULL, encoding); + if (ctxt == NULL) + return(NULL); - ctxt = htmlCreateDocParserCtxt(cur, encoding); - if (ctxt == NULL) return(NULL); if (sax != NULL) { - if (ctxt->sax != NULL) xmlFree (ctxt->sax); - ctxt->sax = sax; + *ctxt->sax = *sax; ctxt->userData = userData; } htmlParseDocument(ctxt); ret = ctxt->myDoc; - if (sax != NULL) { - ctxt->sax = NULL; - ctxt->userData = NULL; - } htmlFreeParserCtxt(ctxt); return(ret); @@ -6090,9 +5873,13 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding, /** * htmlParseDoc: * @cur: a pointer to an array of xmlChar - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: the encoding (optional) + * + * DEPRECATED: Use htmlReadDoc. + * + * Parse an HTML in-memory document and build a tree. * - * parse an HTML in-memory document and build a tree. + * This function uses deprecated global parser options. * * Returns the resulting document tree */ @@ -6106,20 +5893,24 @@ htmlParseDoc(const xmlChar *cur, const char *encoding) { /** * htmlCreateFileParserCtxt: * @filename: the filename - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: optional encoding + * + * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadFile. + * + * Create a parser context to read from a file. + * + * A non-NULL encoding overrides encoding declarations in the document. * - * Create a parser context for a file content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. * - * Returns the new parser context or NULL + * Returns the new parser context or NULL if a memory allocation failed. */ htmlParserCtxtPtr htmlCreateFileParserCtxt(const char *filename, const char *encoding) { htmlParserCtxtPtr ctxt; - htmlParserInputPtr inputStream; - char *canonicFilename; + htmlParserInputPtr input; if (filename == NULL) return(NULL); @@ -6128,30 +5919,13 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) if (ctxt == NULL) { return(NULL); } - canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename); - if (canonicFilename == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt); - xmlFree(canonicFilename); - if (inputStream == NULL) { + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); } - - inputPush(ctxt, inputStream); - - /* set encoding */ - if (encoding) { - xmlCharEncodingHandlerPtr hdlr; - - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } - } + inputPush(ctxt, input); return(ctxt); } @@ -6159,7 +5933,7 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) /** * htmlSAXParseFile: * @filename: the filename - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: encoding (optional) * @sax: the SAX handler block * @userData: if using SAX, this pointer will be provided on callbacks. * @@ -6181,8 +5955,6 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s htmlParserCtxtPtr ctxt; htmlSAXHandlerPtr oldsax = NULL; - xmlInitParser(); - ctxt = htmlCreateFileParserCtxt(filename, encoding); if (ctxt == NULL) return(NULL); if (sax != NULL) { @@ -6206,10 +5978,11 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s /** * htmlParseFile: * @filename: the filename - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: encoding (optional) * - * parse an HTML file and build a tree. Automatic support for ZLIB/Compress - * compressed document is provided by default if found at compile-time. + * Parse an HTML file and build a tree. + * + * See xmlNewInputURL for details. * * Returns the resulting document tree */ @@ -6223,6 +5996,8 @@ htmlParseFile(const char *filename, const char *encoding) { * htmlHandleOmittedElem: * @val: int 0 or 1 * + * DEPRECATED: Use HTML_PARSE_NOIMPLIED + * * Set and return the previous value for handling HTML omitted tags. * * Returns the last value for 0 for no handling, 1 for auto insertion. @@ -6328,7 +6103,7 @@ htmlAttrAllowed(const htmlElemDesc* elt, const xmlChar* attr, int legacy) { * for other nodes, HTML_NA (no checks performed) */ htmlStatus -htmlNodeStatus(const htmlNodePtr node, int legacy) { +htmlNodeStatus(htmlNodePtr node, int legacy) { if ( ! node ) return HTML_INVALID ; @@ -6380,7 +6155,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) if (ctxt == NULL) return; - xmlInitParser(); dict = ctxt->dict; while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ @@ -6410,8 +6184,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) ctxt->version = NULL; DICT_FREE(ctxt->encoding); ctxt->encoding = NULL; - DICT_FREE(ctxt->directory); - ctxt->directory = NULL; DICT_FREE(ctxt->extSubURI); ctxt->extSubURI = NULL; DICT_FREE(ctxt->extSubSystem); @@ -6424,9 +6196,7 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) ctxt->hasExternalSubset = 0; ctxt->hasPErefs = 0; ctxt->html = 1; - ctxt->external = 0; ctxt->instate = XML_PARSER_START; - ctxt->token = 0; ctxt->wellFormed = 1; ctxt->nsWellFormed = 1; @@ -6533,263 +6303,281 @@ htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options) } /** - * htmlDoRead: + * htmlCtxtParseDocument: * @ctxt: an HTML parser context - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) - * @reuse: keep the context for reuse + * @input: parser input + * + * Parse an HTML document and return the resulting document tree. * - * Common front-end for the htmlRead functions + * Available since 2.13.0. * * Returns the resulting document tree or NULL */ -static htmlDocPtr -htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding, - int options, int reuse) +htmlDocPtr +htmlCtxtParseDocument(htmlParserCtxtPtr ctxt, xmlParserInputPtr input) { htmlDocPtr ret; - htmlCtxtUseOptions(ctxt, options); - ctxt->html = 1; - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; + if ((ctxt == NULL) || (input == NULL)) + return(NULL); - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } + /* assert(ctxt->inputNr == 0); */ + while (ctxt->inputNr > 0) + xmlFreeInputStream(inputPop(ctxt)); + + if (inputPush(ctxt, input) < 0) { + xmlFreeInputStream(input); + return(NULL); } - if ((URL != NULL) && (ctxt->input != NULL) && - (ctxt->input->filename == NULL)) - ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + + ctxt->html = 1; htmlParseDocument(ctxt); - ret = ctxt->myDoc; - ctxt->myDoc = NULL; - if (!reuse) { - if ((ctxt->dictNames) && - (ret != NULL) && - (ret->dict == ctxt->dict)) - ctxt->dict = NULL; - xmlFreeParserCtxt(ctxt); + + if (ctxt->errNo != XML_ERR_NO_MEMORY) { + ret = ctxt->myDoc; + } else { + ret = NULL; + xmlFreeDoc(ctxt->myDoc); } - return (ret); + ctxt->myDoc = NULL; + + /* assert(ctxt->inputNr == 1); */ + while (ctxt->inputNr > 0) + xmlFreeInputStream(inputPop(ctxt)); + + return(ret); } /** * htmlReadDoc: - * @cur: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @str: a pointer to a zero terminated string + * @url: only used for error reporting (optoinal) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML in-memory document and build a tree. + * Convenience function to parse an HTML document from a zero-terminated + * string. * - * Returns the resulting document tree + * See htmlCtxtReadDoc for details. + * + * Returns the resulting document tree. */ htmlDocPtr -htmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) +htmlReadDoc(const xmlChar *str, const char *url, const char *encoding, + int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - if (cur == NULL) - return (NULL); - - xmlInitParser(); - ctxt = htmlCreateDocParserCtxt(cur, NULL); + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputString(ctxt, url, (const char *) str, encoding, + XML_INPUT_BUF_STATIC); + + doc = htmlCtxtParseDocument(ctxt, input); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadFile: * @filename: a file or URL - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML file from the filesystem or the network. + * Convenience function to parse an HTML file from the filesystem, + * the network or a global user-defined resource loader. * - * Returns the resulting document tree + * See htmlCtxtReadFile for details. + * + * Returns the resulting document tree. */ htmlDocPtr htmlReadFile(const char *filename, const char *encoding, int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - xmlInitParser(); - ctxt = htmlCreateFileParserCtxt(filename, encoding); + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, NULL, NULL, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + + doc = htmlCtxtParseDocument(ctxt, input); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadMemory: * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document + * @url: only used for error reporting (optional) * @encoding: the document encoding, or NULL * @options: a combination of htmlParserOption(s) * - * parse an XML in-memory document and build a tree. + * Convenience function to parse an HTML document from memory. + * The input buffer must not contain any terminating null bytes. + * + * See htmlCtxtReadMemory for details. * * Returns the resulting document tree */ htmlDocPtr -htmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) +htmlReadMemory(const char *buffer, int size, const char *url, + const char *encoding, int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - xmlInitParser(); - ctxt = htmlCreateMemoryParserCtxt(buffer, size); + if (size < 0) + return(NULL); + + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + + doc = htmlCtxtParseDocument(ctxt, input); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadFd: * @fd: an open file descriptor - * @URL: the base URL to use for the document + * @url: only used for error reporting (optional) * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @options: a combination of htmlParserOptions + * + * Convenience function to parse an HTML document from a + * file descriptor. * - * parse an HTML from a file descriptor and build a tree. * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. + * + * See htmlCtxtReadFd for details. * * Returns the resulting document tree */ htmlDocPtr -htmlReadFd(int fd, const char *URL, const char *encoding, int options) +htmlReadFd(int fd, const char *url, const char *encoding, int options) { htmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - htmlParserInputPtr stream; - - if (fd < 0) - return (NULL); + xmlParserInputPtr input; + htmlDocPtr doc; - xmlInitParser(); - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - input->closecallback = NULL; ctxt = htmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - htmlFreeParserCtxt(ctxt); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + if (ctxt == NULL) + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputFd(ctxt, url, fd, encoding, 0); + + doc = htmlCtxtParseDocument(ctxt, input); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadIO: * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @url: only used for error reporting (optional) + * @encoding: the document encoding (optional) * @options: a combination of htmlParserOption(s) * - * parse an HTML document from I/O functions and source and build a tree. + * Convenience function to parse an HTML document from I/O functions + * and context. + * + * See htmlCtxtReadIO for details. * * Returns the resulting document tree */ htmlDocPtr htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, - void *ioctx, const char *URL, const char *encoding, int options) + void *ioctx, const char *url, const char *encoding, int options) { htmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; - - if (ioread == NULL) - return (NULL); - xmlInitParser(); + xmlParserInputPtr input; + htmlDocPtr doc; - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - if (ioclose != NULL) - ioclose(ioctx); - return (NULL); - } ctxt = htmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - xmlFreeParserCtxt(ctxt); + if (ctxt == NULL) return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputIO(ctxt, url, ioread, ioclose, ioctx, encoding, 0); + + doc = htmlCtxtParseDocument(ctxt, input); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlCtxtReadDoc: * @ctxt: an HTML parser context * @str: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions + * + * Parse an HTML in-memory document and build a tree. * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * See htmlCtxtUseOptions for details. * * Returns the resulting document tree */ htmlDocPtr htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar *str, - const char *URL, const char *encoding, int options) + const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; if (ctxt == NULL) return (NULL); - if (str == NULL) - return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateString(str); - if (input == NULL) { - return(NULL); - } - - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } + input = xmlNewInputString(ctxt, URL, (const char *) str, encoding, 0); - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + return(htmlCtxtParseDocument(ctxt, input)); } /** * htmlCtxtReadFile: * @ctxt: an HTML parser context * @filename: a file or URL - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions + * + * Parse an HTML file from the filesystem, the network or a + * user-defined resource loader. * - * parse an XML file from the filesystem or the network. - * This reuses the existing @ctxt parser context + * See xmlNewInputURL and htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6797,22 +6585,17 @@ htmlDocPtr htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options) { - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (filename == NULL) - return (NULL); if (ctxt == NULL) return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - stream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (stream == NULL) { - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, NULL, encoding, options, 1)); + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + + return(htmlCtxtParseDocument(ctxt, input)); } /** @@ -6820,12 +6603,14 @@ htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, * @ctxt: an HTML parser context * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optinal) + * @options: a combination of htmlParserOptions * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * Parse an HTML in-memory document and build a tree. The input buffer must + * not contain any terminating null bytes. + * + * See htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6833,43 +6618,34 @@ htmlDocPtr htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ctxt == NULL) - return (NULL); - if (buffer == NULL) + if ((ctxt == NULL) || (size < 0)) return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateStatic(buffer, size, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - return(NULL); - } + input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding, + XML_INPUT_BUF_STATIC); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } - - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + return(htmlCtxtParseDocument(ctxt, input)); } /** * htmlCtxtReadFd: * @ctxt: an HTML parser context * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optinal) + * @options: a combination of htmlParserOptions + * + * Parse an HTML from a file descriptor and build a tree. * - * parse an XML from a file descriptor and build a tree. - * This reuses the existing @ctxt parser context + * See htmlCtxtUseOptions for details. + * + * NOTE that the file descriptor will not be closed when the + * context is freed or reset. * * Returns the resulting document tree */ @@ -6877,28 +6653,17 @@ htmlDocPtr htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (fd < 0) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + return(htmlCtxtParseDocument(ctxt, input)); } /** @@ -6911,8 +6676,9 @@ htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, * @encoding: the document encoding, or NULL * @options: a combination of htmlParserOption(s) * - * parse an HTML document from I/O functions and source and build a tree. - * This reuses the existing @ctxt parser context + * Parse an HTML document from I/O functions and source and build a tree. + * + * See xmlNewInputIO and htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6922,31 +6688,17 @@ htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ioread == NULL) - return (NULL); if (ctxt == NULL) return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - if (ioclose != NULL) - ioclose(ioctx); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); + + return(htmlCtxtParseDocument(ctxt, input)); } #endif /* LIBXML_HTML_ENABLED */ diff --git a/HTMLtree.c b/HTMLtree.c index 8698f53..6e8baf4 100644 --- a/HTMLtree.c +++ b/HTMLtree.c @@ -334,17 +334,6 @@ htmlIsBooleanAttr(const xmlChar *name) * Output error handlers * * * ************************************************************************/ -/** - * htmlSaveErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -htmlSaveErrMemory(const char *extra) -{ - __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra); -} /** * htmlSaveErr: @@ -358,6 +347,7 @@ static void htmlSaveErr(int code, xmlNodePtr node, const char *extra) { const char *msg = NULL; + int res; switch(code) { case XML_SAVE_NOT_UTF8: @@ -375,7 +365,13 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra) default: msg = "unexpected error number\n"; } - __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra); + + res = __xmlRaiseError(NULL, NULL, NULL, NULL, node, + XML_FROM_OUTPUT, code, XML_ERR_ERROR, NULL, 0, + extra, NULL, NULL, 0, 0, + msg, extra); + if (res < 0) + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_OUTPUT, NULL); } /************************************************************************ @@ -384,6 +380,32 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra) * * ************************************************************************/ +static xmlCharEncodingHandler * +htmlFindOutputEncoder(const char *encoding) { + xmlCharEncodingHandler *handler = NULL; + + if (encoding != NULL) { + xmlCharEncoding enc; + + enc = xmlParseCharEncoding(encoding); + if (enc != XML_CHAR_ENCODING_UTF8) { + xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler); + if (handler == NULL) + htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); + } + } else { + /* + * Fallback to HTML or ASCII when the encoding is unspecified + */ + if (handler == NULL) + xmlOpenCharEncodingHandler("HTML", /* output */ 1, &handler); + if (handler == NULL) + xmlOpenCharEncodingHandler("ascii", /* output */ 1, &handler); + } + + return(handler); +} + /** * htmlBufNodeDumpFormat: * @buf: the xmlBufPtr output @@ -399,20 +421,18 @@ static size_t htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int format) { size_t use; - int ret; + size_t ret; xmlOutputBufferPtr outbuf; if (cur == NULL) { - return (-1); + return ((size_t) -1); } if (buf == NULL) { - return (-1); + return ((size_t) -1); } outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); - if (outbuf == NULL) { - htmlSaveErrMemory("allocating HTML output buffer"); - return (-1); - } + if (outbuf == NULL) + return ((size_t) -1); memset(outbuf, 0, sizeof(xmlOutputBuffer)); outbuf->buffer = buf; outbuf->encoder = NULL; @@ -423,8 +443,11 @@ htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, use = xmlBufUse(buf); htmlNodeDumpFormatOutput(outbuf, doc, cur, NULL, format); + if (outbuf->error) + ret = (size_t) -1; + else + ret = xmlBufUse(buf) - use; xmlFree(outbuf); - ret = xmlBufUse(buf) - use; return (ret); } @@ -452,6 +475,7 @@ htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) { if (buffer == NULL) return(-1); + xmlBufSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); ret = htmlBufNodeDumpFormat(buffer, doc, cur, 1); xmlBufBackToBuffer(buffer); @@ -479,35 +503,20 @@ int htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc, xmlNodePtr cur, const char *encoding, int format) { xmlOutputBufferPtr buf; - xmlCharEncodingHandlerPtr handler = NULL; + xmlCharEncodingHandlerPtr handler; int ret; xmlInitParser(); - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); - } - } else { - /* - * Fallback to HTML or ASCII when the encoding is unspecified - */ - if (handler == NULL) - handler = xmlFindCharEncodingHandler("HTML"); - if (handler == NULL) - handler = xmlFindCharEncodingHandler("ascii"); - } - /* * save the content to a temp buffer. */ + handler = htmlFindOutputEncoder(encoding); buf = xmlOutputBufferCreateFile(out, handler); - if (buf == NULL) return(0); + if (buf == NULL) { + xmlCharEncCloseFunc(handler); + return(0); + } htmlNodeDumpFormatOutput(buf, doc, cur, NULL, format); @@ -549,52 +558,34 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) { if ((mem == NULL) || (size == NULL)) return; - if (cur == NULL) { - *mem = NULL; - *size = 0; + *mem = NULL; + *size = 0; + if (cur == NULL) return; - } encoding = (const char *) htmlGetMetaEncoding(cur); - - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); - - } - } else { - /* - * Fallback to HTML or ASCII when the encoding is unspecified - */ - if (handler == NULL) - handler = xmlFindCharEncodingHandler("HTML"); - if (handler == NULL) - handler = xmlFindCharEncodingHandler("ascii"); - } - + handler = htmlFindOutputEncoder(encoding); buf = xmlAllocOutputBufferInternal(handler); if (buf == NULL) { - *mem = NULL; - *size = 0; + xmlCharEncCloseFunc(handler); return; } htmlDocContentDumpFormatOutput(buf, cur, NULL, format); xmlOutputBufferFlush(buf); - if (buf->conv != NULL) { - *size = xmlBufUse(buf->conv); - *mem = xmlStrndup(xmlBufContent(buf->conv), *size); - } else { - *size = xmlBufUse(buf->buffer); - *mem = xmlStrndup(xmlBufContent(buf->buffer), *size); + + if (!buf->error) { + if (buf->conv != NULL) { + *size = xmlBufUse(buf->conv); + *mem = xmlStrndup(xmlBufContent(buf->conv), *size); + } else { + *size = xmlBufUse(buf->buffer); + *mem = xmlStrndup(xmlBufContent(buf->buffer), *size); + } } - (void)xmlOutputBufferClose(buf); + + xmlOutputBufferClose(buf); } /** @@ -641,15 +632,15 @@ htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->ExternalID != NULL) { xmlOutputBufferWriteString(buf, " PUBLIC "); - xmlBufWriteQuotedString(buf->buffer, cur->ExternalID); + xmlOutputBufferWriteQuotedString(buf, cur->ExternalID); if (cur->SystemID != NULL) { xmlOutputBufferWriteString(buf, " "); - xmlBufWriteQuotedString(buf->buffer, cur->SystemID); + xmlOutputBufferWriteQuotedString(buf, cur->SystemID); } } else if (cur->SystemID != NULL && xmlStrcmp(cur->SystemID, BAD_CAST "about:legacy-compat")) { xmlOutputBufferWriteString(buf, " SYSTEM "); - xmlBufWriteQuotedString(buf->buffer, cur->SystemID); + xmlOutputBufferWriteQuotedString(buf, cur->SystemID); } xmlOutputBufferWriteString(buf, ">\n"); } @@ -709,17 +700,17 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) { escaped = xmlURIEscapeStr(tmp, BAD_CAST "\"#$%&+,/:;<=>?@[\\]^`{|}"); if (escaped != NULL) { - xmlBufWriteQuotedString(buf->buffer, escaped); + xmlOutputBufferWriteQuotedString(buf, escaped); xmlFree(escaped); } else { - xmlBufWriteQuotedString(buf->buffer, value); + buf->error = XML_ERR_NO_MEMORY; } } else { - xmlBufWriteQuotedString(buf->buffer, value); + xmlOutputBufferWriteQuotedString(buf, value); } xmlFree(value); } else { - xmlOutputBufferWriteString(buf, "=\"\""); + buf->error = XML_ERR_NO_MEMORY; } } } @@ -860,10 +851,12 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlChar *buffer; buffer = xmlEncodeEntitiesReentrant(doc, cur->content); - if (buffer != NULL) { - xmlOutputBufferWriteString(buf, (const char *)buffer); - xmlFree(buffer); + if (buffer == NULL) { + buf->error = XML_ERR_NO_MEMORY; + return; } + xmlOutputBufferWriteString(buf, (const char *)buffer); + xmlFree(buffer); } else { xmlOutputBufferWriteString(buf, (const char *)cur->content); } @@ -1039,28 +1032,12 @@ htmlDocDump(FILE *f, xmlDocPtr cur) { } encoding = (const char *) htmlGetMetaEncoding(cur); - - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); - } - } else { - /* - * Fallback to HTML or ASCII when the encoding is unspecified - */ - if (handler == NULL) - handler = xmlFindCharEncodingHandler("HTML"); - if (handler == NULL) - handler = xmlFindCharEncodingHandler("ascii"); - } - + handler = htmlFindOutputEncoder(encoding); buf = xmlOutputBufferCreateFile(f, handler); - if (buf == NULL) return(-1); + if (buf == NULL) { + xmlCharEncCloseFunc(handler); + return(-1); + } htmlDocContentDumpOutput(buf, cur, NULL); ret = xmlOutputBufferClose(buf); @@ -1089,31 +1066,12 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) { xmlInitParser(); encoding = (const char *) htmlGetMetaEncoding(cur); - - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); - } - } else { - /* - * Fallback to HTML or ASCII when the encoding is unspecified - */ - if (handler == NULL) - handler = xmlFindCharEncodingHandler("HTML"); - if (handler == NULL) - handler = xmlFindCharEncodingHandler("ascii"); - } - - /* - * save the content to a temp buffer. - */ + handler = htmlFindOutputEncoder(encoding); buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); - if (buf == NULL) return(0); + if (buf == NULL) { + xmlCharEncCloseFunc(handler); + return(0); + } htmlDocContentDumpOutput(buf, cur, NULL); @@ -1144,33 +1102,20 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur, xmlInitParser(); - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); - } - htmlSetMetaEncoding(cur, (const xmlChar *) encoding); - } else { + handler = htmlFindOutputEncoder(encoding); + if (handler != NULL) + htmlSetMetaEncoding(cur, (const xmlChar *) handler->name); + else htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8"); - /* - * Fallback to HTML or ASCII when the encoding is unspecified - */ - if (handler == NULL) - handler = xmlFindCharEncodingHandler("HTML"); - if (handler == NULL) - handler = xmlFindCharEncodingHandler("ascii"); - } - /* * save the content to a temp buffer. */ buf = xmlOutputBufferCreateFilename(filename, handler, 0); - if (buf == NULL) return(0); + if (buf == NULL) { + xmlCharEncCloseFunc(handler); + return(0); + } htmlDocContentDumpFormatOutput(buf, cur, encoding, format); diff --git a/NEWS b/NEWS index 2fef3ad..a76ffbb 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,231 @@ NEWS file for libxml2 +v2.13.0: Jun 12 2024 + +### Major changes + +Most of the core code should now report malloc failures reliably. Some +API functions were extended with versions that report malloc failures. + +New API functions for error handling were added: + +- xmlCtxtSetErrorHandler +- xmlXPathSetErrorHandler +- xmlXIncludeSetErrorHandler + +This makes it possible to register per-context error handlers without +resorting to global handlers. + +A few error messages were improved and consolidated. Please update +downstream test suites accordingly. + +A new parser option XML_PARSE_NO_XXE can be used to disable loading +of external entities or DTDs. This is most useful in connection with +XML_PARSE_NOENT. + +Support for HTTP POST was removed. + +Support for zlib, liblzma and HTTP is now disabled by default and has +to be enabled by passing --with-zlib, --with-lzma or --with-html to +configure. In legacy mode (--with-legacy) these options are enabled +by default as before. + +Support for FTP and xpointer() XPath extensions will be removed in +the next release. + +Several more legacy symbols were deprecated. Users of the old "SAX1" +API functions are encouraged to upgrade to the new "SAX2" API, +available since version 2.6.0 from 2003. + +Some deprecated global variables were made const: + +- htmlDefaultSAXHandler +- oldXMLWDcompatibility +- xmlDefaultSAXHandler +- xmlDefaultSAXLocator +- xmlParserDebugEntities + +### Deprecations and removals + +- threads: Deprecate remaining ThrDef functions +- unicode: Deprecate most xmlUCSIs* functions +- memory: Remove memory debugging +- tree: Deprecate xmlRegisterNodeDefault +- tree: Deprecate xmlSetCompressMode +- html: Deprecate htmlHandleOmittedElem +- valid: Deprecate internal validation functions +- valid: Deprecate old DTD serialization API +- nanohttp: Deprecate public API +- Remove VMS support +- Remove Trio + +### Bug fixes + +- parser: Fix base URI of internal parameter entities +- tree: Handle predefined entities in xmlBufGetEntityRefContent +- schemas: Allow unlimited length decimals, integers etc. (Tomáš Ženčák) +- reader: Fix preservation of attributes +- parser: Always decode entities in namespace URIs +- relaxng: Fix tree corruption in xmlRelaxNGParseNameClass (Seiya Nakata) +- schemas: Fix ADD_ANNOTATION +- tree: Fix tree iteration in xmlDOMWrapRemoveNode +- tree: Declare namespace on clone in xmlDOMWrapCloneNode +- tree: Fix xmlAddSibling with last sibling +- tree: Fix xmlDocSetRootElement with multiple top-level elements +- catalog: Fetch XML catalog before dumping +- html: Don't close fd in htmlCtxtReadFd + +### Improvements + +- parser: Fix "Truncated multi-byte sequence" error +- Add missing _cplusplus processing clause (Sadaf Ebrahimi) +- parser: Rework handling of undeclared entities +- SAX2: Warn if URI resolution failed +- parser: Don't report error on invalid URI +- xmllint: Clean up option handling +- xmllint: Rework parsing +- parser: Don't create undeclared entity refs in substitution mode +- Make some globals const +- reader: Make xmlTextReaderReadString non-recursive +- reader: Rework xmlTextReaderRead{Inner,Outer}Xml +- Remove redundant size check (Niels Dossche) +- Remove redundant NULL check on cur (Niels Dossche) +- Remove always-false check old == cur (Niels Dossche) +- Remove redundant NULL check on cur (Niels Dossche) +- tree: Don't return empty localname in xmlSplitQName{2,3} +- xinclude: Don't try to fix base of non-elements +- tree: Don't coalesce text nodes in xmlAdd{Prev,Next}Sibling +- SAX2: Optimize appending children +- tree: Align xmlAddChild with other node insertion functions +- html: Use binary search in htmlEntityValueLookup +- io: Allocate output buffer with XML_BUFFER_ALLOC_IO +- encoding: Don't shrink input too early in xmlCharEncOutput +- tree: Tighten source doc check in xmlDOMWrapAdoptNode +- tree: Check destParent->doc in xmlDOMWrapCloneNode +- tree: Refactor text node updates +- tree: Refactor node insertion +- tree: Refactor element creation and parsing of attribute values +- tree: Simplify xmlNodeGetContent, xmlBufGetNodeContent +- buf: Don't use default buffer size for small strings +- string: Fix xmlStrncatNew(NULL, "") +- entities: Don't allow null name in xmlNewEntity +- html: Fix quadratic behavior in htmlNodeDump +- tree: Rewrite xmlSetTreeDoc +- valid: Rework xmlAddID +- tree: Remove unused node types +- tree: Make namespace comparison more consistent +- tree: Don't allow NULL name in xmlSetNsProp +- tree: Rework xmlNodeListGetString +- tree: Rework xmlTextMerge +- tree: Rework xmlNodeSetName +- tree: Simplify xmlAddChild with text parent +- tree: Disallow setting content of entity reference nodes +- tree: Rework xmlReconciliateNs +- schemas: fix spurious warning about truncated snprintf output + (Benjamin Gilbert) +- xmlschemastypes: Remove unreachable if statement (Maks Mishin) +- relaxng: Remove useless if statement (Maks Mishin) +- tree: Check for integer overflow in xmlStringGetNodeList +- http: Improve error message for HTTPS redirects +- catalog: Remove Windows hack +- save: Move DTD serialization code to xmlsave.c +- parser: Report fatal error if document entity couldn't be loaded +- xpath: Fix return of empty node-set in xmlXPathNodeCollectAndTest +- SAX2: Limit entity URI length to 2000 bytes +- parser: Account for full size of non-well-formed entities +- parser: Pop inputs if parsing DTD failed +- parser: Fix quadratic behavior when copying entities +- writer: Implement xmlTextWriterClose +- parser: Avoid duplicate namespace errors +- parser: Add XML_PARSE_NO_XXE parser option +- parser: Make xmlParseContent more useful +- error: Make xmlFormatError public +- encoding: Check whether encoding handlers support input/output +- SAX2: Enforce size limit in xmlSAX2Text with XML_PARSE_HUGE +- parser: Lower maximum entity nesting depth +- parser: Set depth limit to 2048 with XML_PARSE_HUGE +- parser: Implement xmlCtxtSetOptions +- parser: Always prefer option members over bitmask +- parser: Don't modify SAX2 handler if XML_PARSE_SAX1 is set +- parser: Rework parsing of attribute and entity values +- save: Output U+FFFD replacement characters +- parser: Simplify entity size accounting +- parser: Avoid unwanted expansion of parameter entities +- parser: Always copy content from entity to target +- parser: Simplify control flow in xmlParseReference +- parser: Remove xmlSetEntityReferenceFunc feature +- parser: Push general entity input streams on the stack +- parser: Move progressive flag into input struct +- parser: Fix in-parameter-entity and in-external-dtd checks +- xpath: Rewrite substring-before and substring-after +- xinclude: Only set xml:base if necessary +- xinclude: Allow empty nodesets +- parser: Rework general entity parsing +- io: Fix close error handling +- io: Fix read/write error handling +- io: More refactoring and unescaping fixes +- io: Move some code from xmlIO.c to parserInternals.c +- uri: Clean up special parsing modes +- xinclude: Rework xml:base fixup +- parser: Also set document properties when push parsing +- include: Move non-generated parts from xmlversion.h.in +- io: Remove support for HTTP POST +- dict: Move local RNG state to global state +- dict: Get random seed from system PRNG +- io: Don't use "-" to read from stdin +- io: Rework initialization +- io: Consolidate error messages +- xzlib: Fix harmless unsigned integer overflow +- io: Always use unbuffered input +- io: Fix detection of compressed streams +- io: Pass error codes from xmlFileOpenReal to xmlNewInputFromFile +- io: Rework default callbacks +- error: Stop printing some errors by default +- xpath: Don't free nodes of XSLT result value trees +- valid: Fix handling of enumerations +- parser: Allow recovery in xmlParseInNodeContext +- encoding: Support ASCII in xmlLookupCharEncodingHandler +- include: Remove useless 'const' from function arguments +- Avoid EDG -Wignored-qualifiers warnings on wrong 'const *' to '* const' + conversions (makise-homura) +- Avoid EDG deprecation warnings for LCC compiler (makise-homura) +- Avoid EDG -Woverflow warnings on truncating conversions by manually + truncating operand (makise-homura) +- Avoid EDG -Wtype-limits warnings on unsigned comparisons with zero by + conversion from unsigned int to int (makise-homura) +- Avoid using no_sanitize attribute on EDG even if compiler shows as GCC + (makise-homura) + +### Build systems + +- meson: convert boolean options to feature option (Rosen Penev) +- meson: Pass LIBXML_STATIC in dependency (Andrew Potter) +- meson: fix compilation with local binaries (Rosen Penev) +- meson: don't use dl dependency on old meson (Rosen Penev) +- meson: fix usage as a subproject (Rosen Penev) +- autotools: Fix pthread detection on FreeBSD +- build: Remove --with-fexceptions configuration option +- autotools: Remove --with-coverage configuration option +- build: Disable HTTP support by default +- Stop defining _REENTRANT +- doc: Don't install example code +- meson: Initial commit (Vincent Torri) +- build: Disable support for compression libraries by default +- Set LIBXML2_FOUND if it has been properly configured (Michele Bianchi) +- Makefile.am: omit $(top_builddir) from DEPS and LDADDS (Mike Dalessio) + +### Test suite + +- runtest: Work around broken EUC-JP support in musl iconv +- runtest: Check for IBM-1141 encoding handler +- fuzz: Add xmllint fuzzer +- fuzz: Add fuzzer for XML reader API +- fuzz: New tree API fuzzer +- tests: Remove testOOM +- Don't let gentest.py cast types to 'const somethingPtr' to avoid + -Wignored-qualifiers (makise-homura) + + v2.12.8: Jun 12 2024 ### Regressions diff --git a/README.libxml2.md b/README.libxml2.md index e9a5c78..58c9433 100644 --- a/README.libxml2.md +++ b/README.libxml2.md @@ -21,8 +21,8 @@ This code is released under the MIT License, see the Copyright file. ## Build instructions -libxml2 can be built with GNU Autotools, CMake, or several other build -systems in platform-specific subdirectories. +libxml2 can be built with GNU Autotools, CMake, meson or several other +build systems in platform-specific subdirectories. ### Autotools (for POSIX systems like Linux, BSD, macOS) @@ -49,12 +49,11 @@ The following options disable or enable code modules and relevant symbols: --with-history history support for shell (off) --with-readline[=DIR] use readline in DIR (for shell history) --with-html HTML parser (on) - --with-http HTTP support (on) + --with-http HTTP support (off) --with-iconv[=DIR] iconv support (on) --with-icu ICU support (off) --with-iso8859x ISO-8859-X support if no iconv (on) - --with-lzma[=DIR] use liblzma in DIR (on) - --with-mem-debug memory debugging module (off) + --with-lzma[=DIR] use liblzma in DIR (off) --with-modules dynamic modules support (on) --with-output serialization support (on) --with-pattern xmlPattern selection interface (on) @@ -62,7 +61,6 @@ The following options disable or enable code modules and relevant symbols: --with-python Python bindings (on) --with-reader xmlReader parsing interface (on) --with-regexps regular expressions support (on) - --with-run-debug runtime debugging module (off) --with-sax1 older SAX1 interface (on) --with-schemas XML Schemas 1.0 and RELAX NG support (on) --with-schematron Schematron support (on) @@ -74,7 +72,7 @@ The following options disable or enable code modules and relevant symbols: --with-xinclude XInclude 1.0 support (on) --with-xpath XPath 1.0 support (on) --with-xptr XPointer support (on) - --with-zlib[=DIR] use libz in DIR (on) + --with-zlib[=DIR] use libz in DIR (off) Other options: @@ -90,7 +88,7 @@ Now you can run the test suite with: make check -Please report test failures to the mailing list or bug tracker. +Please report test failures to the bug tracker. Then you can install the library: @@ -121,33 +119,46 @@ Common CMake options include: You can also open the libxml source directory with its CMakeLists.txt directly in various IDEs such as CLion, QtCreator, or Visual Studio. +### Meson + +Libxml can also be built with meson. Without option, simply call + +meson setup builddir +ninja -C builddir + +To add options, see the meson_options.txt file. For example: + +meson setup -Dprefix=$prefix -Dftp=true -Dhistory=true -Dicu=true -Dhttp=true builddir + +To install libxml: + +ninja -C builddir install + +To launch tests: + +meson test -C builddir + ## Dependencies Libxml does not require any other libraries. A platform with somewhat recent POSIX support should be sufficient (please report any violation to this rule you may find). -However, if found at configuration time, libxml will detect and use -the following libraries: +The iconv function is required for conversion of character encodings. +This function is part of POSIX.1-2001. If your platform doesn't provide +iconv, you need an external libiconv library, for example +[GNU libiconv](https://www.gnu.org/software/libiconv/). Alternatively, +you can use [ICU](https://icu.unicode.org/). -- [libz](https://zlib.net/), a highly portable and widely available - compression library. -- [liblzma](https://tukaani.org/xz/), another compression library. -- [libiconv](https://www.gnu.org/software/libiconv/), a character encoding - conversion library. The iconv function is part of POSIX.1-2001, so - libiconv isn't required on modern UNIX-like systems like Linux, BSD or - macOS. -- [ICU](https://icu.unicode.org/), a Unicode library. Mainly useful as an - alternative to iconv on Windows. Unnecessary on most other systems. +If enabled, libxml uses [libz](https://zlib.net/) or +[liblzma](https://tukaani.org/xz/) to support reading compressed files. +Use of this feature is discouraged. ## Contributing The current version of the code can be found in GNOME's GitLab at at . The best way to get involved -is by creating issues and merge requests on GitLab. Alternatively, you can -start discussions and send patches to the mailing list. If you want to -work with patches, please format them with git-format-patch and use plain -text attachments. +is by creating issues and merge requests on GitLab. All code must conform to C89 and pass the GitLab CI tests. Add regression tests if possible. diff --git a/README.md b/README.md index c277415..bf7dcdd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ libxml2 Windows build with Visual Studio. -This version is libxml2-2.12.8. +This version is libxml2-2.13.0. Note that LZMA support is only available for VS2013 or later. diff --git a/SAX2.c b/SAX2.c index bb72e16..267a5fb 100644 --- a/SAX2.c +++ b/SAX2.c @@ -31,52 +31,16 @@ #include "private/parser.h" #include "private/tree.h" -/** - * TODO: - * - * macro to flag unimplemented blocks - * XML_CATALOG_PREFER user env to select between system/public preferred - * option. C.f. Richard Tobin - *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with - *> values "system" and "public". I have made the default be "system" to - *> match yours. - */ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); +#define XML_MAX_URI_LENGTH 2000 /* * xmlSAX2ErrMemory: * @ctxt: an XML validation parser context * @msg: a string to accompany the error message */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) { - xmlStructuredErrorFunc schannel = NULL; - const char *str1 = "out of memory\n"; - - if (ctxt != NULL) { - ctxt->errNo = XML_ERR_NO_MEMORY; - if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - __xmlRaiseError(schannel, - ctxt->vctxt.error, ctxt->vctxt.userData, - ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - NULL, NULL, 0, 0, - msg, (const char *) str1, NULL); - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - } else { - __xmlRaiseError(schannel, - NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - NULL, NULL, 0, 0, - msg, (const char *) str1, NULL); - } +static void +xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt) { + xmlCtxtErrMemory(ctxt); } /** @@ -91,32 +55,12 @@ xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) { */ static void LIBXML_ATTR_FORMAT(3,0) xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error, - const char *msg, const char *str1, const char *str2) + const char *msg, const xmlChar *str1, const xmlChar *str2) { - xmlStructuredErrorFunc schannel = NULL; - - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = error; - if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - __xmlRaiseError(schannel, - ctxt->vctxt.error, ctxt->vctxt.userData, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); + xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR, + str1, str2, NULL, 0, msg, str1, str2); + if (ctxt != NULL) ctxt->valid = 0; - } else { - __xmlRaiseError(schannel, - NULL, NULL, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } } /** @@ -133,21 +77,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, - (const char *) str1, (const char *) str2, - NULL, 0, 0, msg, str1, str2); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - ctxt->valid = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -164,15 +95,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, NULL, - NULL, 0, 0, msg, str1); + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING, + str1, NULL, NULL, 0, msg, str1); } /** @@ -188,15 +112,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, (const char *) str2, - NULL, 0, 0, msg, str1, str2); + xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -341,7 +258,7 @@ xmlSAX2InternalSubset(void *ctx, const xmlChar *name, ctxt->myDoc->intSubset = xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID); if (ctxt->myDoc->intSubset == NULL) - xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset"); + xmlSAX2ErrMemory(ctxt); } /** @@ -359,8 +276,9 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; if (ctx == NULL) return; - if (((ExternalID != NULL) || (SystemID != NULL)) && - (((ctxt->validate) || (ctxt->loadsubset != 0)) && + if ((SystemID != NULL) && + ((ctxt->options & XML_PARSE_NO_XXE) == 0) && + (((ctxt->validate) || (ctxt->loadsubset)) && (ctxt->wellFormed && ctxt->myDoc))) { /* * Try to fetch and parse the external subset. @@ -371,7 +289,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, xmlParserInputPtr *oldinputTab; xmlParserInputPtr input = NULL; const xmlChar *oldencoding; - int oldprogressive; unsigned long consumed; size_t buffered; @@ -385,7 +302,11 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, return; } - xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID); + if (xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID) == NULL) { + xmlSAX2ErrMemory(ctxt); + xmlFreeInputStream(input); + return; + } /* * make sure we won't destroy the main document context @@ -395,21 +316,18 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, oldinputMax = ctxt->inputMax; oldinputTab = ctxt->inputTab; oldencoding = ctxt->encoding; - oldprogressive = ctxt->progressive; ctxt->encoding = NULL; - ctxt->progressive = 0; ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr)); if (ctxt->inputTab == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset"); + xmlSAX2ErrMemory(ctxt); xmlFreeInputStream(input); ctxt->input = oldinput; ctxt->inputNr = oldinputNr; ctxt->inputMax = oldinputMax; ctxt->inputTab = oldinputTab; ctxt->encoding = oldencoding; - ctxt->progressive = oldprogressive; return; } ctxt->inputNr = 0; @@ -463,7 +381,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, (!xmlDictOwns(ctxt->dict, ctxt->encoding)))) xmlFree((xmlChar *) ctxt->encoding); ctxt->encoding = oldencoding; - ctxt->progressive = oldprogressive; /* ctxt->wellFormed = oldwellFormed; */ } } @@ -486,22 +403,37 @@ xmlParserInputPtr xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlParserInputPtr ret; + xmlParserInputPtr ret = NULL; xmlChar *URI; - const char *base = NULL; + const xmlChar *base = NULL; + int res; if (ctx == NULL) return(NULL); if (ctxt->input != NULL) - base = ctxt->input->filename; - if (base == NULL) - base = ctxt->directory; + base = BAD_CAST ctxt->input->filename; - URI = xmlBuildURI(systemId, (const xmlChar *) base); + if ((xmlStrlen(systemId) > XML_MAX_URI_LENGTH) || + (xmlStrlen(base) > XML_MAX_URI_LENGTH)) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long"); + return(NULL); + } + res = xmlBuildURISafe(systemId, base, &URI); + if (URI == NULL) { + if (res < 0) + xmlSAX2ErrMemory(ctxt); + else + xmlWarnMsg(ctxt, XML_ERR_INVALID_URI, + "Can't resolve URI: %s\n", systemId); + return(NULL); + } + if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long"); + } else { + ret = xmlLoadExternalEntity((const char *) URI, + (const char *) publicId, ctxt); + } - ret = xmlLoadExternalEntity((const char *) URI, - (const char *) publicId, ctxt); - if (URI != NULL) - xmlFree(URI); + xmlFree(URI); return(ret); } @@ -590,50 +522,73 @@ xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type, { xmlEntityPtr ent; xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + int extSubset; + int res; - if (ctx == NULL) return; - if (ctxt->inSubset == 1) { - ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId, - systemId, content); - if ((ent == NULL) && (ctxt->pedantic)) - xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED, - "Entity(%s) already defined in the internal subset\n", - name); - if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { - xmlChar *URI; - const char *base = NULL; - - if (ctxt->input != NULL) - base = ctxt->input->filename; - if (base == NULL) - base = ctxt->directory; - - URI = xmlBuildURI(systemId, (const xmlChar *) base); - ent->URI = URI; - } - } else if (ctxt->inSubset == 2) { - ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId, - systemId, content); - if ((ent == NULL) && (ctxt->pedantic) && - (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) - ctxt->sax->warning(ctxt->userData, - "Entity(%s) already defined in the external subset\n", name); - if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { - xmlChar *URI; - const char *base = NULL; - - if (ctxt->input != NULL) - base = ctxt->input->filename; - if (base == NULL) - base = ctxt->directory; - - URI = xmlBuildURI(systemId, (const xmlChar *) base); - ent->URI = URI; - } - } else { - xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING, - "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", - name, NULL); + if ((ctxt == NULL) || (ctxt->myDoc == NULL)) + return; + + extSubset = ctxt->inSubset == 2; + res = xmlAddEntity(ctxt->myDoc, extSubset, name, type, publicId, systemId, + content, &ent); + switch (res) { + case XML_ERR_OK: + break; + case XML_ERR_NO_MEMORY: + xmlSAX2ErrMemory(ctxt); + return; + case XML_WAR_ENTITY_REDEFINED: + if (ctxt->pedantic) { + if (extSubset) + xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the" + " external subset\n", name); + else + xmlWarnMsg(ctxt, res, "Entity(%s) already defined in the" + " internal subset\n", name); + } + return; + case XML_ERR_REDECL_PREDEF_ENTITY: + /* + * Technically an error but it's a common mistake to get double + * escaping according to "4.6 Predefined Entities" wrong. + */ + xmlWarnMsg(ctxt, res, "Invalid redeclaration of predefined" + " entity '%s'", name); + return; + default: + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, + "Unexpected error code from xmlAddEntity\n", + NULL, NULL); + return; + } + + if ((ent->URI == NULL) && (systemId != NULL)) { + xmlChar *URI; + const char *base = NULL; + int i; + + for (i = ctxt->inputNr - 1; i >= 0; i--) { + if (ctxt->inputTab[i]->filename != NULL) { + base = ctxt->inputTab[i]->filename; + break; + } + } + + res = xmlBuildURISafe(systemId, (const xmlChar *) base, &URI); + + if (URI == NULL) { + if (res < 0) { + xmlSAX2ErrMemory(ctxt); + } else { + xmlWarnMsg(ctxt, XML_ERR_INVALID_URI, + "Can't resolve URI: %s\n", systemId); + } + } else if (xmlStrlen(URI) > XML_MAX_URI_LENGTH) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, "URI too long"); + xmlFree(URI); + } else { + ent->URI = URI; + } } } @@ -676,6 +631,8 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, } /* TODO: optimize name/prefix allocation */ name = xmlSplitQName(ctxt, fullname, &prefix); + if (name == NULL) + xmlSAX2ErrMemory(ctxt); ctxt->vctxt.valid = 1; if (ctxt->inSubset == 1) attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem, @@ -690,6 +647,7 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name, NULL); xmlFree(name); + xmlFree(prefix); xmlFreeEnumeration(tree); return; } @@ -814,54 +772,8 @@ xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName) { - xmlEntityPtr ent; - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - if (ctx == NULL) return; - if (ctxt->inSubset == 1) { - ent = xmlAddDocEntity(ctxt->myDoc, name, - XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, - publicId, systemId, notationName); - if ((ent == NULL) && (ctxt->pedantic) && - (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) - ctxt->sax->warning(ctxt->userData, - "Entity(%s) already defined in the internal subset\n", name); - if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { - xmlChar *URI; - const char *base = NULL; - - if (ctxt->input != NULL) - base = ctxt->input->filename; - if (base == NULL) - base = ctxt->directory; - - URI = xmlBuildURI(systemId, (const xmlChar *) base); - ent->URI = URI; - } - } else if (ctxt->inSubset == 2) { - ent = xmlAddDtdEntity(ctxt->myDoc, name, - XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, - publicId, systemId, notationName); - if ((ent == NULL) && (ctxt->pedantic) && - (ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) - ctxt->sax->warning(ctxt->userData, - "Entity(%s) already defined in the external subset\n", name); - if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) { - xmlChar *URI; - const char *base = NULL; - - if (ctxt->input != NULL) - base = ctxt->input->filename; - if (base == NULL) - base = ctxt->directory; - - URI = xmlBuildURI(systemId, (const xmlChar *) base); - ent->URI = URI; - } - } else { - xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, - "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", - name, NULL); - } + xmlSAX2EntityDecl(ctx, name, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, + publicId, systemId, (xmlChar *) notationName); } /** @@ -891,25 +803,19 @@ xmlSAX2StartDocument(void *ctx) if (ctx == NULL) return; - if (ctxt->html) { #ifdef LIBXML_HTML_ENABLED + if (ctxt->html) { if (ctxt->myDoc == NULL) ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); if (ctxt->myDoc == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); + xmlSAX2ErrMemory(ctxt); return; } ctxt->myDoc->properties = XML_DOC_HTML; ctxt->myDoc->parseFlags = ctxt->options; -#else - xmlGenericError(xmlGenericErrorContext, - "libxml2 built without HTML support\n"); - ctxt->errNo = XML_ERR_INTERNAL_ERROR; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - return; + } else #endif - } else { + { doc = ctxt->myDoc = xmlNewDoc(ctxt->version); if (doc != NULL) { doc->properties = 0; @@ -918,7 +824,7 @@ xmlSAX2StartDocument(void *ctx) doc->parseFlags = ctxt->options; doc->standalone = ctxt->standalone; } else { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); + xmlSAX2ErrMemory(ctxt); return; } if ((ctxt->dictNames) && (doc != NULL)) { @@ -930,7 +836,7 @@ xmlSAX2StartDocument(void *ctx) (ctxt->input != NULL) && (ctxt->input->filename != NULL)) { ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename); if (ctxt->myDoc->URL == NULL) - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); + xmlSAX2ErrMemory(ctxt); } } @@ -960,11 +866,47 @@ xmlSAX2EndDocument(void *ctx) if (encoding != NULL) { doc->encoding = xmlStrdup(encoding); if (doc->encoding == NULL) - xmlSAX2ErrMemory(ctxt, "xmlSAX2EndDocument"); + xmlSAX2ErrMemory(ctxt); } } } +static void +xmlSAX2AppendChild(xmlParserCtxtPtr ctxt, xmlNodePtr node) { + xmlNodePtr parent; + xmlNodePtr last; + + if (ctxt->inSubset == 1) { + parent = (xmlNodePtr) ctxt->myDoc->intSubset; + } else if (ctxt->inSubset == 2) { + parent = (xmlNodePtr) ctxt->myDoc->extSubset; + } else { + parent = ctxt->node; + if (parent == NULL) + parent = (xmlNodePtr) ctxt->myDoc; + } + + last = parent->last; + if (last == NULL) { + parent->children = node; + } else { + last->next = node; + node->prev = last; + } + + parent->last = node; + node->parent = parent; + + if ((node->type != XML_TEXT_NODE) && + (ctxt->linenumbers) && + (ctxt->input != NULL)) { + if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) + node->line = ctxt->input->line; + else + node->line = USHRT_MAX; + } +} + #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED) /** * xmlNsErrMsg: @@ -980,15 +922,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, - NULL, 0, 0, msg, str1, str2); + xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -1041,7 +976,7 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, } } if (name == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlSAX2ErrMemory(ctxt); if (ns != NULL) xmlFree(ns); return; @@ -1051,6 +986,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, if ((ctxt->html) && (value == NULL) && (htmlIsBooleanAttr(fullname))) { nval = xmlStrdup(fullname); + if (nval == NULL) + xmlSAX2ErrMemory(ctxt); value = (const xmlChar *) nval; } else #endif @@ -1088,12 +1025,10 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, (void) nsret; if (!ctxt->replaceEntities) { - ctxt->depth++; - val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, - 0,0,0); - ctxt->depth--; + /* TODO: normalize if needed */ + val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0); if (val == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlSAX2ErrMemory(ctxt); if (name != NULL) xmlFree(name); if (nval != NULL) @@ -1107,16 +1042,16 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, if (val[0] != 0) { xmlURIPtr uri; - uri = xmlParseURI((const char *)val); + if (xmlParseURISafe((const char *)val, &uri) < 0) + xmlSAX2ErrMemory(ctxt); if (uri == NULL) { - if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) - ctxt->sax->warning(ctxt->userData, - "xmlns: %s not a valid URI\n", val); + xmlNsWarnMsg(ctxt, XML_WAR_NS_URI, + "xmlns:%s: %s not a valid URI\n", name, value); } else { if (uri->scheme == NULL) { - if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) - ctxt->sax->warning(ctxt->userData, - "xmlns: URI %s is not absolute\n", val); + xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE, + "xmlns:%s: URI %s is not absolute\n", + name, value); } xmlFreeURI(uri); } @@ -1124,16 +1059,19 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, /* a default namespace definition */ nsret = xmlNewNs(ctxt->node, val, NULL); - + if (nsret == NULL) { + xmlSAX2ErrMemory(ctxt); + } #ifdef LIBXML_VALID_ENABLED /* * Validate also for namespace decls, they are attributes from * an XML-1.0 perspective */ - if (nsret != NULL && ctxt->validate && ctxt->wellFormed && - ctxt->myDoc && ctxt->myDoc->intSubset) + else if (ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) { ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, ctxt->node, prefix, nsret, val); + } #endif /* LIBXML_VALID_ENABLED */ if (name != NULL) xmlFree(name); @@ -1153,12 +1091,10 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, (void) nsret; if (!ctxt->replaceEntities) { - ctxt->depth++; - val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, - 0,0,0); - ctxt->depth--; + /* TODO: normalize if needed */ + val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0); if (val == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlSAX2ErrMemory(ctxt); xmlFree(ns); if (name != NULL) xmlFree(name); @@ -1177,7 +1113,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, if ((ctxt->pedantic != 0) && (val[0] != 0)) { xmlURIPtr uri; - uri = xmlParseURI((const char *)val); + if (xmlParseURISafe((const char *)val, &uri) < 0) + xmlSAX2ErrMemory(ctxt); if (uri == NULL) { xmlNsWarnMsg(ctxt, XML_WAR_NS_URI, "xmlns:%s: %s not a valid URI\n", name, value); @@ -1193,15 +1130,20 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, /* a standard namespace definition */ nsret = xmlNewNs(ctxt->node, val, name); xmlFree(ns); + + if (nsret == NULL) { + xmlSAX2ErrMemory(ctxt); + } #ifdef LIBXML_VALID_ENABLED /* * Validate also for namespace decls, they are attributes from * an XML-1.0 perspective */ - if (nsret != NULL && ctxt->validate && ctxt->wellFormed && - ctxt->myDoc && ctxt->myDoc->intSubset) + else if (ctxt->validate && ctxt->wellFormed && + ctxt->myDoc && ctxt->myDoc->intSubset) { ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, ctxt->node, prefix, nsret, value); + } #endif /* LIBXML_VALID_ENABLED */ if (name != NULL) xmlFree(name); @@ -1213,7 +1155,11 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, } if (ns != NULL) { - namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns); + int res; + + res = xmlSearchNsSafe(ctxt->node, ns, &namespace); + if (res < 0) + xmlSAX2ErrMemory(ctxt); if (namespace == NULL) { xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, @@ -1228,11 +1174,11 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, if ((xmlStrEqual(name, prop->name)) && ((namespace == prop->ns) || (xmlStrEqual(namespace->href, prop->ns->href)))) { - xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED, - "Attribute %s in %s redefined\n", - name, namespace->href); - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) ctxt->disableSAX = 1; + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, + XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, + name, NULL, NULL, 0, + "Attribute %s in %s redefined\n", + name, namespace->href); if (name != NULL) xmlFree(name); goto error; @@ -1247,25 +1193,22 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, /* !!!!!! */ ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL); - if (ret == NULL) + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt); goto error; + } if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { - xmlNodePtr tmp; - - ret->children = xmlStringGetNodeList(ctxt->myDoc, value); - tmp = ret->children; - while (tmp != NULL) { - tmp->parent = (xmlNodePtr) ret; - if (tmp->next == NULL) - ret->last = tmp; - tmp = tmp->next; - } + if (xmlNodeParseContent((xmlNodePtr) ret, value, INT_MAX) < 0) + xmlSAX2ErrMemory(ctxt); } else if (value != NULL) { ret->children = xmlNewDocText(ctxt->myDoc, value); - ret->last = ret->children; - if (ret->children != NULL) + if (ret->children == NULL) { + xmlSAX2ErrMemory(ctxt); + } else { + ret->last = ret->children; ret->children->parent = (xmlNodePtr) ret; + } } #ifdef LIBXML_VALID_ENABLED @@ -1279,10 +1222,8 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, if (!ctxt->replaceEntities) { xmlChar *val; - ctxt->depth++; - val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, - 0,0,0); - ctxt->depth--; + /* TODO: normalize if needed */ + val = xmlExpandEntitiesInAttValue(ctxt, value, /* normalize */ 0); if (val == NULL) ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, @@ -1295,8 +1236,9 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, * It need to be done twice ... it's an extra burden related * to the ability to keep xmlSAX2References in attributes */ - nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc, - ctxt->node, fullname, val); + nvalnorm = xmlValidCtxtNormalizeAttributeValue( + &ctxt->vctxt, ctxt->myDoc, + ctxt->node, fullname, val); if (nvalnorm != NULL) { xmlFree(val); val = nvalnorm; @@ -1313,8 +1255,6 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, } else #endif /* LIBXML_VALID_ENABLED */ if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && - (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || - ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) && /* Don't create IDs containing entity references */ (ret->children != NULL) && (ret->children->type == XML_TEXT_NODE) && @@ -1332,14 +1272,20 @@ xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, */ if (xmlValidateNCName(content, 1) != 0) { xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, - "xml:id : attribute value %s is not an NCName\n", - (const char *) content, NULL); + "xml:id : attribute value %s is not an NCName\n", + content, NULL); } xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); - } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) - xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); - else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) - xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret); + } else { + int res = xmlIsID(ctxt->myDoc, ctxt->node, ret); + + if (res < 0) + xmlCtxtErrMemory(ctxt); + else if (res > 0) + xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); + else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) + xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret); + } } error: @@ -1391,13 +1337,15 @@ xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, if (attr->prefix != NULL) { fulln = xmlStrdup(attr->prefix); - fulln = xmlStrcat(fulln, BAD_CAST ":"); - fulln = xmlStrcat(fulln, attr->name); + if (fulln != NULL) + fulln = xmlStrcat(fulln, BAD_CAST ":"); + if (fulln != NULL) + fulln = xmlStrcat(fulln, attr->name); } else { fulln = xmlStrdup(attr->name); } if (fulln == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlSAX2ErrMemory(ctxt); break; } @@ -1419,8 +1367,8 @@ xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, if (att == NULL) { xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED, "standalone: attribute %s on %s defaulted from external subset\n", - (const char *)fulln, - (const char *)attr->elem); + fulln, + attr->elem); } xmlFree(fulln); } @@ -1463,7 +1411,7 @@ xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50); if (fulln == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlSAX2ErrMemory(ctxt); return; } @@ -1547,6 +1495,10 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) * Split the full name into a namespace prefix and the tag name */ name = xmlSplitQName(ctxt, fullname, &prefix); + if (name == NULL) { + xmlSAX2ErrMemory(ctxt); + return; + } } /* @@ -1556,26 +1508,22 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) */ ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); if (ret == NULL) { - if (prefix != NULL) - xmlFree(prefix); - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); + xmlFree(prefix); + xmlSAX2ErrMemory(ctxt); return; } ctxt->nodemem = -1; - if (ctxt->linenumbers) { - if (ctxt->input != NULL) { - if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) - ret->line = ctxt->input->line; - else - ret->line = USHRT_MAX; - } - } /* Initialize parent before pushing node */ parent = ctxt->node; if (parent == NULL) parent = (xmlNodePtr) ctxt->myDoc; + /* + * Link the child element + */ + xmlSAX2AppendChild(ctxt, ret); + /* * We are parsing a new node. */ @@ -1587,12 +1535,9 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) return; } - /* - * Link the child element - */ - xmlAddChild(parent, ret); - if (!ctxt->html) { + int res; + /* * Insert all the defaulted attributes from the DTD especially * namespaces @@ -1623,14 +1568,21 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) * Search the namespace, note that since the attributes have been * processed, the local namespaces are available. */ - ns = xmlSearchNs(ctxt->myDoc, ret, prefix); - if ((ns == NULL) && (parent != NULL)) - ns = xmlSearchNs(ctxt->myDoc, parent, prefix); + res = xmlSearchNsSafe(ret, prefix, &ns); + if (res < 0) + xmlSAX2ErrMemory(ctxt); + if ((ns == NULL) && (parent != NULL)) { + res = xmlSearchNsSafe(parent, prefix, &ns); + if (res < 0) + xmlSAX2ErrMemory(ctxt); + } if ((prefix != NULL) && (ns == NULL)) { - ns = xmlNewNs(ret, NULL, prefix); xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, "Namespace prefix %s is not defined\n", prefix, NULL); + ns = xmlNewNs(ret, NULL, prefix); + if (ns == NULL) + xmlSAX2ErrMemory(ctxt); } /* @@ -1751,7 +1703,7 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); } if (ret == NULL) { - xmlErrMemory(ctxt, "xmlSAX2Characters"); + xmlCtxtErrMemory(ctxt); return(NULL); } memset(ret, 0, sizeof(xmlNode)); @@ -1772,6 +1724,11 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { } else if ((len <= 3) && ((cur == '"') || (cur == '\'') || ((cur == '<') && (str[len + 1] != '!')))) { intern = xmlDictLookup(ctxt->dict, str, len); + if (intern == NULL) { + xmlSAX2ErrMemory(ctxt); + xmlFree(ret); + return(NULL); + } } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && (str[len + 1] != '!')) { int i; @@ -1780,6 +1737,11 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { if (!IS_BLANK_CH(str[i])) goto skip; } intern = xmlDictLookup(ctxt->dict, str, len); + if (intern == NULL) { + xmlSAX2ErrMemory(ctxt); + xmlFree(ret); + return(NULL); + } } } skip: @@ -1789,7 +1751,7 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { if (intern == NULL) { ret->content = xmlStrndup(str, len); if (ret->content == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode"); + xmlSAX2ErrMemory(ctxt); xmlFree(ret); return(NULL); } @@ -1816,7 +1778,6 @@ static xmlChar * xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, const xmlChar *end) { const xmlChar *in; - xmlChar *ret; in = str; while (in < end) @@ -1824,11 +1785,12 @@ xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, goto decode; return(NULL); decode: - ctxt->depth++; - ret = xmlStringLenDecodeEntities(ctxt, str, end - str, - XML_SUBSTITUTE_REF, 0,0,0); - ctxt->depth--; - return(ret); + /* + * If the value contains '&', we can be sure it was allocated and is + * zero-terminated. + */ + /* TODO: normalize if needed */ + return(xmlExpandEntitiesInAttValue(ctxt, str, /* normalize */ 0)); } #endif /* LIBXML_VALID_ENABLED */ @@ -1865,7 +1827,11 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, if (prefix != NULL) { namespace = xmlParserNsLookupSax(ctxt, prefix); if ((namespace == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { - namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); + int res; + + res = xmlSearchNsSafe(ctxt->node, prefix, &namespace); + if (res < 0) + xmlSAX2ErrMemory(ctxt); } } @@ -1879,7 +1845,7 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, } else { ret = xmlMalloc(sizeof(*ret)); if (ret == NULL) { - xmlSAX2ErrMemory(ctxt, NULL); + xmlSAX2ErrMemory(ctxt); return(NULL); } } @@ -1900,10 +1866,13 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, ret->doc = ctxt->node->doc; ret->ns = namespace; - if (ctxt->dictNames) + if (ctxt->dictNames) { ret->name = localname; - else + } else { ret->name = xmlStrdup(localname); + if (ret->name == NULL) + xmlSAX2ErrMemory(ctxt); + } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)ret); @@ -1924,17 +1893,10 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, tmp->doc = ret->doc; tmp->parent = (xmlNodePtr) ret; } - } else { - ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, - valueend - value); - tmp = ret->children; - while (tmp != NULL) { - tmp->doc = ret->doc; - tmp->parent = (xmlNodePtr) ret; - if (tmp->next == NULL) - ret->last = tmp; - tmp = tmp->next; - } + } else if (valueend > value) { + if (xmlNodeParseContent((xmlNodePtr) ret, value, + valueend - value) < 0) + xmlSAX2ErrMemory(ctxt); } } else if (value != NULL) { xmlNodePtr tmp; @@ -1968,6 +1930,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, * entry points in the full validation code */ dup = xmlStrndup(value, valueend - value); + if (dup == NULL) + xmlSAX2ErrMemory(ctxt); ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, ctxt->node, ret, dup); @@ -1986,7 +1950,9 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, xmlChar *fullname; fullname = xmlBuildQName(localname, prefix, fn, 50); - if (fullname != NULL) { + if (fullname == NULL) { + xmlSAX2ErrMemory(ctxt); + } else { ctxt->vctxt.valid = 1; nvalnorm = xmlValidCtxtNormalizeAttributeValue( &ctxt->vctxt, ctxt->myDoc, @@ -2012,6 +1978,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, * the attribute as passed is already normalized */ dup = xmlStrndup(value, valueend - value); + if (dup == NULL) + xmlSAX2ErrMemory(ctxt); ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, ctxt->node, ret, dup); @@ -2019,8 +1987,6 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, } else #endif /* LIBXML_VALID_ENABLED */ if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && - (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || - ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) && /* Don't create IDs containing entity references */ (ret->children != NULL) && (ret->children->type == XML_TEXT_NODE) && @@ -2040,14 +2006,19 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, */ if (xmlValidateNCName(content, 1) != 0) { xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, - "xml:id : attribute value %s is not an NCName\n", - (const char *) content, NULL); + "xml:id : attribute value %s is not an NCName\n", + content, NULL); } xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); - } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { - xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); - } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) { - xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret); + } else { + int res = xmlIsID(ctxt->myDoc, ctxt->node, ret); + + if (res < 0) + xmlCtxtErrMemory(ctxt); + else if (res > 0) + xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); + else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) + xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret); } } if (dup != NULL) @@ -2086,7 +2057,6 @@ xmlSAX2StartElementNs(void *ctx, { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlNodePtr ret; - xmlNodePtr parent; xmlNsPtr last = NULL, ns; const xmlChar *uri, *pref; xmlChar *lname = NULL; @@ -2115,10 +2085,17 @@ xmlSAX2StartElementNs(void *ctx, const xmlChar *fullname; fullname = xmlDictQLookup(ctxt->dict, prefix, localname); - if (fullname != NULL) - localname = fullname; + if (fullname == NULL) { + xmlSAX2ErrMemory(ctxt); + return; + } + localname = fullname; } else { lname = xmlBuildQName(localname, prefix, NULL, 0); + if (lname == NULL) { + xmlSAX2ErrMemory(ctxt); + return; + } } } /* @@ -2140,7 +2117,7 @@ xmlSAX2StartElementNs(void *ctx, else ret->name = lname; if (ret->name == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + xmlSAX2ErrMemory(ctxt); xmlFree(ret); return; } @@ -2157,18 +2134,10 @@ xmlSAX2StartElementNs(void *ctx, ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, (xmlChar *) lname, NULL); if (ret == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + xmlSAX2ErrMemory(ctxt); return; } } - if (ctxt->linenumbers) { - if (ctxt->input != NULL) { - if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) - ret->line = ctxt->input->line; - else - ret->line = USHRT_MAX; - } - } /* * Build the namespace list @@ -2187,11 +2156,7 @@ xmlSAX2StartElementNs(void *ctx, if ((URI != NULL) && (prefix == pref)) ret->ns = ns; } else { - /* - * any out of memory error would already have been raised - * but we can't be guaranteed it's the actual error due to the - * API, best is to skip in this case - */ + xmlSAX2ErrMemory(ctxt); continue; } @@ -2207,10 +2172,10 @@ xmlSAX2StartElementNs(void *ctx, } ctxt->nodemem = -1; - /* Initialize parent before pushing node */ - parent = ctxt->node; - if (parent == NULL) - parent = (xmlNodePtr) ctxt->myDoc; + /* + * Link the child element + */ + xmlSAX2AppendChild(ctxt, ret); /* * We are parsing a new node. @@ -2221,11 +2186,6 @@ xmlSAX2StartElementNs(void *ctx, return; } - /* - * Link the child element - */ - xmlAddChild(parent, ret); - /* * Insert the defaulted attributes from the DTD only if requested: */ @@ -2240,13 +2200,17 @@ xmlSAX2StartElementNs(void *ctx, if ((URI != NULL) && (ret->ns == NULL)) { ret->ns = xmlParserNsLookupSax(ctxt, prefix); if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { - ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix); + int res; + + res = xmlSearchNsSafe(ret, prefix, &ret->ns); + if (res < 0) + xmlSAX2ErrMemory(ctxt); } if (ret->ns == NULL) { ns = xmlNewNs(ret, NULL, prefix); if (ns == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs"); + xmlSAX2ErrMemory(ctxt); return; } if (prefix != NULL) @@ -2278,22 +2242,26 @@ xmlSAX2StartElementNs(void *ctx, fullname = xmlDictQLookup(ctxt->dict, attributes[j+1], attributes[j]); - if (fullname != NULL) { - attr = xmlSAX2AttributeNs(ctxt, fullname, NULL, - attributes[j+3], - attributes[j+4]); - goto have_attr; - } + if (fullname == NULL) { + xmlSAX2ErrMemory(ctxt); + return; + } + attr = xmlSAX2AttributeNs(ctxt, fullname, NULL, + attributes[j+3], + attributes[j+4]); + goto have_attr; } else { lname = xmlBuildQName(attributes[j], attributes[j+1], NULL, 0); - if (lname != NULL) { - attr = xmlSAX2AttributeNs(ctxt, lname, NULL, - attributes[j+3], - attributes[j+4]); - xmlFree(lname); - goto have_attr; - } + if (lname == NULL) { + xmlSAX2ErrMemory(ctxt); + return; + } + attr = xmlSAX2AttributeNs(ctxt, lname, NULL, + attributes[j+3], + attributes[j+4]); + xmlFree(lname); + goto have_attr; } } attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], @@ -2383,9 +2351,12 @@ xmlSAX2Reference(void *ctx, const xmlChar *name) if (ctx == NULL) return; ret = xmlNewReference(ctxt->myDoc, name); - if (xmlAddChild(ctxt->node, ret) == NULL) { - xmlFreeNode(ret); + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt); + return; } + + xmlSAX2AppendChild(ctxt, ret); } /** @@ -2432,7 +2403,7 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, ctxt->nodelen = len; ctxt->nodemem = len + 1; } else { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + xmlSAX2ErrMemory(ctxt); return; } } else { @@ -2441,6 +2412,10 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, ((type != XML_TEXT_NODE) || (lastChild->name == xmlStringText)); if ((coalesceText) && (ctxt->nodemem != 0)) { + int maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_TEXT_LENGTH; + /* * The whole point of maintaining nodelen and nodemem, * xmlTextConcat is too costly, i.e. compute length, @@ -2456,16 +2431,13 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, lastChild->content = xmlStrdup(lastChild->content); } if (lastChild->content == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL"); + xmlSAX2ErrMemory(ctxt); return; } - if (ctxt->nodelen > INT_MAX - len) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented"); - return; - } - if ((ctxt->nodelen + len > XML_MAX_TEXT_LENGTH) && - ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node"); + if ((len > maxLength) || (ctxt->nodelen > maxLength - len)) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, + "Text node too long, try XML_PARSE_HUGE"); + xmlHaltParser(ctxt); return; } if (ctxt->nodelen + len >= ctxt->nodemem) { @@ -2478,7 +2450,7 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, size = size > INT_MAX / 2 ? INT_MAX : size * 2; newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); if (newbuf == NULL) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + xmlSAX2ErrMemory(ctxt); return; } ctxt->nodemem = size; @@ -2489,7 +2461,7 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, lastChild->content[ctxt->nodelen] = 0; } else if (coalesceText) { if (xmlTextConcat(lastChild, ch, len)) { - xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters"); + xmlSAX2ErrMemory(ctxt); } if (ctxt->node->children != NULL) { ctxt->nodelen = xmlStrlen(lastChild->content); @@ -2503,8 +2475,10 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, lastChild->doc = ctxt->myDoc; } else lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len); - if (lastChild != NULL) { - xmlAddChild(ctxt->node, lastChild); + if (lastChild == NULL) { + xmlSAX2ErrMemory(ctxt); + } else { + xmlSAX2AppendChild(ctxt, lastChild); if (ctxt->node->children != NULL) { ctxt->nodelen = len; ctxt->nodemem = len + 1; @@ -2569,38 +2543,16 @@ xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target, { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlNodePtr ret; - xmlNodePtr parent; if (ctx == NULL) return; - parent = ctxt->node; ret = xmlNewDocPI(ctxt->myDoc, target, data); - if (ret == NULL) return; - - if (ctxt->linenumbers) { - if (ctxt->input != NULL) { - if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) - ret->line = ctxt->input->line; - else - ret->line = USHRT_MAX; - } - } - if (ctxt->inSubset == 1) { - xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); - return; - } else if (ctxt->inSubset == 2) { - xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); - return; - } - if (parent == NULL) { - xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); - return; - } - if (parent->type == XML_ELEMENT_NODE) { - xmlAddChild(parent, ret); - } else { - xmlAddSibling(parent, ret); + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt); + return; } + + xmlSAX2AppendChild(ctxt, ret); } /** @@ -2615,37 +2567,16 @@ xmlSAX2Comment(void *ctx, const xmlChar *value) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlNodePtr ret; - xmlNodePtr parent; if (ctx == NULL) return; - parent = ctxt->node; + ret = xmlNewDocComment(ctxt->myDoc, value); - if (ret == NULL) return; - if (ctxt->linenumbers) { - if (ctxt->input != NULL) { - if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) - ret->line = ctxt->input->line; - else - ret->line = USHRT_MAX; - } + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt); + return; } - if (ctxt->inSubset == 1) { - xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); - return; - } else if (ctxt->inSubset == 2) { - xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); - return; - } - if (parent == NULL) { - xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); - return; - } - if (parent->type == XML_ELEMENT_NODE) { - xmlAddChild(parent, ret); - } else { - xmlAddSibling(parent, ret); - } + xmlSAX2AppendChild(ctxt, ret); } /** diff --git a/THIS_VERSION_IS_2.12.8 b/THIS_VERSION_IS_2.13.0 similarity index 100% rename from THIS_VERSION_IS_2.12.8 rename to THIS_VERSION_IS_2.13.0 diff --git a/buf.c b/buf.c index 266395f..f9f59b2 100644 --- a/buf.c +++ b/buf.c @@ -89,10 +89,9 @@ struct _xmlBuf { * To be improved... */ static void -xmlBufMemoryError(xmlBufPtr buf, const char *extra) +xmlBufMemoryError(xmlBufPtr buf) { - __xmlSimpleError(XML_FROM_BUFFER, XML_ERR_NO_MEMORY, NULL, NULL, extra); - if ((buf) && (buf->error == 0)) + if (buf->error == 0) buf->error = XML_ERR_NO_MEMORY; } @@ -104,10 +103,9 @@ xmlBufMemoryError(xmlBufPtr buf, const char *extra) * To be improved... */ static void -xmlBufOverflowError(xmlBufPtr buf, const char *extra) +xmlBufOverflowError(xmlBufPtr buf) { - __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra); - if ((buf) && (buf->error == 0)) + if (buf->error == 0) buf->error = XML_BUF_OVERFLOW; } @@ -123,10 +121,8 @@ xmlBufCreate(void) { xmlBufPtr ret; ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf)); - if (ret == NULL) { - xmlBufMemoryError(NULL, "creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->error = 0; ret->buffer = NULL; @@ -135,7 +131,6 @@ xmlBufCreate(void) { ret->alloc = xmlBufferAllocScheme; ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlBufMemoryError(ret, "creating buffer"); xmlFree(ret); return(NULL); } @@ -158,10 +153,8 @@ xmlBufCreateSize(size_t size) { if (size == SIZE_MAX) return(NULL); ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf)); - if (ret == NULL) { - xmlBufMemoryError(NULL, "creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->error = 0; ret->buffer = NULL; @@ -171,7 +164,6 @@ xmlBufCreateSize(size_t size) { if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlBufMemoryError(ret, "creating buffer"); xmlFree(ret); return(NULL); } @@ -203,8 +195,16 @@ xmlBufDetach(xmlBufPtr buf) { if (buf->error) return(NULL); - ret = buf->content; + if ((buf->alloc == XML_BUFFER_ALLOC_IO) && + (buf->content != buf->contentIO)) { + ret = xmlStrndup(buf->content, buf->use); + xmlFree(buf->contentIO); + } else { + ret = buf->content; + } + buf->content = NULL; + buf->contentIO = NULL; buf->size = 0; buf->use = 0; UPDATE_COMPAT(buf); @@ -383,7 +383,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { if (len < buf->size - buf->use) return(buf->size - buf->use - 1); if (len >= SIZE_MAX - buf->use) { - xmlBufMemoryError(buf, "growing buffer past SIZE_MAX"); + xmlBufMemoryError(buf); return(0); } @@ -400,7 +400,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { */ if ((buf->use + len + 1 >= XML_MAX_TEXT_LENGTH) || (buf->size >= XML_MAX_TEXT_LENGTH)) { - xmlBufMemoryError(buf, "buffer error: text too long\n"); + xmlBufMemoryError(buf); return(0); } if (size >= XML_MAX_TEXT_LENGTH) @@ -411,7 +411,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size); if (newbuf == NULL) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return(0); } buf->contentIO = newbuf; @@ -419,7 +419,7 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { } else { newbuf = (xmlChar *) xmlRealloc(buf->content, size); if (newbuf == NULL) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return(0); } buf->content = newbuf; @@ -641,7 +641,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) * Used to provide parsing limits */ if (size >= XML_MAX_TEXT_LENGTH) { - xmlBufMemoryError(buf, "buffer error: text too long\n"); + xmlBufMemoryError(buf); return(0); } } @@ -662,7 +662,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) } while (size > newSize) { if (newSize > SIZE_MAX / 2) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return 0; } newSize *= 2; @@ -678,7 +678,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) newSize = buf->size; while (size > newSize) { if (newSize > SIZE_MAX / 2) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return 0; } newSize *= 2; @@ -703,7 +703,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) } else { rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize); if (rebuf == NULL) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return 0; } buf->contentIO = rebuf; @@ -731,7 +731,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) } } if (rebuf == NULL) { - xmlBufMemoryError(buf, "growing buffer"); + xmlBufMemoryError(buf); return 0; } buf->content = rebuf; @@ -751,8 +751,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) * Add a string range to an XML buffer. if len == -1, the length of * str is recomputed. * - * Returns 0 successful, a positive error code number otherwise - * and -1 in case of internal or API error. + * Returns 0 if successful, -1 in case of error. */ int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { @@ -776,7 +775,7 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { /* Note that both buf->size and buf->use can be zero here. */ if ((size_t) len >= buf->size - buf->use) { if ((size_t) len >= SIZE_MAX - buf->use) { - xmlBufMemoryError(buf, "growing buffer past SIZE_MAX"); + xmlBufMemoryError(buf); return(-1); } needSize = buf->use + len + 1; @@ -785,14 +784,12 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { * Used to provide parsing limits */ if (needSize >= XML_MAX_TEXT_LENGTH) { - xmlBufMemoryError(buf, "buffer error: text too long\n"); + xmlBufMemoryError(buf); return(-1); } } - if (!xmlBufResize(buf, needSize)){ - xmlBufMemoryError(buf, "growing buffer"); - return XML_ERR_NO_MEMORY; - } + if (!xmlBufResize(buf, needSize)) + return(-1); } memmove(&buf->content[buf->use], str, len); @@ -821,72 +818,6 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) { return xmlBufAdd(buf, str, -1); } -/** - * xmlBufCCat: - * @buf: the buffer to dump - * @str: the C char string - * - * Append a zero terminated C string to an XML buffer. - * - * Returns 0 successful, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -int -xmlBufCCat(xmlBufPtr buf, const char *str) { - return xmlBufCat(buf, (const xmlChar *) str); -} - -/** - * xmlBufWriteQuotedString: - * @buf: the XML buffer output - * @string: the string to add - * - * routine which manage and grows an output buffer. This one writes - * a quoted or double quoted #xmlChar string, checking first if it holds - * quote or double-quotes internally - * - * Returns 0 if successful, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -int -xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) { - const xmlChar *cur, *base; - if ((buf == NULL) || (buf->error)) - return(-1); - CHECK_COMPAT(buf) - if (xmlStrchr(string, '\"')) { - if (xmlStrchr(string, '\'')) { - xmlBufCCat(buf, "\""); - base = cur = string; - while(*cur != 0){ - if(*cur == '"'){ - if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST """, 6); - cur++; - base = cur; - } - else { - cur++; - } - } - if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufCCat(buf, "\""); - } - else{ - xmlBufCCat(buf, "\'"); - xmlBufCat(buf, string); - xmlBufCCat(buf, "\'"); - } - } else { - xmlBufCCat(buf, "\""); - xmlBufCat(buf, string); - xmlBufCCat(buf, "\""); - } - return(0); -} - /** * xmlBufFromBuffer: * @buffer: incoming old buffer to convert to a new one @@ -907,7 +838,6 @@ xmlBufFromBuffer(xmlBufferPtr buffer) { ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf)); if (ret == NULL) { - xmlBufMemoryError(NULL, "creating buffer"); return(NULL); } ret->use = buffer->use; @@ -941,12 +871,19 @@ xmlBufBackToBuffer(xmlBufPtr buf) { if (buf == NULL) return(NULL); CHECK_COMPAT(buf) - if ((buf->error) || (buf->buffer == NULL)) { + ret = buf->buffer; + + if ((buf->error) || (ret == NULL)) { xmlBufFree(buf); + if (ret != NULL) { + ret->content = NULL; + ret->contentIO = NULL; + ret->use = 0; + ret->size = 0; + } return(NULL); } - ret = buf->buffer; /* * What to do in case of error in the buffer ??? */ @@ -956,7 +893,7 @@ xmlBufBackToBuffer(xmlBufPtr buf) { * maximum allowed memory for an xmlBuffer on this architecture. * Keep the buffer but provide a truncated size value. */ - xmlBufOverflowError(buf, "Used size too big for xmlBuffer"); + xmlBufOverflowError(buf); ret->use = INT_MAX; ret->size = INT_MAX; } else if (buf->size > INT_MAX) { @@ -966,7 +903,7 @@ xmlBufBackToBuffer(xmlBufPtr buf) { * limit. * Keep the buffer but provide a truncated size value. */ - xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer"); + xmlBufOverflowError(buf); ret->use = buf->use; ret->size = INT_MAX; } else { @@ -980,32 +917,6 @@ xmlBufBackToBuffer(xmlBufPtr buf) { return(ret); } -/** - * xmlBufMergeBuffer: - * @buf: an xmlBufPtr - * @buffer: the buffer to consume into @buf - * - * The content of @buffer is appended to @buf and @buffer is freed - * - * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed - */ -int -xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) { - int ret = 0; - - if ((buf == NULL) || (buf->error)) { - xmlBufferFree(buffer); - return(-1); - } - CHECK_COMPAT(buf) - if ((buffer != NULL) && (buffer->content != NULL) && - (buffer->use > 0)) { - ret = xmlBufAdd(buf, buffer->content, buffer->use); - } - xmlBufferFree(buffer); - return(ret); -} - /** * xmlBufResetInput: * @buf: an xmlBufPtr @@ -1017,16 +928,7 @@ xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) { */ int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) { - if (input == NULL) - return(-1); - if ((buf == NULL) || (buf->error)) { - input->base = input->cur = input->end = BAD_CAST ""; - return(-1); - } - CHECK_COMPAT(buf) - input->base = input->cur = buf->content; - input->end = &buf->content[buf->use]; - return(0); + return(xmlBufUpdateInput(buf, input, 0)); } /** @@ -1042,16 +944,8 @@ xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) { */ int xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) { - if (input == NULL) + if ((buf == NULL) || (input == NULL)) return(-1); - /* - * TODO: It might be safer to keep using the buffer content if there - * was an error. - */ - if ((buf == NULL) || (buf->error)) { - input->base = input->cur = input->end = BAD_CAST ""; - return(-1); - } CHECK_COMPAT(buf) input->base = buf->content; input->cur = input->base + pos; diff --git a/build-VS2008/libxml2-static-for-dll/libxml2-static-for-dll.vcproj b/build-VS2008/libxml2-static-for-dll/libxml2-static-for-dll.vcproj index c2b37a6..07d1eca 100644 --- a/build-VS2008/libxml2-static-for-dll/libxml2-static-for-dll.vcproj +++ b/build-VS2008/libxml2-static-for-dll/libxml2-static-for-dll.vcproj @@ -473,18 +473,6 @@ RelativePath="..\..\timsort.h" > - - - - - - diff --git a/build-VS2008/libxml2-static/libxml2-static.vcproj b/build-VS2008/libxml2-static/libxml2-static.vcproj index 5b90a50..aea15e4 100644 --- a/build-VS2008/libxml2-static/libxml2-static.vcproj +++ b/build-VS2008/libxml2-static/libxml2-static.vcproj @@ -473,18 +473,6 @@ RelativePath="..\..\timsort.h" > - - - - - - diff --git a/build-VS2008/libxml2/libxml2.vcproj b/build-VS2008/libxml2/libxml2.vcproj index 3d40974..2163ad5 100644 --- a/build-VS2008/libxml2/libxml2.vcproj +++ b/build-VS2008/libxml2/libxml2.vcproj @@ -505,18 +505,6 @@ RelativePath="..\..\timsort.h" > - - - - - - diff --git a/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index b50aaa6..f77e874 100644 --- a/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index d8f51fa..b5d429f 100644 --- a/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2010-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj index 992f6ce..098252c 100644 --- a/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj.filters index d8f51fa..b5d429f 100644 --- a/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2010-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2010-MT/libxml2/libxml2.vcxproj b/build-VS2010-MT/libxml2/libxml2.vcxproj index 8c571ef..8175895 100644 --- a/build-VS2010-MT/libxml2/libxml2.vcxproj +++ b/build-VS2010-MT/libxml2/libxml2.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010-MT/libxml2/libxml2.vcxproj.filters b/build-VS2010-MT/libxml2/libxml2.vcxproj.filters index 68c6e7f..f9d74ac 100644 --- a/build-VS2010-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2010-MT/libxml2/libxml2.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index b50aaa6..f77e874 100644 --- a/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index d8f51fa..b5d429f 100644 --- a/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2010/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2010/libxml2-static/libxml2-static.vcxproj b/build-VS2010/libxml2-static/libxml2-static.vcxproj index 992f6ce..098252c 100644 --- a/build-VS2010/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2010/libxml2-static/libxml2-static.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2010/libxml2-static/libxml2-static.vcxproj.filters index d8f51fa..b5d429f 100644 --- a/build-VS2010/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2010/libxml2-static/libxml2-static.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2010/libxml2/libxml2.vcxproj b/build-VS2010/libxml2/libxml2.vcxproj index 8c571ef..8175895 100644 --- a/build-VS2010/libxml2/libxml2.vcxproj +++ b/build-VS2010/libxml2/libxml2.vcxproj @@ -205,9 +205,6 @@ - - - diff --git a/build-VS2010/libxml2/libxml2.vcxproj.filters b/build-VS2010/libxml2/libxml2.vcxproj.filters index 68c6e7f..f9d74ac 100644 --- a/build-VS2010/libxml2/libxml2.vcxproj.filters +++ b/build-VS2010/libxml2/libxml2.vcxproj.filters @@ -161,15 +161,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index ffdb5c7..da4c4e0 100644 --- a/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2013-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj index cc6ae58..9b1a937 100644 --- a/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2013-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013-MT/libxml2/libxml2.vcxproj b/build-VS2013-MT/libxml2/libxml2.vcxproj index a5b231a..39608e5 100644 --- a/build-VS2013-MT/libxml2/libxml2.vcxproj +++ b/build-VS2013-MT/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013-MT/libxml2/libxml2.vcxproj.filters b/build-VS2013-MT/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2013-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2013-MT/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index ffdb5c7..da4c4e0 100644 --- a/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2013/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013/libxml2-static/libxml2-static.vcxproj b/build-VS2013/libxml2-static/libxml2-static.vcxproj index cc6ae58..9b1a937 100644 --- a/build-VS2013/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2013/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2013/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2013/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2013/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2013/libxml2/libxml2.vcxproj b/build-VS2013/libxml2/libxml2.vcxproj index a5b231a..39608e5 100644 --- a/build-VS2013/libxml2/libxml2.vcxproj +++ b/build-VS2013/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2013/libxml2/libxml2.vcxproj.filters b/build-VS2013/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2013/libxml2/libxml2.vcxproj.filters +++ b/build-VS2013/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 53ad9a2..9e91546 100644 --- a/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2015-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj index fa44459..0139900 100644 --- a/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2015-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015-MT/libxml2/libxml2.vcxproj b/build-VS2015-MT/libxml2/libxml2.vcxproj index dd3d676..ed4930e 100644 --- a/build-VS2015-MT/libxml2/libxml2.vcxproj +++ b/build-VS2015-MT/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015-MT/libxml2/libxml2.vcxproj.filters b/build-VS2015-MT/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2015-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2015-MT/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 53ad9a2..9e91546 100644 --- a/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2015/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015/libxml2-static/libxml2-static.vcxproj b/build-VS2015/libxml2-static/libxml2-static.vcxproj index fa44459..0139900 100644 --- a/build-VS2015/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2015/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2015/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2015/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2015/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2015/libxml2/libxml2.vcxproj b/build-VS2015/libxml2/libxml2.vcxproj index dd3d676..ed4930e 100644 --- a/build-VS2015/libxml2/libxml2.vcxproj +++ b/build-VS2015/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2015/libxml2/libxml2.vcxproj.filters b/build-VS2015/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2015/libxml2/libxml2.vcxproj.filters +++ b/build-VS2015/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index bb5f7d6..d12d8eb 100644 --- a/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2017-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj index ff47b66..fe62d81 100644 --- a/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2017-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017-MT/libxml2/libxml2.vcxproj b/build-VS2017-MT/libxml2/libxml2.vcxproj index a35bee6..be940ec 100644 --- a/build-VS2017-MT/libxml2/libxml2.vcxproj +++ b/build-VS2017-MT/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017-MT/libxml2/libxml2.vcxproj.filters b/build-VS2017-MT/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2017-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2017-MT/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index bb5f7d6..d12d8eb 100644 --- a/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2017/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017/libxml2-static/libxml2-static.vcxproj b/build-VS2017/libxml2-static/libxml2-static.vcxproj index ff47b66..fe62d81 100644 --- a/build-VS2017/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2017/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2017/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2017/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2017/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2017/libxml2/libxml2.vcxproj b/build-VS2017/libxml2/libxml2.vcxproj index a35bee6..be940ec 100644 --- a/build-VS2017/libxml2/libxml2.vcxproj +++ b/build-VS2017/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2017/libxml2/libxml2.vcxproj.filters b/build-VS2017/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2017/libxml2/libxml2.vcxproj.filters +++ b/build-VS2017/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 5915a39..4e7679c 100644 --- a/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2019-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj index a89b515..f2a8928 100644 --- a/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2019-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-MT/libxml2/libxml2.vcxproj b/build-VS2019-MT/libxml2/libxml2.vcxproj index 596032d..e3bc85a 100644 --- a/build-VS2019-MT/libxml2/libxml2.vcxproj +++ b/build-VS2019-MT/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-MT/libxml2/libxml2.vcxproj.filters b/build-VS2019-MT/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2019-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2019-MT/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 1587caf..705036b 100644 --- a/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2019-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj b/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj index ab10353..7b8b028 100644 --- a/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2019-arm/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019-arm/libxml2/libxml2.vcxproj b/build-VS2019-arm/libxml2/libxml2.vcxproj index 61b8a44..747b949 100644 --- a/build-VS2019-arm/libxml2/libxml2.vcxproj +++ b/build-VS2019-arm/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019-arm/libxml2/libxml2.vcxproj.filters b/build-VS2019-arm/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2019-arm/libxml2/libxml2.vcxproj.filters +++ b/build-VS2019-arm/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 5915a39..4e7679c 100644 --- a/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2019/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019/libxml2-static/libxml2-static.vcxproj b/build-VS2019/libxml2-static/libxml2-static.vcxproj index a89b515..f2a8928 100644 --- a/build-VS2019/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2019/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2019/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2019/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2019/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2019/libxml2/libxml2.vcxproj b/build-VS2019/libxml2/libxml2.vcxproj index 596032d..e3bc85a 100644 --- a/build-VS2019/libxml2/libxml2.vcxproj +++ b/build-VS2019/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2019/libxml2/libxml2.vcxproj.filters b/build-VS2019/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2019/libxml2/libxml2.vcxproj.filters +++ b/build-VS2019/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index b7d284e..3b208d5 100644 --- a/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2022-MT/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj b/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj index 5b34516..0812b88 100644 --- a/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2022-MT/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-MT/libxml2/libxml2.vcxproj b/build-VS2022-MT/libxml2/libxml2.vcxproj index c8eec4b..f8cfc39 100644 --- a/build-VS2022-MT/libxml2/libxml2.vcxproj +++ b/build-VS2022-MT/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-MT/libxml2/libxml2.vcxproj.filters b/build-VS2022-MT/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2022-MT/libxml2/libxml2.vcxproj.filters +++ b/build-VS2022-MT/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index 7e076f0..93169da 100644 --- a/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2022-arm/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj b/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj index 84c89fa..a712177 100644 --- a/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2022-arm/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022-arm/libxml2/libxml2.vcxproj b/build-VS2022-arm/libxml2/libxml2.vcxproj index 41a192b..c1b7a23 100644 --- a/build-VS2022-arm/libxml2/libxml2.vcxproj +++ b/build-VS2022-arm/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022-arm/libxml2/libxml2.vcxproj.filters b/build-VS2022-arm/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2022-arm/libxml2/libxml2.vcxproj.filters +++ b/build-VS2022-arm/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj b/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj index b7d284e..3b208d5 100644 --- a/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj +++ b/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters b/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters +++ b/build-VS2022/libxml2-static-for-dll/libxml2-static-for-dll.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022/libxml2-static/libxml2-static.vcxproj b/build-VS2022/libxml2-static/libxml2-static.vcxproj index 5b34516..0812b88 100644 --- a/build-VS2022/libxml2-static/libxml2-static.vcxproj +++ b/build-VS2022/libxml2-static/libxml2-static.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022/libxml2-static/libxml2-static.vcxproj.filters b/build-VS2022/libxml2-static/libxml2-static.vcxproj.filters index 9d240db..8b9ab31 100644 --- a/build-VS2022/libxml2-static/libxml2-static.vcxproj.filters +++ b/build-VS2022/libxml2-static/libxml2-static.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/build-VS2022/libxml2/libxml2.vcxproj b/build-VS2022/libxml2/libxml2.vcxproj index c8eec4b..f8cfc39 100644 --- a/build-VS2022/libxml2/libxml2.vcxproj +++ b/build-VS2022/libxml2/libxml2.vcxproj @@ -210,9 +210,6 @@ - - - diff --git a/build-VS2022/libxml2/libxml2.vcxproj.filters b/build-VS2022/libxml2/libxml2.vcxproj.filters index f4eeb14..4affb58 100644 --- a/build-VS2022/libxml2/libxml2.vcxproj.filters +++ b/build-VS2022/libxml2/libxml2.vcxproj.filters @@ -164,15 +164,6 @@ Header Files\win32 - - Header Files - - - Header Files - - - Header Files - Header Files diff --git a/c14n.c b/c14n.c index 3d2e144..964ac99 100644 --- a/c14n.c +++ b/c14n.c @@ -23,8 +23,8 @@ #include #include -#include "private/buf.h" #include "private/error.h" +#include "private/io.h" /************************************************************************ * * @@ -72,7 +72,7 @@ typedef struct _xmlC14NCtx { static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void); static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur); -static void xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur, +static int xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node); static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur, @@ -134,87 +134,85 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input, * Handle a redefinition of memory error */ static void -xmlC14NErrMemory(const char *extra) +xmlC14NErrMemory(xmlC14NCtxPtr ctxt) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); + if (ctxt != NULL) + ctxt->error = XML_ERR_NO_MEMORY; + + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_C14N, NULL); } -/** - * xmlC14NErrParam: - * @extra: extra information - * - * Handle a redefinition of param error - */ static void -xmlC14NErrParam(const char *extra) +xmlC14NErrFull(xmlC14NCtxPtr ctxt, xmlNodePtr node, int code, const char *str1, + const char *msg, ...) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Invalid parameter : %s\n", extra); + va_list ap; + int res; + + if (ctxt != NULL) + ctxt->error = code; + + va_start(ap, msg); + res = xmlVRaiseError(NULL, NULL, NULL, ctxt, node, + XML_FROM_C14N, code, XML_ERR_ERROR, NULL, 0, + str1, NULL, NULL, 0, 0, + msg, ap); + va_end(ap); + if (res < 0) + xmlC14NErrMemory(ctxt); } /** - * xmlC14NErrInternal: + * xmlC14NErrParam: * @extra: extra information * - * Handle a redefinition of internal error + * Handle a param error */ static void -xmlC14NErrInternal(const char *extra) +xmlC14NErrParam(xmlC14NCtxPtr ctxt) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_ERR_INTERNAL_ERROR, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Internal error : %s\n", extra); + xmlC14NErrFull(ctxt, NULL, XML_ERR_ARGUMENT, NULL, + "Invalid argument\n", NULL); } /** * xmlC14NErrInvalidNode: * @extra: extra information * - * Handle a redefinition of invalid node error + * Handle an invalid node error */ static void -xmlC14NErrInvalidNode(const char *node_type, const char *extra) +xmlC14NErrInvalidNode(xmlC14NCtxPtr ctxt, const char *node_type, + const char *extra) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_C14N_INVALID_NODE, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Node %s is invalid here : %s\n", node_type, extra); + xmlC14NErrFull(ctxt, NULL, XML_C14N_INVALID_NODE, extra, + "Node %s is invalid here : %s\n", node_type, extra); } /** * xmlC14NErrUnknownNode: * @extra: extra information * - * Handle a redefinition of unknown node error + * Handle an unknown node error */ static void -xmlC14NErrUnknownNode(int node_type, const char *extra) +xmlC14NErrUnknownNode(xmlC14NCtxPtr ctxt, int node_type, const char *extra) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_C14N_UNKNOW_NODE, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Unknown node type %d found : %s\n", node_type, extra); + xmlC14NErrFull(ctxt, NULL, XML_C14N_UNKNOW_NODE, extra, + "Unknown node type %d found : %s\n", node_type, extra); } /** * xmlC14NErrRelativeNamespace: * @extra: extra information * - * Handle a redefinition of relative namespace error + * Handle a relative namespace error */ static void -xmlC14NErrRelativeNamespace(const char *ns_uri) +xmlC14NErrRelativeNamespace(xmlC14NCtxPtr ctxt, const char *ns_uri) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_C14N, - XML_C14N_RELATIVE_NAMESPACE, XML_ERR_ERROR, NULL, 0, NULL, - NULL, NULL, 0, 0, - "Relative namespace UR is invalid here : %s\n", ns_uri); + xmlC14NErrFull(ctxt, NULL, XML_C14N_RELATIVE_NAMESPACE, ns_uri, + "Relative namespace UR is invalid here : %s\n", ns_uri); } @@ -227,18 +225,13 @@ xmlC14NErrRelativeNamespace(const char *ns_uri) * @msg: the message * @extra: extra information * - * Handle a redefinition of attribute error + * Handle an error */ static void xmlC14NErr(xmlC14NCtxPtr ctxt, xmlNodePtr node, int error, const char * msg) { - if (ctxt != NULL) - ctxt->error = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, node, XML_FROM_C14N, error, - XML_ERR_ERROR, NULL, 0, - NULL, NULL, NULL, 0, 0, "%s", msg); + xmlC14NErrFull(ctxt, node, error, NULL, "%s", msg); } /************************************************************************ @@ -281,10 +274,8 @@ xmlC14NVisibleNsStackCreate(void) { xmlC14NVisibleNsStackPtr ret; ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack)); - if (ret == NULL) { - xmlC14NErrMemory("creating namespaces stack"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlC14NVisibleNsStack)); return(ret); } @@ -292,7 +283,7 @@ xmlC14NVisibleNsStackCreate(void) { static void xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) { if(cur == NULL) { - xmlC14NErrParam("destroying namespaces stack"); + xmlC14NErrParam(NULL); return; } if(cur->nsTab != NULL) { @@ -308,22 +299,18 @@ xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) { } -static void +static int xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr node) { if((cur == NULL) || ((cur->nsTab == NULL) && (cur->nodeTab != NULL)) || - ((cur->nsTab != NULL) && (cur->nodeTab == NULL))) { - xmlC14NErrParam("adding namespace to stack"); - return; - } + ((cur->nsTab != NULL) && (cur->nodeTab == NULL))) + return (1); if ((cur->nsTab == NULL) && (cur->nodeTab == NULL)) { cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); cur->nodeTab = (xmlNodePtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); - if ((cur->nsTab == NULL) || (cur->nodeTab == NULL)) { - xmlC14NErrMemory("adding node to stack"); - return; - } + if ((cur->nsTab == NULL) || (cur->nodeTab == NULL)) + return (-1); memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr)); memset(cur->nodeTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNodePtr)); cur->nsMax = XML_NAMESPACES_DEFAULT; @@ -333,17 +320,13 @@ xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr n tmpSize = 2 * cur->nsMax; tmp = xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr)); - if (tmp == NULL) { - xmlC14NErrMemory("adding node to stack"); - return; - } + if (tmp == NULL) + return (-1); cur->nsTab = (xmlNsPtr*)tmp; tmp = xmlRealloc(cur->nodeTab, tmpSize * sizeof(xmlNodePtr)); - if (tmp == NULL) { - xmlC14NErrMemory("adding node to stack"); - return; - } + if (tmp == NULL) + return (-1); cur->nodeTab = (xmlNodePtr*)tmp; cur->nsMax = tmpSize; @@ -352,12 +335,14 @@ xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlNodePtr n cur->nodeTab[cur->nsCurEnd] = node; ++cur->nsCurEnd; + + return (0); } static void xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { if((cur == NULL) || (state == NULL)) { - xmlC14NErrParam("saving namespaces stack"); + xmlC14NErrParam(NULL); return; } @@ -369,7 +354,7 @@ xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr static void xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) { if((cur == NULL) || (state == NULL)) { - xmlC14NErrParam("restoring namespaces stack"); + xmlC14NErrParam(NULL); return; } cur->nsCurEnd = state->nsCurEnd; @@ -380,7 +365,7 @@ xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStack static void xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) { if(cur == NULL) { - xmlC14NErrParam("shifting namespaces stack"); + xmlC14NErrParam(NULL); return; } cur->nsPrevStart = cur->nsPrevEnd; @@ -416,7 +401,7 @@ xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns) int has_empty_ns; if(cur == NULL) { - xmlC14NErrParam("searching namespaces stack (c14n)"); + xmlC14NErrParam(NULL); return (0); } @@ -449,7 +434,7 @@ xmlExcC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, xmlC14NC int has_empty_ns; if(cur == NULL) { - xmlC14NErrParam("searching namespaces stack (exc c14n)"); + xmlC14NErrParam(ctx); return (0); } @@ -513,8 +498,8 @@ xmlC14NIsXmlNs(xmlNsPtr ns) static int xmlC14NNsCompare(const void *data1, const void *data2) { - const xmlNsPtr ns1 = (const xmlNsPtr) data1; - const xmlNsPtr ns2 = (const xmlNsPtr) data2; + const xmlNs *ns1 = data1; + const xmlNs *ns2 = data2; if (ns1 == ns2) return (0); if (ns1 == NULL) @@ -536,11 +521,11 @@ xmlC14NNsCompare(const void *data1, const void *data2) * Returns 1 on success or 0 on fail. */ static int -xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) +xmlC14NPrintNamespaces(const xmlNs *ns, xmlC14NCtxPtr ctx) { if ((ns == NULL) || (ctx == NULL)) { - xmlC14NErrParam("writing namespaces"); + xmlC14NErrParam(ctx); return 0; } @@ -552,7 +537,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) xmlOutputBufferWriteString(ctx->buf, " xmlns="); } if(ns->href != NULL) { - xmlBufWriteQuotedString(ctx->buf->buffer, ns->href); + xmlOutputBufferWriteQuotedString(ctx->buf, ns->href); } else { xmlOutputBufferWriteString(ctx->buf, "\"\""); } @@ -561,7 +546,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx) static int xmlC14NPrintNamespacesWalker(const void *ns, void *ctx) { - return xmlC14NPrintNamespaces((const xmlNsPtr) ns, (xmlC14NCtxPtr) ctx); + return xmlC14NPrintNamespaces(ns, ctx); } /** @@ -613,7 +598,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) int has_empty_ns = 0; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { - xmlC14NErrParam("processing namespaces axis (c14n)"); + xmlC14NErrParam(ctx); return (-1); } @@ -622,7 +607,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) */ list = xmlListCreate(NULL, xmlC14NNsCompare); if (list == NULL) { - xmlC14NErrInternal("creating namespaces list (c14n)"); + xmlC14NErrMemory(ctx); return (-1); } @@ -634,7 +619,10 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) if((tmp == ns) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) { already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns); if(visible) { - xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) { + xmlC14NErrMemory(ctx); + goto error; + } } if(!already_rendered) { xmlListInsert(list, ns); @@ -673,6 +661,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) /* * Cleanup */ +error: xmlListDelete(list); return (0); } @@ -720,12 +709,12 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) int has_empty_ns_in_inclusive_list = 0; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { - xmlC14NErrParam("processing namespaces axis (exc c14n)"); + xmlC14NErrParam(ctx); return (-1); } if(!xmlC14NIsExclusive(ctx)) { - xmlC14NErrParam("processing namespaces axis (exc c14n)"); + xmlC14NErrParam(ctx); return (-1); } @@ -735,7 +724,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) */ list = xmlListCreate(NULL, xmlC14NNsCompare); if (list == NULL) { - xmlC14NErrInternal("creating namespaces list (exc c14n)"); + xmlC14NErrMemory(ctx); return (-1); } @@ -763,7 +752,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) if((ns != NULL) && !xmlC14NIsXmlNs(ns) && xmlC14NIsVisible(ctx, ns, cur)) { already_rendered = xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns); if(visible) { - xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) { + xmlC14NErrMemory(ctx); + goto error; + } } if(!already_rendered) { xmlListInsert(list, ns); @@ -789,7 +781,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) } } if(visible) { - xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur); + if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns, cur) < 0) { + xmlC14NErrMemory(ctx); + goto error; + } } if(xmlStrlen(ns->prefix) == 0) { has_empty_ns = 1; @@ -806,7 +801,10 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) */ if((attr->ns != NULL) && !xmlC14NIsXmlNs(attr->ns) && xmlC14NIsVisible(ctx, attr, cur)) { already_rendered = xmlExcC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, ctx); - xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur); + if (xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns, cur) < 0) { + xmlC14NErrMemory(ctx); + goto error; + } if(!already_rendered && visible) { xmlListInsert(list, attr->ns); } @@ -850,6 +848,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) /* * Cleanup */ +error: xmlListDelete(list); return (0); } @@ -886,8 +885,8 @@ xmlC14NIsXmlAttr(xmlAttrPtr attr) static int xmlC14NAttrsCompare(const void *data1, const void *data2) { - const xmlAttrPtr attr1 = (const xmlAttrPtr) data1; - const xmlAttrPtr attr2 = (const xmlAttrPtr) data2; + const xmlAttr *attr1 = data1; + const xmlAttr *attr2 = data2; int ret = 0; /* @@ -940,13 +939,13 @@ xmlC14NAttrsCompare(const void *data1, const void *data2) static int xmlC14NPrintAttrs(const void *data, void *user) { - const xmlAttrPtr attr = (const xmlAttrPtr) data; + const xmlAttr *attr = data; xmlC14NCtxPtr ctx = (xmlC14NCtxPtr) user; xmlChar *value; xmlChar *buffer; if ((attr == NULL) || (ctx == NULL)) { - xmlC14NErrParam("writing attributes"); + xmlC14NErrParam(ctx); return (0); } @@ -968,7 +967,7 @@ xmlC14NPrintAttrs(const void *data, void *user) xmlOutputBufferWriteString(ctx->buf, (const char *) buffer); xmlFree(buffer); } else { - xmlC14NErrInternal("normalizing attributes axis"); + xmlC14NErrMemory(ctx); return (0); } } @@ -1017,20 +1016,22 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr) int tmp_str_len; if ((ctx == NULL) || (xml_base_attr == NULL) || (xml_base_attr->parent == NULL)) { - xmlC14NErrParam("processing xml:base attribute"); + xmlC14NErrParam(ctx); return (NULL); } /* start from current value */ res = xmlNodeListGetString(ctx->doc, xml_base_attr->children, 1); if(res == NULL) { - xmlC14NErrInternal("processing xml:base attribute - can't get attr value"); + xmlC14NErrMemory(ctx); return (NULL); } /* go up the stack until we find a node that we rendered already */ cur = xml_base_attr->parent->parent; while((cur != NULL) && (!xmlC14NIsVisible(ctx, cur, cur->parent))) { + int code; + attr = xmlHasNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); if(attr != NULL) { /* get attr value */ @@ -1038,7 +1039,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr) if(tmp_str == NULL) { xmlFree(res); - xmlC14NErrInternal("processing xml:base attribute - can't get attr value"); + xmlC14NErrMemory(ctx); return (NULL); } @@ -1051,7 +1052,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr) xmlFree(tmp_str); xmlFree(res); - xmlC14NErrInternal("processing xml:base attribute - can't modify uri"); + xmlC14NErrMemory(ctx); return (NULL); } @@ -1059,12 +1060,17 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr) } /* build uri */ - tmp_str2 = xmlBuildURI(res, tmp_str); - if(tmp_str2 == NULL) { + code = xmlBuildURISafe(res, tmp_str, &tmp_str2); + if (code != 0) { xmlFree(tmp_str); xmlFree(res); - xmlC14NErrInternal("processing xml:base attribute - can't construct uri"); + if (code < 0) + xmlC14NErrMemory(ctx); + else + xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI, + "processing xml:base attribute - " + "can't construct uri"); return (NULL); } @@ -1089,7 +1095,7 @@ xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr) if(attr == NULL) { xmlFree(res); - xmlC14NErrInternal("processing xml:base attribute - can't construct attribute"); + xmlC14NErrMemory(ctx); return (NULL); } @@ -1144,7 +1150,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible) xmlAttrPtr xml_space_attr = NULL; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { - xmlC14NErrParam("processing attributes axis"); + xmlC14NErrParam(ctx); return (-1); } @@ -1153,7 +1159,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible) */ list = xmlListCreate(NULL, xmlC14NAttrsCompare); if (list == NULL) { - xmlC14NErrInternal("creating attributes list"); + xmlC14NErrMemory(ctx); return (-1); } @@ -1365,7 +1371,7 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur) xmlNsPtr ns; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { - xmlC14NErrParam("checking for relative namespaces"); + xmlC14NErrParam(ctx); return (-1); } @@ -1373,14 +1379,19 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur) while (ns != NULL) { if (xmlStrlen(ns->href) > 0) { xmlURIPtr uri; + int code; - uri = xmlParseURI((const char *) ns->href); + code = xmlParseURISafe((const char *) ns->href, &uri); if (uri == NULL) { - xmlC14NErrInternal("parsing namespace uri"); + if (code < 0) + xmlC14NErrMemory(ctx); + else + xmlC14NErr(ctx, cur, XML_ERR_INVALID_URI, + "parsing namespace uri"); return (-1); } if (xmlStrlen((const xmlChar *) uri->scheme) == 0) { - xmlC14NErrRelativeNamespace(uri->scheme); + xmlC14NErrRelativeNamespace(ctx, uri->scheme); xmlFreeURI(uri); return (-1); } @@ -1422,7 +1433,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) int parent_is_doc = 0; if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) { - xmlC14NErrParam("processing element node"); + xmlC14NErrParam(ctx); return (-1); } @@ -1431,11 +1442,8 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) * implementations of XML canonicalization MUST report an operation * failure on documents containing relative namespace URIs. */ - if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0) { - xmlC14NErrInternal("checking for relative namespaces"); + if (xmlC14NCheckForRelativeNamespaces(ctx, cur) < 0) return (-1); - } - /* * Save ns_rendered stack position @@ -1465,30 +1473,24 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible) } else { ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible); } - if (ret < 0) { - xmlC14NErrInternal("processing namespaces axis"); + if (ret < 0) return (-1); - } /* todo: shouldn't this go to "visible only"? */ if(visible) { xmlC14NVisibleNsStackShift(ctx->ns_rendered); } ret = xmlC14NProcessAttrsAxis(ctx, cur, visible); - if (ret < 0) { - xmlC14NErrInternal("processing attributes axis"); + if (ret < 0) return (-1); - } if (visible) { xmlOutputBufferWriteString(ctx->buf, ">"); } if (cur->children != NULL) { ret = xmlC14NProcessNodeList(ctx, cur->children); - if (ret < 0) { - xmlC14NErrInternal("processing childrens list"); + if (ret < 0) return (-1); - } } if (visible) { xmlOutputBufferWriteString(ctx->buf, "type, "processing node"); + xmlC14NErrUnknownNode(ctx, cur->type, "processing node"); return (-1); } @@ -1716,7 +1718,7 @@ xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur) int ret; if (ctx == NULL) { - xmlC14NErrParam("processing node list"); + xmlC14NErrParam(ctx); return (-1); } @@ -1738,7 +1740,7 @@ static void xmlC14NFreeCtx(xmlC14NCtxPtr ctx) { if (ctx == NULL) { - xmlC14NErrParam("freeing context"); + xmlC14NErrParam(ctx); return; } @@ -1778,7 +1780,7 @@ xmlC14NNewCtx(xmlDocPtr doc, xmlC14NCtxPtr ctx = NULL; if ((doc == NULL) || (buf == NULL)) { - xmlC14NErrParam("creating new context"); + xmlC14NErrParam(ctx); return (NULL); } @@ -1796,7 +1798,7 @@ xmlC14NNewCtx(xmlDocPtr doc, */ ctx = (xmlC14NCtxPtr) xmlMalloc(sizeof(xmlC14NCtx)); if (ctx == NULL) { - xmlC14NErrMemory("creating context"); + xmlC14NErrMemory(ctx); return (NULL); } memset(ctx, 0, sizeof(xmlC14NCtx)); @@ -1814,8 +1816,7 @@ xmlC14NNewCtx(xmlDocPtr doc, ctx->ns_rendered = xmlC14NVisibleNsStackCreate(); if(ctx->ns_rendered == NULL) { - xmlC14NErr(ctx, (xmlNodePtr) doc, XML_C14N_CREATE_STACK, - "xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n"); + xmlC14NErrMemory(ctx); xmlC14NFreeCtx(ctx); return (NULL); } @@ -1828,6 +1829,7 @@ xmlC14NNewCtx(xmlDocPtr doc, if(xmlC14NIsExclusive(ctx)) { ctx->inclusive_ns_prefixes = inclusive_ns_prefixes; } + return (ctx); } @@ -1864,7 +1866,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, int ret; if ((buf == NULL) || (doc == NULL)) { - xmlC14NErrParam("executing c14n"); + xmlC14NErrParam(NULL); return (-1); } @@ -1877,7 +1879,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, c14n_mode = (xmlC14NMode)mode; break; default: - xmlC14NErrParam("invalid mode for executing c14n"); + xmlC14NErrParam(NULL); return (-1); } @@ -1912,7 +1914,6 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, if (doc->children != NULL) { ret = xmlC14NProcessNodeList(ctx, doc->children); if (ret < 0) { - xmlC14NErrInternal("processing docs children list"); xmlC14NFreeCtx(ctx); return (-1); } @@ -1923,7 +1924,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, */ ret = xmlOutputBufferFlush(buf); if (ret < 0) { - xmlC14NErrInternal("flushing output buffer"); + xmlC14NErr(ctx, NULL, buf->error, "flushing output buffer"); xmlC14NFreeCtx(ctx); return (-1); } @@ -2000,7 +2001,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes, xmlOutputBufferPtr buf; if (doc_txt_ptr == NULL) { - xmlC14NErrParam("dumping doc to memory"); + xmlC14NErrParam(NULL); return (-1); } @@ -2011,7 +2012,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes, */ buf = xmlAllocOutputBuffer(NULL); if (buf == NULL) { - xmlC14NErrMemory("creating output buffer"); + xmlC14NErrMemory(NULL); return (-1); } @@ -2021,7 +2022,6 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes, ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes, with_comments, buf); if (ret < 0) { - xmlC14NErrInternal("saving doc to output buffer"); (void) xmlOutputBufferClose(buf); return (-1); } @@ -2033,7 +2033,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes, (void) xmlOutputBufferClose(buf); if ((*doc_txt_ptr == NULL) && (ret >= 0)) { - xmlC14NErrMemory("copying canonicalized document"); + xmlC14NErrMemory(NULL); return (-1); } return (ret); @@ -2071,7 +2071,7 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes, int ret; if (filename == NULL) { - xmlC14NErrParam("saving doc"); + xmlC14NErrParam(NULL); return (-1); } #ifdef LIBXML_ZLIB_ENABLED @@ -2084,7 +2084,7 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes, */ buf = xmlOutputBufferCreateFilename(filename, NULL, compression); if (buf == NULL) { - xmlC14NErrInternal("creating temporary filename"); + xmlC14NErr(NULL, NULL, XML_IO_UNKNOWN, "creating temporary filename"); return (-1); } @@ -2094,7 +2094,6 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes, ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes, with_comments, buf); if (ret < 0) { - xmlC14NErrInternal("canonize document to buffer"); (void) xmlOutputBufferClose(buf); return (-1); } @@ -2106,21 +2105,6 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes, return (ret); } - - -/* - * Macro used to grow the current buffer. - */ -#define growBufferReentrant() { \ - buffer_size *= 2; \ - buffer = (xmlChar *) \ - xmlRealloc(buffer, buffer_size); \ - if (buffer == NULL) { \ - xmlC14NErrMemory("growing buffer"); \ - return(NULL); \ - } \ -} - /** * xmlC11NNormalizeString: * @input: the input string @@ -2150,17 +2134,22 @@ xmlC11NNormalizeString(const xmlChar * input, */ buffer_size = 1000; buffer = (xmlChar *) xmlMallocAtomic(buffer_size); - if (buffer == NULL) { - xmlC14NErrMemory("allocating buffer"); + if (buffer == NULL) return (NULL); - } out = buffer; while (*cur != '\0') { if ((out - buffer) > (buffer_size - 10)) { + xmlChar *tmp; int indx = out - buffer; - growBufferReentrant(); + buffer_size *= 2; + tmp = xmlRealloc(buffer, buffer_size); + if (tmp == NULL) { + xmlFree(buffer); + return(NULL); + } + buffer = tmp; out = &buffer[indx]; } diff --git a/catalog.c b/catalog.c index 33514d9..6a32c0f 100644 --- a/catalog.c +++ b/catalog.c @@ -16,6 +16,7 @@ #include "libxml.h" #ifdef LIBXML_CATALOG_ENABLED +#include #include #include #ifdef HAVE_SYS_STAT_H @@ -52,21 +53,6 @@ # define PATH_SEPARATOR ':' #endif -/** - * TODO: - * - * macro to flag unimplemented blocks - * XML_CATALOG_PREFER user env to select between system/public preferred - * option. C.f. Richard Tobin - *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with - *> values "system" and "public". I have made the default be "system" to - *> match yours. - */ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - #define XML_URN_PUBID "urn:publicid:" #define XML_CATAL_BREAK ((xmlChar *) -1) #ifndef XML_XML_DEFAULT_CATALOG @@ -76,18 +62,6 @@ #define XML_SGML_DEFAULT_CATALOG "file://" SYSCONFDIR "/sgml/catalog" #endif -#if defined(_WIN32) && defined(_MSC_VER) -#undef XML_XML_DEFAULT_CATALOG -static char XML_XML_DEFAULT_CATALOG[256] = "file://" SYSCONFDIR "/xml/catalog"; -#if !defined(_WINDOWS_) -void* __stdcall GetModuleHandleA(const char*); -unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long); -#endif -#endif - -static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID); -static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename); - /************************************************************************ * * * Types, all private * @@ -202,6 +176,21 @@ static xmlRMutexPtr xmlCatalogMutex = NULL; */ static int xmlCatalogInitialized = 0; +/************************************************************************ + * * + * Forward declarations * + * * + ************************************************************************/ + +static xmlChar * +xmlCatalogNormalizePublic(const xmlChar *pubID); + +static int +xmlExpandCatalog(xmlCatalogPtr catal, const char *filename); + +static int +xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal); + /************************************************************************ * * * Catalog error handlers * @@ -215,12 +204,9 @@ static int xmlCatalogInitialized = 0; * Handle an out of memory condition */ static void -xmlCatalogErrMemory(const char *extra) +xmlCatalogErrMemory(void) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_CATALOG, - XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, - extra, NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_CATALOG, NULL); } /** @@ -237,11 +223,15 @@ xmlCatalogErr(xmlCatalogEntryPtr catal, xmlNodePtr node, int error, const char *msg, const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) { - __xmlRaiseError(NULL, NULL, NULL, catal, node, XML_FROM_CATALOG, - error, XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, - (const char *) str3, 0, 0, - msg, str1, str2, str3); + int res; + + res = __xmlRaiseError(NULL, NULL, NULL, catal, node, + XML_FROM_CATALOG, error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, + (const char *) str3, 0, 0, + msg, str1, str2, str3); + if (res < 0) + xmlCatalogErrMemory(); } @@ -273,7 +263,7 @@ xmlNewCatalogEntry(xmlCatalogEntryType type, const xmlChar *name, ret = (xmlCatalogEntryPtr) xmlMalloc(sizeof(xmlCatalogEntry)); if (ret == NULL) { - xmlCatalogErrMemory("allocating catalog entry"); + xmlCatalogErrMemory(); return(NULL); } ret->next = NULL; @@ -331,13 +321,13 @@ xmlFreeCatalogEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { if (xmlDebugCatalogs) { if (ret->name != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Free catalog entry %s\n", ret->name); else if (ret->value != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Free catalog entry %s\n", ret->value); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Free catalog entry\n"); } @@ -411,7 +401,7 @@ xmlCreateNewCatalog(xmlCatalogType type, xmlCatalogPrefer prefer) { ret = (xmlCatalogPtr) xmlMalloc(sizeof(xmlCatalog)); if (ret == NULL) { - xmlCatalogErrMemory("allocating catalog"); + xmlCatalogErrMemory(); return(NULL); } memset(ret, 0, sizeof(xmlCatalog)); @@ -551,6 +541,9 @@ static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog, case XML_CATA_BROKEN_CATALOG: case XML_CATA_CATALOG: if (cur == catal) { + if (cur->children == NULL) { + xmlFetchXMLCatalogFile(cur); + } cur = cur->children; continue; } @@ -795,7 +788,7 @@ xmlConvertSGMLCatalog(xmlCatalogPtr catal) { return(-1); if (xmlDebugCatalogs) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Converting SGML catalog to XML\n"); } xmlHashScan(catal->sgml, xmlCatalogConvertEntry, &catal); @@ -887,13 +880,12 @@ xmlDocPtr xmlParseCatalogFile(const char *filename) { xmlDocPtr ret; xmlParserCtxtPtr ctxt; - char *directory = NULL; xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf; ctxt = xmlNewParserCtxt(); if (ctxt == NULL) { - xmlCatalogErrMemory("allocating parser context"); + xmlCatalogErrMemory(); return(NULL); } @@ -915,10 +907,7 @@ xmlParseCatalogFile(const char *filename) { xmlBufResetInput(buf->buffer, inputStream); inputPush(ctxt, inputStream); - if (ctxt->directory == NULL) - directory = xmlParserGetDirectory(filename); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; + ctxt->valid = 0; ctxt->validate = 0; ctxt->loadsubset = 0; @@ -1012,7 +1001,7 @@ xmlLoadFileContent(const char *filename) #endif content = (xmlChar*)xmlMallocAtomic(size + 10); if (content == NULL) { - xmlCatalogErrMemory("allocating catalog data"); + xmlCatalogErrMemory(); #ifdef HAVE_STAT close(fd); #else @@ -1197,10 +1186,10 @@ xmlParseXMLCatalogOneNode(xmlNodePtr cur, xmlCatalogEntryType type, if (URL != NULL) { if (xmlDebugCatalogs > 1) { if (nameValue != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found %s: '%s' '%s'\n", name, nameValue, URL); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found %s: '%s'\n", name, URL); } ret = xmlNewCatalogEntry(type, nameValue, uriValue, URL, prefer, cgroup); @@ -1369,13 +1358,13 @@ xmlParseXMLCatalogFile(xmlCatalogPrefer prefer, const xmlChar *filename) { doc = xmlParseCatalogFile((const char *) filename); if (doc == NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Failed to parse catalog %s\n", filename); return(NULL); } if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%d Parsing catalog %s\n", xmlGetThreadId(), filename); cur = xmlDocGetRootElement(doc); @@ -1448,7 +1437,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { xmlHashLookup(xmlCatalogXMLFiles, catal->URL); if (doc != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found %s in file hash\n", catal->URL); if (catal->type == XML_CATA_CATALOG) @@ -1460,7 +1449,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { return(0); } if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s not found in file hash\n", catal->URL); } @@ -1487,7 +1476,7 @@ xmlFetchXMLCatalogFile(xmlCatalogEntryPtr catal) { xmlCatalogXMLFiles = xmlHashCreate(10); if (xmlCatalogXMLFiles != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s added to file hash\n", catal->URL); xmlHashAddEntry(xmlCatalogXMLFiles, catal->URL, doc); } @@ -1533,7 +1522,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, typ = xmlGetXMLCatalogEntryType(type); if (typ == XML_CATA_NONE) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Failed to add unknown element %s to catalog\n", type); return(-1); } @@ -1547,7 +1536,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, if ((orig != NULL) && (cur->type == typ) && (xmlStrEqual(orig, cur->name))) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Updating element %s to catalog\n", type); if (cur->value != NULL) xmlFree(cur->value); @@ -1563,7 +1552,7 @@ xmlAddXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *type, } } if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Adding element %s to catalog\n", type); if (cur == NULL) catal->children = xmlNewCatalogEntry(typ, orig, replace, @@ -1615,10 +1604,10 @@ xmlDelXMLCatalog(xmlCatalogEntryPtr catal, const xmlChar *value) { (xmlStrEqual(value, cur->value))) { if (xmlDebugCatalogs) { if (cur->name != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Removing element %s from catalog\n", cur->name); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Removing element %s from catalog\n", cur->value); } cur->type = XML_CATA_REMOVED; @@ -1674,7 +1663,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, case XML_CATA_SYSTEM: if (xmlStrEqual(sysID, cur->name)) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found system match %s, using %s\n", cur->name, cur->URL); catal->depth--; @@ -1703,7 +1692,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, } if (rewrite != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Using rewriting rule %s\n", rewrite->name); ret = xmlStrdup(rewrite->URL); if (ret != NULL) @@ -1738,7 +1727,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, } if (cur->children != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Trying system delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolve( cur->children, NULL, sysID); @@ -1768,7 +1757,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, case XML_CATA_PUBLIC: if (xmlStrEqual(pubID, cur->name)) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found public match %s\n", cur->name); catal->depth--; return(xmlStrdup(cur->URL)); @@ -1817,7 +1806,7 @@ xmlCatalogXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, } if (cur->children != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Trying public delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolve( cur->children, pubID, NULL); @@ -1907,7 +1896,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { case XML_CATA_URI: if (xmlStrEqual(URI, cur->name)) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Found URI match %s\n", cur->name); return(xmlStrdup(cur->URL)); } @@ -1934,7 +1923,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { } if (rewrite != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Using rewriting rule %s\n", rewrite->name); ret = xmlStrdup(rewrite->URL); if (ret != NULL) @@ -1969,7 +1958,7 @@ xmlCatalogXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { } if (cur->children != NULL) { if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Trying URI delegate %s\n", cur->URL); ret = xmlCatalogListXMLResolveURI( cur->children, URI); @@ -2038,10 +2027,10 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, urnID = xmlCatalogUnWrapURN(pubID); if (xmlDebugCatalogs) { if (urnID == NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Public URN ID %s expanded to NULL\n", pubID); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Public URN ID expanded to %s\n", urnID); } ret = xmlCatalogListXMLResolve(catal, urnID, sysID); @@ -2055,10 +2044,10 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID, urnID = xmlCatalogUnWrapURN(sysID); if (xmlDebugCatalogs) { if (urnID == NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "System URN ID %s expanded to NULL\n", sysID); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "System URN ID expanded to %s\n", urnID); } if (pubID == NULL) @@ -2122,10 +2111,10 @@ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { urnID = xmlCatalogUnWrapURN(URI); if (xmlDebugCatalogs) { if (urnID == NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "URN ID %s expanded to NULL\n", URI); else - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "URN ID expanded to %s\n", urnID); } ret = xmlCatalogListXMLResolve(catal, urnID, NULL); @@ -2212,7 +2201,7 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) { } buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - xmlCatalogErrMemory("allocating public ID"); + xmlCatalogErrMemory(); return(NULL); } while (IS_PUBIDCHAR_CH(*cur) || (*cur == '?')) { @@ -2224,7 +2213,7 @@ xmlParseSGMLCatalogPubid(const xmlChar *cur, xmlChar **id) { size *= 2; tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { - xmlCatalogErrMemory("allocating public ID"); + xmlCatalogErrMemory(); xmlFree(buf); return(NULL); } @@ -2804,7 +2793,7 @@ xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID) { return(NULL); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve sysID %s\n", sysID); if (catal->type == XML_XML_CATALOG_TYPE) { @@ -2839,7 +2828,7 @@ xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID) { return(NULL); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve pubID %s\n", pubID); if (catal->type == XML_XML_CATALOG_TYPE) { @@ -2878,13 +2867,13 @@ xmlACatalogResolve(xmlCatalogPtr catal, const xmlChar * pubID, if (xmlDebugCatalogs) { if ((pubID != NULL) && (sysID != NULL)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve: pubID %s sysID %s\n", pubID, sysID); } else if (pubID != NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve: pubID %s\n", pubID); } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve: sysID %s\n", sysID); } } @@ -2921,7 +2910,7 @@ xmlACatalogResolveURI(xmlCatalogPtr catal, const xmlChar *URI) { return(NULL); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve URI %s\n", URI); if (catal->type == XML_XML_CATALOG_TYPE) { @@ -3138,35 +3127,7 @@ xmlInitializeCatalog(void) { catalogs = (const char *) getenv("XML_CATALOG_FILES"); if (catalogs == NULL) -#if defined(_WIN32) && defined(_MSC_VER) - { - void* hmodule; - hmodule = GetModuleHandleA("libxml2.dll"); - if (hmodule == NULL) - hmodule = GetModuleHandleA(NULL); - if (hmodule != NULL) { - char buf[256]; - unsigned long len = GetModuleFileNameA(hmodule, buf, 255); - if (len != 0) { - char* p = &(buf[len]); - while (*p != '\\' && p > buf) - p--; - if (p != buf) { - xmlChar* uri; - strncpy(p, "\\..\\etc\\catalog", 255 - (p - buf)); - uri = xmlCanonicPath((const xmlChar*)buf); - if (uri != NULL) { - strncpy(XML_XML_DEFAULT_CATALOG, (char* )uri, 255); - xmlFree(uri); - } - } - } - } - catalogs = XML_XML_DEFAULT_CATALOG; - } -#else catalogs = XML_XML_DEFAULT_CATALOG; -#endif catal = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE, xmlCatalogDefaultPrefer); @@ -3298,7 +3259,7 @@ xmlCatalogCleanup(void) { xmlRMutexLock(xmlCatalogMutex); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Catalogs cleanup\n"); if (xmlCatalogXMLFiles != NULL) xmlHashFree(xmlCatalogXMLFiles, xmlFreeCatalogHashEntryList); @@ -3526,19 +3487,19 @@ xmlCatalogSetDefaults(xmlCatalogAllow allow) { if (xmlDebugCatalogs) { switch (allow) { case XML_CATA_ALLOW_NONE: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Disabling catalog usage\n"); break; case XML_CATA_ALLOW_GLOBAL: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Allowing only global catalogs\n"); break; case XML_CATA_ALLOW_DOCUMENT: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Allowing only catalogs from the document\n"); break; case XML_CATA_ALLOW_ALL: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Allowing all catalogs\n"); break; } @@ -3566,11 +3527,11 @@ xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer) { if (xmlDebugCatalogs) { switch (prefer) { case XML_CATA_PREFER_PUBLIC: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Setting catalog preference to PUBLIC\n"); break; case XML_CATA_PREFER_SYSTEM: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Setting catalog preference to SYSTEM\n"); break; default: @@ -3646,7 +3607,7 @@ xmlCatalogAddLocal(void *catalogs, const xmlChar *URL) { return(catalogs); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Adding document catalog %s\n", URL); add = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL, URL, NULL, @@ -3690,13 +3651,13 @@ xmlCatalogLocalResolve(void *catalogs, const xmlChar *pubID, if (xmlDebugCatalogs) { if ((pubID != NULL) && (sysID != NULL)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Local Resolve: pubID %s sysID %s\n", pubID, sysID); } else if (pubID != NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Local Resolve: pubID %s\n", pubID); } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Local Resolve: sysID %s\n", sysID); } } @@ -3733,7 +3694,7 @@ xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI) { return(NULL); if (xmlDebugCatalogs) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Resolve URI %s\n", URI); catal = (xmlCatalogEntryPtr) catalogs; @@ -3769,7 +3730,7 @@ xmlCatalogGetSystem(const xmlChar *sysID) { xmlInitializeCatalog(); if (msg == 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Use of deprecated xmlCatalogGetSystem() call\n"); msg++; } @@ -3813,7 +3774,7 @@ xmlCatalogGetPublic(const xmlChar *pubID) { xmlInitializeCatalog(); if (msg == 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Use of deprecated xmlCatalogGetPublic() call\n"); msg++; } diff --git a/debugXML.c b/debugXML.c index 303515e..ed56b0f 100644 --- a/debugXML.c +++ b/debugXML.c @@ -154,31 +154,21 @@ static void xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg) { ctxt->errors++; - __xmlRaiseError(NULL, NULL, NULL, - NULL, ctxt->node, XML_FROM_CHECK, - error, XML_ERR_ERROR, NULL, 0, - NULL, NULL, NULL, 0, 0, - "%s", msg); + fprintf(ctxt->output, "ERROR %d: %s", error, msg); } static void LIBXML_ATTR_FORMAT(3,0) xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra) { ctxt->errors++; - __xmlRaiseError(NULL, NULL, NULL, - NULL, ctxt->node, XML_FROM_CHECK, - error, XML_ERR_ERROR, NULL, 0, - NULL, NULL, NULL, 0, 0, - msg, extra); + fprintf(ctxt->output, "ERROR %d: ", error); + fprintf(ctxt->output, msg, extra); } static void LIBXML_ATTR_FORMAT(3,0) xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra) { ctxt->errors++; - __xmlRaiseError(NULL, NULL, NULL, - NULL, ctxt->node, XML_FROM_CHECK, - error, XML_ERR_ERROR, NULL, 0, - NULL, NULL, NULL, 0, 0, - msg, extra); + fprintf(ctxt->output, "ERROR %d: ", error); + fprintf(ctxt->output, msg, extra); } /** @@ -1824,47 +1814,47 @@ xmlShellPrintXPathError(int errorType, const char *arg) switch (errorType) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s: no such node\n", arg); break; case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s is an XSLT value tree\n", arg); break; } #if 0 - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Try casting the result string function (xpath builtin)\n", arg); #endif @@ -1940,26 +1930,26 @@ xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list) list->nodesetval->nodeTab[indx]); } } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Empty node set\n"); } break; #else - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Node set\n"); #endif /* LIBXML_OUTPUT_ENABLED */ } case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Is a Boolean:%s\n", xmlBoolToText(list->boolval)); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Is a number:%0g\n", list->floatval); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Is a string:%s\n", list->stringval); break; @@ -2331,6 +2321,16 @@ xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, return (0); } +static void +xmlShellPrintf(void *ctx, const char *msg, ...) { + xmlShellCtxtPtr sctxt = ctx; + va_list ap; + + va_start(ap, msg); + vfprintf(sctxt->output, msg, ap); + va_end(ap); +} + #ifdef LIBXML_SCHEMAS_ENABLED /** * xmlShellRNGValidate: @@ -2355,23 +2355,23 @@ xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas, int ret; ctxt = xmlRelaxNGNewParserCtxt(schemas); - xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL); + xmlRelaxNGSetParserErrors(ctxt, xmlShellPrintf, xmlShellPrintf, sctxt); relaxngschemas = xmlRelaxNGParse(ctxt); xmlRelaxNGFreeParserCtxt(ctxt); if (relaxngschemas == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(sctxt->output, "Relax-NG schema %s failed to compile\n", schemas); return(-1); } vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas); - xmlRelaxNGSetValidErrors(vctxt, xmlGenericError, xmlGenericError, NULL); + xmlRelaxNGSetValidErrors(vctxt, xmlShellPrintf, xmlShellPrintf, sctxt); ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc); if (ret == 0) { - fprintf(stderr, "%s validates\n", sctxt->filename); + fprintf(sctxt->output, "%s validates\n", sctxt->filename); } else if (ret > 0) { - fprintf(stderr, "%s fails to validate\n", sctxt->filename); + fprintf(sctxt->output, "%s fails to validate\n", sctxt->filename); } else { - fprintf(stderr, "%s validation generated an internal error\n", + fprintf(sctxt->output, "%s validation generated an internal error\n", sctxt->filename); } xmlRelaxNGFreeValidCtxt(vctxt); @@ -2506,7 +2506,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, } #ifdef W_OK if (access((char *) filename, W_OK)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Cannot write to %s\n", filename); return (-1); } @@ -2514,7 +2514,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, switch (node->type) { case XML_DOCUMENT_NODE: if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to write to %s\n", filename); return (-1); } @@ -2522,13 +2522,13 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, case XML_HTML_DOCUMENT_NODE: #ifdef LIBXML_HTML_ENABLED if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to write to %s\n", filename); return (-1); } #else if (xmlSaveFile((char *) filename, ctxt->doc) < -1) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to write to %s\n", filename); return (-1); } @@ -2539,7 +2539,7 @@ xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, f = fopen((char *) filename, "w"); if (f == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to write to %s\n", filename); return (-1); } @@ -2575,7 +2575,7 @@ xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, return (-1); #ifdef W_OK if (access((char *) filename, W_OK)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Cannot save to %s\n", filename); return (-1); } @@ -2583,25 +2583,25 @@ xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, switch (ctxt->doc->type) { case XML_DOCUMENT_NODE: if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to save to %s\n", filename); } break; case XML_HTML_DOCUMENT_NODE: #ifdef LIBXML_HTML_ENABLED if (htmlSaveFile((char *) filename, ctxt->doc) < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to save to %s\n", filename); } #else if (xmlSaveFile((char *) filename, ctxt->doc) < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Failed to save to %s\n", filename); } #endif /* LIBXML_HTML_ENABLED */ break; default: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "To save to subparts of a document use the 'write' command\n"); return (-1); @@ -2634,8 +2634,9 @@ xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1); memset(&vctxt, 0, sizeof(vctxt)); - vctxt.error = xmlGenericError; - vctxt.warning = xmlGenericError; + vctxt.error = xmlShellPrintf; + vctxt.warning = xmlShellPrintf; + vctxt.userData = ctxt; if ((dtd == NULL) || (dtd[0] == 0)) { res = xmlValidateDocument(&vctxt, ctxt->doc); @@ -2791,7 +2792,7 @@ xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, * using a environment similar to a UNIX commandline. */ void -xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, +xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input, FILE * output) { char prompt[500] = "/ > "; @@ -2936,22 +2937,13 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlShellSave(ctxt, arg, NULL, NULL); } else if (!strcmp(command, "write")) { if (arg[0] == 0) - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Write command requires a filename argument\n"); else xmlShellWrite(ctxt, arg, ctxt->node, NULL); #endif /* LIBXML_OUTPUT_ENABLED */ } else if (!strcmp(command, "grep")) { xmlShellGrep(ctxt, arg, ctxt->node, NULL); - } else if (!strcmp(command, "free")) { - if (arg[0] == 0) { - xmlMemShow(ctxt->output, 0); - } else { - int len = 0; - - sscanf(arg, "%d", &len); - xmlMemShow(ctxt->output, len); - } } else if (!strcmp(command, "pwd")) { char dir[500]; @@ -2971,7 +2963,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if (list != NULL) { switch (list->type) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); break; case XPATH_NODESET:{ @@ -2989,37 +2981,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, break; } case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an XSLT value tree\n", arg); break; @@ -3028,7 +3020,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlXPathFreeObject(list); #endif } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); } ctxt->pctxt->node = NULL; @@ -3040,7 +3032,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, #ifdef LIBXML_XPATH_ENABLED } else if (!strcmp(command, "setns")) { if (arg[0] == 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "setns: prefix=[nsuri] required\n"); } else { xmlShellRegisterNamespace(ctxt, arg, NULL, NULL); @@ -3052,7 +3044,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL); } else if (!strcmp(command, "xpath")) { if (arg[0] == 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "xpath: expression required\n"); } else { ctxt->pctxt->node = ctxt->node; @@ -3084,7 +3076,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if (list != NULL) { switch (list->type) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); break; case XPATH_NODESET:{ @@ -3108,37 +3100,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, break; } case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an XSLT value tree\n", arg); break; @@ -3147,7 +3139,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlXPathFreeObject(list); #endif } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); } ctxt->pctxt->node = NULL; @@ -3168,7 +3160,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if (list != NULL) { switch (list->type) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); break; case XPATH_NODESET:{ @@ -3187,37 +3179,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, break; } case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an XSLT value tree\n", arg); break; @@ -3226,7 +3218,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlXPathFreeObject(list); #endif } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); } ctxt->pctxt->node = NULL; @@ -3249,7 +3241,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if (list != NULL) { switch (list->type) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); break; case XPATH_NODESET: @@ -3259,52 +3251,52 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if ((ctxt->node != NULL) && (ctxt->node->type == XML_NAMESPACE_DECL)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "cannot cd to namespace\n"); ctxt->node = NULL; } } else - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a %d Node Set\n", arg, list->nodesetval->nodeNr); } else - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an empty Node Set\n", arg); break; case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an XSLT value tree\n", arg); break; @@ -3313,7 +3305,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlXPathFreeObject(list); #endif } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); } ctxt->pctxt->node = NULL; @@ -3333,7 +3325,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, if (list != NULL) { switch (list->type) { case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); break; case XPATH_NODESET:{ @@ -3354,37 +3346,37 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, break; } case XPATH_BOOLEAN: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a Boolean\n", arg); break; case XPATH_NUMBER: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a number\n", arg); break; case XPATH_STRING: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a string\n", arg); break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_POINT: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a point\n", arg); break; case XPATH_RANGE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; case XPATH_LOCATIONSET: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is a range\n", arg); break; #endif /* LIBXML_XPTR_LOCS_ENABLED */ case XPATH_USERS: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is user-defined\n", arg); break; case XPATH_XSLT_TREE: - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s is an XSLT value tree\n", arg); break; @@ -3393,14 +3385,14 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, xmlXPathFreeObject(list); #endif } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "%s: no such node\n", arg); } ctxt->pctxt->node = NULL; } #endif /* LIBXML_OUTPUT_ENABLED */ } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(ctxt->output, "Unknown command %s\n", command); } free(cmdline); /* not xmlFree here ! */ diff --git a/dict.c b/dict.c index d7156ed..7d2be5e 100644 --- a/dict.c +++ b/dict.c @@ -19,11 +19,13 @@ #define IN_LIBXML #include "libxml.h" +#include #include +#include #include -#include #include "private/dict.h" +#include "private/globals.h" #include "private/threads.h" #include @@ -508,6 +510,15 @@ xmlDictHashQName(unsigned seed, const xmlChar *prefix, const xmlChar *name, return(h2 | MAX_HASH_SIZE); } +/** + * xmlDictComputeHash: + * @dict: dictionary + * @string: C string + * + * Compute the hash value of a C string. + * + * Returns the hash value. + */ unsigned xmlDictComputeHash(const xmlDict *dict, const xmlChar *string) { size_t len; @@ -516,6 +527,15 @@ xmlDictComputeHash(const xmlDict *dict, const xmlChar *string) { #define HASH_ROL31(x,n) ((x) << (n) | ((x) & 0x7FFFFFFF) >> (31 - (n))) +/** + * xmlDictCombineHash: + * @v1: first hash value + * @v2: second hash value + * + * Combine two hash values. + * + * Returns the combined hash value. + */ ATTRIBUTE_NO_SANITIZE_INTEGER unsigned xmlDictCombineHash(unsigned v1, unsigned v2) { @@ -904,30 +924,79 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { * Pseudo-random generator */ +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include + #include + #ifdef _MSC_VER + #pragma comment(lib, "bcrypt.lib") + #endif +#elif defined(HAVE_GETENTROPY) + #ifdef HAVE_UNISTD_H + #include + #endif + #ifdef HAVE_SYS_RANDOM_H + #include + #endif +#else + #include +#endif + static xmlMutex xmlRngMutex; static unsigned globalRngState[2]; -#ifdef XML_THREAD_LOCAL -static XML_THREAD_LOCAL int localRngInitialized = 0; -static XML_THREAD_LOCAL unsigned localRngState[2]; -#endif - +/* + * xmlInitRandom: + * + * Initialize the PRNG. + */ ATTRIBUTE_NO_SANITIZE_INTEGER void xmlInitRandom(void) { - int var; - xmlInitMutex(&xmlRngMutex); - /* TODO: Get seed values from system PRNG */ - - globalRngState[0] = (unsigned) time(NULL) ^ - HASH_ROL((unsigned) (size_t) &xmlInitRandom, 8); - globalRngState[1] = HASH_ROL((unsigned) (size_t) &xmlRngMutex, 16) ^ - HASH_ROL((unsigned) (size_t) &var, 24); + { +#ifdef _WIN32 + NTSTATUS status; + + status = BCryptGenRandom(NULL, (unsigned char *) globalRngState, + sizeof(globalRngState), + BCRYPT_USE_SYSTEM_PREFERRED_RNG); + if (!BCRYPT_SUCCESS(status)) { + fprintf(stderr, "libxml2: BCryptGenRandom failed with " + "error code %lu\n", GetLastError()); + abort(); + } +#elif defined(HAVE_GETENTROPY) + while (1) { + if (getentropy(globalRngState, sizeof(globalRngState)) == 0) + break; + + if (errno != EINTR) { + fprintf(stderr, "libxml2: getentropy failed with " + "error code %d\n", errno); + abort(); + } + } +#else + int var; + + globalRngState[0] = + (unsigned) time(NULL) ^ + HASH_ROL((unsigned) ((size_t) &xmlInitRandom & 0xFFFFFFFF), 8); + globalRngState[1] = + HASH_ROL((unsigned) ((size_t) &xmlRngMutex & 0xFFFFFFFF), 16) ^ + HASH_ROL((unsigned) ((size_t) &var & 0xFFFFFFFF), 24); +#endif + } } +/* + * xmlCleanupRandom: + * + * Clean up PRNG globals. + */ void xmlCleanupRandom(void) { xmlCleanupMutex(&xmlRngMutex); @@ -947,19 +1016,15 @@ xoroshiro64ss(unsigned *s) { return(result & 0xFFFFFFFF); } +/* + * xmlGlobalRandom: + * + * Generate a pseudo-random value using the global PRNG. + * + * Returns a random value. + */ unsigned -xmlRandom(void) { -#ifdef XML_THREAD_LOCAL - if (!localRngInitialized) { - xmlMutexLock(&xmlRngMutex); - localRngState[0] = xoroshiro64ss(globalRngState); - localRngState[1] = xoroshiro64ss(globalRngState); - localRngInitialized = 1; - xmlMutexUnlock(&xmlRngMutex); - } - - return(xoroshiro64ss(localRngState)); -#else +xmlGlobalRandom(void) { unsigned ret; xmlMutexLock(&xmlRngMutex); @@ -967,6 +1032,21 @@ xmlRandom(void) { xmlMutexUnlock(&xmlRngMutex); return(ret); +} + +/* + * xmlRandom: + * + * Generate a pseudo-random value using the thread-local PRNG. + * + * Returns a random value. + */ +unsigned +xmlRandom(void) { +#ifdef LIBXML_THREAD_ENABLED + return(xoroshiro64ss(xmlGetLocalRngState())); +#else + return(xmlGlobalRandom()); #endif } diff --git a/distfiles/download.url b/distfiles/download.url index 9bb41de..2682ffb 100644 --- a/distfiles/download.url +++ b/distfiles/download.url @@ -1 +1 @@ -https://download.gnome.org/sources/libxml2/2.12/libxml2-2.12.8.tar.xz +https://download.gnome.org/sources/libxml2/2.13/libxml2-2.13.0.tar.xz diff --git a/distfiles/libxml2-2.12.8-import.md5 b/distfiles/libxml2-2.12.8-import.md5 deleted file mode 100644 index d6ed4f8..0000000 --- a/distfiles/libxml2-2.12.8-import.md5 +++ /dev/null @@ -1,138 +0,0 @@ -fec7ecfe714722b2bb0aaff7d200c701 Copyright -7f7555dd7a030f5150fd0c3c32f7462a HTMLparser.c -ac5d42c343d2093d2a031f59036c5f99 HTMLtree.c -dd63184811cb2ff705c3e466364d3773 INSTALL -bf65af783672f87d344a98c41d010184 NEWS -d52aad5f8ace0ed3e5f9b126d72473e1 README.libxml2.md -7283878f36a935a3c00df077cf45af54 SAX.c -09a9556a3b8677675bd45ba603376aa0 SAX2.c -57a293f421ac339af8ceaf40bfa461a6 buf.c -9de80ca09b5855ff9817f90b741452e4 c14n.c -0d7ba01913e22fd832d634c862fc1716 catalog.c -691708e81dee605336b6ef6e431c5c21 chvalid.c -fa4c7d0b18fba04f8458ed1b21ea563a debugXML.c -d1071113f634435266c21de0bffc0315 dict.c -10a103a4ea5dce7e3906291f958b7e9f encoding.c -83e8ff3c5b69908c4a93357bdc60e91c entities.c -bbb4bd2d42423b727ef64d7ce71611f6 error.c -d9d2840f8f9f3e7f5ca35862bfeebf97 globals.c -33d90ee08788d335c459779c0c5fd6e5 hash.c -c3cd3bf7e9b4c37de582641b614cf6e8 include/libxml/HTMLparser.h -bb4e2df91d33306ab3c2d71374559877 include/libxml/HTMLtree.h -44e6202b2e65e38c48a5cacb75afe5bf include/libxml/SAX.h -2f6eb29ddd29a6380634e0ba4757f102 include/libxml/SAX2.h -dbcef76d0839253958697a919ddeea31 include/libxml/c14n.h -17bea9cec4f3b2fb59a68af652c27ad8 include/libxml/catalog.h -5b94bc432b4ab477a11761182334b646 include/libxml/chvalid.h -79bb0a2a5b7cde377bb215214d0ea6d6 include/libxml/debugXML.h -d00de0e505d1b4dfcccf9ff38837b61a include/libxml/dict.h -e567122520ed052588fd6469f2efbc59 include/libxml/encoding.h -b083ed530f79f607acbc1012281852d7 include/libxml/entities.h -bc51344e21f8d3b7f0fc93cc9d554243 include/libxml/globals.h -480b0bd8dded0583369dd8a4be21d450 include/libxml/hash.h -6c03428a747fbfab599d4e86dd17d6b1 include/libxml/list.h -d5c907a6d7d205e286168e007f32504c include/libxml/nanoftp.h -3f166ef07a961ee21d3561682d859edc include/libxml/nanohttp.h -715cf856fa05e7633b1254edfa0a45f4 include/libxml/parser.h -36c2360e8bdaac08bfccba24e461d07f include/libxml/parserInternals.h -f1afd2d52bf66fbf45f02dc35c72c3eb include/libxml/pattern.h -d752e41ee40c2b028d0adb34ffc38810 include/libxml/relaxng.h -853377a2dbf74e9b0d679dcfcc1859b9 include/libxml/schemasInternals.h -7a163ee849171ffc2471a89704a33643 include/libxml/schematron.h -84310bd67922e532329432f7ab04338c include/libxml/threads.h -8508e1498b7772ae84baf83ddd33b65c include/libxml/tree.h -9e795965522a7b231084cbd5ab089eda include/libxml/uri.h -f26be264a608ed72fb7c74de76e3be72 include/libxml/valid.h -d02d257861d28021ad33dad20e2683c3 include/libxml/xinclude.h -4c7ff0fcbc3595d38f47e41f703dbc61 include/libxml/xlink.h -ef62ebccc685b9bb49f75feab0b2ddd0 include/libxml/xmlIO.h -78602d66c5db00b0deece2c56ab86d43 include/libxml/xmlautomata.h -e3fe66a1c3ca6359481c0a4fa25491c6 include/libxml/xmlerror.h -dc29dad477ae3b1779f8b15fbae14a0d include/libxml/xmlexports.h -8eccb2172800caa343515fc0da596f4c include/libxml/xmlmemory.h -1dda0f8301c72cab8c0015a4f36d008f include/libxml/xmlmodule.h -abf4f7189ba11d03e73e22f9d1662328 include/libxml/xmlreader.h -5f98d803fb4dd3fda837e2f922ce4e6a include/libxml/xmlregexp.h -2183378075a4a69030b3280c1fd2d1c0 include/libxml/xmlsave.h -f4c5548787cac73cd7c6d18a07555393 include/libxml/xmlschemas.h -ac3b6d0c4a6fc4ea9fea5652b46b2992 include/libxml/xmlschemastypes.h -74cf81ae5e6c6b553e49683528d78b6b include/libxml/xmlstring.h -dbc8d631b733e9d36151f71e1230a9df include/libxml/xmlunicode.h -33e2c97626678a66adb889aea827276e include/libxml/xmlwriter.h -416bba8961630e597719243786393e4e include/libxml/xpath.h -348e82b05d463eca3d661e2cc2db9aee include/libxml/xpathInternals.h -74590f782d9b322ce115d1530e6f74d6 include/libxml/xpointer.h -0abe699b64ec5d5776977857ce0f5af1 include/private/buf.h -8ebef62d338f9d16691e061fc1fb5a9b include/private/dict.h -ef188f33103bfaa4728d4d2fb885f67a include/private/enc.h -5c2c0c5dd8609f827bad0dd5949b441e include/private/entities.h -6e7e3b6e29613e28499dcf5e8ba63244 include/private/error.h -40217f6d8ee2331ef3da4c894303d217 include/private/globals.h -75db2838e28a9521292c484ccbb63fed include/private/html.h -cccd6f58b21ed284f20a2063fc11751b include/private/io.h -365385352b21fd09182380def0b8b7b5 include/private/memory.h -8e95420939ee2c4d5f33456e7643d76f include/private/parser.h -6188856c04348a92a5388d5176d7d016 include/private/regexp.h -6c05f0bbe213b8b73b0e1028ba458973 include/private/save.h -3b2905ef972b4faf312b39ceb490464d include/private/string.h -a4976b987498c427b83793894d46fbed include/private/threads.h -87384fd1fad9ab1259cbe92ee072f53d include/private/tree.h -aa8f6d446e70001ea87346a7925aee06 include/private/xinclude.h -a14a170c9fc412f09f0fb980b30f18be include/private/xpath.h -ebdf628f8a0505f16f2e545895e3e7d1 include/private/xzlib.h -e857d2ed47c0848d6f469ebc16ef31f1 include/wsockcompat.h -fd5acf7865455100e3a497f9d4d1d58c legacy.c -c2b5c54ee40fd7bfba8eb6b9e90d6dbd libxml.h -67985a9e0fc42eebc29d12b884baa00a list.c -a9e486124ef2c3a00ecb44001d774484 nanoftp.c -a2c34ca6d295906ebc9b56d8e056bf7a nanohttp.c -ee9f8b57c3ed99928380467f80d7df11 parser.c -5d98a417da5fd6a7f614b6a877c246a9 parserInternals.c -8809dafc22e8463d81a392ac8a853a59 pattern.c -15a40570e75a1cf9f9da7350f9557b86 relaxng.c -b66e180243852be9fa9f97b0722679ba runsuite.c -aec7e53688c694f559010cb2a46f30be runtest.c -feb122dee4d10cb493ca85bbb2162792 runxmlconf.c -fc8947f2849d2f27a30318dc3ca831f5 schematron.c -c48cacc169fbe69e961ceafbfb92ee71 testModule.c -673cbe4047f34b7d954fd597d46b8716 testThreads.c -e85d38ab99ab20ed6649989919e52fbd testapi.c -d665963cfccaa91533d3dfb9f69da42a testchar.c -2792f948169570feeb744ddf0cce5025 testdict.c -6a3e7cbf9864c04639a1a8ac0c388ea2 testdso.c -e84fe8d1a9d8ea089bf9ea8544a6ea1b testlimits.c -c3b4626e621b6abe586944ec0e79351e testparser.c -f9dd10b6caf75faf002e92b703b36897 testrecurse.c -bef5d0bbecbb90f5a441e52bd2f926a2 threads.c -1bcb15667ab695cdd2cc8d5b1bc05169 timsort.h -9abdf46cb6883de83f7bc2e9fbbf717a tree.c -5b543ee91a3c2f2c4fb79e37caa071ea trio.c -8b21aea67b16387f2f61a9f36717cdb9 trio.h -a1e52d4d4c9bcba53027aa2fd65c4eef triodef.h -5a8e54865b5685e0863810556180ef98 trionan.c -0c9b238876ae233fd259092313287d58 trionan.h -e79fa3e246145ff28ae6ee96c797b78c triop.h -ae2f0b85a98ac525c8a215e509ac63b1 triostr.c -b93afcad9107d48ce7e66b84db7159c7 triostr.h -eac8b302c12669b0ec1b15afd912dcdf uri.c -fd3d55b1d9817a9ef205f35b1d60f527 valid.c -8ab2045fb3bb5553449a93c85ebbb58a win32/config.h -9ca0965eeabe09b4f8d9a1c6c5d8c3b0 win32/libxml2.rc -27b6a7946ac148c1f96755bf442ef0f4 xinclude.c -0a034450d155e35ec8ba99ee2005b695 xlink.c -ec9a5e17f4cb2e520e10f5a2d6fc71fc xmlIO.c -28bb81f9966d3ec48c510dd56fa10b94 xmlcatalog.c -19ebfd8c205fae4022bb30d387831a36 xmllint.c -47188d0524f25fdb396703aa6d5e1fd6 xmlmemory.c -096b464ed7bd0decd5a9a6d209f0fabd xmlmodule.c -6e71ac671a381c09cbc398e47e5ba33a xmlreader.c -976c32247397c82331e8621977613ea4 xmlregexp.c -419d628dc26e76442a30f4797c770a80 xmlsave.c -c6a6f950f16ba8d1e15ae0d384b259ca xmlschemas.c -906205b67f1d974598edee0322e3c234 xmlschemastypes.c -7b87ec18a05dfab6a30e1c3667d7edee xmlstring.c -c9097be7e143f99684f19d937a775144 xmlunicode.c -110e6d33af683f1b6b04bb53bfe6bb27 xmlwriter.c -4811ad2391b3697581d9045a9ad0fcfb xpath.c -2f6ca95b7ee6583b611f2f2b7e566579 xpointer.c -4f1552a87445e82f1c918eabd97479f1 xzlib.c diff --git a/distfiles/libxml2-2.12.8.tar.xz b/distfiles/libxml2-2.12.8.tar.xz deleted file mode 100644 index 586f0d2..0000000 Binary files a/distfiles/libxml2-2.12.8.tar.xz and /dev/null differ diff --git a/distfiles/libxml2-2.12.8-import.lst b/distfiles/libxml2-2.13.0-import.lst similarity index 96% rename from distfiles/libxml2-2.12.8-import.lst rename to distfiles/libxml2-2.13.0-import.lst index 1edb306..1e114aa 100644 --- a/distfiles/libxml2-2.12.8-import.lst +++ b/distfiles/libxml2-2.13.0-import.lst @@ -106,14 +106,6 @@ testrecurse.c threads.c timsort.h tree.c -trio.c -trio.h -triodef.h -trionan.c -trionan.h -triop.h -triostr.c -triostr.h uri.c valid.c win32/config.h diff --git a/distfiles/libxml2-2.13.0-import.md5 b/distfiles/libxml2-2.13.0-import.md5 new file mode 100644 index 0000000..44dea8b --- /dev/null +++ b/distfiles/libxml2-2.13.0-import.md5 @@ -0,0 +1,130 @@ +f437ed9058e8e5135e47c01e973376ba Copyright +16f41a2c516aa0db1295fd935164345c HTMLparser.c +d04a2b2879cb84c5c3a195c2d444b335 HTMLtree.c +dd63184811cb2ff705c3e466364d3773 INSTALL +516fcfeaa16a8f29342699b27202859d NEWS +5f32c16a4eccf442197b65fa65f3c7b8 README.libxml2.md +7283878f36a935a3c00df077cf45af54 SAX.c +4bb688a8949366334e6803484a0db05b SAX2.c +67a65054d57590e61fdb1e70d2ea5a96 buf.c +4b44ee7f5a69c1058b5e78cecd37a15c c14n.c +b86dee5a15a23fcae795b2fb2544b8dc catalog.c +691708e81dee605336b6ef6e431c5c21 chvalid.c +697a63537714f6d73508f642b8caf24b debugXML.c +08d37f8cc00ce8576a00dd2c2725ffe3 dict.c +c9a558a311456f1df0ce4da7fec493ca encoding.c +74aea6c1f67db19f14a4ea658caabb50 entities.c +1614814772ec00261f6c68dbb3fb2e87 error.c +4a0ab9ada11a64828012376799576cfa globals.c +d8e4da290e7f5ca784452d2ba5f65789 hash.c +c0e828b83cec6c6c1e8ebd53a8ce1de4 include/libxml/HTMLparser.h +bb4e2df91d33306ab3c2d71374559877 include/libxml/HTMLtree.h +44e6202b2e65e38c48a5cacb75afe5bf include/libxml/SAX.h +2f6eb29ddd29a6380634e0ba4757f102 include/libxml/SAX2.h +eeca649010f9bdc2a60b069766e030ab include/libxml/c14n.h +17bea9cec4f3b2fb59a68af652c27ad8 include/libxml/catalog.h +5b94bc432b4ab477a11761182334b646 include/libxml/chvalid.h +63619fe1dbd8ae82c1040d7df0c7eb6e include/libxml/debugXML.h +d00de0e505d1b4dfcccf9ff38837b61a include/libxml/dict.h +8d3a048f503607ca9fbdc63bfa27d02e include/libxml/encoding.h +8821188af2534b982d91cb73cf9a4c96 include/libxml/entities.h +bc51344e21f8d3b7f0fc93cc9d554243 include/libxml/globals.h +637596e31cab013c73d81e02a31a5b65 include/libxml/hash.h +90371c7017be1221a0c4d20089ade92a include/libxml/list.h +d5c907a6d7d205e286168e007f32504c include/libxml/nanoftp.h +95b1e4eadd008ebd16424f0f47213062 include/libxml/nanohttp.h +d863425ee6d4ffe90f7af8532d194095 include/libxml/parser.h +b0d1746c566f0a4e1c368d6b1f734564 include/libxml/parserInternals.h +dfa0e955ce14744df32c8a050c5ee84a include/libxml/pattern.h +d752e41ee40c2b028d0adb34ffc38810 include/libxml/relaxng.h +853377a2dbf74e9b0d679dcfcc1859b9 include/libxml/schemasInternals.h +7a163ee849171ffc2471a89704a33643 include/libxml/schematron.h +84310bd67922e532329432f7ab04338c include/libxml/threads.h +ab717587b70618c1482aaead02514ff5 include/libxml/tree.h +d08bbbc90b3d1d31309fd93c9681390f include/libxml/uri.h +6dc6a9c1e7a9c651d38e34f6b336c2fc include/libxml/valid.h +cf36fb20efcb8e5ad770e1d7ac858910 include/libxml/xinclude.h +4c7ff0fcbc3595d38f47e41f703dbc61 include/libxml/xlink.h +0971aca35e60af238343eb745771c0d5 include/libxml/xmlIO.h +78602d66c5db00b0deece2c56ab86d43 include/libxml/xmlautomata.h +04fa9aa45df384fe962db1a14fb59553 include/libxml/xmlerror.h +225d59fc76e039255b1c6aa3f15771b7 include/libxml/xmlexports.h +13b117b714ad87f0fb17d302d9580cf3 include/libxml/xmlmemory.h +1dda0f8301c72cab8c0015a4f36d008f include/libxml/xmlmodule.h +288e26a1a1b1e495a463ff90b7d243d7 include/libxml/xmlreader.h +5f98d803fb4dd3fda837e2f922ce4e6a include/libxml/xmlregexp.h +f48903903819d60b25e6faf03c8161e3 include/libxml/xmlsave.h +f4c5548787cac73cd7c6d18a07555393 include/libxml/xmlschemas.h +ac3b6d0c4a6fc4ea9fea5652b46b2992 include/libxml/xmlschemastypes.h +74cf81ae5e6c6b553e49683528d78b6b include/libxml/xmlstring.h +157b92f46696fd22d89f7250de7e30ec include/libxml/xmlunicode.h +237a31e0b6328115ed5c1673138615e6 include/libxml/xmlwriter.h +3bbf2dc32947c6f1a6f7cd0da788d86a include/libxml/xpath.h +348e82b05d463eca3d661e2cc2db9aee include/libxml/xpathInternals.h +74590f782d9b322ce115d1530e6f74d6 include/libxml/xpointer.h +238e603990de2fbc5f05e46331be9cb4 include/private/buf.h +1dc45f80ded4ff83027aed7c84091d9d include/private/dict.h +ef188f33103bfaa4728d4d2fb885f67a include/private/enc.h +2c7f255c7af500c08d19cfb53087a4f4 include/private/entities.h +bef80badd674ff57e922a7ab5774674b include/private/error.h +d2eb48f52daec99534d38aef2bdbf201 include/private/globals.h +75db2838e28a9521292c484ccbb63fed include/private/html.h +d6f456de62fd2c94214ebbaab1ea3f7c include/private/io.h +365385352b21fd09182380def0b8b7b5 include/private/memory.h +0db2d8833876738d1a065fbef3231ed5 include/private/parser.h +11c849f3c342b0587c20ac44037e0efa include/private/regexp.h +ba3898fbcbfb81535dbb16c7fdeaaaf7 include/private/save.h +f80f9d5ff71ecd8a4763478227748544 include/private/string.h +a4976b987498c427b83793894d46fbed include/private/threads.h +80d8cfec33f517cb7fe9753c7d7d5c52 include/private/tree.h +aa8f6d446e70001ea87346a7925aee06 include/private/xinclude.h +fbf5b733beada0f7a1eb01c2df5a0b78 include/private/xpath.h +78ce4d27f7df28823e8d7ab368d123a6 include/private/xzlib.h +e857d2ed47c0848d6f469ebc16ef31f1 include/wsockcompat.h +cdbcf52ea11b6ee99454e3b9a3adeaac legacy.c +9a9c078482f505d50c1235f918d334bd libxml.h +62f33a8621e3442770fd15a540a7eba0 list.c +040942573dbd47e7188991ab3c9c9a99 nanoftp.c +4c676ca8672af9c242eab69fb9e2056f nanohttp.c +cae11ea48cd0e72f5ce5b6fbc4c6636c parser.c +3c13537789e87f0a1c8a6a54a943fa84 parserInternals.c +fc88d174a7b70de62c609c32ce3f55f8 pattern.c +06b7f056c759cff032979e0075c5b318 relaxng.c +371edae07b81c37668065294e77dedcd runsuite.c +7812bd8b322311a772526b9904ab18ed runtest.c +8fa00f5991a396805fac801084d67aca runxmlconf.c +ed005321a17c5795e51e10c384c1f5d9 schematron.c +c48cacc169fbe69e961ceafbfb92ee71 testModule.c +673cbe4047f34b7d954fd597d46b8716 testThreads.c +37a4c872a13c70c1e13022f12d21614b testapi.c +5a234e72bb26f3f42c86c630cef998f3 testchar.c +8efef0b6535d6c069678e9f6750d3742 testdict.c +6a3e7cbf9864c04639a1a8ac0c388ea2 testdso.c +e7f8098f4a9e147624c3cf7d652a70c0 testlimits.c +ac0599e08f02704f5d7db1e36134248f testparser.c +71ea68a83739869caba574c1725fba96 testrecurse.c +d746403de87ca28dbb43a4a76e63a3d6 threads.c +1bcb15667ab695cdd2cc8d5b1bc05169 timsort.h +f4cb2dec0f55e6bd9c20dbd1ae562759 tree.c +7be25cd62649ec06302c67a0dbdcccc7 uri.c +e1828d328a36cd0eea27256123122946 valid.c +8ab2045fb3bb5553449a93c85ebbb58a win32/config.h +9ca0965eeabe09b4f8d9a1c6c5d8c3b0 win32/libxml2.rc +9e1d1292d776b102e1ad735144d52e48 xinclude.c +0a034450d155e35ec8ba99ee2005b695 xlink.c +e98f05954ecf94bbbf9438b995ff30bd xmlIO.c +28bb81f9966d3ec48c510dd56fa10b94 xmlcatalog.c +7eeb0736114d53f08e4be4d611e579dd xmllint.c +9a191c58eb3f035c795898caea8e689b xmlmemory.c +9d8d0df11b80a714e97da726359977dc xmlmodule.c +0e186abcab75a69ea5c5b144834a88b6 xmlreader.c +fda6796d6766ba055664f2993eca5ed7 xmlregexp.c +35a26cd93568987405da54e9279d1359 xmlsave.c +7ad15c4a469cee12b90af8115dd76b5e xmlschemas.c +991c4949ca7a25c99a7beff8e7516915 xmlschemastypes.c +82c2b7394f560d8af467b779026d3972 xmlstring.c +c9097be7e143f99684f19d937a775144 xmlunicode.c +a8ab2ac1eb6a00dccdae814c1cfcea68 xmlwriter.c +640161b959d6c0b89b5ca3c57e841436 xpath.c +dcf0c2434204059b5d6f03346dec1004 xpointer.c +8798ea780f20ac559991cf1710c29087 xzlib.c diff --git a/distfiles/libxml2-2.13.0.tar.xz b/distfiles/libxml2-2.13.0.tar.xz new file mode 100644 index 0000000..4fa0fab Binary files /dev/null and b/distfiles/libxml2-2.13.0.tar.xz differ diff --git a/encoding.c b/encoding.c index bc2772d..04c24e4 100644 --- a/encoding.c +++ b/encoding.c @@ -71,57 +71,6 @@ static int xmlCharEncodingAliasesMax = 0; static int xmlLittleEndian = 1; -#ifdef LIBXML_ICU_ENABLED -static uconv_t* -openIcuConverter(const char* name, int toUnicode) -{ - UErrorCode status = U_ZERO_ERROR; - uconv_t *conv = (uconv_t *) xmlMalloc(sizeof(uconv_t)); - if (conv == NULL) - return NULL; - - conv->pivot_source = conv->pivot_buf; - conv->pivot_target = conv->pivot_buf; - - conv->uconv = ucnv_open(name, &status); - if (U_FAILURE(status)) - goto error; - - status = U_ZERO_ERROR; - if (toUnicode) { - ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP, - NULL, NULL, NULL, &status); - } - else { - ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP, - NULL, NULL, NULL, &status); - } - if (U_FAILURE(status)) - goto error; - - status = U_ZERO_ERROR; - conv->utf8 = ucnv_open("UTF-8", &status); - if (U_SUCCESS(status)) - return conv; - -error: - if (conv->uconv) - ucnv_close(conv->uconv); - xmlFree(conv); - return NULL; -} - -static void -closeIcuConverter(uconv_t *conv) -{ - if (conv != NULL) { - ucnv_close(conv->uconv); - ucnv_close(conv->utf8); - xmlFree(conv); - } -} -#endif /* LIBXML_ICU_ENABLED */ - /************************************************************************ * * * Conversions To/From UTF8 encoding * @@ -1374,6 +1323,8 @@ static const xmlCharEncodingHandler defaultHandlers[] = { static const xmlCharEncodingHandler *xmlUTF16LEHandler = &defaultHandlers[1]; static const xmlCharEncodingHandler *xmlUTF16BEHandler = &defaultHandlers[2]; +static const xmlCharEncodingHandler *xmlLatin1Handler = &defaultHandlers[4]; +static const xmlCharEncodingHandler *xmlAsciiHandler = &defaultHandlers[5]; /* the size should be growable, but it's not a big deal ... */ #define MAX_ENCODING_HANDLERS 50 @@ -1535,162 +1486,460 @@ xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) { } } +#ifdef LIBXML_ICONV_ENABLED +static int +xmlCreateIconvHandler(const char *name, xmlCharEncodingHandler **out) { + xmlCharEncodingHandlerPtr enc = NULL; + iconv_t icv_in = (iconv_t) -1; + iconv_t icv_out = (iconv_t) -1; + int ret; + + *out = NULL; + + icv_in = iconv_open("UTF-8", name); + if (icv_in == (iconv_t) -1) { + if (errno == EINVAL) + ret = XML_ERR_UNSUPPORTED_ENCODING; + else if (errno == ENOMEM) + ret = XML_ERR_NO_MEMORY; + else + ret = XML_ERR_SYSTEM; + goto error; + } + + icv_out = iconv_open(name, "UTF-8"); + if (icv_out == (iconv_t) -1) { + if (errno == EINVAL) + ret = XML_ERR_UNSUPPORTED_ENCODING; + else if (errno == ENOMEM) + ret = XML_ERR_NO_MEMORY; + else + ret = XML_ERR_SYSTEM; + goto error; + } + + enc = xmlMalloc(sizeof(*enc)); + if (enc == NULL) { + ret = XML_ERR_NO_MEMORY; + goto error; + } + memset(enc, 0, sizeof(*enc)); + + enc->name = xmlMemStrdup(name); + if (enc->name == NULL) { + ret = XML_ERR_NO_MEMORY; + goto error; + } + enc->iconv_in = icv_in; + enc->iconv_out = icv_out; + + *out = enc; + return(0); + +error: + if (enc != NULL) + xmlFree(enc); + if (icv_in != (iconv_t) -1) + iconv_close(icv_in); + if (icv_out != (iconv_t) -1) + iconv_close(icv_out); + return(ret); +} +#endif /* LIBXML_ICONV_ENABLED */ + +#ifdef LIBXML_ICU_ENABLED +static int +openIcuConverter(const char* name, int toUnicode, uconv_t **out) +{ + UErrorCode status; + uconv_t *conv; + + *out = NULL; + + conv = (uconv_t *) xmlMalloc(sizeof(uconv_t)); + if (conv == NULL) + return(XML_ERR_NO_MEMORY); + + conv->pivot_source = conv->pivot_buf; + conv->pivot_target = conv->pivot_buf; + + status = U_ZERO_ERROR; + conv->uconv = ucnv_open(name, &status); + if (U_FAILURE(status)) + goto error; + + status = U_ZERO_ERROR; + if (toUnicode) { + ucnv_setToUCallBack(conv->uconv, UCNV_TO_U_CALLBACK_STOP, + NULL, NULL, NULL, &status); + } + else { + ucnv_setFromUCallBack(conv->uconv, UCNV_FROM_U_CALLBACK_STOP, + NULL, NULL, NULL, &status); + } + if (U_FAILURE(status)) + goto error; + + status = U_ZERO_ERROR; + conv->utf8 = ucnv_open("UTF-8", &status); + if (U_FAILURE(status)) + goto error; + + *out = conv; + return(0); + +error: + if (conv->uconv) + ucnv_close(conv->uconv); + xmlFree(conv); + + if (status == U_FILE_ACCESS_ERROR) + return(XML_ERR_UNSUPPORTED_ENCODING); + if (status == U_MEMORY_ALLOCATION_ERROR) + return(XML_ERR_NO_MEMORY); + return(XML_ERR_SYSTEM); +} + +static void +closeIcuConverter(uconv_t *conv) +{ + if (conv == NULL) + return; + ucnv_close(conv->uconv); + ucnv_close(conv->utf8); + xmlFree(conv); +} + +static int +xmlCreateUconvHandler(const char *name, xmlCharEncodingHandler **out) { + xmlCharEncodingHandlerPtr enc = NULL; + uconv_t *ucv_in = NULL; + uconv_t *ucv_out = NULL; + int ret; + + ret = openIcuConverter(name, 1, &ucv_in); + if (ret != 0) + goto error; + ret = openIcuConverter(name, 0, &ucv_out); + if (ret != 0) + goto error; + + enc = (xmlCharEncodingHandlerPtr) + xmlMalloc(sizeof(xmlCharEncodingHandler)); + if (enc == NULL) { + ret = XML_ERR_NO_MEMORY; + goto error; + } + memset(enc, 0, sizeof(xmlCharEncodingHandler)); + + enc->name = xmlMemStrdup(name); + if (enc->name == NULL) { + ret = XML_ERR_NO_MEMORY; + goto error; + } + enc->input = NULL; + enc->output = NULL; + enc->uconv_in = ucv_in; + enc->uconv_out = ucv_out; + + *out = enc; + return(0); + +error: + if (enc != NULL) + xmlFree(enc); + if (ucv_in != NULL) + closeIcuConverter(ucv_in); + if (ucv_out != NULL) + closeIcuConverter(ucv_out); + return(ret); +} +#endif /* LIBXML_ICU_ENABLED */ + /** - * xmlGetCharEncodingHandler: + * xmlFindExtraHandler: + * @name: a string describing the char encoding. + * @output: boolean, use handler for output + * @out: pointer to resulting handler + * + * Search the non-default handlers for an exact match. + * + * Returns 0 on success, 1 if no handler was found, -1 if a memory + * allocation failed. + */ +static int +xmlFindExtraHandler(const char *name, int output, + xmlCharEncodingHandler **out) { + int ret; + int i; + + (void) ret; + + if (handlers != NULL) { + for (i = 0; i < nbCharEncodingHandler; i++) { + xmlCharEncodingHandler *handler = handlers[i]; + + if (!xmlStrcasecmp((const xmlChar *) name, + (const xmlChar *) handler->name)) { + if (output) { + if (handler->output != NULL) { + *out = handler; + return(0); + } + } else { + if (handler->input != NULL) { + *out = handler; + return(0); + } + } + } + } + } + +#ifdef LIBXML_ICONV_ENABLED + ret = xmlCreateIconvHandler(name, out); + if (*out != NULL) + return(0); + if (ret != XML_ERR_UNSUPPORTED_ENCODING) + return(ret); +#endif /* LIBXML_ICONV_ENABLED */ + +#ifdef LIBXML_ICU_ENABLED + ret = xmlCreateUconvHandler(name, out); + if (*out != NULL) + return(0); + if (ret != XML_ERR_UNSUPPORTED_ENCODING) + return(ret); +#endif /* LIBXML_ICU_ENABLED */ + + return(XML_ERR_UNSUPPORTED_ENCODING); +} + +/** + * xmlFindHandler: + * @name: a string describing the char encoding. + * @output: boolean, use handler for output + * @out: pointer to resulting handler + * + * Search all handlers for an exact match. + * + * Returns 0 on success, 1 if no handler was found, -1 if a memory + * allocation failed. + */ +static int +xmlFindHandler(const char *name, int output, xmlCharEncodingHandler **out) { + int i; + + /* + * Check for default handlers + */ + for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) { + xmlCharEncodingHandler *handler; + + handler = (xmlCharEncodingHandler *) &defaultHandlers[i]; + + if (xmlStrcasecmp((const xmlChar *) name, + (const xmlChar *) handler->name) == 0) { + if (output) { + if (handler->output != NULL) { + *out = handler; + return(0); + } + } else { + if (handler->input != NULL) { + *out = handler; + return(0); + } + } + } + } + + /* + * Check for other handlers + */ + return(xmlFindExtraHandler(name, output, out)); +} + +/** + * xmlLookupCharEncodingHandler: * @enc: an xmlCharEncoding value. + * @out: pointer to result + * + * Find or create a handler matching the encoding. If no default or + * registered handler could be found, try to create a handler using + * iconv or ICU if supported. * - * Search in the registered set the handler able to read/write that encoding. + * The handler must be closed with xmlCharEncCloseFunc. * - * Returns the handler or NULL if not found + * Available since 2.13.0. + * + * Returns an xmlParserErrors error code. */ -xmlCharEncodingHandlerPtr -xmlGetCharEncodingHandler(xmlCharEncoding enc) { - xmlCharEncodingHandlerPtr handler; +int +xmlLookupCharEncodingHandler(xmlCharEncoding enc, + xmlCharEncodingHandler **out) { + const char *name = NULL; + static const char *const ebcdicNames[] = { + "EBCDIC", "ebcdic", "EBCDIC-US", "IBM-037" + }; + static const char *const ucs4Names[] = { + "ISO-10646-UCS-4", "UCS-4", "UCS4" + }; + static const char *const ucs2Names[] = { + "ISO-10646-UCS-2", "UCS-2", "UCS2" + }; + static const char *const shiftJisNames[] = { + "SHIFT-JIS", "SHIFT_JIS", "Shift_JIS", + }; + const char *const *names = NULL; + int numNames = 0; + int ret; + int i; + + if (out == NULL) + return(XML_ERR_ARGUMENT); + *out = NULL; switch (enc) { case XML_CHAR_ENCODING_ERROR: - return(NULL); + return(XML_ERR_UNSUPPORTED_ENCODING); case XML_CHAR_ENCODING_NONE: - return(NULL); + return(0); case XML_CHAR_ENCODING_UTF8: - return(NULL); + return(0); case XML_CHAR_ENCODING_UTF16LE: - return((xmlCharEncodingHandlerPtr) xmlUTF16LEHandler); + *out = (xmlCharEncodingHandler *) xmlUTF16LEHandler; + return(0); case XML_CHAR_ENCODING_UTF16BE: - return((xmlCharEncodingHandlerPtr) xmlUTF16BEHandler); + *out = (xmlCharEncodingHandler *) xmlUTF16BEHandler; + return(0); case XML_CHAR_ENCODING_EBCDIC: - handler = xmlFindCharEncodingHandler("EBCDIC"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("ebcdic"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("EBCDIC-US"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("IBM-037"); - if (handler != NULL) return(handler); + names = ebcdicNames; + numNames = sizeof(ebcdicNames) / sizeof(ebcdicNames[0]); break; case XML_CHAR_ENCODING_UCS4BE: - handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS-4"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS4"); - if (handler != NULL) return(handler); - break; case XML_CHAR_ENCODING_UCS4LE: - handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS-4"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS4"); - if (handler != NULL) return(handler); + names = ucs4Names; + numNames = sizeof(ucs4Names) / sizeof(ucs4Names[0]); break; case XML_CHAR_ENCODING_UCS4_2143: break; case XML_CHAR_ENCODING_UCS4_3412: break; case XML_CHAR_ENCODING_UCS2: - handler = xmlFindCharEncodingHandler("ISO-10646-UCS-2"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS-2"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("UCS2"); - if (handler != NULL) return(handler); + names = ucs2Names; + numNames = sizeof(ucs2Names) / sizeof(ucs2Names[0]); break; - /* - * We used to keep ISO Latin encodings native in the - * generated data. This led to so many problems that - * this has been removed. One can still change this - * back by registering no-ops encoders for those - */ + case XML_CHAR_ENCODING_ASCII: + *out = (xmlCharEncodingHandler *) xmlAsciiHandler; + return(0); case XML_CHAR_ENCODING_8859_1: - handler = xmlFindCharEncodingHandler("ISO-8859-1"); - if (handler != NULL) return(handler); - break; + *out = (xmlCharEncodingHandler *) xmlLatin1Handler; + return(0); case XML_CHAR_ENCODING_8859_2: - handler = xmlFindCharEncodingHandler("ISO-8859-2"); - if (handler != NULL) return(handler); + name = "ISO-8859-2"; break; case XML_CHAR_ENCODING_8859_3: - handler = xmlFindCharEncodingHandler("ISO-8859-3"); - if (handler != NULL) return(handler); + name = "ISO-8859-3"; break; case XML_CHAR_ENCODING_8859_4: - handler = xmlFindCharEncodingHandler("ISO-8859-4"); - if (handler != NULL) return(handler); + name = "ISO-8859-4"; break; case XML_CHAR_ENCODING_8859_5: - handler = xmlFindCharEncodingHandler("ISO-8859-5"); - if (handler != NULL) return(handler); + name = "ISO-8859-5"; break; case XML_CHAR_ENCODING_8859_6: - handler = xmlFindCharEncodingHandler("ISO-8859-6"); - if (handler != NULL) return(handler); + name = "ISO-8859-6"; break; case XML_CHAR_ENCODING_8859_7: - handler = xmlFindCharEncodingHandler("ISO-8859-7"); - if (handler != NULL) return(handler); + name = "ISO-8859-7"; break; case XML_CHAR_ENCODING_8859_8: - handler = xmlFindCharEncodingHandler("ISO-8859-8"); - if (handler != NULL) return(handler); + name = "ISO-8859-8"; break; case XML_CHAR_ENCODING_8859_9: - handler = xmlFindCharEncodingHandler("ISO-8859-9"); - if (handler != NULL) return(handler); + name = "ISO-8859-9"; break; - case XML_CHAR_ENCODING_2022_JP: - handler = xmlFindCharEncodingHandler("ISO-2022-JP"); - if (handler != NULL) return(handler); + name = "ISO-2022-JP"; break; case XML_CHAR_ENCODING_SHIFT_JIS: - handler = xmlFindCharEncodingHandler("SHIFT-JIS"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("SHIFT_JIS"); - if (handler != NULL) return(handler); - handler = xmlFindCharEncodingHandler("Shift_JIS"); - if (handler != NULL) return(handler); + names = shiftJisNames; + numNames = sizeof(shiftJisNames) / sizeof(shiftJisNames[0]); break; case XML_CHAR_ENCODING_EUC_JP: - handler = xmlFindCharEncodingHandler("EUC-JP"); - if (handler != NULL) return(handler); + name = "EUC-JP"; break; default: break; } - return(NULL); + if (name != NULL) + return(xmlFindExtraHandler(name, 0, out)); + + if (names != NULL) { + for (i = 0; i < numNames; i++) { + ret = xmlFindExtraHandler(names[i], 0, out); + if (*out != NULL) + return(0); + if (ret != XML_ERR_UNSUPPORTED_ENCODING) + return(ret); + } + } + + return(XML_ERR_UNSUPPORTED_ENCODING); } /** - * xmlFindCharEncodingHandler: - * @name: a string describing the char encoding. + * xmlGetCharEncodingHandler: + * @enc: an xmlCharEncoding value. * - * Search in the registered set the handler able to read/write that encoding - * or create a new one. + * DEPRECATED: Use xmlLookupCharEncodingHandler which has better error + * reporting. * - * Returns the handler or NULL if not found + * Returns the handler or NULL if no handler was found or an error + * occurred. */ xmlCharEncodingHandlerPtr -xmlFindCharEncodingHandler(const char *name) { +xmlGetCharEncodingHandler(xmlCharEncoding enc) { + xmlCharEncodingHandler *ret; + + xmlLookupCharEncodingHandler(enc, &ret); + return(ret); +} + +/** + * xmlOpenCharEncodingHandler: + * @name: a string describing the char encoding. + * @output: boolean, use handler for output + * @out: pointer to result + * + * Find or create a handler matching the encoding. If no default or + * registered handler could be found, try to create a handler using + * iconv or ICU if supported. + * + * The handler must be closed with xmlCharEncCloseFunc. + * + * Available since 2.13.0. + * + * Returns an xmlParserErrors error code. + */ +int +xmlOpenCharEncodingHandler(const char *name, int output, + xmlCharEncodingHandler **out) { const char *nalias; const char *norig; - xmlCharEncoding alias; -#ifdef LIBXML_ICONV_ENABLED - xmlCharEncodingHandlerPtr enc; - iconv_t icv_in, icv_out; -#endif /* LIBXML_ICONV_ENABLED */ -#ifdef LIBXML_ICU_ENABLED - xmlCharEncodingHandlerPtr encu; - uconv_t *ucv_in, *ucv_out; -#endif /* LIBXML_ICU_ENABLED */ - char upper[100]; - int i; + xmlCharEncoding enc; + int ret; + + if (out == NULL) + return(XML_ERR_ARGUMENT); + *out = NULL; - if (name == NULL) return(NULL); - if (name[0] == 0) return(NULL); + if (name == NULL) + return(XML_ERR_ARGUMENT); /* * Do the alias resolution @@ -1700,111 +1949,35 @@ xmlFindCharEncodingHandler(const char *name) { if (nalias != NULL) name = nalias; - /* - * Check first for directly registered encoding names - */ - for (i = 0;i < 99;i++) { - upper[i] = (char) toupper((unsigned char) name[i]); - if (upper[i] == 0) break; - } - upper[i] = 0; - - for (i = 0; i < (int) NUM_DEFAULT_HANDLERS; i++) { - if (strcmp(upper, defaultHandlers[i].name) == 0) - return((xmlCharEncodingHandlerPtr) &defaultHandlers[i]); - } - - if (handlers != NULL) { - for (i = 0;i < nbCharEncodingHandler; i++) { - if (!strcmp(upper, handlers[i]->name)) { - return(handlers[i]); - } - } - } - -#ifdef LIBXML_ICONV_ENABLED - /* check whether iconv can handle this */ - icv_in = iconv_open("UTF-8", name); - icv_out = iconv_open(name, "UTF-8"); - if (icv_in == (iconv_t) -1) { - icv_in = iconv_open("UTF-8", upper); - } - if (icv_out == (iconv_t) -1) { - icv_out = iconv_open(upper, "UTF-8"); - } - if ((icv_in != (iconv_t) -1) && (icv_out != (iconv_t) -1)) { - enc = (xmlCharEncodingHandlerPtr) - xmlMalloc(sizeof(xmlCharEncodingHandler)); - if (enc == NULL) { - iconv_close(icv_in); - iconv_close(icv_out); - return(NULL); - } - memset(enc, 0, sizeof(xmlCharEncodingHandler)); - enc->name = xmlMemStrdup(name); - if (enc->name == NULL) { - xmlFree(enc); - iconv_close(icv_in); - iconv_close(icv_out); - return(NULL); - } - enc->input = NULL; - enc->output = NULL; - enc->iconv_in = icv_in; - enc->iconv_out = icv_out; - return enc; - } else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) { - if (icv_in != (iconv_t) -1) - iconv_close(icv_in); - else - iconv_close(icv_out); - } -#endif /* LIBXML_ICONV_ENABLED */ -#ifdef LIBXML_ICU_ENABLED - /* check whether icu can handle this */ - ucv_in = openIcuConverter(name, 1); - ucv_out = openIcuConverter(name, 0); - if (ucv_in != NULL && ucv_out != NULL) { - encu = (xmlCharEncodingHandlerPtr) - xmlMalloc(sizeof(xmlCharEncodingHandler)); - if (encu == NULL) { - closeIcuConverter(ucv_in); - closeIcuConverter(ucv_out); - return(NULL); - } - memset(encu, 0, sizeof(xmlCharEncodingHandler)); - encu->name = xmlMemStrdup(name); - if (encu->name == NULL) { - xmlFree(encu); - closeIcuConverter(ucv_in); - closeIcuConverter(ucv_out); - return(NULL); - } - encu->input = NULL; - encu->output = NULL; - encu->uconv_in = ucv_in; - encu->uconv_out = ucv_out; - return encu; - } else if (ucv_in != NULL || ucv_out != NULL) { - closeIcuConverter(ucv_in); - closeIcuConverter(ucv_out); - } -#endif /* LIBXML_ICU_ENABLED */ + ret = xmlFindHandler(name, output, out); + if (*out != NULL) + return(0); + if (ret != XML_ERR_UNSUPPORTED_ENCODING) + return(ret); /* * Fallback using the canonical names */ - alias = xmlParseCharEncoding(norig); - if (alias != XML_CHAR_ENCODING_ERROR) { - const char* canon; - canon = xmlGetCharEncodingName(alias); - if ((canon != NULL) && (strcmp(name, canon))) { - return(xmlFindCharEncodingHandler(canon)); - } - } + enc = xmlParseCharEncoding(norig); + return(xmlLookupCharEncodingHandler(enc, out)); +} - /* If "none of the above", give up */ - return(NULL); +/** + * xmlFindCharEncodingHandler: + * @name: a string describing the char encoding. + * + * DEPRECATED: Use xmlOpenCharEncodingHandler which has better error + * reporting. + * + * Returns the handler or NULL if no handler was found or an error + * occurred. + */ +xmlCharEncodingHandlerPtr +xmlFindCharEncodingHandler(const char *name) { + xmlCharEncodingHandler *ret; + + xmlOpenCharEncodingHandler(name, 0, &ret); + return(ret); } /************************************************************************ @@ -2169,7 +2342,8 @@ xmlCharEncInput(xmlParserInputBufferPtr input) else input->rawconsumed += c_in; - if ((c_out == 0) && (ret != 0)) { + if (((ret != 0) && (c_out == 0)) || + (ret == XML_ENC_ERR_MEMORY)) { if (input->error == 0) input->error = xmlEncConvertError(ret); return(ret); @@ -2277,7 +2451,10 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init) if (toconv > 64 * 1024) toconv = 64 * 1024; if (toconv * 4 >= written) { - xmlBufGrow(out, toconv * 4); + if (xmlBufGrow(out, toconv * 4) < 0) { + ret = XML_ENC_ERR_MEMORY; + goto error; + } written = xmlBufAvail(out); } if (written > 256 * 1024) @@ -2314,7 +2491,6 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init) */ charrefLen = snprintf((char *) &charref[0], sizeof(charref), "&#%d;", cur); - xmlBufShrink(in, len); xmlBufGrow(out, charrefLen * 4); c_out = xmlBufAvail(out); c_in = charrefLen; @@ -2325,13 +2501,15 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init) goto error; } + xmlBufShrink(in, len); xmlBufAddLen(out, c_out); writtentot += c_out; goto retry; } error: - if ((writtentot <= 0) && (ret != 0)) { + if (((writtentot <= 0) && (ret != 0)) || + (ret == XML_ENC_ERR_MEMORY)) { if (output->error == 0) output->error = xmlEncConvertError(ret); return(ret); @@ -2762,7 +2940,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen, * Lookup tables for ISO-8859-2..ISO-8859-16 transcoding * ************************************************************************/ -static unsigned short const xmlunicodetable_ISO8859_2 [128] = { +static const unsigned short xmlunicodetable_ISO8859_2 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -2811,7 +2989,7 @@ static const unsigned char xmltranscodetable_ISO8859_2 [48 + 6 * 64] = { "\x00\x00\x00\xf3\xf4\x00\xf6\xf7\x00\x00\xfa\x00\xfc\xfd\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_3 [128] = { +static const unsigned short xmlunicodetable_ISO8859_3 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -2864,7 +3042,7 @@ static const unsigned char xmltranscodetable_ISO8859_3 [48 + 7 * 64] = { "\x00\xf1\xf2\xf3\xf4\x00\xf6\xf7\x00\xf9\xfa\xfb\xfc\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_4 [128] = { +static const unsigned short xmlunicodetable_ISO8859_4 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -2913,7 +3091,7 @@ static const unsigned char xmltranscodetable_ISO8859_4 [48 + 6 * 64] = { "\x00\x00\x00\x00\xf4\xf5\xf6\xf7\xf8\x00\xfa\xfb\xfc\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_5 [128] = { +static const unsigned short xmlunicodetable_ISO8859_5 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -2962,7 +3140,7 @@ static const unsigned char xmltranscodetable_ISO8859_5 [48 + 6 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_6 [128] = { +static const unsigned short xmlunicodetable_ISO8859_6 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3007,7 +3185,7 @@ static const unsigned char xmltranscodetable_ISO8859_6 [48 + 5 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_7 [128] = { +static const unsigned short xmlunicodetable_ISO8859_7 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3060,7 +3238,7 @@ static const unsigned char xmltranscodetable_ISO8859_7 [48 + 7 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_8 [128] = { +static const unsigned short xmlunicodetable_ISO8859_8 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3113,7 +3291,7 @@ static const unsigned char xmltranscodetable_ISO8859_8 [48 + 7 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_9 [128] = { +static const unsigned short xmlunicodetable_ISO8859_9 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3158,7 +3336,7 @@ static const unsigned char xmltranscodetable_ISO8859_9 [48 + 5 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_10 [128] = { +static const unsigned short xmlunicodetable_ISO8859_10 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3211,7 +3389,7 @@ static const unsigned char xmltranscodetable_ISO8859_10 [48 + 7 * 64] = { "\xf0\x00\x00\xf3\xf4\xf5\xf6\x00\xf8\x00\xfa\xfb\xfc\xfd\xfe\x00" }; -static unsigned short const xmlunicodetable_ISO8859_11 [128] = { +static const unsigned short xmlunicodetable_ISO8859_11 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3260,7 +3438,7 @@ static const unsigned char xmltranscodetable_ISO8859_11 [48 + 6 * 64] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_13 [128] = { +static const unsigned short xmlunicodetable_ISO8859_13 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3313,7 +3491,7 @@ static const unsigned char xmltranscodetable_ISO8859_13 [48 + 7 * 64] = { "\x00\x00\x00\x00\x00\x00\xcd\xed\x00\x00\x00\xcf\xef\x00\x00\x00" }; -static unsigned short const xmlunicodetable_ISO8859_14 [128] = { +static const unsigned short xmlunicodetable_ISO8859_14 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3378,7 +3556,7 @@ static const unsigned char xmltranscodetable_ISO8859_14 [48 + 10 * 64] = { "\x00\xf1\xf2\xf3\xf4\xf5\xf6\x00\xf8\xf9\xfa\xfb\xfc\xfd\x00\xff" }; -static unsigned short const xmlunicodetable_ISO8859_15 [128] = { +static const unsigned short xmlunicodetable_ISO8859_15 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, @@ -3427,7 +3605,7 @@ static const unsigned char xmltranscodetable_ISO8859_15 [48 + 6 * 64] = { "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" }; -static unsigned short const xmlunicodetable_ISO8859_16 [128] = { +static const unsigned short xmlunicodetable_ISO8859_16 [128] = { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, diff --git a/entities.c b/entities.c index aec5144..f7792a8 100644 --- a/entities.c +++ b/entities.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "private/entities.h" #include "private/error.h" @@ -68,50 +69,11 @@ static xmlEntity xmlEntityApos = { NULL, NULL, NULL, NULL, 0, 0, 0 }; -/** - * xmlEntitiesErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -xmlEntitiesErrMemory(const char *extra) -{ - __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra); -} - -/** - * xmlEntitiesErr: - * @code: the error code - * @msg: the message - * - * Raise an error. - */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlEntitiesErr(xmlParserErrors code, const char *msg) -{ - __xmlSimpleError(XML_FROM_TREE, code, NULL, msg, NULL); -} - -/** - * xmlEntitiesWarn: - * @code: the error code - * @msg: the message - * - * Raise a warning. - */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlEntitiesWarn(xmlParserErrors code, const char *msg, const xmlChar *str1) -{ - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_TREE, code, - XML_ERR_WARNING, NULL, 0, - (const char *)str1, NULL, NULL, 0, 0, - msg, (const char *)str1, NULL); -} - /* - * xmlFreeEntity : clean-up an entity record. + * xmlFreeEntity: + * @entity: an entity + * + * Frees the entity. */ void xmlFreeEntity(xmlEntityPtr entity) @@ -125,7 +87,7 @@ xmlFreeEntity(xmlEntityPtr entity) dict = entity->doc->dict; - if ((entity->children) && (entity->owner == 1) && + if ((entity->children) && (entity == (xmlEntityPtr) entity->children->parent)) xmlFreeNodeList(entity->children); if ((entity->name != NULL) && @@ -150,37 +112,43 @@ xmlFreeEntity(xmlEntityPtr entity) * internal routine doing the entity node structures allocations */ static xmlEntityPtr -xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type, +xmlCreateEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { xmlEntityPtr ret; ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); - if (ret == NULL) { - xmlEntitiesErrMemory("xmlCreateEntity: malloc failed"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlEntity)); + ret->doc = doc; ret->type = XML_ENTITY_DECL; /* * fill the structure. */ ret->etype = (xmlEntityType) type; - if (dict == NULL) { + if ((doc == NULL) || (doc->dict == NULL)) ret->name = xmlStrdup(name); - if (ExternalID != NULL) - ret->ExternalID = xmlStrdup(ExternalID); - if (SystemID != NULL) - ret->SystemID = xmlStrdup(SystemID); - } else { - ret->name = xmlDictLookup(dict, name, -1); - ret->ExternalID = xmlStrdup(ExternalID); - ret->SystemID = xmlStrdup(SystemID); + else + ret->name = xmlDictLookup(doc->dict, name, -1); + if (ret->name == NULL) + goto error; + if (ExternalID != NULL) { + ret->ExternalID = xmlStrdup(ExternalID); + if (ret->ExternalID == NULL) + goto error; + } + if (SystemID != NULL) { + ret->SystemID = xmlStrdup(SystemID); + if (ret->SystemID == NULL) + goto error; } if (content != NULL) { ret->length = xmlStrlen(content); ret->content = xmlStrndup(content, ret->length); + if (ret->content == NULL) + goto error; } else { ret->length = 0; ret->content = NULL; @@ -188,28 +156,53 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type, ret->URI = NULL; /* to be computed by the layer knowing the defining entity */ ret->orig = NULL; - ret->owner = 0; return(ret); + +error: + xmlFreeEntity(ret); + return(NULL); } -/* - * xmlAddEntity : register a new entity for an entities table. +/** + * xmlAddEntity: + * @doc: the document + * @extSubset: add to the external or internal subset + * @name: the entity name + * @type: the entity type XML_xxx_yyy_ENTITY + * @ExternalID: the entity external ID if available + * @SystemID: the entity system ID if available + * @content: the entity content + * @out: pointer to resulting entity (optional) + * + * Register a new entity for this document. + * + * Available since 2.13.0. + * + * Returns an xmlParserErrors error code. */ -static xmlEntityPtr -xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type, +int +xmlAddEntity(xmlDocPtr doc, int extSubset, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, - const xmlChar *content) { + const xmlChar *content, xmlEntityPtr *out) { + xmlDtdPtr dtd; xmlDictPtr dict = NULL; xmlEntitiesTablePtr table = NULL; xmlEntityPtr ret, predef; + int res; - if (name == NULL) - return(NULL); + if (out != NULL) + *out = NULL; + if ((doc == NULL) || (name == NULL)) + return(XML_ERR_ARGUMENT); + dict = doc->dict; + + if (extSubset) + dtd = doc->extSubset; + else + dtd = doc->intSubset; if (dtd == NULL) - return(NULL); - if (dtd->doc != NULL) - dict = dtd->doc->dict; + return(XML_DTD_NO_DTD); switch (type) { case XML_INTERNAL_GENERAL_ENTITY: @@ -246,41 +239,60 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type, } } } - if (!valid) { - xmlEntitiesWarn(XML_ERR_ENTITY_PROCESSING, - "xmlAddEntity: invalid redeclaration of predefined" - " entity '%s'", name); - return(NULL); - } + if (!valid) + return(XML_ERR_REDECL_PREDEF_ENTITY); } - if (dtd->entities == NULL) + if (dtd->entities == NULL) { dtd->entities = xmlHashCreateDict(0, dict); + if (dtd->entities == NULL) + return(XML_ERR_NO_MEMORY); + } table = dtd->entities; break; case XML_INTERNAL_PARAMETER_ENTITY: case XML_EXTERNAL_PARAMETER_ENTITY: - if (dtd->pentities == NULL) + if (dtd->pentities == NULL) { dtd->pentities = xmlHashCreateDict(0, dict); + if (dtd->pentities == NULL) + return(XML_ERR_NO_MEMORY); + } table = dtd->pentities; break; - case XML_INTERNAL_PREDEFINED_ENTITY: - return(NULL); + default: + return(XML_ERR_ARGUMENT); } - if (table == NULL) - return(NULL); - ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content); + ret = xmlCreateEntity(dtd->doc, name, type, ExternalID, SystemID, content); if (ret == NULL) - return(NULL); - ret->doc = dtd->doc; + return(XML_ERR_NO_MEMORY); - if (xmlHashAddEntry(table, name, ret)) { + res = xmlHashAdd(table, name, ret); + if (res < 0) { + xmlFreeEntity(ret); + return(XML_ERR_NO_MEMORY); + } else if (res == 0) { /* * entity was already defined at another level. */ xmlFreeEntity(ret); - return(NULL); + return(XML_WAR_ENTITY_REDEFINED); } - return(ret); + + /* + * Link it to the DTD + */ + ret->parent = dtd; + ret->doc = dtd->doc; + if (dtd->last == NULL) { + dtd->children = dtd->last = (xmlNodePtr) ret; + } else { + dtd->last->next = (xmlNodePtr) ret; + ret->prev = dtd->last; + dtd->last = (xmlNodePtr) ret; + } + + if (out != NULL) + *out = ret; + return(0); } /** @@ -337,34 +349,8 @@ xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { xmlEntityPtr ret; - xmlDtdPtr dtd; - if (doc == NULL) { - xmlEntitiesErr(XML_DTD_NO_DOC, - "xmlAddDtdEntity: document is NULL"); - return(NULL); - } - if (doc->extSubset == NULL) { - xmlEntitiesErr(XML_DTD_NO_DTD, - "xmlAddDtdEntity: document without external subset"); - return(NULL); - } - dtd = doc->extSubset; - ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content); - if (ret == NULL) return(NULL); - - /* - * Link it to the DTD - */ - ret->parent = dtd; - ret->doc = dtd->doc; - if (dtd->last == NULL) { - dtd->children = dtd->last = (xmlNodePtr) ret; - } else { - dtd->last->next = (xmlNodePtr) ret; - ret->prev = dtd->last; - dtd->last = (xmlNodePtr) ret; - } + xmlAddEntity(doc, 1, name, type, ExternalID, SystemID, content, &ret); return(ret); } @@ -386,34 +372,8 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { xmlEntityPtr ret; - xmlDtdPtr dtd; - - if (doc == NULL) { - xmlEntitiesErr(XML_DTD_NO_DOC, - "xmlAddDocEntity: document is NULL"); - return(NULL); - } - if (doc->intSubset == NULL) { - xmlEntitiesErr(XML_DTD_NO_DTD, - "xmlAddDocEntity: document without internal subset"); - return(NULL); - } - dtd = doc->intSubset; - ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content); - if (ret == NULL) return(NULL); - /* - * Link it to the DTD - */ - ret->parent = dtd; - ret->doc = dtd->doc; - if (dtd->last == NULL) { - dtd->children = dtd->last = (xmlNodePtr) ret; - } else { - dtd->last->next = (xmlNodePtr) ret; - ret->prev = dtd->last; - dtd->last = (xmlNodePtr) ret; - } + xmlAddEntity(doc, 0, name, type, ExternalID, SystemID, content, &ret); return(ret); } @@ -438,21 +398,12 @@ xmlEntityPtr xmlNewEntity(xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) { - xmlEntityPtr ret; - xmlDictPtr dict; - if ((doc != NULL) && (doc->intSubset != NULL)) { return(xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content)); } - if (doc != NULL) - dict = doc->dict; - else - dict = NULL; - ret = xmlCreateEntity(dict, name, type, ExternalID, SystemID, content); - if (ret == NULL) + if (name == NULL) return(NULL); - ret->doc = doc; - return(ret); + return(xmlCreateEntity(doc, name, type, ExternalID, SystemID, content)); } /** @@ -604,10 +555,8 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { */ buffer_size = 1000; buffer = (xmlChar *) xmlMalloc(buffer_size); - if (buffer == NULL) { - xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed"); + if (buffer == NULL) return(NULL); - } out = buffer; while (*cur != '\0') { @@ -707,53 +656,18 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { * cur[3] is 10xxxxxx if cur[0] is 1111xxxx * cur[0] is not 11111xxx */ - char buf[11], *ptr; - int val = 0, l = 1; - - if (((cur[0] & 0xC0) != 0xC0) || - ((cur[1] & 0xC0) != 0x80) || - (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) || - (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) || - (((cur[0] & 0xF8) == 0xF8))) { - xmlEntitiesErr(XML_CHECK_NOT_UTF8, - "xmlEncodeEntities: input not UTF-8"); - snprintf(buf, sizeof(buf), "&#%d;", *cur); - buf[sizeof(buf) - 1] = 0; - ptr = buf; - while (*ptr != 0) *out++ = *ptr++; - cur++; - continue; - } else if (*cur < 0xE0) { - val = (cur[0]) & 0x1F; - val <<= 6; - val |= (cur[1]) & 0x3F; - l = 2; - } else if (*cur < 0xF0) { - val = (cur[0]) & 0x0F; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - l = 3; - } else if (*cur < 0xF8) { - val = (cur[0]) & 0x07; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - val <<= 6; - val |= (cur[3]) & 0x3F; - l = 4; - } - if ((l == 1) || (!IS_CHAR(val))) { - xmlEntitiesErr(XML_ERR_INVALID_CHAR, - "xmlEncodeEntities: char out of range\n"); - snprintf(buf, sizeof(buf), "&#%d;", *cur); - buf[sizeof(buf) - 1] = 0; - ptr = buf; - while (*ptr != 0) *out++ = *ptr++; - cur++; - continue; + char buf[13], *ptr; + int val, l; + + l = 4; + val = xmlGetUTF8Char(cur, &l); + if (val < 0) { + val = 0xFFFD; + cur++; + } else { + if (!IS_CHAR(val)) + val = 0xFFFD; + cur += l; } /* * We could do multiple things here. Just save as a char ref @@ -762,7 +676,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { buf[sizeof(buf) - 1] = 0; ptr = buf; while (*ptr != 0) *out++ = *ptr++; - cur += l; continue; } } else if (IS_BYTE_CHAR(*cur)) { @@ -779,7 +692,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { return(buffer); mem_error: - xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed"); xmlFree(buffer); return(NULL); } @@ -840,10 +752,8 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input) */ buffer_size = 1000; buffer = (xmlChar *) xmlMalloc(buffer_size); - if (buffer == NULL) { - xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed"); + if (buffer == NULL) return(NULL); - } out = buffer; while (*cur != '\0') { @@ -899,7 +809,6 @@ xmlEncodeSpecialChars(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlChar *input) return(buffer); mem_error: - xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed"); xmlFree(buffer); return(NULL); } @@ -956,27 +865,47 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlEntityPtr cur; cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); - if (cur == NULL) { - xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlEntity)); cur->type = XML_ENTITY_DECL; cur->etype = ent->etype; - if (ent->name != NULL) + if (ent->name != NULL) { cur->name = xmlStrdup(ent->name); - if (ent->ExternalID != NULL) + if (cur->name == NULL) + goto error; + } + if (ent->ExternalID != NULL) { cur->ExternalID = xmlStrdup(ent->ExternalID); - if (ent->SystemID != NULL) + if (cur->ExternalID == NULL) + goto error; + } + if (ent->SystemID != NULL) { cur->SystemID = xmlStrdup(ent->SystemID); - if (ent->content != NULL) + if (cur->SystemID == NULL) + goto error; + } + if (ent->content != NULL) { cur->content = xmlStrdup(ent->content); - if (ent->orig != NULL) + if (cur->content == NULL) + goto error; + } + if (ent->orig != NULL) { cur->orig = xmlStrdup(ent->orig); - if (ent->URI != NULL) + if (cur->orig == NULL) + goto error; + } + if (ent->URI != NULL) { cur->URI = xmlStrdup(ent->URI); + if (cur->URI == NULL) + goto error; + } return(cur); + +error: + xmlFreeEntity(cur); + return(NULL); } /** @@ -989,52 +918,12 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { */ xmlEntitiesTablePtr xmlCopyEntitiesTable(xmlEntitiesTablePtr table) { - return(xmlHashCopy(table, xmlCopyEntity)); + return(xmlHashCopySafe(table, xmlCopyEntity, xmlFreeEntityWrapper)); } #endif /* LIBXML_TREE_ENABLED */ #ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlDumpEntityContent: - * @buf: An XML buffer. - * @content: The entity content. - * - * This will dump the quoted string value, taking care of the special - * treatment required by % - */ -static void -xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) { - if (xmlStrchr(content, '%')) { - const xmlChar * base, *cur; - - xmlBufferCCat(buf, "\""); - base = cur = content; - while (*cur != 0) { - if (*cur == '"') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST """, 6); - cur++; - base = cur; - } else if (*cur == '%') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST "%", 6); - cur++; - base = cur; - } else { - cur++; - } - } - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferCCat(buf, "\""); - } else { - xmlBufferWriteQuotedString(buf, content); - } -} - /** * xmlDumpEntityDecl: * @buf: An XML buffer. @@ -1044,81 +933,15 @@ xmlDumpEntityContent(xmlBufferPtr buf, const xmlChar *content) { */ void xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) { - if ((buf == NULL) || (ent == NULL)) return; - switch (ent->etype) { - case XML_INTERNAL_GENERAL_ENTITY: - xmlBufferWriteChar(buf, "name); - xmlBufferWriteChar(buf, " "); - if (ent->orig != NULL) - xmlBufferWriteQuotedString(buf, ent->orig); - else - xmlDumpEntityContent(buf, ent->content); - xmlBufferWriteChar(buf, ">\n"); - break; - case XML_EXTERNAL_GENERAL_PARSED_ENTITY: - xmlBufferWriteChar(buf, "name); - if (ent->ExternalID != NULL) { - xmlBufferWriteChar(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf, ent->ExternalID); - xmlBufferWriteChar(buf, " "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } else { - xmlBufferWriteChar(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } - xmlBufferWriteChar(buf, ">\n"); - break; - case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: - xmlBufferWriteChar(buf, "name); - if (ent->ExternalID != NULL) { - xmlBufferWriteChar(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf, ent->ExternalID); - xmlBufferWriteChar(buf, " "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } else { - xmlBufferWriteChar(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } - if (ent->content != NULL) { /* Should be true ! */ - xmlBufferWriteChar(buf, " NDATA "); - if (ent->orig != NULL) - xmlBufferWriteCHAR(buf, ent->orig); - else - xmlBufferWriteCHAR(buf, ent->content); - } - xmlBufferWriteChar(buf, ">\n"); - break; - case XML_INTERNAL_PARAMETER_ENTITY: - xmlBufferWriteChar(buf, "name); - xmlBufferWriteChar(buf, " "); - if (ent->orig == NULL) - xmlDumpEntityContent(buf, ent->content); - else - xmlBufferWriteQuotedString(buf, ent->orig); - xmlBufferWriteChar(buf, ">\n"); - break; - case XML_EXTERNAL_PARAMETER_ENTITY: - xmlBufferWriteChar(buf, "name); - if (ent->ExternalID != NULL) { - xmlBufferWriteChar(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf, ent->ExternalID); - xmlBufferWriteChar(buf, " "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } else { - xmlBufferWriteChar(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf, ent->SystemID); - } - xmlBufferWriteChar(buf, ">\n"); - break; - default: - xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY, - "xmlDumpEntitiesDecl: internal: unknown type entity type"); - } + xmlSaveCtxtPtr save; + + if ((buf == NULL) || (ent == NULL)) + return; + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlSaveTree(save, (xmlNodePtr) ent); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } /** @@ -1129,9 +952,9 @@ xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) { * When using the hash table scan function, arguments need to be reversed */ static void -xmlDumpEntityDeclScan(void *ent, void *buf, +xmlDumpEntityDeclScan(void *ent, void *save, const xmlChar *name ATTRIBUTE_UNUSED) { - xmlDumpEntityDecl((xmlBufferPtr) buf, (xmlEntityPtr) ent); + xmlSaveTree(save, ent); } /** @@ -1143,6 +966,14 @@ xmlDumpEntityDeclScan(void *ent, void *buf, */ void xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) { - xmlHashScan(table, xmlDumpEntityDeclScan, buf); + xmlSaveCtxtPtr save; + + if ((buf == NULL) || (table == NULL)) + return; + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlHashScan(table, xmlDumpEntityDeclScan, save); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } #endif /* LIBXML_OUTPUT_ENABLED */ diff --git a/error.c b/error.c index c87cf2a..b678a0e 100644 --- a/error.c +++ b/error.c @@ -11,45 +11,169 @@ #include #include +#include #include #include #include #include "private/error.h" +#include "private/string.h" -#define XML_MAX_ERRORS 100 - -#define XML_GET_VAR_STR(msg, str) { \ - int size, prev_size = -1; \ - int chars; \ - char *larger; \ - va_list ap; \ - \ - str = (char *) xmlMalloc(150); \ - if (str != NULL) { \ - \ - size = 150; \ - \ - while (size < 64000) { \ - va_start(ap, msg); \ - chars = vsnprintf(str, size, msg, ap); \ - va_end(ap); \ - if ((chars > -1) && (chars < size)) { \ - if (prev_size == chars) { \ - break; \ - } else { \ - prev_size = chars; \ - } \ - } \ - if (chars > -1) \ - size += chars + 1; \ - else \ - size += 100; \ - if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\ - break; \ - } \ - str = larger; \ - }} \ +/************************************************************************ + * * + * Error struct * + * * + ************************************************************************/ + +static int +xmlVSetError(xmlError *err, + void *ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const char *file, int line, + const char *str1, const char *str2, const char *str3, + int int1, int col, + const char *fmt, va_list ap) +{ + char *message = NULL; + char *fileCopy = NULL; + char *str1Copy = NULL; + char *str2Copy = NULL; + char *str3Copy = NULL; + + if (code == XML_ERR_OK) { + xmlResetError(err); + return(0); + } + + /* + * Formatting the message + */ + if (fmt == NULL) { + message = xmlMemStrdup("No error message provided"); + } else { + xmlChar *tmp; + int res; + + res = xmlStrVASPrintf(&tmp, MAX_ERR_MSG_SIZE, fmt, ap); + if (res < 0) + goto err_memory; + message = (char *) tmp; + } + if (message == NULL) + goto err_memory; + + if (file != NULL) { + fileCopy = (char *) xmlStrdup((const xmlChar *) file); + if (fileCopy == NULL) + goto err_memory; + } + if (str1 != NULL) { + str1Copy = (char *) xmlStrdup((const xmlChar *) str1); + if (str1Copy == NULL) + goto err_memory; + } + if (str2 != NULL) { + str2Copy = (char *) xmlStrdup((const xmlChar *) str2); + if (str2Copy == NULL) + goto err_memory; + } + if (str3 != NULL) { + str3Copy = (char *) xmlStrdup((const xmlChar *) str3); + if (str3Copy == NULL) + goto err_memory; + } + + xmlResetError(err); + + err->domain = domain; + err->code = code; + err->message = message; + err->level = level; + err->file = fileCopy; + err->line = line; + err->str1 = str1Copy; + err->str2 = str2Copy; + err->str3 = str3Copy; + err->int1 = int1; + err->int2 = col; + err->node = node; + err->ctxt = ctxt; + + return(0); + +err_memory: + xmlFree(message); + xmlFree(fileCopy); + xmlFree(str1Copy); + xmlFree(str2Copy); + xmlFree(str3Copy); + return(-1); +} + +static int LIBXML_ATTR_FORMAT(14,15) +xmlSetError(xmlError *err, + void *ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const char *file, int line, + const char *str1, const char *str2, const char *str3, + int int1, int col, + const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = xmlVSetError(err, ctxt, node, domain, code, level, file, line, + str1, str2, str3, int1, col, fmt, ap); + va_end(ap); + + return(res); +} + +static int +xmlVUpdateError(xmlError *err, + void *ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const char *file, int line, + const char *str1, const char *str2, const char *str3, + int int1, int col, + const char *fmt, va_list ap) +{ + int res; + + /* + * Find first element parent. + */ + if (node != NULL) { + int i; + + for (i = 0; i < 10; i++) { + if ((node->type == XML_ELEMENT_NODE) || + (node->parent == NULL)) + break; + node = node->parent; + } + } + + /* + * Get file and line from node. + */ + if (node != NULL) { + if ((file == NULL) && (node->doc != NULL)) + file = (const char *) node->doc->URL; + + if (line == 0) { + if (node->type == XML_ELEMENT_NODE) + line = node->line; + if ((line == 0) || (line == 65535)) + line = xmlGetLineNo(node); + } + } + + res = xmlVSetError(err, ctxt, node, domain, code, level, file, line, + str1, str2, str3, int1, col, fmt, ap); + + return(res); } /************************************************************************ @@ -101,14 +225,21 @@ initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler) * @ctx: the new error handling context * @handler: the new handler function * - * Function to reset the handler and the error context for out of - * context error messages. - * This simply means that @handler will be called for subsequent - * error messages while not parsing nor validating. And @ctx will - * be passed as first argument to @handler - * One can simply force messages to be emitted to another FILE * than - * stderr by setting @ctx to this file handle and @handler to NULL. - * For multi-threaded applications, this must be set separately for each thread. + * DEPRECATED: See xmlSetStructuredErrorFunc for alternatives. + * + * Set the global "generic" handler and context for error messages. + * The generic error handler will only receive fragments of error + * messages which should be concatenated or printed to a stream. + * + * If handler is NULL, use the built-in default handler which prints + * to stderr. + * + * Since this is a global setting, it's a good idea to reset the + * error handler to its default value after collecting the errors + * you're interested in. + * + * For multi-threaded applications, this must be set separately for + * each thread. */ void xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { @@ -124,12 +255,30 @@ xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { * @ctx: the new error handling context * @handler: the new handler function * - * Function to reset the handler and the error context for out of - * context structured error messages. - * This simply means that @handler will be called for subsequent - * error messages while not parsing nor validating. And @ctx will - * be passed as first argument to @handler - * For multi-threaded applications, this must be set separately for each thread. + * DEPRECATED: Use a per-context error handler. + * + * It's recommended to use the per-context error handlers instead: + * + * - xmlCtxtSetErrorHandler (since 2.13.0) + * - xmlTextReaderSetStructuredErrorHandler + * - xmlXPathSetErrorHandler (since 2.13.0) + * - xmlXIncludeSetErrorHandler (since 2.13.0) + * - xmlSchemaSetParserStructuredErrors + * - xmlSchemaSetValidStructuredErrors + * - xmlRelaxNGSetParserStructuredErrors + * - xmlRelaxNGSetValidStructuredErrors + * + * Set the global "structured" handler and context for error messages. + * If handler is NULL, the error handler is deactivated. + * + * The structured error handler takes precedence over "generic" + * handlers, even per-context generic handlers. + * + * Since this is a global setting, it's a good idea to deactivate the + * error handler after collecting the errors you're interested in. + * + * For multi-threaded applications, this must be set separately for + * each thread. */ void xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { @@ -147,6 +296,8 @@ xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { * xmlParserPrintFileInfo: * @input: an xmlParserInputPtr input * + * DEPRECATED: Use xmlFormatError. + * * Displays the associated file and line information for the current input */ @@ -238,6 +389,8 @@ xmlParserPrintFileContextInternal(xmlParserInputPtr input , * xmlParserPrintFileContext: * @input: an xmlParserInputPtr input * + * DEPRECATED: Use xmlFormatError. + * * Displays current context within the input content for error tracking */ void @@ -247,35 +400,37 @@ xmlParserPrintFileContext(xmlParserInputPtr input) { } /** - * xmlReportError: - * @err: the error - * @ctx: the parser context or NULL - * @str: the formatted error message + * xmlFormatError: + * @err: the error + * @channel: callback + * @data: user data for callback + * + * Report a formatted error to a printf-like callback. * - * Report an error with its context, replace the 4 old error/warning - * routines. + * This can result in a verbose multi-line report including additional + * information from the parser context. + * + * Available since 2.13.0. */ -static void -xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, - xmlGenericErrorFunc channel, void *data) +void +xmlFormatError(const xmlError *err, xmlGenericErrorFunc channel, void *data) { - char *file = NULL; - int line = 0; - int code = -1; + const char *message; + const char *file; + int line; + int code; int domain; const xmlChar *name = NULL; xmlNodePtr node; xmlErrorLevel level; + xmlParserCtxtPtr ctxt = NULL; xmlParserInputPtr input = NULL; xmlParserInputPtr cur = NULL; - if (err == NULL) + if ((err == NULL) || (channel == NULL)) return; - if (channel == NULL) { - channel = xmlGenericError; - data = xmlGenericErrorContext; - } + message = err->message; file = err->file; line = err->line; code = err->code; @@ -286,25 +441,30 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, if (code == XML_ERR_OK) return; - if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) + if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || + (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || + (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { + ctxt = err->ctxt; + } + + if ((node != NULL) && (node->type == XML_ELEMENT_NODE) && + (domain != XML_FROM_SCHEMASV)) name = node->name; /* * Maintain the compatibility with the legacy error handling */ - if (ctxt != NULL) { + if ((ctxt != NULL) && (ctxt->input != NULL)) { input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && + if ((input->filename == NULL) && (ctxt->inputNr > 1)) { cur = input; input = ctxt->inputTab[ctxt->inputNr - 2]; } - if (input != NULL) { - if (input->filename) - channel(data, "%s:%d: ", input->filename, input->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", input->line); - } + if (input->filename) + channel(data, "%s:%d: ", input->filename, input->line); + else if ((line != 0) && (domain == XML_FROM_PARSER)) + channel(data, "Entity: line %d: ", input->line); } else { if (file != NULL) channel(data, "%s:%d: ", file, line); @@ -405,19 +565,35 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, channel(data, "error : "); break; } - if (str != NULL) { + if (message != NULL) { int len; - len = xmlStrlen((const xmlChar *)str); - if ((len > 0) && (str[len - 1] != '\n')) - channel(data, "%s\n", str); + len = xmlStrlen((const xmlChar *) message); + if ((len > 0) && (message[len - 1] != '\n')) + channel(data, "%s\n", message); else - channel(data, "%s", str); + channel(data, "%s", message); } else { - channel(data, "%s\n", "out of memory error"); + channel(data, "%s\n", "No error message provided"); } if (ctxt != NULL) { + if ((input != NULL) && + ((input->buf == NULL) || (input->buf->encoder == NULL)) && + (code == XML_ERR_INVALID_ENCODING) && + (input->cur < input->end)) { + int i; + + channel(data, "Bytes:"); + for (i = 0; i < 4; i++) { + if (input->cur + i >= input->end) + break; + channel(data, " 0x%02X", input->cur[i]); + } + channel(data, "\n"); + } + xmlParserPrintFileContextInternal(input, channel, data); + if (cur != NULL) { if (cur->filename) channel(data, "%s:%d: \n", cur->filename, cur->line); @@ -442,12 +618,53 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, } /** - * __xmlRaiseError: + * xmlRaiseMemoryError: + * @schannel: the structured callback channel + * @channel: the old callback channel + * @data: the callback data + * @domain: the domain for the error + * @error: optional error struct to be filled + * + * Update the global and optional error structure, then forward the + * error to an error handler. + * + * This function doesn't make memory allocations which are likely + * to fail after an OOM error. + */ +void +xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, + void *data, int domain, xmlError *error) +{ + xmlError *lastError = &xmlLastError; + + xmlResetLastError(); + lastError->domain = domain; + lastError->code = XML_ERR_NO_MEMORY; + lastError->level = XML_ERR_FATAL; + + if (error != NULL) { + xmlResetError(error); + error->domain = domain; + error->code = XML_ERR_NO_MEMORY; + error->level = XML_ERR_FATAL; + } + + if (schannel != NULL) { + schannel(data, lastError); + } else if (xmlStructuredError != NULL) { + xmlStructuredError(xmlStructuredErrorContext, lastError); + } else if (channel != NULL) { + channel(data, "libxml2: out of memory\n"); + } +} + +/** + * xmlVRaiseError: * @schannel: the structured callback channel * @channel: the old callback channel * @data: the callback data * @ctx: the parser context or NULL - * @ctx: the parser context or NULL + * @node: the current node or NULL * @domain: the domain for the error * @code: the code for the error * @level: the xmlErrorLevel for the error @@ -459,258 +676,128 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, * @int1: extra int info * @col: column number of the error or 0 if N/A * @msg: the message to display/transmit - * @...: extra parameters for the message display + * @ap: extra parameters for the message display * * Update the appropriate global or contextual error structure, * then forward the error message down the parser or generic * error callback handler + * + * Returns 0 on success, -1 if a memory allocation failed. */ -void -__xmlRaiseError(xmlStructuredErrorFunc schannel, - xmlGenericErrorFunc channel, void *data, void *ctx, - void *nod, int domain, int code, xmlErrorLevel level, - const char *file, int line, const char *str1, - const char *str2, const char *str3, int int1, int col, - const char *msg, ...) +int +xmlVRaiseError(xmlStructuredErrorFunc schannel, + xmlGenericErrorFunc channel, void *data, void *ctx, + xmlNode *node, int domain, int code, xmlErrorLevel level, + const char *file, int line, const char *str1, + const char *str2, const char *str3, int int1, int col, + const char *msg, va_list ap) { xmlParserCtxtPtr ctxt = NULL; - xmlNodePtr node = (xmlNodePtr) nod; - char *str = NULL; - xmlParserInputPtr input = NULL; - xmlErrorPtr to = &xmlLastError; - xmlNodePtr baseptr = NULL; + /* xmlLastError is a macro retrieving the per-thread global. */ + xmlErrorPtr lastError = &xmlLastError; + xmlErrorPtr to = lastError; if (code == XML_ERR_OK) - return; + return(0); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (code == XML_ERR_INTERNAL_ERROR) { + fprintf(stderr, "Unexpected error: %d\n", code); + abort(); + } +#endif if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING)) - return; + return(0); + if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { ctxt = (xmlParserCtxtPtr) ctx; - if (ctxt != NULL) { - if (level == XML_ERR_WARNING) { - if (ctxt->nbWarnings >= XML_MAX_ERRORS) - return; - ctxt->nbWarnings += 1; - } else { - if (ctxt->nbErrors >= XML_MAX_ERRORS) - return; - ctxt->nbErrors += 1; - } - - if ((schannel == NULL) && (ctxt->sax != NULL) && - (ctxt->sax->initialized == XML_SAX2_MAGIC) && - (ctxt->sax->serror != NULL)) { - schannel = ctxt->sax->serror; - data = ctxt->userData; - } - } - } - /* - * Check if structured error handler set - */ - if (schannel == NULL) { - schannel = xmlStructuredError; - /* - * if user has defined handler, change data ptr to user's choice - */ - if (schannel != NULL) - data = xmlStructuredErrorContext; - } - /* - * Formatting the message - */ - if (msg == NULL) { - str = (char *) xmlStrdup(BAD_CAST "No error message provided"); - } else { - XML_GET_VAR_STR(msg, str); + if (ctxt != NULL) + to = &ctxt->lastError; } - /* - * specific processing if a parser context is provided - */ - if (ctxt != NULL) { - if (file == NULL) { - input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && - (ctxt->inputNr > 1)) { - input = ctxt->inputTab[ctxt->inputNr - 2]; - } - if (input != NULL) { - file = input->filename; - line = input->line; - col = input->col; - } - } - to = &ctxt->lastError; - } else if ((node != NULL) && (file == NULL)) { - int i; - - if ((node->doc != NULL) && (node->doc->URL != NULL)) { - baseptr = node; -/* file = (const char *) node->doc->URL; */ - } - for (i = 0; - ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE)); - i++) - node = node->parent; - if ((baseptr == NULL) && (node != NULL) && - (node->doc != NULL) && (node->doc->URL != NULL)) - baseptr = node; - - if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) - line = node->line; - if ((line == 0) || (line == 65535)) - line = xmlGetLineNo(node); - } + if (xmlVUpdateError(to, ctxt, node, domain, code, level, file, line, + str1, str2, str3, int1, col, msg, ap)) + return(-1); - /* - * Save the information about the error - */ - xmlResetError(to); - to->domain = domain; - to->code = code; - to->message = str; - to->level = level; - if (file != NULL) - to->file = (char *) xmlStrdup((const xmlChar *) file); - else if (baseptr != NULL) { -#ifdef LIBXML_XINCLUDE_ENABLED - /* - * We check if the error is within an XInclude section and, - * if so, attempt to print out the href of the XInclude instead - * of the usual "base" (doc->URL) for the node (bug 152623). - */ - xmlNodePtr prev = baseptr; - char *href = NULL; - int inclcount = 0; - while (prev != NULL) { - if (prev->prev == NULL) - prev = prev->parent; - else { - prev = prev->prev; - if (prev->type == XML_XINCLUDE_START) { - if (inclcount > 0) { - --inclcount; - } else { - href = (char *) xmlGetProp(prev, BAD_CAST "href"); - if (href != NULL) - break; - } - } else if (prev->type == XML_XINCLUDE_END) - inclcount++; - } - } - if (href != NULL) - to->file = href; - else -#endif - to->file = (char *) xmlStrdup(baseptr->doc->URL); - if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) { - to->file = (char *) xmlStrdup(node->doc->URL); - } + if (to != lastError) { + if (xmlCopyError(to, lastError) < 0) + return(-1); } - to->line = line; - if (str1 != NULL) - to->str1 = (char *) xmlStrdup((const xmlChar *) str1); - if (str2 != NULL) - to->str2 = (char *) xmlStrdup((const xmlChar *) str2); - if (str3 != NULL) - to->str3 = (char *) xmlStrdup((const xmlChar *) str3); - to->int1 = int1; - to->int2 = col; - to->node = node; - to->ctxt = ctx; - - if (to != &xmlLastError) - xmlCopyError(to,&xmlLastError); if (schannel != NULL) { schannel(data, to); - return; - } - - /* - * Find the callback channel if channel param is NULL - */ - if ((ctxt != NULL) && (channel == NULL) && - (xmlStructuredError == NULL) && (ctxt->sax != NULL)) { - if (level == XML_ERR_WARNING) - channel = ctxt->sax->warning; + } else if (xmlStructuredError != NULL) { + xmlStructuredError(xmlStructuredErrorContext, to); + } else if (channel != NULL) { + /* Don't invoke legacy error handlers */ + if ((channel == xmlGenericErrorDefaultFunc) || + (channel == xmlParserError) || + (channel == xmlParserWarning) || + (channel == xmlParserValidityError) || + (channel == xmlParserValidityWarning)) + xmlFormatError(to, xmlGenericError, xmlGenericErrorContext); else - channel = ctxt->sax->error; - data = ctxt->userData; - } else if (channel == NULL) { - channel = xmlGenericError; - if (ctxt != NULL) { - data = ctxt; - } else { - data = xmlGenericErrorContext; - } + channel(data, "%s", to->message); } - if (channel == NULL) - return; - if ((channel == xmlParserError) || - (channel == xmlParserWarning) || - (channel == xmlParserValidityError) || - (channel == xmlParserValidityWarning)) - xmlReportError(to, ctxt, str, NULL, NULL); - else if (((void(*)(void)) channel == (void(*)(void)) fprintf) || - (channel == xmlGenericErrorDefaultFunc)) - xmlReportError(to, ctxt, str, channel, data); - else - channel(data, "%s", str); + return(0); } /** - * __xmlSimpleError: - * @domain: where the error comes from - * @code: the error code - * @node: the context node - * @extra: extra information - * - * Handle an out of memory condition - */ -void -__xmlSimpleError(int domain, int code, xmlNodePtr node, - const char *msg, const char *extra) -{ - - if (code == XML_ERR_NO_MEMORY) { - if (extra) - __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); - } else { - __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain, - code, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, msg, extra); - } -} -/** - * xmlParserError: - * @ctx: an XML parser context + * __xmlRaiseError: + * @schannel: the structured callback channel + * @channel: the old callback channel + * @data: the callback data + * @ctx: the parser context or NULL + * @nod: the node or NULL + * @domain: the domain for the error + * @code: the code for the error + * @level: the xmlErrorLevel for the error + * @file: the file source of the error (or NULL) + * @line: the line of the error or 0 if N/A + * @str1: extra string info + * @str2: extra string info + * @str3: extra string info + * @int1: extra int info + * @col: column number of the error or 0 if N/A * @msg: the message to display/transmit * @...: extra parameters for the message display * - * Display and format an error messages, gives file, line, position and - * extra parameters. + * Update the appropriate global or contextual error structure, + * then forward the error message down the parser or generic + * error callback handler + * + * Returns 0 on success, -1 if a memory allocation failed. */ -void -xmlParserError(void *ctx, const char *msg, ...) +int +__xmlRaiseError(xmlStructuredErrorFunc schannel, + xmlGenericErrorFunc channel, void *data, void *ctx, + xmlNode *node, int domain, int code, xmlErrorLevel level, + const char *file, int line, const char *str1, + const char *str2, const char *str3, int int1, int col, + const char *msg, ...) { + va_list ap; + int res; + + va_start(ap, msg); + res = xmlVRaiseError(schannel, channel, data, ctx, node, domain, code, + level, file, line, str1, str2, str3, int1, col, msg, + ap); + va_end(ap); + + return(res); +} + +static void +xmlVFormatLegacyError(void *ctx, const char *level, + const char *fmt, va_list ap) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlParserInputPtr input = NULL; xmlParserInputPtr cur = NULL; - char * str; + xmlChar *str = NULL; if (ctxt != NULL) { input = ctxt->input; @@ -722,11 +809,13 @@ xmlParserError(void *ctx, const char *msg, ...) xmlParserPrintFileInfo(input); } - xmlGenericError(xmlGenericErrorContext, "error: "); - XML_GET_VAR_STR(msg, str); - xmlGenericError(xmlGenericErrorContext, "%s", str); - if (str != NULL) + xmlGenericError(xmlGenericErrorContext, "%s: ", level); + + xmlStrVASPrintf(&str, MAX_ERR_MSG_SIZE, fmt, ap); + if (str != NULL) { + xmlGenericError(xmlGenericErrorContext, "%s", (char *) str); xmlFree(str); + } if (ctxt != NULL) { xmlParserPrintFileContext(input); @@ -739,54 +828,43 @@ xmlParserError(void *ctx, const char *msg, ...) } /** - * xmlParserWarning: + * xmlParserError: * @ctx: an XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * - * Display and format a warning messages, gives file, line, position and + * Display and format an error messages, gives file, line, position and * extra parameters. */ void -xmlParserWarning(void *ctx, const char *msg, ...) +xmlParserError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlParserInputPtr input = NULL; - xmlParserInputPtr cur = NULL; - char * str; + va_list ap; - if (ctxt != NULL) { - input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && - (ctxt->inputNr > 1)) { - cur = input; - input = ctxt->inputTab[ctxt->inputNr - 2]; - } - xmlParserPrintFileInfo(input); - } + va_start(ap, msg); + xmlVFormatLegacyError(ctx, "error", msg, ap); + va_end(ap); +} - xmlGenericError(xmlGenericErrorContext, "warning: "); - XML_GET_VAR_STR(msg, str); - xmlGenericError(xmlGenericErrorContext, "%s", str); - if (str != NULL) - xmlFree(str); +/** + * xmlParserWarning: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format a warning messages, gives file, line, position and + * extra parameters. + */ +void +xmlParserWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) +{ + va_list ap; - if (ctxt != NULL) { - xmlParserPrintFileContext(input); - if (cur != NULL) { - xmlParserPrintFileInfo(cur); - xmlGenericError(xmlGenericErrorContext, "\n"); - xmlParserPrintFileContext(cur); - } - } + va_start(ap, msg); + xmlVFormatLegacyError(ctx, "warning", msg, ap); + va_end(ap); } -/************************************************************************ - * * - * Handling of validation errors * - * * - ************************************************************************/ - /** * xmlParserValidityError: * @ctx: an XML parser context @@ -797,38 +875,13 @@ xmlParserWarning(void *ctx, const char *msg, ...) * line, position and extra parameters. */ void -xmlParserValidityError(void *ctx, const char *msg, ...) +xmlParserValidityError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlParserInputPtr input = NULL; - char * str; - int len = xmlStrlen((const xmlChar *) msg); - static int had_info = 0; - - if ((len > 1) && (msg[len - 2] != ':')) { - if (ctxt != NULL) { - input = ctxt->input; - if ((input->filename == NULL) && (ctxt->inputNr > 1)) - input = ctxt->inputTab[ctxt->inputNr - 2]; - - if (had_info == 0) { - xmlParserPrintFileInfo(input); - } - } - xmlGenericError(xmlGenericErrorContext, "validity error: "); - had_info = 0; - } else { - had_info = 1; - } + va_list ap; - XML_GET_VAR_STR(msg, str); - xmlGenericError(xmlGenericErrorContext, "%s", str); - if (str != NULL) - xmlFree(str); - - if ((ctxt != NULL) && (input != NULL)) { - xmlParserPrintFileContext(input); - } + va_start(ap, msg); + xmlVFormatLegacyError(ctx, "validity error", msg, ap); + va_end(ap); } /** @@ -841,30 +894,13 @@ xmlParserValidityError(void *ctx, const char *msg, ...) * position and extra parameters. */ void -xmlParserValidityWarning(void *ctx, const char *msg, ...) +xmlParserValidityWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlParserInputPtr input = NULL; - char * str; - int len = xmlStrlen((const xmlChar *) msg); - - if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) { - input = ctxt->input; - if ((input->filename == NULL) && (ctxt->inputNr > 1)) - input = ctxt->inputTab[ctxt->inputNr - 2]; + va_list ap; - xmlParserPrintFileInfo(input); - } - - xmlGenericError(xmlGenericErrorContext, "validity warning: "); - XML_GET_VAR_STR(msg, str); - xmlGenericError(xmlGenericErrorContext, "%s", str); - if (str != NULL) - xmlFree(str); - - if (ctxt != NULL) { - xmlParserPrintFileContext(input); - } + va_start(ap, msg); + xmlVFormatLegacyError(ctx, "validity warning", msg, ap); + va_end(ap); } @@ -982,42 +1018,351 @@ xmlCtxtResetLastError(void *ctx) */ int xmlCopyError(const xmlError *from, xmlErrorPtr to) { - char *message, *file, *str1, *str2, *str3; + const char *fmt = NULL; if ((from == NULL) || (to == NULL)) return(-1); - message = (char *) xmlStrdup((xmlChar *) from->message); - file = (char *) xmlStrdup ((xmlChar *) from->file); - str1 = (char *) xmlStrdup ((xmlChar *) from->str1); - str2 = (char *) xmlStrdup ((xmlChar *) from->str2); - str3 = (char *) xmlStrdup ((xmlChar *) from->str3); - - if (to->message != NULL) - xmlFree(to->message); - if (to->file != NULL) - xmlFree(to->file); - if (to->str1 != NULL) - xmlFree(to->str1); - if (to->str2 != NULL) - xmlFree(to->str2); - if (to->str3 != NULL) - xmlFree(to->str3); - to->domain = from->domain; - to->code = from->code; - to->level = from->level; - to->line = from->line; - to->node = from->node; - to->int1 = from->int1; - to->int2 = from->int2; - to->node = from->node; - to->ctxt = from->ctxt; - to->message = message; - to->file = file; - to->str1 = str1; - to->str2 = str2; - to->str3 = str3; - - return 0; + if (from->message != NULL) + fmt = "%s"; + + return(xmlSetError(to, from->ctxt, from->node, + from->domain, from->code, from->level, + from->file, from->line, + from->str1, from->str2, from->str3, + from->int1, from->int2, + fmt, from->message)); } +/** + * xmlErrString: + * @code: an xmlParserErrors code + * + * Returns an error message for a code. + */ +const char * +xmlErrString(xmlParserErrors code) { + const char *errmsg; + + switch (code) { + case XML_ERR_INVALID_HEX_CHARREF: + errmsg = "CharRef: invalid hexadecimal value"; + break; + case XML_ERR_INVALID_DEC_CHARREF: + errmsg = "CharRef: invalid decimal value"; + break; + case XML_ERR_INVALID_CHARREF: + errmsg = "CharRef: invalid value"; + break; + case XML_ERR_INTERNAL_ERROR: + errmsg = "internal error"; + break; + case XML_ERR_PEREF_AT_EOF: + errmsg = "PEReference at end of document"; + break; + case XML_ERR_PEREF_IN_PROLOG: + errmsg = "PEReference in prolog"; + break; + case XML_ERR_PEREF_IN_EPILOG: + errmsg = "PEReference in epilog"; + break; + case XML_ERR_PEREF_NO_NAME: + errmsg = "PEReference: no name"; + break; + case XML_ERR_PEREF_SEMICOL_MISSING: + errmsg = "PEReference: expecting ';'"; + break; + case XML_ERR_ENTITY_LOOP: + errmsg = "Detected an entity reference loop"; + break; + case XML_ERR_ENTITY_NOT_STARTED: + errmsg = "EntityValue: \" or ' expected"; + break; + case XML_ERR_ENTITY_PE_INTERNAL: + errmsg = "PEReferences forbidden in internal subset"; + break; + case XML_ERR_ENTITY_NOT_FINISHED: + errmsg = "EntityValue: \" or ' expected"; + break; + case XML_ERR_ATTRIBUTE_NOT_STARTED: + errmsg = "AttValue: \" or ' expected"; + break; + case XML_ERR_LT_IN_ATTRIBUTE: + errmsg = "Unescaped '<' not allowed in attributes values"; + break; + case XML_ERR_LITERAL_NOT_STARTED: + errmsg = "SystemLiteral \" or ' expected"; + break; + case XML_ERR_LITERAL_NOT_FINISHED: + errmsg = "Unfinished System or Public ID \" or ' expected"; + break; + case XML_ERR_MISPLACED_CDATA_END: + errmsg = "Sequence ']]>' not allowed in content"; + break; + case XML_ERR_URI_REQUIRED: + errmsg = "SYSTEM or PUBLIC, the URI is missing"; + break; + case XML_ERR_PUBID_REQUIRED: + errmsg = "PUBLIC, the Public Identifier is missing"; + break; + case XML_ERR_HYPHEN_IN_COMMENT: + errmsg = "Comment must not contain '--' (double-hyphen)"; + break; + case XML_ERR_PI_NOT_STARTED: + errmsg = "xmlParsePI : no target name"; + break; + case XML_ERR_RESERVED_XML_NAME: + errmsg = "Invalid PI name"; + break; + case XML_ERR_NOTATION_NOT_STARTED: + errmsg = "NOTATION: Name expected here"; + break; + case XML_ERR_NOTATION_NOT_FINISHED: + errmsg = "'>' required to close NOTATION declaration"; + break; + case XML_ERR_VALUE_REQUIRED: + errmsg = "Entity value required"; + break; + case XML_ERR_URI_FRAGMENT: + errmsg = "Fragment not allowed"; + break; + case XML_ERR_ATTLIST_NOT_STARTED: + errmsg = "'(' required to start ATTLIST enumeration"; + break; + case XML_ERR_NMTOKEN_REQUIRED: + errmsg = "NmToken expected in ATTLIST enumeration"; + break; + case XML_ERR_ATTLIST_NOT_FINISHED: + errmsg = "')' required to finish ATTLIST enumeration"; + break; + case XML_ERR_MIXED_NOT_STARTED: + errmsg = "MixedContentDecl : '|' or ')*' expected"; + break; + case XML_ERR_PCDATA_REQUIRED: + errmsg = "MixedContentDecl : '#PCDATA' expected"; + break; + case XML_ERR_ELEMCONTENT_NOT_STARTED: + errmsg = "ContentDecl : Name or '(' expected"; + break; + case XML_ERR_ELEMCONTENT_NOT_FINISHED: + errmsg = "ContentDecl : ',' '|' or ')' expected"; + break; + case XML_ERR_PEREF_IN_INT_SUBSET: + errmsg = + "PEReference: forbidden within markup decl in internal subset"; + break; + case XML_ERR_GT_REQUIRED: + errmsg = "expected '>'"; + break; + case XML_ERR_CONDSEC_INVALID: + errmsg = "XML conditional section '[' expected"; + break; + case XML_ERR_INT_SUBSET_NOT_FINISHED: + errmsg = "Content error in the internal subset"; + break; + case XML_ERR_EXT_SUBSET_NOT_FINISHED: + errmsg = "Content error in the external subset"; + break; + case XML_ERR_CONDSEC_INVALID_KEYWORD: + errmsg = + "conditional section INCLUDE or IGNORE keyword expected"; + break; + case XML_ERR_CONDSEC_NOT_FINISHED: + errmsg = "XML conditional section not closed"; + break; + case XML_ERR_XMLDECL_NOT_STARTED: + errmsg = "Text declaration '' expected"; + break; + case XML_ERR_EXT_ENTITY_STANDALONE: + errmsg = "external parsed entities cannot be standalone"; + break; + case XML_ERR_ENTITYREF_SEMICOL_MISSING: + errmsg = "EntityRef: expecting ';'"; + break; + case XML_ERR_DOCTYPE_NOT_FINISHED: + errmsg = "DOCTYPE improperly terminated"; + break; + case XML_ERR_LTSLASH_REQUIRED: + errmsg = "EndTag: ' #include #include -#include #include #include #include #include #include +#include "private/dict.h" #include "private/error.h" #include "private/globals.h" #include "private/threads.h" @@ -76,10 +76,13 @@ struct _xmlGlobalState { void *waitHandle; #endif +#ifdef LIBXML_THREAD_ENABLED + unsigned localRngState[2]; +#endif + #define XML_OP XML_DECLARE_MEMBER XML_GLOBALS_ALLOC XML_GLOBALS_ERROR -XML_GLOBALS_HTML XML_GLOBALS_IO XML_GLOBALS_PARSER XML_GLOBALS_TREE @@ -164,17 +167,14 @@ xmlFreeGlobalState(void *state); * * ************************************************************************/ +#ifdef LIBXML_THREAD_ENABLED +static unsigned xmlMainThreadRngState[2]; +#endif + /* * Memory allocation routines */ -#if defined(DEBUG_MEMORY_LOCATION) -xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree; -xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc; -xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc; -xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc; -xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup; -#else /** * xmlFree: * @mem: an already allocated block of memory @@ -233,7 +233,6 @@ xmlPosixStrdup(const char *cur) { * Returns the copy of the string or NULL in case of error */ xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup; -#endif /* DEBUG_MEMORY_LOCATION */ /** * xmlBufferAllocScheme: @@ -264,7 +263,7 @@ static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE; * * Global setting, DEPRECATED. */ -int oldXMLWDcompatibility = 0; /* DEPRECATED */ +const int oldXMLWDcompatibility = 0; /* DEPRECATED */ /** * xmlParserDebugEntities: * @@ -274,8 +273,7 @@ int oldXMLWDcompatibility = 0; /* DEPRECATED */ * while handling entities. * Disabled by default */ -int xmlParserDebugEntities = 0; -static int xmlParserDebugEntitiesThrDef = 0; +const int xmlParserDebugEntities = 0; /** * xmlDoValidityCheckingDefaultValue: * @@ -289,7 +287,7 @@ static int xmlDoValidityCheckingDefaultValueThrDef = 0; /** * xmlGetWarningsDefaultValue: * - * DEPRECATED: Don't use + * DEPRECATED: Use the modern options API with XML_PARSE_NOWARNING. * * Global setting, indicate that the DTD validation should provide warnings. * Activated by default. @@ -460,7 +458,7 @@ static int xmlSaveNoEmptyTagsThrDef = 0; * * Default SAX version1 handler for XML, builds the DOM tree */ -xmlSAXHandlerV1 xmlDefaultSAXHandler = { +const xmlSAXHandlerV1 xmlDefaultSAXHandler = { xmlSAX2InternalSubset, xmlSAX2IsStandalone, xmlSAX2HasInternalSubset, @@ -500,7 +498,7 @@ xmlSAXHandlerV1 xmlDefaultSAXHandler = { * The default SAX Locator * { getPublicId, getSystemId, getLineNumber, getColumnNumber} */ -xmlSAXLocator xmlDefaultSAXLocator = { +const xmlSAXLocator xmlDefaultSAXLocator = { xmlSAX2GetPublicId, xmlSAX2GetSystemId, xmlSAX2GetLineNumber, @@ -516,7 +514,7 @@ xmlSAXLocator xmlDefaultSAXLocator = { * * Default old SAX v1 handler for HTML, builds the DOM tree */ -xmlSAXHandlerV1 htmlDefaultSAXHandler = { +const xmlSAXHandlerV1 htmlDefaultSAXHandler = { xmlSAX2InternalSubset, NULL, NULL, @@ -596,6 +594,11 @@ void xmlInitGlobalsInternal(void) { #endif mainthread = GetCurrentThreadId(); #endif + +#ifdef LIBXML_THREAD_ENABLED + xmlMainThreadRngState[0] = xmlGlobalRandom(); + xmlMainThreadRngState[1] = xmlGlobalRandom(); +#endif } /** @@ -756,36 +759,21 @@ static void xmlInitGlobalState(xmlGlobalStatePtr gs) { xmlMutexLock(&xmlThrDefMutex); -#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED) - inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler); +#ifdef LIBXML_THREAD_ENABLED + gs->localRngState[0] = xmlGlobalRandom(); + gs->localRngState[1] = xmlGlobalRandom(); #endif - gs->gs_oldXMLWDcompatibility = 0; gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef; gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef; -#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED) - initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1); -#endif /* LIBXML_SAX1_ENABLED */ - gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId; - gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId; - gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber; - gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber; gs->gs_xmlDoValidityCheckingDefaultValue = xmlDoValidityCheckingDefaultValueThrDef; #ifdef LIBXML_THREAD_ALLOC_ENABLED -#ifdef DEBUG_MEMORY_LOCATION - gs->gs_xmlFree = xmlMemFree; - gs->gs_xmlMalloc = xmlMemMalloc; - gs->gs_xmlMallocAtomic = xmlMemMalloc; - gs->gs_xmlRealloc = xmlMemRealloc; - gs->gs_xmlMemStrdup = xmlMemoryStrdup; -#else gs->gs_xmlFree = free; gs->gs_xmlMalloc = malloc; gs->gs_xmlMallocAtomic = malloc; gs->gs_xmlRealloc = realloc; gs->gs_xmlMemStrdup = xmlPosixStrdup; -#endif #endif gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef; #ifdef LIBXML_OUTPUT_ENABLED @@ -796,7 +784,6 @@ xmlInitGlobalState(xmlGlobalStatePtr gs) { gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef; gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef; gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef; - gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef; gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef; gs->gs_xmlSubstituteEntitiesDefaultValue = xmlSubstituteEntitiesDefaultValueThrDef; @@ -904,12 +891,26 @@ xmlGetThreadLocalStorage(int allowFailure) { #define XML_OP XML_DEFINE_GLOBAL_WRAPPER XML_GLOBALS_ALLOC XML_GLOBALS_ERROR -XML_GLOBALS_HTML XML_GLOBALS_IO XML_GLOBALS_PARSER XML_GLOBALS_TREE #undef XML_OP +#ifdef LIBXML_THREAD_ENABLED +/** + * xmlGetLocalRngState: + * + * Returns the local RNG state. + */ +unsigned * +xmlGetLocalRngState(void) { + if (IS_MAIN_THREAD) + return(xmlMainThreadRngState); + else + return(xmlGetThreadLocalStorage(0)->localRngState); +} +#endif + /* For backward compatibility */ const char *const * @@ -917,6 +918,35 @@ __xmlParserVersion(void) { return &xmlParserVersion; } +const int * +__oldXMLWDcompatibility(void) { + return &oldXMLWDcompatibility; +} + +const int * +__xmlParserDebugEntities(void) { + return &xmlParserDebugEntities; +} + +const xmlSAXLocator * +__xmlDefaultSAXLocator(void) { + return &xmlDefaultSAXLocator; +} + +#ifdef LIBXML_SAX1_ENABLED +const xmlSAXHandlerV1 * +__xmlDefaultSAXHandler(void) { + return &xmlDefaultSAXHandler; +} + +#ifdef LIBXML_HTML_ENABLED +const xmlSAXHandlerV1 * +__htmlDefaultSAXHandler(void) { + return &htmlDefaultSAXHandler; +} +#endif /* LIBXML_HTML_ENABLED */ +#endif /* LIBXML_SAX1_ENABLED */ + #endif /* LIBXML_THREAD_ENABLED */ /** @@ -950,6 +980,8 @@ xmlCheckThreadLocalStorage(void) { return(0); } +/** DOC_DISABLE */ + /** * DllMain: * @hinstDLL: handle to DLL instance @@ -1115,13 +1147,8 @@ int xmlThrDefLoadExtDtdDefaultValue(int v) { return ret; } -int xmlThrDefParserDebugEntities(int v) { - int ret; - xmlMutexLock(&xmlThrDefMutex); - ret = xmlParserDebugEntitiesThrDef; - xmlParserDebugEntitiesThrDef = v; - xmlMutexUnlock(&xmlThrDefMutex); - return ret; +int xmlThrDefParserDebugEntities(int v ATTRIBUTE_UNUSED) { + return(xmlParserDebugEntities); } int xmlThrDefPedanticParserDefaultValue(int v) { @@ -1207,3 +1234,5 @@ xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc fun return(old); } +/** DOC_ENABLE */ + diff --git a/hash.c b/hash.c index 38341d7..6af8527 100644 --- a/hash.c +++ b/hash.c @@ -445,16 +445,9 @@ xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key, if (dealloc) dealloc(entry->payload, entry->key); entry->payload = payload; - return(0); - } else { - /* - * xmlHashAddEntry found an existing entry. - * - * TODO: We should return a different error code here to - * distinguish from malloc failures. - */ - return(-1); } + + return(0); } /* @@ -589,7 +582,7 @@ xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key, hash->nbElems++; - return(0); + return(1); } /** @@ -604,6 +597,70 @@ xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) { xmlFree(entry); } +/** + * xmlHashAdd: + * @hash: hash table + * @key: string key + * @payload: pointer to the payload + * + * Add a hash table entry. If an entry with this key already exists, + * payload will not be updated and 0 is returned. This return value + * can't be distinguished from out-of-memory errors, so this function + * should be used with care. + * + * Available since 2.13.0. + * + * Returns 1 on success, 0 if an entry exists and -1 in case of error. + */ +int +xmlHashAdd(xmlHashTablePtr hash, const xmlChar *key, void *payload) { + return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0)); +} + +/** + * xmlHashAdd2: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @payload: pointer to the payload + * + * Add a hash table entry with two strings as key. + * + * See xmlHashAdd. + * + * Available since 2.13.0. + * + * Returns 1 on success, 0 if an entry exists and -1 in case of error. + */ +int +xmlHashAdd2(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, void *payload) { + return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0)); +} + +/** + * xmlHashAdd3: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key + * @payload: pointer to the payload + * + * Add a hash table entry with three strings as key. + * + * See xmlHashAdd. + * + * Available since 2.13.0. + * + * Returns 1 on success, 0 if an entry exists and -1 in case of error. + */ +int +xmlHashAdd3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + void *payload) { + return(xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0)); +} + /** * xmlHashAddEntry: * @hash: hash table @@ -615,11 +672,21 @@ xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) { * can't be distinguished from out-of-memory errors, so this function * should be used with care. * + * NOTE: This function doesn't allow to distinguish malloc failures from + * existing entries. Use xmlHashAdd instead. + * * Returns 0 on success and -1 in case of error. */ int xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) { - return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0)); + int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0); + + if (res == 0) + res = -1; + else if (res == 1) + res = 0; + + return(res); } /** @@ -638,7 +705,14 @@ xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) { int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload) { - return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0)); + int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0); + + if (res == 0) + res = -1; + else if (res == 1) + res = 0; + + return(res); } /** @@ -659,7 +733,14 @@ int xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, void *payload) { - return(xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0)); + int res = xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0); + + if (res == 0) + res = -1; + else if (res == 1) + res = 0; + + return(res); } /** @@ -677,8 +758,13 @@ xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key, int xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload, xmlHashDeallocator dealloc) { - return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, - dealloc, 1)); + int res = xmlHashUpdateInternal(hash, key, NULL, NULL, payload, + dealloc, 1); + + if (res == 1) + res = 0; + + return(res); } /** @@ -699,8 +785,13 @@ int xmlHashUpdateEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload, xmlHashDeallocator dealloc) { - return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, - dealloc, 1)); + int res = xmlHashUpdateInternal(hash, key, key2, NULL, payload, + dealloc, 1); + + if (res == 1) + res = 0; + + return(res); } /** @@ -722,8 +813,13 @@ int xmlHashUpdateEntry3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, void *payload, xmlHashDeallocator dealloc) { - return(xmlHashUpdateInternal(hash, key, key2, key3, payload, - dealloc, 1)); + int res = xmlHashUpdateInternal(hash, key, key2, key3, payload, + dealloc, 1); + + if (res == 1) + res = 0; + + return(res); } /** @@ -1037,21 +1133,25 @@ xmlHashScanFull3(xmlHashTablePtr hash, const xmlChar *key, } } -/** - * xmlHashCopy: +/* + * xmlHashCopySafe: * @hash: hash table - * @copy: copier function for items in the hash + * @copyFunc: copier function for items in the hash + * @deallocFunc: deallocation function in case of errors + * + * Copy the hash table using @copyFunc to copy payloads. * - * Copy the hash @table using @copy to copy payloads. + * Available since 2.13.0. * * Returns the new table or NULL if a memory allocation failed. */ xmlHashTablePtr -xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) { +xmlHashCopySafe(xmlHashTablePtr hash, xmlHashCopier copyFunc, + xmlHashDeallocator deallocFunc) { const xmlHashEntry *entry, *end; xmlHashTablePtr ret; - if ((hash == NULL) || (copy == NULL)) + if ((hash == NULL) || (copyFunc == NULL)) return(NULL); ret = xmlHashCreate(hash->size); @@ -1064,12 +1164,42 @@ xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) { end = &hash->table[hash->size]; for (entry = hash->table; entry < end; entry++) { - if (entry->hashValue != 0) - xmlHashAddEntry3(ret, entry->key, entry->key2, entry->key3, - copy(entry->payload, entry->key)); + if (entry->hashValue != 0) { + void *copy; + + copy = copyFunc(entry->payload, entry->key); + if (copy == NULL) + goto error; + if (xmlHashAdd3(ret, entry->key, entry->key2, entry->key3, + copy) <= 0) { + if (deallocFunc != NULL) + deallocFunc(copy, entry->key); + goto error; + } + } } return(ret); + +error: + xmlHashFree(ret, deallocFunc); + return(NULL); +} + +/* + * xmlHashCopy: + * @hash: hash table + * @copy: copier function for items in the hash + * + * DEPRECATED: Leaks memory in error case. + * + * Copy the hash table using @copy to copy payloads. + * + * Returns the new table or NULL if a memory allocation failed. + */ +xmlHashTablePtr +xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) { + return(xmlHashCopySafe(hash, copy, NULL)); } /** diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h index e16d774..7be3d2b 100644 --- a/include/libxml/HTMLparser.h +++ b/include/libxml/HTMLparser.h @@ -80,22 +80,17 @@ struct _htmlEntityDesc { const char *desc; /* the description */ }; -/** DOC_DISABLE */ #ifdef LIBXML_SAX1_ENABLED - #define XML_GLOBALS_HTML \ - XML_OP(htmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED) -#else - #define XML_GLOBALS_HTML -#endif -#define XML_OP XML_DECLARE_GLOBAL -XML_GLOBALS_HTML -#undef XML_OP +XML_DEPRECATED +XMLPUBVAR const xmlSAXHandlerV1 htmlDefaultSAXHandler; -#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) - #define htmlDefaultSAXHandler XML_GLOBAL_MACRO(htmlDefaultSAXHandler) +#ifdef LIBXML_THREAD_ENABLED +XML_DEPRECATED +XMLPUBFUN const xmlSAXHandlerV1 *__htmlDefaultSAXHandler(void); #endif -/** DOC_ENABLE */ + +#endif /* LIBXML_SAX1_ENABLED */ /* * There is only few public functions. @@ -173,6 +168,7 @@ XMLPUBFUN int int *inlen, int quoteChar); XMLPUBFUN int htmlIsScriptAttribute(const xmlChar *name); +XML_DEPRECATED XMLPUBFUN int htmlHandleOmittedElem(int val); @@ -251,6 +247,9 @@ XMLPUBFUN htmlDocPtr const char *URL, const char *encoding, int options); +XMLPUBFUN htmlDocPtr + htmlCtxtParseDocument (htmlParserCtxtPtr ctxt, + xmlParserInputPtr input); XMLPUBFUN htmlDocPtr htmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, @@ -300,7 +299,7 @@ typedef enum { XMLPUBFUN htmlStatus htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ; XMLPUBFUN int htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ; XMLPUBFUN htmlStatus htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ; -XMLPUBFUN htmlStatus htmlNodeStatus(const htmlNodePtr, int) ; +XMLPUBFUN htmlStatus htmlNodeStatus(htmlNodePtr, int) ; /** * htmlDefaultSubelement: * @elt: HTML element @@ -333,11 +332,5 @@ XMLPUBFUN htmlStatus htmlNodeStatus(const htmlNodePtr, int) ; } #endif -#else /* LIBXML_HTML_ENABLED */ - -/** DOC_DISABLE */ -#define XML_GLOBALS_HTML -/** DOC_ENABLE */ - #endif /* LIBXML_HTML_ENABLED */ #endif /* __HTML_PARSER_H__ */ diff --git a/include/libxml/c14n.h b/include/libxml/c14n.h index f9bdf9b..8ccd1ce 100644 --- a/include/libxml/c14n.h +++ b/include/libxml/c14n.h @@ -39,18 +39,7 @@ extern "C" { * a) default attributes (if any) are added to all nodes * b) all character and parsed entity references are resolved * In order to achieve this in libxml2 the document MUST be loaded with - * following global settings: - * - * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; - * xmlSubstituteEntitiesDefault(1); - * - * or corresponding parser context setting: - * xmlParserCtxtPtr ctxt; - * - * ... - * ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; - * ctxt->replaceEntities = 1; - * ... + * following options: XML_PARSE_DTDATTR | XML_PARSE_NOENT */ /* diff --git a/include/libxml/debugXML.h b/include/libxml/debugXML.h index 8274687..1332dd7 100644 --- a/include/libxml/debugXML.h +++ b/include/libxml/debugXML.h @@ -203,7 +203,7 @@ XMLPUBFUN int */ XMLPUBFUN void xmlShell (xmlDocPtr doc, - char *filename, + const char *filename, xmlShellReadlineFunc input, FILE *output); diff --git a/include/libxml/encoding.h b/include/libxml/encoding.h index 8594cff..599a03e 100644 --- a/include/libxml/encoding.h +++ b/include/libxml/encoding.h @@ -162,6 +162,13 @@ XMLPUBFUN void xmlCleanupCharEncodingHandlers (void); XMLPUBFUN void xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler); +XMLPUBFUN int + xmlLookupCharEncodingHandler (xmlCharEncoding enc, + xmlCharEncodingHandlerPtr *out); +XMLPUBFUN int + xmlOpenCharEncodingHandler (const char *name, + int output, + xmlCharEncodingHandlerPtr *out); XMLPUBFUN xmlCharEncodingHandlerPtr xmlGetCharEncodingHandler (xmlCharEncoding enc); XMLPUBFUN xmlCharEncodingHandlerPtr @@ -195,7 +202,9 @@ XMLPUBFUN xmlCharEncoding xmlDetectCharEncoding (const unsigned char *in, int len); +/** DOC_DISABLE */ struct _xmlBuffer; +/** DOC_ENABLE */ XMLPUBFUN int xmlCharEncOutFunc (xmlCharEncodingHandler *handler, struct _xmlBuffer *out, diff --git a/include/libxml/entities.h b/include/libxml/entities.h index f679375..96029ba 100644 --- a/include/libxml/entities.h +++ b/include/libxml/entities.h @@ -12,9 +12,7 @@ #define __XML_ENTITIES_H__ #include -#define XML_TREE_INTERNALS #include -#undef XML_TREE_INTERNALS #ifdef __cplusplus extern "C" { @@ -57,7 +55,7 @@ struct _xmlEntity { struct _xmlEntity *nexte; /* unused */ const xmlChar *URI; /* the full URI as computed */ - int owner; /* does the entity own the childrens */ + int owner; /* unused */ int flags; /* various flags */ unsigned long expandedSize; /* expanded size */ }; @@ -89,6 +87,15 @@ XMLPUBFUN xmlEntityPtr const xmlChar *content); XMLPUBFUN void xmlFreeEntity (xmlEntityPtr entity); +XMLPUBFUN int + xmlAddEntity (xmlDocPtr doc, + int extSubset, + const xmlChar *name, + int type, + const xmlChar *ExternalID, + const xmlChar *SystemID, + const xmlChar *content, + xmlEntityPtr *out); XMLPUBFUN xmlEntityPtr xmlAddDocEntity (xmlDocPtr doc, const xmlChar *name, diff --git a/include/libxml/hash.h b/include/libxml/hash.h index f4af09e..135b696 100644 --- a/include/libxml/hash.h +++ b/include/libxml/hash.h @@ -109,6 +109,10 @@ XMLPUBFUN void /* * Add a new entry to the hash table. */ +XMLPUBFUN int + xmlHashAdd (xmlHashTablePtr hash, + const xmlChar *name, + void *userdata); XMLPUBFUN int xmlHashAddEntry (xmlHashTablePtr hash, const xmlChar *name, @@ -118,6 +122,11 @@ XMLPUBFUN int const xmlChar *name, void *userdata, xmlHashDeallocator dealloc); +XMLPUBFUN int + xmlHashAdd2 (xmlHashTablePtr hash, + const xmlChar *name, + const xmlChar *name2, + void *userdata); XMLPUBFUN int xmlHashAddEntry2 (xmlHashTablePtr hash, const xmlChar *name, @@ -129,6 +138,12 @@ XMLPUBFUN int const xmlChar *name2, void *userdata, xmlHashDeallocator dealloc); +XMLPUBFUN int + xmlHashAdd3 (xmlHashTablePtr hash, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + void *userdata); XMLPUBFUN int xmlHashAddEntry3 (xmlHashTablePtr hash, const xmlChar *name, @@ -199,6 +214,10 @@ XMLPUBFUN void * /* * Helpers. */ +XMLPUBFUN xmlHashTablePtr + xmlHashCopySafe (xmlHashTablePtr hash, + xmlHashCopier copy, + xmlHashDeallocator dealloc); XMLPUBFUN xmlHashTablePtr xmlHashCopy (xmlHashTablePtr hash, xmlHashCopier copy); diff --git a/include/libxml/list.h b/include/libxml/list.h index 5eab8f5..1fa76af 100644 --- a/include/libxml/list.h +++ b/include/libxml/list.h @@ -119,10 +119,10 @@ XMLPUBFUN void xmlListMerge (xmlListPtr l1, xmlListPtr l2); XMLPUBFUN xmlListPtr - xmlListDup (const xmlListPtr old); + xmlListDup (xmlListPtr old); XMLPUBFUN int xmlListCopy (xmlListPtr cur, - const xmlListPtr old); + xmlListPtr old); /* Link operators */ XMLPUBFUN void * xmlLinkGetData (xmlLinkPtr lk); diff --git a/include/libxml/nanohttp.h b/include/libxml/nanohttp.h index 3b5e037..c70d1c2 100644 --- a/include/libxml/nanohttp.h +++ b/include/libxml/nanohttp.h @@ -18,16 +18,21 @@ #ifdef __cplusplus extern "C" { #endif +XML_DEPRECATED XMLPUBFUN void xmlNanoHTTPInit (void); +XML_DEPRECATED XMLPUBFUN void xmlNanoHTTPCleanup (void); +XML_DEPRECATED XMLPUBFUN void xmlNanoHTTPScanProxy (const char *URL); +XML_DEPRECATED XMLPUBFUN int xmlNanoHTTPFetch (const char *URL, const char *filename, char **contentType); +XML_DEPRECATED XMLPUBFUN void * xmlNanoHTTPMethod (const char *URL, const char *method, @@ -35,6 +40,7 @@ XMLPUBFUN void * char **contentType, const char *headers, int ilen); +XML_DEPRECATED XMLPUBFUN void * xmlNanoHTTPMethodRedir (const char *URL, const char *method, @@ -43,34 +49,45 @@ XMLPUBFUN void * char **redir, const char *headers, int ilen); +XML_DEPRECATED XMLPUBFUN void * xmlNanoHTTPOpen (const char *URL, char **contentType); +XML_DEPRECATED XMLPUBFUN void * xmlNanoHTTPOpenRedir (const char *URL, char **contentType, char **redir); +XML_DEPRECATED XMLPUBFUN int xmlNanoHTTPReturnCode (void *ctx); +XML_DEPRECATED XMLPUBFUN const char * xmlNanoHTTPAuthHeader (void *ctx); +XML_DEPRECATED XMLPUBFUN const char * xmlNanoHTTPRedir (void *ctx); +XML_DEPRECATED XMLPUBFUN int xmlNanoHTTPContentLength( void * ctx ); +XML_DEPRECATED XMLPUBFUN const char * xmlNanoHTTPEncoding (void *ctx); +XML_DEPRECATED XMLPUBFUN const char * xmlNanoHTTPMimeType (void *ctx); +XML_DEPRECATED XMLPUBFUN int xmlNanoHTTPRead (void *ctx, void *dest, int len); #ifdef LIBXML_OUTPUT_ENABLED +XML_DEPRECATED XMLPUBFUN int xmlNanoHTTPSave (void *ctxt, const char *filename); #endif /* LIBXML_OUTPUT_ENABLED */ +XML_DEPRECATED XMLPUBFUN void xmlNanoHTTPClose (void *ctx); #ifdef __cplusplus diff --git a/include/libxml/parser.h b/include/libxml/parser.h index 87aacef..86dd54f 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -11,9 +11,7 @@ #define __XML_PARSER_H__ #include -#define XML_TREE_INTERNALS #include -#undef XML_TREE_INTERNALS #include #include #include @@ -62,11 +60,11 @@ struct _xmlParserInput { xmlParserInputBufferPtr buf; /* UTF-8 encoded buffer */ const char *filename; /* The file analyzed, if any */ - const char *directory; /* the directory/base of the file */ + const char *directory; /* unused */ const xmlChar *base; /* Base of the array to parse */ const xmlChar *cur; /* Current char being parsed */ const xmlChar *end; /* end of the array to parse */ - int length; /* length if known */ + int length; /* unused */ int line; /* Current line */ int col; /* Current column */ unsigned long consumed; /* How many xmlChars already consumed */ @@ -75,7 +73,7 @@ struct _xmlParserInput { const xmlChar *version; /* the version string for entity */ int flags; /* Flags */ int id; /* an unique identifier for the entity */ - unsigned long parentConsumed; /* consumed bytes from parents */ + unsigned long parentConsumed; /* unused */ xmlEntityPtr entity; /* entity, if any */ }; @@ -134,30 +132,14 @@ typedef enum { XML_PARSER_XML_DECL /* before XML decl (but after BOM) */ } xmlParserInputState; -/** - * XML_DETECT_IDS: - * - * Bit in the loadsubset context field to tell to do ID/REFs lookups. - * Use it to initialize xmlLoadExtDtdDefaultValue. +/** DOC_DISABLE */ +/* + * Internal bits in the 'loadsubset' context member */ #define XML_DETECT_IDS 2 - -/** - * XML_COMPLETE_ATTRS: - * - * Bit in the loadsubset context field to tell to do complete the - * elements attributes lists with the ones defaulted from the DTDs. - * Use it to initialize xmlLoadExtDtdDefaultValue. - */ #define XML_COMPLETE_ATTRS 4 - -/** - * XML_SKIP_IDS: - * - * Bit in the loadsubset context field to tell to not do ID/REFs registration. - * Used to initialize xmlLoadExtDtdDefaultValue in some special cases. - */ #define XML_SKIP_IDS 8 +/** DOC_ENABLE */ /** * xmlParserMode: @@ -222,16 +204,16 @@ struct _xmlParserCtxt { int hasExternalSubset; /* reference and external subset */ int hasPErefs; /* the internal subset has PE refs */ - int external; /* are we parsing an external entity */ + int external; /* unused */ int valid; /* is the document valid */ int validate; /* shall we try to validate ? */ xmlValidCtxt vctxt; /* The validity context */ - xmlParserInputState instate; /* current type of input */ - int token; /* next char look-ahead */ + xmlParserInputState instate; /* push parser state */ + int token; /* unused */ - char *directory; /* the data directory */ + char *directory; /* unused */ /* Node name stack */ const xmlChar *name; /* Current parsed Node */ @@ -255,7 +237,7 @@ struct _xmlParserCtxt { int * spaceTab; /* array of space infos */ int depth; /* to prevent entity substitution loops */ - xmlParserInputPtr entity; /* used to check entities boundaries */ + xmlParserInputPtr entity; /* unused */ int charset; /* unused */ int nodelen; /* Those two fields are there to */ int nodemem; /* Speed up large node parsing */ @@ -266,11 +248,11 @@ struct _xmlParserCtxt { int linenumbers; /* set line number in element content */ void *catalogs; /* document's own catalog */ int recovery; /* run in recovery mode */ - int progressive; /* is this a progressive parsing */ + int progressive; /* unused */ xmlDictPtr dict; /* dictionary for the parser */ const xmlChar * *atts; /* array for the attributes callbacks */ int maxatts; /* the size of the array */ - int docdict; /* use strings from dict to build tree */ + int docdict; /* unused */ /* * pre-interned strings @@ -308,7 +290,7 @@ struct _xmlParserCtxt { xmlError lastError; xmlParserMode parseMode; /* the parser mode */ unsigned long nbentities; /* unused */ - unsigned long sizeentities; /* size of parsed entities */ + unsigned long sizeentities; /* size of external entities */ /* for use by HTML non-recursive parser */ xmlParserNodeInfo *nodeInfo; /* Current NodeInfo */ @@ -327,6 +309,9 @@ struct _xmlParserCtxt { xmlParserNsData *nsdb; /* namespace database */ unsigned attrHashMax; /* allocated size */ xmlAttrHashBucket *attrHash; /* atttribute hash table */ + + xmlStructuredErrorFunc errorHandler; + void *errorCtxt; }; /** @@ -843,21 +828,39 @@ typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL, */ XMLPUBVAR const char *const xmlParserVersion; +XML_DEPRECATED +XMLPUBVAR const int oldXMLWDcompatibility; +XML_DEPRECATED +XMLPUBVAR const int xmlParserDebugEntities; +XML_DEPRECATED +XMLPUBVAR const xmlSAXLocator xmlDefaultSAXLocator; +#ifdef LIBXML_SAX1_ENABLED +XML_DEPRECATED +XMLPUBVAR const xmlSAXHandlerV1 xmlDefaultSAXHandler; +#endif + #ifdef LIBXML_THREAD_ENABLED /* backward compatibility */ XMLPUBFUN const char *const *__xmlParserVersion(void); +XML_DEPRECATED +XMLPUBFUN const int *__oldXMLWDcompatibility(void); +XML_DEPRECATED +XMLPUBFUN const int *__xmlParserDebugEntities(void); +XML_DEPRECATED +XMLPUBFUN const xmlSAXLocator *__xmlDefaultSAXLocator(void); +#ifdef LIBXML_SAX1_ENABLED +XML_DEPRECATED +XMLPUBFUN const xmlSAXHandlerV1 *__xmlDefaultSAXHandler(void); +#endif #endif /** DOC_DISABLE */ #define XML_GLOBALS_PARSER_CORE \ - XML_OP(oldXMLWDcompatibility, int, XML_DEPRECATED) \ - XML_OP(xmlDefaultSAXLocator, xmlSAXLocator, XML_DEPRECATED) \ XML_OP(xmlDoValidityCheckingDefaultValue, int, XML_DEPRECATED) \ XML_OP(xmlGetWarningsDefaultValue, int, XML_DEPRECATED) \ XML_OP(xmlKeepBlanksDefaultValue, int, XML_DEPRECATED) \ XML_OP(xmlLineNumbersDefaultValue, int, XML_DEPRECATED) \ XML_OP(xmlLoadExtDtdDefaultValue, int, XML_DEPRECATED) \ - XML_OP(xmlParserDebugEntities, int, XML_DEPRECATED) \ XML_OP(xmlPedanticParserDefaultValue, int, XML_DEPRECATED) \ XML_OP(xmlSubstituteEntitiesDefaultValue, int, XML_DEPRECATED) @@ -870,26 +873,15 @@ XMLPUBFUN const char *const *__xmlParserVersion(void); #define XML_GLOBALS_PARSER_OUTPUT #endif -#ifdef LIBXML_SAX1_ENABLED - #define XML_GLOBALS_PARSER_SAX1 \ - XML_OP(xmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED) -#else - #define XML_GLOBALS_PARSER_SAX1 -#endif - #define XML_GLOBALS_PARSER \ XML_GLOBALS_PARSER_CORE \ - XML_GLOBALS_PARSER_OUTPUT \ - XML_GLOBALS_PARSER_SAX1 + XML_GLOBALS_PARSER_OUTPUT #define XML_OP XML_DECLARE_GLOBAL XML_GLOBALS_PARSER #undef XML_OP #if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) - #define oldXMLWDcompatibility XML_GLOBAL_MACRO(oldXMLWDcompatibility) - #define xmlDefaultSAXHandler XML_GLOBAL_MACRO(xmlDefaultSAXHandler) - #define xmlDefaultSAXLocator XML_GLOBAL_MACRO(xmlDefaultSAXLocator) #define xmlDoValidityCheckingDefaultValue \ XML_GLOBAL_MACRO(xmlDoValidityCheckingDefaultValue) #define xmlGetWarningsDefaultValue \ @@ -898,7 +890,6 @@ XML_GLOBALS_PARSER #define xmlLineNumbersDefaultValue \ XML_GLOBAL_MACRO(xmlLineNumbersDefaultValue) #define xmlLoadExtDtdDefaultValue XML_GLOBAL_MACRO(xmlLoadExtDtdDefaultValue) - #define xmlParserDebugEntities XML_GLOBAL_MACRO(xmlParserDebugEntities) #define xmlPedanticParserDefaultValue \ XML_GLOBAL_MACRO(xmlPedanticParserDefaultValue) #define xmlSubstituteEntitiesDefaultValue \ @@ -1185,18 +1176,18 @@ XMLPUBFUN xmlParserInputPtr * Node infos. */ XMLPUBFUN const xmlParserNodeInfo* - xmlParserFindNodeInfo (const xmlParserCtxtPtr ctxt, - const xmlNodePtr node); + xmlParserFindNodeInfo (xmlParserCtxtPtr ctxt, + xmlNodePtr node); XMLPUBFUN void xmlInitNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); XMLPUBFUN void xmlClearNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); XMLPUBFUN unsigned long - xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq, - const xmlNodePtr node); + xmlParserFindNodeInfoIndex(xmlParserNodeInfoSeqPtr seq, + xmlNodePtr node); XMLPUBFUN void xmlParserAddNodeInfo (xmlParserCtxtPtr ctxt, - const xmlParserNodeInfoPtr info); + xmlParserNodeInfoPtr info); /* * External entities handling actually implemented in xmlIO. @@ -1251,7 +1242,8 @@ typedef enum { XML_PARSE_HUGE = 1<<19,/* relax any hardcoded limit from the parser */ XML_PARSE_OLDSAX = 1<<20,/* parse using SAX2 interface before 2.7.0 */ XML_PARSE_IGNORE_ENC= 1<<21,/* ignore internal document encoding hint */ - XML_PARSE_BIG_LINES = 1<<22 /* Store big lines numbers in text PSVI field */ + XML_PARSE_BIG_LINES = 1<<22,/* Store big lines numbers in text PSVI field */ + XML_PARSE_NO_XXE = 1<<23 /* disable loading of external content */ } xmlParserOption; XMLPUBFUN void @@ -1262,9 +1254,16 @@ XMLPUBFUN int int size, const char *filename, const char *encoding); +XMLPUBFUN int + xmlCtxtSetOptions (xmlParserCtxtPtr ctxt, + int options); XMLPUBFUN int xmlCtxtUseOptions (xmlParserCtxtPtr ctxt, int options); +XMLPUBFUN void + xmlCtxtSetErrorHandler (xmlParserCtxtPtr ctxt, + xmlStructuredErrorFunc handler, + void *data); XMLPUBFUN void xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl); @@ -1295,6 +1294,9 @@ XMLPUBFUN xmlDocPtr const char *URL, const char *encoding, int options); +XMLPUBFUN xmlDocPtr + xmlCtxtParseDocument (xmlParserCtxtPtr ctxt, + xmlParserInputPtr input); XMLPUBFUN xmlDocPtr xmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, @@ -1368,7 +1370,7 @@ typedef enum { XML_WITH_MODULES = 27, XML_WITH_DEBUG = 28, XML_WITH_DEBUG_MEM = 29, - XML_WITH_DEBUG_RUN = 30, + XML_WITH_DEBUG_RUN = 30, /* unused */ XML_WITH_ZLIB = 31, XML_WITH_ICU = 32, XML_WITH_LZMA = 33, diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h index 073ddf3..a79bb62 100644 --- a/include/libxml/parserInternals.h +++ b/include/libxml/parserInternals.h @@ -25,11 +25,14 @@ extern "C" { /** * xmlParserMaxDepth: * + * DEPRECATED: has no effect + * * arbitrary depth limit for the XML documents that we allow to * process. This is not a limitation of the parser but a safety * boundary feature, use XML_PARSE_HUGE option to override it. */ -XMLPUBVAR unsigned int xmlParserMaxDepth; +XML_DEPRECATED +XMLPUBVAR const unsigned int xmlParserMaxDepth; /** * XML_MAX_TEXT_LENGTH: @@ -313,9 +316,14 @@ XMLPUBFUN xmlParserCtxtPtr xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, const xmlChar *base); +XMLPUBFUN void + xmlCtxtErrMemory (xmlParserCtxtPtr ctxt); XMLPUBFUN int xmlSwitchEncoding (xmlParserCtxtPtr ctxt, xmlCharEncoding enc); +XMLPUBFUN int + xmlSwitchEncodingName (xmlParserCtxtPtr ctxt, + const char *encoding); XMLPUBFUN int xmlSwitchToEncoding (xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler); diff --git a/include/libxml/pattern.h b/include/libxml/pattern.h index 72bf239..947f090 100644 --- a/include/libxml/pattern.h +++ b/include/libxml/pattern.h @@ -54,6 +54,12 @@ XMLPUBFUN xmlPatternPtr xmlDict *dict, int flags, const xmlChar **namespaces); +XMLPUBFUN int + xmlPatternCompileSafe (const xmlChar *pattern, + xmlDict *dict, + int flags, + const xmlChar **namespaces, + xmlPatternPtr *patternOut); XMLPUBFUN int xmlPatternMatch (xmlPatternPtr comp, xmlNodePtr node); diff --git a/include/libxml/tree.h b/include/libxml/tree.h index a90a174..19bb126 100644 --- a/include/libxml/tree.h +++ b/include/libxml/tree.h @@ -9,15 +9,6 @@ * Author: Daniel Veillard */ -#ifndef XML_TREE_INTERNALS - -/* - * Emulate circular dependency for backward compatibility - */ -#include - -#else /* XML_TREE_INTERNALS */ - #ifndef __XML_TREE_H__ #define __XML_TREE_H__ @@ -173,13 +164,13 @@ typedef enum { XML_TEXT_NODE= 3, XML_CDATA_SECTION_NODE= 4, XML_ENTITY_REF_NODE= 5, - XML_ENTITY_NODE= 6, + XML_ENTITY_NODE= 6, /* unused */ XML_PI_NODE= 7, XML_COMMENT_NODE= 8, XML_DOCUMENT_NODE= 9, - XML_DOCUMENT_TYPE_NODE= 10, + XML_DOCUMENT_TYPE_NODE= 10, /* unused */ XML_DOCUMENT_FRAG_NODE= 11, - XML_NOTATION_NODE= 12, + XML_NOTATION_NODE= 12, /* unused */ XML_HTML_DOCUMENT_NODE= 13, XML_DTD_NODE= 14, XML_ELEMENT_DECL= 15, @@ -449,6 +440,7 @@ struct _xmlAttr { xmlNs *ns; /* pointer to the associated namespace */ xmlAttributeType atype; /* the attribute type if validating */ void *psvi; /* for type/PSVI information */ + struct _xmlID *id; /* the ID struct */ }; /** @@ -1011,10 +1003,10 @@ XMLPUBFUN void xmlFreeNodeList (xmlNodePtr cur); XMLPUBFUN void xmlFreeNode (xmlNodePtr cur); -XMLPUBFUN void +XMLPUBFUN int xmlSetTreeDoc (xmlNodePtr tree, xmlDocPtr doc); -XMLPUBFUN void +XMLPUBFUN int xmlSetListDoc (xmlNodePtr list, xmlDocPtr doc); /* @@ -1030,6 +1022,10 @@ XMLPUBFUN xmlNsPtr const xmlChar *href); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int + xmlGetNsListSafe (const xmlDoc *doc, + const xmlNode *node, + xmlNsPtr **out); XMLPUBFUN xmlNsPtr * xmlGetNsList (const xmlDoc *doc, const xmlNode *node); @@ -1059,6 +1055,11 @@ XMLPUBFUN xmlAttrPtr const xmlChar *value); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */ +XMLPUBFUN int + xmlNodeGetAttrValue (const xmlNode *node, + const xmlChar *name, + const xmlChar *nsUri, + xmlChar **out); XMLPUBFUN xmlChar * xmlGetNoNsProp (const xmlNode *node, const xmlChar *name); @@ -1093,19 +1094,19 @@ XMLPUBFUN xmlChar * const xmlNode *list, int inLine); #endif /* LIBXML_TREE_ENABLED */ -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetContent (xmlNodePtr cur, const xmlChar *content); #ifdef LIBXML_TREE_ENABLED -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetContentLen (xmlNodePtr cur, const xmlChar *content, int len); #endif /* LIBXML_TREE_ENABLED */ -XMLPUBFUN void +XMLPUBFUN int xmlNodeAddContent (xmlNodePtr cur, const xmlChar *content); -XMLPUBFUN void +XMLPUBFUN int xmlNodeAddContentLen (xmlNodePtr cur, const xmlChar *content, int len); @@ -1124,18 +1125,22 @@ XMLPUBFUN xmlChar * XMLPUBFUN int xmlNodeGetSpacePreserve (const xmlNode *cur); #ifdef LIBXML_TREE_ENABLED -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetLang (xmlNodePtr cur, const xmlChar *lang); -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetSpacePreserve (xmlNodePtr cur, int val); #endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN int + xmlNodeGetBaseSafe (const xmlDoc *doc, + const xmlNode *cur, + xmlChar **baseOut); XMLPUBFUN xmlChar * xmlNodeGetBase (const xmlDoc *doc, const xmlNode *cur); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetBase (xmlNodePtr cur, const xmlChar *uri); #endif @@ -1283,8 +1288,10 @@ XMLPUBFUN int XMLPUBFUN void xmlSetDocCompressMode (xmlDocPtr doc, int mode); +XML_DEPRECATED XMLPUBFUN int xmlGetCompressMode (void); +XML_DEPRECATED XMLPUBFUN void xmlSetCompressMode (int mode); @@ -1338,12 +1345,16 @@ XMLPUBFUN xmlNodePtr xmlPreviousElementSibling (xmlNodePtr node); #endif +XML_DEPRECATED XMLPUBFUN xmlRegisterNodeFunc xmlRegisterNodeDefault (xmlRegisterNodeFunc func); +XML_DEPRECATED XMLPUBFUN xmlDeregisterNodeFunc xmlDeregisterNodeDefault (xmlDeregisterNodeFunc func); +XML_DEPRECATED XMLPUBFUN xmlRegisterNodeFunc xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); +XML_DEPRECATED XMLPUBFUN xmlDeregisterNodeFunc xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); @@ -1358,5 +1369,3 @@ XML_DEPRECATED XMLPUBFUN int #endif /* __XML_TREE_H__ */ -#endif /* XML_TREE_INTERNALS */ - diff --git a/include/libxml/uri.h b/include/libxml/uri.h index eb8631c..19980b7 100644 --- a/include/libxml/uri.h +++ b/include/libxml/uri.h @@ -52,14 +52,25 @@ struct _xmlURI { */ XMLPUBFUN xmlURIPtr xmlCreateURI (void); +XMLPUBFUN int + xmlBuildURISafe (const xmlChar *URI, + const xmlChar *base, + xmlChar **out); XMLPUBFUN xmlChar * xmlBuildURI (const xmlChar *URI, const xmlChar *base); +XMLPUBFUN int + xmlBuildRelativeURISafe (const xmlChar *URI, + const xmlChar *base, + xmlChar **out); XMLPUBFUN xmlChar * xmlBuildRelativeURI (const xmlChar *URI, const xmlChar *base); XMLPUBFUN xmlURIPtr xmlParseURI (const char *str); +XMLPUBFUN int + xmlParseURISafe (const char *str, + xmlURIPtr *uri); XMLPUBFUN xmlURIPtr xmlParseURIRaw (const char *str, int raw); diff --git a/include/libxml/valid.h b/include/libxml/valid.h index 3e04b55..361e965 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -13,9 +13,7 @@ #include #include -#define XML_TREE_INTERNALS #include -#undef XML_TREE_INTERNALS #include #include #include @@ -150,9 +148,11 @@ XMLPUBFUN xmlNotationTablePtr XMLPUBFUN void xmlFreeNotationTable (xmlNotationTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED +XML_DEPRECATED XMLPUBFUN void xmlDumpNotationDecl (xmlBufferPtr buf, xmlNotationPtr nota); +/* XML_DEPRECATED, still used in lxml */ XMLPUBFUN void xmlDumpNotationTable (xmlBufferPtr buf, xmlNotationTablePtr table); @@ -184,13 +184,12 @@ XMLPUBFUN void xmlElementContentPtr content, int englob); #ifdef LIBXML_OUTPUT_ENABLED -/* DEPRECATED */ +XML_DEPRECATED XMLPUBFUN void xmlSprintfElementContent(char *buf, xmlElementContentPtr content, int englob); #endif /* LIBXML_OUTPUT_ENABLED */ -/* DEPRECATED */ /* Element */ XMLPUBFUN xmlElementPtr @@ -206,9 +205,11 @@ XMLPUBFUN xmlElementTablePtr XMLPUBFUN void xmlFreeElementTable (xmlElementTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED +XML_DEPRECATED XMLPUBFUN void xmlDumpElementTable (xmlBufferPtr buf, xmlElementTablePtr table); +XML_DEPRECATED XMLPUBFUN void xmlDumpElementDecl (xmlBufferPtr buf, xmlElementPtr elem); @@ -242,15 +243,20 @@ XMLPUBFUN xmlAttributeTablePtr XMLPUBFUN void xmlFreeAttributeTable (xmlAttributeTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED +XML_DEPRECATED XMLPUBFUN void xmlDumpAttributeTable (xmlBufferPtr buf, xmlAttributeTablePtr table); +XML_DEPRECATED XMLPUBFUN void xmlDumpAttributeDecl (xmlBufferPtr buf, xmlAttributePtr attr); #endif /* LIBXML_OUTPUT_ENABLED */ /* IDs */ +XMLPUBFUN int + xmlAddIDSafe (xmlAttrPtr attr, + const xmlChar *value); XMLPUBFUN xmlIDPtr xmlAddID (xmlValidCtxtPtr ctxt, xmlDocPtr doc, @@ -303,31 +309,38 @@ XMLPUBFUN xmlValidCtxtPtr XMLPUBFUN void xmlFreeValidCtxt(xmlValidCtxtPtr); +XML_DEPRECATED XMLPUBFUN int xmlValidateRoot (xmlValidCtxtPtr ctxt, xmlDocPtr doc); +XML_DEPRECATED XMLPUBFUN int xmlValidateElementDecl (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlElementPtr elem); +XML_DEPRECATED XMLPUBFUN xmlChar * xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value); +XML_DEPRECATED XMLPUBFUN xmlChar * xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value); +XML_DEPRECATED XMLPUBFUN int xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlAttributePtr attr); +XML_DEPRECATED XMLPUBFUN int xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value); +XML_DEPRECATED XMLPUBFUN int xmlValidateNotationDecl (xmlValidCtxtPtr ctxt, xmlDocPtr doc, @@ -336,6 +349,7 @@ XMLPUBFUN int xmlValidateDtd (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd); +XML_DEPRECATED XMLPUBFUN int xmlValidateDtdFinal (xmlValidCtxtPtr ctxt, xmlDocPtr doc); @@ -346,16 +360,19 @@ XMLPUBFUN int xmlValidateElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); +XML_DEPRECATED XMLPUBFUN int xmlValidateOneElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); +XML_DEPRECATED XMLPUBFUN int xmlValidateOneAttribute (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value); +XML_DEPRECATED XMLPUBFUN int xmlValidateOneNamespace (xmlValidCtxtPtr ctxt, xmlDocPtr doc, @@ -363,12 +380,14 @@ XMLPUBFUN int const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value); +XML_DEPRECATED XMLPUBFUN int xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc); #endif /* LIBXML_VALID_ENABLED */ #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XML_DEPRECATED XMLPUBFUN int xmlValidateNotationUse (xmlValidCtxtPtr ctxt, xmlDocPtr doc, @@ -424,19 +443,23 @@ XMLPUBFUN int /* * Validation based on the regexp support */ +XML_DEPRECATED XMLPUBFUN int xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem); +XML_DEPRECATED XMLPUBFUN int xmlValidatePushElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *qname); +XML_DEPRECATED XMLPUBFUN int xmlValidatePushCData (xmlValidCtxtPtr ctxt, const xmlChar *data, int len); +XML_DEPRECATED XMLPUBFUN int xmlValidatePopElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, diff --git a/include/libxml/xinclude.h b/include/libxml/xinclude.h index e1d135b..6a67953 100644 --- a/include/libxml/xinclude.h +++ b/include/libxml/xinclude.h @@ -115,6 +115,12 @@ XMLPUBFUN xmlXIncludeCtxtPtr XMLPUBFUN int xmlXIncludeSetFlags (xmlXIncludeCtxtPtr ctxt, int flags); +XMLPUBFUN void + xmlXIncludeSetErrorHandler(xmlXIncludeCtxtPtr ctxt, + xmlStructuredErrorFunc handler, + void *data); +XMLPUBFUN int + xmlXIncludeGetLastError (xmlXIncludeCtxtPtr ctxt); XMLPUBFUN void xmlXIncludeFreeContext (xmlXIncludeCtxtPtr ctxt); XMLPUBFUN int diff --git a/include/libxml/xmlIO.h b/include/libxml/xmlIO.h index 2487be3..66eebd4 100644 --- a/include/libxml/xmlIO.h +++ b/include/libxml/xmlIO.h @@ -13,9 +13,7 @@ #include #include #include -#define XML_TREE_INTERNALS #include -#undef XML_TREE_INTERNALS #ifdef __cplusplus extern "C" { @@ -323,12 +321,14 @@ xmlOutputBufferPtr #ifdef LIBXML_HTTP_ENABLED /* This function only exists if HTTP support built into the library */ +XML_DEPRECATED XMLPUBFUN void xmlRegisterHTTPPostCallbacks (void ); #endif /* LIBXML_HTTP_ENABLED */ #endif /* LIBXML_OUTPUT_ENABLED */ +XML_DEPRECATED XMLPUBFUN xmlParserInputPtr xmlCheckHTTPInput (xmlParserCtxtPtr ctxt, xmlParserInputPtr ret); @@ -341,26 +341,28 @@ XMLPUBFUN xmlParserInputPtr const char *ID, xmlParserCtxtPtr ctxt); -/* - * xmlNormalizeWindowsPath is obsolete, don't use it. - * Check xmlCanonicPath in uri.h for a better alternative. - */ +XML_DEPRECATED XMLPUBFUN xmlChar * xmlNormalizeWindowsPath (const xmlChar *path); +XML_DEPRECATED XMLPUBFUN int xmlCheckFilename (const char *path); /** * Default 'file://' protocol callbacks */ +XML_DEPRECATED XMLPUBFUN int xmlFileMatch (const char *filename); +XML_DEPRECATED XMLPUBFUN void * xmlFileOpen (const char *filename); +XML_DEPRECATED XMLPUBFUN int xmlFileRead (void * context, char * buffer, int len); +XML_DEPRECATED XMLPUBFUN int xmlFileClose (void * context); @@ -368,19 +370,24 @@ XMLPUBFUN int * Default 'http://' protocol callbacks */ #ifdef LIBXML_HTTP_ENABLED +XML_DEPRECATED XMLPUBFUN int xmlIOHTTPMatch (const char *filename); +XML_DEPRECATED XMLPUBFUN void * xmlIOHTTPOpen (const char *filename); #ifdef LIBXML_OUTPUT_ENABLED +XML_DEPRECATED XMLPUBFUN void * xmlIOHTTPOpenW (const char * post_uri, int compression ); #endif /* LIBXML_OUTPUT_ENABLED */ +XML_DEPRECATED XMLPUBFUN int xmlIOHTTPRead (void * context, char * buffer, int len); +XML_DEPRECATED XMLPUBFUN int xmlIOHTTPClose (void * context); #endif /* LIBXML_HTTP_ENABLED */ @@ -389,14 +396,18 @@ XMLPUBFUN int * Default 'ftp://' protocol callbacks */ #if defined(LIBXML_FTP_ENABLED) +XML_DEPRECATED XMLPUBFUN int xmlIOFTPMatch (const char *filename); +XML_DEPRECATED XMLPUBFUN void * xmlIOFTPOpen (const char *filename); +XML_DEPRECATED XMLPUBFUN int xmlIOFTPRead (void * context, char * buffer, int len); +XML_DEPRECATED XMLPUBFUN int xmlIOFTPClose (void * context); #endif /* defined(LIBXML_FTP_ENABLED) */ @@ -407,9 +418,11 @@ XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLPUBFUN xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameDefault( xmlOutputBufferCreateFilenameFunc func); +XML_DEPRECATED XMLPUBFUN xmlOutputBufferCreateFilenameFunc xmlThrDefOutputBufferCreateFilenameDefault( xmlOutputBufferCreateFilenameFunc func); +XML_DEPRECATED XMLPUBFUN xmlParserInputBufferCreateFilenameFunc xmlThrDefParserInputBufferCreateFilenameDefault( xmlParserInputBufferCreateFilenameFunc func); diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h index 1f0ab4a..36381be 100644 --- a/include/libxml/xmlerror.h +++ b/include/libxml/xmlerror.h @@ -211,6 +211,11 @@ typedef enum { XML_ERR_USER_STOP, /* 111 */ XML_ERR_COMMENT_ABRUPTLY_ENDED, /* 112 */ XML_WAR_ENCODING_MISMATCH, /* 113 */ + XML_ERR_RESOURCE_LIMIT, /* 114 */ + XML_ERR_ARGUMENT, /* 115 */ + XML_ERR_SYSTEM, /* 116 */ + XML_ERR_REDECL_PREDEF_ENTITY, /* 117 */ + XML_ERR_INT_SUBSET_NOT_FINISHED, /* 118 */ XML_NS_ERR_XML_NAMESPACE = 200, XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */ XML_NS_ERR_QNAME, /* 202 */ @@ -473,6 +478,7 @@ typedef enum { XML_IO_EADDRINUSE, /* 1554 */ XML_IO_EALREADY, /* 1555 */ XML_IO_EAFNOSUPPORT, /* 1556 */ + XML_IO_UNSUPPORTED_PROTOCOL, /* 1557 */ XML_XINCLUDE_RECURSION=1600, XML_XINCLUDE_PARSE_VALUE, /* 1601 */ XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */ @@ -886,6 +892,7 @@ XML_GLOBALS_ERROR XMLPUBFUN void xmlSetGenericErrorFunc (void *ctx, xmlGenericErrorFunc handler); +XML_DEPRECATED XMLPUBFUN void xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler); @@ -896,6 +903,7 @@ XMLPUBFUN void XMLPUBFUN void xmlSetStructuredErrorFunc (void *ctx, xmlStructuredErrorFunc handler); +XML_DEPRECATED XMLPUBFUN void xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler); @@ -919,11 +927,17 @@ XMLPUBFUN void xmlParserValidityWarning (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); +/** DOC_DISABLE */ struct _xmlParserInput; +/** DOC_ENABLE */ XMLPUBFUN void xmlParserPrintFileInfo (struct _xmlParserInput *input); XMLPUBFUN void xmlParserPrintFileContext (struct _xmlParserInput *input); +XMLPUBFUN void +xmlFormatError (const xmlError *err, + xmlGenericErrorFunc channel, + void *data); /* * Extended error information routines diff --git a/include/libxml/xmlexports.h b/include/libxml/xmlexports.h index 3b063e7..99f9c37 100644 --- a/include/libxml/xmlexports.h +++ b/include/libxml/xmlexports.h @@ -9,6 +9,11 @@ #define __XML_EXPORTS_H__ /** DOC_DISABLE */ + +/* + * Symbol visibility + */ + #if defined(_WIN32) || defined(__CYGWIN__) #ifdef LIBXML_STATIC #define XMLPUBLIC @@ -20,30 +25,119 @@ #else /* not Windows */ #define XMLPUBLIC #endif /* platform switch */ -/** DOC_ENABLE */ -/* - * XMLPUBFUN: - * - * Macro which declares an exportable function - */ #define XMLPUBFUN XMLPUBLIC -/** - * XMLPUBVAR: - * - * Macro which declares an exportable variable - */ #define XMLPUBVAR XMLPUBLIC extern -/** DOC_DISABLE */ /* Compatibility */ #define XMLCALL #define XMLCDECL -#if !defined(LIBXML_DLL_IMPORT) -#define LIBXML_DLL_IMPORT XMLPUBVAR +#ifndef LIBXML_DLL_IMPORT + #define LIBXML_DLL_IMPORT XMLPUBVAR +#endif + +/* + * Attributes + */ + +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 207 + #define ATTRIBUTE_UNUSED __attribute__((unused)) +#else + #define ATTRIBUTE_UNUSED +#endif + +#if !defined(__clang__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) + #define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x))) +#else + #define LIBXML_ATTR_ALLOC_SIZE(x) +#endif + +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 303 + #define LIBXML_ATTR_FORMAT(fmt,args) \ + __attribute__((__format__(__printf__,fmt,args))) +#else + #define LIBXML_ATTR_FORMAT(fmt,args) +#endif + +#ifndef XML_DEPRECATED + #if defined(IN_LIBXML) + #define XML_DEPRECATED + #elif __GNUC__ * 100 + __GNUC_MINOR__ >= 301 + #define XML_DEPRECATED __attribute__((deprecated)) + #elif _MSC_VER >= 1400 + /* Available since Visual Studio 2005 */ + #define XML_DEPRECATED __declspec(deprecated) + #else + #define XML_DEPRECATED + #endif +#endif + +/* + * Warnings pragmas, should be moved from public headers + */ + +#if defined(__LCC__) + + #define XML_IGNORE_FPTR_CAST_WARNINGS + #define XML_POP_WARNINGS \ + _Pragma("diag_default 1215") + +#elif defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) + + #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 800) + #define XML_IGNORE_FPTR_CAST_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ + _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"") + #else + #define XML_IGNORE_FPTR_CAST_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"") + #endif + #define XML_POP_WARNINGS \ + _Pragma("GCC diagnostic pop") + +#elif _MSC_VER >= 1400 + + #define XML_IGNORE_FPTR_CAST_WARNINGS __pragma(warning(push)) + #define XML_POP_WARNINGS __pragma(warning(pop)) + +#else + + #define XML_IGNORE_FPTR_CAST_WARNINGS + #define XML_POP_WARNINGS + +#endif + +/* + * Accessors for globals + */ + +#define XML_NO_ATTR + +#ifdef LIBXML_THREAD_ENABLED + #define XML_DECLARE_GLOBAL(name, type, attrs) \ + attrs XMLPUBFUN type *__##name(void); + #define XML_GLOBAL_MACRO(name) (*__##name()) +#else + #define XML_DECLARE_GLOBAL(name, type, attrs) \ + attrs XMLPUBVAR type name; +#endif + +/* + * Originally declared in xmlversion.h which is generated + */ + +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN void xmlCheckVersion(int version); + +#ifdef __cplusplus +} #endif -/** DOC_ENABLE */ #endif /* __XML_EXPORTS_H__ */ diff --git a/include/libxml/xmlmemory.h b/include/libxml/xmlmemory.h index 097e3c8..1de3e9f 100644 --- a/include/libxml/xmlmemory.h +++ b/include/libxml/xmlmemory.h @@ -147,12 +147,16 @@ XMLPUBFUN int xmlMemUsed (void); XMLPUBFUN int xmlMemBlocks (void); +XML_DEPRECATED XMLPUBFUN void xmlMemDisplay (FILE *fp); +XML_DEPRECATED XMLPUBFUN void xmlMemDisplayLast(FILE *fp, long nbBytes); +XML_DEPRECATED XMLPUBFUN void xmlMemShow (FILE *fp, int nr); +XML_DEPRECATED XMLPUBFUN void xmlMemoryDump (void); XMLPUBFUN void * @@ -163,60 +167,19 @@ XMLPUBFUN void xmlMemFree (void *ptr); XMLPUBFUN char * xmlMemoryStrdup (const char *str); +XML_DEPRECATED XMLPUBFUN void * xmlMallocLoc (size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1); +XML_DEPRECATED XMLPUBFUN void * xmlReallocLoc (void *ptr, size_t size, const char *file, int line); +XML_DEPRECATED XMLPUBFUN void * xmlMallocAtomicLoc (size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1); +XML_DEPRECATED XMLPUBFUN char * xmlMemStrdupLoc (const char *str, const char *file, int line); - -/** DOC_DISABLE */ -#ifdef DEBUG_MEMORY_LOCATION -/** - * xmlMalloc: - * @size: number of bytes to allocate - * - * Wrapper for the malloc() function used in the XML library. - * - * Returns the pointer to the allocated area or NULL in case of error. - */ -#define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__) -/** - * xmlMallocAtomic: - * @size: number of bytes to allocate - * - * Wrapper for the malloc() function used in the XML library for allocation - * of block not containing pointers to other areas. - * - * Returns the pointer to the allocated area or NULL in case of error. - */ -#define xmlMallocAtomic(size) xmlMallocAtomicLoc((size), __FILE__, __LINE__) -/** - * xmlRealloc: - * @ptr: pointer to the existing allocated area - * @size: number of bytes to allocate - * - * Wrapper for the realloc() function used in the XML library. - * - * Returns the pointer to the allocated area or NULL in case of error. - */ -#define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__) -/** - * xmlMemStrdup: - * @str: pointer to the existing string - * - * Wrapper for the strdup() function, xmlStrdup() is usually preferred. - * - * Returns the pointer to the allocated area or NULL in case of error. - */ -#define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__) - -#endif /* DEBUG_MEMORY_LOCATION */ -/** DOC_ENABLE */ - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/libxml/xmlreader.h b/include/libxml/xmlreader.h index b9f6989..5d4fc5d 100644 --- a/include/libxml/xmlreader.h +++ b/include/libxml/xmlreader.h @@ -127,6 +127,8 @@ XMLPUBFUN int XMLPUBFUN void xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl); +XMLPUBFUN const xmlError * + xmlTextReaderGetLastError(xmlTextReaderPtr reader); /* * Iterators diff --git a/include/libxml/xmlsave.h b/include/libxml/xmlsave.h index fbf293a..e266e46 100644 --- a/include/libxml/xmlsave.h +++ b/include/libxml/xmlsave.h @@ -73,6 +73,8 @@ XMLPUBFUN int xmlSaveFlush (xmlSaveCtxtPtr ctxt); XMLPUBFUN int xmlSaveClose (xmlSaveCtxtPtr ctxt); +XMLPUBFUN int + xmlSaveFinish (xmlSaveCtxtPtr ctxt); XMLPUBFUN int xmlSaveSetEscape (xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape); @@ -80,10 +82,13 @@ XMLPUBFUN int xmlSaveSetAttrEscape (xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape); +XML_DEPRECATED XMLPUBFUN int xmlThrDefIndentTreeOutput(int v); +XML_DEPRECATED XMLPUBFUN const char * xmlThrDefTreeIndentString(const char * v); +XML_DEPRECATED XMLPUBFUN int xmlThrDefSaveNoEmptyTags(int v); diff --git a/include/libxml/xmlunicode.h b/include/libxml/xmlunicode.h index 2e50a49..b6d795b 100644 --- a/include/libxml/xmlunicode.h +++ b/include/libxml/xmlunicode.h @@ -7,7 +7,7 @@ * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1.html * using the genUnicode.py Python script. * - * Generation date: Mon Mar 27 11:09:52 2006 + * Generation date: Tue Apr 30 17:30:38 2024 * Sources: Blocks-4.0.1.txt UnicodeData-4.0.1.txt * Author: Daniel Veillard */ @@ -23,172 +23,336 @@ extern "C" { #endif +XML_DEPRECATED XMLPUBFUN int xmlUCSIsAegeanNumbers (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsAlphabeticPresentationForms (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsArabic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsArabicPresentationFormsA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsArabicPresentationFormsB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsArmenian (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsArrows (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBasicLatin (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBengali (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBlockElements (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBopomofo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBopomofoExtended (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBoxDrawing (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBraillePatterns (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsBuhid (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsByzantineMusicalSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKCompatibility (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKCompatibilityForms (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKCompatibilityIdeographs (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKCompatibilityIdeographsSupplement (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKRadicalsSupplement (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKSymbolsandPunctuation (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographs (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographsExtensionA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCJKUnifiedIdeographsExtensionB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCherokee (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCombiningDiacriticalMarks (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCombiningDiacriticalMarksforSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCombiningHalfMarks (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCombiningMarksforSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsControlPictures (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCurrencySymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCypriotSyllabary (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCyrillic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCyrillicSupplement (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsDeseret (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsDevanagari (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsDingbats (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsEnclosedAlphanumerics (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsEnclosedCJKLettersandMonths (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsEthiopic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGeneralPunctuation (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGeometricShapes (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGeorgian (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGothic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGreek (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGreekExtended (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGreekandCoptic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGujarati (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsGurmukhi (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHalfwidthandFullwidthForms (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHangulCompatibilityJamo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHangulJamo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHangulSyllables (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHanunoo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHebrew (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHighPrivateUseSurrogates (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHighSurrogates (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsHiragana (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsIPAExtensions (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsIdeographicDescriptionCharacters (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKanbun (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKangxiRadicals (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKannada (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKatakana (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKatakanaPhoneticExtensions (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKhmer (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsKhmerSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLao (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLatin1Supplement (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLatinExtendedA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLatinExtendedB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLatinExtendedAdditional (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLetterlikeSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLimbu (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLinearBIdeograms (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLinearBSyllabary (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsLowSurrogates (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMalayalam (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMathematicalAlphanumericSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMathematicalOperators (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMiscellaneousMathematicalSymbolsA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMiscellaneousMathematicalSymbolsB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMiscellaneousSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMiscellaneousSymbolsandArrows (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMiscellaneousTechnical (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMongolian (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMusicalSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsMyanmar (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsNumberForms (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsOgham (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsOldItalic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsOpticalCharacterRecognition (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsOriya (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsOsmanya (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsPhoneticExtensions (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsPrivateUse (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsPrivateUseArea (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsRunic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsShavian (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSinhala (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSmallFormVariants (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSpacingModifierLetters (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSpecials (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSuperscriptsandSubscripts (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSupplementalArrowsA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSupplementalArrowsB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSupplementalMathematicalOperators (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSupplementaryPrivateUseAreaA (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSupplementaryPrivateUseAreaB (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsSyriac (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTagalog (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTagbanwa (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTags (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTaiLe (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTaiXuanJingSymbols (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTamil (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTelugu (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsThaana (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsThai (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsTibetan (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsUgaritic (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsUnifiedCanadianAboriginalSyllabics (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsVariationSelectors (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsVariationSelectorsSupplement (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsYiRadicals (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsYiSyllables (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsYijingHexagramSymbols (int code); XMLPUBFUN int xmlUCSIsBlock (int code, const char *block); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatC (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatCc (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatCf (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatCo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatCs (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatL (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatLl (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatLm (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatLo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatLt (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatLu (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatM (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatMc (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatMe (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatMn (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatN (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatNd (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatNl (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatNo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatP (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPc (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPd (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPe (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPf (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPi (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatPs (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatS (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatSc (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatSk (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatSm (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatSo (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatZ (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatZl (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatZp (int code); +XML_DEPRECATED XMLPUBFUN int xmlUCSIsCatZs (int code); XMLPUBFUN int xmlUCSIsCat (int code, const char *cat); diff --git a/include/libxml/xmlversion.h b/include/libxml/xmlversion.h index 1218a40..0838bce 100644 --- a/include/libxml/xmlversion.h +++ b/include/libxml/xmlversion.h @@ -10,40 +10,26 @@ #ifndef __XML_VERSION_H__ #define __XML_VERSION_H__ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * use those to be sure nothing nasty will happen if - * your library and includes mismatch - */ -#ifndef LIBXML2_COMPILING_MSCCDEF -XMLPUBFUN void xmlCheckVersion(int version); -#endif /* LIBXML2_COMPILING_MSCCDEF */ - /** * LIBXML_DOTTED_VERSION: * * the version string like "1.2.3" */ -#define LIBXML_DOTTED_VERSION "2.12.8" +#define LIBXML_DOTTED_VERSION "2.13.0" /** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXML_VERSION 21208 +#define LIBXML_VERSION 21300 /** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXML_VERSION_STRING "21208" +#define LIBXML_VERSION_STRING "21300" /** * LIBXML_VERSION_EXTRA: @@ -58,32 +44,7 @@ XMLPUBFUN void xmlCheckVersion(int version); * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ -#define LIBXML_TEST_VERSION xmlCheckVersion(21208); - -#ifndef VMS -#if 0 -/** - * WITH_TRIO: - * - * defined if the trio support need to be configured in - */ -#define WITH_TRIO -#else -/** - * WITHOUT_TRIO: - * - * defined if the trio support should not be configured in - */ -#define WITHOUT_TRIO -#endif -#else /* VMS */ -/** - * WITH_TRIO: - * - * defined if the trio support need to be configured in - */ -#define WITH_TRIO 1 -#endif /* VMS */ +#define LIBXML_TEST_VERSION xmlCheckVersion(21300); /** * LIBXML_THREAD_ENABLED: @@ -301,24 +262,6 @@ XMLPUBFUN void xmlCheckVersion(int version); #define LIBXML_DEBUG_ENABLED #endif -/** - * DEBUG_MEMORY_LOCATION: - * - * Whether the memory debugging is configured in - */ -#if 0 -#define DEBUG_MEMORY_LOCATION -#endif - -/** - * LIBXML_DEBUG_RUNTIME: - * - * Removed - */ -#if 0 -#define LIBXML_DEBUG_RUNTIME -#endif - /** * LIBXML_UNICODE_ENABLED: * @@ -346,17 +289,6 @@ XMLPUBFUN void xmlCheckVersion(int version); #define LIBXML_AUTOMATA_ENABLED #endif -/** - * LIBXML_EXPR_ENABLED: - * - * Whether the formal expressions interfaces are compiled in - * - * This code is unused and disabled unconditionally for now. - */ -#if 0 -#define LIBXML_EXPR_ENABLED -#endif - /** * LIBXML_SCHEMAS_ENABLED: * @@ -410,104 +342,8 @@ XMLPUBFUN void xmlCheckVersion(int version); #endif #endif -#ifdef __GNUC__ -/** DOC_DISABLE */ - -#ifndef ATTRIBUTE_UNUSED -# if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) -# define ATTRIBUTE_UNUSED __attribute__((unused)) -# else -# define ATTRIBUTE_UNUSED -# endif -#endif - -#ifndef LIBXML_ATTR_ALLOC_SIZE -# if (!defined(__clang__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))) -# define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x))) -# else -# define LIBXML_ATTR_ALLOC_SIZE(x) -# endif -#else -# define LIBXML_ATTR_ALLOC_SIZE(x) -#endif - -#ifndef LIBXML_ATTR_FORMAT -# if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3))) -# define LIBXML_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args))) -# else -# define LIBXML_ATTR_FORMAT(fmt,args) -# endif -#else -# define LIBXML_ATTR_FORMAT(fmt,args) -#endif - -#ifndef XML_DEPRECATED -# if defined (IN_LIBXML) || (__GNUC__ * 100 + __GNUC_MINOR__ < 301) -# define XML_DEPRECATED -/* Available since at least GCC 3.1 */ -# else -# define XML_DEPRECATED __attribute__((deprecated)) -# endif -#endif - -#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) - #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 800) - #define XML_IGNORE_FPTR_CAST_WARNINGS \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ - _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"") - #else - #define XML_IGNORE_FPTR_CAST_WARNINGS \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wpedantic\"") - #endif - #define XML_POP_WARNINGS \ - _Pragma("GCC diagnostic pop") -#else - #define XML_IGNORE_FPTR_CAST_WARNINGS - #define XML_POP_WARNINGS -#endif - -#else /* ! __GNUC__ */ -#define ATTRIBUTE_UNUSED -#define LIBXML_ATTR_ALLOC_SIZE(x) -#define LIBXML_ATTR_FORMAT(fmt,args) -#ifndef XML_DEPRECATED -# if defined (IN_LIBXML) || !defined (_MSC_VER) -# define XML_DEPRECATED -/* Available since Visual Studio 2005 */ -# elif defined (_MSC_VER) && (_MSC_VER >= 1400) -# define XML_DEPRECATED __declspec(deprecated) -# endif -#endif -#if defined (_MSC_VER) && (_MSC_VER >= 1400) -# define XML_IGNORE_FPTR_CAST_WARNINGS __pragma(warning(push)) -#else -# define XML_IGNORE_FPTR_CAST_WARNINGS -#endif -#ifndef XML_POP_WARNINGS -# if defined (_MSC_VER) && (_MSC_VER >= 1400) -# define XML_POP_WARNINGS __pragma(warning(pop)) -# else -# define XML_POP_WARNINGS -# endif -#endif -#endif /* __GNUC__ */ - -#define XML_NO_ATTR - -#ifdef LIBXML_THREAD_ENABLED - #define XML_DECLARE_GLOBAL(name, type, attrs) \ - attrs XMLPUBFUN type *__##name(void); - #define XML_GLOBAL_MACRO(name) (*__##name()) -#else - #define XML_DECLARE_GLOBAL(name, type, attrs) \ - attrs XMLPUBVAR type name; -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +#include + #endif diff --git a/include/libxml/xmlwriter.h b/include/libxml/xmlwriter.h index 339f251..55f88bc 100644 --- a/include/libxml/xmlwriter.h +++ b/include/libxml/xmlwriter.h @@ -478,6 +478,7 @@ extern "C" { * misc */ XMLPUBFUN int xmlTextWriterFlush(xmlTextWriterPtr writer); + XMLPUBFUN int xmlTextWriterClose(xmlTextWriterPtr writer); #ifdef __cplusplus } diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h index 6dae078..b89e105 100644 --- a/include/libxml/xpath.h +++ b/include/libxml/xpath.h @@ -515,6 +515,10 @@ XMLPUBFUN xmlXPathContextPtr xmlXPathNewContext (xmlDocPtr doc); XMLPUBFUN void xmlXPathFreeContext (xmlXPathContextPtr ctxt); +XMLPUBFUN void + xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt, + xmlStructuredErrorFunc handler, + void *context); XMLPUBFUN int xmlXPathContextSetCache(xmlXPathContextPtr ctxt, int active, diff --git a/include/private/buf.h b/include/private/buf.h index 6fef4ce..982b9ee 100644 --- a/include/private/buf.h +++ b/include/private/buf.h @@ -28,10 +28,6 @@ XML_HIDDEN int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len); XML_HIDDEN int xmlBufCat(xmlBufPtr buf, const xmlChar *str); -XML_HIDDEN int -xmlBufCCat(xmlBufPtr buf, const char *str); -XML_HIDDEN int -xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string); XML_HIDDEN size_t xmlBufAvail(const xmlBufPtr buf); @@ -56,8 +52,6 @@ XML_HIDDEN xmlBufPtr xmlBufFromBuffer(xmlBufferPtr buffer); XML_HIDDEN xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf); -XML_HIDDEN int -xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer); XML_HIDDEN int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input); diff --git a/include/private/dict.h b/include/private/dict.h index 9b0be62..826ac54 100644 --- a/include/private/dict.h +++ b/include/private/dict.h @@ -67,6 +67,8 @@ xmlInitRandom(void); XML_HIDDEN void xmlCleanupRandom(void); XML_HIDDEN unsigned +xmlGlobalRandom(void); +XML_HIDDEN unsigned xmlRandom(void); #endif /* XML_DICT_H_PRIVATE__ */ diff --git a/include/private/entities.h b/include/private/entities.h index c3f15e6..d262ef4 100644 --- a/include/private/entities.h +++ b/include/private/entities.h @@ -9,13 +9,17 @@ * * XML_ENT_PARSED: The entity was parsed and `children` points to the * content. - * XML_ENT_CHECKED: The entity was checked for loops. + * + * XML_ENT_CHECKED: The entity was checked for loops and amplification. + * expandedSize was set. + * + * XML_ENT_VALIDATED: The entity contains a valid attribute value. + * Only used when entities aren't substituted. */ -#define XML_ENT_PARSED (1<<0) -#define XML_ENT_CHECKED (1<<1) -#define XML_ENT_EXPANDING (1<<2) -#define XML_ENT_CHECKED_LT (1<<3) -#define XML_ENT_CONTAINS_LT (1<<4) +#define XML_ENT_PARSED (1u << 0) +#define XML_ENT_CHECKED (1u << 1) +#define XML_ENT_VALIDATED (1u << 2) +#define XML_ENT_EXPANDING (1u << 3) XML_HIDDEN xmlChar * xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input); diff --git a/include/private/error.h b/include/private/error.h index 165b782..506405a 100644 --- a/include/private/error.h +++ b/include/private/error.h @@ -4,20 +4,31 @@ #include #include +#define MAX_ERR_MSG_SIZE 64000 + struct _xmlNode; XML_HIDDEN void -__xmlRaiseError(xmlStructuredErrorFunc schannel, - xmlGenericErrorFunc channel, void *data, void *ctx, - void *nod, int domain, int code, xmlErrorLevel level, +xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, + void *data, int domain, xmlError *error); +XML_HIDDEN int +xmlVRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, + void *data, void *ctx, struct _xmlNode *node, + int domain, int code, xmlErrorLevel level, + const char *file, int line, const char *str1, + const char *str2, const char *str3, int int1, int col, + const char *msg, va_list ap); +XML_HIDDEN int +__xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, + void *data, void *ctx, struct _xmlNode *node, + int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg, ...) LIBXML_ATTR_FORMAT(16,17); XML_HIDDEN void -__xmlSimpleError(int domain, int code, struct _xmlNode *node, - const char *msg, const char *extra) LIBXML_ATTR_FORMAT(4,0); -XML_HIDDEN void xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); +XML_HIDDEN const char * +xmlErrString(xmlParserErrors code); #endif /* XML_ERROR_H_PRIVATE__ */ diff --git a/include/private/globals.h b/include/private/globals.h index 5f3f112..828b6d5 100644 --- a/include/private/globals.h +++ b/include/private/globals.h @@ -6,4 +6,9 @@ xmlInitGlobalsInternal(void); XML_HIDDEN void xmlCleanupGlobalsInternal(void); +#ifdef LIBXML_THREAD_ENABLED +XML_HIDDEN unsigned * +xmlGetLocalRngState(void); +#endif + #endif /* XML_GLOBALS_H_PRIVATE__ */ diff --git a/include/private/io.h b/include/private/io.h index 5f4b210..a2535ae 100644 --- a/include/private/io.h +++ b/include/private/io.h @@ -6,17 +6,30 @@ #include XML_HIDDEN void +xmlInitIOCallbacks(void); + +XML_HIDDEN int __xmlIOErr(int domain, int code, const char *extra); -XML_HIDDEN void -__xmlLoaderErr(void *ctx, const char *msg, - const char *filename) LIBXML_ATTR_FORMAT(2,0); -xmlParserInputBufferPtr -xmlParserInputBufferCreateString(const xmlChar *str); +XML_HIDDEN int +xmlNoNetExists(const char *filename); + +XML_HIDDEN int +xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc, + xmlParserInputBufferPtr *out); + +XML_HIDDEN xmlParserInputBufferPtr +xmlNewInputBufferString(const char *str, int flags); +XML_HIDDEN xmlParserInputBufferPtr +xmlNewInputBufferMemory(const void *mem, size_t size, int flags, + xmlCharEncoding enc); #ifdef LIBXML_OUTPUT_ENABLED XML_HIDDEN xmlOutputBufferPtr xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder); +XML_HIDDEN void +xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf, + const xmlChar *string); #endif #endif /* XML_IO_H_PRIVATE__ */ diff --git a/include/private/parser.h b/include/private/parser.h index 7f8f691..b14bebf 100644 --- a/include/private/parser.h +++ b/include/private/parser.h @@ -25,18 +25,41 @@ #define XML_INPUT_AUTO_OTHER (4u << 1) #define XML_INPUT_USES_ENC_DECL (1u << 4) #define XML_INPUT_ENCODING_ERROR (1u << 5) +#define XML_INPUT_PROGRESSIVE (1u << 6) +#define PARSER_STOPPED(ctxt) ((ctxt)->disableSAX > 1) + +#define PARSER_PROGRESSIVE(ctxt) \ + ((ctxt)->input->flags & XML_INPUT_PROGRESSIVE) + +#define PARSER_IN_PE(ctxt) \ + (((ctxt)->input->entity != NULL) && \ + (((ctxt)->input->entity->etype == XML_INTERNAL_PARAMETER_ENTITY) || \ + ((ctxt)->input->entity->etype == XML_EXTERNAL_PARAMETER_ENTITY))) + +#define PARSER_EXTERNAL(ctxt) \ + (((ctxt)->inSubset == 2) || \ + (((ctxt)->input->entity != NULL) && \ + ((ctxt)->input->entity->etype == XML_EXTERNAL_PARAMETER_ENTITY))) + +XML_HIDDEN void +xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain, + xmlParserErrors code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, va_list ap); XML_HIDDEN void -xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra); +xmlCtxtErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain, + xmlParserErrors code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, ...); XML_HIDDEN void xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info); XML_HIDDEN void LIBXML_ATTR_FORMAT(3,0) xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2); XML_HIDDEN void -__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, - const char *msg, const xmlChar *str1, - const xmlChar *str2) LIBXML_ATTR_FORMAT(3,0); +xmlCtxtErrIO(xmlParserCtxtPtr ctxt, int code, const char *uri); + XML_HIDDEN void xmlHaltParser(xmlParserCtxtPtr ctxt); XML_HIDDEN int @@ -65,4 +88,34 @@ xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix, XML_HIDDEN void * xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix); +#define XML_INPUT_BUF_STATIC (1u << 1) +#define XML_INPUT_BUF_ZERO_TERMINATED (1u << 2) + +XML_HIDDEN xmlParserInputPtr +xmlNewInputURL(xmlParserCtxtPtr ctxt, const char *url, const char *publicId, + const char *encoding, int flags); +XML_HIDDEN xmlParserInputPtr +xmlNewInputMemory(xmlParserCtxtPtr ctxt, const char *url, + const void *mem, size_t size, + const char *encoding, int flags); +XML_HIDDEN xmlParserInputPtr +xmlNewInputString(xmlParserCtxtPtr ctxt, const char *url, const char *str, + const char *encoding, int flags); +XML_HIDDEN xmlParserInputPtr +xmlNewInputFd(xmlParserCtxtPtr ctxt, const char *filename, int fd, + const char *encoding, int flags); +XML_HIDDEN xmlParserInputPtr +xmlNewInputIO(xmlParserCtxtPtr ctxt, const char *url, + xmlInputReadCallback ioRead, + xmlInputCloseCallback ioClose, + void *ioCtxt, + const char *encoding, int flags); +XML_HIDDEN xmlParserInputPtr +xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url, + const char *chunk, int size, const char *encoding); + +XML_HIDDEN xmlChar * +xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str, + int normalize); + #endif /* XML_PARSER_H_PRIVATE__ */ diff --git a/include/private/regexp.h b/include/private/regexp.h index f202493..b55c932 100644 --- a/include/private/regexp.h +++ b/include/private/regexp.h @@ -3,7 +3,21 @@ #include +#ifdef LIBXML_REGEXP_ENABLED + +/* + * -2 and -3 are used by xmlValidateElementType for other things. + */ +#define XML_REGEXP_OK 0 +#define XML_REGEXP_NOT_FOUND (-1) +#define XML_REGEXP_INTERNAL_ERROR (-4) +#define XML_REGEXP_OUT_OF_MEMORY (-5) +#define XML_REGEXP_INTERNAL_LIMIT (-6) +#define XML_REGEXP_INVALID_UTF8 (-7) + XML_HIDDEN void xmlAutomataSetFlags(xmlAutomataPtr am, int flags); +#endif /* LIBXML_REGEXP_ENABLED */ + #endif /* XML_REGEXP_H_PRIVATE__ */ diff --git a/include/private/save.h b/include/private/save.h index 873aad7..5d4a753 100644 --- a/include/private/save.h +++ b/include/private/save.h @@ -2,13 +2,19 @@ #define XML_SAVE_H_PRIVATE__ #include +#include #include #ifdef LIBXML_OUTPUT_ENABLED +XML_HIDDEN int +xmlSaveNotationDecl(xmlSaveCtxtPtr ctxt, xmlNotationPtr cur); +XML_HIDDEN int +xmlSaveNotationTable(xmlSaveCtxtPtr ctxt, xmlNotationTablePtr cur); + XML_HIDDEN void -xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc, - xmlAttrPtr attr, const xmlChar * string); +xmlBufAttrSerializeTxtContent(xmlOutputBufferPtr buf, xmlDocPtr doc, + const xmlChar *string); XML_HIDDEN void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur); diff --git a/include/private/string.h b/include/private/string.h index 9665fc4..34f4c96 100644 --- a/include/private/string.h +++ b/include/private/string.h @@ -3,6 +3,10 @@ #include +XML_HIDDEN int +xmlStrVASPrintf(xmlChar **out, int maxSize, const char *msg, va_list ap); +XML_HIDDEN int +xmlStrASPrintf(xmlChar **out, int maxSize, const char *msg, ...); XML_HIDDEN xmlChar * xmlEscapeFormatString(xmlChar **msg); diff --git a/include/private/tree.h b/include/private/tree.h index fb5e162..2d651d5 100644 --- a/include/private/tree.h +++ b/include/private/tree.h @@ -9,10 +9,19 @@ XML_HIDDEN extern int __xmlRegisterCallbacks; +XML_HIDDEN int +xmlSearchNsSafe(xmlNodePtr node, const xmlChar *href, xmlNsPtr *out); +XML_HIDDEN int +xmlSearchNsByHrefSafe(xmlNodePtr node, const xmlChar *href, xmlNsPtr *out); + +XML_HIDDEN int +xmlNodeParseContent(xmlNodePtr node, const xmlChar *content, int len); XML_HIDDEN xmlNodePtr xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, int extended); XML_HIDDEN xmlNodePtr xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent); +XML_HIDDEN const xmlChar * +xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr); #endif /* XML_TREE_H_PRIVATE__ */ diff --git a/include/private/xpath.h b/include/private/xpath.h index 0e8d752..72a6972 100644 --- a/include/private/xpath.h +++ b/include/private/xpath.h @@ -1,7 +1,16 @@ #ifndef XML_XPATH_H_PRIVATE__ #define XML_XPATH_H_PRIVATE__ +#include + XML_HIDDEN void xmlInitXPathInternal(void); +#ifdef LIBXML_XPATH_ENABLED +XML_HIDDEN void +xmlXPathErrMemory(xmlXPathContextPtr ctxt); +XML_HIDDEN void +xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt); +#endif + #endif /* XML_XPATH_H_PRIVATE__ */ diff --git a/include/private/xzlib.h b/include/private/xzlib.h index b332698..8505ef3 100644 --- a/include/private/xzlib.h +++ b/include/private/xzlib.h @@ -19,7 +19,7 @@ typedef void *xzFile; /* opaque lzma file descriptor */ XML_HIDDEN xzFile __libxml2_xzopen(const char *path, const char *mode); XML_HIDDEN xzFile -__libxml2_xzdopen(int fd, const char *mode); +__libxml2_xzdopen(const char *path, int fd, const char *mode); XML_HIDDEN int __libxml2_xzread(xzFile file, void *buf, unsigned len); XML_HIDDEN int diff --git a/legacy.c b/legacy.c index 4bd25fb..ac80c0e 100644 --- a/legacy.c +++ b/legacy.c @@ -11,6 +11,7 @@ #include "libxml.h" #ifdef LIBXML_LEGACY_ENABLED +#include #include #include @@ -55,7 +56,7 @@ htmlDecodeEntities(htmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "htmlDecodeEntities() deprecated function reached\n"); deprecated = 1; } @@ -416,7 +417,7 @@ xmlDecodeEntities(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlDecodeEntities() deprecated function reached\n"); deprecated = 1; } @@ -446,7 +447,7 @@ xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlNamespaceParseNCName() deprecated function reached\n"); deprecated = 1; } @@ -481,7 +482,7 @@ xmlNamespaceParseQName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlNamespaceParseQName() deprecated function reached\n"); deprecated = 1; } @@ -510,7 +511,7 @@ xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlNamespaceParseNSDef() deprecated function reached\n"); deprecated = 1; } @@ -533,7 +534,7 @@ xmlParseQuotedString(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlParseQuotedString() deprecated function reached\n"); deprecated = 1; } @@ -561,7 +562,7 @@ xmlParseNamespace(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlParseNamespace() deprecated function reached\n"); deprecated = 1; } @@ -593,7 +594,7 @@ xmlScanName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlScanName() deprecated function reached\n"); deprecated = 1; } @@ -633,7 +634,7 @@ xmlParserHandleReference(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlParserHandleReference() deprecated function reached\n"); deprecated = 1; } @@ -659,7 +660,7 @@ xmlHandleEntity(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlHandleEntity() deprecated function reached\n"); deprecated = 1; } @@ -683,7 +684,7 @@ xmlNewGlobalNs(xmlDocPtr doc ATTRIBUTE_UNUSED, static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlNewGlobalNs() deprecated function reached\n"); deprecated = 1; } @@ -703,7 +704,7 @@ xmlUpgradeOldNs(xmlDocPtr doc ATTRIBUTE_UNUSED) static int deprecated = 0; if (!deprecated) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "xmlUpgradeOldNs() deprecated function reached\n"); deprecated = 1; } @@ -729,15 +730,26 @@ xmlEncodeEntities(xmlDocPtr doc ATTRIBUTE_UNUSED, static int warning = 1; if (warning) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n"); - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n"); warning = 0; } return (NULL); } +/** + * xmlSetEntityReferenceFunc: + * @func: A valid function + * + * Set the function to call call back when a xml reference has been made + */ +void +xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func ATTRIBUTE_UNUSED) +{ +} + /************************************************************************ * * * Old set of SAXv1 functions * @@ -747,7 +759,7 @@ static int deprecated_v1_msg = 0; #define DEPRECATED(n) \ if (deprecated_v1_msg == 0) \ - xmlGenericError(xmlGenericErrorContext, \ + fprintf(stderr, \ "Use of deprecated SAXv1 function %s\n", n); \ deprecated_v1_msg++; diff --git a/libxml.h b/libxml.h index 2f72e0a..d94677b 100644 --- a/libxml.h +++ b/libxml.h @@ -38,11 +38,6 @@ #define SYSCONFDIR "/etc" #endif -#ifdef WITH_TRIO - #define TRIO_REPLACE_STDIO - #include "trio.h" -#endif - #if !defined(_WIN32) && \ !defined(__CYGWIN__) && \ (defined(__clang__) || \ @@ -53,16 +48,21 @@ #endif #if defined(__clang__) || \ - (defined(__GNUC__) && (__GNUC__ >= 8)) + (defined(__GNUC__) && (__GNUC__ >= 8) && !defined(__EDG__)) #define ATTRIBUTE_NO_SANITIZE(arg) __attribute__((no_sanitize(arg))) #else #define ATTRIBUTE_NO_SANITIZE(arg) #endif #ifdef __clang__ - #define ATTRIBUTE_NO_SANITIZE_INTEGER \ - ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \ - ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") + #if __clang_major__ >= 12 + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \ + ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") + #else + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") + #endif #else #define ATTRIBUTE_NO_SANITIZE_INTEGER #endif diff --git a/list.c b/list.c index 4927a26..20df26c 100644 --- a/list.c +++ b/list.c @@ -188,18 +188,13 @@ xmlListPtr xmlListCreate(xmlListDeallocator deallocator, xmlListDataCompare compare) { xmlListPtr l; - if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for list"); + if (NULL == (l = (xmlListPtr )xmlMalloc( sizeof(xmlList)))) return (NULL); - } /* Initialize the list to NULL */ memset(l, 0, sizeof(xmlList)); /* Add the sentinel */ if (NULL ==(l->sentinel = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for sentinel"); xmlFree(l); return (NULL); } @@ -279,11 +274,8 @@ xmlListInsert(xmlListPtr l, void *data) lkPlace = xmlListLowerSearch(l, data); /* Add the new link */ lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); - if (lkNew == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for new link"); + if (lkNew == NULL) return (1); - } lkNew->data = data; lkPlace = lkPlace->prev; lkNew->next = lkPlace->next; @@ -311,11 +303,8 @@ int xmlListAppend(xmlListPtr l, void *data) lkPlace = xmlListHigherSearch(l, data); /* Add the new link */ lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); - if (lkNew == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for new link"); + if (lkNew == NULL) return (1); - } lkNew->data = data; lkNew->next = lkPlace->next; (lkPlace->next)->prev = lkNew; @@ -548,11 +537,8 @@ xmlListPushFront(xmlListPtr l, void *data) lkPlace = l->sentinel; /* Add the new link */ lkNew = (xmlLinkPtr) xmlMalloc(sizeof(xmlLink)); - if (lkNew == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for new link"); + if (lkNew == NULL) return (0); - } lkNew->data = data; lkNew->next = lkPlace->next; (lkPlace->next)->prev = lkNew; @@ -579,11 +565,8 @@ xmlListPushBack(xmlListPtr l, void *data) return(0); lkPlace = l->sentinel->prev; /* Add the new link */ - if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) { - xmlGenericError(xmlGenericErrorContext, - "Cannot initialize memory for new link"); + if (NULL ==(lkNew = (xmlLinkPtr )xmlMalloc(sizeof(xmlLink)))) return (0); - } lkNew->data = data; lkNew->next = lkPlace->next; (lkPlace->next)->prev = lkNew; @@ -729,7 +712,7 @@ xmlListMerge(xmlListPtr l1, xmlListPtr l2) * Returns a new copy of the list or NULL in case of error */ xmlListPtr -xmlListDup(const xmlListPtr old) +xmlListDup(xmlListPtr old) { xmlListPtr cur; @@ -758,7 +741,7 @@ xmlListDup(const xmlListPtr old) * Returns 0 in case of success 1 in case of error */ int -xmlListCopy(xmlListPtr cur, const xmlListPtr old) +xmlListCopy(xmlListPtr cur, xmlListPtr old) { /* Walk the old tree and insert the data into the new one */ xmlLinkPtr lk; diff --git a/nanoftp.c b/nanoftp.c index 8fbe7aa..fc8f8d7 100644 --- a/nanoftp.c +++ b/nanoftp.c @@ -137,9 +137,9 @@ int have_ipv6(void) { * Handle an out of memory condition */ static void -xmlFTPErrMemory(const char *extra) +xmlFTPErrMemory(const char *extra ATTRIBUTE_UNUSED) { - __xmlSimpleError(XML_FROM_FTP, XML_ERR_NO_MEMORY, NULL, NULL, extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_FTP, NULL); } /** @@ -1923,7 +1923,7 @@ static void ftpList(void *userData, const char *filename, const char* attrib, const char *owner, const char *group, unsigned long size, int links, int year, const char *month, int day, int hour, int minute) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s %s %s %ld %s\n", attrib, owner, group, size, filename); } static @@ -1945,7 +1945,7 @@ int main(int argc, char **argv) { if (argc > 1) { ctxt = xmlNanoFTPNewCtxt(argv[1]); if (xmlNanoFTPConnect(ctxt) < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Couldn't connect to %s\n", argv[1]); exit(1); } @@ -1954,7 +1954,7 @@ int main(int argc, char **argv) { } else ctxt = xmlNanoFTPConnectTo("localhost", 0); if (ctxt == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Couldn't connect to localhost\n"); exit(1); } @@ -1962,7 +1962,7 @@ int main(int argc, char **argv) { output = fopen("/tmp/tstdata", "w"); if (output != NULL) { if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0) - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Failed to get file\n"); } @@ -1974,7 +1974,7 @@ int main(int argc, char **argv) { #ifdef STANDALONE #include int main(int argc, char **argv) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s : FTP support not compiled in\n", argv[0]); return(0); } diff --git a/nanohttp.c b/nanohttp.c index ec6b50a..ca68d66 100644 --- a/nanohttp.c +++ b/nanohttp.c @@ -150,9 +150,9 @@ static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len ); * Handle an out of memory condition */ static void -xmlHTTPErrMemory(const char *extra) +xmlHTTPErrMemory(void) { - __xmlSimpleError(XML_FROM_HTTP, XML_ERR_NO_MEMORY, NULL, NULL, extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_HTTP, NULL); } /** @@ -361,7 +361,7 @@ xmlNanoHTTPNewCtxt(const char *URL) { ret = (xmlNanoHTTPCtxtPtr) xmlMalloc(sizeof(xmlNanoHTTPCtxt)); if (ret == NULL) { - xmlHTTPErrMemory("allocating context"); + xmlHTTPErrMemory(); return(NULL); } @@ -507,7 +507,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) if (ctxt->in == NULL) { ctxt->in = (char *) xmlMallocAtomic(65000); if (ctxt->in == NULL) { - xmlHTTPErrMemory("allocating input"); + xmlHTTPErrMemory(); ctxt->last = -1; return (-1); } @@ -532,7 +532,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) ctxt->inlen *= 2; ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); if (ctxt->in == NULL) { - xmlHTTPErrMemory("allocating input buffer"); + xmlHTTPErrMemory(); xmlFree(tmp_ptr); ctxt->last = -1; return (-1); @@ -1222,8 +1222,10 @@ xmlNanoHTTPRead(void *ctx, void *dest, int len) { } if (ctxt->inptr - ctxt->inrptr < len) len = ctxt->inptr - ctxt->inrptr; - memcpy(dest, ctxt->inrptr, len); - ctxt->inrptr += len; + if (len > 0) { + memcpy(dest, ctxt->inrptr, len); + ctxt->inrptr += len; + } return(len); } @@ -1391,7 +1393,7 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, } if ((ctxt->protocol == NULL) || (strcmp(ctxt->protocol, "http"))) { - __xmlIOErr(XML_FROM_HTTP, XML_HTTP_URL_SYNTAX, "Not a valid HTTP URI"); + __xmlIOErr(XML_FROM_IO, XML_IO_UNSUPPORTED_PROTOCOL, ctxt->protocol); xmlNanoHTTPFreeCtxt(ctxt); if (redirURL != NULL) xmlFree(redirURL); return(NULL); @@ -1447,7 +1449,7 @@ xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, bp = (char*)xmlMallocAtomic(blen); if ( bp == NULL ) { xmlNanoHTTPFreeCtxt( ctxt ); - xmlHTTPErrMemory("allocating header buffer"); + xmlHTTPErrMemory(); return ( NULL ); } @@ -1834,9 +1836,9 @@ int main(int argc, char **argv) { xmlNanoHTTPFetch(argv[1], "-", &contentType); if (contentType != NULL) xmlFree(contentType); } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s: minimal HTTP GET implementation\n", argv[0]); - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "\tusage %s [ URL [ filename ] ]\n", argv[0]); } xmlNanoHTTPCleanup(); @@ -1847,7 +1849,7 @@ int main(int argc, char **argv) { #ifdef STANDALONE #include int main(int argc, char **argv) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "%s : HTTP support not compiled in\n", argv[0]); return(0); } diff --git a/parser.c b/parser.c index ac621a6..0001ef9 100644 --- a/parser.c +++ b/parser.c @@ -108,23 +108,25 @@ struct _xmlParserNsData { unsigned elementId; int defaultNsIndex; + int minNsIndex; }; struct _xmlAttrHashBucket { int index; }; -static xmlParserCtxtPtr -xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, - const xmlChar *URL, const xmlChar *ID, const xmlChar *base, - xmlParserCtxtPtr pctx); - static int xmlParseElementStart(xmlParserCtxtPtr ctxt); static void xmlParseElementEnd(xmlParserCtxtPtr ctxt); +static xmlEntityPtr +xmlLookupGeneralEntity(xmlParserCtxtPtr ctxt, const xmlChar *name, int inAttr); + +static const xmlChar * +xmlParseEntityRefInternal(xmlParserCtxtPtr ctxt); + /************************************************************************ * * * Arbitrary limits set in the parser. See XML_PARSE_HUGE * @@ -159,7 +161,7 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt); * boundary feature. It can be disabled with the XML_PARSE_HUGE * parser option. */ -unsigned int xmlParserMaxDepth = 256; +const unsigned int xmlParserMaxDepth = 256; @@ -201,23 +203,8 @@ static const char* const xmlW3CPIs[] = { static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str); -static xmlParserErrors -xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, - xmlSAXHandlerPtr sax, - void *user_data, int depth, const xmlChar *URL, - const xmlChar *ID, xmlNodePtr *list); - -static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options); -#ifdef LIBXML_LEGACY_ENABLED static void -xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, - xmlNodePtr lastNode); -#endif /* LIBXML_LEGACY_ENABLED */ - -static xmlParserErrors -xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, - const xmlChar *string, void *user_data, xmlNodePtr *lst); +xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent); static int xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity); @@ -228,6 +215,11 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity); * * ************************************************************************/ +static void +xmlErrMemory(xmlParserCtxtPtr ctxt) { + xmlCtxtErrMemory(ctxt); +} + /** * xmlErrAttributeDup: * @ctxt: an XML parser context @@ -240,28 +232,14 @@ static void xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix, const xmlChar * localname) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED; - if (prefix == NULL) - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, - (const char *) localname, NULL, NULL, 0, 0, - "Attribute %s redefined\n", localname); + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED, + XML_ERR_FATAL, localname, NULL, NULL, 0, + "Attribute %s redefined\n", localname); else - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, - (const char *) prefix, (const char *) localname, - NULL, 0, 0, "Attribute %s:%s redefined\n", prefix, - localname); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED, + XML_ERR_FATAL, prefix, localname, NULL, 0, + "Attribute %s:%s redefined\n", prefix, localname); } /** @@ -276,18 +254,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, 0, "%s", msg); } /** @@ -304,29 +272,8 @@ void LIBXML_ATTR_FORMAT(3,0) xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - xmlStructuredErrorFunc schannel = NULL; - - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if ((ctxt != NULL) && (ctxt->sax != NULL) && - (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - if (ctxt != NULL) { - __xmlRaiseError(schannel, - (ctxt->sax) ? ctxt->sax->warning : NULL, - ctxt->userData, - ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } else { - __xmlRaiseError(schannel, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -342,31 +289,10 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - xmlStructuredErrorFunc schannel = NULL; + ctxt->valid = 0; - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = error; - if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - } - if (ctxt != NULL) { - __xmlRaiseError(schannel, - ctxt->vctxt.error, ctxt->vctxt.userData, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - ctxt->valid = 0; - } else { - __xmlRaiseError(schannel, NULL, NULL, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } + xmlCtxtErr(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -382,19 +308,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, int val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, NULL, NULL, NULL, val, 0, msg, val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, val, msg, val); } /** @@ -413,20 +328,8 @@ xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, int val, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, (const char *) str1, (const char *) str2, - NULL, val, 0, msg, str1, val, str2); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + str1, str2, NULL, val, msg, str1, val, str2); } /** @@ -442,20 +345,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar * val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, - XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, - val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + val, NULL, NULL, 0, msg, val); } /** @@ -471,15 +362,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar * val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, - XML_FROM_PARSER, error, XML_ERR_ERROR, - NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, - val); + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_ERROR, + val, NULL, NULL, 0, msg, val); } /** @@ -498,17 +382,10 @@ xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const xmlChar * info1, const xmlChar * info2, const xmlChar * info3) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_ERROR, NULL, 0, (const char *) info1, - (const char *) info2, (const char *) info3, 0, 0, msg, - info1, info2, info3); - if (ctxt != NULL) - ctxt->nsWellFormed = 0; + ctxt->nsWellFormed = 0; + + xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR, + info1, info2, info3, 0, msg, info1, info2, info3); } /** @@ -527,13 +404,8 @@ xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error, const xmlChar * info1, const xmlChar * info2, const xmlChar * info3) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_WARNING, NULL, 0, (const char *) info1, - (const char *) info2, (const char *) info3, 0, 0, msg, - info1, info2, info3); + xmlCtxtErr(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING, + info1, info2, info3, 0, msg, info1, info2, info3); } static void @@ -559,7 +431,7 @@ xmlSaturatedAddSizeT(unsigned long *dst, unsigned long val) { * * Check for non-linear entity expansion behaviour. * - * In some cases like xmlStringDecodeEntities, this function is called + * In some cases like xmlExpandEntityInAttValue, this function is called * for each, possibly nested entity and its unexpanded content length. * * In other cases like xmlParseReference, it's only called for each @@ -580,37 +452,41 @@ static int xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra) { unsigned long consumed; + unsigned long *expandedSize; xmlParserInputPtr input = ctxt->input; xmlEntityPtr entity = input->entity; + if ((entity) && (entity->flags & XML_ENT_CHECKED)) + return(0); + /* * Compute total consumed bytes so far, including input streams of * external entities. */ - consumed = input->parentConsumed; - if ((entity == NULL) || - ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && - ((entity->flags & XML_ENT_PARSED) == 0))) { - xmlSaturatedAdd(&consumed, input->consumed); - xmlSaturatedAddSizeT(&consumed, input->cur - input->base); - } + consumed = input->consumed; + xmlSaturatedAddSizeT(&consumed, input->cur - input->base); xmlSaturatedAdd(&consumed, ctxt->sizeentities); + if (entity) + expandedSize = &entity->expandedSize; + else + expandedSize = &ctxt->sizeentcopy; + /* * Add extra cost and some fixed cost. */ - xmlSaturatedAdd(&ctxt->sizeentcopy, extra); - xmlSaturatedAdd(&ctxt->sizeentcopy, XML_ENT_FIXED_COST); + xmlSaturatedAdd(expandedSize, extra); + xmlSaturatedAdd(expandedSize, XML_ENT_FIXED_COST); /* * It's important to always use saturation arithmetic when tracking * entity sizes to make the size checks reliable. If "sizeentcopy" * overflows, we have to abort. */ - if ((ctxt->sizeentcopy > XML_PARSER_ALLOWED_EXPANSION) && - ((ctxt->sizeentcopy >= ULONG_MAX) || - (ctxt->sizeentcopy / ctxt->maxAmpl > consumed))) { - xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP, + if ((*expandedSize > XML_PARSER_ALLOWED_EXPANSION) && + ((*expandedSize >= ULONG_MAX) || + (*expandedSize / ctxt->maxAmpl > consumed))) { + xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT, "Maximum entity amplification factor exceeded, see " "xmlCtxtSetMaxAmplification.\n"); xmlHaltParser(ctxt); @@ -809,12 +685,6 @@ xmlHasFeature(xmlFeature feature) return(0); #endif case XML_WITH_DEBUG_MEM: -#ifdef DEBUG_MEMORY_LOCATION - return(1); -#else - return(0); -#endif - case XML_WITH_DEBUG_RUN: return(0); case XML_WITH_ZLIB: #ifdef LIBXML_ZLIB_ENABLED @@ -840,6 +710,220 @@ xmlHasFeature(xmlFeature feature) return(0); } +/************************************************************************ + * * + * Simple string buffer * + * * + ************************************************************************/ + +typedef struct { + xmlChar *mem; + unsigned size; + unsigned cap; /* size < cap */ + unsigned max; /* size <= max */ + xmlParserErrors code; +} xmlSBuf; + +static void +xmlSBufInit(xmlSBuf *buf, unsigned max) { + buf->mem = NULL; + buf->size = 0; + buf->cap = 0; + buf->max = max; + buf->code = XML_ERR_OK; +} + +static int +xmlSBufGrow(xmlSBuf *buf, unsigned len) { + xmlChar *mem; + unsigned cap; + + if (len >= UINT_MAX / 2 - buf->size) { + if (buf->code == XML_ERR_OK) + buf->code = XML_ERR_RESOURCE_LIMIT; + return(-1); + } + + cap = (buf->size + len) * 2; + if (cap < 240) + cap = 240; + + mem = xmlRealloc(buf->mem, cap); + if (mem == NULL) { + buf->code = XML_ERR_NO_MEMORY; + return(-1); + } + + buf->mem = mem; + buf->cap = cap; + + return(0); +} + +static void +xmlSBufAddString(xmlSBuf *buf, const xmlChar *str, unsigned len) { + if (buf->max - buf->size < len) { + if (buf->code == XML_ERR_OK) + buf->code = XML_ERR_RESOURCE_LIMIT; + return; + } + + if (buf->cap - buf->size <= len) { + if (xmlSBufGrow(buf, len) < 0) + return; + } + + if (len > 0) + memcpy(buf->mem + buf->size, str, len); + buf->size += len; +} + +static void +xmlSBufAddCString(xmlSBuf *buf, const char *str, unsigned len) { + xmlSBufAddString(buf, (const xmlChar *) str, len); +} + +static void +xmlSBufAddChar(xmlSBuf *buf, int c) { + xmlChar *end; + + if (buf->max - buf->size < 4) { + if (buf->code == XML_ERR_OK) + buf->code = XML_ERR_RESOURCE_LIMIT; + return; + } + + if (buf->cap - buf->size <= 4) { + if (xmlSBufGrow(buf, 4) < 0) + return; + } + + end = buf->mem + buf->size; + + if (c < 0x80) { + *end = (xmlChar) c; + buf->size += 1; + } else { + buf->size += xmlCopyCharMultiByte(end, c); + } +} + +static void +xmlSBufAddReplChar(xmlSBuf *buf) { + xmlSBufAddCString(buf, "\xEF\xBF\xBD", 3); +} + +static void +xmlSBufReportError(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) { + if (buf->code == XML_ERR_NO_MEMORY) + xmlCtxtErrMemory(ctxt); + else + xmlFatalErr(ctxt, buf->code, errMsg); +} + +static xmlChar * +xmlSBufFinish(xmlSBuf *buf, int *sizeOut, xmlParserCtxtPtr ctxt, + const char *errMsg) { + if (buf->mem == NULL) { + buf->mem = xmlMalloc(1); + if (buf->mem == NULL) { + buf->code = XML_ERR_NO_MEMORY; + } else { + buf->mem[0] = 0; + } + } else { + buf->mem[buf->size] = 0; + } + + if (buf->code == XML_ERR_OK) { + if (sizeOut != NULL) + *sizeOut = buf->size; + return(buf->mem); + } + + xmlSBufReportError(buf, ctxt, errMsg); + + xmlFree(buf->mem); + + if (sizeOut != NULL) + *sizeOut = 0; + return(NULL); +} + +static void +xmlSBufCleanup(xmlSBuf *buf, xmlParserCtxtPtr ctxt, const char *errMsg) { + if (buf->code != XML_ERR_OK) + xmlSBufReportError(buf, ctxt, errMsg); + + xmlFree(buf->mem); +} + +static int +xmlUTF8MultibyteLen(xmlParserCtxtPtr ctxt, const xmlChar *str, + const char *errMsg) { + int c = str[0]; + int c1 = str[1]; + + if ((c1 & 0xC0) != 0x80) + goto encoding_error; + + if (c < 0xE0) { + /* 2-byte sequence */ + if (c < 0xC2) + goto encoding_error; + + return(2); + } else { + int c2 = str[2]; + + if ((c2 & 0xC0) != 0x80) + goto encoding_error; + + if (c < 0xF0) { + /* 3-byte sequence */ + if (c == 0xE0) { + /* overlong */ + if (c1 < 0xA0) + goto encoding_error; + } else if (c == 0xED) { + /* surrogate */ + if (c1 >= 0xA0) + goto encoding_error; + } else if (c == 0xEF) { + /* U+FFFE and U+FFFF are invalid Chars */ + if ((c1 == 0xBF) && (c2 >= 0xBE)) + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, errMsg); + } + + return(3); + } else { + /* 4-byte sequence */ + if ((str[3] & 0xC0) != 0x80) + goto encoding_error; + if (c == 0xF0) { + /* overlong */ + if (c1 < 0x90) + goto encoding_error; + } else if (c >= 0xF4) { + /* greater than 0x10FFFF */ + if ((c > 0xF4) || (c1 >= 0x90)) + goto encoding_error; + } + + return(4); + } + } + +encoding_error: + /* Only report the first error */ + if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { + xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL); + ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; + } + + return(0); +} + /************************************************************************ * * * SAX2 defaulted attributes handling * @@ -847,18 +931,25 @@ xmlHasFeature(xmlFeature feature) ************************************************************************/ /** - * xmlDetectSAX2: + * xmlCtxtInitializeLate: * @ctxt: an XML parser context * - * Do the SAX2 detection and specific initialization + * Final initialization of the parser context before starting to parse. + * + * This accounts for users modifying struct members of parser context + * directly. */ static void -xmlDetectSAX2(xmlParserCtxtPtr ctxt) { +xmlCtxtInitializeLate(xmlParserCtxtPtr ctxt) { xmlSAXHandlerPtr sax; /* Avoid unused variable warning if features are disabled. */ (void) sax; + /* + * Changing the SAX struct directly is still widespread practice + * in internal and external code. + */ if (ctxt == NULL) return; sax = ctxt->sax; #ifdef LIBXML_SAX1_ENABLED @@ -866,7 +957,9 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { * Only enable SAX2 if there SAX2 element handlers, except when there * are no element handlers at all. */ - if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && + if (((ctxt->options & XML_PARSE_SAX1) == 0) && + (sax) && + (sax->initialized == XML_SAX2_MAGIC) && ((sax->startElementNs != NULL) || (sax->endElementNs != NULL) || ((sax->startElement == NULL) && (sax->endElement == NULL)))) @@ -875,12 +968,16 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { ctxt->sax2 = 1; #endif /* LIBXML_SAX1_ENABLED */ + /* + * Some users replace the dictionary directly in the context struct. + * We really need an API function to do that cleanly. + */ ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || (ctxt->str_xml_ns == NULL)) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); } } @@ -945,65 +1042,6 @@ xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst) return(dst); } -/** - * xmlAttrNormalizeSpace2: - * @src: the source string - * - * Normalize the space in non CDATA attribute values, a slightly more complex - * front end to avoid allocation problems when running on attribute values - * coming from the input. - * - * Returns a pointer to the normalized value (dst) or NULL if no conversion - * is needed. - */ -static const xmlChar * -xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len) -{ - int i; - int remove_head = 0; - int need_realloc = 0; - const xmlChar *cur; - - if ((ctxt == NULL) || (src == NULL) || (len == NULL)) - return(NULL); - i = *len; - if (i <= 0) - return(NULL); - - cur = src; - while (*cur == 0x20) { - cur++; - remove_head++; - } - while (*cur != 0) { - if (*cur == 0x20) { - cur++; - if ((*cur == 0x20) || (*cur == 0)) { - need_realloc = 1; - break; - } - } else - cur++; - } - if (need_realloc) { - xmlChar *ret; - - ret = xmlStrndup(src + remove_head, i - remove_head + 1); - if (ret == NULL) { - xmlErrMemory(ctxt, NULL); - return(NULL); - } - xmlAttrNormalizeSpace(ret, ret); - *len = strlen((const char *)ret); - return(ret); - } else if (remove_head) { - *len -= remove_head; - memmove(src, src + remove_head, 1 + *len); - return(src); - } - return(NULL); -} - /** * xmlAddDefAttrs: * @ctxt: an XML parser context @@ -1115,13 +1153,13 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt, attr->prefix = prefix; attr->value = hvalue; attr->valueEnd = hvalue.name + len; - attr->external = ctxt->external; + attr->external = PARSER_EXTERNAL(ctxt); attr->expandedSize = expandedSize; return; mem_error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return; } @@ -1146,15 +1184,13 @@ xmlAddSpecialAttr(xmlParserCtxtPtr ctxt, goto mem_error; } - if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL) - return; - - xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr, - (void *) (ptrdiff_t) type); + if (xmlHashAdd2(ctxt->attsSpecial, fullname, fullattr, + (void *) (ptrdiff_t) type) < 0) + goto mem_error; return; mem_error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return; } @@ -1399,8 +1435,8 @@ xmlCheckLanguageID(const xmlChar * lang) * * ************************************************************************/ -static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, - const xmlChar ** str); +static xmlChar * +xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar **str); /** * xmlParserNsCreate: @@ -1545,8 +1581,12 @@ xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) { if (prefix->name == ctxt->str_xml) return(ctxt->str_xml_ns); + /* + * minNsIndex is used when building an entity tree. We must + * ignore namespaces declared outside the entity. + */ nsIndex = xmlParserNsLookup(ctxt, prefix, NULL); - if (nsIndex == INT_MAX) + if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex)) return(NULL); ret = ctxt->nsTab[nsIndex * 2 + 1]; @@ -1579,7 +1619,7 @@ xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) { else hprefix.hashValue = 0; nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL); - if (nsIndex == INT_MAX) + if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex)) return(NULL); return(ctxt->nsdb->extra[nsIndex].saxData); @@ -1612,7 +1652,7 @@ xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix, else hprefix.hashValue = 0; nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL); - if (nsIndex == INT_MAX) + if ((nsIndex == INT_MAX) || (nsIndex < ctxt->nsdb->minNsIndex)) return(-1); ctxt->nsdb->extra[nsIndex].saxData = saxData; @@ -1651,7 +1691,7 @@ xmlParserNsGrow(xmlParserCtxtPtr ctxt) { return(0); error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(-1); } @@ -1680,7 +1720,7 @@ xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix, return(0); if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(-1); } @@ -1746,13 +1786,13 @@ xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix, unsigned newSize, i, index; if (ctxt->nsdb->hashSize > UINT_MAX / 2) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(-1); } newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16; newHash = xmlMalloc(newSize * sizeof(newHash[0])); if (newHash == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(-1); } memset(newHash, 0, newSize * sizeof(newHash[0])); @@ -1880,7 +1920,7 @@ xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) { } return(ctxt->maxatts); mem_error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(-1); } @@ -1905,7 +1945,7 @@ inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value) tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab, newSize * sizeof(*tmp)); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return (-1); } ctxt->inputTab = tmp; @@ -1955,7 +1995,19 @@ inputPop(xmlParserCtxtPtr ctxt) int nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value) { - if (ctxt == NULL) return(0); + int maxDepth; + + if (ctxt == NULL) + return(0); + + maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256; + if (ctxt->nodeNr > maxDepth) { + xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT, + "Excessive depth in document: %d use XML_PARSE_HUGE option\n", + ctxt->nodeNr); + xmlHaltParser(ctxt); + return(-1); + } if (ctxt->nodeNr >= ctxt->nodeMax) { xmlNodePtr *tmp; @@ -1963,20 +2015,12 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value) ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0])); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return (-1); } ctxt->nodeTab = tmp; ctxt->nodeMax *= 2; } - if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) && - ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR, - "Excessive depth in document: %d use XML_PARSE_HUGE option\n", - xmlParserMaxDepth); - xmlHaltParser(ctxt); - return(-1); - } ctxt->nodeTab[ctxt->nodeNr] = value; ctxt->node = value; return (ctxt->nodeNr++); @@ -2064,7 +2108,7 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value, tag->nsNr = nsNr; return (ctxt->nameNr++); mem_error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return (-1); } #ifdef LIBXML_PUSH_ENABLED @@ -2125,7 +2169,7 @@ namePush(xmlParserCtxtPtr ctxt, const xmlChar * value) ctxt->name = value; return (ctxt->nameNr++); mem_error: - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return (-1); } @@ -2164,7 +2208,7 @@ static int spacePush(xmlParserCtxtPtr ctxt, int val) { tmp = (int *) xmlRealloc(ctxt->spaceTab, ctxt->spaceMax * sizeof(ctxt->spaceTab[0])); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); ctxt->spaceMax /=2; return(-1); } @@ -2265,18 +2309,21 @@ static int spacePop(xmlParserCtxtPtr ctxt) { xmlParserGrow(ctxt); \ } while (0) -/* Don't shrink push parser buffer. */ #define SHRINK \ - if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && \ + if ((!PARSER_PROGRESSIVE(ctxt)) && \ (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ xmlParserShrink(ctxt); -#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \ +#define GROW \ + if ((!PARSER_PROGRESSIVE(ctxt)) && \ + (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ xmlParserGrow(ctxt); #define SKIP_BLANKS xmlSkipBlankChars(ctxt) +#define SKIP_BLANKS_PE xmlSkipBlankCharsPE(ctxt) + #define NEXT xmlNextChar(ctxt) #define NEXT1 { \ @@ -2306,97 +2353,146 @@ static int spacePop(xmlParserCtxtPtr ctxt) { * * DEPRECATED: Internal function, do not use. * - * skip all blanks character found at that point in the input streams. - * It pops up finished entities in the process if allowable at that point. + * Skip whitespace in the input stream. * * Returns the number of space chars skipped */ - int xmlSkipBlankChars(xmlParserCtxtPtr ctxt) { + const xmlChar *cur; int res = 0; /* * It's Okay to use CUR/NEXT here since all the blanks are on * the ASCII range. */ - if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) || - (ctxt->instate == XML_PARSER_START)) { - const xmlChar *cur; - /* - * if we are in the document content, go really fast - */ - cur = ctxt->input->cur; - while (IS_BLANK_CH(*cur)) { - if (*cur == '\n') { - ctxt->input->line++; ctxt->input->col = 1; - } else { - ctxt->input->col++; - } - cur++; - if (res < INT_MAX) - res++; - if (*cur == 0) { - ctxt->input->cur = cur; - xmlParserGrow(ctxt); - cur = ctxt->input->cur; - } - } - ctxt->input->cur = cur; - } else { - int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1)); + cur = ctxt->input->cur; + while (IS_BLANK_CH(*cur)) { + if (*cur == '\n') { + ctxt->input->line++; ctxt->input->col = 1; + } else { + ctxt->input->col++; + } + cur++; + if (res < INT_MAX) + res++; + if (*cur == 0) { + ctxt->input->cur = cur; + xmlParserGrow(ctxt); + cur = ctxt->input->cur; + } + } + ctxt->input->cur = cur; - while (ctxt->instate != XML_PARSER_EOF) { - if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */ - NEXT; - } else if (CUR == '%') { - /* - * Need to handle support of entities branching here - */ - if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0)) - break; - xmlParsePEReference(ctxt); - } else if (CUR == 0) { - unsigned long consumed; - xmlEntityPtr ent; + return(res); +} - if (ctxt->inputNr <= 1) - break; +static void +xmlPopPE(xmlParserCtxtPtr ctxt) { + unsigned long consumed; + xmlEntityPtr ent; - consumed = ctxt->input->consumed; - xmlSaturatedAddSizeT(&consumed, - ctxt->input->cur - ctxt->input->base); + ent = ctxt->input->entity; - /* - * Add to sizeentities when parsing an external entity - * for the first time. - */ - ent = ctxt->input->entity; - if ((ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) && - ((ent->flags & XML_ENT_PARSED) == 0)) { - ent->flags |= XML_ENT_PARSED; + ent->flags &= ~XML_ENT_EXPANDING; - xmlSaturatedAdd(&ctxt->sizeentities, consumed); - } + if ((ent->flags & XML_ENT_CHECKED) == 0) { + int result; - xmlParserEntityCheck(ctxt, consumed); + /* + * Read the rest of the stream in case of errors. We want + * to account for the whole entity size. + */ + do { + ctxt->input->cur = ctxt->input->end; + xmlParserShrink(ctxt); + result = xmlParserGrow(ctxt); + } while (result > 0); - xmlPopInput(ctxt); - } else { + consumed = ctxt->input->consumed; + xmlSaturatedAddSizeT(&consumed, + ctxt->input->end - ctxt->input->base); + + xmlSaturatedAdd(&ent->expandedSize, consumed); + + /* + * Add to sizeentities when parsing an external entity + * for the first time. + */ + if (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY) { + xmlSaturatedAdd(&ctxt->sizeentities, consumed); + } + + ent->flags |= XML_ENT_CHECKED; + } + + xmlPopInput(ctxt); + + xmlParserEntityCheck(ctxt, ent->expandedSize); +} + +/** + * xmlSkipBlankCharsPE: + * @ctxt: the XML parser context + * + * Skip whitespace in the input stream, also handling parameter + * entities. + * + * Returns the number of space chars skipped + */ +static int +xmlSkipBlankCharsPE(xmlParserCtxtPtr ctxt) { + int res = 0; + int inParam; + int expandParam; + + inParam = PARSER_IN_PE(ctxt); + expandParam = PARSER_EXTERNAL(ctxt); + + if (!inParam && !expandParam) + return(xmlSkipBlankChars(ctxt)); + + while (PARSER_STOPPED(ctxt) == 0) { + if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */ + NEXT; + } else if (CUR == '%') { + if ((expandParam == 0) || + (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0)) break; - } /* - * Also increase the counter when entering or exiting a PERef. - * The spec says: "When a parameter-entity reference is recognized - * in the DTD and included, its replacement text MUST be enlarged - * by the attachment of one leading and one following space (#x20) - * character." + * Expand parameter entity. We continue to consume + * whitespace at the start of the entity and possible + * even consume the whole entity and pop it. We might + * even pop multiple PEs in this loop. */ - if (res < INT_MAX) - res++; + xmlParsePEReference(ctxt); + + inParam = PARSER_IN_PE(ctxt); + expandParam = PARSER_EXTERNAL(ctxt); + } else if (CUR == 0) { + if (inParam == 0) + break; + + xmlPopPE(ctxt); + + inParam = PARSER_IN_PE(ctxt); + expandParam = PARSER_EXTERNAL(ctxt); + } else { + break; } + + /* + * Also increase the counter when entering or exiting a PERef. + * The spec says: "When a parameter-entity reference is recognized + * in the DTD and included, its replacement text MUST be enlarged + * by the attachment of one leading and one following space (#x20) + * character." + */ + if (res < INT_MAX) + res++; } + return(res); } @@ -2420,16 +2516,7 @@ xmlPopInput(xmlParserCtxtPtr ctxt) { xmlParserInputPtr input; if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0); - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "Popping input %d\n", ctxt->inputNr); - if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) && - (ctxt->instate != XML_PARSER_EOF)) - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, - "Unfinished entity outside the DTD"); input = inputPop(ctxt); - if (input->entity != NULL) - input->entity->flags &= ~XML_ENT_EXPANDING; xmlFreeInputStream(input); if (*ctxt->input->cur == 0) xmlParserGrow(ctxt); @@ -2441,33 +2528,29 @@ xmlPopInput(xmlParserCtxtPtr ctxt) { * @ctxt: an XML parser context * @input: an XML parser input fragment (entity, XML fragment ...). * - * xmlPushInput: switch to a new input stream which is stacked on top - * of the previous one(s). - * Returns -1 in case of error or the index in the input stack + * Push an input stream onto the stack. + * + * This makes the parser use an input returned from advanced functions + * like xmlNewInputURL or xmlNewInputMemory. + * + * Returns -1 in case of error or the index in the input stack */ int xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { + int maxDepth; int ret; - if (input == NULL) return(-1); - - if (xmlParserDebugEntities) { - if ((ctxt->input != NULL) && (ctxt->input->filename)) - xmlGenericError(xmlGenericErrorContext, - "%s(%d): ", ctxt->input->filename, - ctxt->input->line); - xmlGenericError(xmlGenericErrorContext, - "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur); - } - if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) || - (ctxt->inputNr > 100)) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); - while (ctxt->inputNr > 1) - xmlFreeInputStream(inputPop(ctxt)); + + if ((ctxt == NULL) || (input == NULL)) + return(-1); + + maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20; + if (ctxt->inputNr > maxDepth) { + xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT, + "Maximum entity nesting depth exceeded"); + xmlHaltParser(ctxt); return(-1); } ret = inputPush(ctxt, input); - if (ctxt->instate == XML_PARSER_EOF) - return(-1); GROW; return(ret); } @@ -2501,12 +2584,10 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { (NXT(2) == 'x')) { SKIP(3); GROW; - while (RAW != ';') { /* loop blocked by count */ + while ((RAW != ';') && (PARSER_STOPPED(ctxt) == 0)) { if (count++ > 20) { count = 0; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(0); } if ((RAW >= '0') && (RAW <= '9')) val = val * 16 + (CUR - '0'); @@ -2537,8 +2618,6 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { if (count++ > 20) { count = 0; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(0); } if ((RAW >= '0') && (RAW <= '9')) val = val * 10 + (CUR - '0'); @@ -2713,288 +2792,9 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) { */ void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { - switch(ctxt->instate) { - case XML_PARSER_CDATA_SECTION: - return; - case XML_PARSER_COMMENT: - return; - case XML_PARSER_START_TAG: - return; - case XML_PARSER_END_TAG: - return; - case XML_PARSER_EOF: - xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL); - return; - case XML_PARSER_PROLOG: - case XML_PARSER_START: - case XML_PARSER_XML_DECL: - case XML_PARSER_MISC: - xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL); - return; - case XML_PARSER_ENTITY_DECL: - case XML_PARSER_CONTENT: - case XML_PARSER_ATTRIBUTE_VALUE: - case XML_PARSER_PI: - case XML_PARSER_SYSTEM_LITERAL: - case XML_PARSER_PUBLIC_LITERAL: - /* we just ignore it there */ - return; - case XML_PARSER_EPILOG: - xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL); - return; - case XML_PARSER_ENTITY_VALUE: - /* - * NOTE: in the case of entity values, we don't do the - * substitution here since we need the literal - * entity value to be able to save the internal - * subset of the document. - * This will be handled by xmlStringDecodeEntities - */ - return; - case XML_PARSER_DTD: - /* - * [WFC: Well-Formedness Constraint: PEs in Internal Subset] - * In the internal DTD subset, parameter-entity references - * can occur only where markup declarations can occur, not - * within markup declarations. - * In that case this is handled in xmlParseMarkupDecl - */ - if ((ctxt->external == 0) && (ctxt->inputNr == 1)) - return; - if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0) - return; - break; - case XML_PARSER_IGNORE: - return; - } - xmlParsePEReference(ctxt); } -/* - * Macro used to grow the current buffer. - * buffer##_size is expected to be a size_t - * mem_error: is expected to handle memory allocation failures - */ -#define growBuffer(buffer, n) { \ - xmlChar *tmp; \ - size_t new_size = buffer##_size * 2 + n; \ - if (new_size < buffer##_size) goto mem_error; \ - tmp = (xmlChar *) xmlRealloc(buffer, new_size); \ - if (tmp == NULL) goto mem_error; \ - buffer = tmp; \ - buffer##_size = new_size; \ -} - -/** - * xmlStringDecodeEntitiesInt: - * @ctxt: the parser context - * @str: the input string - * @len: the string length - * @what: combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF - * @end: an end marker xmlChar, 0 if none - * @end2: an end marker xmlChar, 0 if none - * @end3: an end marker xmlChar, 0 if none - * @check: whether to perform entity checks - */ -static xmlChar * -xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, - int what, xmlChar end, xmlChar end2, xmlChar end3, - int check) { - xmlChar *buffer = NULL; - size_t buffer_size = 0; - size_t nbchars = 0; - - xmlChar *current = NULL; - xmlChar *rep = NULL; - const xmlChar *last; - xmlEntityPtr ent; - int c,l; - - if (str == NULL) - return(NULL); - last = str + len; - - if (((ctxt->depth > 40) && - ((ctxt->options & XML_PARSE_HUGE) == 0)) || - (ctxt->depth > 100)) { - xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP, - "Maximum entity nesting depth exceeded"); - return(NULL); - } - - /* - * allocate a translation buffer. - */ - buffer_size = XML_PARSER_BIG_BUFFER_SIZE; - buffer = (xmlChar *) xmlMallocAtomic(buffer_size); - if (buffer == NULL) goto mem_error; - - /* - * OK loop until we reach one of the ending char or a size limit. - * we are operating on already parsed values. - */ - if (str < last) - c = CUR_SCHAR(str, l); - else - c = 0; - while ((c != 0) && (c != end) && /* non input consuming loop */ - (c != end2) && (c != end3) && - (ctxt->instate != XML_PARSER_EOF)) { - - if (c == 0) break; - if ((c == '&') && (str[1] == '#')) { - int val = xmlParseStringCharRef(ctxt, &str); - if (val == 0) - goto int_error; - COPY_BUF(buffer, nbchars, val); - if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); - } - } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "String decoding Entity Reference: %.30s\n", - str); - ent = xmlParseStringEntityRef(ctxt, &str); - if ((ent != NULL) && - (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { - if (ent->content != NULL) { - COPY_BUF(buffer, nbchars, ent->content[0]); - if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); - } - } else { - xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, - "predefined entity has no content\n"); - goto int_error; - } - } else if ((ent != NULL) && (ent->content != NULL)) { - if ((check) && (xmlParserEntityCheck(ctxt, ent->length))) - goto int_error; - - if (ent->flags & XML_ENT_EXPANDING) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); - xmlHaltParser(ctxt); - ent->content[0] = 0; - goto int_error; - } - - ent->flags |= XML_ENT_EXPANDING; - ctxt->depth++; - rep = xmlStringDecodeEntitiesInt(ctxt, ent->content, - ent->length, what, 0, 0, 0, check); - ctxt->depth--; - ent->flags &= ~XML_ENT_EXPANDING; - - if (rep == NULL) { - ent->content[0] = 0; - goto int_error; - } - - current = rep; - while (*current != 0) { /* non input consuming loop */ - buffer[nbchars++] = *current++; - if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); - } - } - xmlFree(rep); - rep = NULL; - } else if (ent != NULL) { - int i = xmlStrlen(ent->name); - const xmlChar *cur = ent->name; - - buffer[nbchars++] = '&'; - if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE); - } - for (;i > 0;i--) - buffer[nbchars++] = *cur++; - buffer[nbchars++] = ';'; - } - } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) { - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "String decoding PE Reference: %.30s\n", str); - ent = xmlParseStringPEReference(ctxt, &str); - if (ent != NULL) { - if (ent->content == NULL) { - /* - * Note: external parsed entities will not be loaded, - * it is not required for a non-validating parser to - * complete external PEReferences coming from the - * internal subset - */ - if (((ctxt->options & XML_PARSE_NOENT) != 0) || - ((ctxt->options & XML_PARSE_DTDVALID) != 0) || - (ctxt->validate != 0)) { - xmlLoadEntityContent(ctxt, ent); - } else { - xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING, - "not validating will not read content for PE entity %s\n", - ent->name, NULL); - } - } - - if ((check) && (xmlParserEntityCheck(ctxt, ent->length))) - goto int_error; - - if (ent->flags & XML_ENT_EXPANDING) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); - xmlHaltParser(ctxt); - if (ent->content != NULL) - ent->content[0] = 0; - goto int_error; - } - - ent->flags |= XML_ENT_EXPANDING; - ctxt->depth++; - rep = xmlStringDecodeEntitiesInt(ctxt, ent->content, - ent->length, what, 0, 0, 0, check); - ctxt->depth--; - ent->flags &= ~XML_ENT_EXPANDING; - - if (rep == NULL) { - if (ent->content != NULL) - ent->content[0] = 0; - goto int_error; - } - current = rep; - while (*current != 0) { /* non input consuming loop */ - buffer[nbchars++] = *current++; - if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); - } - } - xmlFree(rep); - rep = NULL; - } - } else { - COPY_BUF(buffer, nbchars, c); - str += l; - if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); - } - } - if (str < last) - c = CUR_SCHAR(str, l); - else - c = 0; - } - buffer[nbchars] = 0; - return(buffer); - -mem_error: - xmlErrMemory(ctxt, NULL); -int_error: - if (rep != NULL) - xmlFree(rep); - if (buffer != NULL) - xmlFree(buffer); - return(NULL); -} - /** * xmlStringLenDecodeEntities: * @ctxt: the parser context @@ -3007,23 +2807,21 @@ xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, * * DEPRECATED: Internal function, don't use. * - * Takes a entity string content and process to do the adequate substitutions. - * - * [67] Reference ::= EntityRef | CharRef - * - * [69] PEReference ::= '%' Name ';' - * * Returns A newly allocated string with the substitution done. The caller * must deallocate it ! */ xmlChar * xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, - int what, xmlChar end, xmlChar end2, - xmlChar end3) { + int what ATTRIBUTE_UNUSED, + xmlChar end, xmlChar end2, xmlChar end3) { if ((ctxt == NULL) || (str == NULL) || (len < 0)) return(NULL); - return(xmlStringDecodeEntitiesInt(ctxt, str, len, what, - end, end2, end3, 0)); + + if ((str[len] != 0) || + (end != 0) || (end2 != 0) || (end3 != 0)) + return(NULL); + + return(xmlExpandEntitiesInAttValue(ctxt, str, 0)); } /** @@ -3037,21 +2835,20 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, * * DEPRECATED: Internal function, don't use. * - * Takes a entity string content and process to do the adequate substitutions. - * - * [67] Reference ::= EntityRef | CharRef - * - * [69] PEReference ::= '%' Name ';' - * * Returns A newly allocated string with the substitution done. The caller * must deallocate it ! */ xmlChar * -xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, +xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, + int what ATTRIBUTE_UNUSED, xmlChar end, xmlChar end2, xmlChar end3) { - if ((ctxt == NULL) || (str == NULL)) return(NULL); - return(xmlStringDecodeEntitiesInt(ctxt, str, xmlStrlen(str), what, - end, end2, end3, 0)); + if ((ctxt == NULL) || (str == NULL)) + return(NULL); + + if ((end != 0) || (end2 != 0) || (end3 != 0)) + return(NULL); + + return(xmlExpandEntitiesInAttValue(ctxt, str, 0)); } /************************************************************************ @@ -3074,7 +2871,7 @@ xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, int blank_chars) { - int i, ret; + int i; xmlNodePtr lastChild; /* @@ -3104,9 +2901,25 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, */ if (ctxt->node == NULL) return(0); if (ctxt->myDoc != NULL) { - ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name); - if (ret == 0) return(1); - if (ret == 1) return(0); + xmlElementPtr elemDecl = NULL; + xmlDocPtr doc = ctxt->myDoc; + const xmlChar *prefix = NULL; + + if (ctxt->node->ns) + prefix = ctxt->node->ns->prefix; + if (doc->intSubset != NULL) + elemDecl = xmlHashLookup2(doc->intSubset->elements, ctxt->node->name, + prefix); + if ((elemDecl == NULL) && (doc->extSubset != NULL)) + elemDecl = xmlHashLookup2(doc->extSubset->elements, ctxt->node->name, + prefix); + if (elemDecl != NULL) { + if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) + return(1); + if ((elemDecl->etype == XML_ELEMENT_TYPE_ANY) || + (elemDecl->etype == XML_ELEMENT_TYPE_MIXED)) + return(0); + } } /* @@ -3139,7 +2952,7 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, * xmlSplitQName: * @ctxt: an XML parser context * @name: an XML parser context - * @prefix: a xmlChar ** + * @prefixOut: a xmlChar ** * * parse an UTF8 encoded XML qualified name string * @@ -3154,27 +2967,21 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, */ xmlChar * -xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { +xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) { xmlChar buf[XML_MAX_NAMELEN + 5]; xmlChar *buffer = NULL; int len = 0; int max = XML_MAX_NAMELEN; xmlChar *ret = NULL; + xmlChar *prefix; const xmlChar *cur = name; int c; - if (prefix == NULL) return(NULL); - *prefix = NULL; + if (prefixOut == NULL) return(NULL); + *prefixOut = NULL; if (cur == NULL) return(NULL); -#ifndef XML_XML_NAMESPACE - /* xml: prefix is not really a namespace */ - if ((cur[0] == 'x') && (cur[1] == 'm') && - (cur[2] == 'l') && (cur[3] == ':')) - return(xmlStrdup(name)); -#endif - /* nasty but well=formed */ if (cur[0] == ':') return(xmlStrdup(name)); @@ -3193,7 +3000,7 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } memcpy(buffer, buf, len); @@ -3205,7 +3012,7 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { xmlFree(buffer); - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } buffer = tmp; @@ -3219,13 +3026,16 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { if ((c == ':') && (*cur == 0)) { if (buffer != NULL) xmlFree(buffer); - *prefix = NULL; return(xmlStrdup(name)); } - if (buffer == NULL) + if (buffer == NULL) { ret = xmlStrndup(buf, len); - else { + if (ret == NULL) { + xmlErrMemory(ctxt); + return(NULL); + } + } else { ret = buffer; buffer = NULL; max = XML_MAX_NAMELEN; @@ -3234,9 +3044,15 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { if (c == ':') { c = *cur; - *prefix = ret; + prefix = ret; if (c == 0) { - return(xmlStrndup(BAD_CAST "", 0)); + ret = xmlStrndup(BAD_CAST "", 0); + if (ret == NULL) { + xmlFree(prefix); + return(NULL); + } + *prefixOut = prefix; + return(ret); } len = 0; @@ -3271,7 +3087,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); + xmlFree(prefix); return(NULL); } memcpy(buffer, buf, len); @@ -3282,7 +3099,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { max *= 2; tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); + xmlFree(prefix); xmlFree(buffer); return(NULL); } @@ -3294,11 +3112,17 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { buffer[len] = 0; } - if (buffer == NULL) + if (buffer == NULL) { ret = xmlStrndup(buf, len); - else { + if (ret == NULL) { + xmlFree(prefix); + return(NULL); + } + } else { ret = buffer; } + + *prefixOut = prefix; } return(ret); @@ -3397,11 +3221,9 @@ xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) { return(0); } -static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, - int *len, int *alloc, int normalize); - static const xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + const xmlChar *ret; int len = 0, l; int c; int maxLength = (ctxt->options & XML_PARSE_HUGE) ? @@ -3486,8 +3308,6 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); } } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); return(NULL); @@ -3503,8 +3323,12 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { return (NULL); } if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) - return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len)); - return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len); + else + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len); + if (ret == NULL) + xmlErrMemory(ctxt); + return(ret); } /** @@ -3535,8 +3359,6 @@ xmlParseName(xmlParserCtxtPtr ctxt) { XML_MAX_NAME_LENGTH; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); /* * Accelerator for simple ASCII names @@ -3562,7 +3384,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) { ctxt->input->cur = in; ctxt->input->col += count; if (ret == NULL) - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(ret); } } @@ -3600,13 +3422,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { NEXTL(l); c = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return(ret); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); return(ret); } ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len); + if (ret.name == NULL) + xmlErrMemory(ctxt); return(ret); } @@ -3663,7 +3485,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) { ctxt->input->cur = in; ctxt->input->col += count; if (ret.name == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); } return(ret); } @@ -3690,8 +3512,6 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { const xmlChar *ret; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); in = ctxt->input->cur; while (*in != 0 && *in == *cmp) { @@ -3734,6 +3554,7 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { static xmlChar * xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { xmlChar buf[XML_MAX_NAMELEN + 5]; + xmlChar *ret; const xmlChar *cur = *str; int len = 0, l; int c; @@ -3763,7 +3584,7 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } memcpy(buffer, buf, len); @@ -3774,7 +3595,7 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { max *= 2; tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); xmlFree(buffer); return(NULL); } @@ -3799,7 +3620,10 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { return(NULL); } *str = cur; - return(xmlStrndup(buf, len)); + ret = xmlStrndup(buf, len); + if (ret == NULL) + xmlErrMemory(ctxt); + return(ret); } /** @@ -3820,6 +3644,7 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { xmlChar * xmlParseNmtoken(xmlParserCtxtPtr ctxt) { xmlChar buf[XML_MAX_NAMELEN + 5]; + xmlChar *ret; int len = 0, l; int c; int maxLength = (ctxt->options & XML_PARSE_HUGE) ? @@ -3842,7 +3667,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } memcpy(buffer, buf, len); @@ -3853,7 +3678,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { max *= 2; tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); xmlFree(buffer); return(NULL); } @@ -3869,22 +3694,170 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); } buffer[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buffer); - return(NULL); - } return(buffer); } } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); if (len == 0) return(NULL); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); return(NULL); } - return(xmlStrndup(buf, len)); + ret = xmlStrndup(buf, len); + if (ret == NULL) + xmlErrMemory(ctxt); + return(ret); +} + +/** + * xmlExpandPEsInEntityValue: + * @ctxt: parser context + * @buf: string buffer + * @str: entity value + * @length: size of entity value + * @depth: nesting depth + * + * Validate an entity value and expand parameter entities. + */ +static void +xmlExpandPEsInEntityValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf, + const xmlChar *str, int length, int depth) { + int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20; + const xmlChar *end, *chunk; + int c, l; + + if (str == NULL) + return; + + depth += 1; + if (depth > maxDepth) { + xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT, + "Maximum entity nesting depth exceeded"); + return; + } + + end = str + length; + chunk = str; + + while ((str < end) && (!PARSER_STOPPED(ctxt))) { + c = *str; + + if (c >= 0x80) { + l = xmlUTF8MultibyteLen(ctxt, str, + "invalid character in entity value\n"); + if (l == 0) { + if (chunk < str) + xmlSBufAddString(buf, chunk, str - chunk); + xmlSBufAddReplChar(buf); + str += 1; + chunk = str; + } else { + str += l; + } + } else if (c == '&') { + if (str[1] == '#') { + if (chunk < str) + xmlSBufAddString(buf, chunk, str - chunk); + + c = xmlParseStringCharRef(ctxt, &str); + if (c == 0) + return; + + xmlSBufAddChar(buf, c); + + chunk = str; + } else { + xmlChar *name; + + /* + * General entity references are checked for + * syntactic validity. + */ + str++; + name = xmlParseStringName(ctxt, &str); + + if ((name == NULL) || (*str++ != ';')) { + xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_CHAR_ERROR, + "EntityValue: '&' forbidden except for entities " + "references\n"); + xmlFree(name); + return; + } + + xmlFree(name); + } + } else if (c == '%') { + xmlEntityPtr ent; + + if (chunk < str) + xmlSBufAddString(buf, chunk, str - chunk); + + ent = xmlParseStringPEReference(ctxt, &str); + if (ent == NULL) + return; + + if (!PARSER_EXTERNAL(ctxt)) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL); + return; + } + + if (ent->content == NULL) { + /* + * Note: external parsed entities will not be loaded, + * it is not required for a non-validating parser to + * complete external PEReferences coming from the + * internal subset + */ + if (((ctxt->options & XML_PARSE_NO_XXE) == 0) && + ((ctxt->replaceEntities) || + (ctxt->validate))) { + xmlLoadEntityContent(ctxt, ent); + } else { + xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING, + "not validating will not read content for " + "PE entity %s\n", ent->name, NULL); + } + } + + /* + * TODO: Skip if ent->content is still NULL. + */ + + if (xmlParserEntityCheck(ctxt, ent->length)) + return; + + if (ent->flags & XML_ENT_EXPANDING) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + xmlHaltParser(ctxt); + return; + } + + ent->flags |= XML_ENT_EXPANDING; + xmlExpandPEsInEntityValue(ctxt, buf, ent->content, ent->length, + depth); + ent->flags &= ~XML_ENT_EXPANDING; + + chunk = str; + } else { + /* Normal ASCII char */ + if (!IS_BYTE_CHAR(c)) { + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, + "invalid character in entity value\n"); + if (chunk < str) + xmlSBufAddString(buf, chunk, str - chunk); + xmlSBufAddReplChar(buf); + str += 1; + chunk = str; + } else { + str += 1; + } + } + } + + if (chunk < str) + xmlSBufAddString(buf, chunk, str - chunk); + + return; } /** @@ -3901,404 +3874,640 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { * * Returns the EntityValue parsed with reference substituted or NULL */ - xmlChar * xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { - xmlChar *buf = NULL; - int len = 0; - int size = XML_PARSER_BUFFER_SIZE; - int c, l; - int maxLength = (ctxt->options & XML_PARSE_HUGE) ? - XML_MAX_HUGE_LENGTH : - XML_MAX_TEXT_LENGTH; - xmlChar stop; - xmlChar *ret = NULL; - const xmlChar *cur = NULL; - xmlParserInputPtr input; + unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_TEXT_LENGTH; + xmlSBuf buf; + const xmlChar *start; + int quote, length; - if (RAW == '"') stop = '"'; - else if (RAW == '\'') stop = '\''; - else { - xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL); - return(NULL); - } - buf = (xmlChar *) xmlMallocAtomic(size); - if (buf == NULL) { - xmlErrMemory(ctxt, NULL); + xmlSBufInit(&buf, maxLength); + + GROW; + + quote = CUR; + if ((quote != '"') && (quote != '\'')) { + xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL); return(NULL); } + CUR_PTR++; - /* - * The content of the entity definition is copied in a buffer. - */ + length = 0; - ctxt->instate = XML_PARSER_ENTITY_VALUE; - input = ctxt->input; - GROW; - if (ctxt->instate == XML_PARSER_EOF) - goto error; - NEXT; - c = CUR_CHAR(l); /* - * NOTE: 4.4.5 Included in Literal - * When a parameter entity reference appears in a literal entity - * value, ... a single or double quote character in the replacement - * text is always treated as a normal data character and will not - * terminate the literal. - * In practice it means we stop the loop only when back at parsing - * the initial entity and the quote is found + * Copy raw content of the entity into a buffer */ - while (((IS_CHAR(c)) && ((c != stop) || /* checked */ - (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) { - if (len + 5 >= size) { - xmlChar *tmp; + while (1) { + int c; - size *= 2; - tmp = (xmlChar *) xmlRealloc(buf, size); - if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); - goto error; - } - buf = tmp; - } - COPY_BUF(buf, len, c); - NEXTL(l); + if (PARSER_STOPPED(ctxt)) + goto error; - GROW; - c = CUR_CHAR(l); - if (c == 0) { - GROW; - c = CUR_CHAR(l); - } + if (CUR_PTR >= ctxt->input->end) { + xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL); + goto error; + } - if (len > maxLength) { - xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, - "entity value too long\n"); + c = CUR; + + if (c == 0) { + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, + "invalid character in entity value\n"); goto error; } + if (c == quote) + break; + NEXTL(1); + length += 1; + + /* + * TODO: Check growth threshold + */ + if (ctxt->input->end - CUR_PTR < 10) + GROW; } - buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) - goto error; - if (c != stop) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL); - goto error; + + start = CUR_PTR - length; + + if (orig != NULL) { + *orig = xmlStrndup(start, length); + if (*orig == NULL) + xmlErrMemory(ctxt); + } + + xmlExpandPEsInEntityValue(ctxt, &buf, start, length, ctxt->inputNr); + + NEXTL(1); + + return(xmlSBufFinish(&buf, NULL, ctxt, "entity length too long")); + +error: + xmlSBufCleanup(&buf, ctxt, "entity length too long"); + return(NULL); +} + +/** + * xmlCheckEntityInAttValue: + * @ctxt: parser context + * @pent: entity + * @depth: nesting depth + * + * Check an entity reference in an attribute value for validity + * without expanding it. + */ +static void +xmlCheckEntityInAttValue(xmlParserCtxtPtr ctxt, xmlEntityPtr pent, int depth) { + int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20; + const xmlChar *str; + unsigned long expandedSize = pent->length; + int c, flags; + + depth += 1; + if (depth > maxDepth) { + xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT, + "Maximum entity nesting depth exceeded"); + return; + } + + if (pent->flags & XML_ENT_EXPANDING) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + xmlHaltParser(ctxt); + return; } - NEXT; /* - * Raise problem w.r.t. '&' and '%' being used in non-entities - * reference constructs. Note Charref will be handled in - * xmlStringDecodeEntities() + * If we're parsing a default attribute value in DTD content, + * the entity might reference other entities which weren't + * defined yet, so the check isn't reliable. */ - cur = buf; - while (*cur != 0) { /* non input consuming */ - if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) { - xmlChar *name; - xmlChar tmp = *cur; - int nameOk = 0; + if (ctxt->inSubset == 0) + flags = XML_ENT_CHECKED | XML_ENT_VALIDATED; + else + flags = XML_ENT_VALIDATED; - cur++; - name = xmlParseStringName(ctxt, &cur); - if (name != NULL) { - nameOk = 1; - xmlFree(name); + str = pent->content; + if (str == NULL) + goto done; + + /* + * Note that entity values are already validated. We only check + * for illegal less-than signs and compute the expanded size + * of the entity. No special handling for multi-byte characters + * is needed. + */ + while (!PARSER_STOPPED(ctxt)) { + c = *str; + + if (c != '&') { + if (c == 0) + break; + + if (c == '<') + xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, + "'<' in entity '%s' is not allowed in attributes " + "values\n", pent->name); + + str += 1; + } else if (str[1] == '#') { + int val; + + val = xmlParseStringCharRef(ctxt, &str); + if (val == 0) { + pent->content[0] = 0; + break; } - if ((nameOk == 0) || (*cur != ';')) { - xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR, - "EntityValue: '%c' forbidden except for entities references\n", - tmp); - goto error; - } - if ((tmp == '%') && (ctxt->inSubset == 1) && - (ctxt->inputNr == 1)) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL); - goto error; - } - if (*cur == 0) - break; - } - cur++; + } else { + xmlChar *name; + xmlEntityPtr ent; + + name = xmlParseStringEntityRef(ctxt, &str); + if (name == NULL) { + pent->content[0] = 0; + break; + } + + ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1); + xmlFree(name); + + if ((ent != NULL) && + (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) { + if ((ent->flags & flags) != flags) { + pent->flags |= XML_ENT_EXPANDING; + xmlCheckEntityInAttValue(ctxt, ent, depth); + pent->flags &= ~XML_ENT_EXPANDING; + } + + xmlSaturatedAdd(&expandedSize, ent->expandedSize); + xmlSaturatedAdd(&expandedSize, XML_ENT_FIXED_COST); + } + } + } + +done: + if (ctxt->inSubset == 0) + pent->expandedSize = expandedSize; + + pent->flags |= flags; +} + +/** + * xmlExpandEntityInAttValue: + * @ctxt: parser context + * @buf: string buffer + * @str: entity or attribute value + * @pent: entity for entity value, NULL for attribute values + * @normalize: whether to collapse whitespace + * @inSpace: whitespace state + * @depth: nesting depth + * @check: whether to check for amplification + * + * Expand general entity references in an entity or attribute value. + * Perform attribute value normalization. + */ +static void +xmlExpandEntityInAttValue(xmlParserCtxtPtr ctxt, xmlSBuf *buf, + const xmlChar *str, xmlEntityPtr pent, int normalize, + int *inSpace, int depth, int check) { + int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20; + int c, chunkSize; + + if (str == NULL) + return; + + depth += 1; + if (depth > maxDepth) { + xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT, + "Maximum entity nesting depth exceeded"); + return; + } + + if (pent != NULL) { + if (pent->flags & XML_ENT_EXPANDING) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + xmlHaltParser(ctxt); + return; + } + + if (check) { + if (xmlParserEntityCheck(ctxt, pent->length)) + return; + } } + chunkSize = 0; + /* - * Then PEReference entities are substituted. - * - * NOTE: 4.4.7 Bypassed - * When a general entity reference appears in the EntityValue in - * an entity declaration, it is bypassed and left as is. - * so XML_SUBSTITUTE_REF is not set here. + * Note that entity values are already validated. No special + * handling for multi-byte characters is needed. */ - ++ctxt->depth; - ret = xmlStringDecodeEntitiesInt(ctxt, buf, len, XML_SUBSTITUTE_PEREF, - 0, 0, 0, /* check */ 1); - --ctxt->depth; + while (!PARSER_STOPPED(ctxt)) { + c = *str; - if (orig != NULL) { - *orig = buf; - buf = NULL; + if (c != '&') { + if (c == 0) + break; + + /* + * If this function is called without an entity, it is used to + * expand entities in an attribute content where less-than was + * already unscaped and is allowed. + */ + if ((pent != NULL) && (c == '<')) { + xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, + "'<' in entity '%s' is not allowed in attributes " + "values\n", pent->name); + break; + } + + if (c <= 0x20) { + if ((normalize) && (*inSpace)) { + /* Skip char */ + if (chunkSize > 0) { + xmlSBufAddString(buf, str - chunkSize, chunkSize); + chunkSize = 0; + } + } else if (c < 0x20) { + if (chunkSize > 0) { + xmlSBufAddString(buf, str - chunkSize, chunkSize); + chunkSize = 0; + } + + xmlSBufAddCString(buf, " ", 1); + } else { + chunkSize += 1; + } + + *inSpace = 1; + } else { + chunkSize += 1; + *inSpace = 0; + } + + str += 1; + } else if (str[1] == '#') { + int val; + + if (chunkSize > 0) { + xmlSBufAddString(buf, str - chunkSize, chunkSize); + chunkSize = 0; + } + + val = xmlParseStringCharRef(ctxt, &str); + if (val == 0) { + if (pent != NULL) + pent->content[0] = 0; + break; + } + + if (val == ' ') { + if ((!normalize) || (!*inSpace)) + xmlSBufAddCString(buf, " ", 1); + *inSpace = 1; + } else { + xmlSBufAddChar(buf, val); + *inSpace = 0; + } + } else { + xmlChar *name; + xmlEntityPtr ent; + + if (chunkSize > 0) { + xmlSBufAddString(buf, str - chunkSize, chunkSize); + chunkSize = 0; + } + + name = xmlParseStringEntityRef(ctxt, &str); + if (name == NULL) { + if (pent != NULL) + pent->content[0] = 0; + break; + } + + ent = xmlLookupGeneralEntity(ctxt, name, /* inAttr */ 1); + xmlFree(name); + + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (ent->content == NULL) { + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, + "predefined entity has no content\n"); + break; + } + + xmlSBufAddString(buf, ent->content, ent->length); + + *inSpace = 0; + } else if ((ent != NULL) && (ent->content != NULL)) { + if (pent != NULL) + pent->flags |= XML_ENT_EXPANDING; + xmlExpandEntityInAttValue(ctxt, buf, ent->content, ent, + normalize, inSpace, depth, check); + if (pent != NULL) + pent->flags &= ~XML_ENT_EXPANDING; + } + } } -error: - if (buf != NULL) - xmlFree(buf); - return(ret); + if (chunkSize > 0) + xmlSBufAddString(buf, str - chunkSize, chunkSize); + + return; +} + +/** + * xmlExpandEntitiesInAttValue: + * @ctxt: parser context + * @str: entity or attribute value + * @normalize: whether to collapse whitespace + * + * Expand general entity references in an entity or attribute value. + * Perform attribute value normalization. + * + * Returns the expanded attribtue value. + */ +xmlChar * +xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str, + int normalize) { + unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_TEXT_LENGTH; + xmlSBuf buf; + int inSpace = 1; + + xmlSBufInit(&buf, maxLength); + + xmlExpandEntityInAttValue(ctxt, &buf, str, NULL, normalize, &inSpace, + ctxt->inputNr, /* check */ 0); + + if ((normalize) && (inSpace) && (buf.size > 0)) + buf.size--; + + return(xmlSBufFinish(&buf, NULL, ctxt, "AttValue length too long")); } /** - * xmlParseAttValueComplex: + * xmlParseAttValueInternal: * @ctxt: an XML parser context - * @len: the resulting attribute len - * @normalize: whether to apply the inner normalization + * @len: attribute len result + * @alloc: whether the attribute was reallocated as a new string + * @normalize: if 1 then further non-CDATA normalization must be done * - * parse a value for an attribute, this is the fallback function - * of xmlParseAttValue() when the attribute parsing requires handling - * of non-ASCII characters, or normalization compaction. + * parse a value for an attribute. + * NOTE: if no normalization is needed, the routine will return pointers + * directly from the data buffer. * - * Returns the AttValue parsed or NULL. The value has to be freed by the caller. + * 3.3.3 Attribute-Value Normalization: + * Before the value of an attribute is passed to the application or + * checked for validity, the XML processor must normalize it as follows: + * - a character reference is processed by appending the referenced + * character to the attribute value + * - an entity reference is processed by recursively processing the + * replacement text of the entity + * - a whitespace character (#x20, #xD, #xA, #x9) is processed by + * appending #x20 to the normalized value, except that only a single + * #x20 is appended for a "#xD#xA" sequence that is part of an external + * parsed entity or the literal entity value of an internal parsed entity + * - other characters are processed by appending them to the normalized value + * If the declared value is not CDATA, then the XML processor must further + * process the normalized attribute value by discarding any leading and + * trailing space (#x20) characters, and by replacing sequences of space + * (#x20) characters by a single space (#x20) character. + * All attributes for which no declaration has been read should be treated + * by a non-validating parser as if declared CDATA. + * + * Returns the AttValue parsed or NULL. The value has to be freed by the + * caller if it was copied, this can be detected by val[*len] == 0. */ static xmlChar * -xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { - xmlChar limit = 0; - xmlChar *buf = NULL; - xmlChar *rep = NULL; - size_t len = 0; - size_t buf_size = 0; - size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? - XML_MAX_HUGE_LENGTH : - XML_MAX_TEXT_LENGTH; - int c, l, in_space = 0; - xmlChar *current = NULL; - xmlEntityPtr ent; +xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc, + int normalize, int isNamespace) { + unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_TEXT_LENGTH; + xmlSBuf buf; + xmlChar *ret; + int c, l, quote, flags, chunkSize; + int inSpace = 1; + int replaceEntities; - if (NXT(0) == '"') { - ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; - limit = '"'; - NEXT; - } else if (NXT(0) == '\'') { - limit = '\''; - ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE; - NEXT; - } else { + /* Always expand namespace URIs */ + replaceEntities = (ctxt->replaceEntities) || (isNamespace); + + xmlSBufInit(&buf, maxLength); + + GROW; + + quote = CUR; + if ((quote != '"') && (quote != '\'')) { xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL); return(NULL); } + NEXTL(1); - /* - * allocate a translation buffer. - */ - buf_size = XML_PARSER_BUFFER_SIZE; - buf = (xmlChar *) xmlMallocAtomic(buf_size); - if (buf == NULL) goto mem_error; + if (ctxt->inSubset == 0) + flags = XML_ENT_CHECKED | XML_ENT_VALIDATED; + else + flags = XML_ENT_VALIDATED; - /* - * OK loop until we reach one of the ending char or a size limit. - */ - c = CUR_CHAR(l); - while (((NXT(0) != limit) && /* checked */ - (IS_CHAR(c)) && (c != '<')) && - (ctxt->instate != XML_PARSER_EOF)) { - if (c == '&') { - in_space = 0; - if (NXT(1) == '#') { - int val = xmlParseCharRef(ctxt); - - if (val == '&') { - if (ctxt->replaceEntities) { - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - buf[len++] = '&'; - } else { - /* - * The reparsing will be done in xmlStringGetNodeList() - * called by the attribute() function in SAX.c - */ - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - buf[len++] = '&'; - buf[len++] = '#'; - buf[len++] = '3'; - buf[len++] = '8'; - buf[len++] = ';'; - } - } else if (val != 0) { - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - len += xmlCopyChar(0, &buf[len], val); - } - } else { - ent = xmlParseEntityRef(ctxt); - if ((ent != NULL) && - (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - if ((ctxt->replaceEntities == 0) && - (ent->content[0] == '&')) { - buf[len++] = '&'; - buf[len++] = '#'; - buf[len++] = '3'; - buf[len++] = '8'; - buf[len++] = ';'; - } else { - buf[len++] = ent->content[0]; - } - } else if ((ent != NULL) && - (ctxt->replaceEntities != 0)) { - if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) { - if (xmlParserEntityCheck(ctxt, ent->length)) - goto error; + inSpace = 1; + chunkSize = 0; - ++ctxt->depth; - rep = xmlStringDecodeEntitiesInt(ctxt, ent->content, - ent->length, XML_SUBSTITUTE_REF, 0, 0, 0, - /* check */ 1); - --ctxt->depth; - if (rep != NULL) { - current = rep; - while (*current != 0) { /* non input consuming */ - if ((*current == 0xD) || (*current == 0xA) || - (*current == 0x9)) { - buf[len++] = 0x20; - current++; - } else - buf[len++] = *current++; - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - } - xmlFree(rep); - rep = NULL; - } - } else { - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - if (ent->content != NULL) - buf[len++] = ent->content[0]; - } - } else if (ent != NULL) { - int i = xmlStrlen(ent->name); - const xmlChar *cur = ent->name; + while (1) { + if (PARSER_STOPPED(ctxt)) + goto error; - /* - * We also check for recursion and amplification - * when entities are not substituted. They're - * often expanded later. - */ - if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && - (ent->content != NULL)) { - if ((ent->flags & XML_ENT_CHECKED) == 0) { - unsigned long oldCopy = ctxt->sizeentcopy; - - ctxt->sizeentcopy = ent->length; - - ++ctxt->depth; - rep = xmlStringDecodeEntitiesInt(ctxt, - ent->content, ent->length, - XML_SUBSTITUTE_REF, 0, 0, 0, - /* check */ 1); - --ctxt->depth; - - /* - * If we're parsing DTD content, the entity - * might reference other entities which - * weren't defined yet, so the check isn't - * reliable. - */ - if (ctxt->inSubset == 0) { - ent->flags |= XML_ENT_CHECKED; - ent->expandedSize = ctxt->sizeentcopy; - } + if (CUR_PTR >= ctxt->input->end) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue: ' expected\n"); + goto error; + } - if (rep != NULL) { - xmlFree(rep); - rep = NULL; - } else { - ent->content[0] = 0; - } + /* + * TODO: Check growth threshold + */ + if (ctxt->input->end - CUR_PTR < 10) + GROW; - if (xmlParserEntityCheck(ctxt, oldCopy)) - goto error; - } else { - if (xmlParserEntityCheck(ctxt, ent->expandedSize)) - goto error; - } - } + c = CUR; - /* - * Just output the reference - */ - buf[len++] = '&'; - while (len + i + 10 > buf_size) { - growBuffer(buf, i + 10); - } - for (;i > 0;i--) - buf[len++] = *cur++; - buf[len++] = ';'; - } - } - } else { - if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) { - if ((len != 0) || (!normalize)) { - if ((!normalize) || (!in_space)) { - COPY_BUF(buf, len, 0x20); - while (len + 10 > buf_size) { - growBuffer(buf, 10); - } - } - in_space = 1; - } - } else { - in_space = 0; - COPY_BUF(buf, len, c); - if (len + 10 > buf_size) { - growBuffer(buf, 10); - } - } - NEXTL(l); + if (c >= 0x80) { + l = xmlUTF8MultibyteLen(ctxt, CUR_PTR, + "invalid character in attribute value\n"); + if (l == 0) { + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + xmlSBufAddReplChar(&buf); + NEXTL(1); + } else { + chunkSize += l; + NEXTL(l); + } + + inSpace = 0; + } else if (c != '&') { + if (c > 0x20) { + if (c == quote) + break; + + if (c == '<') + xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL); + + chunkSize += 1; + inSpace = 0; + } else if (!IS_BYTE_CHAR(c)) { + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, + "invalid character in attribute value\n"); + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + xmlSBufAddReplChar(&buf); + inSpace = 0; + } else { + /* Whitespace */ + if ((normalize) && (inSpace)) { + /* Skip char */ + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + } else if (c < 0x20) { + /* Convert to space */ + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + + xmlSBufAddCString(&buf, " ", 1); + } else { + chunkSize += 1; + } + + inSpace = 1; + + if ((c == 0xD) && (NXT(1) == 0xA)) + CUR_PTR++; + } + + NEXTL(1); + } else if (NXT(1) == '#') { + int val; + + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + + val = xmlParseCharRef(ctxt); + if (val == 0) + goto error; + + if ((val == '&') && (!replaceEntities)) { + /* + * The reparsing will be done in xmlStringGetNodeList() + * called by the attribute() function in SAX.c + */ + xmlSBufAddCString(&buf, "&", 5); + inSpace = 0; + } else if (val == ' ') { + if ((!normalize) || (!inSpace)) + xmlSBufAddCString(&buf, " ", 1); + inSpace = 1; + } else { + xmlSBufAddChar(&buf, val); + inSpace = 0; + } + } else { + const xmlChar *name; + xmlEntityPtr ent; + + if (chunkSize > 0) { + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + chunkSize = 0; + } + + name = xmlParseEntityRefInternal(ctxt); + if (name == NULL) { + /* + * Probably a literal '&' which wasn't escaped. + * TODO: Handle gracefully in recovery mode. + */ + continue; + } + + ent = xmlLookupGeneralEntity(ctxt, name, /* isAttr */ 1); + if (ent == NULL) + continue; + + if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) { + if ((ent->content[0] == '&') && (!replaceEntities)) + xmlSBufAddCString(&buf, "&", 5); + else + xmlSBufAddString(&buf, ent->content, ent->length); + inSpace = 0; + } else if (replaceEntities) { + xmlExpandEntityInAttValue(ctxt, &buf, ent->content, ent, + normalize, &inSpace, ctxt->inputNr, + /* check */ 1); + } else { + if ((ent->flags & flags) != flags) + xmlCheckEntityInAttValue(ctxt, ent, ctxt->inputNr); + + if (xmlParserEntityCheck(ctxt, ent->expandedSize)) { + ent->content[0] = 0; + goto error; + } + + /* + * Just output the reference + */ + xmlSBufAddCString(&buf, "&", 1); + xmlSBufAddString(&buf, ent->name, xmlStrlen(ent->name)); + xmlSBufAddCString(&buf, ";", 1); + + inSpace = 0; + } } - GROW; - c = CUR_CHAR(l); - if (len > maxLength) { - xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue length too long\n"); - goto mem_error; - } } - if (ctxt->instate == XML_PARSER_EOF) - goto error; - if ((in_space) && (normalize)) { - while ((len > 0) && (buf[len - 1] == 0x20)) len--; - } - buf[len] = 0; - if (RAW == '<') { - xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL); - } else if (RAW != limit) { - if ((c != 0) && (!IS_CHAR(c))) { - xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, - "invalid character in attribute value\n"); - } else { - xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue: ' expected\n"); + if ((buf.mem == NULL) && (alloc != NULL)) { + ret = (xmlChar *) CUR_PTR - chunkSize; + + if (attlen != NULL) + *attlen = chunkSize; + if ((normalize) && (inSpace) && (chunkSize > 0)) + *attlen -= 1; + *alloc = 0; + + /* Report potential error */ + xmlSBufCleanup(&buf, ctxt, "AttValue length too long"); + } else { + if (chunkSize > 0) + xmlSBufAddString(&buf, CUR_PTR - chunkSize, chunkSize); + + if ((normalize) && (inSpace) && (buf.size > 0)) + buf.size--; + + ret = xmlSBufFinish(&buf, attlen, ctxt, "AttValue length too long"); + + if (ret != NULL) { + if (attlen != NULL) + *attlen = buf.size; + if (alloc != NULL) + *alloc = 1; } - } else - NEXT; + } - if (attlen != NULL) *attlen = len; - return(buf); + NEXTL(1); + + return(ret); -mem_error: - xmlErrMemory(ctxt, NULL); error: - if (buf != NULL) - xmlFree(buf); - if (rep != NULL) - xmlFree(rep); + xmlSBufCleanup(&buf, ctxt, "AttValue length too long"); return(NULL); } @@ -4341,7 +4550,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { xmlChar * xmlParseAttValue(xmlParserCtxtPtr ctxt) { if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL); - return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0)); + return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0, 0)); } /** @@ -4367,7 +4576,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH; xmlChar stop; - int state = ctxt->instate; if (RAW == '"') { NEXT; @@ -4382,10 +4590,9 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } - ctxt->instate = XML_PARSER_SYSTEM_LITERAL; cur = CUR_CHAR(l); while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */ if (len + 5 >= size) { @@ -4395,8 +4602,7 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { xmlFree(buf); - xmlErrMemory(ctxt, NULL); - ctxt->instate = (xmlParserInputState) state; + xmlErrMemory(ctxt); return(NULL); } buf = tmp; @@ -4405,18 +4611,12 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); xmlFree(buf); - ctxt->instate = (xmlParserInputState) state; return(NULL); } NEXTL(l); cur = CUR_CHAR(l); } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return(NULL); - } - ctxt->instate = (xmlParserInputState) state; if (!IS_CHAR(cur)) { xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); } else { @@ -4448,7 +4648,6 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { XML_MAX_NAME_LENGTH; xmlChar cur; xmlChar stop; - xmlParserInputState oldstate = ctxt->instate; if (RAW == '"') { NEXT; @@ -4462,19 +4661,19 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { } buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return(NULL); } - ctxt->instate = XML_PARSER_PUBLIC_LITERAL; cur = CUR; - while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */ + while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop) && + (PARSER_STOPPED(ctxt) == 0)) { /* checked */ if (len + 1 >= size) { xmlChar *tmp; size *= 2; tmp = (xmlChar *) xmlRealloc(buf, size); if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); xmlFree(buf); return(NULL); } @@ -4490,16 +4689,11 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { cur = CUR; } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return(NULL); - } if (cur != stop) { xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); } else { NEXTL(1); } - ctxt->instate = oldstate; return(buf); } @@ -4630,8 +4824,7 @@ xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) { if (*in == ']') { if ((in[1] == ']') && (in[2] == '>')) { xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); - if (ctxt->instate != XML_PARSER_EOF) - ctxt->input->cur = in + 1; + ctxt->input->cur = in + 1; return; } in++; @@ -4669,8 +4862,6 @@ xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) { line = ctxt->input->line; col = ctxt->input->col; } - if (ctxt->instate == XML_PARSER_EOF) - return; } ctxt->input->cur = in; if (*in == 0xD) { @@ -4691,8 +4882,6 @@ xmlParseCharDataInternal(xmlParserCtxtPtr ctxt, int partial) { } SHRINK; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return; in = ctxt->input->cur; } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a)); @@ -4749,15 +4938,10 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) { } } nbchar = 0; - /* something really bad happened in the SAX callback */ - if (ctxt->instate != XML_PARSER_CONTENT) - return; SHRINK; } cur = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return; if (nbchar != 0) { buf[nbchar] = 0; /* @@ -4779,9 +4963,8 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) { /* * cur == 0 can mean * - * - XML_PARSER_EOF or memory error. This is checked above. - * - An actual 0 character. * - End of buffer. + * - An actual 0 character. * - An incomplete UTF-8 sequence. This is allowed if partial is set. */ if (ctxt->input->cur < ctxt->input->end) { @@ -4910,16 +5093,13 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? XML_MAX_HUGE_LENGTH : XML_MAX_TEXT_LENGTH; - int inputid; - - inputid = ctxt->input->id; if (buf == NULL) { len = 0; size = XML_PARSER_BUFFER_SIZE; buf = (xmlChar *) xmlMallocAtomic(size); if (buf == NULL) { - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return; } } @@ -4962,7 +5142,7 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, new_buf = (xmlChar *) xmlRealloc(buf, new_size); if (new_buf == NULL) { xmlFree (buf); - xmlErrMemory(ctxt, NULL); + xmlErrMemory(ctxt); return; } buf = new_buf; @@ -4986,10 +5166,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return; - } if (cur == 0) { xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, "Comment not terminated \n", 3))) goto done; xmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; break; } @@ -11874,8 +11283,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { else xmlParseEndTag1(ctxt, 0); #endif /* LIBXML_SAX1_ENABLED */ - if (ctxt->instate == XML_PARSER_EOF) - goto done; if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; } else { @@ -11927,8 +11334,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->characters(ctxt->userData, ctxt->input->cur, tmp); } - if (ctxt->instate == XML_PARSER_EOF) - goto done; SKIPL(tmp); } else { int base = term - CUR_PTR; @@ -11962,8 +11367,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->characters(ctxt->userData, ctxt->input->cur, base); } - if (ctxt->instate == XML_PARSER_EOF) - goto done; SKIPL(base + 3); ctxt->instate = XML_PARSER_CONTENT; } @@ -11985,8 +11388,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { (!xmlParseLookupString(ctxt, 2, "?>", 2))) goto done; xmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; break; } else if (next == '!') { if ((!terminate) && (avail < 3)) @@ -12000,8 +11401,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { (!xmlParseLookupString(ctxt, 4, "-->", 3))) goto done; xmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; break; } } else if (ctxt->instate == XML_PARSER_MISC) { @@ -12018,8 +11417,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { goto done; ctxt->inSubset = 1; xmlParseDocTypeDecl(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; if (RAW == '[') { ctxt->instate = XML_PARSER_DTD; } else { @@ -12037,8 +11434,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->extSubURI); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } break; @@ -12051,8 +11446,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { if (ctxt->errNo == XML_ERR_OK) xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); ctxt->instate = XML_PARSER_EOF; - if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) - ctxt->sax->endDocument(ctxt->userData); + xmlFinishDocument(ctxt); } else { ctxt->instate = XML_PARSER_START_TAG; } @@ -12061,8 +11455,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt))) goto done; xmlParseInternalSubset(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->inSubset = 2; if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && (ctxt->sax->externalSubset != NULL)) @@ -12070,13 +11462,11 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; break; } default: - xmlGenericError(xmlGenericErrorContext, + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "PP: internal error\n"); ctxt->instate = XML_PARSER_EOF; break; @@ -12085,19 +11475,10 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { done: return(ret); encoding_error: - if (ctxt->input->end - ctxt->input->cur < 4) { - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n", - NULL, NULL); - } else { - char buffer[150]; - - snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); + /* Only report the first error */ + if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { + xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL); + ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; } return(0); } @@ -12105,31 +11486,42 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { /** * xmlParseChunk: * @ctxt: an XML parser context - * @chunk: an char array - * @size: the size in byte of the chunk + * @chunk: chunk of memory + * @size: size of chunk in bytes * @terminate: last chunk indicator * - * Parse a Chunk of memory + * Parse a chunk of memory in push parser mode. + * + * Assumes that the parser context was initialized with + * xmlCreatePushParserCtxt. + * + * The last chunk, which will often be empty, must be marked with + * the @terminate flag. With the default SAX callbacks, the resulting + * document will be available in ctxt->myDoc. This pointer will not + * be freed by the library. * - * Returns zero if no error, the xmlParserErrors otherwise. + * If the document isn't well-formed, ctxt->myDoc is set to NULL. + * The push parser doesn't support recovery mode. + * + * Returns an xmlParserErrors code (0 on success). */ int xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, int terminate) { + size_t curBase; + size_t maxLength; int end_in_lf = 0; - if (ctxt == NULL) - return(XML_ERR_INTERNAL_ERROR); - if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) + if ((ctxt == NULL) || (size < 0)) + return(XML_ERR_ARGUMENT); + if (ctxt->disableSAX != 0) return(ctxt->errNo); - if (ctxt->instate == XML_PARSER_EOF) - return(-1); if (ctxt->input == NULL) - return(-1); + return(XML_ERR_INTERNAL_ERROR); - ctxt->progressive = 1; + ctxt->input->flags |= XML_INPUT_PROGRESSIVE; if (ctxt->instate == XML_PARSER_START) - xmlDetectSAX2(ctxt); + xmlCtxtInitializeLate(ctxt); if ((size > 0) && (chunk != NULL) && (!terminate) && (chunk[size - 1] == '\r')) { end_in_lf = 1; @@ -12137,30 +11529,31 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, } if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { + (ctxt->input->buf != NULL)) { size_t pos = ctxt->input->cur - ctxt->input->base; int res; res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); return(ctxt->errNo); } } xmlParseTryOrFinish(ctxt, terminate); - if (ctxt->instate == XML_PARSER_EOF) - return(ctxt->errNo); - if ((ctxt->input != NULL) && - (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) || - ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) && - ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup"); + curBase = ctxt->input->cur - ctxt->input->base; + maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_LOOKUP_LIMIT; + if (curBase > maxLength) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, + "Buffer size limit exceeded, try XML_PARSE_HUGE\n"); xmlHaltParser(ctxt); } + if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) return(ctxt->errNo); @@ -12172,7 +11565,7 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); return(ctxt->errNo); } @@ -12197,15 +11590,15 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, } } else if ((ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL) && + (ctxt->input->buf->error == 0) && (!xmlBufIsEmpty(ctxt->input->buf->raw))) { xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, "Truncated multi-byte sequence at EOF\n"); } if (ctxt->instate != XML_PARSER_EOF) { - if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) - ctxt->sax->endDocument(ctxt->userData); + ctxt->instate = XML_PARSER_EOF; + xmlFinishDocument(ctxt); } - ctxt->instate = XML_PARSER_EOF; } if (ctxt->wellFormed == 0) return((xmlParserErrors) ctxt->errNo); @@ -12221,81 +11614,42 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, /** * xmlCreatePushParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks - * @chunk: a pointer to an array of chars - * @size: number of chars in the array - * @filename: an optional file name or URI + * @sax: a SAX handler (optional) + * @user_data: user data for SAX callbacks (optional) + * @chunk: initial chunk (optional, deprecated) + * @size: size of initial chunk in bytes + * @filename: file name or URI (optional) * * Create a parser context for using the XML parser in push mode. - * If @buffer and @size are non-NULL, the data is used to detect - * the encoding. The remaining characters will be parsed so they - * don't need to be fed in again through xmlParseChunk. - * To allow content encoding detection, @size should be >= 4 - * The value of @filename is used for fetching external entities - * and error/warning reports. + * See xmlParseChunk. * - * Returns the new parser context or NULL + * Passing an initial chunk is useless and deprecated. + * + * @filename is used as base URI to fetch external entities and for + * error reports. + * + * Returns the new parser context or NULL in case of error. */ xmlParserCtxtPtr xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; - - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) return(NULL); + xmlParserInputPtr input; ctxt = xmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlErrMemory(NULL, "creating parser: out of memory\n"); - xmlFreeParserInputBuffer(buf); + if (ctxt == NULL) return(NULL); - } + + ctxt->options &= ~XML_PARSE_NODICT; ctxt->dictNames = 1; - if (filename == NULL) { - ctxt->directory = NULL; - } else { - ctxt->directory = xmlParserGetDirectory(filename); - } - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { + input = xmlNewInputPush(ctxt, filename, chunk, size, NULL); + if (input == NULL) { xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); return(NULL); } - - if (filename == NULL) - inputStream->filename = NULL; - else { - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - if (inputStream->filename == NULL) { - xmlFreeInputStream(inputStream); - xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); - return(NULL); - } - } - inputStream->buf = buf; - xmlBufResetInput(inputStream->buf->buffer, inputStream); - inputPush(ctxt, inputStream); - - if ((size != 0) && (chunk != NULL) && - (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; - - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); - xmlHaltParser(ctxt); - } - } + inputPush(ctxt, input); return(ctxt); } @@ -12312,17 +11666,18 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; xmlHaltParser(ctxt); - ctxt->errNo = XML_ERR_USER_STOP; + if (ctxt->errNo != XML_ERR_NO_MEMORY) + ctxt->errNo = XML_ERR_USER_STOP; } /** * xmlCreateIOParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks + * @sax: a SAX handler (optional) + * @user_data: user data for SAX callbacks (optional) * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a parser context for using the XML parser with an existing * I/O stream @@ -12331,33 +11686,24 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { */ xmlParserCtxtPtr xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data, - xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, - void *ioctx, xmlCharEncoding enc) { + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, xmlCharEncoding enc) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; - - if (ioread == NULL) return(NULL); - - buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc); - if (buf == NULL) { - if (ioclose != NULL) - ioclose(ioctx); - return (NULL); - } + xmlParserInputPtr input; + const char *encoding; ctxt = xmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); + if (ctxt == NULL) return(NULL); - } - inputStream = xmlNewIOInputStream(ctxt, buf, enc); - if (inputStream == NULL) { + encoding = xmlGetCharEncodingName(enc); + input = xmlNewInputIO(ctxt, NULL, ioread, ioclose, ioctx, encoding, 0); + if (input == NULL) { xmlFreeParserCtxt(ctxt); - return(NULL); + return (NULL); } - inputPush(ctxt, inputStream); + inputPush(ctxt, input); return(ctxt); } @@ -12397,11 +11743,6 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, return(NULL); } - /* We are loading a DTD */ - ctxt->options |= XML_PARSE_DTDLOAD; - - xmlDetectSAX2(ctxt); - /* * generate a parser input from the I/O handler */ @@ -12427,18 +11768,15 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, /* * let's parse that entity knowing it's an external subset. */ - ctxt->inSubset = 2; ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); if (ctxt->myDoc == NULL) { - xmlErrMemory(ctxt, "New Doc failed"); + xmlErrMemory(ctxt); return(NULL); } ctxt->myDoc->properties = XML_DOC_INTERNAL; ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", BAD_CAST "none", BAD_CAST "none"); - xmlDetectEncoding(ctxt); - xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none"); if (ctxt->myDoc != NULL) { @@ -12494,9 +11832,6 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, return(NULL); } - /* We are loading a DTD */ - ctxt->options |= XML_PARSE_DTDLOAD; - /* * Canonicalise the system ID */ @@ -12540,16 +11875,20 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, /* * let's parse that entity knowing it's an external subset. */ - ctxt->inSubset = 2; ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0"); if (ctxt->myDoc == NULL) { - xmlErrMemory(ctxt, "New Doc failed"); + xmlErrMemory(ctxt); xmlFreeParserCtxt(ctxt); return(NULL); } ctxt->myDoc->properties = XML_DOC_INTERNAL; ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", ExternalID, SystemID); + if (ctxt->myDoc->extSubset == NULL) { + xmlFreeDoc(ctxt->myDoc); + xmlFreeParserCtxt(ctxt); + return(NULL); + } xmlParseExternalSubset(ctxt, ExternalID, SystemID); if (ctxt->myDoc != NULL) { @@ -12600,258 +11939,246 @@ xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) { * * ************************************************************************/ -/** - * xmlParseCtxtExternalEntity: - * @ctx: the existing parsing context - * @URL: the URL for the entity to load - * @ID: the System ID for the entity to load - * @lst: the return value for the set of parsed nodes - * - * Parse an external general entity within an existing parsing context - * An external general parsed entity is well-formed if it matches the - * production labeled extParsedEnt. - * - * [78] extParsedEnt ::= TextDecl? content - * - * Returns 0 if the entity is well formed, -1 in case of args problem and - * the parser error code otherwise - */ +static xmlNodePtr +xmlCtxtParseContent(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, + int hasTextDecl, int buildTree) { + xmlNodePtr root = NULL; + xmlNodePtr list = NULL; + xmlChar *rootName = BAD_CAST "#root"; + int result; -int -xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL, - const xmlChar *ID, xmlNodePtr *lst) { - void *userData; + if (buildTree) { + root = xmlNewDocNode(ctxt->myDoc, NULL, rootName, NULL); + if (root == NULL) { + xmlErrMemory(ctxt); + goto error; + } + } - if (ctx == NULL) return(-1); - /* - * If the user provided their own SAX callbacks, then reuse the - * userData callback field, otherwise the expected setup in a - * DOM builder is to have userData == ctxt - */ - if (ctx->userData == ctx) - userData = NULL; - else - userData = ctx->userData; - return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax, - userData, ctx->depth + 1, - URL, ID, lst); -} + if (xmlPushInput(ctxt, input) < 0) + goto error; -/** - * xmlParseExternalEntityPrivate: - * @doc: the document the chunk pertains to - * @oldctxt: the previous parser context if available - * @sax: the SAX handler block (possibly NULL) - * @user_data: The user data returned on SAX callbacks (possibly NULL) - * @depth: Used for loop detection, use 0 - * @URL: the URL for the entity to load - * @ID: the System ID for the entity to load - * @list: the return value for the set of parsed nodes - * - * Private version of xmlParseExternalEntity() - * - * Returns 0 if the entity is well formed, -1 in case of args problem and - * the parser error code otherwise - */ + nameNsPush(ctxt, rootName, NULL, NULL, 0, 0); + spacePush(ctxt, -1); -static xmlParserErrors -xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, - xmlSAXHandlerPtr sax, - void *user_data, int depth, const xmlChar *URL, - const xmlChar *ID, xmlNodePtr *list) { - xmlParserCtxtPtr ctxt; - xmlDocPtr newDoc; - xmlNodePtr newRoot; - xmlParserErrors ret = XML_ERR_OK; + if (buildTree) + nodePush(ctxt, root); - if (((depth > 40) && - ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) || - (depth > 100)) { - xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP, - "Maximum entity nesting depth exceeded"); - return(XML_ERR_ENTITY_LOOP); + if (hasTextDecl) { + xmlDetectEncoding(ctxt); + + /* + * Parse a possible text declaration first + */ + if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && + (IS_BLANK_CH(NXT(5)))) { + xmlParseTextDecl(ctxt); + /* + * An XML-1.0 document can't reference an entity not XML-1.0 + */ + if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) && + (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { + xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, + "Version mismatch between document and " + "entity\n"); + } + } } - if (list != NULL) - *list = NULL; - if ((URL == NULL) && (ID == NULL)) - return(XML_ERR_INTERNAL_ERROR); - if (doc == NULL) - return(XML_ERR_INTERNAL_ERROR); + xmlParseContentInternal(ctxt); - ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL, - oldctxt); - if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); - if (oldctxt != NULL) { - ctxt->nbErrors = oldctxt->nbErrors; - ctxt->nbWarnings = oldctxt->nbWarnings; - } - xmlDetectSAX2(ctxt); + if (ctxt->input->cur < ctxt->input->end) + xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - newDoc = xmlNewDoc(BAD_CAST "1.0"); - if (newDoc == NULL) { - xmlFreeParserCtxt(ctxt); - return(XML_ERR_INTERNAL_ERROR); - } - newDoc->properties = XML_DOC_INTERNAL; - if (doc) { - newDoc->intSubset = doc->intSubset; - newDoc->extSubset = doc->extSubset; - if (doc->dict) { - newDoc->dict = doc->dict; - xmlDictReference(newDoc->dict); - } - if (doc->URL != NULL) { - newDoc->URL = xmlStrdup(doc->URL); + if ((ctxt->wellFormed) || + ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) { + if (root != NULL) { + xmlNodePtr cur; + + /* + * Return the newly created nodeset after unlinking it from + * its pseudo parent. + */ + cur = root->children; + list = cur; + while (cur != NULL) { + cur->parent = NULL; + cur = cur->next; + } + root->children = NULL; + root->last = NULL; } } - newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); - if (newRoot == NULL) { - if (sax != NULL) - xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - xmlFreeDoc(newDoc); - return(XML_ERR_INTERNAL_ERROR); - } - xmlAddChild((xmlNodePtr) newDoc, newRoot); - nodePush(ctxt, newDoc->children); - if (doc == NULL) { - ctxt->myDoc = newDoc; - } else { - ctxt->myDoc = doc; - newRoot->doc = doc; - } - xmlDetectEncoding(ctxt); + /* + * Read the rest of the stream in case of errors. We want + * to account for the whole entity size. + */ + do { + ctxt->input->cur = ctxt->input->end; + xmlParserShrink(ctxt); + result = xmlParserGrow(ctxt); + } while (result > 0); + + if (buildTree) + nodePop(ctxt); + + namePop(ctxt); + spacePop(ctxt); + + /* xmlPopInput would free the stream */ + inputPop(ctxt); + +error: + xmlFreeNode(root); + + return(list); +} + +static void +xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) { + xmlParserInputPtr input; + xmlNodePtr list; + unsigned long consumed; + int isExternal; + int buildTree; + int oldMinNsIndex; + int oldNodelen, oldNodemem; + + isExternal = (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY); + buildTree = (ctxt->node != NULL); /* - * Parse a possible text declaration first + * Recursion check */ - if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { - xmlParseTextDecl(ctxt); - /* - * An XML-1.0 document can't reference an entity not XML-1.0 - */ - if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) && - (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { - xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, - "Version mismatch between document and entity\n"); - } + if (ent->flags & XML_ENT_EXPANDING) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + xmlHaltParser(ctxt); + goto error; } - ctxt->instate = XML_PARSER_CONTENT; - ctxt->depth = depth; - if (oldctxt != NULL) { - ctxt->_private = oldctxt->_private; - ctxt->loadsubset = oldctxt->loadsubset; - ctxt->validate = oldctxt->validate; - ctxt->valid = oldctxt->valid; - ctxt->replaceEntities = oldctxt->replaceEntities; - if (oldctxt->validate) { - ctxt->vctxt.error = oldctxt->vctxt.error; - ctxt->vctxt.warning = oldctxt->vctxt.warning; - ctxt->vctxt.userData = oldctxt->vctxt.userData; - ctxt->vctxt.flags = oldctxt->vctxt.flags; - } - ctxt->external = oldctxt->external; - if (ctxt->dict) xmlDictFree(ctxt->dict); - ctxt->dict = oldctxt->dict; - ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); - ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); - ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); - ctxt->dictNames = oldctxt->dictNames; - ctxt->attsDefault = oldctxt->attsDefault; - ctxt->attsSpecial = oldctxt->attsSpecial; - ctxt->linenumbers = oldctxt->linenumbers; - ctxt->record_info = oldctxt->record_info; - ctxt->node_seq.maximum = oldctxt->node_seq.maximum; - ctxt->node_seq.length = oldctxt->node_seq.length; - ctxt->node_seq.buffer = oldctxt->node_seq.buffer; - } else { - /* - * Doing validity checking on chunk without context - * doesn't make sense - */ - ctxt->_private = NULL; - ctxt->validate = 0; - ctxt->external = 2; - ctxt->loadsubset = 0; - } + /* + * Load entity + */ + input = xmlNewEntityInputStream(ctxt, ent); + if (input == NULL) + goto error; - xmlParseContent(ctxt); + /* + * When building a tree, we need to limit the scope of namespace + * declarations, so that entities don't reference xmlNs structs + * from the parent of a reference. + */ + oldMinNsIndex = ctxt->nsdb->minNsIndex; + if (buildTree) + ctxt->nsdb->minNsIndex = ctxt->nsNr; - if ((RAW == '<') && (NXT(1) == '/')) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } else if (RAW != 0) { - xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); - } - if (ctxt->node != newDoc->children) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } + oldNodelen = ctxt->nodelen; + oldNodemem = ctxt->nodemem; + ctxt->nodelen = 0; + ctxt->nodemem = 0; - if (!ctxt->wellFormed) { - ret = (xmlParserErrors)ctxt->errNo; - if (oldctxt != NULL) { - oldctxt->errNo = ctxt->errNo; - oldctxt->wellFormed = 0; - xmlCopyError(&ctxt->lastError, &oldctxt->lastError); - } - } else { - if (list != NULL) { - xmlNodePtr cur; + /* + * Parse content + * + * This initiates a recursive call chain: + * + * - xmlCtxtParseContent + * - xmlParseContentInternal + * - xmlParseReference + * - xmlCtxtParseEntity + * + * The nesting depth is limited by the maximum number of inputs, + * see xmlPushInput. + * + * It's possible to make this non-recursive (minNsIndex must be + * stored in the input struct) at the expense of code readability. + */ - /* - * Return the newly created nodeset after unlinking it from - * they pseudo parent. - */ - cur = newDoc->children->children; - *list = cur; - while (cur != NULL) { - cur->parent = NULL; - cur = cur->next; - } - newDoc->children->children = NULL; - } - ret = XML_ERR_OK; - } + ent->flags |= XML_ENT_EXPANDING; + + list = xmlCtxtParseContent(ctxt, input, isExternal, buildTree); + + ent->flags &= ~XML_ENT_EXPANDING; + + ctxt->nsdb->minNsIndex = oldMinNsIndex; + ctxt->nodelen = oldNodelen; + ctxt->nodemem = oldNodemem; /* - * Also record the size of the entity parsed + * Entity size accounting */ - if (ctxt->input != NULL && oldctxt != NULL) { - unsigned long consumed = ctxt->input->consumed; + consumed = input->consumed; + xmlSaturatedAddSizeT(&consumed, input->end - input->base); - xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base); + if ((ent->flags & XML_ENT_CHECKED) == 0) + xmlSaturatedAdd(&ent->expandedSize, consumed); - xmlSaturatedAdd(&oldctxt->sizeentities, consumed); - xmlSaturatedAdd(&oldctxt->sizeentities, ctxt->sizeentities); + if ((ent->flags & XML_ENT_PARSED) == 0) { + if (isExternal) + xmlSaturatedAdd(&ctxt->sizeentities, consumed); - xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed); - xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy); + ent->children = list; + + while (list != NULL) { + list->parent = (xmlNodePtr) ent; + if (list->next == NULL) + ent->last = list; + list = list->next; + } + } else { + xmlFreeNodeList(list); } - if (oldctxt != NULL) { - ctxt->dict = NULL; - ctxt->attsDefault = NULL; - ctxt->attsSpecial = NULL; - oldctxt->nbErrors = ctxt->nbErrors; - oldctxt->nbWarnings = ctxt->nbWarnings; - oldctxt->validate = ctxt->validate; - oldctxt->valid = ctxt->valid; - oldctxt->node_seq.maximum = ctxt->node_seq.maximum; - oldctxt->node_seq.length = ctxt->node_seq.length; - oldctxt->node_seq.buffer = ctxt->node_seq.buffer; - } - ctxt->node_seq.maximum = 0; - ctxt->node_seq.length = 0; - ctxt->node_seq.buffer = NULL; - xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - xmlFreeDoc(newDoc); + xmlFreeInputStream(input); + +error: + ent->flags |= XML_ENT_PARSED | XML_ENT_CHECKED; +} + +/** + * xmlParseCtxtExternalEntity: + * @ctxt: the existing parsing context + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @listOut: the return value for the set of parsed nodes + * + * Parse an external general entity within an existing parsing context + * An external general parsed entity is well-formed if it matches the + * production labeled extParsedEnt. + * + * [78] extParsedEnt ::= TextDecl? content + * + * Returns 0 if the entity is well formed, -1 in case of args problem and + * the parser error code otherwise + */ + +int +xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctxt, const xmlChar *URL, + const xmlChar *ID, xmlNodePtr *listOut) { + xmlParserInputPtr input; + xmlNodePtr list; + + if (listOut != NULL) + *listOut = NULL; + + if (ctxt == NULL) + return(XML_ERR_ARGUMENT); + + input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); + if (input == NULL) + return(ctxt->errNo); + + xmlCtxtInitializeLate(ctxt); - return(ret); + list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 1, 1); + if (listOut != NULL) + *listOut = list; + else + xmlFreeNodeList(list); + + xmlFreeInputStream(input); + return(ctxt->errNo); } #ifdef LIBXML_SAX1_ENABLED @@ -12863,7 +12190,9 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, * @depth: Used for loop detection, use 0 * @URL: the URL for the entity to load * @ID: the System ID for the entity to load - * @lst: the return value for the set of parsed nodes + * @list: the return value for the set of parsed nodes + * + * DEPRECATED: Use xmlParseCtxtExternalEntity. * * Parse an external general entity * An external general parsed entity is well-formed if it matches the @@ -12877,9 +12206,26 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, int xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, - int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) { - return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL, - ID, lst)); + int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *list) { + xmlParserCtxtPtr ctxt; + int ret; + + if (list != NULL) + *list = NULL; + + if (doc == NULL) + return(XML_ERR_ARGUMENT); + + ctxt = xmlNewSAXParserCtxt(sax, user_data); + if (ctxt == NULL) + return(XML_ERR_NO_MEMORY); + + ctxt->depth = depth; + ctxt->myDoc = doc; + ret = xmlParseCtxtExternalEntity(ctxt, URL, ID, list); + + xmlFreeParserCtxt(ctxt); + return(ret); } /** @@ -12910,229 +12256,6 @@ xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax, } #endif /* LIBXML_SAX1_ENABLED */ -/** - * xmlParseBalancedChunkMemoryInternal: - * @oldctxt: the existing parsing context - * @string: the input string in UTF8 or ISO-Latin (zero terminated) - * @user_data: the user data field for the parser context - * @lst: the return value for the set of parsed nodes - * - * - * Parse a well-balanced chunk of an XML document - * called by the parser - * The allowed sequence for the Well Balanced Chunk is the one defined by - * the content production in the XML grammar: - * - * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* - * - * Returns XML_ERR_OK if the chunk is well balanced, and the parser - * error code otherwise - * - * In case recover is set to 1, the nodelist will not be empty even if - * the parsed chunk is not well balanced. - */ -static xmlParserErrors -xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, - const xmlChar *string, void *user_data, xmlNodePtr *lst) { - xmlParserCtxtPtr ctxt; - xmlDocPtr newDoc = NULL; - xmlNodePtr newRoot; - xmlSAXHandlerPtr oldsax = NULL; - xmlNodePtr content = NULL; - xmlNodePtr last = NULL; - xmlParserErrors ret = XML_ERR_OK; - xmlHashedString hprefix, huri; - unsigned i; - - if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) || - (oldctxt->depth > 100)) { - xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP, - "Maximum entity nesting depth exceeded"); - return(XML_ERR_ENTITY_LOOP); - } - - - if (lst != NULL) - *lst = NULL; - if (string == NULL) - return(XML_ERR_INTERNAL_ERROR); - - ctxt = xmlCreateDocParserCtxt(string); - if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); - ctxt->nbErrors = oldctxt->nbErrors; - ctxt->nbWarnings = oldctxt->nbWarnings; - if (user_data != NULL) - ctxt->userData = user_data; - else - ctxt->userData = ctxt; - if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); - ctxt->dict = oldctxt->dict; - ctxt->input_id = oldctxt->input_id; - ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); - ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); - ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); - - /* - * Propagate namespaces down the entity - * - * Making entities and namespaces work correctly requires additional - * changes, see xmlParseReference. - */ - - /* Default namespace */ - hprefix.name = NULL; - hprefix.hashValue = 0; - huri.name = xmlParserNsLookupUri(oldctxt, &hprefix); - huri.hashValue = 0; - if (huri.name != NULL) - xmlParserNsPush(ctxt, NULL, &huri, NULL, 0); - - for (i = 0; i < oldctxt->nsdb->hashSize; i++) { - xmlParserNsBucket *bucket = &oldctxt->nsdb->hash[i]; - const xmlChar **ns; - xmlParserNsExtra *extra; - unsigned nsIndex; - - if ((bucket->hashValue != 0) && - (bucket->index != INT_MAX)) { - nsIndex = bucket->index; - ns = &oldctxt->nsTab[nsIndex * 2]; - extra = &oldctxt->nsdb->extra[nsIndex]; - - hprefix.name = ns[0]; - hprefix.hashValue = bucket->hashValue; - huri.name = ns[1]; - huri.hashValue = extra->uriHashValue; - /* - * Don't copy SAX data to avoid a use-after-free with XML reader. - * This matches the pre-2.12 behavior. - */ - xmlParserNsPush(ctxt, &hprefix, &huri, NULL, 0); - } - } - - oldsax = ctxt->sax; - ctxt->sax = oldctxt->sax; - xmlDetectSAX2(ctxt); - ctxt->replaceEntities = oldctxt->replaceEntities; - ctxt->options = oldctxt->options; - - ctxt->_private = oldctxt->_private; - if (oldctxt->myDoc == NULL) { - newDoc = xmlNewDoc(BAD_CAST "1.0"); - if (newDoc == NULL) { - ret = XML_ERR_INTERNAL_ERROR; - goto error; - } - newDoc->properties = XML_DOC_INTERNAL; - newDoc->dict = ctxt->dict; - xmlDictReference(newDoc->dict); - ctxt->myDoc = newDoc; - } else { - ctxt->myDoc = oldctxt->myDoc; - content = ctxt->myDoc->children; - last = ctxt->myDoc->last; - } - newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL); - if (newRoot == NULL) { - ret = XML_ERR_INTERNAL_ERROR; - goto error; - } - ctxt->myDoc->children = NULL; - ctxt->myDoc->last = NULL; - xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot); - nodePush(ctxt, ctxt->myDoc->children); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->depth = oldctxt->depth; - - ctxt->validate = 0; - ctxt->loadsubset = oldctxt->loadsubset; - if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) { - /* - * ID/IDREF registration will be done in xmlValidateElement below - */ - ctxt->loadsubset |= XML_SKIP_IDS; - } - ctxt->dictNames = oldctxt->dictNames; - ctxt->attsDefault = oldctxt->attsDefault; - ctxt->attsSpecial = oldctxt->attsSpecial; - - xmlParseContent(ctxt); - if ((RAW == '<') && (NXT(1) == '/')) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } else if (RAW != 0) { - xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); - } - if (ctxt->node != ctxt->myDoc->children) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } - - if (!ctxt->wellFormed) { - ret = (xmlParserErrors)ctxt->errNo; - oldctxt->errNo = ctxt->errNo; - oldctxt->wellFormed = 0; - xmlCopyError(&ctxt->lastError, &oldctxt->lastError); - } else { - ret = XML_ERR_OK; - } - - if ((lst != NULL) && (ret == XML_ERR_OK)) { - xmlNodePtr cur; - - /* - * Return the newly created nodeset after unlinking it from - * they pseudo parent. - */ - cur = ctxt->myDoc->children->children; - *lst = cur; - while (cur != NULL) { -#ifdef LIBXML_VALID_ENABLED - if ((oldctxt->validate) && (oldctxt->wellFormed) && - (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) && - (cur->type == XML_ELEMENT_NODE)) { - oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt, - oldctxt->myDoc, cur); - } -#endif /* LIBXML_VALID_ENABLED */ - cur->parent = NULL; - cur = cur->next; - } - ctxt->myDoc->children->children = NULL; - } - if (ctxt->myDoc != NULL) { - xmlFreeNode(ctxt->myDoc->children); - ctxt->myDoc->children = content; - ctxt->myDoc->last = last; - } - - /* - * Also record the size of the entity parsed - */ - if (ctxt->input != NULL && oldctxt != NULL) { - unsigned long consumed = ctxt->input->consumed; - - xmlSaturatedAddSizeT(&consumed, ctxt->input->cur - ctxt->input->base); - - xmlSaturatedAdd(&oldctxt->sizeentcopy, consumed); - xmlSaturatedAdd(&oldctxt->sizeentcopy, ctxt->sizeentcopy); - } - - oldctxt->nbErrors = ctxt->nbErrors; - oldctxt->nbWarnings = ctxt->nbWarnings; - -error: - ctxt->sax = oldsax; - ctxt->dict = NULL; - ctxt->attsDefault = NULL; - ctxt->attsSpecial = NULL; - xmlFreeParserCtxt(ctxt); - if (newDoc != NULL) { - xmlFreeDoc(newDoc); - } - - return(ret); -} - /** * xmlParseInNodeContext: * @node: the context node @@ -13166,7 +12289,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, * check all input parameters, grab the document */ if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0)) - return(XML_ERR_INTERNAL_ERROR); + return(XML_ERR_ARGUMENT); switch (node->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: @@ -13219,33 +12342,30 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, /* * Use input doc's dict if present, else assure XML_PARSE_NODICT is set. - * We need a dictionary for xmlDetectSAX2, so if there's no doc dict + * We need a dictionary for xmlCtxtInitializeLate, so if there's no doc dict * we must wait until the last moment to free the original one. */ if (doc->dict != NULL) { if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); ctxt->dict = doc->dict; - } else + } else { options |= XML_PARSE_NODICT; - - if (doc->encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; - - hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } else { - return(XML_ERR_UNSUPPORTED_ENCODING); - } + ctxt->dictNames = 0; } - xmlCtxtUseOptionsInternal(ctxt, options); - xmlDetectSAX2(ctxt); + if (doc->encoding != NULL) + xmlSwitchEncodingName(ctxt, (const char *) doc->encoding); + + xmlCtxtUseOptions(ctxt, options); + xmlCtxtInitializeLate(ctxt); ctxt->myDoc = doc; /* parsing in context, i.e. as within existing content */ ctxt->input_id = 2; - ctxt->instate = XML_PARSER_CONTENT; + + /* + * TODO: Use xmlCtxtParseContent + */ fake = xmlNewDocComment(node->doc, NULL); if (fake == NULL) { @@ -13289,26 +12409,18 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, __htmlParseContent(ctxt); else #endif - xmlParseContent(ctxt); + xmlParseContentInternal(ctxt); - xmlParserNsPop(ctxt, nsnr); - if ((RAW == '<') && (NXT(1) == '/')) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } else if (RAW != 0) { - xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); - } - if ((ctxt->node != NULL) && (ctxt->node != node)) { + if (ctxt->input->cur < ctxt->input->end) xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - ctxt->wellFormed = 0; - } - if (!ctxt->wellFormed) { - if (ctxt->errNo == 0) - ret = XML_ERR_INTERNAL_ERROR; - else - ret = (xmlParserErrors)ctxt->errNo; - } else { + xmlParserNsPop(ctxt, nsnr); + + if ((ctxt->wellFormed) || + ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) { ret = XML_ERR_OK; + } else { + ret = (xmlParserErrors) ctxt->errNo; } /* @@ -13355,19 +12467,18 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, * @user_data: The user data returned on SAX callbacks (possibly NULL) * @depth: Used for loop detection, use 0 * @string: the input string in UTF8 or ISO-Latin (zero terminated) - * @lst: the return value for the set of parsed nodes + * @listOut: the return value for the set of parsed nodes * @recover: return nodes even if the data is broken (use 0) * - * * Parse a well-balanced chunk of an XML document - * called by the parser + * * The allowed sequence for the Well Balanced Chunk is the one defined by * the content production in the XML grammar: * * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* * - * Returns 0 if the chunk is well balanced, -1 in case of args problem and - * the parser error code otherwise + * Returns 0 if the chunk is well balanced, or thehe parser error code + * otherwise. * * In case recover is set to 1, the nodelist will not be empty even if * the parsed chunk is not well balanced, assuming the parsing succeeded to @@ -13375,142 +12486,46 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, */ int xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, - void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst, + void *user_data, int depth, const xmlChar *string, xmlNodePtr *listOut, int recover) { xmlParserCtxtPtr ctxt; - xmlDocPtr newDoc; - xmlSAXHandlerPtr oldsax = NULL; - xmlNodePtr content, newRoot; - int ret = 0; - - if (depth > 40) { - return(XML_ERR_ENTITY_LOOP); - } + xmlParserInputPtr input; + xmlNodePtr list; + int ret; + if (listOut != NULL) + *listOut = NULL; - if (lst != NULL) - *lst = NULL; if (string == NULL) - return(-1); + return(XML_ERR_ARGUMENT); - ctxt = xmlCreateDocParserCtxt(string); - if (ctxt == NULL) return(-1); - ctxt->userData = ctxt; - if (sax != NULL) { - oldsax = ctxt->sax; - ctxt->sax = sax; - if (user_data != NULL) - ctxt->userData = user_data; - } - newDoc = xmlNewDoc(BAD_CAST "1.0"); - if (newDoc == NULL) { - xmlFreeParserCtxt(ctxt); - return(-1); - } - newDoc->properties = XML_DOC_INTERNAL; - if ((doc != NULL) && (doc->dict != NULL)) { - xmlDictFree(ctxt->dict); - ctxt->dict = doc->dict; - xmlDictReference(ctxt->dict); - ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); - ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); - ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); - ctxt->dictNames = 1; - newDoc->dict = ctxt->dict; - xmlDictReference(newDoc->dict); - } else { - xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT); - } - /* doc == NULL is only supported for historic reasons */ - if (doc != NULL) { - newDoc->intSubset = doc->intSubset; - newDoc->extSubset = doc->extSubset; - } - newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); - if (newRoot == NULL) { - if (sax != NULL) - ctxt->sax = oldsax; - xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - xmlFreeDoc(newDoc); - return(-1); - } - xmlAddChild((xmlNodePtr) newDoc, newRoot); - nodePush(ctxt, newRoot); - /* doc == NULL is only supported for historic reasons */ - if (doc == NULL) { - ctxt->myDoc = newDoc; - } else { - ctxt->myDoc = newDoc; - /* Ensure that doc has XML spec namespace */ - xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE); - newDoc->oldNs = doc->oldNs; - } - ctxt->instate = XML_PARSER_CONTENT; - ctxt->input_id = 2; - ctxt->depth = depth; + ctxt = xmlNewSAXParserCtxt(sax, user_data); + if (ctxt == NULL) + return(XML_ERR_NO_MEMORY); - /* - * Doing validity checking on chunk doesn't make sense - */ - ctxt->validate = 0; - ctxt->loadsubset = 0; - xmlDetectSAX2(ctxt); + xmlCtxtInitializeLate(ctxt); - if ( doc != NULL ){ - content = doc->children; - doc->children = NULL; - xmlParseContent(ctxt); - doc->children = content; - } - else { - xmlParseContent(ctxt); - } - if ((RAW == '<') && (NXT(1) == '/')) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); - } else if (RAW != 0) { - xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); - } - if (ctxt->node != newDoc->children) { - xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); + ctxt->depth = depth; + ctxt->myDoc = doc; + if (recover) { + ctxt->options |= XML_PARSE_RECOVER; + ctxt->recovery = 1; } - if (!ctxt->wellFormed) { - if (ctxt->errNo == 0) - ret = 1; - else - ret = ctxt->errNo; - } else { - ret = 0; - } + input = xmlNewStringInputStream(ctxt, string); + if (input == NULL) + return(ctxt->errNo); - if ((lst != NULL) && ((ret == 0) || (recover == 1))) { - xmlNodePtr cur; + list = xmlCtxtParseContent(ctxt, input, /* hasTextDecl */ 0, 1); + if (listOut != NULL) + *listOut = list; + else + xmlFreeNodeList(list); - /* - * Return the newly created nodeset after unlinking it from - * they pseudo parent. - */ - cur = newDoc->children->children; - *lst = cur; - while (cur != NULL) { - xmlSetTreeDoc(cur, doc); - cur->parent = NULL; - cur = cur->next; - } - newDoc->children->children = NULL; - } + ret = ctxt->errNo; - if (sax != NULL) - ctxt->sax = oldsax; + xmlFreeInputStream(input); xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - /* This leaks the namespace list if doc == NULL */ - newDoc->oldNs = NULL; - xmlFreeDoc(newDoc); - return(ret); } @@ -13542,117 +12557,47 @@ xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) { return(NULL); } if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = NULL; } xmlParseExtParsedEnt(ctxt); - if (ctxt->wellFormed) + if (ctxt->wellFormed) { ret = ctxt->myDoc; - else { + } else { ret = NULL; xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; - } - if (sax != NULL) - ctxt->sax = NULL; - xmlFreeParserCtxt(ctxt); - - return(ret); -} - -/** - * xmlParseEntity: - * @filename: the filename - * - * parse an XML external entity out of context and build a tree. - * - * [78] extParsedEnt ::= TextDecl? content - * - * This correspond to a "Well Balanced" chunk - * - * Returns the resulting document tree - */ - -xmlDocPtr -xmlParseEntity(const char *filename) { - return(xmlSAXParseEntity(NULL, filename)); -} -#endif /* LIBXML_SAX1_ENABLED */ - -/** - * xmlCreateEntityParserCtxtInternal: - * @URL: the entity URL - * @ID: the entity PUBLIC ID - * @base: a possible base for the target URI - * @pctx: parser context used to set options on new context - * - * Create a parser context for an external entity - * Automatic support for ZLIB/Compress compressed document is provided - * by default if found at compile-time. - * - * Returns the new parser context or NULL - */ -static xmlParserCtxtPtr -xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, - const xmlChar *URL, const xmlChar *ID, const xmlChar *base, - xmlParserCtxtPtr pctx) { - xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - char *directory = NULL; - xmlChar *uri; - - ctxt = xmlNewSAXParserCtxt(sax, userData); - if (ctxt == NULL) { - return(NULL); - } - - if (pctx != NULL) { - ctxt->options = pctx->options; - ctxt->_private = pctx->_private; - ctxt->input_id = pctx->input_id; } - /* Don't read from stdin. */ - if (xmlStrcmp(URL, BAD_CAST "-") == 0) - URL = BAD_CAST "./-"; - - uri = xmlBuildURI(URL, base); - - if (uri == NULL) { - inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - inputPush(ctxt, inputStream); - - if ((ctxt->directory == NULL) && (directory == NULL)) - directory = xmlParserGetDirectory((char *)URL); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; - } else { - inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt); - if (inputStream == NULL) { - xmlFree(uri); - xmlFreeParserCtxt(ctxt); - return(NULL); - } + xmlFreeParserCtxt(ctxt); - inputPush(ctxt, inputStream); + return(ret); +} - if ((ctxt->directory == NULL) && (directory == NULL)) - directory = xmlParserGetDirectory((char *)uri); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; - xmlFree(uri); - } - return(ctxt); +/** + * xmlParseEntity: + * @filename: the filename + * + * parse an XML external entity out of context and build a tree. + * + * [78] extParsedEnt ::= TextDecl? content + * + * This correspond to a "Well Balanced" chunk + * + * Returns the resulting document tree + */ + +xmlDocPtr +xmlParseEntity(const char *filename) { + return(xmlSAXParseEntity(NULL, filename)); } +#endif /* LIBXML_SAX1_ENABLED */ /** * xmlCreateEntityParserCtxt: @@ -13660,6 +12605,8 @@ xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, * @ID: the entity PUBLIC ID * @base: a possible base for the target URI * + * DEPRECATED: Use xmlNewInputURL. + * * Create a parser context for an external entity * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. @@ -13669,8 +12616,35 @@ xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, xmlParserCtxtPtr xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, const xmlChar *base) { - return xmlCreateEntityParserCtxtInternal(NULL, NULL, URL, ID, base, NULL); + xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlChar *uri = NULL; + + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) + return(NULL); + + if (base != NULL) { + if (xmlBuildURISafe(URL, base, &uri) < 0) + goto error; + if (uri != NULL) + URL = uri; + } + input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); + if (input == NULL) + goto error; + + if (inputPush(ctxt, input) < 0) + goto error; + + xmlFree(uri); + return(ctxt); + +error: + xmlFree(uri); + xmlFreeParserCtxt(ctxt); + return(NULL); } /************************************************************************ @@ -13684,6 +12658,8 @@ xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, * @filename: the filename or URL * @options: a combination of xmlParserOption * + * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile. + * * Create a parser context for a file or URL content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time and for file accesses @@ -13694,30 +12670,21 @@ xmlParserCtxtPtr xmlCreateURLParserCtxt(const char *filename, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - char *directory = NULL; + xmlParserInputPtr input; ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlErrMemory(NULL, "cannot allocate parser context"); + if (ctxt == NULL) return(NULL); - } - if (options) - xmlCtxtUseOptionsInternal(ctxt, options); + xmlCtxtUseOptions(ctxt, options); ctxt->linenumbers = 1; - inputStream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (inputStream == NULL) { + input = xmlLoadExternalEntity(filename, NULL, ctxt); + if (input == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); } - - inputPush(ctxt, inputStream); - if ((ctxt->directory == NULL) && (directory == NULL)) - directory = xmlParserGetDirectory(filename); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; + inputPush(ctxt, input); return(ctxt); } @@ -13726,6 +12693,8 @@ xmlCreateURLParserCtxt(const char *filename, int options) * xmlCreateFileParserCtxt: * @filename: the filename * + * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile. + * * Create a parser context for a file content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. @@ -13765,48 +12734,25 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename, int recovery, void *data) { xmlDocPtr ret; xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; - xmlInitParser(); - - ctxt = xmlCreateFileParserCtxt(filename); - if (ctxt == NULL) { + ctxt = xmlNewSAXParserCtxt(sax, NULL); + if (ctxt == NULL) return(NULL); - } - if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; - } - xmlDetectSAX2(ctxt); - if (data!=NULL) { + + if (data != NULL) ctxt->_private = data; - } - if (ctxt->directory == NULL) - ctxt->directory = xmlParserGetDirectory(filename); + if (recovery) { + ctxt->options |= XML_PARSE_RECOVER; + ctxt->recovery = 1; + } - ctxt->recovery = recovery; + input = xmlNewInputURL(ctxt, filename, NULL, NULL, 0); - xmlParseDocument(ctxt); + ret = xmlCtxtParseDocument(ctxt, input); - if ((ctxt->wellFormed) || recovery) { - ret = ctxt->myDoc; - if ((ret != NULL) && (ctxt->input->buf != NULL)) { - if (ctxt->input->buf->compressed > 0) - ret->compression = 9; - else - ret->compression = ctxt->input->buf->compressed; - } - } - else { - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; - } - if (sax != NULL) - ctxt->sax = NULL; xmlFreeParserCtxt(ctxt); - return(ret); } @@ -13910,19 +12856,11 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer, if ((ctxt == NULL) || (buffer == NULL)) return; - input = xmlNewInputStream(ctxt); - if (input == NULL) { - xmlErrMemory(NULL, "parsing new buffer: out of memory\n"); - xmlClearParserCtxt(ctxt); - return; - } - xmlClearParserCtxt(ctxt); - if (filename != NULL) - input->filename = (char *) xmlCanonicPath((const xmlChar *)filename); - input->base = buffer; - input->cur = buffer; - input->end = &buffer[xmlStrlen(buffer)]; + + input = xmlNewInputString(ctxt, filename, (const char *) buffer, NULL, 0); + if (input == NULL) + return; inputPush(ctxt, input); } @@ -13947,13 +12885,15 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) return -1; - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; - xmlDetectSAX2(ctxt); - - if (user_data != NULL) + if (sax != NULL) { + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = user_data; + } xmlParseDocument(ctxt); @@ -13965,8 +12905,6 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, else ret = -1; } - if (sax != NULL) - ctxt->sax = NULL; if (ctxt->myDoc != NULL) { xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; @@ -13988,7 +12926,8 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, * @buffer: a pointer to a char array * @size: the size of the array * - * Create a parser context for an XML in-memory document. + * Create a parser context for an XML in-memory document. The input buffer + * must not contain a terminating null byte. * * Returns the new parser context or NULL */ @@ -13996,35 +12935,21 @@ xmlParserCtxtPtr xmlCreateMemoryParserCtxt(const char *buffer, int size) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; - if (buffer == NULL) - return(NULL); - if (size <= 0) + if (size < 0) return(NULL); ctxt = xmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } @@ -14052,38 +12977,32 @@ xmlCreateMemoryParserCtxt(const char *buffer, int size) { xmlDocPtr xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer, - int size, int recovery, void *data) { + int size, int recovery, void *data) { xmlDocPtr ret; xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; - xmlInitParser(); + if (size < 0) + return(NULL); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); - if (ctxt == NULL) return(NULL); - if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; - } - xmlDetectSAX2(ctxt); - if (data!=NULL) { + ctxt = xmlNewSAXParserCtxt(sax, NULL); + if (ctxt == NULL) + return(NULL); + + if (data != NULL) ctxt->_private=data; + + if (recovery) { + ctxt->options |= XML_PARSE_RECOVER; + ctxt->recovery = 1; } - ctxt->recovery = recovery; + input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL, + XML_INPUT_BUF_STATIC); - xmlParseDocument(ctxt); + ret = xmlCtxtParseDocument(ctxt, input); - if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; - else { - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; - } - if (sax != NULL) - ctxt->sax = NULL; xmlFreeParserCtxt(ctxt); - return(ret); } @@ -14161,17 +13080,17 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, int ret = 0; xmlParserCtxtPtr ctxt; - xmlInitParser(); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); if (ctxt == NULL) return -1; - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; - xmlDetectSAX2(ctxt); - - if (user_data != NULL) + if (sax != NULL) { + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = user_data; + } xmlParseDocument(ctxt); @@ -14183,8 +13102,6 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, else ret = -1; } - if (sax != NULL) - ctxt->sax = NULL; if (ctxt->myDoc != NULL) { xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; @@ -14207,33 +13124,18 @@ xmlParserCtxtPtr xmlCreateDocParserCtxt(const xmlChar *str) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; - - if (str == NULL) - return(NULL); ctxt = xmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateString(str); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputString(ctxt, NULL, (const char *) str, NULL, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } @@ -14270,7 +13172,6 @@ xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) { ctxt->sax = sax; ctxt->userData = NULL; } - xmlDetectSAX2(ctxt); xmlParseDocument(ctxt); if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; @@ -14303,47 +13204,6 @@ xmlParseDoc(const xmlChar *cur) { } #endif /* LIBXML_SAX1_ENABLED */ -#ifdef LIBXML_LEGACY_ENABLED -/************************************************************************ - * * - * Specific function to keep track of entities references * - * and used by the XSLT debugger * - * * - ************************************************************************/ - -static xmlEntityReferenceFunc xmlEntityRefFunc = NULL; - -/** - * xmlAddEntityReference: - * @ent : A valid entity - * @firstNode : A valid first node for children of entity - * @lastNode : A valid last node of children entity - * - * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY - */ -static void -xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, - xmlNodePtr lastNode) -{ - if (xmlEntityRefFunc != NULL) { - (*xmlEntityRefFunc) (ent, firstNode, lastNode); - } -} - - -/** - * xmlSetEntityReferenceFunc: - * @func: A valid function - * - * Set the function to call call back when a xml reference has been made - */ -void -xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func) -{ - xmlEntityRefFunc = func; -} -#endif /* LIBXML_LEGACY_ENABLED */ - /************************************************************************ * * * New set (2.6.0) of simpler and more flexible APIs * @@ -14407,8 +13267,6 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) ctxt->version = NULL; DICT_FREE(ctxt->encoding); ctxt->encoding = NULL; - DICT_FREE(ctxt->directory); - ctxt->directory = NULL; DICT_FREE(ctxt->extSubURI); ctxt->extSubURI = NULL; DICT_FREE(ctxt->extSubSystem); @@ -14421,9 +13279,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) ctxt->hasExternalSubset = 0; ctxt->hasPErefs = 0; ctxt->html = 0; - ctxt->external = 0; ctxt->instate = XML_PARSER_START; - ctxt->token = 0; ctxt->wellFormed = 1; ctxt->nsWellFormed = 1; @@ -14480,208 +13336,258 @@ int xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, int size, const char *filename, const char *encoding) { - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; + xmlParserInputPtr input; if (ctxt == NULL) return(1); - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) - return(1); - - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); - return(1); - } - xmlCtxtReset(ctxt); - if (filename == NULL) { - ctxt->directory = NULL; - } else { - ctxt->directory = xmlParserGetDirectory(filename); - } - - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { - xmlFreeParserInputBuffer(buf); + input = xmlNewInputPush(ctxt, filename, chunk, size, encoding); + if (input == NULL) return(1); - } - - if (filename == NULL) - inputStream->filename = NULL; - else - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - inputStream->buf = buf; - xmlBufResetInput(buf->buffer, inputStream); + inputPush(ctxt, input); - inputPush(ctxt, inputStream); + return(0); +} - if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; +static int +xmlCtxtSetOptionsInternal(xmlParserCtxtPtr ctxt, int options, int keepMask) +{ + int allMask; - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); - xmlHaltParser(ctxt); - return(1); - } - } + if (ctxt == NULL) + return(-1); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; + /* + * XInclude options aren't handled by the parser. + * + * XML_PARSE_XINCLUDE + * XML_PARSE_NOXINCNODE + * XML_PARSE_NOBASEFIX + */ + allMask = XML_PARSE_RECOVER | + XML_PARSE_NOENT | + XML_PARSE_DTDLOAD | + XML_PARSE_DTDATTR | + XML_PARSE_DTDVALID | + XML_PARSE_NOERROR | + XML_PARSE_NOWARNING | + XML_PARSE_PEDANTIC | + XML_PARSE_NOBLANKS | +#ifdef LIBXML_SAX1_ENABLED + XML_PARSE_SAX1 | +#endif + XML_PARSE_NONET | + XML_PARSE_NODICT | + XML_PARSE_NSCLEAN | + XML_PARSE_NOCDATA | + XML_PARSE_COMPACT | + XML_PARSE_OLD10 | + XML_PARSE_HUGE | + XML_PARSE_OLDSAX | + XML_PARSE_IGNORE_ENC | + XML_PARSE_BIG_LINES | + XML_PARSE_NO_XXE; + + ctxt->options = (ctxt->options & keepMask) | (options & allMask); + + /* + * For some options, struct members are historically the source + * of truth. The values are initalized from global variables and + * old code could also modify them directly. Several older API + * functions that don't take an options argument rely on these + * deprecated mechanisms. + * + * Once public access to struct members and the globals are + * disabled, we can use the options bitmask as source of + * truth, making all these struct members obsolete. + * + * The XML_DETECT_IDS flags is misnamed. It simply enables + * loading of the external subset. + */ + ctxt->recovery = (options & XML_PARSE_RECOVER) ? 1 : 0; + ctxt->replaceEntities = (options & XML_PARSE_NOENT) ? 1 : 0; + ctxt->loadsubset = (options & XML_PARSE_DTDLOAD) ? XML_DETECT_IDS : 0; + ctxt->loadsubset |= (options & XML_PARSE_DTDATTR) ? XML_COMPLETE_ATTRS : 0; + ctxt->validate = (options & XML_PARSE_DTDVALID) ? 1 : 0; + ctxt->pedantic = (options & XML_PARSE_PEDANTIC) ? 1 : 0; + ctxt->keepBlanks = (options & XML_PARSE_NOBLANKS) ? 0 : 1; + ctxt->dictNames = (options & XML_PARSE_NODICT) ? 0 : 1; - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } else { - xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding %s\n", BAD_CAST encoding); - } + /* + * Changing SAX callbacks is a bad idea. This should be fixed. + */ + if (options & XML_PARSE_NOBLANKS) { + ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace; + } + if (options & XML_PARSE_NOCDATA) { + ctxt->sax->cdataBlock = NULL; + } + if (options & XML_PARSE_HUGE) { + if (ctxt->dict != NULL) + xmlDictSetLimit(ctxt->dict, 0); } - return(0); -} + ctxt->linenumbers = 1; + return(options & ~allMask); +} /** - * xmlCtxtUseOptionsInternal: + * xmlCtxtSetOptions: * @ctxt: an XML parser context - * @options: a combination of xmlParserOption - * @encoding: the user provided encoding to use + * @options: a bitmask of xmlParserOption values + * + * Applies the options to the parser context. Unset options are + * cleared. + * + * Available since 2.13.0. With older versions, you can use + * xmlCtxtUseOptions. + * + * XML_PARSE_RECOVER + * + * Enable "recovery" mode which allows non-wellformed documents. + * How this mode behaves exactly is unspecified and may change + * without further notice. Use of this feature is DISCOURAGED. + * + * XML_PARSE_NOENT + * + * Despite the confusing name, this option enables substitution + * of entities. The resulting tree won't contain any entity + * reference nodes. + * + * This option also enables loading of external entities (both + * general and parameter entities) which is dangerous. If you + * process untrusted data, it's recommended to set the + * XML_PARSE_NO_XXE option to disable loading of external + * entities. + * + * XML_PARSE_DTDLOAD + * + * Enables loading of an external DTD and the loading and + * substitution of external parameter entities. Has no effect + * if XML_PARSE_NO_XXE is set. + * + * XML_PARSE_DTDATTR + * + * Adds default attributes from the DTD to the result document. + * + * Implies XML_PARSE_DTDLOAD, but loading of external content + * can be disabled with XML_PARSE_NO_XXE. + * + * XML_PARSE_DTDVALID + * + * This option enables DTD validation which requires to load + * external DTDs and external entities (both general and + * parameter entities) unless XML_PARSE_NO_XXE was set. + * + * XML_PARSE_NO_XXE + * + * Disables loading of external DTDs or entities. + * + * XML_PARSE_NOERROR + * + * Disable error and warning reports to the error handlers. + * Errors are still accessible with xmlCtxtGetLastError. + * + * XML_PARSE_NOWARNING + * + * Disable warning reports. + * + * XML_PARSE_PEDANTIC + * + * Enable some pedantic warnings. + * + * XML_PARSE_NOBLANKS + * + * Remove some text nodes containing only whitespace from the + * result document. Which nodes are removed depends on DTD + * element declarations or a conservative heuristic. The + * reindenting feature of the serialization code relies on this + * option to be set when parsing. Use of this option is + * DISCOURAGED. + * + * XML_PARSE_SAX1 + * + * Always invoke the deprecated SAX1 startElement and endElement + * handlers. This option is DEPRECATED. + * + * XML_PARSE_NONET + * + * Disable network access with the builtin HTTP and FTP clients. + * + * XML_PARSE_NODICT + * + * Create a document without interned strings, making all + * strings separate memory allocations. + * + * XML_PARSE_NSCLEAN + * + * Remove redundant namespace declarations from the result + * document. + * + * XML_PARSE_NOCDATA + * + * Output normal text nodes instead of CDATA nodes. + * + * XML_PARSE_COMPACT * - * Applies the options to the parser context + * Store small strings directly in the node struct to save + * memory. + * + * XML_PARSE_OLD10 + * + * Use old Name productions from before XML 1.0 Fifth Edition. + * This options is DEPRECATED. + * + * XML_PARSE_HUGE + * + * Relax some internal limits. + * + * Maximum size of text nodes, tags, comments, processing instructions, + * CDATA sections, entity values + * + * normal: 10M + * huge: 1B + * + * Maximum size of names, system literals, pubid literals + * + * normal: 50K + * huge: 10M + * + * Maximum nesting depth of elements + * + * normal: 256 + * huge: 2048 + * + * Maximum nesting depth of entities + * + * normal: 20 + * huge: 40 + * + * XML_PARSE_OLDSAX + * + * Enable an unspecified legacy mode for SAX parsers. This + * option is DEPRECATED. + * + * XML_PARSE_IGNORE_ENC + * + * Ignore the encoding in the XML declaration. This option is + * mostly unneeded these days. The only effect is to enforce + * UTF-8 decoding of ASCII-like data. + * + * XML_PARSE_BIG_LINES + * + * Enable reporting of line numbers larger than 65535. * * Returns 0 in case of success, the set of unknown or unimplemented options * in case of error. */ -static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options) +int +xmlCtxtSetOptions(xmlParserCtxtPtr ctxt, int options) { - if (ctxt == NULL) - return(-1); - if (options & XML_PARSE_RECOVER) { - ctxt->recovery = 1; - options -= XML_PARSE_RECOVER; - ctxt->options |= XML_PARSE_RECOVER; - } else - ctxt->recovery = 0; - if (options & XML_PARSE_DTDLOAD) { - ctxt->loadsubset = XML_DETECT_IDS; - options -= XML_PARSE_DTDLOAD; - ctxt->options |= XML_PARSE_DTDLOAD; - } else - ctxt->loadsubset = 0; - if (options & XML_PARSE_DTDATTR) { - ctxt->loadsubset |= XML_COMPLETE_ATTRS; - options -= XML_PARSE_DTDATTR; - ctxt->options |= XML_PARSE_DTDATTR; - } - if (options & XML_PARSE_NOENT) { - ctxt->replaceEntities = 1; - /* ctxt->loadsubset |= XML_DETECT_IDS; */ - options -= XML_PARSE_NOENT; - ctxt->options |= XML_PARSE_NOENT; - } else - ctxt->replaceEntities = 0; - if (options & XML_PARSE_PEDANTIC) { - ctxt->pedantic = 1; - options -= XML_PARSE_PEDANTIC; - ctxt->options |= XML_PARSE_PEDANTIC; - } else - ctxt->pedantic = 0; - if (options & XML_PARSE_NOBLANKS) { - ctxt->keepBlanks = 0; - ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace; - options -= XML_PARSE_NOBLANKS; - ctxt->options |= XML_PARSE_NOBLANKS; - } else - ctxt->keepBlanks = 1; - if (options & XML_PARSE_DTDVALID) { - ctxt->validate = 1; - if (options & XML_PARSE_NOWARNING) - ctxt->vctxt.warning = NULL; - if (options & XML_PARSE_NOERROR) - ctxt->vctxt.error = NULL; - options -= XML_PARSE_DTDVALID; - ctxt->options |= XML_PARSE_DTDVALID; - } else - ctxt->validate = 0; - if (options & XML_PARSE_NOWARNING) { - ctxt->sax->warning = NULL; - options -= XML_PARSE_NOWARNING; - } - if (options & XML_PARSE_NOERROR) { - ctxt->sax->error = NULL; - ctxt->sax->fatalError = NULL; - options -= XML_PARSE_NOERROR; - } -#ifdef LIBXML_SAX1_ENABLED - if (options & XML_PARSE_SAX1) { - ctxt->sax->startElementNs = NULL; - ctxt->sax->endElementNs = NULL; - ctxt->sax->initialized = 1; - options -= XML_PARSE_SAX1; - ctxt->options |= XML_PARSE_SAX1; - } -#endif /* LIBXML_SAX1_ENABLED */ - if (options & XML_PARSE_NODICT) { - ctxt->dictNames = 0; - options -= XML_PARSE_NODICT; - ctxt->options |= XML_PARSE_NODICT; - } else { - ctxt->dictNames = 1; - } - if (options & XML_PARSE_NOCDATA) { - ctxt->sax->cdataBlock = NULL; - options -= XML_PARSE_NOCDATA; - ctxt->options |= XML_PARSE_NOCDATA; - } - if (options & XML_PARSE_NSCLEAN) { - ctxt->options |= XML_PARSE_NSCLEAN; - options -= XML_PARSE_NSCLEAN; - } - if (options & XML_PARSE_NONET) { - ctxt->options |= XML_PARSE_NONET; - options -= XML_PARSE_NONET; - } - if (options & XML_PARSE_COMPACT) { - ctxt->options |= XML_PARSE_COMPACT; - options -= XML_PARSE_COMPACT; - } - if (options & XML_PARSE_OLD10) { - ctxt->options |= XML_PARSE_OLD10; - options -= XML_PARSE_OLD10; - } - if (options & XML_PARSE_NOBASEFIX) { - ctxt->options |= XML_PARSE_NOBASEFIX; - options -= XML_PARSE_NOBASEFIX; - } - if (options & XML_PARSE_HUGE) { - ctxt->options |= XML_PARSE_HUGE; - options -= XML_PARSE_HUGE; - if (ctxt->dict != NULL) - xmlDictSetLimit(ctxt->dict, 0); - } - if (options & XML_PARSE_OLDSAX) { - ctxt->options |= XML_PARSE_OLDSAX; - options -= XML_PARSE_OLDSAX; - } - if (options & XML_PARSE_IGNORE_ENC) { - ctxt->options |= XML_PARSE_IGNORE_ENC; - options -= XML_PARSE_IGNORE_ENC; - } - if (options & XML_PARSE_BIG_LINES) { - ctxt->options |= XML_PARSE_BIG_LINES; - options -= XML_PARSE_BIG_LINES; - } - ctxt->linenumbers = 1; - return (options); + return(xmlCtxtSetOptionsInternal(ctxt, options, 0)); } /** @@ -14689,7 +13595,22 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options) * @ctxt: an XML parser context * @options: a combination of xmlParserOption * - * Applies the options to the parser context + * DEPRECATED: Use xmlCtxtSetOptions. + * + * Applies the options to the parser context. The following options + * are never cleared and can only be enabled: + * + * XML_PARSE_NOERROR + * XML_PARSE_NOWARNING + * XML_PARSE_NONET + * XML_PARSE_NSCLEAN + * XML_PARSE_NOCDATA + * XML_PARSE_COMPACT + * XML_PARSE_OLD10 + * XML_PARSE_HUGE + * XML_PARSE_OLDSAX + * XML_PARSE_IGNORE_ENC + * XML_PARSE_BIG_LINES * * Returns 0 in case of success, the set of unknown or unimplemented options * in case of error. @@ -14697,7 +13618,24 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options) int xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options) { - return(xmlCtxtUseOptionsInternal(ctxt, options)); + int keepMask; + + /* + * For historic reasons, some options can only be enabled. + */ + keepMask = XML_PARSE_NOERROR | + XML_PARSE_NOWARNING | + XML_PARSE_NONET | + XML_PARSE_NSCLEAN | + XML_PARSE_NOCDATA | + XML_PARSE_COMPACT | + XML_PARSE_OLD10 | + XML_PARSE_HUGE | + XML_PARSE_OLDSAX | + XML_PARSE_IGNORE_ENC | + XML_PARSE_BIG_LINES; + + return(xmlCtxtSetOptionsInternal(ctxt, options, keepMask)); } /** @@ -14720,90 +13658,102 @@ xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl) } /** - * xmlDoRead: + * xmlCtxtParseDocument: * @ctxt: an XML parser context - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of xmlParserOption - * @reuse: keep the context for reuse + * @input: parser input * - * Common front-end for the xmlRead functions + * Parse an XML document and return the resulting document tree. + * Takes ownership of the input object. + * + * Available since 2.13.0. * * Returns the resulting document tree or NULL */ -static xmlDocPtr -xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding, - int options, int reuse) +xmlDocPtr +xmlCtxtParseDocument(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { - xmlDocPtr ret; + xmlDocPtr ret = NULL; - xmlCtxtUseOptionsInternal(ctxt, options); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; + if ((ctxt == NULL) || (input == NULL)) + return(NULL); - /* - * TODO: We should consider to set XML_PARSE_IGNORE_ENC if the - * caller provided an encoding. Otherwise, we might switch to - * the encoding from the XML declaration which is likely to - * break things. Also see xmlSwitchInputEncoding. - */ - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) - xmlSwitchToEncoding(ctxt, hdlr); + /* assert(ctxt->inputNr == 0); */ + while (ctxt->inputNr > 0) + xmlFreeInputStream(inputPop(ctxt)); + + if (inputPush(ctxt, input) < 0) { + xmlFreeInputStream(input); + return(NULL); } - if ((URL != NULL) && (ctxt->input != NULL) && - (ctxt->input->filename == NULL)) - ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || ctxt->recovery) + + if ((ctxt->wellFormed) || + ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) { ret = ctxt->myDoc; - else { + } else { + if (ctxt->errNo == XML_ERR_OK) + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "unknown error\n"); + ret = NULL; - if (ctxt->myDoc != NULL) { - xmlFreeDoc(ctxt->myDoc); - } + xmlFreeDoc(ctxt->myDoc); } ctxt->myDoc = NULL; - if (!reuse) { - xmlFreeParserCtxt(ctxt); - } - return (ret); + /* assert(ctxt->inputNr == 1); */ + while (ctxt->inputNr > 0) + xmlFreeInputStream(inputPop(ctxt)); + + return(ret); } /** * xmlReadDoc: * @cur: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. + * Convenience function to parse an XML document from a + * zero-terminated string. + * + * See xmlCtxtReadDoc for details. * * Returns the resulting document tree */ xmlDocPtr -xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) +xmlReadDoc(const xmlChar *cur, const char *URL, const char *encoding, + int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - if (cur == NULL) - return (NULL); - xmlInitParser(); - - ctxt = xmlCreateDocParserCtxt(cur); + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputString(ctxt, URL, (const char *) cur, encoding, + XML_INPUT_BUF_STATIC); + + doc = xmlCtxtParseDocument(ctxt, input); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadFile: * @filename: a file or URL - * @encoding: the document encoding, or NULL + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML file from the filesystem or the network. + * Convenience function to parse an XML file from the filesystem, + * the network or a global user-define resource loader. + * + * See xmlCtxtReadFile for details. * * Returns the resulting document tree */ @@ -14811,48 +13761,77 @@ xmlDocPtr xmlReadFile(const char *filename, const char *encoding, int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - xmlInitParser(); - ctxt = xmlCreateURLParserCtxt(filename, options); + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, NULL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + + doc = xmlCtxtParseDocument(ctxt, input); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadMemory: * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @url: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. + * Parse an XML in-memory document and build a tree. The input buffer must + * not contain a terminating null byte. + * + * See xmlCtxtReadMemory for details. * * Returns the resulting document tree */ xmlDocPtr -xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) +xmlReadMemory(const char *buffer, int size, const char *url, + const char *encoding, int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - xmlInitParser(); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); + if (size < 0) + return(NULL); + + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + + doc = xmlCtxtParseDocument(ctxt, input); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadFd: * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML from a file descriptor and build a tree. + * Parse an XML from a file descriptor and build a tree. + * + * See xmlCtxtReadFd for details. + * * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. * * Returns the resulting document tree */ @@ -14860,42 +13839,35 @@ xmlDocPtr xmlReadFd(int fd, const char *URL, const char *encoding, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; - - if (fd < 0) - return (NULL); - xmlInitParser(); + xmlParserInputPtr input; + xmlDocPtr doc; - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - input->closecallback = NULL; ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - xmlFreeParserCtxt(ctxt); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + if (ctxt == NULL) + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); + + doc = xmlCtxtParseDocument(ctxt, input); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadIO: * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML document from I/O functions and source and build a tree. + * Parse an XML document from I/O functions and context and build a tree. + * + * See xmlCtxtReadIO for details. * * Returns the resulting document tree */ @@ -14904,45 +13876,37 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; - - if (ioread == NULL) - return (NULL); - xmlInitParser(); + xmlParserInputPtr input; + xmlDocPtr doc; - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - if (ioclose != NULL) - ioclose(ioctx); - return (NULL); - } ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - xmlFreeParserCtxt(ctxt); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + if (ctxt == NULL) + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); + + doc = xmlCtxtParseDocument(ctxt, input); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlCtxtReadDoc: * @ctxt: an XML parser context * @str: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * Parse an XML in-memory document and build a tree. + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -14950,41 +13914,31 @@ xmlDocPtr xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; if (ctxt == NULL) - return (NULL); - if (str == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateString(str); - if (input == NULL) { - return(NULL); - } - - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } + input = xmlNewInputString(ctxt, URL, (const char *) str, encoding, + XML_INPUT_BUF_STATIC); - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + return(xmlCtxtParseDocument(ctxt, input)); } /** * xmlCtxtReadFile: * @ctxt: an XML parser context * @filename: a file or URL - * @encoding: the document encoding, or NULL + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML file from the filesystem or the network. - * This reuses the existing @ctxt parser context + * Parse an XML file from the filesystem, the network or a user-defined + * resource loader. + * + * See xmlNewInputURL and xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -14992,22 +13946,17 @@ xmlDocPtr xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options) { - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (filename == NULL) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - stream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (stream == NULL) { - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, NULL, encoding, options, 1)); + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + + return(xmlCtxtParseDocument(ctxt, input)); } /** @@ -15015,12 +13964,17 @@ xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename, * @ctxt: an XML parser context * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * Parse an XML in-memory document and build a tree. The input buffer must + * not contain a terminating null byte. + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -15028,45 +13982,37 @@ xmlDocPtr xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ctxt == NULL) - return (NULL); - if (buffer == NULL) - return (NULL); - xmlInitParser(); + if ((ctxt == NULL) || (size < 0)) + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateStatic(buffer, size, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - return(NULL); - } - - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } + input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding, + XML_INPUT_BUF_STATIC); - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + return(xmlCtxtParseDocument(ctxt, input)); } /** * xmlCtxtReadFd: * @ctxt: an XML parser context * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML from a file descriptor and build a tree. - * This reuses the existing @ctxt parser context + * Parse an XML document from a file descriptor and build a tree. + * * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -15074,29 +14020,17 @@ xmlDocPtr xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (fd < 0) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - input->closecallback = NULL; - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + return(xmlCtxtParseDocument(ctxt, input)); } /** @@ -15112,6 +14046,11 @@ xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd, * parse an XML document from I/O functions and source and build a tree. * This reuses the existing @ctxt parser context * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. + * * Returns the resulting document tree */ xmlDocPtr @@ -15120,30 +14059,16 @@ xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ioread == NULL) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - if (ioclose != NULL) - ioclose(ioctx); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); + + return(xmlCtxtParseDocument(ctxt, input)); } diff --git a/parserInternals.c b/parserInternals.c index 166397b..6a43cc8 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -35,6 +35,7 @@ #include #endif #include +#include #define CUR(ctxt) ctxt->input->cur #define END(ctxt) ctxt->input->end @@ -45,6 +46,8 @@ #include "private/io.h" #include "private/parser.h" +#define XML_MAX_ERRORS 100 + /* * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification * factor of serialized output after entity expansion. @@ -60,7 +63,6 @@ * @version: the include version number * * check the compiled lib version against the include one. - * This can warn or immediately kill the application */ void xmlCheckVersion(int version) { @@ -69,15 +71,11 @@ xmlCheckVersion(int version) { xmlInitParser(); if ((myversion / 10000) != (version / 10000)) { - xmlGenericError(xmlGenericErrorContext, - "Fatal: program compiled against libxml %d using libxml %d\n", - (version / 10000), (myversion / 10000)); fprintf(stderr, "Fatal: program compiled against libxml %d using libxml %d\n", (version / 10000), (myversion / 10000)); - } - if ((myversion / 100) < (version / 100)) { - xmlGenericError(xmlGenericErrorContext, + } else if ((myversion / 100) < (version / 100)) { + fprintf(stderr, "Warning: program compiled against libxml %d using older %d\n", (version / 100), (myversion / 100)); } @@ -92,338 +90,293 @@ xmlCheckVersion(int version) { /** - * xmlErrMemory: + * xmlCtxtSetErrorHandler: * @ctxt: an XML parser context - * @extra: extra information + * @handler: error handler + * @data: data for error handler + * + * Register a callback function that will be called on errors and + * warnings. If handler is NULL, the error handler will be deactivated. + * + * This is the recommended way to collect errors from the parser and + * takes precedence over all other error reporting mechanisms. + * These are (in order of precedence): + * + * - per-context structured handler (xmlCtxtSetErrorHandler) + * - per-context structured "serror" SAX handler + * - global structured handler (xmlSetStructuredErrorFunc) + * - per-context generic "error" and "warning" SAX handlers + * - global generic handler (xmlSetGenericErrorFunc) + * - print to stderr * - * Handle a redefinition of attribute error + * Available since 2.13.0. */ void -xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra) +xmlCtxtSetErrorHandler(xmlParserCtxtPtr ctxt, xmlStructuredErrorFunc handler, + void *data) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - } - if (extra) - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); + if (ctxt == NULL) + return; + ctxt->errorHandler = handler; + ctxt->errorCtxt = data; } /** - * __xmlErrEncoding: + * xmlCtxtErrMemory: * @ctxt: an XML parser context - * @xmlerr: the error number - * @msg: the error message - * @str1: an string info - * @str2: an string info * - * Handle an encoding error + * Handle an out-of-memory error. + * + * Available since 2.13.0. */ void -__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, - const char *msg, const xmlChar * str1, const xmlChar * str2) +xmlCtxtErrMemory(xmlParserCtxtPtr ctxt) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = xmlerr; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL, - NULL, 0, (const char *) str1, (const char *) str2, - NULL, 0, 0, msg, str1, str2); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data; + + if (ctxt == NULL) + return; + + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */ + ctxt->wellFormed = 0; + ctxt->disableSAX = 2; + + if (ctxt->errorHandler) { + schannel = ctxt->errorHandler; + data = ctxt->errorCtxt; + } else if ((ctxt->sax->initialized == XML_SAX2_MAGIC) && + (ctxt->sax->serror != NULL)) { + schannel = ctxt->sax->serror; + data = ctxt->userData; + } else { + channel = ctxt->sax->error; + data = ctxt->userData; } + + xmlRaiseMemoryError(schannel, channel, data, XML_FROM_PARSER, + &ctxt->lastError); } /** - * xmlErrInternal: - * @ctxt: an XML parser context - * @msg: the error message - * @str: error information + * xmlCtxtErrIO: + * @ctxt: parser context + * @code: xmlParserErrors code + * @uri: filename or URI (optional) * - * Handle an internal error + * If filename is empty, use the one from context input if available. + * + * Report an IO error to the parser context. + */ +void +xmlCtxtErrIO(xmlParserCtxtPtr ctxt, int code, const char *uri) +{ + const char *errstr, *msg, *str1, *str2; + xmlErrorLevel level; + + if (ctxt == NULL) + return; + + /* + * Don't report a well-formedness error if an external entity could + * not be found. We assume that inputNr is zero for the document + * entity which is somewhat fragile. + */ + if ((ctxt->inputNr > 0) && + ((code == XML_IO_ENOENT) || + (code == XML_IO_NETWORK_ATTEMPT) || + (code == XML_IO_UNKNOWN))) { + if (ctxt->validate == 0) + level = XML_ERR_WARNING; + else + level = XML_ERR_ERROR; + } else { + level = XML_ERR_FATAL; + } + + errstr = xmlErrString(code); + + if (uri == NULL) { + msg = "%s\n"; + str1 = errstr; + str2 = NULL; + } else { + msg = "failed to load \"%s\": %s\n"; + str1 = uri; + str2 = errstr; + } + + xmlCtxtErr(ctxt, NULL, XML_FROM_IO, code, level, + (const xmlChar *) uri, NULL, NULL, 0, + msg, str1, str2); +} + +/** + * xmlCtxtVErr: + * @ctxt: a parser context + * @node: the current node or NULL + * @domain: the domain for the error + * @code: the code for the error + * @level: the xmlErrorLevel for the error + * @str1: extra string info + * @str2: extra string info + * @str3: extra string info + * @int1: extra int info + * @msg: the message to display/transmit + * @ap: extra parameters for the message display + * + * Raise a parser error. */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str) +void +xmlCtxtVErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain, + xmlParserErrors code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, va_list ap) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + const char *file = NULL; + int line = 0; + int col = 0; + int res; + + if (code == XML_ERR_NO_MEMORY) { + xmlCtxtErrMemory(ctxt); + return; + } + + if (PARSER_STOPPED(ctxt)) return; - if (ctxt != NULL) - ctxt->errNo = XML_ERR_INTERNAL_ERROR; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR, - XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL, - 0, 0, msg, str); - if (ctxt != NULL) { + + if (level == XML_ERR_WARNING) { + if (ctxt->nbWarnings >= XML_MAX_ERRORS) + return; + ctxt->nbWarnings += 1; + } else { + if (ctxt->nbErrors >= XML_MAX_ERRORS) + return; + ctxt->nbErrors += 1; + } + + if (((ctxt->options & XML_PARSE_NOERROR) == 0) && + ((level != XML_ERR_WARNING) || + ((ctxt->options & XML_PARSE_NOWARNING) == 0))) { + if (ctxt->errorHandler) { + schannel = ctxt->errorHandler; + data = ctxt->errorCtxt; + } else if ((ctxt->sax->initialized == XML_SAX2_MAGIC) && + (ctxt->sax->serror != NULL)) { + schannel = ctxt->sax->serror; + data = ctxt->userData; + } else if ((domain == XML_FROM_VALID) || (domain == XML_FROM_DTD)) { + if (level == XML_ERR_WARNING) + channel = ctxt->vctxt.warning; + else + channel = ctxt->vctxt.error; + data = ctxt->vctxt.userData; + } else { + if (level == XML_ERR_WARNING) + channel = ctxt->sax->warning; + else + channel = ctxt->sax->error; + data = ctxt->userData; + } + } + + if (ctxt->input != NULL) { + xmlParserInputPtr input = ctxt->input; + + if ((input->filename == NULL) && + (ctxt->inputNr > 1)) { + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + file = input->filename; + line = input->line; + col = input->col; + } + + res = xmlVRaiseError(schannel, channel, data, ctxt, node, domain, code, + level, file, line, (const char *) str1, + (const char *) str2, (const char *) str3, int1, col, + msg, ap); + + if (res < 0) { + xmlCtxtErrMemory(ctxt); + return; + } + + if (level >= XML_ERR_ERROR) + ctxt->errNo = code; + if (level == XML_ERR_FATAL) { ctxt->wellFormed = 0; if (ctxt->recovery == 0) ctxt->disableSAX = 1; } + + return; +} + +/** + * xmlCtxtErr: + * @ctxt: a parser context + * @node: the current node or NULL + * @domain: the domain for the error + * @code: the code for the error + * @level: the xmlErrorLevel for the error + * @str1: extra string info + * @str2: extra string info + * @str3: extra string info + * @int1: extra int info + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Raise a parser error. + */ +void +xmlCtxtErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain, + xmlParserErrors code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + xmlCtxtVErr(ctxt, node, domain, code, level, + str1, str2, str3, int1, msg, ap); + va_end(ap); } /** * xmlFatalErr: * @ctxt: an XML parser context - * @error: the error number + * @code: the error number * @info: extra information string * * Handle a fatal parser error, i.e. violating Well-Formedness constraints */ void -xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) +xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors code, const char *info) { const char *errmsg; + xmlErrorLevel level; + + if (code == XML_ERR_UNSUPPORTED_ENCODING) + level = XML_ERR_WARNING; + else + level = XML_ERR_FATAL; + + errmsg = xmlErrString(code); - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - switch (error) { - case XML_ERR_INVALID_HEX_CHARREF: - errmsg = "CharRef: invalid hexadecimal value"; - break; - case XML_ERR_INVALID_DEC_CHARREF: - errmsg = "CharRef: invalid decimal value"; - break; - case XML_ERR_INVALID_CHARREF: - errmsg = "CharRef: invalid value"; - break; - case XML_ERR_INTERNAL_ERROR: - errmsg = "internal error"; - break; - case XML_ERR_PEREF_AT_EOF: - errmsg = "PEReference at end of document"; - break; - case XML_ERR_PEREF_IN_PROLOG: - errmsg = "PEReference in prolog"; - break; - case XML_ERR_PEREF_IN_EPILOG: - errmsg = "PEReference in epilog"; - break; - case XML_ERR_PEREF_NO_NAME: - errmsg = "PEReference: no name"; - break; - case XML_ERR_PEREF_SEMICOL_MISSING: - errmsg = "PEReference: expecting ';'"; - break; - case XML_ERR_ENTITY_LOOP: - errmsg = "Detected an entity reference loop"; - break; - case XML_ERR_ENTITY_NOT_STARTED: - errmsg = "EntityValue: \" or ' expected"; - break; - case XML_ERR_ENTITY_PE_INTERNAL: - errmsg = "PEReferences forbidden in internal subset"; - break; - case XML_ERR_ENTITY_NOT_FINISHED: - errmsg = "EntityValue: \" or ' expected"; - break; - case XML_ERR_ATTRIBUTE_NOT_STARTED: - errmsg = "AttValue: \" or ' expected"; - break; - case XML_ERR_LT_IN_ATTRIBUTE: - errmsg = "Unescaped '<' not allowed in attributes values"; - break; - case XML_ERR_LITERAL_NOT_STARTED: - errmsg = "SystemLiteral \" or ' expected"; - break; - case XML_ERR_LITERAL_NOT_FINISHED: - errmsg = "Unfinished System or Public ID \" or ' expected"; - break; - case XML_ERR_MISPLACED_CDATA_END: - errmsg = "Sequence ']]>' not allowed in content"; - break; - case XML_ERR_URI_REQUIRED: - errmsg = "SYSTEM or PUBLIC, the URI is missing"; - break; - case XML_ERR_PUBID_REQUIRED: - errmsg = "PUBLIC, the Public Identifier is missing"; - break; - case XML_ERR_HYPHEN_IN_COMMENT: - errmsg = "Comment must not contain '--' (double-hyphen)"; - break; - case XML_ERR_PI_NOT_STARTED: - errmsg = "xmlParsePI : no target name"; - break; - case XML_ERR_RESERVED_XML_NAME: - errmsg = "Invalid PI name"; - break; - case XML_ERR_NOTATION_NOT_STARTED: - errmsg = "NOTATION: Name expected here"; - break; - case XML_ERR_NOTATION_NOT_FINISHED: - errmsg = "'>' required to close NOTATION declaration"; - break; - case XML_ERR_VALUE_REQUIRED: - errmsg = "Entity value required"; - break; - case XML_ERR_URI_FRAGMENT: - errmsg = "Fragment not allowed"; - break; - case XML_ERR_ATTLIST_NOT_STARTED: - errmsg = "'(' required to start ATTLIST enumeration"; - break; - case XML_ERR_NMTOKEN_REQUIRED: - errmsg = "NmToken expected in ATTLIST enumeration"; - break; - case XML_ERR_ATTLIST_NOT_FINISHED: - errmsg = "')' required to finish ATTLIST enumeration"; - break; - case XML_ERR_MIXED_NOT_STARTED: - errmsg = "MixedContentDecl : '|' or ')*' expected"; - break; - case XML_ERR_PCDATA_REQUIRED: - errmsg = "MixedContentDecl : '#PCDATA' expected"; - break; - case XML_ERR_ELEMCONTENT_NOT_STARTED: - errmsg = "ContentDecl : Name or '(' expected"; - break; - case XML_ERR_ELEMCONTENT_NOT_FINISHED: - errmsg = "ContentDecl : ',' '|' or ')' expected"; - break; - case XML_ERR_PEREF_IN_INT_SUBSET: - errmsg = - "PEReference: forbidden within markup decl in internal subset"; - break; - case XML_ERR_GT_REQUIRED: - errmsg = "expected '>'"; - break; - case XML_ERR_CONDSEC_INVALID: - errmsg = "XML conditional section '[' expected"; - break; - case XML_ERR_EXT_SUBSET_NOT_FINISHED: - errmsg = "Content error in the external subset"; - break; - case XML_ERR_CONDSEC_INVALID_KEYWORD: - errmsg = - "conditional section INCLUDE or IGNORE keyword expected"; - break; - case XML_ERR_CONDSEC_NOT_FINISHED: - errmsg = "XML conditional section not closed"; - break; - case XML_ERR_XMLDECL_NOT_STARTED: - errmsg = "Text declaration '' expected"; - break; - case XML_ERR_EXT_ENTITY_STANDALONE: - errmsg = "external parsed entities cannot be standalone"; - break; - case XML_ERR_ENTITYREF_SEMICOL_MISSING: - errmsg = "EntityRef: expecting ';'"; - break; - case XML_ERR_DOCTYPE_NOT_FINISHED: - errmsg = "DOCTYPE improperly terminated"; - break; - case XML_ERR_LTSLASH_REQUIRED: - errmsg = "EndTag: 'errNo = error; if (info == NULL) { - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n", - errmsg); + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, level, + NULL, NULL, NULL, 0, "%s\n", errmsg); } else { - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n", - errmsg, info); - } - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } -} - -/** - * xmlErrEncodingInt: - * @ctxt: an XML parser context - * @error: the error number - * @msg: the error message - * @val: an integer value - * - * n encoding error - */ -static void LIBXML_ATTR_FORMAT(3,0) -xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, - const char *msg, int val) -{ - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, NULL, NULL, NULL, val, 0, msg, val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; + xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, code, level, + (const xmlChar *) info, NULL, NULL, 0, + "%s: %s\n", errmsg, info); } } @@ -461,28 +414,8 @@ void xmlHaltParser(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - while (ctxt->inputNr > 1) - xmlFreeInputStream(inputPop(ctxt)); - if (ctxt->input != NULL) { - /* - * in case there was a specific allocation deallocate before - * overriding base - */ - if (ctxt->input->free != NULL) { - ctxt->input->free((xmlChar *) ctxt->input->base); - ctxt->input->free = NULL; - } - if (ctxt->input->buf != NULL) { - xmlFreeParserInputBuffer(ctxt->input->buf); - ctxt->input->buf = NULL; - } - ctxt->input->cur = BAD_CAST""; - ctxt->input->length = 0; - ctxt->input->base = ctxt->input->cur; - ctxt->input->end = ctxt->input->cur; - } + ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */ + ctxt->disableSAX = 2; } /** @@ -511,14 +444,17 @@ int xmlParserGrow(xmlParserCtxtPtr ctxt) { xmlParserInputPtr in = ctxt->input; xmlParserInputBufferPtr buf = in->buf; - ptrdiff_t curEnd = in->end - in->cur; - ptrdiff_t curBase = in->cur - in->base; + size_t curEnd = in->end - in->cur; + size_t curBase = in->cur - in->base; + size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? + XML_MAX_HUGE_LENGTH : + XML_MAX_LOOKUP_LIMIT; int ret; if (buf == NULL) return(0); /* Don't grow push parser buffer. */ - if ((ctxt->progressive) && (ctxt->inputNr <= 1)) + if (PARSER_PROGRESSIVE(ctxt)) return(0); /* Don't grow memory buffers. */ if ((buf->encoder == NULL) && (buf->readcallback == NULL)) @@ -526,10 +462,9 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { if (buf->error != 0) return(-1); - if (((curEnd > XML_MAX_LOOKUP_LIMIT) || - (curBase > XML_MAX_LOOKUP_LIMIT)) && - ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlErrMemory(ctxt, "Huge input lookup"); + if (curBase > maxLength) { + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, + "Buffer size limit exceeded, try XML_PARSE_HUGE\n"); xmlHaltParser(ctxt); return(-1); } @@ -541,10 +476,7 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { xmlBufUpdateInput(buf->buffer, in, curBase); if (ret < 0) { - xmlFatalErr(ctxt, buf->error, NULL); - /* Buffer contents may be lost in case of memory errors. */ - if (buf->error == XML_ERR_NO_MEMORY) - xmlHaltParser(ctxt); + xmlCtxtErrIO(ctxt, buf->error, NULL); } return(ret); @@ -612,7 +544,7 @@ xmlParserShrink(xmlParserCtxtPtr ctxt) { if (buf == NULL) return; /* Don't shrink pull parser memory buffers. */ - if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && + if ((!PARSER_PROGRESSIVE(ctxt)) && (buf->encoder == NULL) && (buf->readcallback == NULL)) return; @@ -712,16 +644,14 @@ xmlNextChar(xmlParserCtxtPtr ctxt) size_t avail; int c; - if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) || - (ctxt->input == NULL)) + if ((ctxt == NULL) || (ctxt->input == NULL)) return; avail = ctxt->input->end - ctxt->input->cur; if (avail < INPUT_CHUNK) { xmlParserGrow(ctxt); - if ((ctxt->instate == XML_PARSER_EOF) || - (ctxt->input->cur >= ctxt->input->end)) + if (ctxt->input->cur >= ctxt->input->end) return; avail = ctxt->input->end - ctxt->input->cur; } @@ -788,21 +718,7 @@ xmlNextChar(xmlParserCtxtPtr ctxt) encoding_error: /* Only report the first error */ if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { - if ((ctxt == NULL) || (ctxt->input == NULL) || - (ctxt->input->end - ctxt->input->cur < 4)) { - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n", - NULL, NULL); - } else { - char buffer[150]; - - snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); - } + xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL); ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; } ctxt->input->cur++; @@ -836,15 +752,11 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { int c; if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0); - if (ctxt->instate == XML_PARSER_EOF) - return(0); avail = ctxt->input->end - ctxt->input->cur; if (avail < INPUT_CHUNK) { xmlParserGrow(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - return(0); avail = ctxt->input->end - ctxt->input->cur; } @@ -879,8 +791,8 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { * TODO: Null bytes should be handled by callers, * but this can be tricky. */ - xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x0 out of allowed range\n", c); + xmlFatalErr(ctxt, XML_ERR_INVALID_CHAR, + "Char 0x0 out of allowed range\n"); } } else { *len = 1; @@ -942,20 +854,7 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { encoding_error: /* Only report the first error */ if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { - if (ctxt->input->end - ctxt->input->cur < 4) { - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n", - NULL, NULL); - } else { - char buffer[150]; - - snprintf(&buffer[0], 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); - } + xmlCtxtErrIO(ctxt, XML_ERR_INVALID_ENCODING, NULL); ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; } *len = 1; @@ -1029,9 +928,10 @@ xmlCopyCharMultiByte(xmlChar *out, int val) { else if (val < 0x10000) { *out++= (val >> 12) | 0xE0; bits= 6;} else if (val < 0x110000) { *out++= (val >> 18) | 0xF0; bits= 12; } else { - xmlErrEncodingInt(NULL, XML_ERR_INVALID_CHAR, - "Internal error, xmlCopyCharMultiByte 0x%X out of bound\n", - val); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + fprintf(stderr, "xmlCopyCharMultiByte: codepoint out of range\n"); + abort(); +#endif return(0); } for ( ; bits >= 0; bits-= 6) @@ -1070,24 +970,30 @@ xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) { * * ************************************************************************/ -static xmlCharEncodingHandlerPtr -xmlDetectEBCDIC(xmlParserInputPtr input) { +static int +xmlDetectEBCDIC(xmlParserInputPtr input, xmlCharEncodingHandlerPtr *hout) { xmlChar out[200]; xmlCharEncodingHandlerPtr handler; int inlen, outlen, res, i; + *hout = NULL; + /* * To detect the EBCDIC code page, we convert the first 200 bytes * to EBCDIC-US and try to find the encoding declaration. */ - handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC); - if (handler == NULL) - return(NULL); + res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler); + if (res != 0) + return(res); outlen = sizeof(out) - 1; inlen = input->end - input->cur; res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen); + /* + * Return the EBCDIC handler if decoding failed. The error will + * be reported later. + */ if (res < 0) - return(handler); + goto done; out[outlen] = 0; for (i = 0; i < outlen; i++) { @@ -1119,15 +1025,25 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { break; out[i] = 0; xmlCharEncCloseFunc(handler); - return(xmlFindCharEncodingHandler((char *) out + start)); + res = xmlOpenCharEncodingHandler((char *) out + start, + /* output */ 0, &handler); + if (res != 0) + return(res); + *hout = handler; + return(0); } } +done: /* - * ICU handlers are stateful, so we have to recreate them. + * Encoding handlers are stateful, so we have to recreate them. */ xmlCharEncCloseFunc(handler); - return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC)); + res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler); + if (res != 0) + return(res); + *hout = handler; + return(0); } /** @@ -1135,10 +1051,11 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { * @ctxt: the parser context * @enc: the encoding value (number) * - * Use encoding specified by enum to decode input data. + * Use encoding specified by enum to decode input data. This overrides + * the encoding found in the XML declaration. * - * This function can be used to enforce the encoding of chunks passed - * to xmlParseChunk. + * This function can also be used to override the encoding of chunks + * passed to xmlParseChunk. * * Returns 0 in case of success, -1 otherwise */ @@ -1146,8 +1063,8 @@ int xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) { xmlCharEncodingHandlerPtr handler = NULL; - int check = 1; int ret; + int res; if ((ctxt == NULL) || (ctxt->input == NULL)) return(-1); @@ -1156,28 +1073,20 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) case XML_CHAR_ENCODING_NONE: case XML_CHAR_ENCODING_UTF8: case XML_CHAR_ENCODING_ASCII: - check = 0; + res = 0; break; case XML_CHAR_ENCODING_EBCDIC: - handler = xmlDetectEBCDIC(ctxt->input); + res = xmlDetectEBCDIC(ctxt->input, &handler); break; default: - handler = xmlGetCharEncodingHandler(enc); + res = xmlLookupCharEncodingHandler(enc, &handler); break; } - if ((check) && (handler == NULL)) { + if (res != 0) { const char *name = xmlGetCharEncodingName(enc); - __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "encoding not supported: %s\n", - BAD_CAST (name ? name : ""), NULL); - /* - * TODO: We could recover from errors in external entities - * if we didn't stop the parser. But most callers of this - * function don't check the return value. - */ - xmlStopParser(ctxt); + xmlFatalErr(ctxt, res, (name ? name : "")); return(-1); } @@ -1191,8 +1100,59 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) } /** - * xmlSwitchInputEncoding: + * xmlSwitchEncodingName: + * @ctxt: the parser context, only for error reporting + * @input: the input strea, + * @encoding: the encoding name + * + * Available since 2.13.0. + * + * Returns 0 in case of success, -1 otherwise + */ +static int +xmlSwitchInputEncodingName(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, + const char *encoding) { + xmlCharEncodingHandlerPtr handler; + int res; + + if (encoding == NULL) + return(-1); + + res = xmlOpenCharEncodingHandler(encoding, /* output */ 0, &handler); + if (res != 0) { + xmlFatalErr(ctxt, res, encoding); + return(-1); + } + + return(xmlSwitchInputEncoding(ctxt, input, handler)); +} + +/** + * xmlSwitchEncodingName: * @ctxt: the parser context + * @encoding: the encoding name + * + * Use specified encoding to decode input data. This overrides the + * encoding found in the XML declaration. + * + * This function can also be used to override the encoding of chunks + * passed to xmlParseChunk. + * + * Available since 2.13.0. + * + * Returns 0 in case of success, -1 otherwise + */ +int +xmlSwitchEncodingName(xmlParserCtxtPtr ctxt, const char *encoding) { + if (ctxt == NULL) + return(-1); + + return(xmlSwitchInputEncodingName(ctxt, ctxt->input, encoding)); +} + +/** + * xmlSwitchInputEncoding: + * @ctxt: the parser context, only for error reporting * @input: the input stream * @handler: the encoding handler * @@ -1250,8 +1210,15 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, * Is there already some content down the pipe to convert ? */ if (xmlBufIsEmpty(in->buffer) == 0) { + xmlBufPtr buf; size_t processed; + buf = xmlBufCreate(); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(-1); + } + /* * Shrink the current input buffer. * Move it as the raw buffer and create a new input buffer @@ -1260,16 +1227,15 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, xmlBufShrink(in->buffer, processed); input->consumed += processed; in->raw = in->buffer; - in->buffer = xmlBufCreate(); + in->buffer = buf; in->rawconsumed = processed; nbchars = xmlCharEncInput(in); xmlBufResetInput(in->buffer, input); - if (nbchars < 0) { - /* TODO: This could be an out of memory or an encoding error. */ - xmlErrInternal(ctxt, - "switching encoding: encoder error\n", - NULL); + if (nbchars == XML_ENC_ERR_MEMORY) { + xmlCtxtErrMemory(ctxt); + } else if (nbchars < 0) { + xmlCtxtErrIO(ctxt, in->error, NULL); xmlHaltParser(ctxt); return (-1); } @@ -1412,23 +1378,9 @@ xmlDetectEncoding(xmlParserCtxtPtr ctxt) { */ void xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) { - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = encoding; - if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) && ((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) { - xmlCharEncodingHandlerPtr handler; - - handler = xmlFindCharEncodingHandler((const char *) encoding); - if (handler == NULL) { - __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding: %s\n", - encoding, NULL); - return; - } - - xmlSwitchToEncoding(ctxt, handler); + xmlSwitchEncodingName(ctxt, (const char *) encoding); ctxt->input->flags |= XML_INPUT_USES_ENC_DECL; } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) { static const char *allowedUTF8[] = { @@ -1474,9 +1426,17 @@ xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) { "Encoding '%s' doesn't match " "auto-detected '%s'\n", encoding, BAD_CAST autoEnc); + xmlFree(encoding); + encoding = xmlStrdup(BAD_CAST autoEnc); + if (encoding == NULL) + xmlCtxtErrMemory(ctxt); } } } + + if (ctxt->encoding != NULL) + xmlFree((xmlChar *) ctxt->encoding); + ctxt->encoding = encoding; } /** @@ -1520,7 +1480,6 @@ xmlFreeInputStream(xmlParserInputPtr input) { if (input == NULL) return; if (input->filename != NULL) xmlFree((char *) input->filename); - if (input->directory != NULL) xmlFree((char *) input->directory); if (input->version != NULL) xmlFree((char *) input->version); if ((input->free != NULL) && (input->base != NULL)) input->free((xmlChar *) input->base); @@ -1543,7 +1502,7 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) { input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput)); if (input == NULL) { - xmlErrMemory(ctxt, "couldn't allocate a new input stream\n"); + xmlCtxtErrMemory(ctxt); return(NULL); } memset(input, 0, sizeof(xmlParserInput)); @@ -1557,7 +1516,7 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) { */ if (ctxt != NULL) { if (input->id >= INT_MAX) { - xmlErrMemory(ctxt, "Input ID overflow\n"); + xmlCtxtErrMemory(ctxt); return(NULL); } input->id = ctxt->input_id++; @@ -1567,43 +1526,342 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) { } /** - * xmlNewIOInputStream: - * @ctxt: an XML parser context - * @input: an I/O Input - * @enc: the charset encoding if known - * - * Create a new input stream structure encapsulating the @input into - * a stream suitable for the parser. - * - * Returns the new input stream or NULL + * xmlNewInputURL: + * @ctxt: parser context + * @url: filename or URL + * @publicId: publid ID from doctype (optional) + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input from the filesystem, the network or + * a user-defined resource loader. + * + * @url is a filename or URL. If if contains the substring "://", + * it is assumed to be a Legacy Extended IRI. Otherwise, it is + * treated as a filesystem path. + * + * @publicId is an optional XML public ID, typically from a doctype + * declaration. It is used for catalog lookups. + * + * If @encoding is specified, it will override any encodings found + * in XML declarations, text declarations, BOMs, etc. Pass NULL + * for auto-detection. + * + * The following resource loaders will be called if they were + * registered (in order of precedence): + * + * - the global external entity loader set with + * xmlSetExternalEntityLoader + * - the per-thread xmlParserInputBufferCreateFilenameFunc set with + * xmlParserInputBufferCreateFilenameDefault + * - the default loader which will return + * - the result from a matching global input callback set with + * xmlRegisterInputCallbacks + * - a HTTP resource if support is compiled in. + * - a file opened from the filesystem, with automatic detection + * of compressed files if support is compiled in. + * + * The returned input can be passed to xmlCtxtParseDocument or + * htmlCtxtParseDocument. + * + * This function should not be invoked from user-defined resource + * loaders to avoid infinite loops. + * + * Returns a new parser input. */ xmlParserInputPtr -xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, - xmlCharEncoding enc) { - xmlParserInputPtr inputStream; +xmlNewInputURL(xmlParserCtxtPtr ctxt, const char *url, const char *publicId, + const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputPtr input; - if (input == NULL) return(NULL); - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, "new input from I/O\n"); - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { + if ((ctxt == NULL) || (url == NULL)) return(NULL); - } - inputStream->filename = NULL; - inputStream->buf = input; - xmlBufResetInput(inputStream->buf->buffer, inputStream); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } + input = xmlLoadExternalEntity(url, publicId, ctxt); + if (input == NULL) + return(NULL); - return(inputStream); + if (encoding != NULL) + xmlSwitchInputEncodingName(ctxt, input, encoding); + + return(input); } /** - * xmlNewEntityInputStream: + * xmlNewInputInternal: + * @ctxt: parser context + * @buf: parser input buffer + * @filename: filename or URL + * @encoding: character encoding (optional) + * + * Internal helper function. + * + * Returns a new parser input. + */ +static xmlParserInputPtr +xmlNewInputInternal(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf, + const char *filename, const char *encoding) { + xmlParserInputPtr input; + + input = xmlNewInputStream(ctxt); + if (input == NULL) { + xmlFreeParserInputBuffer(buf); + return(NULL); + } + + input->buf = buf; + xmlBufResetInput(input->buf->buffer, input); + + if (filename != NULL) { + input->filename = xmlMemStrdup(filename); + if (input->filename == NULL) { + xmlCtxtErrMemory(ctxt); + xmlFreeInputStream(input); + return(NULL); + } + } + + if (encoding != NULL) + xmlSwitchInputEncodingName(ctxt, input, encoding); + + return(input); +} + +/** + * xmlNewInputMemory: + * @ctxt: parser context + * @url: base URL (optional) + * @mem: pointer to char array + * @size: size of array + * @encoding: character encoding (optional) + * @flags: optimization hints + * + * Creates a new parser input to read from a memory area. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * If the XML_INPUT_BUF_STATIC flag is set, the memory area must + * stay unchanged until parsing has finished. This can avoid + * temporary copies. + * + * If the XML_INPUT_BUF_ZERO_TERMINATED flag is set, the memory + * area must contain a zero byte after the buffer at position @size. + * This can avoid temporary copies. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputMemory(xmlParserCtxtPtr ctxt, const char *url, + const void *mem, size_t size, + const char *encoding, int flags) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (mem == NULL)) + return(NULL); + + buf = xmlNewInputBufferMemory(mem, size, flags, XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputString: + * @ctxt: parser context + * @url: base URL (optional) + * @str: zero-terminated string + * @encoding: character encoding (optional) + * @flags: optimization hints + * + * Creates a new parser input to read from a zero-terminated string. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * If the XML_INPUT_BUF_STATIC flag is set, the string must + * stay unchanged until parsing has finished. This can avoid + * temporary copies. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputString(xmlParserCtxtPtr ctxt, const char *url, + const char *str, const char *encoding, int flags) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (str == NULL)) + return(NULL); + + buf = xmlNewInputBufferString(str, flags); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputFd: + * @ctxt: parser context + * @url: base URL (optional) + * @fd: file descriptor + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input to read from a zero-terminated string. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * @fd is closed after parsing has finished. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputFd(xmlParserCtxtPtr ctxt, const char *url, + int fd, const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (fd < 0)) + return(NULL); + + buf = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputIO: + * @ctxt: parser context + * @url: base URL (optional) + * @ioRead: read callback + * @ioClose: close callback (optional) + * @ioCtxt: IO context + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input to read from input callbacks and + * cintext. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * @ioRead is called to read new data into a provided buffer. + * It must return the number of bytes written into the buffer + * ot a negative xmlParserErrors code on failure. + * + * @ioClose is called after parsing has finished. + * + * @ioCtxt is an opaque pointer passed to the callbacks. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputIO(xmlParserCtxtPtr ctxt, const char *url, + xmlInputReadCallback ioRead, xmlInputCloseCallback ioClose, + void *ioCtxt, + const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (ioRead == NULL)) + return(NULL); + + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + if (ioClose != NULL) + ioClose(ioCtxt); + return(NULL); + } + + buf->context = ioCtxt; + buf->readcallback = ioRead; + buf->closecallback = ioClose; + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputPush: + * @ctxt: parser context + * @url: base URL (optional) + * @chunk: pointer to char array + * @size: size of array + * @encoding: character encoding (optional) + * + * Creates a new parser input for a push parser. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url, + const char *chunk, int size, const char *encoding) { + xmlParserInputBufferPtr buf; + xmlParserInputPtr input; + + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + input = xmlNewInputInternal(ctxt, buf, url, encoding); + if (input == NULL) + return(NULL); + + input->flags |= XML_INPUT_PROGRESSIVE; + + if ((size > 0) && (chunk != NULL)) { + int res; + + res = xmlParserInputBufferPush(input->buf, size, chunk); + xmlBufResetInput(input->buf->buffer, input); + if (res < 0) { + xmlCtxtErrIO(ctxt, input->buf->error, NULL); + xmlFreeInputStream(input); + return(NULL); + } + } + + return(input); +} + +/** + * xmlNewIOInputStream: * @ctxt: an XML parser context - * @entity: an Entity pointer + * @buf: an input buffer + * @enc: the charset encoding if known + * + * Create a new input stream structure encapsulating the @input into + * a stream suitable for the parser. + * + * Returns the new input stream or NULL + */ +xmlParserInputPtr +xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf, + xmlCharEncoding enc) { + const char *encoding; + + if (buf == NULL) + return(NULL); + + encoding = xmlGetCharEncodingName(enc); + return(xmlNewInputInternal(ctxt, buf, NULL, encoding)); +} + +/** + * xmlNewEntityInputStream: + * @ctxt: an XML parser context + * @ent: an Entity pointer * * DEPRECATED: Internal function, do not use. * @@ -1612,61 +1870,27 @@ xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, * Returns the new input stream or NULL */ xmlParserInputPtr -xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { +xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) { xmlParserInputPtr input; - if (entity == NULL) { - xmlErrInternal(ctxt, "xmlNewEntityInputStream entity = NULL\n", - NULL); - return(NULL); - } - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "new input from entity: %s\n", entity->name); - if (entity->content == NULL) { - switch (entity->etype) { - case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: - xmlErrInternal(ctxt, "Cannot parse entity %s\n", - entity->name); - break; - case XML_EXTERNAL_GENERAL_PARSED_ENTITY: - case XML_EXTERNAL_PARAMETER_ENTITY: - input = xmlLoadExternalEntity((char *) entity->URI, - (char *) entity->ExternalID, ctxt); - if (input != NULL) - input->entity = entity; - return(input); - case XML_INTERNAL_GENERAL_ENTITY: - xmlErrInternal(ctxt, - "Internal entity %s without content !\n", - entity->name); - break; - case XML_INTERNAL_PARAMETER_ENTITY: - xmlErrInternal(ctxt, - "Internal parameter entity %s without content !\n", - entity->name); - break; - case XML_INTERNAL_PREDEFINED_ENTITY: - xmlErrInternal(ctxt, - "Predefined entity %s without content !\n", - entity->name); - break; - } - return(NULL); - } - input = xmlNewInputStream(ctxt); - if (input == NULL) { + if ((ctxt == NULL) || (ent == NULL)) return(NULL); + + if (ent->content != NULL) { + input = xmlNewInputString(ctxt, NULL, (const char *) ent->content, + NULL, XML_INPUT_BUF_STATIC); + } else if (ent->URI != NULL) { + input = xmlLoadExternalEntity((char *) ent->URI, + (char *) ent->ExternalID, ctxt); + } else { + return(NULL); } - if (entity->URI != NULL) - input->filename = (char *) xmlStrdup((xmlChar *) entity->URI); - input->base = entity->content; - if (entity->length == 0) - entity->length = xmlStrlen(entity->content); - input->cur = entity->content; - input->length = entity->length; - input->end = &entity->content[input->length]; - input->entity = entity; + + if (input == NULL) + return(NULL); + + input->entity = ent; + return(input); } @@ -1676,35 +1900,159 @@ xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { * @buffer: an memory buffer * * Create a new input stream based on a memory buffer. + * * Returns the new input stream */ xmlParserInputPtr xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) { - xmlParserInputPtr input; - xmlParserInputBufferPtr buf; + return(xmlNewInputString(ctxt, NULL, (const char *) buffer, NULL, 0)); +} - if (buffer == NULL) { - xmlErrInternal(ctxt, "xmlNewStringInputStream string = NULL\n", - NULL); - return(NULL); - } - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "new fixed input: %.30s\n", buffer); - buf = xmlParserInputBufferCreateString(buffer); - if (buf == NULL) { - xmlErrMemory(ctxt, NULL); - return(NULL); + +/**************************************************************** + * * + * External entities loading * + * * + ****************************************************************/ + +#ifdef LIBXML_CATALOG_ENABLED + +/** + * xmlResolveResourceFromCatalog: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * Resolves the URL and ID against the appropriate catalog. + * This function is used by xmlDefaultExternalEntityLoader and + * xmlNoNetExternalEntityLoader. + * + * Returns a new allocated URL, or NULL. + */ +static xmlChar * +xmlResolveResourceFromCatalog(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + xmlChar *resource = NULL; + xmlCatalogAllow pref; + + /* + * If the resource doesn't exists as a file, + * try to load it from the resource pointed in the catalogs + */ + pref = xmlCatalogGetDefaults(); + + if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) { + /* + * Do a local lookup + */ + if ((ctxt != NULL) && (ctxt->catalogs != NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_DOCUMENT))) { + resource = xmlCatalogLocalResolve(ctxt->catalogs, + (const xmlChar *)ID, + (const xmlChar *)URL); + } + /* + * Try a global lookup + */ + if ((resource == NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_GLOBAL))) { + resource = xmlCatalogResolve((const xmlChar *)ID, + (const xmlChar *)URL); + } + if ((resource == NULL) && (URL != NULL)) + resource = xmlStrdup((const xmlChar *) URL); + + /* + * TODO: do an URI lookup on the reference + */ + if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) { + xmlChar *tmp = NULL; + + if ((ctxt != NULL) && (ctxt->catalogs != NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_DOCUMENT))) { + tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource); + } + if ((tmp == NULL) && + ((pref == XML_CATA_ALLOW_ALL) || + (pref == XML_CATA_ALLOW_GLOBAL))) { + tmp = xmlCatalogResolveURI(resource); + } + + if (tmp != NULL) { + xmlFree(resource); + resource = tmp; + } + } } - input = xmlNewInputStream(ctxt); - if (input == NULL) { - xmlErrMemory(ctxt, "couldn't allocate a new input stream\n"); - xmlFreeParserInputBuffer(buf); - return(NULL); + + return resource; +} + +#endif + +/** + * xmlCheckHTTPInput: + * @ctxt: an XML parser context + * @ret: an XML parser input + * + * DEPRECATED: Internal function, don't use. + * + * Check an input in case it was created from an HTTP stream, in that + * case it will handle encoding and update of the base URL in case of + * redirection. It also checks for HTTP errors in which case the input + * is cleanly freed up and an appropriate error is raised in context + * + * Returns the input or NULL in case of HTTP error. + */ +xmlParserInputPtr +xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { + /* Avoid unused variable warning if features are disabled. */ + (void) ctxt; + +#ifdef LIBXML_HTTP_ENABLED + if ((ret != NULL) && (ret->buf != NULL) && + (ret->buf->readcallback == xmlIOHTTPRead) && + (ret->buf->context != NULL)) { + const char *encoding; + const char *redir; + const char *mime; + int code; + + code = xmlNanoHTTPReturnCode(ret->buf->context); + if (code >= 400) { + /* fatal error */ + if (ret->filename != NULL) + xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, ret->filename); + else + xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, ""); + xmlFreeInputStream(ret); + ret = NULL; + } else { + + mime = xmlNanoHTTPMimeType(ret->buf->context); + if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) || + (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) { + encoding = xmlNanoHTTPEncoding(ret->buf->context); + if (encoding != NULL) + xmlSwitchEncodingName(ctxt, encoding); +#if 0 + } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { +#endif + } + redir = xmlNanoHTTPRedir(ret->buf->context); + if (redir != NULL) { + if (ret->filename != NULL) + xmlFree((xmlChar *) ret->filename); + ret->filename = + (char *) xmlStrdup((const xmlChar *) redir); + } + } } - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - return(input); +#endif + return(ret); } /** @@ -1720,22 +2068,17 @@ xmlParserInputPtr xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) { xmlParserInputBufferPtr buf; xmlParserInputPtr inputStream; - char *directory = NULL; - xmlChar *URI = NULL; - - if (xmlParserDebugEntities) - xmlGenericError(xmlGenericErrorContext, - "new input from file: %s\n", filename); - if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); + const xmlChar *URI; + xmlChar *canonic; + int code; + + if ((ctxt == NULL) || (filename == NULL)) + return(NULL); + + code = xmlParserInputBufferCreateFilenameSafe(filename, + XML_CHAR_ENCODING_NONE, &buf); if (buf == NULL) { - if (filename == NULL) - __xmlLoaderErr(ctxt, - "failed to load external entity: NULL filename \n", - NULL); - else - __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", - (const char *) filename); + xmlCtxtErrIO(ctxt, code, filename); return(NULL); } @@ -1751,21 +2094,168 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) { return(NULL); if (inputStream->filename == NULL) - URI = xmlStrdup((xmlChar *) filename); + URI = (xmlChar *) filename; else - URI = xmlStrdup((xmlChar *) inputStream->filename); - directory = xmlParserGetDirectory((const char *) URI); - if (inputStream->filename != NULL) xmlFree((char *)inputStream->filename); - inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URI); - if (URI != NULL) xmlFree((char *) URI); - inputStream->directory = directory; + URI = (xmlChar *) inputStream->filename; + canonic = xmlCanonicPath(URI); + if (canonic == NULL) { + xmlCtxtErrMemory(ctxt); + xmlFreeInputStream(inputStream); + return(NULL); + } + if (inputStream->filename != NULL) + xmlFree((char *) inputStream->filename); + inputStream->filename = (char *) canonic; xmlBufResetInput(inputStream->buf->buffer, inputStream); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory); + return(inputStream); } +/** + * xmlDefaultExternalEntityLoader: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * By default we don't load external entities, yet. + * + * Returns a new allocated xmlParserInputPtr, or NULL. + */ +static xmlParserInputPtr +xmlDefaultExternalEntityLoader(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) +{ + xmlParserInputPtr ret = NULL; + xmlChar *resource = NULL; + + if (URL == NULL) + return(NULL); + + if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) { + int options = ctxt->options; + + ctxt->options -= XML_PARSE_NONET; + ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); + ctxt->options = options; + return(ret); + } +#ifdef LIBXML_CATALOG_ENABLED + resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); +#endif + + if (resource == NULL) + resource = (xmlChar *) URL; + + ret = xmlNewInputFromFile(ctxt, (const char *) resource); + if ((resource != NULL) && (resource != (xmlChar *) URL)) + xmlFree(resource); + return (ret); +} + +/** + * xmlNoNetExternalEntityLoader: + * @URL: the URL for the entity to load + * @ID: the System ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * A specific entity loader disabling network accesses, though still + * allowing local catalog accesses for resolution. + * + * Returns a new allocated xmlParserInputPtr, or NULL. + */ +xmlParserInputPtr +xmlNoNetExternalEntityLoader(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + xmlParserInputPtr input = NULL; + xmlChar *resource = NULL; + +#ifdef LIBXML_CATALOG_ENABLED + resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); +#endif + + if (resource == NULL) + resource = (xmlChar *) URL; + + if (resource != NULL) { + if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) || + (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) { + xmlCtxtErrIO(ctxt, XML_IO_NETWORK_ATTEMPT, + (const char *) resource); + /* + * Also forward the error directly to the global error + * handler, which the XML::LibXML test suite expects. + */ + __xmlIOErr(XML_FROM_IO, XML_IO_NETWORK_ATTEMPT, + (const char *) resource); + if (resource != (xmlChar *) URL) + xmlFree(resource); + return(NULL); + } + } + input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt); + if (resource != (xmlChar *) URL) + xmlFree(resource); + return(input); +} + +/* + * This global has to die eventually + */ +static xmlExternalEntityLoader +xmlCurrentExternalEntityLoader = xmlDefaultExternalEntityLoader; + +/** + * xmlSetExternalEntityLoader: + * @f: the new entity resolver function + * + * Changes the defaultexternal entity resolver function for the application + */ +void +xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { + xmlCurrentExternalEntityLoader = f; +} + +/** + * xmlGetExternalEntityLoader: + * + * Get the default external entity resolver function for the application + * + * Returns the xmlExternalEntityLoader function pointer + */ +xmlExternalEntityLoader +xmlGetExternalEntityLoader(void) { + return(xmlCurrentExternalEntityLoader); +} + +/** + * xmlLoadExternalEntity: + * @URL: the URL for the entity to load + * @ID: the Public ID for the entity to load + * @ctxt: the context in which the entity is called or NULL + * + * Returns the xmlParserInputPtr or NULL + */ +xmlParserInputPtr +xmlLoadExternalEntity(const char *URL, const char *ID, + xmlParserCtxtPtr ctxt) { + char *canonicFilename; + xmlParserInputPtr ret; + + if (URL == NULL) + return(NULL); + + canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); + if (canonicFilename == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt); + xmlFree(canonicFilename); + return(ret); +} + /************************************************************************ * * * Commodity functions to handle parser contexts * @@ -1789,27 +2279,19 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, { xmlParserInputPtr input; - if(ctxt==NULL) { - xmlErrInternal(NULL, "Got NULL parser context\n", NULL); + if (ctxt == NULL) return(-1); - } - - xmlInitParser(); if (ctxt->dict == NULL) ctxt->dict = xmlDictCreate(); - if (ctxt->dict == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); + if (ctxt->dict == NULL) return(-1); - } xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT); if (ctxt->sax == NULL) ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); - if (ctxt->sax == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); + if (ctxt->sax == NULL) return(-1); - } if (sax == NULL) { memset(ctxt->sax, 0, sizeof(xmlSAXHandler)); xmlSAXVersion(ctxt->sax, 2); @@ -1832,13 +2314,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, xmlMalloc(5 * sizeof(xmlParserInputPtr)); ctxt->inputMax = 5; } - if (ctxt->inputTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->inputTab == NULL) return(-1); - } while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ xmlFreeInputStream(input); } @@ -1851,26 +2328,15 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->hasExternalSubset = 0; ctxt->hasPErefs = 0; ctxt->html = 0; - ctxt->external = 0; ctxt->instate = XML_PARSER_START; - ctxt->token = 0; - ctxt->directory = NULL; /* Allocate the Node stack */ if (ctxt->nodeTab == NULL) { ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr)); ctxt->nodeMax = 10; } - if (ctxt->nodeTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->nodeTab == NULL) return(-1); - } ctxt->nodeNr = 0; ctxt->node = NULL; @@ -1879,19 +2345,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *)); ctxt->nameMax = 10; } - if (ctxt->nameTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; - ctxt->nameNr = 0; - ctxt->nameMax = 0; - ctxt->name = NULL; + if (ctxt->nameTab == NULL) return(-1); - } ctxt->nameNr = 0; ctxt->name = NULL; @@ -1900,22 +2355,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int)); ctxt->spaceMax = 10; } - if (ctxt->spaceTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; - ctxt->nameNr = 0; - ctxt->nameMax = 0; - ctxt->name = NULL; - ctxt->spaceNr = 0; - ctxt->spaceMax = 0; - ctxt->space = NULL; + if (ctxt->spaceTab == NULL) return(-1); - } ctxt->spaceNr = 1; ctxt->spaceMax = 10; ctxt->spaceTab[0] = -1; @@ -1924,11 +2365,23 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->wellFormed = 1; ctxt->nsWellFormed = 1; ctxt->valid = 1; + + ctxt->options = XML_PARSE_NODICT; + + /* + * Initialize some parser options from deprecated global variables. + * Note that the "modern" API taking options arguments or + * xmlCtxtSetOptions will ignore these defaults. They're only + * relevant if old API functions like xmlParseFile are used. + */ ctxt->loadsubset = xmlLoadExtDtdDefaultValue; if (ctxt->loadsubset) { ctxt->options |= XML_PARSE_DTDLOAD; } ctxt->validate = xmlDoValidityCheckingDefaultValue; + if (ctxt->validate) { + ctxt->options |= XML_PARSE_DTDVALID; + } ctxt->pedantic = xmlPedanticParserDefaultValue; if (ctxt->pedantic) { ctxt->options |= XML_PARSE_PEDANTIC; @@ -1939,23 +2392,18 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace; ctxt->options |= XML_PARSE_NOBLANKS; } + ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue; + if (ctxt->replaceEntities) { + ctxt->options |= XML_PARSE_NOENT; + } + if (xmlGetWarningsDefaultValue == 0) + ctxt->options |= XML_PARSE_NOWARNING; ctxt->vctxt.flags = XML_VCTXT_USE_PCTXT; ctxt->vctxt.userData = ctxt; ctxt->vctxt.error = xmlParserValidityError; ctxt->vctxt.warning = xmlParserValidityWarning; - if (ctxt->validate) { - if (xmlGetWarningsDefaultValue == 0) - ctxt->vctxt.warning = NULL; - else - ctxt->vctxt.warning = xmlParserValidityWarning; - ctxt->vctxt.nodeMax = 0; - ctxt->options |= XML_PARSE_DTDVALID; - } - ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue; - if (ctxt->replaceEntities) { - ctxt->options |= XML_PARSE_NOENT; - } + ctxt->record_info = 0; ctxt->checkIndex = 0; ctxt->inSubset = 0; @@ -1971,7 +2419,7 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, if (ctxt->nsdb == NULL) { ctxt->nsdb = xmlParserNsCreate(); if (ctxt->nsdb == NULL) { - xmlErrMemory(ctxt, NULL); + xmlCtxtErrMemory(ctxt); return(-1); } } @@ -2031,7 +2479,6 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt) if (ctxt->sax != NULL) #endif /* LIBXML_SAX1_ENABLED */ xmlFree(ctxt->sax); - if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory); if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab); if (ctxt->atts != NULL) xmlFree((xmlChar * *)ctxt->atts); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); @@ -2107,6 +2554,10 @@ xmlNewParserCtxt(void) * Allocate and initialize a new SAX parser context. If userData is NULL, * the parser context will be passed as user data. * + * Available since 2.11.0. If you want support older versions, + * it's best to invoke xmlNewParserCtxt and set ctxt->sax with + * struct assignment. + * * Returns the xmlParserCtxtPtr or NULL if memory allocation failed. */ @@ -2115,11 +2566,11 @@ xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData) { xmlParserCtxtPtr ctxt; + xmlInitParser(); + ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt)); - if (ctxt == NULL) { - xmlErrMemory(NULL, "cannot allocate parser context\n"); + if (ctxt == NULL) return(NULL); - } memset(ctxt, 0, sizeof(xmlParserCtxt)); if (xmlInitSAXParserCtxt(ctxt, sax, userData) < 0) { xmlFreeParserCtxt(ctxt); @@ -2163,7 +2614,7 @@ xmlClearParserCtxt(xmlParserCtxtPtr ctxt) * Returns an xmlParserNodeInfo block pointer or NULL */ const xmlParserNodeInfo * -xmlParserFindNodeInfo(const xmlParserCtxtPtr ctx, const xmlNodePtr node) +xmlParserFindNodeInfo(xmlParserCtxtPtr ctx, xmlNodePtr node) { unsigned long pos; @@ -2229,8 +2680,8 @@ xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq) * Returns a long indicating the position of the record */ unsigned long -xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq, - const xmlNodePtr node) +xmlParserFindNodeInfoIndex(xmlParserNodeInfoSeqPtr seq, + xmlNodePtr node) { unsigned long upper, lower, middle; int found = 0; @@ -2271,7 +2722,7 @@ xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq, */ void xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt, - const xmlParserNodeInfoPtr info) + xmlParserNodeInfoPtr info) { unsigned long pos; @@ -2307,7 +2758,7 @@ xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt, byte_size); if (tmp_buffer == NULL) { - xmlErrMemory(ctxt, "failed to allocate buffer\n"); + xmlCtxtErrMemory(ctxt); return; } ctxt->node_seq.buffer = tmp_buffer; diff --git a/pattern.c b/pattern.c index 55ae2d3..23b5274 100644 --- a/pattern.c +++ b/pattern.c @@ -344,9 +344,8 @@ xmlFreePatParserContext(xmlPatParserContextPtr ctxt) { * Returns -1 in case of failure, 0 otherwise. */ static int -xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED, - xmlPatternPtr comp, - xmlPatOp op, xmlChar * value, xmlChar * value2) +xmlPatternAdd(xmlPatParserContextPtr ctxt, xmlPatternPtr comp, + xmlPatOp op, xmlChar * value, xmlChar * value2) { if (comp->nbStep >= comp->maxStep) { xmlStepOpPtr temp; @@ -355,6 +354,7 @@ xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED, if (temp == NULL) { ERROR(ctxt, NULL, NULL, "xmlPatternAdd: realloc failed\n"); + ctxt->error = -1; return (-1); } comp->steps = temp; @@ -697,10 +697,6 @@ xmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) { * * ************************************************************************/ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); #define CUR (*ctxt->cur) #define SKIP(val) ctxt->cur += (val) #define NXT(val) ctxt->cur[(val)] @@ -717,14 +713,6 @@ xmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) { #define PUSH(op, val, val2) \ if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error; -#define XSLT_ERROR(X) \ - { xsltError(ctxt, __FILE__, __LINE__, X); \ - ctxt->error = (X); return; } - -#define XSLT_ERROR0(X) \ - { xsltError(ctxt, __FILE__, __LINE__, X); \ - ctxt->error = (X); return(0); } - #if 0 /** * xmlPatScanLiteral: @@ -869,6 +857,8 @@ xmlPatScanNCName(xmlPatParserContextPtr ctxt) { ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); else ret = xmlStrndup(q, cur - q); + if (ret == NULL) + ctxt->error = -1; CUR_PTR = cur; return(ret); } @@ -913,6 +903,8 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { SKIP_BLANKS; name = xmlPatScanNCName(ctxt); + if (ctxt->error < 0) + return; if (name == NULL) { if (CUR == '*') { PUSH(XML_OP_ATTR, NULL, NULL); @@ -1032,6 +1024,8 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { return; } name = xmlPatScanNCName(ctxt); + if (ctxt->error < 0) + return; if (name == NULL) { if (CUR == '*') { NEXT; @@ -1248,6 +1242,8 @@ xmlCompilePathPattern(xmlPatParserContextPtr ctxt) { if (CUR == '@') { NEXT; xmlCompileAttributeTest(ctxt); + if (ctxt->error != 0) + goto error; SKIP_BLANKS; /* TODO: check for incompleteness */ if (CUR != 0) { @@ -1788,7 +1784,7 @@ static int xmlStreamPushInternal(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns, int nodeType) { - int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc; + int ret = 0, final = 0, tmp, i, m, match, stepNr, desc; xmlStreamCompPtr comp; xmlStreamStep step; @@ -1819,10 +1815,8 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, */ ret = 1; } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) { - /* TODO: Do we need this ? */ - tmp = xmlStreamCtxtAddState(stream, 0, 0); - if (tmp < 0) - err++; + if (xmlStreamCtxtAddState(stream, 0, 0) < 0) + return(-1); } } } @@ -1977,9 +1971,9 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, final = step.flags & XML_STREAM_STEP_FINAL; if (final) { ret = 1; - } else { - xmlStreamCtxtAddState(stream, stepNr + 1, - stream->level + 1); + } else if (xmlStreamCtxtAddState(stream, stepNr + 1, + stream->level + 1) < 0) { + return(-1); } if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { /* @@ -2081,10 +2075,11 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, } final = step.flags & XML_STREAM_STEP_FINAL; if (match) { - if (final) + if (final) { ret = 1; - else - xmlStreamCtxtAddState(stream, 1, stream->level); + } else if (xmlStreamCtxtAddState(stream, 1, stream->level) < 0) { + return(-1); + } if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { /* * Check if we have a special case like "foo//.", where @@ -2106,8 +2101,6 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, stream = stream->next; } /* while stream != NULL */ - if (err > 0) - ret = -1; return(ret); } @@ -2259,28 +2252,37 @@ xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt) ************************************************************************/ /** - * xmlPatterncompile: + * xmlPatternCompileSafe: * @pattern: the pattern to compile * @dict: an optional dictionary for interned strings * @flags: compilation flags, see xmlPatternFlags * @namespaces: the prefix definitions, array of [URI, prefix] or NULL + * @patternOut: output pattern * * Compile a pattern. * - * Returns the compiled form of the pattern or NULL in case of error + * Available since 2.13.0. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -xmlPatternPtr -xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, - const xmlChar **namespaces) { +int +xmlPatternCompileSafe(const xmlChar *pattern, xmlDict *dict, int flags, + const xmlChar **namespaces, xmlPatternPtr *patternOut) { xmlPatternPtr ret = NULL, cur; xmlPatParserContextPtr ctxt = NULL; const xmlChar *or, *start; xmlChar *tmp = NULL; int type = 0; int streamable = 1; + int error; - if (pattern == NULL) - return(NULL); + if (patternOut == NULL) + return(1); + + if (pattern == NULL) { + error = 1; + goto error; + } start = pattern; or = start; @@ -2296,9 +2298,15 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, } or++; } - if (ctxt == NULL) goto error; + if (ctxt == NULL) { + error = -1; + goto error; + } cur = xmlNewPattern(); - if (cur == NULL) goto error; + if (cur == NULL) { + error = -1; + goto error; + } /* * Assign string dict. */ @@ -2319,8 +2327,10 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, xmlCompileIDCXPathPath(ctxt); else xmlCompilePathPattern(ctxt); - if (ctxt->error != 0) + if (ctxt->error != 0) { + error = ctxt->error; goto error; + } xmlFreePatParserContext(ctxt); ctxt = NULL; @@ -2336,9 +2346,13 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, streamable = 0; } } - if (streamable) - xmlStreamCompile(cur); - if (xmlReversePattern(cur) < 0) + if (streamable) { + error = xmlStreamCompile(cur); + if (error != 0) + goto error; + } + error = xmlReversePattern(cur); + if (error != 0) goto error; if (tmp != NULL) { xmlFree(tmp); @@ -2357,12 +2371,33 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, } } - return(ret); + *patternOut = ret; + return(0); error: if (ctxt != NULL) xmlFreePatParserContext(ctxt); if (ret != NULL) xmlFreePattern(ret); if (tmp != NULL) xmlFree(tmp); - return(NULL); + *patternOut = NULL; + return(error); +} + +/** + * xmlPatterncompile: + * @pattern: the pattern to compile + * @dict: an optional dictionary for interned strings + * @flags: compilation flags, see xmlPatternFlags + * @namespaces: the prefix definitions, array of [URI, prefix] or NULL + * + * Compile a pattern. + * + * Returns the compiled form of the pattern or NULL in case of error + */ +xmlPatternPtr +xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, + const xmlChar **namespaces) { + xmlPatternPtr ret; + xmlPatternCompileSafe(pattern, dict, flags, namespaces, &ret); + return(ret); } /** diff --git a/relaxng.c b/relaxng.c index d7c407d..24c3e51 100644 --- a/relaxng.c +++ b/relaxng.c @@ -53,11 +53,6 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) #define MAX_ERROR 5 -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema; typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr; @@ -415,7 +410,7 @@ struct _xmlRelaxNGDocument { * Handle a redefinition of attribute error */ static void -xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra) +xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt) { xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; @@ -429,17 +424,8 @@ xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra) data = ctxt->userData; ctxt->nbErrors++; } - if (extra) - __xmlRaiseError(schannel, channel, data, - NULL, NULL, XML_FROM_RELAXNGP, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(schannel, channel, data, - NULL, NULL, XML_FROM_RELAXNGP, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); + + xmlRaiseMemoryError(schannel, channel, data, XML_FROM_RELAXNGP, NULL); } /** @@ -450,7 +436,7 @@ xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra) * Handle a redefinition of attribute error */ static void -xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra) +xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt) { xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; @@ -464,17 +450,8 @@ xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra) data = ctxt->userData; ctxt->nbErrors++; } - if (extra) - __xmlRaiseError(schannel, channel, data, - NULL, NULL, XML_FROM_RELAXNGV, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(schannel, channel, data, - NULL, NULL, XML_FROM_RELAXNGV, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); + + xmlRaiseMemoryError(schannel, channel, data, XML_FROM_RELAXNGV, NULL); } /** @@ -495,6 +472,7 @@ xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error, xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; void *data = NULL; + int res; if (ctxt != NULL) { if (ctxt->serror != NULL) @@ -504,11 +482,18 @@ xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error, data = ctxt->userData; ctxt->nbErrors++; } - __xmlRaiseError(schannel, channel, data, - NULL, node, XML_FROM_RELAXNGP, - error, XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, str1, str2); + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + res = __xmlRaiseError(schannel, channel, data, NULL, node, + XML_FROM_RELAXNGP, error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, str1, str2); + if (res < 0) + xmlRngPErrMemory(ctxt); } /** @@ -529,6 +514,7 @@ xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error, xmlStructuredErrorFunc schannel = NULL; xmlGenericErrorFunc channel = NULL; void *data = NULL; + int res; if (ctxt != NULL) { if (ctxt->serror != NULL) @@ -538,11 +524,18 @@ xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error, data = ctxt->userData; ctxt->nbErrors++; } - __xmlRaiseError(schannel, channel, data, - NULL, node, XML_FROM_RELAXNGV, - error, XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, str1, str2); + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + res = __xmlRaiseError(schannel, channel, data, NULL, node, + XML_FROM_RELAXNGV, error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, str1, str2); + if (res < 0) + xmlRngVErrMemory(ctxt); } /************************************************************************ @@ -744,7 +737,7 @@ xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt) ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG)); if (ret == NULL) { - xmlRngPErrMemory(ctxt, NULL); + xmlRngPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNG)); @@ -823,7 +816,7 @@ xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt) ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar)); if (ret == NULL) { - xmlRngPErrMemory(ctxt, NULL); + xmlRngPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGGrammar)); @@ -879,7 +872,7 @@ xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) ctxt->defTab = (xmlRelaxNGDefinePtr *) xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr)); if (ctxt->defTab == NULL) { - xmlRngPErrMemory(ctxt, "allocating define\n"); + xmlRngPErrMemory(ctxt); return (NULL); } } else if (ctxt->defMax <= ctxt->defNr) { @@ -891,14 +884,14 @@ xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) sizeof (xmlRelaxNGDefinePtr)); if (tmp == NULL) { - xmlRngPErrMemory(ctxt, "allocating define\n"); + xmlRngPErrMemory(ctxt); return (NULL); } ctxt->defTab = tmp; } ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine)); if (ret == NULL) { - xmlRngPErrMemory(ctxt, "allocating define\n"); + xmlRngPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGDefine)); @@ -1004,7 +997,7 @@ xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size) 1) * sizeof(xmlRelaxNGValidStatePtr)); if (ret == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); return (NULL); } ret->nbState = 0; @@ -1013,7 +1006,7 @@ xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size) sizeof (xmlRelaxNGValidStatePtr)); if (ret->tabState == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); xmlFree(ret); return (NULL); } @@ -1049,7 +1042,7 @@ xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt, sizeof (xmlRelaxNGValidStatePtr)); if (tmp == NULL) { - xmlRngVErrMemory(ctxt, "adding states\n"); + xmlRngVErrMemory(ctxt); return (-1); } states->tabState = tmp; @@ -1089,7 +1082,7 @@ xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt, sizeof (xmlRelaxNGValidStatePtr)); if (tmp == NULL) { - xmlRngVErrMemory(ctxt, "adding states\n"); + xmlRngVErrMemory(ctxt); return (-1); } states->tabState = tmp; @@ -1124,7 +1117,7 @@ xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt, ctxt->freeStates = (xmlRelaxNGStatesPtr *) xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr)); if (ctxt->freeStates == NULL) { - xmlRngVErrMemory(ctxt, "storing states\n"); + xmlRngVErrMemory(ctxt); } } else if ((ctxt != NULL) && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) { @@ -1135,7 +1128,7 @@ xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt, sizeof (xmlRelaxNGStatesPtr)); if (tmp == NULL) { - xmlRngVErrMemory(ctxt, "storing states\n"); + xmlRngVErrMemory(ctxt); xmlFree(states->tabState); xmlFree(states); return; @@ -1191,7 +1184,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node) (xmlRelaxNGValidStatePtr) xmlMalloc(sizeof(xmlRelaxNGValidState)); if (ret == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGValidState)); @@ -1215,7 +1208,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node) ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs * sizeof(xmlAttrPtr)); if (ret->attrs == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); return (ret); } } else if (ret->maxAttrs < nbAttrs) { @@ -1224,7 +1217,7 @@ xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node) tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs * sizeof(xmlAttrPtr)); if (tmp == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); return (ret); } ret->attrs = tmp; @@ -1273,7 +1266,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt, (xmlRelaxNGValidStatePtr) xmlMalloc(sizeof(xmlRelaxNGValidState)); if (ret == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGValidState)); @@ -1289,7 +1282,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt, ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs * sizeof(xmlAttrPtr)); if (ret->attrs == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); ret->nbAttrs = 0; return (ret); } @@ -1299,7 +1292,7 @@ xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt, tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs * sizeof(xmlAttrPtr)); if (tmp == NULL) { - xmlRngVErrMemory(ctxt, "allocating states\n"); + xmlRngVErrMemory(ctxt); ret->nbAttrs = 0; return (ret); } @@ -1418,6 +1411,42 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags) static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc); +static xmlDoc * +xmlRelaxReadFile(xmlRelaxNGParserCtxtPtr ctxt, const char *filename) { + xmlParserCtxtPtr pctxt; + xmlDocPtr doc; + + pctxt = xmlNewParserCtxt(); + if (pctxt == NULL) { + xmlRngPErrMemory(ctxt); + return(NULL); + } + if (ctxt->serror != NULL) + xmlCtxtSetErrorHandler(pctxt, ctxt->serror, ctxt->userData); + doc = xmlCtxtReadFile(pctxt, filename, NULL, 0); + xmlFreeParserCtxt(pctxt); + + return(doc); +} + +static xmlDoc * +xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *buf, int size) { + xmlParserCtxtPtr pctxt; + xmlDocPtr doc; + + pctxt = xmlNewParserCtxt(); + if (pctxt == NULL) { + xmlRngPErrMemory(ctxt); + return(NULL); + } + if (ctxt->serror != NULL) + xmlCtxtSetErrorHandler(pctxt, ctxt->serror, ctxt->userData); + doc = xmlCtxtReadMemory(pctxt, buf, size, NULL, NULL, 0); + xmlFreeParserCtxt(pctxt); + + return(doc); +} + /** * xmlRelaxNGIncludePush: * @ctxt: the parser context @@ -1438,7 +1467,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax * sizeof(ctxt->incTab[0])); if (ctxt->incTab == NULL) { - xmlRngPErrMemory(ctxt, "allocating include\n"); + xmlRngPErrMemory(ctxt); return (0); } } @@ -1449,7 +1478,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, ctxt->incMax * sizeof(ctxt->incTab[0])); if (ctxt->incTab == NULL) { - xmlRngPErrMemory(ctxt, "allocating include\n"); + xmlRngPErrMemory(ctxt); return (0); } } @@ -1583,7 +1612,7 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, /* * load the document */ - doc = xmlReadFile((const char *) URL,NULL,0); + doc = xmlRelaxReadFile(ctxt, (const char *) URL); if (doc == NULL) { xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR, "xmlRelaxNG: could not load %s\n", URL, NULL); @@ -1595,7 +1624,7 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, */ ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude)); if (ret == NULL) { - xmlRngPErrMemory(ctxt, "allocating include\n"); + xmlRngPErrMemory(ctxt); xmlFreeDoc(doc); return (NULL); } @@ -1737,7 +1766,7 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, sizeof (xmlRelaxNGValidError)); if (ctxt->errTab == NULL) { - xmlRngVErrMemory(ctxt, "pushing error\n"); + xmlRngVErrMemory(ctxt); return (0); } ctxt->err = NULL; @@ -1750,7 +1779,7 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, sizeof (xmlRelaxNGValidError)); if (ctxt->errTab == NULL) { - xmlRngVErrMemory(ctxt, "pushing error\n"); + xmlRngVErrMemory(ctxt); return (0); } ctxt->err = &ctxt->errTab[ctxt->errNr - 1]; @@ -1832,7 +1861,7 @@ xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt, (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax * sizeof(ctxt->docTab[0])); if (ctxt->docTab == NULL) { - xmlRngPErrMemory(ctxt, "adding document\n"); + xmlRngPErrMemory(ctxt); return (0); } } @@ -1843,7 +1872,7 @@ xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt, ctxt->docMax * sizeof(ctxt->docTab[0])); if (ctxt->docTab == NULL) { - xmlRngPErrMemory(ctxt, "adding document\n"); + xmlRngPErrMemory(ctxt); return (0); } } @@ -1913,7 +1942,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, /* * load the document */ - doc = xmlReadFile((const char *) URL,NULL,0); + doc = xmlRelaxReadFile(ctxt, (const char *) URL); if (doc == NULL) { xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, "xmlRelaxNG: could not load %s\n", URL, NULL); @@ -1925,8 +1954,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, */ ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument)); if (ret == NULL) { - xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY, - "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL); + xmlRngPErrMemory(ctxt); xmlFreeDoc(doc); return (NULL); } @@ -2712,17 +2740,13 @@ xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data, if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) || (check == NULL) || (comp == NULL)) return (-1); - if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) { - xmlGenericError(xmlGenericErrorContext, - "Relax-NG types library '%s' already registered\n", - namespace); + if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) return (-1); - } lib = (xmlRelaxNGTypeLibraryPtr) xmlMalloc(sizeof(xmlRelaxNGTypeLibrary)); if (lib == NULL) { - xmlRngVErrMemory(NULL, "adding types library\n"); + xmlRngVErrMemory(NULL); return (-1); } memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary)); @@ -2735,9 +2759,6 @@ xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data, lib->freef = freef; ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib); if (ret < 0) { - xmlGenericError(xmlGenericErrorContext, - "Relax-NG types library failed to register '%s'\n", - namespace); xmlRelaxNGFreeTypeLibrary(lib, namespace); return (-1); } @@ -2757,11 +2778,8 @@ xmlRelaxNGInitTypes(void) if (xmlRelaxNGTypeInitialized != 0) return (0); xmlRelaxNGRegisteredTypes = xmlHashCreate(10); - if (xmlRelaxNGRegisteredTypes == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Failed to allocate sh table for Relax-NG types\n"); + if (xmlRelaxNGRegisteredTypes == NULL) return (-1); - } xmlRelaxNGRegisterTypeLibrary(BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes", NULL, xmlRelaxNGSchemaTypeHave, @@ -3723,7 +3741,8 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, else if (ret == 1) ret = 0; } else { - TODO ret = 0; + /* TODO */ + ret = 0; } if (ret == 0) return (ret); @@ -3754,7 +3773,8 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, ret = 1; } } else { - TODO ret = 0; + /* TODO */ + ret = 0; } return (ret); @@ -3911,7 +3931,7 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, ret = (xmlRelaxNGDefinePtr *) xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr)); if (ret == NULL) { - xmlRngPErrMemory(ctxt, "getting element list\n"); + xmlRngPErrMemory(ctxt); return (NULL); } } else if (max <= len) { @@ -3921,7 +3941,7 @@ xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, temp = xmlRealloc(ret, (max + 1) * sizeof(xmlRelaxNGDefinePtr)); if (temp == NULL) { - xmlRngPErrMemory(ctxt, "getting element list\n"); + xmlRngPErrMemory(ctxt); xmlFree(ret); return (NULL); } @@ -4019,7 +4039,7 @@ xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt, sizeof(xmlRelaxNGDefinePtr *)); if (list == NULL) { - xmlRngPErrMemory(ctxt, "building choice\n"); + xmlRngPErrMemory(ctxt); return; } i = 0; @@ -4156,7 +4176,7 @@ xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt, sizeof(xmlRelaxNGDefinePtr *)); if (list == NULL) { - xmlRngPErrMemory(ctxt, "building group\n"); + xmlRngPErrMemory(ctxt); return; } i = 0; @@ -4348,7 +4368,7 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data, return; error: - xmlRngPErrMemory(ctxt, "in interleave computation\n"); + xmlRngPErrMemory(ctxt); if (groups != NULL) { for (i = 0; i < nbgroups; i++) if (groups[i] != NULL) { @@ -4386,7 +4406,7 @@ xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) if (ctxt->interleaves == NULL) ctxt->interleaves = xmlHashCreate(10); if (ctxt->interleaves == NULL) { - xmlRngPErrMemory(ctxt, "create interleaves\n"); + xmlRngPErrMemory(ctxt); } else { char name[32]; @@ -5253,7 +5273,7 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, if (tmp != NULL) { if (last == NULL) { last = tmp; - } else { + } else if (tmp != ret) { last->next = tmp; last = tmp; } @@ -6617,13 +6637,11 @@ xmlRelaxNGNewParserCtxt(const char *URL) ret = (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); if (ret == NULL) { - xmlRngPErrMemory(NULL, "building parser\n"); + xmlRngPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGParserCtxt)); ret->URL = xmlStrdup((const xmlChar *) URL); - ret->error = xmlGenericError; - ret->userData = xmlGenericErrorContext; return (ret); } @@ -6648,14 +6666,12 @@ xmlRelaxNGNewMemParserCtxt(const char *buffer, int size) ret = (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); if (ret == NULL) { - xmlRngPErrMemory(NULL, "building parser\n"); + xmlRngPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGParserCtxt)); ret->buffer = buffer; ret->size = size; - ret->error = xmlGenericError; - ret->userData = xmlGenericErrorContext; return (ret); } @@ -6684,7 +6700,7 @@ xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc) ret = (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); if (ret == NULL) { - xmlRngPErrMemory(NULL, "building parser\n"); + xmlRngPErrMemory(NULL); xmlFreeDoc(copy); return (NULL); } @@ -7366,7 +7382,7 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) * First step is to parse the input document into an DOM/Infoset */ if (ctxt->URL != NULL) { - doc = xmlReadFile((const char *) ctxt->URL,NULL,0); + doc = xmlRelaxReadFile(ctxt, (const char *) ctxt->URL); if (doc == NULL) { xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, "xmlRelaxNGParse: could not load %s\n", ctxt->URL, @@ -7374,7 +7390,7 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) return (NULL); } } else if (ctxt->buffer != NULL) { - doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0); + doc = xmlRelaxReadMemory(ctxt, ctxt->buffer, ctxt->size); if (doc == NULL) { xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, "xmlRelaxNGParse: could not parse schemas\n", NULL, @@ -7485,6 +7501,8 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) * @warn: the warning callback * @ctx: contextual data for the callbacks * + * DEPRECATED: Use xmlRelaxNGSetParserStructuredErrors. + * * Set the callback functions used to handle errors for a validation context */ void @@ -7679,11 +7697,13 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) break; case XML_RELAXNG_DATATYPE: case XML_RELAXNG_VALUE: - TODO break; + /* TODO */ + break; case XML_RELAXNG_START: case XML_RELAXNG_EXCEPT: case XML_RELAXNG_PARAM: - TODO break; + /* TODO */ + break; case XML_RELAXNG_NOOP: xmlRelaxNGDumpDefines(output, define->content); break; @@ -7951,7 +7971,7 @@ xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec) sizeof (xmlRegExecCtxtPtr)); if (ctxt->elemTab == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); return (-1); } } @@ -7962,7 +7982,7 @@ xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec) sizeof (xmlRegExecCtxtPtr)); if (ctxt->elemTab == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); return (-1); } } @@ -8033,13 +8053,7 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec ctxt->pstate = -1; return; } - if ((ctxt == NULL) || (define == NULL)) { - fprintf(stderr, "callback on %s missing info\n", token); - if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) - ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; - ctxt->pstate = -1; - return; - } else if (define->type != XML_RELAXNG_ELEMENT) { + if (define->type != XML_RELAXNG_ELEMENT) { fprintf(stderr, "callback on %s define is not element\n", token); if (ctxt->errNo == XML_RELAXNG_OK) ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; @@ -8382,7 +8396,7 @@ xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str) ret = (xmlChar *) xmlMallocAtomic(len + 1); if (ret == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); return (NULL); } p = ret; @@ -8793,7 +8807,8 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, } break; default: - TODO ret = -1; + /* TODO */ + ret = -1; } return (ret); } @@ -8881,7 +8896,9 @@ xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt, } return (0); } else { - TODO} + /* TODO */ + return (0); + } return (1); } @@ -9133,13 +9150,13 @@ xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, */ list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); if (list == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); return (-1); } memset(list, 0, nbgroups * sizeof(xmlNodePtr)); lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); if (lasts == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); return (-1); } memset(lasts, 0, nbgroups * sizeof(xmlNodePtr)); @@ -9516,7 +9533,8 @@ xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, ctxt->flags = oldflags; } } else { - TODO ret = -1; + /* TODO */ + ret = -1; } return (ret); } @@ -10226,7 +10244,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, if (content == NULL) { content = xmlStrdup(BAD_CAST ""); if (content == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); ret = -1; break; } @@ -10269,7 +10287,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, if (content == NULL) { content = xmlStrdup(BAD_CAST ""); if (content == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); ret = -1; break; } @@ -10320,7 +10338,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, if (content == NULL) { content = xmlStrdup(BAD_CAST ""); if (content == NULL) { - xmlRngVErrMemory(ctxt, "validating\n"); + xmlRngVErrMemory(ctxt); ret = -1; break; } @@ -10344,7 +10362,8 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, } case XML_RELAXNG_EXCEPT: case XML_RELAXNG_PARAM: - TODO ret = -1; + /* TODO */ + ret = -1; break; } ctxt->depth--; @@ -10371,7 +10390,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, * We should NOT have both ctxt->state and ctxt->states */ if ((ctxt->state != NULL) && (ctxt->states != NULL)) { - TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + /* TODO */ + xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; } @@ -10383,7 +10403,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, } ret = xmlRelaxNGValidateState(ctxt, define); if ((ctxt->state != NULL) && (ctxt->states != NULL)) { - TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + /* TODO */ + xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; } if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) { @@ -10408,7 +10429,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, * We should NOT have both ctxt->state and ctxt->states */ if ((ctxt->state != NULL) && (ctxt->states != NULL)) { - TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + /* TODO */ + xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; } if (ret == 0) { @@ -10474,7 +10496,8 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, } } if ((ctxt->state != NULL) && (ctxt->states != NULL)) { - TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); + /* TODO */ + xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; } return (ret); @@ -10552,9 +10575,16 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) memset(&vctxt, 0, sizeof(xmlValidCtxt)); vctxt.valid = 1; - vctxt.error = ctxt->error; - vctxt.warning = ctxt->warning; - vctxt.userData = ctxt->userData; + + if (ctxt->error == NULL) { + vctxt.error = xmlGenericError; + vctxt.warning = xmlGenericError; + vctxt.userData = xmlGenericErrorContext; + } else { + vctxt.error = ctxt->error; + vctxt.warning = ctxt->warning; + vctxt.userData = ctxt->userData; + } if (xmlValidateDocumentFinal(&vctxt, doc) != 1) ret = -1; @@ -10641,13 +10671,11 @@ xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema) ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt)); if (ret == NULL) { - xmlRngVErrMemory(NULL, "building context\n"); + xmlRngVErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlRelaxNGValidCtxt)); ret->schema = schema; - ret->error = xmlGenericError; - ret->userData = xmlGenericErrorContext; ret->errNr = 0; ret->errMax = 0; ret->err = NULL; @@ -10710,6 +10738,8 @@ xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt) * @warn: the warning function * @ctx: the functions context * + * DEPRECATED: Use xmlRelaxNGSetValidStructuredErrors. + * * Set the error and warning callback information */ void diff --git a/runsuite.c b/runsuite.c index 396f3ca..b7f36c2 100644 --- a/runsuite.c +++ b/runsuite.c @@ -1036,7 +1036,7 @@ xstcMetadata(const char *metadata, const char *base) { int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { int ret = 0; - int old_errors, old_tests, old_leaks; + int old_errors, old_tests, old_leaks, expected_errors; logfile = fopen(LOGFILE, "w"); if (logfile == NULL) { @@ -1054,16 +1054,17 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { old_tests = nb_tests; old_leaks = nb_leaks; xsdTest(); + expected_errors = 3; printf("Ran %d tests, %d errors, %d leaks\n", nb_tests - old_tests, nb_errors - old_errors, nb_leaks - old_leaks); - if (nb_errors - old_errors == 10) { - printf("10 errors were expected\n"); + if (nb_errors - old_errors == expected_errors) { + printf("%d errors were expected\n", expected_errors); nb_errors = old_errors; } else { - printf("10 errors were expected, got %d errors\n", - nb_errors - old_errors); + printf("%d errors were expected, got %d errors\n", + expected_errors, nb_errors - old_errors); nb_errors = old_errors + 1; } diff --git a/runtest.c b/runtest.c index fef5612..4f4a0b8 100644 --- a/runtest.c +++ b/runtest.c @@ -11,6 +11,8 @@ * daniel@veillard.com */ +#define XML_DEPRECATED + #include "libxml.h" #include #ifdef HAVE_UNISTD_H @@ -271,281 +273,9 @@ testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { testErrors[testErrorsSize] = 0; } -static void -channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { - va_list args; - int res; - - if (testErrorsSize >= 32768) - return; - va_start(args, msg); - res = vsnprintf(&testErrors[testErrorsSize], - 32768 - testErrorsSize, - msg, args); - va_end(args); - if (testErrorsSize + res >= 32768) { - /* buffer is full */ - testErrorsSize = 32768; - testErrors[testErrorsSize] = 0; - } else { - testErrorsSize += res; - } - testErrors[testErrorsSize] = 0; -} - -/** - * xmlParserPrintFileContextInternal: - * @input: an xmlParserInputPtr input - * - * Displays current context within the input content for error tracking - */ - -static void -xmlParserPrintFileContextInternal(xmlParserInputPtr input , - xmlGenericErrorFunc chanl, void *data ) { - const xmlChar *cur, *base, *start; - unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ - xmlChar content[81]; /* space for 80 chars + line terminator */ - xmlChar *ctnt; - - if ((input == NULL) || (input->cur == NULL)) - return; - - cur = input->cur; - base = input->base; - /* skip backwards over any end-of-lines */ - while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { - cur--; - } - n = 0; - /* search backwards for beginning-of-line (to max buff size) */ - while ((n++ < (sizeof(content)-1)) && (cur > base) && - (*(cur) != '\n') && (*(cur) != '\r')) - cur--; - if ((*(cur) == '\n') || (*(cur) == '\r')) { - cur++; - } else { - /* skip over continuation bytes */ - while ((cur < input->cur) && ((*cur & 0xC0) == 0x80)) - cur++; - } - /* calculate the error position in terms of the current position */ - col = input->cur - cur; - /* search forward for end-of-line (to max buff size) */ - n = 0; - start = cur; - /* copy selected text to our buffer */ - while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) { - int len = input->end - cur; - int c = xmlGetUTF8Char(cur, &len); - - if ((c < 0) || (n + len > sizeof(content)-1)) - break; - cur += len; - n += len; - } - memcpy(content, start, n); - content[n] = 0; - /* print out the selected text */ - chanl(data ,"%s\n", content); - /* create blank line with problem pointer */ - n = 0; - ctnt = content; - /* (leave buffer space for pointer + line terminator) */ - while ((nfile; - line = err->line; - code = err->code; - domain = err->domain; - level = err->level; - node = err->node; - if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || - (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || - (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { - ctxt = err->ctxt; - } - str = err->message; - - if (code == XML_ERR_OK) - return; - - if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) - name = node->name; - - /* - * Maintain the compatibility with the legacy error handling - */ - if (ctxt != NULL) { - input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && - (ctxt->inputNr > 1)) { - cur = input; - input = ctxt->inputTab[ctxt->inputNr - 2]; - } - if (input != NULL) { - if (input->filename) - channel(data, "%s:%d: ", input->filename, input->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", input->line); - } - } else { - if (file != NULL) - channel(data, "%s:%d: ", file, line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", line); - } - /* - * Skip element name when testing schemas to make memory and streaming - * output match. - */ - if ((domain != XML_FROM_SCHEMASV) && (name != NULL)) { - channel(data, "element %s: ", name); - } - if (code == XML_ERR_OK) - return; - switch (domain) { - case XML_FROM_PARSER: - channel(data, "parser "); - break; - case XML_FROM_NAMESPACE: - channel(data, "namespace "); - break; - case XML_FROM_DTD: - case XML_FROM_VALID: - channel(data, "validity "); - break; - case XML_FROM_HTML: - channel(data, "HTML parser "); - break; - case XML_FROM_MEMORY: - channel(data, "memory "); - break; - case XML_FROM_OUTPUT: - channel(data, "output "); - break; - case XML_FROM_IO: - channel(data, "I/O "); - break; - case XML_FROM_XINCLUDE: - channel(data, "XInclude "); - break; - case XML_FROM_XPATH: - channel(data, "XPath "); - break; - case XML_FROM_XPOINTER: - channel(data, "parser "); - break; - case XML_FROM_REGEXP: - channel(data, "regexp "); - break; - case XML_FROM_MODULE: - channel(data, "module "); - break; - case XML_FROM_SCHEMASV: - channel(data, "Schemas validity "); - break; - case XML_FROM_SCHEMASP: - channel(data, "Schemas parser "); - break; - case XML_FROM_RELAXNGP: - channel(data, "Relax-NG parser "); - break; - case XML_FROM_RELAXNGV: - channel(data, "Relax-NG validity "); - break; - case XML_FROM_CATALOG: - channel(data, "Catalog "); - break; - case XML_FROM_C14N: - channel(data, "C14N "); - break; - case XML_FROM_XSLT: - channel(data, "XSLT "); - break; - default: - break; - } - if (code == XML_ERR_OK) - return; - switch (level) { - case XML_ERR_NONE: - channel(data, ": "); - break; - case XML_ERR_WARNING: - channel(data, "warning : "); - break; - case XML_ERR_ERROR: - channel(data, "error : "); - break; - case XML_ERR_FATAL: - channel(data, "error : "); - break; - } - if (code == XML_ERR_OK) - return; - if (str != NULL) { - int len; - len = xmlStrlen((const xmlChar *)str); - if ((len > 0) && (str[len - 1] != '\n')) - channel(data, "%s\n", str); - else - channel(data, "%s", str); - } else { - channel(data, "%s\n", "out of memory error"); - } - if (code == XML_ERR_OK) - return; - - if (ctxt != NULL) { - xmlParserPrintFileContextInternal(input, channel, data); - if (cur != NULL) { - if (cur->filename) - channel(data, "%s:%d: \n", cur->filename, cur->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: \n", cur->line); - xmlParserPrintFileContextInternal(cur, channel, data); - } - } - if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && - (err->int1 < 100) && - (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { - xmlChar buf[150]; - int i; - - channel(data, "%s\n", err->str1); - for (i=0;i < err->int1;i++) - buf[i] = ' '; - buf[i++] = '^'; - buf[i] = 0; - channel(data, "%s\n", buf); - } + xmlFormatError(err, testErrorHandler, NULL); } static void @@ -561,7 +291,6 @@ initializeLibxml2(void) { xmlInitParser(); xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); xmlSetExternalEntityLoader(testExternalEntityLoader); - xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); #ifdef LIBXML_SCHEMAS_ENABLED xmlSchemaInitTypes(); xmlRelaxNGInitTypes(); @@ -607,10 +336,6 @@ static char *resultFilename(const char *filename, const char *out, out = ""; strncpy(suffixbuff,suffix,499); -#ifdef VMS - if(strstr(base,".") && suffixbuff[0]=='.') - suffixbuff[0]='_'; -#endif if (snprintf(res, 499, "%s%s%s", out, base, suffixbuff) >= 499) res[499] = 0; @@ -1093,6 +818,16 @@ entityDeclDebug(void *ctx, const xmlChar *name, int type, xmlEntityPtr ent; const xmlChar *nullstr = BAD_CAST "(null)"; + ent = xmlNewEntity(NULL, name, type, publicId, systemId, content); + if (systemId != NULL) + ent->URI = xmlBuildURI(systemId, (const xmlChar *) ctxt->filename); + + if ((type == XML_INTERNAL_PARAMETER_ENTITY) || + (type == XML_EXTERNAL_PARAMETER_ENTITY)) + xmlHashAddEntry(ctxt->parameterEntities, name, ent); + else + xmlHashAddEntry(ctxt->generalEntities, name, ent); + /* not all libraries handle printing null pointers nicely */ if (publicId == NULL) publicId = nullstr; @@ -1105,16 +840,6 @@ entityDeclDebug(void *ctx, const xmlChar *name, int type, return; fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", name, type, publicId, systemId, content); - - ent = xmlNewEntity(NULL, name, type, publicId, systemId, content); - if (systemId != NULL) - ent->URI = xmlBuildURI(systemId, (const xmlChar *) ctxt->filename); - - if ((type == XML_INTERNAL_PARAMETER_ENTITY) || - (type == XML_EXTERNAL_PARAMETER_ENTITY)) - xmlHashAddEntry(ctxt->parameterEntities, name, ent); - else - xmlHashAddEntry(ctxt->generalEntities, name, ent); } /** @@ -1809,10 +1534,6 @@ saxParseTest(const char *filename, const char *result, return(-1); } - /* for SAX we really want the callbacks though the context handlers */ - xmlSetStructuredErrorFunc(NULL, NULL); - xmlSetGenericErrorFunc(NULL, testErrorHandler); - #ifdef LIBXML_HTML_ENABLED if (options & XML_PARSE_HTML) { htmlParserCtxtPtr ctxt; @@ -1832,8 +1553,8 @@ saxParseTest(const char *filename, const char *result, xmlFreeDoc(ctxt->myDoc); xmlFreeParserCtxt(ctxt); } - if (ret == XML_WAR_UNDECLARED_ENTITY) { - fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret); + if (ret == XML_ERR_UNDECLARED_ENTITY) { + fprintf(SAXdebug, "xmlParseDocument returned error %d\n", ret); ret = 0; } if (ret != 0) { @@ -1873,10 +1594,6 @@ saxParseTest(const char *filename, const char *result, xmlFreeDoc(ctxt->myDoc); xmlFreeParserCtxt(ctxt); } - if (ret == XML_WAR_UNDECLARED_ENTITY) { - fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret); - ret = 0; - } fclose(SAXdebug); if (compareFiles(temp, result)) { fprintf(stderr, "Got a difference for %s\n", filename); @@ -1889,10 +1606,6 @@ saxParseTest(const char *filename, const char *result, free(temp); } - /* switch back to structured error handling */ - xmlSetGenericErrorFunc(NULL, NULL); - xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); - return(ret); } @@ -1926,9 +1639,11 @@ oldParseTest(const char *filename, const char *result, * base of the test, parse with the old API */ #ifdef LIBXML_SAX1_ENABLED + xmlGetWarningsDefaultValue = 0; doc = xmlParseFile(filename); + xmlGetWarningsDefaultValue = 1; #else - doc = xmlReadFile(filename, NULL, 0); + doc = xmlReadFile(filename, NULL, XML_PARSE_NOWARNING); #endif if (doc == NULL) return(1); @@ -1947,9 +1662,11 @@ oldParseTest(const char *filename, const char *result, * Parse the saved result to make sure the round trip is okay */ #ifdef LIBXML_SAX1_ENABLED + xmlGetWarningsDefaultValue = 0; doc = xmlParseFile(temp); + xmlGetWarningsDefaultValue = 1; #else - doc = xmlReadFile(temp, NULL, 0); + doc = xmlReadFile(temp, NULL, XML_PARSE_NOWARNING); #endif if (doc == NULL) return(1); @@ -1963,6 +1680,7 @@ oldParseTest(const char *filename, const char *result, unlink(temp); free(temp); } + return(res); } @@ -2008,6 +1726,7 @@ pushParseTest(const char *filename, const char *result, else #endif ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, chunkSize, filename); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); xmlCtxtUseOptions(ctxt, options); cur += chunkSize; chunkSize = 1024; @@ -2227,6 +1946,7 @@ pushBoundaryTest(const char *filename, const char *result, else #endif ctxt = xmlCreatePushParserCtxt(&bndSAX, NULL, base, 1, filename); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); xmlCtxtUseOptions(ctxt, options); cur = 1; consumed = 0; @@ -2405,7 +2125,7 @@ memParseTest(const char *filename, const char *result, return(-1); } - doc = xmlReadMemory(base, size, filename, NULL, 0); + doc = xmlReadMemory(base, size, filename, NULL, XML_PARSE_NOWARNING); unloadMem(base); if (doc == NULL) { return(1); @@ -2447,7 +2167,8 @@ noentParseTest(const char *filename, const char *result, /* * base of the test, parse with the old API */ - doc = xmlReadFile(filename, NULL, options); + doc = xmlReadFile(filename, NULL, + options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR); if (doc == NULL) return(1); temp = resultFilename(filename, temp_directory, ".res"); @@ -2464,7 +2185,8 @@ noentParseTest(const char *filename, const char *result, /* * Parse the saved result to make sure the round trip is okay */ - doc = xmlReadFile(filename, NULL, options); + doc = xmlReadFile(filename, NULL, + options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR); if (doc == NULL) return(1); xmlSaveFile(temp, doc); @@ -2493,6 +2215,7 @@ noentParseTest(const char *filename, const char *result, static int errParseTest(const char *filename, const char *result, const char *err, int options) { + xmlParserCtxtPtr ctxt; xmlDocPtr doc; const char *base = NULL; int size, res = 0; @@ -2500,20 +2223,32 @@ errParseTest(const char *filename, const char *result, const char *err, nb_tests++; #ifdef LIBXML_HTML_ENABLED if (options & XML_PARSE_HTML) { - doc = htmlReadFile(filename, NULL, options); + ctxt = htmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); + doc = htmlCtxtReadFile(ctxt, filename, NULL, options); + htmlFreeParserCtxt(ctxt); } else #endif + { + ctxt = xmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); + doc = xmlCtxtReadFile(ctxt, filename, NULL, options); + xmlFreeParserCtxt(ctxt); #ifdef LIBXML_XINCLUDE_ENABLED - if (options & XML_PARSE_XINCLUDE) { - doc = xmlReadFile(filename, NULL, options); - if (xmlXIncludeProcessFlags(doc, options) < 0) { - xmlFreeDoc(doc); - doc = NULL; + if (options & XML_PARSE_XINCLUDE) { + xmlXIncludeCtxtPtr xinc = NULL; + + xinc = xmlXIncludeNewContext(doc); + xmlXIncludeSetErrorHandler(xinc, testStructuredErrorHandler, NULL); + xmlXIncludeSetFlags(xinc, options); + if (xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc) < 0) { + testErrorHandler(NULL, "%s : failed to parse\n", filename); + xmlFreeDoc(doc); + doc = NULL; + } + xmlXIncludeFreeContext(xinc); } - } else #endif - { - doc = xmlReadFile(filename, NULL, options); } if (result) { if (doc == NULL) { @@ -2566,6 +2301,7 @@ errParseTest(const char *filename, const char *result, const char *err, static int fdParseTest(const char *filename, const char *result, const char *err, int options) { + xmlParserCtxtPtr ctxt; xmlDocPtr doc; const char *base = NULL; int size, res = 0, fd; @@ -2574,11 +2310,17 @@ fdParseTest(const char *filename, const char *result, const char *err, fd = open(filename, RD_FLAGS); #ifdef LIBXML_HTML_ENABLED if (options & XML_PARSE_HTML) { - doc = htmlReadFd(fd, filename, NULL, options); + ctxt = htmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); + doc = htmlCtxtReadFd(ctxt, fd, filename, NULL, options); + htmlFreeParserCtxt(ctxt); } else #endif { - doc = xmlReadFd(fd, filename, NULL, options); + ctxt = xmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); + doc = xmlCtxtReadFd(ctxt, fd, filename, NULL, options); + xmlFreeParserCtxt(ctxt); } close(fd); if (result) { @@ -2750,6 +2492,8 @@ streamParseTest(const char *filename, const char *result, const char *err, int ret; reader = xmlReaderForFile(filename, NULL, options); + xmlTextReaderSetStructuredErrorHandler(reader, testStructuredErrorHandler, + NULL); ret = streamProcessTest(filename, result, err, reader, NULL, options); xmlFreeTextReader(reader); return(ret); @@ -2772,7 +2516,7 @@ walkerParseTest(const char *filename, const char *result, const char *err, xmlTextReaderPtr reader; int ret; - doc = xmlReadFile(filename, NULL, options); + doc = xmlReadFile(filename, NULL, options | XML_PARSE_NOWARNING); if (doc == NULL) { fprintf(stderr, "Failed to parse %s\n", filename); return(-1); @@ -2810,6 +2554,8 @@ streamMemParseTest(const char *filename, const char *result, const char *err, return(-1); } reader = xmlReaderForMemory(base, size, filename, NULL, options); + xmlTextReaderSetStructuredErrorHandler(reader, testStructuredErrorHandler, + NULL); ret = streamProcessTest(filename, result, err, reader, NULL, options); free((char *)base); xmlFreeTextReader(reader); @@ -2828,27 +2574,21 @@ streamMemParseTest(const char *filename, const char *result, const char *err, static FILE *xpathOutput; static xmlDocPtr xpathDocument; -static void -ignoreGenericError(void *ctx ATTRIBUTE_UNUSED, - const char *msg ATTRIBUTE_UNUSED, ...) { -} - static void testXPath(const char *str, int xptr, int expr) { xmlXPathObjectPtr res; xmlXPathContextPtr ctxt; - /* Don't print generic errors to stderr. */ - xmlSetGenericErrorFunc(NULL, ignoreGenericError); - nb_tests++; #if defined(LIBXML_XPTR_ENABLED) if (xptr) { ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL); + xmlXPathSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); res = xmlXPtrEval(BAD_CAST str, ctxt); } else { #endif ctxt = xmlXPathNewContext(xpathDocument); + xmlXPathSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); ctxt->node = xmlDocGetRootElement(xpathDocument); if (expr) res = xmlXPathEvalExpression(BAD_CAST str, ctxt); @@ -2869,9 +2609,6 @@ testXPath(const char *str, int xptr, int expr) { xmlXPathDebugDumpObject(xpathOutput, res, 0); xmlXPathFreeObject(res); xmlXPathFreeContext(ctxt); - - /* Reset generic error handler. */ - xmlSetGenericErrorFunc(NULL, NULL); } /** @@ -2906,7 +2643,7 @@ xpathCommonTest(const char *filename, const char *result, input = fopen(filename, "rb"); if (input == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Cannot open %s for reading\n", filename); free(temp); return(-1); @@ -3081,13 +2818,16 @@ xmlidDocTest(const char *filename, const char *result, const char *err, int options) { - + xmlParserCtxtPtr ctxt; int res = 0; int ret = 0; char *temp; - xpathDocument = xmlReadFile(filename, NULL, - options | XML_PARSE_DTDATTR | XML_PARSE_NOENT); + ctxt = xmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL); + xpathDocument = xmlCtxtReadFile(ctxt, filename, NULL, + options | XML_PARSE_DTDATTR | XML_PARSE_NOENT); + xmlFreeParserCtxt(ctxt); if (xpathDocument == NULL) { fprintf(stderr, "Failed to load %s\n", filename); return(-1); @@ -3506,8 +3246,12 @@ schemasOneTest(const char *sch, testErrorsSize = parseErrorsSize; testErrors[parseErrorsSize] = 0; + if (schemas == NULL) + goto done; + ctxt = xmlSchemaNewValidCtxt(schemas); - xmlSchemaSetValidErrors(ctxt, testErrorHandler, testErrorHandler, ctxt); + xmlSchemaSetValidStructuredErrors(ctxt, testStructuredErrorHandler, + NULL); schemasOutput = fopen(temp, "wb"); if (schemasOutput == NULL) { @@ -3539,19 +3283,23 @@ schemasOneTest(const char *sch, filename); } fclose(schemasOutput); + if (result) { if (compareFiles(temp, result)) { fprintf(stderr, "Result for %s on %s failed\n", filename, sch); ret = 1; } } + + xmlSchemaFreeValidCtxt(ctxt); + +done: if (compareFileMem(err, testErrors, testErrorsSize)) { fprintf(stderr, "Error for %s on %s failed\n", filename, sch); ret = 1; } unlink(temp); - xmlSchemaFreeValidCtxt(ctxt); } free(temp); @@ -3590,7 +3338,7 @@ schemasTest(const char *filename, /* first compile the schemas if possible */ ctxt = xmlSchemaNewParserCtxt(filename); - xmlSchemaSetParserErrors(ctxt, testErrorHandler, testErrorHandler, ctxt); + xmlSchemaSetParserStructuredErrors(ctxt, testStructuredErrorHandler, NULL); schemas = xmlSchemaParse(ctxt); xmlSchemaFreeParserCtxt(ctxt); parseErrorsSize = testErrorsSize; @@ -3644,13 +3392,12 @@ schemasTest(const char *filename, fprintf(stderr, "don't know how to process %s\n", instance); continue; } - if (schemas != NULL) { - nb_tests++; - ret = schemasOneTest(filename, instance, result, err, - options, schemas); - if (ret != 0) - res = ret; - } + + nb_tests++; + ret = schemasOneTest(filename, instance, result, err, + options, schemas); + if (ret != 0) + res = ret; } globfree(&globbuf); xmlSchemaFree(schemas); @@ -3695,7 +3442,7 @@ rngOneTest(const char *sch, } ctxt = xmlRelaxNGNewValidCtxt(schemas); - xmlRelaxNGSetValidErrors(ctxt, testErrorHandler, testErrorHandler, ctxt); + xmlRelaxNGSetValidStructuredErrors(ctxt, testStructuredErrorHandler, NULL); ret = xmlRelaxNGValidateDoc(ctxt, doc); if (ret == 0) { testErrorHandler(NULL, "%s validates\n", filename); @@ -3754,7 +3501,8 @@ rngTest(const char *filename, /* first compile the schemas if possible */ ctxt = xmlRelaxNGNewParserCtxt(filename); - xmlRelaxNGSetParserErrors(ctxt, testErrorHandler, testErrorHandler, ctxt); + xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, + NULL); schemas = xmlRelaxNGParse(ctxt); xmlRelaxNGFreeParserCtxt(ctxt); if (schemas == NULL) @@ -3808,7 +3556,7 @@ rngTest(const char *filename, if (compareFileMem(err, testErrors, testErrorsSize)) { fprintf(stderr, "Error for %s on %s failed\n", instance, filename); - res = 1; + ret = 1; } } globfree(&globbuf); @@ -3894,6 +3642,8 @@ rngStreamTest(const char *filename, continue; } reader = xmlReaderForFile(instance, NULL, options); + xmlTextReaderSetStructuredErrorHandler(reader, + testStructuredErrorHandler, NULL); if (reader == NULL) { fprintf(stderr, "Failed to build reader for %s\n", instance); } @@ -4293,7 +4043,8 @@ c14nRunTest(const char* xml_filename, int with_comments, int mode, * build an XML tree from a the file; we need to add default * attributes and resolve all character and entities references */ - doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT); + doc = xmlReadFile(xml_filename, NULL, + XML_PARSE_DTDATTR | XML_PARSE_NOENT | XML_PARSE_NOWARNING); if (doc == NULL) { fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename); return(-1); @@ -4657,13 +4408,19 @@ regexpTest(const char *filename, const char *result, const char *err, char expression[5000]; int len, ret, res = 0; + /* + * TODO: Custom error handler for regexp + */ + xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); + nb_tests++; input = fopen(filename, "rb"); if (input == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Cannot open %s for reading\n", filename); - return(-1); + ret = -1; + goto done; } temp = resultFilename(filename, "", ".res"); if (temp == NULL) { @@ -4674,7 +4431,8 @@ regexpTest(const char *filename, const char *result, const char *err, if (output == NULL) { fprintf(stderr, "failed to open output file %s\n", temp); free(temp); - return(-1); + ret = -1; + goto done; } while (fgets(expression, 4500, input) != NULL) { len = strlen(expression); @@ -4732,6 +4490,9 @@ regexpTest(const char *filename, const char *result, const char *err, res = 1; } +done: + xmlSetStructuredErrorFunc(NULL, NULL); + return(res); } @@ -4779,7 +4540,7 @@ automataTest(const char *filename, const char *result, input = fopen(filename, "rb"); if (input == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Cannot open %s for reading\n", filename); return(-1); } @@ -4797,14 +4558,14 @@ automataTest(const char *filename, const char *result, am = xmlNewAutomata(); if (am == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Cannot create automata\n"); fclose(input); return(-1); } states[0] = xmlAutomataGetInitState(am); if (states[0] == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Cannot get start state\n"); xmlFreeAutomata(am); fclose(input); @@ -4828,7 +4589,7 @@ automataTest(const char *filename, const char *result, from = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4837,7 +4598,7 @@ automataTest(const char *filename, const char *result, ptr++; to = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4852,7 +4613,7 @@ automataTest(const char *filename, const char *result, from = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4869,7 +4630,7 @@ automataTest(const char *filename, const char *result, state = scanNumber(&ptr); if (states[state] == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad state %d : %s\n", state, expr); break; } @@ -4881,7 +4642,7 @@ automataTest(const char *filename, const char *result, from = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4890,7 +4651,7 @@ automataTest(const char *filename, const char *result, ptr++; to = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4899,14 +4660,14 @@ automataTest(const char *filename, const char *result, ptr++; min = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } ptr++; max = scanNumber(&ptr); if (*ptr != ' ') { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Bad line %s\n", expr); break; } @@ -4919,7 +4680,7 @@ automataTest(const char *filename, const char *result, xmlFreeAutomata(am); am = NULL; if (regexp == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Failed to compile the automata"); break; } @@ -4947,7 +4708,7 @@ automataTest(const char *filename, const char *result, exec = xmlRegNewExecCtxt(regexp, NULL, NULL); ret = xmlRegExecPushString(exec, BAD_CAST expr, NULL); } else { - xmlGenericError(xmlGenericErrorContext, + fprintf(stderr, "Unexpected line %s\n", expr); } } @@ -5209,10 +4970,29 @@ launchTests(testDescPtr tst) { char *result; char *error; int mem; - xmlCharEncodingHandlerPtr ebcdicHandler, eucJpHandler; + xmlCharEncodingHandlerPtr ebcdicHandler, ibm1141Handler, eucJpHandler; ebcdicHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC); + ibm1141Handler = xmlFindCharEncodingHandler("IBM-1141"); + + /* + * When decoding EUC-JP, musl doesn't seem to support 0x8F control + * codes. + */ eucJpHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EUC_JP); + if (eucJpHandler != NULL) { + xmlBufferPtr in, out; + + in = xmlBufferCreateSize(10); + xmlBufferCCat(in, "\x8f\xe9\xae"); + out = xmlBufferCreateSize(10); + if (xmlCharEncInFunc(eucJpHandler, out, in) != 3) { + xmlCharEncCloseFunc(eucJpHandler); + eucJpHandler = NULL; + } + xmlBufferFree(out); + xmlBufferFree(in); + } if (tst == NULL) return(-1); if (tst->in != NULL) { @@ -5223,7 +5003,7 @@ launchTests(testDescPtr tst) { for (i = 0;i < globbuf.gl_pathc;i++) { if (!checkTestFile(globbuf.gl_pathv[i])) continue; - if (((ebcdicHandler == NULL) && + if ((((ebcdicHandler == NULL) || (ibm1141Handler == NULL)) && (strstr(globbuf.gl_pathv[i], "ebcdic") != NULL)) || ((eucJpHandler == NULL) && (strstr(globbuf.gl_pathv[i], "icu_parse_test") != NULL))) @@ -5289,6 +5069,7 @@ launchTests(testDescPtr tst) { } xmlCharEncCloseFunc(ebcdicHandler); + xmlCharEncCloseFunc(ibm1141Handler); xmlCharEncCloseFunc(eucJpHandler); return(err); diff --git a/runxmlconf.c b/runxmlconf.c index 8505590..36ab448 100644 --- a/runxmlconf.c +++ b/runxmlconf.c @@ -173,7 +173,6 @@ initializeLibxml2(void) { */ if (ctxtXPath->cache != NULL) xmlXPathContextSetCache(ctxtXPath, 0, -1, 0); - xmlSetStructuredErrorFunc(NULL, testErrorHandler); } /************************************************************************ @@ -194,6 +193,7 @@ xmlconfTestInvalid(const char *id, const char *filename, int options) { id, filename); return(0); } + xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL); doc = xmlCtxtReadFile(ctxt, filename, NULL, options); if (doc == NULL) { test_log("test %s : %s invalid document turned not well-formed too\n", @@ -224,6 +224,7 @@ xmlconfTestValid(const char *id, const char *filename, int options) { id, filename); return(0); } + xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL); doc = xmlCtxtReadFile(ctxt, filename, NULL, options); if (doc == NULL) { test_log("test %s : %s failed to parse a valid document\n", @@ -246,14 +247,17 @@ xmlconfTestValid(const char *id, const char *filename, int options) { static int xmlconfTestNotNSWF(const char *id, const char *filename, int options) { + xmlParserCtxtPtr ctxt; xmlDocPtr doc; int ret = 1; + ctxt = xmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL); /* * In case of Namespace errors, libxml2 will still parse the document * but log a Namespace error. */ - doc = xmlReadFile(filename, NULL, options); + doc = xmlCtxtReadFile(ctxt, filename, NULL, options); if (doc == NULL) { test_log("test %s : %s failed to parse the XML\n", id, filename); @@ -271,15 +275,19 @@ xmlconfTestNotNSWF(const char *id, const char *filename, int options) { } xmlFreeDoc(doc); } + xmlFreeParserCtxt(ctxt); return(ret); } static int xmlconfTestNotWF(const char *id, const char *filename, int options) { + xmlParserCtxtPtr ctxt; xmlDocPtr doc; int ret = 1; - doc = xmlReadFile(filename, NULL, options); + ctxt = xmlNewParserCtxt(); + xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL); + doc = xmlCtxtReadFile(ctxt, filename, NULL, options); if (doc != NULL) { test_log("test %s : %s failed to detect not well formedness\n", id, filename); @@ -287,6 +295,7 @@ xmlconfTestNotWF(const char *id, const char *filename, int options) { xmlFreeDoc(doc); ret = 0; } + xmlFreeParserCtxt(ctxt); return(ret); } @@ -416,7 +425,6 @@ xmlconfTestItem(xmlDocPtr doc, xmlNodePtr cur) { test_log("test %s : %s leaked %d bytes\n", id, filename, final - mem); nb_leaks++; - xmlMemDisplayLast(logfile, final - mem); } nb_tests++; diff --git a/schematron.c b/schematron.c index a825920..1de25de 100644 --- a/schematron.c +++ b/schematron.c @@ -63,16 +63,6 @@ static const xmlChar *xmlOldSchematronNs = SCT_OLD_NS; node = node->next; \ } -/** - * TODO: - * - * macro to flag unimplemented blocks - */ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - typedef enum { XML_SCHEMATRON_ASSERT=1, XML_SCHEMATRON_REPORT=2 @@ -242,13 +232,11 @@ struct _xmlSchematronParserCtxt { * Handle an out of memory condition */ static void -xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt, - const char *extra, xmlNodePtr node) +xmlSchematronPErrMemory(xmlSchematronParserCtxtPtr ctxt) { if (ctxt != NULL) ctxt->nberrors++; - __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL, - extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASP, NULL); } /** @@ -269,6 +257,7 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error, xmlGenericErrorFunc channel = NULL; xmlStructuredErrorFunc schannel = NULL; void *data = NULL; + int res; if (ctxt != NULL) { ctxt->nberrors++; @@ -276,10 +265,18 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error, data = ctxt->userData; schannel = ctxt->serror; } - __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, - error, XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, str1, str2); + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + res = __xmlRaiseError(schannel, channel, data, ctxt, node, + XML_FROM_SCHEMASP, error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, (const char *) str2, NULL, 0, 0, + msg, str1, str2); + if (res < 0) + xmlSchematronPErrMemory(ctxt); } /** @@ -290,15 +287,53 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error, * Handle an out of memory condition */ static void -xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt, - const char *extra, xmlNodePtr node) +xmlSchematronVErrMemory(xmlSchematronValidCtxtPtr ctxt) { if (ctxt != NULL) { ctxt->nberrors++; ctxt->err = XML_SCHEMAV_INTERNAL; } - __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL, - extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_SCHEMASV, NULL); +} + +/** + * xmlSchematronVErr: + * @ctxt: the parsing context + * @node: the context node + * @error: the error code + * @msg: the error message + * @str1: extra data + * @str2: extra data + * + * Handle a validation error + */ +static void LIBXML_ATTR_FORMAT(3,0) +xmlSchematronVErr(xmlSchematronValidCtxtPtr ctxt, int error, + const char *msg, const xmlChar * str1) +{ + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + int res; + + if (ctxt != NULL) { + ctxt->nberrors++; + channel = ctxt->error; + data = ctxt->userData; + schannel = ctxt->serror; + } + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + res = __xmlRaiseError(schannel, channel, data, ctxt, NULL, + XML_FROM_SCHEMASV, error, XML_ERR_ERROR, NULL, 0, + (const char *) str1, NULL, NULL, 0, 0, + msg, str1); + if (res < 0) + xmlSchematronVErrMemory(ctxt); } /************************************************************************ @@ -347,7 +382,7 @@ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt, ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest)); if (ret == NULL) { - xmlSchematronPErrMemory(ctxt, "allocating schema test", node); + xmlSchematronPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchematronTest)); @@ -451,7 +486,7 @@ xmlSchematronAddRule(xmlSchematronParserCtxtPtr ctxt, xmlSchematronPtr schema, ret = (xmlSchematronRulePtr) xmlMalloc(sizeof(xmlSchematronRule)); if (ret == NULL) { - xmlSchematronPErrMemory(ctxt, "allocating schema rule", node); + xmlSchematronPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchematronRule)); @@ -532,7 +567,7 @@ xmlSchematronAddPattern(xmlSchematronParserCtxtPtr ctxt, ret = (xmlSchematronPatternPtr) xmlMalloc(sizeof(xmlSchematronPattern)); if (ret == NULL) { - xmlSchematronPErrMemory(ctxt, "allocating schema pattern", node); + xmlSchematronPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchematronPattern)); @@ -584,7 +619,7 @@ xmlSchematronNewSchematron(xmlSchematronParserCtxtPtr ctxt) ret = (xmlSchematronPtr) xmlMalloc(sizeof(xmlSchematron)); if (ret == NULL) { - xmlSchematronPErrMemory(ctxt, "allocating schema", NULL); + xmlSchematronPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchematron)); @@ -639,8 +674,7 @@ xmlSchematronNewParserCtxt(const char *URL) (xmlSchematronParserCtxtPtr) xmlMalloc(sizeof(xmlSchematronParserCtxt)); if (ret == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser context", - NULL); + xmlSchematronPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchematronParserCtxt)); @@ -650,8 +684,7 @@ xmlSchematronNewParserCtxt(const char *URL) ret->includes = NULL; ret->xctxt = xmlXPathNewContext(NULL); if (ret->xctxt == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", - NULL); + xmlSchematronPErrMemory(NULL); xmlSchematronFreeParserCtxt(ret); return (NULL); } @@ -681,8 +714,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size) (xmlSchematronParserCtxtPtr) xmlMalloc(sizeof(xmlSchematronParserCtxt)); if (ret == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser context", - NULL); + xmlSchematronPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchematronParserCtxt)); @@ -691,8 +723,7 @@ xmlSchematronNewMemParserCtxt(const char *buffer, int size) ret->dict = xmlDictCreate(); ret->xctxt = xmlXPathNewContext(NULL); if (ret->xctxt == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", - NULL); + xmlSchematronPErrMemory(NULL); xmlSchematronFreeParserCtxt(ret); return (NULL); } @@ -720,8 +751,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc) (xmlSchematronParserCtxtPtr) xmlMalloc(sizeof(xmlSchematronParserCtxt)); if (ret == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser context", - NULL); + xmlSchematronPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchematronParserCtxt)); @@ -731,8 +761,7 @@ xmlSchematronNewDocParserCtxt(xmlDocPtr doc) ret->preserve = 1; ret->xctxt = xmlXPathNewContext(doc); if (ret->xctxt == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", - NULL); + xmlSchematronPErrMemory(NULL); xmlSchematronFreeParserCtxt(ret); return (NULL); } @@ -780,8 +809,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt, ctxt->includes = (xmlNodePtr *) xmlMalloc(ctxt->maxIncludes * 2 * sizeof(xmlNodePtr)); if (ctxt->includes == NULL) { - xmlSchematronPErrMemory(NULL, "allocating parser includes", - NULL); + xmlSchematronPErrMemory(NULL); return; } ctxt->nbIncludes = 0; @@ -792,8 +820,7 @@ xmlSchematronPushInclude(xmlSchematronParserCtxtPtr ctxt, xmlRealloc(ctxt->includes, ctxt->maxIncludes * 4 * sizeof(xmlNodePtr)); if (tmp == NULL) { - xmlSchematronPErrMemory(NULL, "allocating parser includes", - NULL); + xmlSchematronPErrMemory(NULL); return; } ctxt->includes = tmp; @@ -850,8 +877,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt, ctxt->namespaces = (const xmlChar **) xmlMalloc(ctxt->maxNamespaces * 2 * sizeof(const xmlChar *)); if (ctxt->namespaces == NULL) { - xmlSchematronPErrMemory(NULL, "allocating parser namespaces", - NULL); + xmlSchematronPErrMemory(NULL); return; } ctxt->nbNamespaces = 0; @@ -862,8 +888,7 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt, xmlRealloc((xmlChar **) ctxt->namespaces, ctxt->maxNamespaces * 4 * sizeof(const xmlChar *)); if (tmp == NULL) { - xmlSchematronPErrMemory(NULL, "allocating parser namespaces", - NULL); + xmlSchematronPErrMemory(NULL); return; } ctxt->namespaces = tmp; @@ -1493,9 +1518,6 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt, ret = xmlStrcat(ret, spacer); ret = xmlStrcat(ret, eval->nodesetval->nodeTab[indx]->name); } - } else { - xmlGenericError(xmlGenericErrorContext, - "Empty node set\n"); } break; } @@ -1521,8 +1543,8 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt, ret = xmlStrcat(ret, eval->stringval); break; default: - xmlGenericError(xmlGenericErrorContext, - "Unsupported XPATH Type: %d\n", eval->type); + xmlSchematronVErr(ctxt, XML_ERR_INTERNAL_ERROR, + "Unsupported XPATH Type\n", NULL); } xmlXPathFreeObject(eval); xmlXPathFreeCompExpr(comp); @@ -1581,7 +1603,7 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt, (test->type == XML_SCHEMATRON_REPORT)) return; if (ctxt->flags & XML_SCHEMATRON_OUT_XML) { - TODO + /* TODO */ } else { xmlChar *path; char msg[1000]; @@ -1612,26 +1634,33 @@ xmlSchematronReportSuccess(xmlSchematronValidCtxtPtr ctxt, line, (const char *) report); if (ctxt->flags & XML_SCHEMATRON_OUT_ERROR) { - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - void *data = NULL; - - if (ctxt != NULL) { - if (ctxt->serror != NULL) - schannel = ctxt->serror; - else - channel = ctxt->error; - data = ctxt->userData; + xmlStructuredErrorFunc schannel; + xmlGenericErrorFunc channel; + void *data; + int res; + + schannel = ctxt->serror; + channel = ctxt->error; + data = ctxt->userData; + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; } - __xmlRaiseError(schannel, channel, data, - NULL, cur, XML_FROM_SCHEMATRONV, - (test->type == XML_SCHEMATRON_ASSERT)?XML_SCHEMATRONV_ASSERT:XML_SCHEMATRONV_REPORT, - XML_ERR_ERROR, NULL, line, - (pattern == NULL)?NULL:((const char *) pattern->name), - (const char *) path, - (const char *) report, 0, 0, - "%s", msg); + res = __xmlRaiseError(schannel, channel, data, NULL, cur, + XML_FROM_SCHEMATRONV, + (test->type == XML_SCHEMATRON_ASSERT) ? + XML_SCHEMATRONV_ASSERT : + XML_SCHEMATRONV_REPORT, + XML_ERR_ERROR, NULL, line, + (pattern == NULL) ? + NULL : + (const char *) pattern->name, + (const char *) path, (const char *) report, 0, 0, + "%s", msg); + if (res < 0) + xmlSchematronVErrMemory(ctxt); } else { xmlSchematronReportOutput(ctxt, cur, &msg[0]); } @@ -1658,7 +1687,7 @@ xmlSchematronReportPattern(xmlSchematronValidCtxtPtr ctxt, if ((ctxt->flags & XML_SCHEMATRON_OUT_QUIET) || (ctxt->flags & XML_SCHEMATRON_OUT_ERROR)) /* Error gives pattern name as part of error */ return; if (ctxt->flags & XML_SCHEMATRON_OUT_XML) { - TODO + /* TODO */ } else { char msg[1000]; @@ -1713,8 +1742,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options) ret = (xmlSchematronValidCtxtPtr) xmlMalloc(sizeof(xmlSchematronValidCtxt)); if (ret == NULL) { - xmlSchematronVErrMemory(NULL, "allocating validation context", - NULL); + xmlSchematronVErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchematronValidCtxt)); @@ -1723,8 +1751,7 @@ xmlSchematronNewValidCtxt(xmlSchematronPtr schema, int options) ret->xctxt = xmlXPathNewContext(NULL); ret->flags = options; if (ret->xctxt == NULL) { - xmlSchematronPErrMemory(NULL, "allocating schema parser XPath context", - NULL); + xmlSchematronPErrMemory(NULL); xmlSchematronFreeValidCtxt(ret); return (NULL); } @@ -1870,7 +1897,9 @@ xmlSchematronRunTest(xmlSchematronValidCtxtPtr ctxt, * Returns -1 in case of errors, otherwise 0 */ static int -xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let, +xmlSchematronRegisterVariables(xmlSchematronValidCtxtPtr vctxt, + xmlXPathContextPtr ctxt, + xmlSchematronLetPtr let, xmlDocPtr instance, xmlNodePtr cur) { xmlXPathObjectPtr let_eval; @@ -1880,13 +1909,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let, while (let != NULL) { let_eval = xmlXPathCompiledEval(let->comp, ctxt); if (let_eval == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Evaluation of compiled expression failed\n"); + xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR, + "Evaluation of compiled expression failed\n", + NULL); return -1; } if(xmlXPathRegisterVariableNS(ctxt, let->name, NULL, let_eval)) { - xmlGenericError(xmlGenericErrorContext, - "Registering a let variable failed\n"); + xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR, + "Registering a let variable failed\n", NULL); return -1; } let = let->next; @@ -1904,12 +1934,14 @@ xmlSchematronRegisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let, * Returns -1 in case of errors, otherwise 0 */ static int -xmlSchematronUnregisterVariables(xmlXPathContextPtr ctxt, xmlSchematronLetPtr let) +xmlSchematronUnregisterVariables(xmlSchematronValidCtxtPtr vctxt, + xmlXPathContextPtr ctxt, + xmlSchematronLetPtr let) { while (let != NULL) { if (xmlXPathRegisterVariableNS(ctxt, let->name, NULL, NULL)) { - xmlGenericError(xmlGenericErrorContext, - "Unregistering a let variable failed\n"); + xmlSchematronVErr(vctxt, XML_ERR_INTERNAL_ERROR, + "Unregistering a let variable failed\n", NULL); return -1; } let = let->next; @@ -1941,7 +1973,7 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance) ctxt->nberrors = 0; root = xmlDocGetRootElement(instance); if (root == NULL) { - TODO + /* TODO */ ctxt->nberrors++; return(1); } @@ -1958,7 +1990,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance) if (xmlPatternMatch(rule->pattern, cur) == 1) { test = rule->tests; - if (xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets, instance, cur)) + if (xmlSchematronRegisterVariables(ctxt, ctxt->xctxt, + rule->lets, instance, cur)) return -1; while (test != NULL) { @@ -1966,7 +1999,8 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance) test = test->next; } - if (xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets)) + if (xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt, + rule->lets)) return -1; } @@ -1996,15 +2030,16 @@ xmlSchematronValidateDoc(xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance) while (rule != NULL) { if (xmlPatternMatch(rule->pattern, cur) == 1) { test = rule->tests; - xmlSchematronRegisterVariables(ctxt->xctxt, rule->lets, - instance, cur); + xmlSchematronRegisterVariables(ctxt, ctxt->xctxt, + rule->lets, instance, cur); while (test != NULL) { xmlSchematronRunTest(ctxt, test, instance, cur, pattern); test = test->next; } - xmlSchematronUnregisterVariables(ctxt->xctxt, rule->lets); + xmlSchematronUnregisterVariables(ctxt, ctxt->xctxt, + rule->lets); } rule = rule->patnext; } diff --git a/testapi.c b/testapi.c index 0a0aadf..d85e560 100644 --- a/testapi.c +++ b/testapi.c @@ -207,12 +207,6 @@ int main(int argc, char **argv) { #include #include -/* - We manually define xmlErrMemory because it's normal declaration - is "hidden" by #ifdef IN_LIBXML -*/ -void xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra); - /* We need some "remote" addresses, but want to avoid getting into name resolution delays, so we use these @@ -229,17 +223,6 @@ static void *gen_void_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { static void des_void_ptr(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { } -#if 0 -#define gen_nb_const_void_ptr 2 - -static const void *gen_const_void_ptr(int no, int nr ATTRIBUTE_UNUSED) { - if (no == 0) return((const void *) "immutable string"); - return(NULL); -} -static void des_const_void_ptr(int no ATTRIBUTE_UNUSED, const void *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { -} -#endif - #define gen_nb_userdata 3 static void *gen_userdata(int no, int nr ATTRIBUTE_UNUSED) { @@ -372,7 +355,7 @@ static void des_int_ptr(int no ATTRIBUTE_UNUSED, int *val ATTRIBUTE_UNUSED, int #define gen_nb_const_char_ptr 4 -static char *gen_const_char_ptr(int no, int nr ATTRIBUTE_UNUSED) { +static const char *gen_const_char_ptr(int no, int nr ATTRIBUTE_UNUSED) { if (no == 0) return((char *) "foo"); if (no == 1) return((char *) ""); if (no == 2) return((char *) "test/ent2"); @@ -412,7 +395,7 @@ static void des_debug_FILE_ptr(int no ATTRIBUTE_UNUSED, FILE *val, int nr ATTRIB #define gen_nb_const_xmlChar_ptr 5 -static xmlChar *gen_const_xmlChar_ptr(int no, int nr ATTRIBUTE_UNUSED) { +static const xmlChar *gen_const_xmlChar_ptr(int no, int nr ATTRIBUTE_UNUSED) { if (no == 0) return((xmlChar *) "foo"); if (no == 1) return((xmlChar *) ""); if (no == 2) return((xmlChar *) "n" "\xf8" "ne"); @@ -885,7 +868,8 @@ static void desret_xmlNanoHTTPCtxtPtr(void *val) { #endif /* cut and pasted from autogenerated to avoid troubles */ #define gen_nb_const_xmlChar_ptr_ptr 1 -static xmlChar ** gen_const_xmlChar_ptr_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { +static const xmlChar ** +gen_const_xmlChar_ptr_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { return(NULL); } static void des_const_xmlChar_ptr_ptr(int no ATTRIBUTE_UNUSED, const xmlChar ** val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { @@ -899,21 +883,13 @@ static void des_unsigned_char_ptr(int no ATTRIBUTE_UNUSED, unsigned char * val A } #define gen_nb_const_unsigned_char_ptr 1 -static unsigned char * gen_const_unsigned_char_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { +static const unsigned char * +gen_const_unsigned_char_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { return(NULL); } static void des_const_unsigned_char_ptr(int no ATTRIBUTE_UNUSED, const unsigned char * val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { } -#ifdef LIBXML_HTML_ENABLED -#define gen_nb_const_htmlNodePtr 1 -static htmlNodePtr gen_const_htmlNodePtr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { - return(NULL); -} -static void des_const_htmlNodePtr(int no ATTRIBUTE_UNUSED, const htmlNodePtr val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { -} -#endif - #ifdef LIBXML_HTML_ENABLED #define gen_nb_htmlDocPtr 3 static htmlDocPtr gen_htmlDocPtr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { @@ -1007,6 +983,13 @@ static void des_void_ptr_ptr(int no ATTRIBUTE_UNUSED, void ** val ATTRIBUTE_UNUS } #endif +#define gen_nb_xmlParserInputPtr 1 +static xmlParserInputPtr gen_xmlParserInputPtr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { + return(NULL); +} +static void des_xmlParserInputPtr(int no ATTRIBUTE_UNUSED, xmlParserInputPtr val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { +} + /************************************************************************ * * * WARNING: end of the manually maintained part of the test code * @@ -1313,7 +1296,7 @@ test_UTF8ToHtml(void) { int n_out; int * outlen; /* the length of @out */ int n_outlen; - unsigned char * in; /* a pointer to an array of UTF-8 chars */ + const unsigned char * in; /* a pointer to an array of UTF-8 chars */ int n_in; int * inlen; /* the length of @in */ int n_inlen; @@ -1328,12 +1311,12 @@ test_UTF8ToHtml(void) { in = gen_const_unsigned_char_ptr(n_in, 2); inlen = gen_int_ptr(n_inlen, 3); - ret_val = UTF8ToHtml(out, outlen, (const unsigned char *)in, inlen); + ret_val = UTF8ToHtml(out, outlen, in, inlen); desret_int(ret_val); call_tests++; des_unsigned_char_ptr(n_out, out, 0); des_int_ptr(n_outlen, outlen, 1); - des_const_unsigned_char_ptr(n_in, (const unsigned char *)in, 2); + des_const_unsigned_char_ptr(n_in, in, 2); des_int_ptr(n_inlen, inlen, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1371,9 +1354,9 @@ test_htmlAttrAllowed(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlStatus ret_val; - htmlElemDesc * elt; /* HTML element */ + const htmlElemDesc * elt; /* HTML element */ int n_elt; - xmlChar * attr; /* HTML attribute */ + const xmlChar * attr; /* HTML attribute */ int n_attr; int legacy; /* whether to allow deprecated attributes */ int n_legacy; @@ -1386,11 +1369,11 @@ test_htmlAttrAllowed(void) { attr = gen_const_xmlChar_ptr(n_attr, 1); legacy = gen_int(n_legacy, 2); - ret_val = htmlAttrAllowed((const htmlElemDesc *)elt, (const xmlChar *)attr, legacy); + ret_val = htmlAttrAllowed(elt, attr, legacy); desret_htmlStatus(ret_val); call_tests++; - des_const_htmlElemDesc_ptr(n_elt, (const htmlElemDesc *)elt, 0); - des_const_xmlChar_ptr(n_attr, (const xmlChar *)attr, 1); + des_const_htmlElemDesc_ptr(n_elt, elt, 0); + des_const_xmlChar_ptr(n_attr, attr, 1); des_int(n_legacy, legacy, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1428,7 +1411,7 @@ test_htmlAutoCloseTag(void) { int ret_val; htmlDocPtr doc; /* the HTML document */ int n_doc; - xmlChar * name; /* The tag name */ + const xmlChar * name; /* The tag name */ int n_name; htmlNodePtr elem; /* the HTML element */ int n_elem; @@ -1441,11 +1424,11 @@ test_htmlAutoCloseTag(void) { name = gen_const_xmlChar_ptr(n_name, 1); elem = gen_htmlNodePtr(n_elem, 2); - ret_val = htmlAutoCloseTag(doc, (const xmlChar *)name, elem); + ret_val = htmlAutoCloseTag(doc, name, elem); desret_int(ret_val); call_tests++; des_htmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_htmlNodePtr(n_elem, elem, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1476,7 +1459,7 @@ test_htmlCreateFileParserCtxt(void) { htmlParserCtxtPtr ret_val; const char * filename; /* the filename */ int n_filename; - char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ + const char * encoding; /* optional encoding */ int n_encoding; for (n_filename = 0;n_filename < gen_nb_fileoutput;n_filename++) { @@ -1485,11 +1468,11 @@ test_htmlCreateFileParserCtxt(void) { filename = gen_fileoutput(n_filename, 0); encoding = gen_const_char_ptr(n_encoding, 1); - ret_val = htmlCreateFileParserCtxt(filename, (const char *)encoding); + ret_val = htmlCreateFileParserCtxt(filename, encoding); desret_htmlParserCtxtPtr(ret_val); call_tests++; des_fileoutput(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlCreateFileParserCtxt", @@ -1515,7 +1498,7 @@ test_htmlCreateMemoryParserCtxt(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlParserCtxtPtr ret_val; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -1529,10 +1512,10 @@ test_htmlCreateMemoryParserCtxt(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = htmlCreateMemoryParserCtxt((const char *)buffer, size); + ret_val = htmlCreateMemoryParserCtxt(buffer, size); desret_htmlParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1566,17 +1549,17 @@ test_htmlCreatePushParserCtxt(void) { #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_PUSH_ENABLED) int mem_base; htmlParserCtxtPtr ret_val; - htmlSAXHandlerPtr sax; /* a SAX handler */ + htmlSAXHandlerPtr sax; /* a SAX handler (optional) */ int n_sax; - void * user_data; /* The user data returned on SAX callbacks */ + void * user_data; /* The user data returned on SAX callbacks (optional) */ int n_user_data; - char * chunk; /* a pointer to an array of chars */ + const char * chunk; /* a pointer to an array of chars (optional) */ int n_chunk; int size; /* number of chars in the array */ int n_size; - const char * filename; /* an optional file name or URI */ + const char * filename; /* only used for error reporting (optional) */ int n_filename; - xmlCharEncoding enc; /* an optional encoding */ + xmlCharEncoding enc; /* encoding (deprecated, pass XML_CHAR_ENCODING_NONE) */ int n_enc; for (n_sax = 0;n_sax < gen_nb_htmlSAXHandlerPtr;n_sax++) { @@ -1596,12 +1579,12 @@ test_htmlCreatePushParserCtxt(void) { (size > xmlStrlen(BAD_CAST chunk))) size = 0; - ret_val = htmlCreatePushParserCtxt(sax, user_data, (const char *)chunk, size, filename, enc); + ret_val = htmlCreatePushParserCtxt(sax, user_data, chunk, size, filename, enc); desret_htmlParserCtxtPtr(ret_val); call_tests++; des_htmlSAXHandlerPtr(n_sax, sax, 0); des_userdata(n_user_data, user_data, 1); - des_const_char_ptr(n_chunk, (const char *)chunk, 2); + des_const_char_ptr(n_chunk, chunk, 2); des_int(n_size, size, 3); des_fileoutput(n_filename, filename, 4); des_xmlCharEncoding(n_enc, enc, 5); @@ -1631,6 +1614,47 @@ test_htmlCreatePushParserCtxt(void) { } +static int +test_htmlCtxtParseDocument(void) { + int test_ret = 0; + +#if defined(LIBXML_HTML_ENABLED) + int mem_base; + htmlDocPtr ret_val; + htmlParserCtxtPtr ctxt; /* an HTML parser context */ + int n_ctxt; + xmlParserInputPtr input; /* parser input */ + int n_input; + + for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) { + for (n_input = 0;n_input < gen_nb_xmlParserInputPtr;n_input++) { + mem_base = xmlMemBlocks(); + ctxt = gen_htmlParserCtxtPtr(n_ctxt, 0); + input = gen_xmlParserInputPtr(n_input, 1); + + ret_val = htmlCtxtParseDocument(ctxt, input); + desret_htmlDocPtr(ret_val); + call_tests++; + des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_xmlParserInputPtr(n_input, input, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in htmlCtxtParseDocument", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_input); + printf("\n"); + } + } + } + function_tests++; +#endif + + return(test_ret); +} + + static int test_htmlCtxtReadDoc(void) { int test_ret = 0; @@ -1640,34 +1664,34 @@ test_htmlCtxtReadDoc(void) { htmlDocPtr ret_val; htmlParserCtxtPtr ctxt; /* an HTML parser context */ int n_ctxt; - xmlChar * str; /* a pointer to a zero terminated string */ + const xmlChar * str; /* a pointer to a zero terminated string */ int n_str; - const char * URL; /* the base URL to use for the document */ + const char * URL; /* only used for error reporting (optional) */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; - int options; /* a combination of htmlParserOption(s) */ + int options; /* a combination of htmlParserOptions */ int n_options; for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) { for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { - for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) { + for (n_URL = 0;n_URL < gen_nb_const_char_ptr;n_URL++) { for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { for (n_options = 0;n_options < gen_nb_int;n_options++) { mem_base = xmlMemBlocks(); ctxt = gen_htmlParserCtxtPtr(n_ctxt, 0); str = gen_const_xmlChar_ptr(n_str, 1); - URL = gen_filepath(n_URL, 2); + URL = gen_const_char_ptr(n_URL, 2); encoding = gen_const_char_ptr(n_encoding, 3); options = gen_int(n_options, 4); - ret_val = htmlCtxtReadDoc(ctxt, (const xmlChar *)str, URL, (const char *)encoding, options); + ret_val = htmlCtxtReadDoc(ctxt, str, URL, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); - des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_xmlChar_ptr(n_str, str, 1); + des_const_char_ptr(n_URL, URL, 2); + des_const_char_ptr(n_encoding, encoding, 3); des_int(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1703,9 +1727,9 @@ test_htmlCtxtReadFile(void) { int n_ctxt; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; - int options; /* a combination of htmlParserOption(s) */ + int options; /* a combination of htmlParserOptions */ int n_options; for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) { @@ -1717,12 +1741,12 @@ test_htmlCtxtReadFile(void) { encoding = gen_const_char_ptr(n_encoding, 2); options = gen_int(n_options, 3); - ret_val = htmlCtxtReadFile(ctxt, filename, (const char *)encoding, options); + ret_val = htmlCtxtReadFile(ctxt, filename, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); des_filepath(n_filename, filename, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_options, options, 3); xmlResetLastError(); } @@ -1745,42 +1769,42 @@ test_htmlCtxtReadMemory(void) { htmlDocPtr ret_val; htmlParserCtxtPtr ctxt; /* an HTML parser context */ int n_ctxt; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; - const char * URL; /* the base URL to use for the document */ + const char * URL; /* only used for error reporting (optional) */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optinal) */ int n_encoding; - int options; /* a combination of htmlParserOption(s) */ + int options; /* a combination of htmlParserOptions */ int n_options; for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) { for (n_buffer = 0;n_buffer < gen_nb_const_char_ptr;n_buffer++) { for (n_size = 0;n_size < gen_nb_int;n_size++) { - for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) { + for (n_URL = 0;n_URL < gen_nb_const_char_ptr;n_URL++) { for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { for (n_options = 0;n_options < gen_nb_int;n_options++) { mem_base = xmlMemBlocks(); ctxt = gen_htmlParserCtxtPtr(n_ctxt, 0); buffer = gen_const_char_ptr(n_buffer, 1); size = gen_int(n_size, 2); - URL = gen_filepath(n_URL, 3); + URL = gen_const_char_ptr(n_URL, 3); encoding = gen_const_char_ptr(n_encoding, 4); options = gen_int(n_options, 5); if ((buffer != NULL) && (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = htmlCtxtReadMemory(ctxt, (const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = htmlCtxtReadMemory(ctxt, buffer, size, URL, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_char_ptr(n_buffer, (const char *)buffer, 1); + des_const_char_ptr(n_buffer, buffer, 1); des_int(n_size, size, 2); - des_filepath(n_URL, URL, 3); - des_const_char_ptr(n_encoding, (const char *)encoding, 4); + des_const_char_ptr(n_URL, URL, 3); + des_const_char_ptr(n_encoding, encoding, 4); des_int(n_options, options, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -1888,9 +1912,9 @@ test_htmlElementAllowedHere(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; int ret_val; - htmlElemDesc * parent; /* HTML parent element */ + const htmlElemDesc * parent; /* HTML parent element */ int n_parent; - xmlChar * elt; /* HTML element */ + const xmlChar * elt; /* HTML element */ int n_elt; for (n_parent = 0;n_parent < gen_nb_const_htmlElemDesc_ptr;n_parent++) { @@ -1899,11 +1923,11 @@ test_htmlElementAllowedHere(void) { parent = gen_const_htmlElemDesc_ptr(n_parent, 0); elt = gen_const_xmlChar_ptr(n_elt, 1); - ret_val = htmlElementAllowedHere((const htmlElemDesc *)parent, (const xmlChar *)elt); + ret_val = htmlElementAllowedHere(parent, elt); desret_int(ret_val); call_tests++; - des_const_htmlElemDesc_ptr(n_parent, (const htmlElemDesc *)parent, 0); - des_const_xmlChar_ptr(n_elt, (const xmlChar *)elt, 1); + des_const_htmlElemDesc_ptr(n_parent, parent, 0); + des_const_xmlChar_ptr(n_elt, elt, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlElementAllowedHere", @@ -1929,9 +1953,9 @@ test_htmlElementStatusHere(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlStatus ret_val; - htmlElemDesc * parent; /* HTML parent element */ + const htmlElemDesc * parent; /* HTML parent element */ int n_parent; - htmlElemDesc * elt; /* HTML element */ + const htmlElemDesc * elt; /* HTML element */ int n_elt; for (n_parent = 0;n_parent < gen_nb_const_htmlElemDesc_ptr;n_parent++) { @@ -1940,11 +1964,11 @@ test_htmlElementStatusHere(void) { parent = gen_const_htmlElemDesc_ptr(n_parent, 0); elt = gen_const_htmlElemDesc_ptr(n_elt, 1); - ret_val = htmlElementStatusHere((const htmlElemDesc *)parent, (const htmlElemDesc *)elt); + ret_val = htmlElementStatusHere(parent, elt); desret_htmlStatus(ret_val); call_tests++; - des_const_htmlElemDesc_ptr(n_parent, (const htmlElemDesc *)parent, 0); - des_const_htmlElemDesc_ptr(n_elt, (const htmlElemDesc *)elt, 1); + des_const_htmlElemDesc_ptr(n_parent, parent, 0); + des_const_htmlElemDesc_ptr(n_elt, elt, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlElementStatusHere", @@ -1974,7 +1998,7 @@ test_htmlEncodeEntities(void) { int n_out; int * outlen; /* the length of @out */ int n_outlen; - unsigned char * in; /* a pointer to an array of UTF-8 chars */ + const unsigned char * in; /* a pointer to an array of UTF-8 chars */ int n_in; int * inlen; /* the length of @in */ int n_inlen; @@ -1993,12 +2017,12 @@ test_htmlEncodeEntities(void) { inlen = gen_int_ptr(n_inlen, 3); quoteChar = gen_int(n_quoteChar, 4); - ret_val = htmlEncodeEntities(out, outlen, (const unsigned char *)in, inlen, quoteChar); + ret_val = htmlEncodeEntities(out, outlen, in, inlen, quoteChar); desret_int(ret_val); call_tests++; des_unsigned_char_ptr(n_out, out, 0); des_int_ptr(n_outlen, outlen, 1); - des_const_unsigned_char_ptr(n_in, (const unsigned char *)in, 2); + des_const_unsigned_char_ptr(n_in, in, 2); des_int_ptr(n_inlen, inlen, 3); des_int(n_quoteChar, quoteChar, 4); xmlResetLastError(); @@ -2032,17 +2056,17 @@ test_htmlEntityLookup(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; const htmlEntityDesc * ret_val; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_xmlChar_ptr(n_name, 0); - ret_val = htmlEntityLookup((const xmlChar *)name); + ret_val = htmlEntityLookup(name); desret_const_htmlEntityDesc_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlEntityLookup", @@ -2200,17 +2224,17 @@ test_htmlIsScriptAttribute(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; int ret_val; - xmlChar * name; /* an attribute name */ + const xmlChar * name; /* an attribute name */ int n_name; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_xmlChar_ptr(n_name, 0); - ret_val = htmlIsScriptAttribute((const xmlChar *)name); + ret_val = htmlIsScriptAttribute(name); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlIsScriptAttribute", @@ -2268,7 +2292,7 @@ test_htmlNewSAXParserCtxt(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlParserCtxtPtr ret_val; - htmlSAXHandler * sax; /* SAX handler */ + const htmlSAXHandler * sax; /* SAX handler */ int n_sax; void * userData; /* user data */ int n_userData; @@ -2279,10 +2303,10 @@ test_htmlNewSAXParserCtxt(void) { sax = gen_const_htmlSAXHandler_ptr(n_sax, 0); userData = gen_userdata(n_userData, 1); - ret_val = htmlNewSAXParserCtxt((const htmlSAXHandler *)sax, userData); + ret_val = htmlNewSAXParserCtxt(sax, userData); desret_htmlParserCtxtPtr(ret_val); call_tests++; - des_const_htmlSAXHandler_ptr(n_sax, (const htmlSAXHandler *)sax, 0); + des_const_htmlSAXHandler_ptr(n_sax, sax, 0); des_userdata(n_userData, userData, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -2314,16 +2338,16 @@ test_htmlNodeStatus(void) { int legacy; /* whether to allow deprecated elements (YES is faster here for Element nodes) */ int n_legacy; - for (n_node = 0;n_node < gen_nb_const_htmlNodePtr;n_node++) { + for (n_node = 0;n_node < gen_nb_htmlNodePtr;n_node++) { for (n_legacy = 0;n_legacy < gen_nb_int;n_legacy++) { mem_base = xmlMemBlocks(); - node = gen_const_htmlNodePtr(n_node, 0); + node = gen_htmlNodePtr(n_node, 0); legacy = gen_int(n_legacy, 1); - ret_val = htmlNodeStatus((const htmlNodePtr)node, legacy); + ret_val = htmlNodeStatus(node, legacy); desret_htmlStatus(ret_val); call_tests++; - des_const_htmlNodePtr(n_node, (const htmlNodePtr)node, 0); + des_htmlNodePtr(n_node, node, 0); des_int(n_legacy, legacy, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -2386,9 +2410,9 @@ test_htmlParseChunk(void) { int ret_val; htmlParserCtxtPtr ctxt; /* an HTML parser context */ int n_ctxt; - char * chunk; /* an char array */ + const char * chunk; /* chunk of memory */ int n_chunk; - int size; /* the size in byte of the chunk */ + int size; /* size of chunk in bytes */ int n_size; int terminate; /* last chunk indicator */ int n_terminate; @@ -2406,12 +2430,12 @@ test_htmlParseChunk(void) { (size > xmlStrlen(BAD_CAST chunk))) size = 0; - ret_val = htmlParseChunk(ctxt, (const char *)chunk, size, terminate); + ret_val = htmlParseChunk(ctxt, chunk, size, terminate); if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} desret_int(ret_val); call_tests++; des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_char_ptr(n_chunk, (const char *)chunk, 1); + des_const_char_ptr(n_chunk, chunk, 1); des_int(n_size, size, 2); des_int(n_terminate, terminate, 3); xmlResetLastError(); @@ -2443,9 +2467,9 @@ test_htmlParseDoc(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - xmlChar * cur; /* a pointer to an array of xmlChar */ + const xmlChar * cur; /* a pointer to an array of xmlChar */ int n_cur; - char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ + const char * encoding; /* the encoding (optional) */ int n_encoding; for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) { @@ -2454,11 +2478,11 @@ test_htmlParseDoc(void) { cur = gen_const_xmlChar_ptr(n_cur, 0); encoding = gen_const_char_ptr(n_encoding, 1); - ret_val = htmlParseDoc((const xmlChar *)cur, (const char *)encoding); + ret_val = htmlParseDoc(cur, encoding); desret_htmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_xmlChar_ptr(n_cur, cur, 0); + des_const_char_ptr(n_encoding, encoding, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlParseDoc", @@ -2553,7 +2577,7 @@ test_htmlParseEntityRef(void) { const htmlEntityDesc * ret_val; htmlParserCtxtPtr ctxt; /* an HTML parser context */ int n_ctxt; - xmlChar ** str; /* location to store the entity name */ + const xmlChar ** str; /* location to store the entity name */ int n_str; for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) { @@ -2562,11 +2586,11 @@ test_htmlParseEntityRef(void) { ctxt = gen_htmlParserCtxtPtr(n_ctxt, 0); str = gen_const_xmlChar_ptr_ptr(n_str, 1); - ret_val = htmlParseEntityRef(ctxt, (const xmlChar **)str); + ret_val = htmlParseEntityRef(ctxt, str); desret_const_htmlEntityDesc_ptr(ret_val); call_tests++; des_htmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr_ptr(n_str, (const xmlChar **)str, 1); + des_const_xmlChar_ptr_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlParseEntityRef", @@ -2593,7 +2617,7 @@ test_htmlParseFile(void) { htmlDocPtr ret_val; const char * filename; /* the filename */ int n_filename; - char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ + const char * encoding; /* encoding (optional) */ int n_encoding; for (n_filename = 0;n_filename < gen_nb_filepath;n_filename++) { @@ -2601,11 +2625,11 @@ test_htmlParseFile(void) { filename = gen_filepath(n_filename, 0); encoding = gen_const_char_ptr(n_encoding, 1); - ret_val = htmlParseFile(filename, (const char *)encoding); + ret_val = htmlParseFile(filename, encoding); desret_htmlDocPtr(ret_val); call_tests++; des_filepath(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); xmlResetLastError(); } } @@ -2623,39 +2647,39 @@ test_htmlReadDoc(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - xmlChar * cur; /* a pointer to a zero terminated string */ - int n_cur; - const char * URL; /* the base URL to use for the document */ - int n_URL; - char * encoding; /* the document encoding, or NULL */ + const xmlChar * str; /* a pointer to a zero terminated string */ + int n_str; + const char * url; /* only used for error reporting (optoinal) */ + int n_url; + const char * encoding; /* the document encoding (optional) */ int n_encoding; - int options; /* a combination of htmlParserOption(s) */ + int options; /* a combination of htmlParserOptions */ int n_options; - for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) { - for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) { + for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { + for (n_url = 0;n_url < gen_nb_const_char_ptr;n_url++) { for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { for (n_options = 0;n_options < gen_nb_int;n_options++) { mem_base = xmlMemBlocks(); - cur = gen_const_xmlChar_ptr(n_cur, 0); - URL = gen_filepath(n_URL, 1); + str = gen_const_xmlChar_ptr(n_str, 0); + url = gen_const_char_ptr(n_url, 1); encoding = gen_const_char_ptr(n_encoding, 2); options = gen_int(n_options, 3); - ret_val = htmlReadDoc((const xmlChar *)cur, URL, (const char *)encoding, options); + ret_val = htmlReadDoc(str, url, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); - des_filepath(n_URL, URL, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_xmlChar_ptr(n_str, str, 0); + des_const_char_ptr(n_url, url, 1); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_options, options, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlReadDoc", xmlMemBlocks() - mem_base); test_ret++; - printf(" %d", n_cur); - printf(" %d", n_URL); + printf(" %d", n_str); + printf(" %d", n_url); printf(" %d", n_encoding); printf(" %d", n_options); printf("\n"); @@ -2680,9 +2704,9 @@ test_htmlReadFile(void) { htmlDocPtr ret_val; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; - int options; /* a combination of htmlParserOption(s) */ + int options; /* a combination of htmlParserOptions */ int n_options; for (n_filename = 0;n_filename < gen_nb_filepath;n_filename++) { @@ -2693,11 +2717,11 @@ test_htmlReadFile(void) { encoding = gen_const_char_ptr(n_encoding, 1); options = gen_int(n_options, 2); - ret_val = htmlReadFile(filename, (const char *)encoding, options); + ret_val = htmlReadFile(filename, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; des_filepath(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); des_int(n_options, options, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -2726,39 +2750,39 @@ test_htmlReadMemory(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; - const char * URL; /* the base URL to use for the document */ - int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * url; /* only used for error reporting (optional) */ + int n_url; + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of htmlParserOption(s) */ int n_options; for (n_buffer = 0;n_buffer < gen_nb_const_char_ptr;n_buffer++) { for (n_size = 0;n_size < gen_nb_int;n_size++) { - for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) { + for (n_url = 0;n_url < gen_nb_const_char_ptr;n_url++) { for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { for (n_options = 0;n_options < gen_nb_int;n_options++) { mem_base = xmlMemBlocks(); buffer = gen_const_char_ptr(n_buffer, 0); size = gen_int(n_size, 1); - URL = gen_filepath(n_URL, 2); + url = gen_const_char_ptr(n_url, 2); encoding = gen_const_char_ptr(n_encoding, 3); options = gen_int(n_options, 4); if ((buffer != NULL) && (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = htmlReadMemory((const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = htmlReadMemory(buffer, size, url, encoding, options); desret_htmlDocPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); - des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_url, url, 2); + des_const_char_ptr(n_encoding, encoding, 3); des_int(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -2767,7 +2791,7 @@ test_htmlReadMemory(void) { test_ret++; printf(" %d", n_buffer); printf(" %d", n_size); - printf(" %d", n_URL); + printf(" %d", n_url); printf(" %d", n_encoding); printf(" %d", n_options); printf("\n"); @@ -2791,9 +2815,9 @@ test_htmlSAXParseDoc(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - xmlChar * cur; /* a pointer to an array of xmlChar */ + const xmlChar * cur; /* a pointer to an array of xmlChar */ int n_cur; - char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ + const char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ int n_encoding; htmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; @@ -2810,11 +2834,11 @@ test_htmlSAXParseDoc(void) { sax = gen_htmlSAXHandlerPtr(n_sax, 2); userData = gen_userdata(n_userData, 3); - ret_val = htmlSAXParseDoc((const xmlChar *)cur, (const char *)encoding, sax, userData); + ret_val = htmlSAXParseDoc(cur, encoding, sax, userData); desret_htmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_xmlChar_ptr(n_cur, cur, 0); + des_const_char_ptr(n_encoding, encoding, 1); des_htmlSAXHandlerPtr(n_sax, sax, 2); des_userdata(n_userData, userData, 3); xmlResetLastError(); @@ -2848,7 +2872,7 @@ test_htmlSAXParseFile(void) { htmlDocPtr ret_val; const char * filename; /* the filename */ int n_filename; - char * encoding; /* a free form C string describing the HTML document encoding, or NULL */ + const char * encoding; /* encoding (optional) */ int n_encoding; htmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; @@ -2865,11 +2889,11 @@ test_htmlSAXParseFile(void) { sax = gen_htmlSAXHandlerPtr(n_sax, 2); userData = gen_userdata(n_userData, 3); - ret_val = htmlSAXParseFile(filename, (const char *)encoding, sax, userData); + ret_val = htmlSAXParseFile(filename, encoding, sax, userData); desret_htmlDocPtr(ret_val); call_tests++; des_filepath(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); des_htmlSAXHandlerPtr(n_sax, sax, 2); des_userdata(n_userData, userData, 3); xmlResetLastError(); @@ -2907,13 +2931,14 @@ static int test_HTMLparser(void) { int test_ret = 0; - if (quiet == 0) printf("Testing HTMLparser : 35 of 41 functions ...\n"); + if (quiet == 0) printf("Testing HTMLparser : 36 of 42 functions ...\n"); test_ret += test_UTF8ToHtml(); test_ret += test_htmlAttrAllowed(); test_ret += test_htmlAutoCloseTag(); test_ret += test_htmlCreateFileParserCtxt(); test_ret += test_htmlCreateMemoryParserCtxt(); test_ret += test_htmlCreatePushParserCtxt(); + test_ret += test_htmlCtxtParseDocument(); test_ret += test_htmlCtxtReadDoc(); test_ret += test_htmlCtxtReadFile(); test_ret += test_htmlCtxtReadMemory(); @@ -2960,7 +2985,7 @@ test_htmlDocContentDumpFormatOutput(void) { int n_buf; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the encoding string (unused) */ + const char * encoding; /* the encoding string (unused) */ int n_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -2975,11 +3000,11 @@ test_htmlDocContentDumpFormatOutput(void) { encoding = gen_const_char_ptr(n_encoding, 2); format = gen_int(n_format, 3); - htmlDocContentDumpFormatOutput(buf, cur, (const char *)encoding, format); + htmlDocContentDumpFormatOutput(buf, cur, encoding, format); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_format, format, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -3013,7 +3038,7 @@ test_htmlDocContentDumpOutput(void) { int n_buf; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the encoding string (unused) */ + const char * encoding; /* the encoding string (unused) */ int n_encoding; for (n_buf = 0;n_buf < gen_nb_xmlOutputBufferPtr;n_buf++) { @@ -3024,11 +3049,11 @@ test_htmlDocContentDumpOutput(void) { cur = gen_xmlDocPtr(n_cur, 1); encoding = gen_const_char_ptr(n_encoding, 2); - htmlDocContentDumpOutput(buf, cur, (const char *)encoding); + htmlDocContentDumpOutput(buf, cur, encoding); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlDocContentDumpOutput", @@ -3234,17 +3259,17 @@ test_htmlIsBooleanAttr(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; int ret_val; - xmlChar * name; /* the name of the attribute to check */ + const xmlChar * name; /* the name of the attribute to check */ int n_name; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_xmlChar_ptr(n_name, 0); - ret_val = htmlIsBooleanAttr((const xmlChar *)name); + ret_val = htmlIsBooleanAttr(name); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlIsBooleanAttr", @@ -3268,9 +3293,9 @@ test_htmlNewDoc(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - xmlChar * URI; /* URI for the dtd, or NULL */ + const xmlChar * URI; /* URI for the dtd, or NULL */ int n_URI; - xmlChar * ExternalID; /* the external ID of the DTD, or NULL */ + const xmlChar * ExternalID; /* the external ID of the DTD, or NULL */ int n_ExternalID; for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { @@ -3279,11 +3304,11 @@ test_htmlNewDoc(void) { URI = gen_const_xmlChar_ptr(n_URI, 0); ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 1); - ret_val = htmlNewDoc((const xmlChar *)URI, (const xmlChar *)ExternalID); + ret_val = htmlNewDoc(URI, ExternalID); desret_htmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 0); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 1); + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlNewDoc", @@ -3309,9 +3334,9 @@ test_htmlNewDocNoDtD(void) { #if defined(LIBXML_HTML_ENABLED) int mem_base; htmlDocPtr ret_val; - xmlChar * URI; /* URI for the dtd, or NULL */ + const xmlChar * URI; /* URI for the dtd, or NULL */ int n_URI; - xmlChar * ExternalID; /* the external ID of the DTD, or NULL */ + const xmlChar * ExternalID; /* the external ID of the DTD, or NULL */ int n_ExternalID; for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { @@ -3320,11 +3345,11 @@ test_htmlNewDocNoDtD(void) { URI = gen_const_xmlChar_ptr(n_URI, 0); ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 1); - ret_val = htmlNewDocNoDtD((const xmlChar *)URI, (const xmlChar *)ExternalID); + ret_val = htmlNewDocNoDtD(URI, ExternalID); desret_htmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 0); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 1); + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlNewDocNoDtD", @@ -3450,7 +3475,7 @@ test_htmlNodeDumpFileFormat(void) { int n_doc; xmlNodePtr cur; /* the current node */ int n_cur; - char * encoding; /* the document encoding */ + const char * encoding; /* the document encoding */ int n_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -3467,13 +3492,13 @@ test_htmlNodeDumpFileFormat(void) { encoding = gen_const_char_ptr(n_encoding, 3); format = gen_int(n_format, 4); - ret_val = htmlNodeDumpFileFormat(out, doc, cur, (const char *)encoding, format); + ret_val = htmlNodeDumpFileFormat(out, doc, cur, encoding, format); desret_int(ret_val); call_tests++; des_FILE_ptr(n_out, out, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_cur, cur, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_int(n_format, format, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -3511,7 +3536,7 @@ test_htmlNodeDumpFormatOutput(void) { int n_doc; xmlNodePtr cur; /* the current node */ int n_cur; - char * encoding; /* the encoding string (unused) */ + const char * encoding; /* the encoding string (unused) */ int n_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -3528,12 +3553,12 @@ test_htmlNodeDumpFormatOutput(void) { encoding = gen_const_char_ptr(n_encoding, 3); format = gen_int(n_format, 4); - htmlNodeDumpFormatOutput(buf, doc, cur, (const char *)encoding, format); + htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_cur, cur, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_int(n_format, format, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -3571,7 +3596,7 @@ test_htmlNodeDumpOutput(void) { int n_doc; xmlNodePtr cur; /* the current node */ int n_cur; - char * encoding; /* the encoding string (unused) */ + const char * encoding; /* the encoding string (unused) */ int n_encoding; for (n_buf = 0;n_buf < gen_nb_xmlOutputBufferPtr;n_buf++) { @@ -3584,12 +3609,12 @@ test_htmlNodeDumpOutput(void) { cur = gen_xmlNodePtr(n_cur, 2); encoding = gen_const_char_ptr(n_encoding, 3); - htmlNodeDumpOutput(buf, doc, cur, (const char *)encoding); + htmlNodeDumpOutput(buf, doc, cur, encoding); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_cur, cur, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlNodeDumpOutput", @@ -3664,7 +3689,7 @@ test_htmlSaveFileEnc(void) { int n_filename; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the document encoding */ + const char * encoding; /* the document encoding */ int n_encoding; for (n_filename = 0;n_filename < gen_nb_fileoutput;n_filename++) { @@ -3675,12 +3700,12 @@ test_htmlSaveFileEnc(void) { cur = gen_xmlDocPtr(n_cur, 1); encoding = gen_const_char_ptr(n_encoding, 2); - ret_val = htmlSaveFileEnc(filename, cur, (const char *)encoding); + ret_val = htmlSaveFileEnc(filename, cur, encoding); desret_int(ret_val); call_tests++; des_fileoutput(n_filename, filename, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlSaveFileEnc", @@ -3712,7 +3737,7 @@ test_htmlSaveFileFormat(void) { int n_filename; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the document encoding */ + const char * encoding; /* the document encoding */ int n_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -3727,12 +3752,12 @@ test_htmlSaveFileFormat(void) { encoding = gen_const_char_ptr(n_encoding, 2); format = gen_int(n_format, 3); - ret_val = htmlSaveFileFormat(filename, cur, (const char *)encoding, format); + ret_val = htmlSaveFileFormat(filename, cur, encoding, format); desret_int(ret_val); call_tests++; des_fileoutput(n_filename, filename, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_format, format, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -3765,7 +3790,7 @@ test_htmlSetMetaEncoding(void) { int ret_val; htmlDocPtr doc; /* the document */ int n_doc; - xmlChar * encoding; /* the encoding string */ + const xmlChar * encoding; /* the encoding string */ int n_encoding; for (n_doc = 0;n_doc < gen_nb_htmlDocPtr;n_doc++) { @@ -3774,11 +3799,11 @@ test_htmlSetMetaEncoding(void) { doc = gen_htmlDocPtr(n_doc, 0); encoding = gen_const_xmlChar_ptr(n_encoding, 1); - ret_val = htmlSetMetaEncoding(doc, (const xmlChar *)encoding); + ret_val = htmlSetMetaEncoding(doc, encoding); desret_int(ret_val); call_tests++; des_htmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_encoding, (const xmlChar *)encoding, 1); + des_const_xmlChar_ptr(n_encoding, encoding, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in htmlSetMetaEncoding", @@ -3886,15 +3911,15 @@ test_xmlSAX2AttributeDecl(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * elem; /* the name of the element */ + const xmlChar * elem; /* the name of the element */ int n_elem; - xmlChar * fullname; /* the attribute name */ + const xmlChar * fullname; /* the attribute name */ int n_fullname; int type; /* the attribute type */ int n_type; int def; /* the type of default value */ int n_def; - xmlChar * defaultValue; /* the attribute default value */ + const xmlChar * defaultValue; /* the attribute default value */ int n_defaultValue; xmlEnumerationPtr tree; /* the tree of enumerated value set */ int n_tree; @@ -3915,14 +3940,14 @@ test_xmlSAX2AttributeDecl(void) { defaultValue = gen_const_xmlChar_ptr(n_defaultValue, 5); tree = gen_xmlEnumerationPtr(n_tree, 6); - xmlSAX2AttributeDecl(ctx, (const xmlChar *)elem, (const xmlChar *)fullname, type, def, (const xmlChar *)defaultValue, tree); + xmlSAX2AttributeDecl(ctx, elem, fullname, type, def, defaultValue, tree); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_elem, (const xmlChar *)elem, 1); - des_const_xmlChar_ptr(n_fullname, (const xmlChar *)fullname, 2); + des_const_xmlChar_ptr(n_elem, elem, 1); + des_const_xmlChar_ptr(n_fullname, fullname, 2); des_int(n_type, type, 3); des_int(n_def, def, 4); - des_const_xmlChar_ptr(n_defaultValue, (const xmlChar *)defaultValue, 5); + des_const_xmlChar_ptr(n_defaultValue, defaultValue, 5); des_xmlEnumerationPtr(n_tree, tree, 6); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -3958,7 +3983,7 @@ test_xmlSAX2CDataBlock(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * value; /* The pcdata content */ + const xmlChar * value; /* The pcdata content */ int n_value; int len; /* the block length */ int n_len; @@ -3974,10 +3999,10 @@ test_xmlSAX2CDataBlock(void) { (len > xmlStrlen(BAD_CAST value))) len = 0; - xmlSAX2CDataBlock(ctx, (const xmlChar *)value, len); + xmlSAX2CDataBlock(ctx, value, len); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -4005,7 +4030,7 @@ test_xmlSAX2Characters(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * ch; /* a xmlChar string */ + const xmlChar * ch; /* a xmlChar string */ int n_ch; int len; /* the number of xmlChar */ int n_len; @@ -4021,10 +4046,10 @@ test_xmlSAX2Characters(void) { (len > xmlStrlen(BAD_CAST ch))) len = 0; - xmlSAX2Characters(ctx, (const xmlChar *)ch, len); + xmlSAX2Characters(ctx, ch, len); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_ch, (const xmlChar *)ch, 1); + des_const_xmlChar_ptr(n_ch, ch, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -4052,7 +4077,7 @@ test_xmlSAX2Comment(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * value; /* the xmlSAX2Comment content */ + const xmlChar * value; /* the xmlSAX2Comment content */ int n_value; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4061,10 +4086,10 @@ test_xmlSAX2Comment(void) { ctx = gen_void_ptr(n_ctx, 0); value = gen_const_xmlChar_ptr(n_value, 1); - xmlSAX2Comment(ctx, (const xmlChar *)value); + xmlSAX2Comment(ctx, value); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2Comment", @@ -4089,7 +4114,7 @@ test_xmlSAX2ElementDecl(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* the element name */ + const xmlChar * name; /* the element name */ int n_name; int type; /* the element type */ int n_type; @@ -4106,10 +4131,10 @@ test_xmlSAX2ElementDecl(void) { type = gen_int(n_type, 2); content = gen_xmlElementContentPtr(n_content, 3); - xmlSAX2ElementDecl(ctx, (const xmlChar *)name, type, content); + xmlSAX2ElementDecl(ctx, name, type, content); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_type, type, 2); des_xmlElementContentPtr(n_content, content, 3); xmlResetLastError(); @@ -4172,7 +4197,7 @@ test_xmlSAX2EndElement(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The element name */ + const xmlChar * name; /* The element name */ int n_name; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4181,10 +4206,10 @@ test_xmlSAX2EndElement(void) { ctx = gen_void_ptr(n_ctx, 0); name = gen_const_xmlChar_ptr(n_name, 1); - xmlSAX2EndElement(ctx, (const xmlChar *)name); + xmlSAX2EndElement(ctx, name); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2EndElement", @@ -4211,11 +4236,11 @@ test_xmlSAX2EndElementNs(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * localname; /* the local name of the element */ + const xmlChar * localname; /* the local name of the element */ int n_localname; - xmlChar * prefix; /* the element namespace prefix if available */ + const xmlChar * prefix; /* the element namespace prefix if available */ int n_prefix; - xmlChar * URI; /* the element namespace name if available */ + const xmlChar * URI; /* the element namespace name if available */ int n_URI; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4228,12 +4253,12 @@ test_xmlSAX2EndElementNs(void) { prefix = gen_const_xmlChar_ptr(n_prefix, 2); URI = gen_const_xmlChar_ptr(n_URI, 3); - xmlSAX2EndElementNs(ctx, (const xmlChar *)localname, (const xmlChar *)prefix, (const xmlChar *)URI); + xmlSAX2EndElementNs(ctx, localname, prefix, URI); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_localname, (const xmlChar *)localname, 1); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 2); - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 3); + des_const_xmlChar_ptr(n_localname, localname, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 2); + des_const_xmlChar_ptr(n_URI, URI, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2EndElementNs", @@ -4262,13 +4287,13 @@ test_xmlSAX2EntityDecl(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; int type; /* the entity type */ int n_type; - xmlChar * publicId; /* The public ID of the entity */ + const xmlChar * publicId; /* The public ID of the entity */ int n_publicId; - xmlChar * systemId; /* The system ID of the entity */ + const xmlChar * systemId; /* The system ID of the entity */ int n_systemId; xmlChar * content; /* the entity value (without processing). */ int n_content; @@ -4287,13 +4312,13 @@ test_xmlSAX2EntityDecl(void) { systemId = gen_const_xmlChar_ptr(n_systemId, 4); content = gen_xmlChar_ptr(n_content, 5); - xmlSAX2EntityDecl(ctx, (const xmlChar *)name, type, (const xmlChar *)publicId, (const xmlChar *)systemId, content); + xmlSAX2EntityDecl(ctx, name, type, publicId, systemId, content); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_type, type, 2); - des_const_xmlChar_ptr(n_publicId, (const xmlChar *)publicId, 3); - des_const_xmlChar_ptr(n_systemId, (const xmlChar *)systemId, 4); + des_const_xmlChar_ptr(n_publicId, publicId, 3); + des_const_xmlChar_ptr(n_systemId, systemId, 4); des_xmlChar_ptr(n_content, content, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -4327,11 +4352,11 @@ test_xmlSAX2ExternalSubset(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* the root element name */ + const xmlChar * name; /* the root element name */ int n_name; - xmlChar * ExternalID; /* the external ID */ + const xmlChar * ExternalID; /* the external ID */ int n_ExternalID; - xmlChar * SystemID; /* the SYSTEM ID (e.g. filename or URL) */ + const xmlChar * SystemID; /* the SYSTEM ID (e.g. filename or URL) */ int n_SystemID; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4344,12 +4369,12 @@ test_xmlSAX2ExternalSubset(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 2); SystemID = gen_const_xmlChar_ptr(n_SystemID, 3); - xmlSAX2ExternalSubset(ctx, (const xmlChar *)name, (const xmlChar *)ExternalID, (const xmlChar *)SystemID); + xmlSAX2ExternalSubset(ctx, name, ExternalID, SystemID); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 2); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 2); + des_const_xmlChar_ptr(n_SystemID, SystemID, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2ExternalSubset", @@ -4411,7 +4436,7 @@ test_xmlSAX2GetEntity(void) { xmlEntityPtr ret_val; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The entity name */ + const xmlChar * name; /* The entity name */ int n_name; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4420,11 +4445,11 @@ test_xmlSAX2GetEntity(void) { ctx = gen_void_ptr(n_ctx, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlSAX2GetEntity(ctx, (const xmlChar *)name); + ret_val = xmlSAX2GetEntity(ctx, name); desret_xmlEntityPtr(ret_val); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2GetEntity", @@ -4482,7 +4507,7 @@ test_xmlSAX2GetParameterEntity(void) { xmlEntityPtr ret_val; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The entity name */ + const xmlChar * name; /* The entity name */ int n_name; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4491,11 +4516,11 @@ test_xmlSAX2GetParameterEntity(void) { ctx = gen_void_ptr(n_ctx, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlSAX2GetParameterEntity(ctx, (const xmlChar *)name); + ret_val = xmlSAX2GetParameterEntity(ctx, name); desret_xmlEntityPtr(ret_val); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2GetParameterEntity", @@ -4648,7 +4673,7 @@ test_xmlSAX2IgnorableWhitespace(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * ch; /* a xmlChar string */ + const xmlChar * ch; /* a xmlChar string */ int n_ch; int len; /* the number of xmlChar */ int n_len; @@ -4664,10 +4689,10 @@ test_xmlSAX2IgnorableWhitespace(void) { (len > xmlStrlen(BAD_CAST ch))) len = 0; - xmlSAX2IgnorableWhitespace(ctx, (const xmlChar *)ch, len); + xmlSAX2IgnorableWhitespace(ctx, ch, len); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_ch, (const xmlChar *)ch, 1); + des_const_xmlChar_ptr(n_ch, ch, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -4768,11 +4793,11 @@ test_xmlSAX2InternalSubset(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* the root element name */ + const xmlChar * name; /* the root element name */ int n_name; - xmlChar * ExternalID; /* the external ID */ + const xmlChar * ExternalID; /* the external ID */ int n_ExternalID; - xmlChar * SystemID; /* the SYSTEM ID (e.g. filename or URL) */ + const xmlChar * SystemID; /* the SYSTEM ID (e.g. filename or URL) */ int n_SystemID; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4785,12 +4810,12 @@ test_xmlSAX2InternalSubset(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 2); SystemID = gen_const_xmlChar_ptr(n_SystemID, 3); - xmlSAX2InternalSubset(ctx, (const xmlChar *)name, (const xmlChar *)ExternalID, (const xmlChar *)SystemID); + xmlSAX2InternalSubset(ctx, name, ExternalID, SystemID); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 2); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 2); + des_const_xmlChar_ptr(n_SystemID, SystemID, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2InternalSubset", @@ -4851,11 +4876,11 @@ test_xmlSAX2NotationDecl(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The name of the notation */ + const xmlChar * name; /* The name of the notation */ int n_name; - xmlChar * publicId; /* The public ID of the entity */ + const xmlChar * publicId; /* The public ID of the entity */ int n_publicId; - xmlChar * systemId; /* The system ID of the entity */ + const xmlChar * systemId; /* The system ID of the entity */ int n_systemId; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4868,12 +4893,12 @@ test_xmlSAX2NotationDecl(void) { publicId = gen_const_xmlChar_ptr(n_publicId, 2); systemId = gen_const_xmlChar_ptr(n_systemId, 3); - xmlSAX2NotationDecl(ctx, (const xmlChar *)name, (const xmlChar *)publicId, (const xmlChar *)systemId); + xmlSAX2NotationDecl(ctx, name, publicId, systemId); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_publicId, (const xmlChar *)publicId, 2); - des_const_xmlChar_ptr(n_systemId, (const xmlChar *)systemId, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_publicId, publicId, 2); + des_const_xmlChar_ptr(n_systemId, systemId, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2NotationDecl", @@ -4902,9 +4927,9 @@ test_xmlSAX2ProcessingInstruction(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * target; /* the target name */ + const xmlChar * target; /* the target name */ int n_target; - xmlChar * data; /* the PI data's */ + const xmlChar * data; /* the PI data's */ int n_data; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4915,11 +4940,11 @@ test_xmlSAX2ProcessingInstruction(void) { target = gen_const_xmlChar_ptr(n_target, 1); data = gen_const_xmlChar_ptr(n_data, 2); - xmlSAX2ProcessingInstruction(ctx, (const xmlChar *)target, (const xmlChar *)data); + xmlSAX2ProcessingInstruction(ctx, target, data); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_target, (const xmlChar *)target, 1); - des_const_xmlChar_ptr(n_data, (const xmlChar *)data, 2); + des_const_xmlChar_ptr(n_target, target, 1); + des_const_xmlChar_ptr(n_data, data, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2ProcessingInstruction", @@ -4946,7 +4971,7 @@ test_xmlSAX2Reference(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The entity name */ + const xmlChar * name; /* The entity name */ int n_name; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4955,10 +4980,10 @@ test_xmlSAX2Reference(void) { ctx = gen_void_ptr(n_ctx, 0); name = gen_const_xmlChar_ptr(n_name, 1); - xmlSAX2Reference(ctx, (const xmlChar *)name); + xmlSAX2Reference(ctx, name); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2Reference", @@ -4984,9 +5009,9 @@ test_xmlSAX2ResolveEntity(void) { xmlParserInputPtr ret_val; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * publicId; /* The public ID of the entity */ + const xmlChar * publicId; /* The public ID of the entity */ int n_publicId; - xmlChar * systemId; /* The system ID of the entity */ + const xmlChar * systemId; /* The system ID of the entity */ int n_systemId; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -4997,12 +5022,12 @@ test_xmlSAX2ResolveEntity(void) { publicId = gen_const_xmlChar_ptr(n_publicId, 1); systemId = gen_const_xmlChar_ptr(n_systemId, 2); - ret_val = xmlSAX2ResolveEntity(ctx, (const xmlChar *)publicId, (const xmlChar *)systemId); + ret_val = xmlSAX2ResolveEntity(ctx, publicId, systemId); desret_xmlParserInputPtr(ret_val); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_publicId, (const xmlChar *)publicId, 1); - des_const_xmlChar_ptr(n_systemId, (const xmlChar *)systemId, 2); + des_const_xmlChar_ptr(n_publicId, publicId, 1); + des_const_xmlChar_ptr(n_systemId, systemId, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2ResolveEntity", @@ -5102,9 +5127,9 @@ test_xmlSAX2StartElement(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * fullname; /* The element name, including namespace prefix */ + const xmlChar * fullname; /* The element name, including namespace prefix */ int n_fullname; - xmlChar ** atts; /* An array of name/value attributes pairs, NULL terminated */ + const xmlChar ** atts; /* An array of name/value attributes pairs, NULL terminated */ int n_atts; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -5115,11 +5140,11 @@ test_xmlSAX2StartElement(void) { fullname = gen_const_xmlChar_ptr(n_fullname, 1); atts = gen_const_xmlChar_ptr_ptr(n_atts, 2); - xmlSAX2StartElement(ctx, (const xmlChar *)fullname, (const xmlChar **)atts); + xmlSAX2StartElement(ctx, fullname, atts); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_fullname, (const xmlChar *)fullname, 1); - des_const_xmlChar_ptr_ptr(n_atts, (const xmlChar **)atts, 2); + des_const_xmlChar_ptr(n_fullname, fullname, 1); + des_const_xmlChar_ptr_ptr(n_atts, atts, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2StartElement", @@ -5148,21 +5173,21 @@ test_xmlSAX2StartElementNs(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * localname; /* the local name of the element */ + const xmlChar * localname; /* the local name of the element */ int n_localname; - xmlChar * prefix; /* the element namespace prefix if available */ + const xmlChar * prefix; /* the element namespace prefix if available */ int n_prefix; - xmlChar * URI; /* the element namespace name if available */ + const xmlChar * URI; /* the element namespace name if available */ int n_URI; int nb_namespaces; /* number of namespace definitions on that node */ int n_nb_namespaces; - xmlChar ** namespaces; /* pointer to the array of prefix/URI pairs namespace definitions */ + const xmlChar ** namespaces; /* pointer to the array of prefix/URI pairs namespace definitions */ int n_namespaces; int nb_attributes; /* the number of attributes on that node */ int n_nb_attributes; int nb_defaulted; /* the number of defaulted attributes. */ int n_nb_defaulted; - xmlChar ** attributes; /* pointer to the array of (localname/prefix/URI/value/end) attribute values. */ + const xmlChar ** attributes; /* pointer to the array of (localname/prefix/URI/value/end) attribute values. */ int n_attributes; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -5185,17 +5210,17 @@ test_xmlSAX2StartElementNs(void) { nb_defaulted = gen_int(n_nb_defaulted, 7); attributes = gen_const_xmlChar_ptr_ptr(n_attributes, 8); - xmlSAX2StartElementNs(ctx, (const xmlChar *)localname, (const xmlChar *)prefix, (const xmlChar *)URI, nb_namespaces, (const xmlChar **)namespaces, nb_attributes, nb_defaulted, (const xmlChar **)attributes); + xmlSAX2StartElementNs(ctx, localname, prefix, URI, nb_namespaces, namespaces, nb_attributes, nb_defaulted, attributes); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_localname, (const xmlChar *)localname, 1); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 2); - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 3); + des_const_xmlChar_ptr(n_localname, localname, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 2); + des_const_xmlChar_ptr(n_URI, URI, 3); des_int(n_nb_namespaces, nb_namespaces, 4); - des_const_xmlChar_ptr_ptr(n_namespaces, (const xmlChar **)namespaces, 5); + des_const_xmlChar_ptr_ptr(n_namespaces, namespaces, 5); des_int(n_nb_attributes, nb_attributes, 6); des_int(n_nb_defaulted, nb_defaulted, 7); - des_const_xmlChar_ptr_ptr(n_attributes, (const xmlChar **)attributes, 8); + des_const_xmlChar_ptr_ptr(n_attributes, attributes, 8); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2StartElementNs", @@ -5234,13 +5259,13 @@ test_xmlSAX2UnparsedEntityDecl(void) { int mem_base; void * ctx; /* the user data (XML parser context) */ int n_ctx; - xmlChar * name; /* The name of the entity */ + const xmlChar * name; /* The name of the entity */ int n_name; - xmlChar * publicId; /* The public ID of the entity */ + const xmlChar * publicId; /* The public ID of the entity */ int n_publicId; - xmlChar * systemId; /* The system ID of the entity */ + const xmlChar * systemId; /* The system ID of the entity */ int n_systemId; - xmlChar * notationName; /* the name of the notation */ + const xmlChar * notationName; /* the name of the notation */ int n_notationName; for (n_ctx = 0;n_ctx < gen_nb_void_ptr;n_ctx++) { @@ -5255,13 +5280,13 @@ test_xmlSAX2UnparsedEntityDecl(void) { systemId = gen_const_xmlChar_ptr(n_systemId, 3); notationName = gen_const_xmlChar_ptr(n_notationName, 4); - xmlSAX2UnparsedEntityDecl(ctx, (const xmlChar *)name, (const xmlChar *)publicId, (const xmlChar *)systemId, (const xmlChar *)notationName); + xmlSAX2UnparsedEntityDecl(ctx, name, publicId, systemId, notationName); call_tests++; des_void_ptr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_publicId, (const xmlChar *)publicId, 2); - des_const_xmlChar_ptr(n_systemId, (const xmlChar *)systemId, 3); - des_const_xmlChar_ptr(n_notationName, (const xmlChar *)notationName, 4); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_publicId, publicId, 2); + des_const_xmlChar_ptr(n_systemId, systemId, 3); + des_const_xmlChar_ptr(n_notationName, notationName, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAX2UnparsedEntityDecl", @@ -5668,11 +5693,11 @@ test_xmlACatalogAdd(void) { int ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * type; /* the type of record to add to the catalog */ + const xmlChar * type; /* the type of record to add to the catalog */ int n_type; - xmlChar * orig; /* the system, public or prefix to match */ + const xmlChar * orig; /* the system, public or prefix to match */ int n_orig; - xmlChar * replace; /* the replacement value for the match */ + const xmlChar * replace; /* the replacement value for the match */ int n_replace; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5685,13 +5710,13 @@ test_xmlACatalogAdd(void) { orig = gen_const_xmlChar_ptr(n_orig, 2); replace = gen_const_xmlChar_ptr(n_replace, 3); - ret_val = xmlACatalogAdd(catal, (const xmlChar *)type, (const xmlChar *)orig, (const xmlChar *)replace); + ret_val = xmlACatalogAdd(catal, type, orig, replace); desret_int(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_type, (const xmlChar *)type, 1); - des_const_xmlChar_ptr(n_orig, (const xmlChar *)orig, 2); - des_const_xmlChar_ptr(n_replace, (const xmlChar *)replace, 3); + des_const_xmlChar_ptr(n_type, type, 1); + des_const_xmlChar_ptr(n_orig, orig, 2); + des_const_xmlChar_ptr(n_replace, replace, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogAdd", @@ -5762,7 +5787,7 @@ test_xmlACatalogRemove(void) { int ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * value; /* the value to remove */ + const xmlChar * value; /* the value to remove */ int n_value; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5771,11 +5796,11 @@ test_xmlACatalogRemove(void) { catal = gen_xmlCatalogPtr(n_catal, 0); value = gen_const_xmlChar_ptr(n_value, 1); - ret_val = xmlACatalogRemove(catal, (const xmlChar *)value); + ret_val = xmlACatalogRemove(catal, value); desret_int(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogRemove", @@ -5803,9 +5828,9 @@ test_xmlACatalogResolve(void) { xmlChar * ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * pubID; /* the public ID string */ + const xmlChar * pubID; /* the public ID string */ int n_pubID; - xmlChar * sysID; /* the system ID string */ + const xmlChar * sysID; /* the system ID string */ int n_sysID; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5816,12 +5841,12 @@ test_xmlACatalogResolve(void) { pubID = gen_const_xmlChar_ptr(n_pubID, 1); sysID = gen_const_xmlChar_ptr(n_sysID, 2); - ret_val = xmlACatalogResolve(catal, (const xmlChar *)pubID, (const xmlChar *)sysID); + ret_val = xmlACatalogResolve(catal, pubID, sysID); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_pubID, (const xmlChar *)pubID, 1); - des_const_xmlChar_ptr(n_sysID, (const xmlChar *)sysID, 2); + des_const_xmlChar_ptr(n_pubID, pubID, 1); + des_const_xmlChar_ptr(n_sysID, sysID, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogResolve", @@ -5851,7 +5876,7 @@ test_xmlACatalogResolvePublic(void) { xmlChar * ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * pubID; /* the public ID string */ + const xmlChar * pubID; /* the public ID string */ int n_pubID; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5860,11 +5885,11 @@ test_xmlACatalogResolvePublic(void) { catal = gen_xmlCatalogPtr(n_catal, 0); pubID = gen_const_xmlChar_ptr(n_pubID, 1); - ret_val = xmlACatalogResolvePublic(catal, (const xmlChar *)pubID); + ret_val = xmlACatalogResolvePublic(catal, pubID); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_pubID, (const xmlChar *)pubID, 1); + des_const_xmlChar_ptr(n_pubID, pubID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogResolvePublic", @@ -5892,7 +5917,7 @@ test_xmlACatalogResolveSystem(void) { xmlChar * ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * sysID; /* the system ID string */ + const xmlChar * sysID; /* the system ID string */ int n_sysID; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5901,11 +5926,11 @@ test_xmlACatalogResolveSystem(void) { catal = gen_xmlCatalogPtr(n_catal, 0); sysID = gen_const_xmlChar_ptr(n_sysID, 1); - ret_val = xmlACatalogResolveSystem(catal, (const xmlChar *)sysID); + ret_val = xmlACatalogResolveSystem(catal, sysID); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_sysID, (const xmlChar *)sysID, 1); + des_const_xmlChar_ptr(n_sysID, sysID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogResolveSystem", @@ -5933,7 +5958,7 @@ test_xmlACatalogResolveURI(void) { xmlChar * ret_val; xmlCatalogPtr catal; /* a Catalog */ int n_catal; - xmlChar * URI; /* the URI */ + const xmlChar * URI; /* the URI */ int n_URI; for (n_catal = 0;n_catal < gen_nb_xmlCatalogPtr;n_catal++) { @@ -5942,11 +5967,11 @@ test_xmlACatalogResolveURI(void) { catal = gen_xmlCatalogPtr(n_catal, 0); URI = gen_const_xmlChar_ptr(n_URI, 1); - ret_val = xmlACatalogResolveURI(catal, (const xmlChar *)URI); + ret_val = xmlACatalogResolveURI(catal, URI); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlCatalogPtr(n_catal, catal, 0); - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 1); + des_const_xmlChar_ptr(n_URI, URI, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlACatalogResolveURI", @@ -5972,11 +5997,11 @@ test_xmlCatalogAdd(void) { #if defined(LIBXML_CATALOG_ENABLED) int mem_base; int ret_val; - xmlChar * type; /* the type of record to add to the catalog */ + const xmlChar * type; /* the type of record to add to the catalog */ int n_type; - xmlChar * orig; /* the system, public or prefix to match */ + const xmlChar * orig; /* the system, public or prefix to match */ int n_orig; - xmlChar * replace; /* the replacement value for the match */ + const xmlChar * replace; /* the replacement value for the match */ int n_replace; for (n_type = 0;n_type < gen_nb_const_xmlChar_ptr;n_type++) { @@ -5987,12 +6012,12 @@ test_xmlCatalogAdd(void) { orig = gen_const_xmlChar_ptr(n_orig, 1); replace = gen_const_xmlChar_ptr(n_replace, 2); - ret_val = xmlCatalogAdd((const xmlChar *)type, (const xmlChar *)orig, (const xmlChar *)replace); + ret_val = xmlCatalogAdd(type, orig, replace); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_type, (const xmlChar *)type, 0); - des_const_xmlChar_ptr(n_orig, (const xmlChar *)orig, 1); - des_const_xmlChar_ptr(n_replace, (const xmlChar *)replace, 2); + des_const_xmlChar_ptr(n_type, type, 0); + des_const_xmlChar_ptr(n_orig, orig, 1); + des_const_xmlChar_ptr(n_replace, replace, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogAdd", @@ -6151,9 +6176,9 @@ test_xmlCatalogLocalResolve(void) { xmlChar * ret_val; void * catalogs; /* a document's list of catalogs */ int n_catalogs; - xmlChar * pubID; /* the public ID string */ + const xmlChar * pubID; /* the public ID string */ int n_pubID; - xmlChar * sysID; /* the system ID string */ + const xmlChar * sysID; /* the system ID string */ int n_sysID; for (n_catalogs = 0;n_catalogs < gen_nb_void_ptr;n_catalogs++) { @@ -6164,12 +6189,12 @@ test_xmlCatalogLocalResolve(void) { pubID = gen_const_xmlChar_ptr(n_pubID, 1); sysID = gen_const_xmlChar_ptr(n_sysID, 2); - ret_val = xmlCatalogLocalResolve(catalogs, (const xmlChar *)pubID, (const xmlChar *)sysID); + ret_val = xmlCatalogLocalResolve(catalogs, pubID, sysID); desret_xmlChar_ptr(ret_val); call_tests++; des_void_ptr(n_catalogs, catalogs, 0); - des_const_xmlChar_ptr(n_pubID, (const xmlChar *)pubID, 1); - des_const_xmlChar_ptr(n_sysID, (const xmlChar *)sysID, 2); + des_const_xmlChar_ptr(n_pubID, pubID, 1); + des_const_xmlChar_ptr(n_sysID, sysID, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogLocalResolve", @@ -6199,7 +6224,7 @@ test_xmlCatalogLocalResolveURI(void) { xmlChar * ret_val; void * catalogs; /* a document's list of catalogs */ int n_catalogs; - xmlChar * URI; /* the URI */ + const xmlChar * URI; /* the URI */ int n_URI; for (n_catalogs = 0;n_catalogs < gen_nb_void_ptr;n_catalogs++) { @@ -6208,11 +6233,11 @@ test_xmlCatalogLocalResolveURI(void) { catalogs = gen_void_ptr(n_catalogs, 0); URI = gen_const_xmlChar_ptr(n_URI, 1); - ret_val = xmlCatalogLocalResolveURI(catalogs, (const xmlChar *)URI); + ret_val = xmlCatalogLocalResolveURI(catalogs, URI); desret_xmlChar_ptr(ret_val); call_tests++; des_void_ptr(n_catalogs, catalogs, 0); - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 1); + des_const_xmlChar_ptr(n_URI, URI, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogLocalResolveURI", @@ -6237,16 +6262,16 @@ test_xmlCatalogRemove(void) { #if defined(LIBXML_CATALOG_ENABLED) int ret_val; - xmlChar * value; /* the value to remove */ + const xmlChar * value; /* the value to remove */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlCatalogRemove((const xmlChar *)value); + ret_val = xmlCatalogRemove(value); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); } function_tests++; @@ -6262,9 +6287,9 @@ test_xmlCatalogResolve(void) { #if defined(LIBXML_CATALOG_ENABLED) xmlChar * ret_val; - xmlChar * pubID; /* the public ID string */ + const xmlChar * pubID; /* the public ID string */ int n_pubID; - xmlChar * sysID; /* the system ID string */ + const xmlChar * sysID; /* the system ID string */ int n_sysID; for (n_pubID = 0;n_pubID < gen_nb_const_xmlChar_ptr;n_pubID++) { @@ -6272,11 +6297,11 @@ test_xmlCatalogResolve(void) { pubID = gen_const_xmlChar_ptr(n_pubID, 0); sysID = gen_const_xmlChar_ptr(n_sysID, 1); - ret_val = xmlCatalogResolve((const xmlChar *)pubID, (const xmlChar *)sysID); + ret_val = xmlCatalogResolve(pubID, sysID); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_pubID, (const xmlChar *)pubID, 0); - des_const_xmlChar_ptr(n_sysID, (const xmlChar *)sysID, 1); + des_const_xmlChar_ptr(n_pubID, pubID, 0); + des_const_xmlChar_ptr(n_sysID, sysID, 1); xmlResetLastError(); } } @@ -6294,17 +6319,17 @@ test_xmlCatalogResolvePublic(void) { #if defined(LIBXML_CATALOG_ENABLED) int mem_base; xmlChar * ret_val; - xmlChar * pubID; /* the public ID string */ + const xmlChar * pubID; /* the public ID string */ int n_pubID; for (n_pubID = 0;n_pubID < gen_nb_const_xmlChar_ptr;n_pubID++) { mem_base = xmlMemBlocks(); pubID = gen_const_xmlChar_ptr(n_pubID, 0); - ret_val = xmlCatalogResolvePublic((const xmlChar *)pubID); + ret_val = xmlCatalogResolvePublic(pubID); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_pubID, (const xmlChar *)pubID, 0); + des_const_xmlChar_ptr(n_pubID, pubID, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogResolvePublic", @@ -6328,17 +6353,17 @@ test_xmlCatalogResolveSystem(void) { #if defined(LIBXML_CATALOG_ENABLED) int mem_base; xmlChar * ret_val; - xmlChar * sysID; /* the system ID string */ + const xmlChar * sysID; /* the system ID string */ int n_sysID; for (n_sysID = 0;n_sysID < gen_nb_const_xmlChar_ptr;n_sysID++) { mem_base = xmlMemBlocks(); sysID = gen_const_xmlChar_ptr(n_sysID, 0); - ret_val = xmlCatalogResolveSystem((const xmlChar *)sysID); + ret_val = xmlCatalogResolveSystem(sysID); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_sysID, (const xmlChar *)sysID, 0); + des_const_xmlChar_ptr(n_sysID, sysID, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogResolveSystem", @@ -6362,17 +6387,17 @@ test_xmlCatalogResolveURI(void) { #if defined(LIBXML_CATALOG_ENABLED) int mem_base; xmlChar * ret_val; - xmlChar * URI; /* the URI */ + const xmlChar * URI; /* the URI */ int n_URI; for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { mem_base = xmlMemBlocks(); URI = gen_const_xmlChar_ptr(n_URI, 0); - ret_val = xmlCatalogResolveURI((const xmlChar *)URI); + ret_val = xmlCatalogResolveURI(URI); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 0); + des_const_xmlChar_ptr(n_URI, URI, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCatalogResolveURI", @@ -6554,15 +6579,15 @@ test_xmlLoadCatalogs(void) { int test_ret = 0; #if defined(LIBXML_CATALOG_ENABLED) - char * pathss; /* a list of directories separated by a colon or a space. */ + const char * pathss; /* a list of directories separated by a colon or a space. */ int n_pathss; for (n_pathss = 0;n_pathss < gen_nb_const_char_ptr;n_pathss++) { pathss = gen_const_char_ptr(n_pathss, 0); - xmlLoadCatalogs((const char *)pathss); + xmlLoadCatalogs(pathss); call_tests++; - des_const_char_ptr(n_pathss, (const char *)pathss, 0); + des_const_char_ptr(n_pathss, pathss, 0); xmlResetLastError(); } function_tests++; @@ -6678,7 +6703,7 @@ test_xmlCharInRange(void) { int ret_val; unsigned int val; /* character to be validated */ int n_val; - xmlChRangeGroup * rptr; /* pointer to range to be used to validate */ + const xmlChRangeGroup * rptr; /* pointer to range to be used to validate */ int n_rptr; for (n_val = 0;n_val < gen_nb_unsigned_int;n_val++) { @@ -6687,11 +6712,11 @@ test_xmlCharInRange(void) { val = gen_unsigned_int(n_val, 0); rptr = gen_const_xmlChRangeGroup_ptr(n_rptr, 1); - ret_val = xmlCharInRange(val, (const xmlChRangeGroup *)rptr); + ret_val = xmlCharInRange(val, rptr); desret_int(ret_val); call_tests++; des_unsigned_int(n_val, val, 0); - des_const_xmlChRangeGroup_ptr(n_rptr, (const xmlChRangeGroup *)rptr, 1); + des_const_xmlChRangeGroup_ptr(n_rptr, rptr, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCharInRange", @@ -7453,7 +7478,7 @@ test_xmlDebugDumpString(void) { int mem_base; FILE * output; /* the FILE * for the output */ int n_output; - xmlChar * str; /* the string */ + const xmlChar * str; /* the string */ int n_str; for (n_output = 0;n_output < gen_nb_debug_FILE_ptr;n_output++) { @@ -7462,10 +7487,10 @@ test_xmlDebugDumpString(void) { output = gen_debug_FILE_ptr(n_output, 0); str = gen_const_xmlChar_ptr(n_str, 1); - xmlDebugDumpString(output, (const xmlChar *)str); + xmlDebugDumpString(output, str); call_tests++; des_debug_FILE_ptr(n_output, output, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDebugDumpString", @@ -8277,7 +8302,7 @@ test_xmlDictExists(void) { const xmlChar * ret_val; xmlDictPtr dict; /* the dictionary */ int n_dict; - xmlChar * name; /* the name of the userdata */ + const xmlChar * name; /* the name of the userdata */ int n_name; int len; /* the length of the name, if -1 it is recomputed */ int n_len; @@ -8293,11 +8318,11 @@ test_xmlDictExists(void) { (len > xmlStrlen(BAD_CAST name))) len = 0; - ret_val = xmlDictExists(dict, (const xmlChar *)name, len); + ret_val = xmlDictExists(dict, name, len); desret_const_xmlChar_ptr(ret_val); call_tests++; des_xmlDictPtr(n_dict, dict, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -8336,7 +8361,7 @@ test_xmlDictLookup(void) { const xmlChar * ret_val; xmlDictPtr dict; /* dictionary */ int n_dict; - xmlChar * name; /* string key */ + const xmlChar * name; /* string key */ int n_name; int len; /* length of the key, if -1 it is recomputed */ int n_len; @@ -8352,11 +8377,11 @@ test_xmlDictLookup(void) { (len > xmlStrlen(BAD_CAST name))) len = 0; - ret_val = xmlDictLookup(dict, (const xmlChar *)name, len); + ret_val = xmlDictLookup(dict, name, len); desret_const_xmlChar_ptr(ret_val); call_tests++; des_xmlDictPtr(n_dict, dict, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -8385,7 +8410,7 @@ test_xmlDictOwns(void) { int ret_val; xmlDictPtr dict; /* the dictionary */ int n_dict; - xmlChar * str; /* the string */ + const xmlChar * str; /* the string */ int n_str; for (n_dict = 0;n_dict < gen_nb_xmlDictPtr;n_dict++) { @@ -8394,11 +8419,11 @@ test_xmlDictOwns(void) { dict = gen_xmlDictPtr(n_dict, 0); str = gen_const_xmlChar_ptr(n_str, 1); - ret_val = xmlDictOwns(dict, (const xmlChar *)str); + ret_val = xmlDictOwns(dict, str); desret_int(ret_val); call_tests++; des_xmlDictPtr(n_dict, dict, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDictOwns", @@ -8424,9 +8449,9 @@ test_xmlDictQLookup(void) { const xmlChar * ret_val; xmlDictPtr dict; /* the dictionary */ int n_dict; - xmlChar * prefix; /* the prefix */ + const xmlChar * prefix; /* the prefix */ int n_prefix; - xmlChar * name; /* the name */ + const xmlChar * name; /* the name */ int n_name; for (n_dict = 0;n_dict < gen_nb_xmlDictPtr;n_dict++) { @@ -8437,12 +8462,12 @@ test_xmlDictQLookup(void) { prefix = gen_const_xmlChar_ptr(n_prefix, 1); name = gen_const_xmlChar_ptr(n_name, 2); - ret_val = xmlDictQLookup(dict, (const xmlChar *)prefix, (const xmlChar *)name); + ret_val = xmlDictQLookup(dict, prefix, name); desret_const_xmlChar_ptr(ret_val); call_tests++; des_xmlDictPtr(n_dict, dict, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDictQLookup", @@ -8596,7 +8621,7 @@ test_UTF8Toisolat1(void) { int n_out; int * outlen; /* the length of @out */ int n_outlen; - unsigned char * in; /* a pointer to an array of UTF-8 chars */ + const unsigned char * in; /* a pointer to an array of UTF-8 chars */ int n_in; int * inlen; /* the length of @in */ int n_inlen; @@ -8611,12 +8636,12 @@ test_UTF8Toisolat1(void) { in = gen_const_unsigned_char_ptr(n_in, 2); inlen = gen_int_ptr(n_inlen, 3); - ret_val = UTF8Toisolat1(out, outlen, (const unsigned char *)in, inlen); + ret_val = UTF8Toisolat1(out, outlen, in, inlen); desret_int(ret_val); call_tests++; des_unsigned_char_ptr(n_out, out, 0); des_int_ptr(n_outlen, outlen, 1); - des_const_unsigned_char_ptr(n_in, (const unsigned char *)in, 2); + des_const_unsigned_char_ptr(n_in, in, 2); des_int_ptr(n_inlen, inlen, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -8651,7 +8676,7 @@ test_isolat1ToUTF8(void) { int n_out; int * outlen; /* the length of @out */ int n_outlen; - unsigned char * in; /* a pointer to an array of ISO Latin 1 chars */ + const unsigned char * in; /* a pointer to an array of ISO Latin 1 chars */ int n_in; int * inlen; /* the length of @in */ int n_inlen; @@ -8666,12 +8691,12 @@ test_isolat1ToUTF8(void) { in = gen_const_unsigned_char_ptr(n_in, 2); inlen = gen_int_ptr(n_inlen, 3); - ret_val = isolat1ToUTF8(out, outlen, (const unsigned char *)in, inlen); + ret_val = isolat1ToUTF8(out, outlen, in, inlen); desret_int(ret_val); call_tests++; des_unsigned_char_ptr(n_out, out, 0); des_int_ptr(n_outlen, outlen, 1); - des_const_unsigned_char_ptr(n_in, (const unsigned char *)in, 2); + des_const_unsigned_char_ptr(n_in, in, 2); des_int_ptr(n_inlen, inlen, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -8699,9 +8724,9 @@ test_xmlAddEncodingAlias(void) { int test_ret = 0; int ret_val; - char * name; /* the encoding name as parsed, in UTF-8 format (ASCII actually) */ + const char * name; /* the encoding name as parsed, in UTF-8 format (ASCII actually) */ int n_name; - char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ + const char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ int n_alias; for (n_name = 0;n_name < gen_nb_const_char_ptr;n_name++) { @@ -8709,11 +8734,11 @@ test_xmlAddEncodingAlias(void) { name = gen_const_char_ptr(n_name, 0); alias = gen_const_char_ptr(n_alias, 1); - ret_val = xmlAddEncodingAlias((const char *)name, (const char *)alias); + ret_val = xmlAddEncodingAlias(name, alias); desret_int(ret_val); call_tests++; - des_const_char_ptr(n_name, (const char *)name, 0); - des_const_char_ptr(n_alias, (const char *)alias, 1); + des_const_char_ptr(n_name, name, 0); + des_const_char_ptr(n_alias, alias, 1); xmlResetLastError(); } } @@ -8941,17 +8966,17 @@ test_xmlDelEncodingAlias(void) { int mem_base; int ret_val; - char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ + const char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ int n_alias; for (n_alias = 0;n_alias < gen_nb_const_char_ptr;n_alias++) { mem_base = xmlMemBlocks(); alias = gen_const_char_ptr(n_alias, 0); - ret_val = xmlDelEncodingAlias((const char *)alias); + ret_val = xmlDelEncodingAlias(alias); desret_int(ret_val); call_tests++; - des_const_char_ptr(n_alias, (const char *)alias, 0); + des_const_char_ptr(n_alias, alias, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDelEncodingAlias", @@ -8973,7 +8998,7 @@ test_xmlDetectCharEncoding(void) { int mem_base; xmlCharEncoding ret_val; - unsigned char * in; /* a pointer to the first bytes of the XML entity, must be at least 2 bytes long (at least 4 if encoding is UTF4 variant). */ + const unsigned char * in; /* a pointer to the first bytes of the XML entity, must be at least 2 bytes long (at least 4 if encoding is UTF4 variant). */ int n_in; int len; /* pointer to the length of the buffer */ int n_len; @@ -8984,10 +9009,10 @@ test_xmlDetectCharEncoding(void) { in = gen_const_unsigned_char_ptr(n_in, 0); len = gen_int(n_len, 1); - ret_val = xmlDetectCharEncoding((const unsigned char *)in, len); + ret_val = xmlDetectCharEncoding(in, len); desret_xmlCharEncoding(ret_val); call_tests++; - des_const_unsigned_char_ptr(n_in, (const unsigned char *)in, 0); + des_const_unsigned_char_ptr(n_in, in, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -9064,17 +9089,17 @@ test_xmlGetEncodingAlias(void) { int mem_base; const char * ret_val; - char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ + const char * alias; /* the alias name as parsed, in UTF-8 format (ASCII actually) */ int n_alias; for (n_alias = 0;n_alias < gen_nb_const_char_ptr;n_alias++) { mem_base = xmlMemBlocks(); alias = gen_const_char_ptr(n_alias, 0); - ret_val = xmlGetEncodingAlias((const char *)alias); + ret_val = xmlGetEncodingAlias(alias); desret_const_char_ptr(ret_val); call_tests++; - des_const_char_ptr(n_alias, (const char *)alias, 0); + des_const_char_ptr(n_alias, alias, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetEncodingAlias", @@ -9105,6 +9130,16 @@ test_xmlInitCharEncodingHandlers(void) { } +static int +test_xmlLookupCharEncodingHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlNewCharEncodingHandler(void) { int test_ret = 0; @@ -9115,23 +9150,33 @@ test_xmlNewCharEncodingHandler(void) { } +static int +test_xmlOpenCharEncodingHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlParseCharEncoding(void) { int test_ret = 0; int mem_base; xmlCharEncoding ret_val; - char * name; /* the encoding name as parsed, in UTF-8 format (ASCII actually) */ + const char * name; /* the encoding name as parsed, in UTF-8 format (ASCII actually) */ int n_name; for (n_name = 0;n_name < gen_nb_const_char_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_char_ptr(n_name, 0); - ret_val = xmlParseCharEncoding((const char *)name); + ret_val = xmlParseCharEncoding(name); desret_xmlCharEncoding(ret_val); call_tests++; - des_const_char_ptr(n_name, (const char *)name, 0); + des_const_char_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseCharEncoding", @@ -9184,7 +9229,7 @@ static int test_encoding(void) { int test_ret = 0; - if (quiet == 0) printf("Testing encoding : 16 of 19 functions ...\n"); + if (quiet == 0) printf("Testing encoding : 16 of 21 functions ...\n"); test_ret += test_UTF8Toisolat1(); test_ret += test_isolat1ToUTF8(); test_ret += test_xmlAddEncodingAlias(); @@ -9201,7 +9246,9 @@ test_encoding(void) { test_ret += test_xmlGetCharEncodingName(); test_ret += test_xmlGetEncodingAlias(); test_ret += test_xmlInitCharEncodingHandlers(); + test_ret += test_xmlLookupCharEncodingHandler(); test_ret += test_xmlNewCharEncodingHandler(); + test_ret += test_xmlOpenCharEncodingHandler(); test_ret += test_xmlParseCharEncoding(); test_ret += test_xmlRegisterCharEncodingHandler(); @@ -9218,15 +9265,15 @@ test_xmlAddDocEntity(void) { xmlEntityPtr ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; int type; /* the entity type XML_xxx_yyy_ENTITY */ int n_type; - xmlChar * ExternalID; /* the entity external ID if available */ + const xmlChar * ExternalID; /* the entity external ID if available */ int n_ExternalID; - xmlChar * SystemID; /* the entity system ID if available */ + const xmlChar * SystemID; /* the entity system ID if available */ int n_SystemID; - xmlChar * content; /* the entity content */ + const xmlChar * content; /* the entity content */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9243,15 +9290,15 @@ test_xmlAddDocEntity(void) { SystemID = gen_const_xmlChar_ptr(n_SystemID, 4); content = gen_const_xmlChar_ptr(n_content, 5); - ret_val = xmlAddDocEntity(doc, (const xmlChar *)name, type, (const xmlChar *)ExternalID, (const xmlChar *)SystemID, (const xmlChar *)content); + ret_val = xmlAddDocEntity(doc, name, type, ExternalID, SystemID, content); desret_xmlEntityPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_type, type, 2); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 3); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 4); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 5); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 3); + des_const_xmlChar_ptr(n_SystemID, SystemID, 4); + des_const_xmlChar_ptr(n_content, content, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAddDocEntity", @@ -9285,15 +9332,15 @@ test_xmlAddDtdEntity(void) { xmlEntityPtr ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; int type; /* the entity type XML_xxx_yyy_ENTITY */ int n_type; - xmlChar * ExternalID; /* the entity external ID if available */ + const xmlChar * ExternalID; /* the entity external ID if available */ int n_ExternalID; - xmlChar * SystemID; /* the entity system ID if available */ + const xmlChar * SystemID; /* the entity system ID if available */ int n_SystemID; - xmlChar * content; /* the entity content */ + const xmlChar * content; /* the entity content */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9310,15 +9357,15 @@ test_xmlAddDtdEntity(void) { SystemID = gen_const_xmlChar_ptr(n_SystemID, 4); content = gen_const_xmlChar_ptr(n_content, 5); - ret_val = xmlAddDtdEntity(doc, (const xmlChar *)name, type, (const xmlChar *)ExternalID, (const xmlChar *)SystemID, (const xmlChar *)content); + ret_val = xmlAddDtdEntity(doc, name, type, ExternalID, SystemID, content); desret_xmlEntityPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_type, type, 2); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 3); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 4); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 5); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 3); + des_const_xmlChar_ptr(n_SystemID, SystemID, 4); + des_const_xmlChar_ptr(n_content, content, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAddDtdEntity", @@ -9344,6 +9391,91 @@ test_xmlAddDtdEntity(void) { } +#define gen_nb_xmlEntityPtr_ptr 1 +#define gen_xmlEntityPtr_ptr(no, nr) NULL +#define des_xmlEntityPtr_ptr(no, val, nr) + +static int +test_xmlAddEntity(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlDocPtr doc; /* the document */ + int n_doc; + int extSubset; /* add to the external or internal subset */ + int n_extSubset; + const xmlChar * name; /* the entity name */ + int n_name; + int type; /* the entity type XML_xxx_yyy_ENTITY */ + int n_type; + const xmlChar * ExternalID; /* the entity external ID if available */ + int n_ExternalID; + const xmlChar * SystemID; /* the entity system ID if available */ + int n_SystemID; + const xmlChar * content; /* the entity content */ + int n_content; + xmlEntityPtr * out; /* pointer to resulting entity (optional) */ + int n_out; + + for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { + for (n_extSubset = 0;n_extSubset < gen_nb_int;n_extSubset++) { + for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { + for (n_type = 0;n_type < gen_nb_int;n_type++) { + for (n_ExternalID = 0;n_ExternalID < gen_nb_const_xmlChar_ptr;n_ExternalID++) { + for (n_SystemID = 0;n_SystemID < gen_nb_const_xmlChar_ptr;n_SystemID++) { + for (n_content = 0;n_content < gen_nb_const_xmlChar_ptr;n_content++) { + for (n_out = 0;n_out < gen_nb_xmlEntityPtr_ptr;n_out++) { + mem_base = xmlMemBlocks(); + doc = gen_xmlDocPtr(n_doc, 0); + extSubset = gen_int(n_extSubset, 1); + name = gen_const_xmlChar_ptr(n_name, 2); + type = gen_int(n_type, 3); + ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 4); + SystemID = gen_const_xmlChar_ptr(n_SystemID, 5); + content = gen_const_xmlChar_ptr(n_content, 6); + out = gen_xmlEntityPtr_ptr(n_out, 7); + + ret_val = xmlAddEntity(doc, extSubset, name, type, ExternalID, SystemID, content, out); + desret_int(ret_val); + call_tests++; + des_xmlDocPtr(n_doc, doc, 0); + des_int(n_extSubset, extSubset, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_int(n_type, type, 3); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 4); + des_const_xmlChar_ptr(n_SystemID, SystemID, 5); + des_const_xmlChar_ptr(n_content, content, 6); + des_xmlEntityPtr_ptr(n_out, out, 7); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlAddEntity", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_doc); + printf(" %d", n_extSubset); + printf(" %d", n_name); + printf(" %d", n_type); + printf(" %d", n_ExternalID); + printf(" %d", n_SystemID); + printf(" %d", n_content); + printf(" %d", n_out); + printf("\n"); + } + } + } + } + } + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCopyEntitiesTable(void) { int test_ret = 0; @@ -9458,7 +9590,7 @@ test_xmlEncodeEntitiesReentrant(void) { xmlChar * ret_val; xmlDocPtr doc; /* the document containing the string */ int n_doc; - xmlChar * input; /* A string to convert to XML. */ + const xmlChar * input; /* A string to convert to XML. */ int n_input; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9467,11 +9599,11 @@ test_xmlEncodeEntitiesReentrant(void) { doc = gen_xmlDocPtr(n_doc, 0); input = gen_const_xmlChar_ptr(n_input, 1); - ret_val = xmlEncodeEntitiesReentrant(doc, (const xmlChar *)input); + ret_val = xmlEncodeEntitiesReentrant(doc, input); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_input, (const xmlChar *)input, 1); + des_const_xmlChar_ptr(n_input, input, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlEncodeEntitiesReentrant", @@ -9499,9 +9631,9 @@ test_xmlEncodeSpecialChars(void) { int mem_base; xmlChar * ret_val; - xmlDoc * doc; /* the document containing the string */ + const xmlDoc * doc; /* the document containing the string */ int n_doc; - xmlChar * input; /* A string to convert to XML. */ + const xmlChar * input; /* A string to convert to XML. */ int n_input; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -9510,11 +9642,11 @@ test_xmlEncodeSpecialChars(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); input = gen_const_xmlChar_ptr(n_input, 1); - ret_val = xmlEncodeSpecialChars((const xmlDoc *)doc, (const xmlChar *)input); + ret_val = xmlEncodeSpecialChars(doc, input); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_input, (const xmlChar *)input, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_input, input, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlEncodeSpecialChars", @@ -9538,9 +9670,9 @@ test_xmlGetDocEntity(void) { int mem_base; xmlEntityPtr ret_val; - xmlDoc * doc; /* the document referencing the entity */ + const xmlDoc * doc; /* the document referencing the entity */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -9549,11 +9681,11 @@ test_xmlGetDocEntity(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetDocEntity((const xmlDoc *)doc, (const xmlChar *)name); + ret_val = xmlGetDocEntity(doc, name); desret_xmlEntityPtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDocEntity", @@ -9579,7 +9711,7 @@ test_xmlGetDtdEntity(void) { xmlEntityPtr ret_val; xmlDocPtr doc; /* the document referencing the entity */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9588,11 +9720,11 @@ test_xmlGetDtdEntity(void) { doc = gen_xmlDocPtr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetDtdEntity(doc, (const xmlChar *)name); + ret_val = xmlGetDtdEntity(doc, name); desret_xmlEntityPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDtdEntity", @@ -9618,7 +9750,7 @@ test_xmlGetParameterEntity(void) { xmlEntityPtr ret_val; xmlDocPtr doc; /* the document referencing the entity */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9627,11 +9759,11 @@ test_xmlGetParameterEntity(void) { doc = gen_xmlDocPtr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetParameterEntity(doc, (const xmlChar *)name); + ret_val = xmlGetParameterEntity(doc, name); desret_xmlEntityPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetParameterEntity", @@ -9655,17 +9787,17 @@ test_xmlGetPredefinedEntity(void) { int mem_base; xmlEntityPtr ret_val; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_xmlChar_ptr(n_name, 0); - ret_val = xmlGetPredefinedEntity((const xmlChar *)name); + ret_val = xmlGetPredefinedEntity(name); desret_xmlEntityPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetPredefinedEntity", @@ -9689,15 +9821,15 @@ test_xmlNewEntity(void) { xmlEntityPtr ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; int type; /* the entity type XML_xxx_yyy_ENTITY */ int n_type; - xmlChar * ExternalID; /* the entity external ID if available */ + const xmlChar * ExternalID; /* the entity external ID if available */ int n_ExternalID; - xmlChar * SystemID; /* the entity system ID if available */ + const xmlChar * SystemID; /* the entity system ID if available */ int n_SystemID; - xmlChar * content; /* the entity content */ + const xmlChar * content; /* the entity content */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -9714,15 +9846,15 @@ test_xmlNewEntity(void) { SystemID = gen_const_xmlChar_ptr(n_SystemID, 4); content = gen_const_xmlChar_ptr(n_content, 5); - ret_val = xmlNewEntity(doc, (const xmlChar *)name, type, (const xmlChar *)ExternalID, (const xmlChar *)SystemID, (const xmlChar *)content); + ret_val = xmlNewEntity(doc, name, type, ExternalID, SystemID, content); desret_xmlEntityPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_int(n_type, type, 2); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 3); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 4); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 5); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 3); + des_const_xmlChar_ptr(n_SystemID, SystemID, 4); + des_const_xmlChar_ptr(n_content, content, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewEntity", @@ -9751,9 +9883,10 @@ static int test_entities(void) { int test_ret = 0; - if (quiet == 0) printf("Testing entities : 11 of 18 functions ...\n"); + if (quiet == 0) printf("Testing entities : 12 of 19 functions ...\n"); test_ret += test_xmlAddDocEntity(); test_ret += test_xmlAddDtdEntity(); + test_ret += test_xmlAddEntity(); test_ret += test_xmlCopyEntitiesTable(); test_ret += test_xmlCreateEntitiesTable(); test_ret += test_xmlDumpEntitiesTable(); @@ -9771,6 +9904,165 @@ test_entities(void) { return(test_ret); } +static int +test_xmlHashAdd(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlHashTablePtr hash; /* hash table */ + int n_hash; + const xmlChar * key; /* string key */ + int n_key; + void * payload; /* pointer to the payload */ + int n_payload; + + for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { + for (n_key = 0;n_key < gen_nb_const_xmlChar_ptr;n_key++) { + for (n_payload = 0;n_payload < gen_nb_void_ptr;n_payload++) { + mem_base = xmlMemBlocks(); + hash = gen_xmlHashTablePtr(n_hash, 0); + key = gen_const_xmlChar_ptr(n_key, 1); + payload = gen_void_ptr(n_payload, 2); + + ret_val = xmlHashAdd(hash, key, payload); + desret_int(ret_val); + call_tests++; + des_xmlHashTablePtr(n_hash, hash, 0); + des_const_xmlChar_ptr(n_key, key, 1); + des_void_ptr(n_payload, payload, 2); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlHashAdd", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_hash); + printf(" %d", n_key); + printf(" %d", n_payload); + printf("\n"); + } + } + } + } + function_tests++; + + return(test_ret); +} + + +static int +test_xmlHashAdd2(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlHashTablePtr hash; /* hash table */ + int n_hash; + const xmlChar * key; /* first string key */ + int n_key; + const xmlChar * key2; /* second string key */ + int n_key2; + void * payload; /* pointer to the payload */ + int n_payload; + + for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { + for (n_key = 0;n_key < gen_nb_const_xmlChar_ptr;n_key++) { + for (n_key2 = 0;n_key2 < gen_nb_const_xmlChar_ptr;n_key2++) { + for (n_payload = 0;n_payload < gen_nb_void_ptr;n_payload++) { + mem_base = xmlMemBlocks(); + hash = gen_xmlHashTablePtr(n_hash, 0); + key = gen_const_xmlChar_ptr(n_key, 1); + key2 = gen_const_xmlChar_ptr(n_key2, 2); + payload = gen_void_ptr(n_payload, 3); + + ret_val = xmlHashAdd2(hash, key, key2, payload); + desret_int(ret_val); + call_tests++; + des_xmlHashTablePtr(n_hash, hash, 0); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_void_ptr(n_payload, payload, 3); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlHashAdd2", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_hash); + printf(" %d", n_key); + printf(" %d", n_key2); + printf(" %d", n_payload); + printf("\n"); + } + } + } + } + } + function_tests++; + + return(test_ret); +} + + +static int +test_xmlHashAdd3(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlHashTablePtr hash; /* hash table */ + int n_hash; + const xmlChar * key; /* first string key */ + int n_key; + const xmlChar * key2; /* second string key */ + int n_key2; + const xmlChar * key3; /* third string key */ + int n_key3; + void * payload; /* pointer to the payload */ + int n_payload; + + for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { + for (n_key = 0;n_key < gen_nb_const_xmlChar_ptr;n_key++) { + for (n_key2 = 0;n_key2 < gen_nb_const_xmlChar_ptr;n_key2++) { + for (n_key3 = 0;n_key3 < gen_nb_const_xmlChar_ptr;n_key3++) { + for (n_payload = 0;n_payload < gen_nb_void_ptr;n_payload++) { + mem_base = xmlMemBlocks(); + hash = gen_xmlHashTablePtr(n_hash, 0); + key = gen_const_xmlChar_ptr(n_key, 1); + key2 = gen_const_xmlChar_ptr(n_key2, 2); + key3 = gen_const_xmlChar_ptr(n_key3, 3); + payload = gen_void_ptr(n_payload, 4); + + ret_val = xmlHashAdd3(hash, key, key2, key3, payload); + desret_int(ret_val); + call_tests++; + des_xmlHashTablePtr(n_hash, hash, 0); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_const_xmlChar_ptr(n_key3, key3, 3); + des_void_ptr(n_payload, payload, 4); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlHashAdd3", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_hash); + printf(" %d", n_key); + printf(" %d", n_key2); + printf(" %d", n_key3); + printf(" %d", n_payload); + printf("\n"); + } + } + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlHashAddEntry(void) { int test_ret = 0; @@ -9779,7 +10071,7 @@ test_xmlHashAddEntry(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* string key */ + const xmlChar * key; /* string key */ int n_key; void * payload; /* pointer to the payload */ int n_payload; @@ -9792,11 +10084,11 @@ test_xmlHashAddEntry(void) { key = gen_const_xmlChar_ptr(n_key, 1); payload = gen_void_ptr(n_payload, 2); - ret_val = xmlHashAddEntry(hash, (const xmlChar *)key, payload); + ret_val = xmlHashAddEntry(hash, key, payload); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); + des_const_xmlChar_ptr(n_key, key, 1); des_void_ptr(n_payload, payload, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -9825,9 +10117,9 @@ test_xmlHashAddEntry2(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; void * payload; /* pointer to the payload */ int n_payload; @@ -9842,12 +10134,12 @@ test_xmlHashAddEntry2(void) { key2 = gen_const_xmlChar_ptr(n_key2, 2); payload = gen_void_ptr(n_payload, 3); - ret_val = xmlHashAddEntry2(hash, (const xmlChar *)key, (const xmlChar *)key2, payload); + ret_val = xmlHashAddEntry2(hash, key, key2, payload); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); des_void_ptr(n_payload, payload, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -9878,11 +10170,11 @@ test_xmlHashAddEntry3(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; - xmlChar * key3; /* third string key */ + const xmlChar * key3; /* third string key */ int n_key3; void * payload; /* pointer to the payload */ int n_payload; @@ -9899,13 +10191,13 @@ test_xmlHashAddEntry3(void) { key3 = gen_const_xmlChar_ptr(n_key3, 3); payload = gen_void_ptr(n_payload, 4); - ret_val = xmlHashAddEntry3(hash, (const xmlChar *)key, (const xmlChar *)key2, (const xmlChar *)key3, payload); + ret_val = xmlHashAddEntry3(hash, key, key2, key3, payload); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); - des_const_xmlChar_ptr(n_key3, (const xmlChar *)key3, 3); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_const_xmlChar_ptr(n_key3, key3, 3); des_void_ptr(n_payload, payload, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -9940,6 +10232,16 @@ test_xmlHashCopy(void) { } +static int +test_xmlHashCopySafe(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlHashCreate(void) { int test_ret = 0; @@ -9967,7 +10269,7 @@ test_xmlHashDefaultDeallocator(void) { int mem_base; void * entry; /* hash table entry */ int n_entry; - xmlChar * key; /* the entry's string key */ + const xmlChar * key; /* the entry's string key */ int n_key; for (n_entry = 0;n_entry < gen_nb_void_ptr;n_entry++) { @@ -9976,10 +10278,10 @@ test_xmlHashDefaultDeallocator(void) { entry = gen_void_ptr(n_entry, 0); key = gen_const_xmlChar_ptr(n_key, 1); - xmlHashDefaultDeallocator(entry, (const xmlChar *)key); + xmlHashDefaultDeallocator(entry, key); call_tests++; des_void_ptr(n_entry, entry, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); + des_const_xmlChar_ptr(n_key, key, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashDefaultDeallocator", @@ -10005,7 +10307,7 @@ test_xmlHashLookup(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* string key */ + const xmlChar * key; /* string key */ int n_key; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10014,11 +10316,11 @@ test_xmlHashLookup(void) { hash = gen_xmlHashTablePtr(n_hash, 0); key = gen_const_xmlChar_ptr(n_key, 1); - ret_val = xmlHashLookup(hash, (const xmlChar *)key); + ret_val = xmlHashLookup(hash, key); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); + des_const_xmlChar_ptr(n_key, key, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashLookup", @@ -10044,9 +10346,9 @@ test_xmlHashLookup2(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10057,12 +10359,12 @@ test_xmlHashLookup2(void) { key = gen_const_xmlChar_ptr(n_key, 1); key2 = gen_const_xmlChar_ptr(n_key2, 2); - ret_val = xmlHashLookup2(hash, (const xmlChar *)key, (const xmlChar *)key2); + ret_val = xmlHashLookup2(hash, key, key2); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashLookup2", @@ -10090,11 +10392,11 @@ test_xmlHashLookup3(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; - xmlChar * key3; /* third string key */ + const xmlChar * key3; /* third string key */ int n_key3; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10107,13 +10409,13 @@ test_xmlHashLookup3(void) { key2 = gen_const_xmlChar_ptr(n_key2, 2); key3 = gen_const_xmlChar_ptr(n_key3, 3); - ret_val = xmlHashLookup3(hash, (const xmlChar *)key, (const xmlChar *)key2, (const xmlChar *)key3); + ret_val = xmlHashLookup3(hash, key, key2, key3); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); - des_const_xmlChar_ptr(n_key3, (const xmlChar *)key3, 3); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_const_xmlChar_ptr(n_key3, key3, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashLookup3", @@ -10143,9 +10445,9 @@ test_xmlHashQLookup(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * prefix; /* prefix of the string key */ + const xmlChar * prefix; /* prefix of the string key */ int n_prefix; - xmlChar * name; /* local name of the string key */ + const xmlChar * name; /* local name of the string key */ int n_name; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10156,12 +10458,12 @@ test_xmlHashQLookup(void) { prefix = gen_const_xmlChar_ptr(n_prefix, 1); name = gen_const_xmlChar_ptr(n_name, 2); - ret_val = xmlHashQLookup(hash, (const xmlChar *)prefix, (const xmlChar *)name); + ret_val = xmlHashQLookup(hash, prefix, name); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashQLookup", @@ -10189,13 +10491,13 @@ test_xmlHashQLookup2(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * prefix; /* first prefix */ + const xmlChar * prefix; /* first prefix */ int n_prefix; - xmlChar * name; /* first local name */ + const xmlChar * name; /* first local name */ int n_name; - xmlChar * prefix2; /* second prefix */ + const xmlChar * prefix2; /* second prefix */ int n_prefix2; - xmlChar * name2; /* second local name */ + const xmlChar * name2; /* second local name */ int n_name2; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10210,14 +10512,14 @@ test_xmlHashQLookup2(void) { prefix2 = gen_const_xmlChar_ptr(n_prefix2, 3); name2 = gen_const_xmlChar_ptr(n_name2, 4); - ret_val = xmlHashQLookup2(hash, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)prefix2, (const xmlChar *)name2); + ret_val = xmlHashQLookup2(hash, prefix, name, prefix2, name2); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_prefix2, (const xmlChar *)prefix2, 3); - des_const_xmlChar_ptr(n_name2, (const xmlChar *)name2, 4); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_prefix2, prefix2, 3); + des_const_xmlChar_ptr(n_name2, name2, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashQLookup2", @@ -10249,17 +10551,17 @@ test_xmlHashQLookup3(void) { void * ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * prefix; /* first prefix */ + const xmlChar * prefix; /* first prefix */ int n_prefix; - xmlChar * name; /* first local name */ + const xmlChar * name; /* first local name */ int n_name; - xmlChar * prefix2; /* second prefix */ + const xmlChar * prefix2; /* second prefix */ int n_prefix2; - xmlChar * name2; /* second local name */ + const xmlChar * name2; /* second local name */ int n_name2; - xmlChar * prefix3; /* third prefix */ + const xmlChar * prefix3; /* third prefix */ int n_prefix3; - xmlChar * name3; /* third local name */ + const xmlChar * name3; /* third local name */ int n_name3; for (n_hash = 0;n_hash < gen_nb_xmlHashTablePtr;n_hash++) { @@ -10278,16 +10580,16 @@ test_xmlHashQLookup3(void) { prefix3 = gen_const_xmlChar_ptr(n_prefix3, 5); name3 = gen_const_xmlChar_ptr(n_name3, 6); - ret_val = xmlHashQLookup3(hash, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)prefix2, (const xmlChar *)name2, (const xmlChar *)prefix3, (const xmlChar *)name3); + ret_val = xmlHashQLookup3(hash, prefix, name, prefix2, name2, prefix3, name3); desret_void_ptr(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_prefix2, (const xmlChar *)prefix2, 3); - des_const_xmlChar_ptr(n_name2, (const xmlChar *)name2, 4); - des_const_xmlChar_ptr(n_prefix3, (const xmlChar *)prefix3, 5); - des_const_xmlChar_ptr(n_name3, (const xmlChar *)name3, 6); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_prefix2, prefix2, 3); + des_const_xmlChar_ptr(n_name2, name2, 4); + des_const_xmlChar_ptr(n_prefix3, prefix3, 5); + des_const_xmlChar_ptr(n_name3, name3, 6); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHashQLookup3", @@ -10323,7 +10625,7 @@ test_xmlHashRemoveEntry(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* string key */ + const xmlChar * key; /* string key */ int n_key; xmlHashDeallocator dealloc; /* deallocator function for removed item or NULL */ int n_dealloc; @@ -10336,11 +10638,11 @@ test_xmlHashRemoveEntry(void) { key = gen_const_xmlChar_ptr(n_key, 1); dealloc = gen_xmlHashDeallocator(n_dealloc, 2); - ret_val = xmlHashRemoveEntry(hash, (const xmlChar *)key, dealloc); + ret_val = xmlHashRemoveEntry(hash, key, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); + des_const_xmlChar_ptr(n_key, key, 1); des_xmlHashDeallocator(n_dealloc, dealloc, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -10369,9 +10671,9 @@ test_xmlHashRemoveEntry2(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; xmlHashDeallocator dealloc; /* deallocator function for removed item or NULL */ int n_dealloc; @@ -10386,12 +10688,12 @@ test_xmlHashRemoveEntry2(void) { key2 = gen_const_xmlChar_ptr(n_key2, 2); dealloc = gen_xmlHashDeallocator(n_dealloc, 3); - ret_val = xmlHashRemoveEntry2(hash, (const xmlChar *)key, (const xmlChar *)key2, dealloc); + ret_val = xmlHashRemoveEntry2(hash, key, key2, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); des_xmlHashDeallocator(n_dealloc, dealloc, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -10422,11 +10724,11 @@ test_xmlHashRemoveEntry3(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; - xmlChar * key3; /* third string key */ + const xmlChar * key3; /* third string key */ int n_key3; xmlHashDeallocator dealloc; /* deallocator function for removed item or NULL */ int n_dealloc; @@ -10443,13 +10745,13 @@ test_xmlHashRemoveEntry3(void) { key3 = gen_const_xmlChar_ptr(n_key3, 3); dealloc = gen_xmlHashDeallocator(n_dealloc, 4); - ret_val = xmlHashRemoveEntry3(hash, (const xmlChar *)key, (const xmlChar *)key2, (const xmlChar *)key3, dealloc); + ret_val = xmlHashRemoveEntry3(hash, key, key2, key3, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); - des_const_xmlChar_ptr(n_key3, (const xmlChar *)key3, 3); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_const_xmlChar_ptr(n_key3, key3, 3); des_xmlHashDeallocator(n_dealloc, dealloc, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -10554,7 +10856,7 @@ test_xmlHashUpdateEntry(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* string key */ + const xmlChar * key; /* string key */ int n_key; void * payload; /* pointer to the payload */ int n_payload; @@ -10571,11 +10873,11 @@ test_xmlHashUpdateEntry(void) { payload = gen_void_ptr(n_payload, 2); dealloc = gen_xmlHashDeallocator(n_dealloc, 3); - ret_val = xmlHashUpdateEntry(hash, (const xmlChar *)key, payload, dealloc); + ret_val = xmlHashUpdateEntry(hash, key, payload, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); + des_const_xmlChar_ptr(n_key, key, 1); des_void_ptr(n_payload, payload, 2); des_xmlHashDeallocator(n_dealloc, dealloc, 3); xmlResetLastError(); @@ -10607,9 +10909,9 @@ test_xmlHashUpdateEntry2(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; void * payload; /* pointer to the payload */ int n_payload; @@ -10628,12 +10930,12 @@ test_xmlHashUpdateEntry2(void) { payload = gen_void_ptr(n_payload, 3); dealloc = gen_xmlHashDeallocator(n_dealloc, 4); - ret_val = xmlHashUpdateEntry2(hash, (const xmlChar *)key, (const xmlChar *)key2, payload, dealloc); + ret_val = xmlHashUpdateEntry2(hash, key, key2, payload, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); des_void_ptr(n_payload, payload, 3); des_xmlHashDeallocator(n_dealloc, dealloc, 4); xmlResetLastError(); @@ -10667,11 +10969,11 @@ test_xmlHashUpdateEntry3(void) { int ret_val; xmlHashTablePtr hash; /* hash table */ int n_hash; - xmlChar * key; /* first string key */ + const xmlChar * key; /* first string key */ int n_key; - xmlChar * key2; /* second string key */ + const xmlChar * key2; /* second string key */ int n_key2; - xmlChar * key3; /* third string key */ + const xmlChar * key3; /* third string key */ int n_key3; void * payload; /* pointer to the payload */ int n_payload; @@ -10692,13 +10994,13 @@ test_xmlHashUpdateEntry3(void) { payload = gen_void_ptr(n_payload, 4); dealloc = gen_xmlHashDeallocator(n_dealloc, 5); - ret_val = xmlHashUpdateEntry3(hash, (const xmlChar *)key, (const xmlChar *)key2, (const xmlChar *)key3, payload, dealloc); + ret_val = xmlHashUpdateEntry3(hash, key, key2, key3, payload, dealloc); desret_int(ret_val); call_tests++; des_xmlHashTablePtr(n_hash, hash, 0); - des_const_xmlChar_ptr(n_key, (const xmlChar *)key, 1); - des_const_xmlChar_ptr(n_key2, (const xmlChar *)key2, 2); - des_const_xmlChar_ptr(n_key3, (const xmlChar *)key3, 3); + des_const_xmlChar_ptr(n_key, key, 1); + des_const_xmlChar_ptr(n_key2, key2, 2); + des_const_xmlChar_ptr(n_key3, key3, 3); des_void_ptr(n_payload, payload, 4); des_xmlHashDeallocator(n_dealloc, dealloc, 5); xmlResetLastError(); @@ -10729,11 +11031,15 @@ static int test_hash(void) { int test_ret = 0; - if (quiet == 0) printf("Testing hash : 17 of 25 functions ...\n"); + if (quiet == 0) printf("Testing hash : 20 of 29 functions ...\n"); + test_ret += test_xmlHashAdd(); + test_ret += test_xmlHashAdd2(); + test_ret += test_xmlHashAdd3(); test_ret += test_xmlHashAddEntry(); test_ret += test_xmlHashAddEntry2(); test_ret += test_xmlHashAddEntry3(); test_ret += test_xmlHashCopy(); + test_ret += test_xmlHashCopySafe(); test_ret += test_xmlHashCreate(); test_ret += test_xmlHashCreateDict(); test_ret += test_xmlHashDefaultDeallocator(); @@ -10865,10 +11171,6 @@ test_xmlListClear(void) { } -#define gen_nb_const_xmlListPtr 1 -#define gen_const_xmlListPtr(no, nr) NULL -#define des_const_xmlListPtr(no, val, nr) - static int test_xmlListCopy(void) { int test_ret = 0; @@ -10881,16 +11183,16 @@ test_xmlListCopy(void) { int n_old; for (n_cur = 0;n_cur < gen_nb_xmlListPtr;n_cur++) { - for (n_old = 0;n_old < gen_nb_const_xmlListPtr;n_old++) { + for (n_old = 0;n_old < gen_nb_xmlListPtr;n_old++) { mem_base = xmlMemBlocks(); cur = gen_xmlListPtr(n_cur, 0); - old = gen_const_xmlListPtr(n_old, 1); + old = gen_xmlListPtr(n_old, 1); - ret_val = xmlListCopy(cur, (const xmlListPtr)old); + ret_val = xmlListCopy(cur, old); desret_int(ret_val); call_tests++; des_xmlListPtr(n_cur, cur, 0); - des_const_xmlListPtr(n_old, (const xmlListPtr)old, 1); + des_xmlListPtr(n_old, old, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlListCopy", @@ -12075,6 +12377,29 @@ test_xmlByteConsumed(void) { } +static int +test_xmlCleanupGlobals(void) { + int test_ret = 0; + + int mem_base; + + mem_base = xmlMemBlocks(); + + xmlCleanupGlobals(); + call_tests++; + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCleanupGlobals", + xmlMemBlocks() - mem_base); + test_ret++; + printf("\n"); + } + function_tests++; + + return(test_ret); +} + + static int test_xmlClearNodeInfoSeq(void) { int test_ret = 0; @@ -12141,17 +12466,17 @@ test_xmlCreateDocParserCtxt(void) { int mem_base; xmlParserCtxtPtr ret_val; - xmlChar * str; /* a pointer to an array of xmlChar */ + const xmlChar * str; /* a pointer to an array of xmlChar */ int n_str; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { mem_base = xmlMemBlocks(); str = gen_const_xmlChar_ptr(n_str, 0); - ret_val = xmlCreateDocParserCtxt((const xmlChar *)str); + ret_val = xmlCreateDocParserCtxt(str); desret_xmlParserCtxtPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCreateDocParserCtxt", @@ -12174,15 +12499,15 @@ test_xmlCreatePushParserCtxt(void) { #if defined(LIBXML_PUSH_ENABLED) int mem_base; xmlParserCtxtPtr ret_val; - xmlSAXHandlerPtr sax; /* a SAX handler */ + xmlSAXHandlerPtr sax; /* a SAX handler (optional) */ int n_sax; - void * user_data; /* The user data returned on SAX callbacks */ + void * user_data; /* user data for SAX callbacks (optional) */ int n_user_data; - char * chunk; /* a pointer to an array of chars */ + const char * chunk; /* initial chunk (optional, deprecated) */ int n_chunk; - int size; /* number of chars in the array */ + int size; /* size of initial chunk in bytes */ int n_size; - const char * filename; /* an optional file name or URI */ + const char * filename; /* file name or URI (optional) */ int n_filename; for (n_sax = 0;n_sax < gen_nb_xmlSAXHandlerPtr;n_sax++) { @@ -12200,12 +12525,12 @@ test_xmlCreatePushParserCtxt(void) { (size > xmlStrlen(BAD_CAST chunk))) size = 0; - ret_val = xmlCreatePushParserCtxt(sax, user_data, (const char *)chunk, size, filename); + ret_val = xmlCreatePushParserCtxt(sax, user_data, chunk, size, filename); desret_xmlParserCtxtPtr(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); des_userdata(n_user_data, user_data, 1); - des_const_char_ptr(n_chunk, (const char *)chunk, 2); + des_const_char_ptr(n_chunk, chunk, 2); des_int(n_size, size, 3); des_fileoutput(n_filename, filename, 4); xmlResetLastError(); @@ -12232,6 +12557,45 @@ test_xmlCreatePushParserCtxt(void) { } +static int +test_xmlCtxtParseDocument(void) { + int test_ret = 0; + + int mem_base; + xmlDocPtr ret_val; + xmlParserCtxtPtr ctxt; /* an XML parser context */ + int n_ctxt; + xmlParserInputPtr input; /* parser input */ + int n_input; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + for (n_input = 0;n_input < gen_nb_xmlParserInputPtr;n_input++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + input = gen_xmlParserInputPtr(n_input, 1); + + ret_val = xmlCtxtParseDocument(ctxt, input); + desret_xmlDocPtr(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_xmlParserInputPtr(n_input, input, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtParseDocument", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_input); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCtxtReadDoc(void) { int test_ret = 0; @@ -12240,11 +12604,11 @@ test_xmlCtxtReadDoc(void) { xmlDocPtr ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlChar * str; /* a pointer to a zero terminated string */ + const xmlChar * str; /* a pointer to a zero terminated string */ int n_str; - const char * URL; /* the base URL to use for the document */ + const char * URL; /* base URL (optional) */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -12261,13 +12625,13 @@ test_xmlCtxtReadDoc(void) { encoding = gen_const_char_ptr(n_encoding, 3); options = gen_parseroptions(n_options, 4); - ret_val = xmlCtxtReadDoc(ctxt, (const xmlChar *)str, URL, (const char *)encoding, options); + ret_val = xmlCtxtReadDoc(ctxt, str, URL, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_parseroptions(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12302,7 +12666,7 @@ test_xmlCtxtReadFile(void) { int n_ctxt; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -12317,12 +12681,12 @@ test_xmlCtxtReadFile(void) { encoding = gen_const_char_ptr(n_encoding, 2); options = gen_parseroptions(n_options, 3); - ret_val = xmlCtxtReadFile(ctxt, filename, (const char *)encoding, options); + ret_val = xmlCtxtReadFile(ctxt, filename, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); des_filepath(n_filename, filename, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_parseroptions(n_options, options, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12353,13 +12717,13 @@ test_xmlCtxtReadMemory(void) { xmlDocPtr ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; - const char * URL; /* the base URL to use for the document */ + const char * URL; /* base URL (optional) */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -12381,14 +12745,14 @@ test_xmlCtxtReadMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlCtxtReadMemory(ctxt, (const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = xmlCtxtReadMemory(ctxt, buffer, size, URL, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_char_ptr(n_buffer, (const char *)buffer, 1); + des_const_char_ptr(n_buffer, buffer, 1); des_int(n_size, size, 2); des_filepath(n_URL, URL, 3); - des_const_char_ptr(n_encoding, (const char *)encoding, 4); + des_const_char_ptr(n_encoding, encoding, 4); des_parseroptions(n_options, options, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12453,13 +12817,13 @@ test_xmlCtxtResetPush(void) { int ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - char * chunk; /* a pointer to an array of chars */ + const char * chunk; /* a pointer to an array of chars */ int n_chunk; int size; /* number of chars in the array */ int n_size; const char * filename; /* an optional file name or URI */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { @@ -12477,14 +12841,14 @@ test_xmlCtxtResetPush(void) { (size > xmlStrlen(BAD_CAST chunk))) size = 0; - ret_val = xmlCtxtResetPush(ctxt, (const char *)chunk, size, filename, (const char *)encoding); + ret_val = xmlCtxtResetPush(ctxt, chunk, size, filename, encoding); desret_int(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_char_ptr(n_chunk, (const char *)chunk, 1); + des_const_char_ptr(n_chunk, chunk, 1); des_int(n_size, size, 2); des_filepath(n_filename, filename, 3); - des_const_char_ptr(n_encoding, (const char *)encoding, 4); + des_const_char_ptr(n_encoding, encoding, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCtxtResetPush", @@ -12508,6 +12872,16 @@ test_xmlCtxtResetPush(void) { } +static int +test_xmlCtxtSetErrorHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlCtxtSetMaxAmplification(void) { int test_ret = 0; @@ -12518,6 +12892,45 @@ test_xmlCtxtSetMaxAmplification(void) { } +static int +test_xmlCtxtSetOptions(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlParserCtxtPtr ctxt; /* an XML parser context */ + int n_ctxt; + int options; /* a bitmask of xmlParserOption values */ + int n_options; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + for (n_options = 0;n_options < gen_nb_parseroptions;n_options++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + options = gen_parseroptions(n_options, 1); + + ret_val = xmlCtxtSetOptions(ctxt, options); + desret_int(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_parseroptions(n_options, options, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtSetOptions", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_options); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCtxtUseOptions(void) { int test_ret = 0; @@ -12639,6 +13052,29 @@ test_xmlIOParseDTD(void) { } +static int +test_xmlInitGlobals(void) { + int test_ret = 0; + + int mem_base; + + mem_base = xmlMemBlocks(); + + xmlInitGlobals(); + call_tests++; + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlInitGlobals", + xmlMemBlocks() - mem_base); + test_ret++; + printf("\n"); + } + function_tests++; + + return(test_ret); +} + + static int test_xmlInitNodeInfoSeq(void) { int test_ret = 0; @@ -12796,7 +13232,7 @@ test_xmlLoadExternalEntity(void) { xmlParserInputPtr ret_val; const char * URL; /* the URL for the entity to load */ int n_URL; - char * ID; /* the Public ID for the entity to load */ + const char * ID; /* the Public ID for the entity to load */ int n_ID; xmlParserCtxtPtr ctxt; /* the context in which the entity is called or NULL */ int n_ctxt; @@ -12809,11 +13245,11 @@ test_xmlLoadExternalEntity(void) { ID = gen_const_char_ptr(n_ID, 1); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 2); - ret_val = xmlLoadExternalEntity(URL, (const char *)ID, ctxt); + ret_val = xmlLoadExternalEntity(URL, ID, ctxt); desret_xmlParserInputPtr(ret_val); call_tests++; des_filepath(n_URL, URL, 0); - des_const_char_ptr(n_ID, (const char *)ID, 1); + des_const_char_ptr(n_ID, ID, 1); des_xmlParserCtxtPtr(n_ctxt, ctxt, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12842,25 +13278,25 @@ test_xmlNewIOInputStream(void) { xmlParserInputPtr ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlParserInputBufferPtr input; /* an I/O Input */ - int n_input; + xmlParserInputBufferPtr buf; /* an input buffer */ + int n_buf; xmlCharEncoding enc; /* the charset encoding if known */ int n_enc; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { - for (n_input = 0;n_input < gen_nb_xmlParserInputBufferPtr;n_input++) { + for (n_buf = 0;n_buf < gen_nb_xmlParserInputBufferPtr;n_buf++) { for (n_enc = 0;n_enc < gen_nb_xmlCharEncoding;n_enc++) { mem_base = xmlMemBlocks(); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); - input = gen_xmlParserInputBufferPtr(n_input, 1); + buf = gen_xmlParserInputBufferPtr(n_buf, 1); enc = gen_xmlCharEncoding(n_enc, 2); - ret_val = xmlNewIOInputStream(ctxt, input, enc); - if (ret_val != NULL) input = NULL; + ret_val = xmlNewIOInputStream(ctxt, buf, enc); + if (ret_val != NULL) buf = NULL; desret_xmlParserInputPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_xmlParserInputBufferPtr(n_input, input, 1); + des_xmlParserInputBufferPtr(n_buf, buf, 1); des_xmlCharEncoding(n_enc, enc, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12868,7 +13304,7 @@ test_xmlNewIOInputStream(void) { xmlMemBlocks() - mem_base); test_ret++; printf(" %d", n_ctxt); - printf(" %d", n_input); + printf(" %d", n_buf); printf(" %d", n_enc); printf("\n"); } @@ -12916,7 +13352,7 @@ test_xmlNewSAXParserCtxt(void) { int mem_base; xmlParserCtxtPtr ret_val; - xmlSAXHandler * sax; /* SAX handler */ + const xmlSAXHandler * sax; /* SAX handler */ int n_sax; void * userData; /* user data */ int n_userData; @@ -12927,10 +13363,10 @@ test_xmlNewSAXParserCtxt(void) { sax = gen_const_xmlSAXHandler_ptr(n_sax, 0); userData = gen_userdata(n_userData, 1); - ret_val = xmlNewSAXParserCtxt((const xmlSAXHandler *)sax, userData); + ret_val = xmlNewSAXParserCtxt(sax, userData); desret_xmlParserCtxtPtr(ret_val); call_tests++; - des_const_xmlSAXHandler_ptr(n_sax, (const xmlSAXHandler *)sax, 0); + des_const_xmlSAXHandler_ptr(n_sax, sax, 0); des_userdata(n_userData, userData, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -12969,7 +13405,7 @@ test_xmlParseBalancedChunkMemory(void) { int n_user_data; int depth; /* Used for loop detection, use 0 */ int n_depth; - xmlChar * string; /* the input string in UTF8 or ISO-Latin (zero terminated) */ + const xmlChar * string; /* the input string in UTF8 or ISO-Latin (zero terminated) */ int n_string; xmlNodePtr * lst; /* the return value for the set of parsed nodes */ int n_lst; @@ -12993,14 +13429,14 @@ test_xmlParseBalancedChunkMemory(void) { #endif - ret_val = xmlParseBalancedChunkMemory(doc, sax, user_data, depth, (const xmlChar *)string, lst); + ret_val = xmlParseBalancedChunkMemory(doc, sax, user_data, depth, string, lst); desret_int(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlSAXHandlerPtr(n_sax, sax, 1); des_userdata(n_user_data, user_data, 2); des_int(n_depth, depth, 3); - des_const_xmlChar_ptr(n_string, (const xmlChar *)string, 4); + des_const_xmlChar_ptr(n_string, string, 4); des_xmlNodePtr_ptr(n_lst, lst, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -13045,10 +13481,10 @@ test_xmlParseBalancedChunkMemoryRecover(void) { int n_user_data; int depth; /* Used for loop detection, use 0 */ int n_depth; - xmlChar * string; /* the input string in UTF8 or ISO-Latin (zero terminated) */ + const xmlChar * string; /* the input string in UTF8 or ISO-Latin (zero terminated) */ int n_string; - xmlNodePtr * lst; /* the return value for the set of parsed nodes */ - int n_lst; + xmlNodePtr * listOut; /* the return value for the set of parsed nodes */ + int n_listOut; int recover; /* return nodes even if the data is broken (use 0) */ int n_recover; @@ -13057,7 +13493,7 @@ test_xmlParseBalancedChunkMemoryRecover(void) { for (n_user_data = 0;n_user_data < gen_nb_userdata;n_user_data++) { for (n_depth = 0;n_depth < gen_nb_int;n_depth++) { for (n_string = 0;n_string < gen_nb_const_xmlChar_ptr;n_string++) { - for (n_lst = 0;n_lst < gen_nb_xmlNodePtr_ptr;n_lst++) { + for (n_listOut = 0;n_listOut < gen_nb_xmlNodePtr_ptr;n_listOut++) { for (n_recover = 0;n_recover < gen_nb_int;n_recover++) { mem_base = xmlMemBlocks(); doc = gen_xmlDocPtr(n_doc, 0); @@ -13065,7 +13501,7 @@ test_xmlParseBalancedChunkMemoryRecover(void) { user_data = gen_userdata(n_user_data, 2); depth = gen_int(n_depth, 3); string = gen_const_xmlChar_ptr(n_string, 4); - lst = gen_xmlNodePtr_ptr(n_lst, 5); + listOut = gen_xmlNodePtr_ptr(n_listOut, 5); recover = gen_int(n_recover, 6); #ifdef LIBXML_SAX1_ENABLED @@ -13073,15 +13509,15 @@ test_xmlParseBalancedChunkMemoryRecover(void) { #endif - ret_val = xmlParseBalancedChunkMemoryRecover(doc, sax, user_data, depth, (const xmlChar *)string, lst, recover); + ret_val = xmlParseBalancedChunkMemoryRecover(doc, sax, user_data, depth, string, listOut, recover); desret_int(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlSAXHandlerPtr(n_sax, sax, 1); des_userdata(n_user_data, user_data, 2); des_int(n_depth, depth, 3); - des_const_xmlChar_ptr(n_string, (const xmlChar *)string, 4); - des_xmlNodePtr_ptr(n_lst, lst, 5); + des_const_xmlChar_ptr(n_string, string, 4); + des_xmlNodePtr_ptr(n_listOut, listOut, 5); des_int(n_recover, recover, 6); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -13093,7 +13529,7 @@ test_xmlParseBalancedChunkMemoryRecover(void) { printf(" %d", n_user_data); printf(" %d", n_depth); printf(" %d", n_string); - printf(" %d", n_lst); + printf(" %d", n_listOut); printf(" %d", n_recover); printf("\n"); } @@ -13121,9 +13557,9 @@ test_xmlParseChunk(void) { int ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - char * chunk; /* an char array */ + const char * chunk; /* chunk of memory */ int n_chunk; - int size; /* the size in byte of the chunk */ + int size; /* size of chunk in bytes */ int n_size; int terminate; /* last chunk indicator */ int n_terminate; @@ -13141,12 +13577,12 @@ test_xmlParseChunk(void) { (size > xmlStrlen(BAD_CAST chunk))) size = 0; - ret_val = xmlParseChunk(ctxt, (const char *)chunk, size, terminate); + ret_val = xmlParseChunk(ctxt, chunk, size, terminate); if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} desret_int(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_char_ptr(n_chunk, (const char *)chunk, 1); + des_const_char_ptr(n_chunk, chunk, 1); des_int(n_size, size, 2); des_int(n_terminate, terminate, 3); xmlResetLastError(); @@ -13177,41 +13613,41 @@ test_xmlParseCtxtExternalEntity(void) { int mem_base; int ret_val; - xmlParserCtxtPtr ctx; /* the existing parsing context */ - int n_ctx; - xmlChar * URL; /* the URL for the entity to load */ + xmlParserCtxtPtr ctxt; /* the existing parsing context */ + int n_ctxt; + const xmlChar * URL; /* the URL for the entity to load */ int n_URL; - xmlChar * ID; /* the System ID for the entity to load */ + const xmlChar * ID; /* the System ID for the entity to load */ int n_ID; - xmlNodePtr * lst; /* the return value for the set of parsed nodes */ - int n_lst; + xmlNodePtr * listOut; /* the return value for the set of parsed nodes */ + int n_listOut; - for (n_ctx = 0;n_ctx < gen_nb_xmlParserCtxtPtr;n_ctx++) { + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { for (n_URL = 0;n_URL < gen_nb_const_xmlChar_ptr;n_URL++) { for (n_ID = 0;n_ID < gen_nb_const_xmlChar_ptr;n_ID++) { - for (n_lst = 0;n_lst < gen_nb_xmlNodePtr_ptr;n_lst++) { + for (n_listOut = 0;n_listOut < gen_nb_xmlNodePtr_ptr;n_listOut++) { mem_base = xmlMemBlocks(); - ctx = gen_xmlParserCtxtPtr(n_ctx, 0); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); URL = gen_const_xmlChar_ptr(n_URL, 1); ID = gen_const_xmlChar_ptr(n_ID, 2); - lst = gen_xmlNodePtr_ptr(n_lst, 3); + listOut = gen_xmlNodePtr_ptr(n_listOut, 3); - ret_val = xmlParseCtxtExternalEntity(ctx, (const xmlChar *)URL, (const xmlChar *)ID, lst); + ret_val = xmlParseCtxtExternalEntity(ctxt, URL, ID, listOut); desret_int(ret_val); call_tests++; - des_xmlParserCtxtPtr(n_ctx, ctx, 0); - des_const_xmlChar_ptr(n_URL, (const xmlChar *)URL, 1); - des_const_xmlChar_ptr(n_ID, (const xmlChar *)ID, 2); - des_xmlNodePtr_ptr(n_lst, lst, 3); + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_const_xmlChar_ptr(n_URL, URL, 1); + des_const_xmlChar_ptr(n_ID, ID, 2); + des_xmlNodePtr_ptr(n_listOut, listOut, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseCtxtExternalEntity", xmlMemBlocks() - mem_base); test_ret++; - printf(" %d", n_ctx); + printf(" %d", n_ctxt); printf(" %d", n_URL); printf(" %d", n_ID); - printf(" %d", n_lst); + printf(" %d", n_listOut); printf("\n"); } } @@ -13232,9 +13668,9 @@ test_xmlParseDTD(void) { #ifdef LIBXML_VALID_ENABLED int mem_base; xmlDtdPtr ret_val; - xmlChar * ExternalID; /* a NAME* containing the External ID of the DTD */ + const xmlChar * ExternalID; /* a NAME* containing the External ID of the DTD */ int n_ExternalID; - xmlChar * SystemID; /* a NAME* containing the URL to the DTD */ + const xmlChar * SystemID; /* a NAME* containing the URL to the DTD */ int n_SystemID; for (n_ExternalID = 0;n_ExternalID < gen_nb_const_xmlChar_ptr;n_ExternalID++) { @@ -13243,11 +13679,11 @@ test_xmlParseDTD(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 0); SystemID = gen_const_xmlChar_ptr(n_SystemID, 1); - ret_val = xmlParseDTD((const xmlChar *)ExternalID, (const xmlChar *)SystemID); + ret_val = xmlParseDTD(ExternalID, SystemID); desret_xmlDtdPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 0); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 1); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 0); + des_const_xmlChar_ptr(n_SystemID, SystemID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseDTD", @@ -13275,17 +13711,17 @@ test_xmlParseDoc(void) { #ifdef LIBXML_SAX1_ENABLED int mem_base; xmlDocPtr ret_val; - xmlChar * cur; /* a pointer to an array of xmlChar */ + const xmlChar * cur; /* a pointer to an array of xmlChar */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlChar_ptr(n_cur, 0); - ret_val = xmlParseDoc((const xmlChar *)cur); + ret_val = xmlParseDoc(cur); desret_xmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseDoc", @@ -13421,12 +13857,12 @@ test_xmlParseExternalEntity(void) { int n_user_data; int depth; /* Used for loop detection, use 0 */ int n_depth; - xmlChar * URL; /* the URL for the entity to load */ + const xmlChar * URL; /* the URL for the entity to load */ int n_URL; - xmlChar * ID; /* the System ID for the entity to load */ + const xmlChar * ID; /* the System ID for the entity to load */ int n_ID; - xmlNodePtr * lst; /* the return value for the set of parsed nodes */ - int n_lst; + xmlNodePtr * list; /* the return value for the set of parsed nodes */ + int n_list; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { for (n_sax = 0;n_sax < gen_nb_xmlSAXHandlerPtr;n_sax++) { @@ -13434,7 +13870,7 @@ test_xmlParseExternalEntity(void) { for (n_depth = 0;n_depth < gen_nb_int;n_depth++) { for (n_URL = 0;n_URL < gen_nb_const_xmlChar_ptr;n_URL++) { for (n_ID = 0;n_ID < gen_nb_const_xmlChar_ptr;n_ID++) { - for (n_lst = 0;n_lst < gen_nb_xmlNodePtr_ptr;n_lst++) { + for (n_list = 0;n_list < gen_nb_xmlNodePtr_ptr;n_list++) { mem_base = xmlMemBlocks(); doc = gen_xmlDocPtr(n_doc, 0); sax = gen_xmlSAXHandlerPtr(n_sax, 1); @@ -13442,18 +13878,18 @@ test_xmlParseExternalEntity(void) { depth = gen_int(n_depth, 3); URL = gen_const_xmlChar_ptr(n_URL, 4); ID = gen_const_xmlChar_ptr(n_ID, 5); - lst = gen_xmlNodePtr_ptr(n_lst, 6); + list = gen_xmlNodePtr_ptr(n_list, 6); - ret_val = xmlParseExternalEntity(doc, sax, user_data, depth, (const xmlChar *)URL, (const xmlChar *)ID, lst); + ret_val = xmlParseExternalEntity(doc, sax, user_data, depth, URL, ID, list); desret_int(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlSAXHandlerPtr(n_sax, sax, 1); des_userdata(n_user_data, user_data, 2); des_int(n_depth, depth, 3); - des_const_xmlChar_ptr(n_URL, (const xmlChar *)URL, 4); - des_const_xmlChar_ptr(n_ID, (const xmlChar *)ID, 5); - des_xmlNodePtr_ptr(n_lst, lst, 6); + des_const_xmlChar_ptr(n_URL, URL, 4); + des_const_xmlChar_ptr(n_ID, ID, 5); + des_xmlNodePtr_ptr(n_list, list, 6); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseExternalEntity", @@ -13465,7 +13901,7 @@ test_xmlParseExternalEntity(void) { printf(" %d", n_depth); printf(" %d", n_URL); printf(" %d", n_ID); - printf(" %d", n_lst); + printf(" %d", n_list); printf("\n"); } } @@ -13527,7 +13963,7 @@ test_xmlParseInNodeContext(void) { xmlParserErrors ret_val; xmlNodePtr node; /* the context node */ int n_node; - char * data; /* the input string */ + const char * data; /* the input string */ int n_data; int datalen; /* the input string length in bytes */ int n_datalen; @@ -13548,11 +13984,11 @@ test_xmlParseInNodeContext(void) { options = gen_parseroptions(n_options, 3); lst = gen_xmlNodePtr_ptr(n_lst, 4); - ret_val = xmlParseInNodeContext(node, (const char *)data, datalen, options, lst); + ret_val = xmlParseInNodeContext(node, data, datalen, options, lst); desret_xmlParserErrors(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_char_ptr(n_data, (const char *)data, 1); + des_const_char_ptr(n_data, data, 1); des_int(n_datalen, datalen, 2); des_parseroptions(n_options, options, 3); des_xmlNodePtr_ptr(n_lst, lst, 4); @@ -13587,7 +14023,7 @@ test_xmlParseMemory(void) { #ifdef LIBXML_SAX1_ENABLED int mem_base; xmlDocPtr ret_val; - char * buffer; /* an pointer to a char array */ + const char * buffer; /* an pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -13601,10 +14037,10 @@ test_xmlParseMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlParseMemory((const char *)buffer, size); + ret_val = xmlParseMemory(buffer, size); desret_xmlDocPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -13625,9 +14061,9 @@ test_xmlParseMemory(void) { } -#define gen_nb_const_xmlParserNodeInfoPtr 1 -#define gen_const_xmlParserNodeInfoPtr(no, nr) NULL -#define des_const_xmlParserNodeInfoPtr(no, val, nr) +#define gen_nb_xmlParserNodeInfoPtr 1 +#define gen_xmlParserNodeInfoPtr(no, nr) NULL +#define des_xmlParserNodeInfoPtr(no, val, nr) static int test_xmlParserAddNodeInfo(void) { @@ -13640,15 +14076,15 @@ test_xmlParserAddNodeInfo(void) { int n_info; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { - for (n_info = 0;n_info < gen_nb_const_xmlParserNodeInfoPtr;n_info++) { + for (n_info = 0;n_info < gen_nb_xmlParserNodeInfoPtr;n_info++) { mem_base = xmlMemBlocks(); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); - info = gen_const_xmlParserNodeInfoPtr(n_info, 1); + info = gen_xmlParserNodeInfoPtr(n_info, 1); - xmlParserAddNodeInfo(ctxt, (const xmlParserNodeInfoPtr)info); + xmlParserAddNodeInfo(ctxt, info); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlParserNodeInfoPtr(n_info, (const xmlParserNodeInfoPtr)info, 1); + des_xmlParserNodeInfoPtr(n_info, info, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParserAddNodeInfo", @@ -13666,14 +14102,6 @@ test_xmlParserAddNodeInfo(void) { } -#define gen_nb_const_xmlParserCtxtPtr 1 -#define gen_const_xmlParserCtxtPtr(no, nr) NULL -#define des_const_xmlParserCtxtPtr(no, val, nr) - -#define gen_nb_const_xmlNodePtr 1 -#define gen_const_xmlNodePtr(no, nr) NULL -#define des_const_xmlNodePtr(no, val, nr) - static int test_xmlParserFindNodeInfo(void) { int test_ret = 0; @@ -13685,17 +14113,17 @@ test_xmlParserFindNodeInfo(void) { xmlNodePtr node; /* an XML node within the tree */ int n_node; - for (n_ctx = 0;n_ctx < gen_nb_const_xmlParserCtxtPtr;n_ctx++) { - for (n_node = 0;n_node < gen_nb_const_xmlNodePtr;n_node++) { + for (n_ctx = 0;n_ctx < gen_nb_xmlParserCtxtPtr;n_ctx++) { + for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { mem_base = xmlMemBlocks(); - ctx = gen_const_xmlParserCtxtPtr(n_ctx, 0); - node = gen_const_xmlNodePtr(n_node, 1); + ctx = gen_xmlParserCtxtPtr(n_ctx, 0); + node = gen_xmlNodePtr(n_node, 1); - ret_val = xmlParserFindNodeInfo((const xmlParserCtxtPtr)ctx, (const xmlNodePtr)node); + ret_val = xmlParserFindNodeInfo(ctx, node); desret_const_xmlParserNodeInfo_ptr(ret_val); call_tests++; - des_const_xmlParserCtxtPtr(n_ctx, (const xmlParserCtxtPtr)ctx, 0); - des_const_xmlNodePtr(n_node, (const xmlNodePtr)node, 1); + des_xmlParserCtxtPtr(n_ctx, ctx, 0); + des_xmlNodePtr(n_node, node, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParserFindNodeInfo", @@ -13713,10 +14141,6 @@ test_xmlParserFindNodeInfo(void) { } -#define gen_nb_const_xmlParserNodeInfoSeqPtr 1 -#define gen_const_xmlParserNodeInfoSeqPtr(no, nr) NULL -#define des_const_xmlParserNodeInfoSeqPtr(no, val, nr) - static int test_xmlParserFindNodeInfoIndex(void) { int test_ret = 0; @@ -13728,17 +14152,17 @@ test_xmlParserFindNodeInfoIndex(void) { xmlNodePtr node; /* an XML node pointer */ int n_node; - for (n_seq = 0;n_seq < gen_nb_const_xmlParserNodeInfoSeqPtr;n_seq++) { - for (n_node = 0;n_node < gen_nb_const_xmlNodePtr;n_node++) { + for (n_seq = 0;n_seq < gen_nb_xmlParserNodeInfoSeqPtr;n_seq++) { + for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { mem_base = xmlMemBlocks(); - seq = gen_const_xmlParserNodeInfoSeqPtr(n_seq, 0); - node = gen_const_xmlNodePtr(n_node, 1); + seq = gen_xmlParserNodeInfoSeqPtr(n_seq, 0); + node = gen_xmlNodePtr(n_node, 1); - ret_val = xmlParserFindNodeInfoIndex((const xmlParserNodeInfoSeqPtr)seq, (const xmlNodePtr)node); + ret_val = xmlParserFindNodeInfoIndex(seq, node); desret_unsigned_long(ret_val); call_tests++; - des_const_xmlParserNodeInfoSeqPtr(n_seq, (const xmlParserNodeInfoSeqPtr)seq, 0); - des_const_xmlNodePtr(n_node, (const xmlNodePtr)node, 1); + des_xmlParserNodeInfoSeqPtr(n_seq, seq, 0); + des_xmlNodePtr(n_node, node, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParserFindNodeInfoIndex", @@ -13756,10 +14180,6 @@ test_xmlParserFindNodeInfoIndex(void) { } -#define gen_nb_xmlParserInputPtr 1 -#define gen_xmlParserInputPtr(no, nr) NULL -#define des_xmlParserInputPtr(no, val, nr) - static int test_xmlParserInputGrow(void) { int test_ret = 0; @@ -13876,11 +14296,11 @@ test_xmlReadDoc(void) { int mem_base; xmlDocPtr ret_val; - xmlChar * cur; /* a pointer to a zero terminated string */ + const xmlChar * cur; /* a pointer to a zero terminated string */ int n_cur; - const char * URL; /* the base URL to use for the document */ + const char * URL; /* base URL (optional) */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -13895,12 +14315,12 @@ test_xmlReadDoc(void) { encoding = gen_const_char_ptr(n_encoding, 2); options = gen_parseroptions(n_options, 3); - ret_val = xmlReadDoc((const xmlChar *)cur, URL, (const char *)encoding, options); + ret_val = xmlReadDoc(cur, URL, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); des_filepath(n_URL, URL, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_parseroptions(n_options, options, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -13931,7 +14351,7 @@ test_xmlReadFile(void) { xmlDocPtr ret_val; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -13944,11 +14364,11 @@ test_xmlReadFile(void) { encoding = gen_const_char_ptr(n_encoding, 1); options = gen_parseroptions(n_options, 2); - ret_val = xmlReadFile(filename, (const char *)encoding, options); + ret_val = xmlReadFile(filename, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; des_filepath(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); des_parseroptions(n_options, options, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -13975,39 +14395,39 @@ test_xmlReadMemory(void) { int mem_base; xmlDocPtr ret_val; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; - const char * URL; /* the base URL to use for the document */ - int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * url; /* base URL (optional) */ + int n_url; + const char * encoding; /* the document encoding (optional) */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; for (n_buffer = 0;n_buffer < gen_nb_const_char_ptr;n_buffer++) { for (n_size = 0;n_size < gen_nb_int;n_size++) { - for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) { + for (n_url = 0;n_url < gen_nb_filepath;n_url++) { for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { for (n_options = 0;n_options < gen_nb_parseroptions;n_options++) { mem_base = xmlMemBlocks(); buffer = gen_const_char_ptr(n_buffer, 0); size = gen_int(n_size, 1); - URL = gen_filepath(n_URL, 2); + url = gen_filepath(n_url, 2); encoding = gen_const_char_ptr(n_encoding, 3); options = gen_parseroptions(n_options, 4); if ((buffer != NULL) && (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlReadMemory((const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = xmlReadMemory(buffer, size, url, encoding, options); desret_xmlDocPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); - des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_filepath(n_url, url, 2); + des_const_char_ptr(n_encoding, encoding, 3); des_parseroptions(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -14016,7 +14436,7 @@ test_xmlReadMemory(void) { test_ret++; printf(" %d", n_buffer); printf(" %d", n_size); - printf(" %d", n_URL); + printf(" %d", n_url); printf(" %d", n_encoding); printf(" %d", n_options); printf("\n"); @@ -14040,17 +14460,17 @@ test_xmlRecoverDoc(void) { #ifdef LIBXML_SAX1_ENABLED int mem_base; xmlDocPtr ret_val; - xmlChar * cur; /* a pointer to an array of xmlChar */ + const xmlChar * cur; /* a pointer to an array of xmlChar */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlChar_ptr(n_cur, 0); - ret_val = xmlRecoverDoc((const xmlChar *)cur); + ret_val = xmlRecoverDoc(cur); desret_xmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlRecoverDoc", @@ -14112,7 +14532,7 @@ test_xmlRecoverMemory(void) { #ifdef LIBXML_SAX1_ENABLED int mem_base; xmlDocPtr ret_val; - char * buffer; /* an pointer to a char array */ + const char * buffer; /* an pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -14126,10 +14546,10 @@ test_xmlRecoverMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlRecoverMemory((const char *)buffer, size); + ret_val = xmlRecoverMemory(buffer, size); desret_xmlDocPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -14160,9 +14580,9 @@ test_xmlSAXParseDTD(void) { xmlDtdPtr ret_val; xmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; - xmlChar * ExternalID; /* a NAME* containing the External ID of the DTD */ + const xmlChar * ExternalID; /* a NAME* containing the External ID of the DTD */ int n_ExternalID; - xmlChar * SystemID; /* a NAME* containing the URL to the DTD */ + const xmlChar * SystemID; /* a NAME* containing the URL to the DTD */ int n_SystemID; for (n_sax = 0;n_sax < gen_nb_xmlSAXHandlerPtr;n_sax++) { @@ -14173,12 +14593,12 @@ test_xmlSAXParseDTD(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 1); SystemID = gen_const_xmlChar_ptr(n_SystemID, 2); - ret_val = xmlSAXParseDTD(sax, (const xmlChar *)ExternalID, (const xmlChar *)SystemID); + ret_val = xmlSAXParseDTD(sax, ExternalID, SystemID); desret_xmlDtdPtr(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 1); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 2); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 1); + des_const_xmlChar_ptr(n_SystemID, SystemID, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSAXParseDTD", @@ -14210,7 +14630,7 @@ test_xmlSAXParseDoc(void) { xmlDocPtr ret_val; xmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; - xmlChar * cur; /* a pointer to an array of xmlChar */ + const xmlChar * cur; /* a pointer to an array of xmlChar */ int n_cur; int recovery; /* work in recovery mode, i.e. tries to read no Well Formed documents */ int n_recovery; @@ -14223,11 +14643,11 @@ test_xmlSAXParseDoc(void) { cur = gen_const_xmlChar_ptr(n_cur, 1); recovery = gen_int(n_recovery, 2); - ret_val = xmlSAXParseDoc(sax, (const xmlChar *)cur, recovery); + ret_val = xmlSAXParseDoc(sax, cur, recovery); desret_xmlDocPtr(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 1); + des_const_xmlChar_ptr(n_cur, cur, 1); des_int(n_recovery, recovery, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -14410,7 +14830,7 @@ test_xmlSAXParseMemory(void) { xmlDocPtr ret_val; xmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; - char * buffer; /* an pointer to a char array */ + const char * buffer; /* an pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -14430,11 +14850,11 @@ test_xmlSAXParseMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlSAXParseMemory(sax, (const char *)buffer, size, recovery); + ret_val = xmlSAXParseMemory(sax, buffer, size, recovery); desret_xmlDocPtr(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); - des_const_char_ptr(n_buffer, (const char *)buffer, 1); + des_const_char_ptr(n_buffer, buffer, 1); des_int(n_size, size, 2); des_int(n_recovery, recovery, 3); xmlResetLastError(); @@ -14470,7 +14890,7 @@ test_xmlSAXParseMemoryWithData(void) { xmlDocPtr ret_val; xmlSAXHandlerPtr sax; /* the SAX handler block */ int n_sax; - char * buffer; /* an pointer to a char array */ + const char * buffer; /* an pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -14494,11 +14914,11 @@ test_xmlSAXParseMemoryWithData(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlSAXParseMemoryWithData(sax, (const char *)buffer, size, recovery, data); + ret_val = xmlSAXParseMemoryWithData(sax, buffer, size, recovery, data); desret_xmlDocPtr(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); - des_const_char_ptr(n_buffer, (const char *)buffer, 1); + des_const_char_ptr(n_buffer, buffer, 1); des_int(n_size, size, 2); des_int(n_recovery, recovery, 3); des_userdata(n_data, data, 4); @@ -14594,7 +15014,7 @@ test_xmlSAXUserParseMemory(void) { int n_sax; void * user_data; /* The user data returned on SAX callbacks */ int n_user_data; - char * buffer; /* an in-memory XML document input */ + const char * buffer; /* an in-memory XML document input */ int n_buffer; int size; /* the length of the XML document in bytes */ int n_size; @@ -14617,12 +15037,12 @@ test_xmlSAXUserParseMemory(void) { #endif - ret_val = xmlSAXUserParseMemory(sax, user_data, (const char *)buffer, size); + ret_val = xmlSAXUserParseMemory(sax, user_data, buffer, size); desret_int(ret_val); call_tests++; des_xmlSAXHandlerPtr(n_sax, sax, 0); des_userdata(n_user_data, user_data, 1); - des_const_char_ptr(n_buffer, (const char *)buffer, 2); + des_const_char_ptr(n_buffer, buffer, 2); des_int(n_size, size, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -14666,7 +15086,7 @@ test_xmlSetupParserForBuffer(void) { int mem_base; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlChar * buffer; /* a xmlChar * buffer */ + const xmlChar * buffer; /* a xmlChar * buffer */ int n_buffer; const char * filename; /* a file name */ int n_filename; @@ -14679,10 +15099,10 @@ test_xmlSetupParserForBuffer(void) { buffer = gen_const_xmlChar_ptr(n_buffer, 1); filename = gen_filepath(n_filename, 2); - xmlSetupParserForBuffer(ctxt, (const xmlChar *)buffer, filename); + xmlSetupParserForBuffer(ctxt, buffer, filename); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_buffer, (const xmlChar *)buffer, 1); + des_const_xmlChar_ptr(n_buffer, buffer, 1); des_filepath(n_filename, filename, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -15028,22 +15448,27 @@ static int test_parser(void) { int test_ret = 0; - if (quiet == 0) printf("Testing parser : 67 of 80 functions ...\n"); + if (quiet == 0) printf("Testing parser : 71 of 85 functions ...\n"); test_ret += test_xmlByteConsumed(); + test_ret += test_xmlCleanupGlobals(); test_ret += test_xmlClearNodeInfoSeq(); test_ret += test_xmlClearParserCtxt(); test_ret += test_xmlCreateDocParserCtxt(); test_ret += test_xmlCreatePushParserCtxt(); + test_ret += test_xmlCtxtParseDocument(); test_ret += test_xmlCtxtReadDoc(); test_ret += test_xmlCtxtReadFile(); test_ret += test_xmlCtxtReadMemory(); test_ret += test_xmlCtxtReset(); test_ret += test_xmlCtxtResetPush(); + test_ret += test_xmlCtxtSetErrorHandler(); test_ret += test_xmlCtxtSetMaxAmplification(); + test_ret += test_xmlCtxtSetOptions(); test_ret += test_xmlCtxtUseOptions(); test_ret += test_xmlGetExternalEntityLoader(); test_ret += test_xmlHasFeature(); test_ret += test_xmlIOParseDTD(); + test_ret += test_xmlInitGlobals(); test_ret += test_xmlInitNodeInfoSeq(); test_ret += test_xmlInitParser(); test_ret += test_xmlInitParserCtxt(); @@ -15216,7 +15641,7 @@ test_namePush(void) { int ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlChar * value; /* the element name */ + const xmlChar * value; /* the element name */ int n_value; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { @@ -15225,11 +15650,11 @@ test_namePush(void) { ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); value = gen_const_xmlChar_ptr(n_value, 1); - ret_val = namePush(ctxt, (const xmlChar *)value); + ret_val = namePush(ctxt, value); desret_int(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in namePush", @@ -15324,17 +15749,17 @@ test_xmlCheckLanguageID(void) { int mem_base; int ret_val; - xmlChar * lang; /* pointer to the string value */ + const xmlChar * lang; /* pointer to the string value */ int n_lang; for (n_lang = 0;n_lang < gen_nb_const_xmlChar_ptr;n_lang++) { mem_base = xmlMemBlocks(); lang = gen_const_xmlChar_ptr(n_lang, 0); - ret_val = xmlCheckLanguageID((const xmlChar *)lang); + ret_val = xmlCheckLanguageID(lang); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_lang, (const xmlChar *)lang, 0); + des_const_xmlChar_ptr(n_lang, lang, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCheckLanguageID", @@ -15441,11 +15866,11 @@ test_xmlCreateEntityParserCtxt(void) { int mem_base; xmlParserCtxtPtr ret_val; - xmlChar * URL; /* the entity URL */ + const xmlChar * URL; /* the entity URL */ int n_URL; - xmlChar * ID; /* the entity PUBLIC ID */ + const xmlChar * ID; /* the entity PUBLIC ID */ int n_ID; - xmlChar * base; /* a possible base for the target URI */ + const xmlChar * base; /* a possible base for the target URI */ int n_base; for (n_URL = 0;n_URL < gen_nb_const_xmlChar_ptr;n_URL++) { @@ -15456,12 +15881,12 @@ test_xmlCreateEntityParserCtxt(void) { ID = gen_const_xmlChar_ptr(n_ID, 1); base = gen_const_xmlChar_ptr(n_base, 2); - ret_val = xmlCreateEntityParserCtxt((const xmlChar *)URL, (const xmlChar *)ID, (const xmlChar *)base); + ret_val = xmlCreateEntityParserCtxt(URL, ID, base); desret_xmlParserCtxtPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URL, (const xmlChar *)URL, 0); - des_const_xmlChar_ptr(n_ID, (const xmlChar *)ID, 1); - des_const_xmlChar_ptr(n_base, (const xmlChar *)base, 2); + des_const_xmlChar_ptr(n_URL, URL, 0); + des_const_xmlChar_ptr(n_ID, ID, 1); + des_const_xmlChar_ptr(n_base, base, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCreateEntityParserCtxt", @@ -15519,7 +15944,7 @@ test_xmlCreateMemoryParserCtxt(void) { int mem_base; xmlParserCtxtPtr ret_val; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -15533,10 +15958,10 @@ test_xmlCreateMemoryParserCtxt(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlCreateMemoryParserCtxt((const char *)buffer, size); + ret_val = xmlCreateMemoryParserCtxt(buffer, size); desret_xmlParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -15594,6 +16019,36 @@ test_xmlCreateURLParserCtxt(void) { } +static int +test_xmlCtxtErrMemory(void) { + int test_ret = 0; + + int mem_base; + xmlParserCtxtPtr ctxt; /* an XML parser context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + + xmlCtxtErrMemory(ctxt); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtErrMemory", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCurrentChar(void) { int test_ret = 0; @@ -15673,27 +16128,27 @@ test_xmlNewEntityInputStream(void) { xmlParserInputPtr ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlEntityPtr entity; /* an Entity pointer */ - int n_entity; + xmlEntityPtr ent; /* an Entity pointer */ + int n_ent; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { - for (n_entity = 0;n_entity < gen_nb_xmlEntityPtr;n_entity++) { + for (n_ent = 0;n_ent < gen_nb_xmlEntityPtr;n_ent++) { mem_base = xmlMemBlocks(); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); - entity = gen_xmlEntityPtr(n_entity, 1); + ent = gen_xmlEntityPtr(n_ent, 1); - ret_val = xmlNewEntityInputStream(ctxt, entity); + ret_val = xmlNewEntityInputStream(ctxt, ent); desret_xmlParserInputPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_xmlEntityPtr(n_entity, entity, 1); + des_xmlEntityPtr(n_ent, ent, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewEntityInputStream", xmlMemBlocks() - mem_base); test_ret++; printf(" %d", n_ctxt); - printf(" %d", n_entity); + printf(" %d", n_ent); printf("\n"); } } @@ -15783,7 +16238,7 @@ test_xmlNewStringInputStream(void) { xmlParserInputPtr ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlChar * buffer; /* an memory buffer */ + const xmlChar * buffer; /* an memory buffer */ int n_buffer; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { @@ -15792,11 +16247,11 @@ test_xmlNewStringInputStream(void) { ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); buffer = gen_const_xmlChar_ptr(n_buffer, 1); - ret_val = xmlNewStringInputStream(ctxt, (const xmlChar *)buffer); + ret_val = xmlNewStringInputStream(ctxt, buffer); desret_xmlParserInputPtr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_buffer, (const xmlChar *)buffer, 1); + des_const_xmlChar_ptr(n_buffer, buffer, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewStringInputStream", @@ -15963,25 +16418,25 @@ test_xmlSplitQName(void) { xmlChar * ret_val; xmlParserCtxtPtr ctxt; /* an XML parser context */ int n_ctxt; - xmlChar * name; /* an XML parser context */ + const xmlChar * name; /* an XML parser context */ int n_name; - xmlChar ** prefix; /* a xmlChar ** */ - int n_prefix; + xmlChar ** prefixOut; /* a xmlChar ** */ + int n_prefixOut; for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { - for (n_prefix = 0;n_prefix < gen_nb_xmlChar_ptr_ptr;n_prefix++) { + for (n_prefixOut = 0;n_prefixOut < gen_nb_xmlChar_ptr_ptr;n_prefixOut++) { mem_base = xmlMemBlocks(); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); name = gen_const_xmlChar_ptr(n_name, 1); - prefix = gen_xmlChar_ptr_ptr(n_prefix, 2); + prefixOut = gen_xmlChar_ptr_ptr(n_prefixOut, 2); - ret_val = xmlSplitQName(ctxt, (const xmlChar *)name, prefix); + ret_val = xmlSplitQName(ctxt, name, prefixOut); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_xmlChar_ptr_ptr(n_prefix, prefix, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_xmlChar_ptr_ptr(n_prefixOut, prefixOut, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSplitQName", @@ -15989,7 +16444,7 @@ test_xmlSplitQName(void) { test_ret++; printf(" %d", n_ctxt); printf(" %d", n_name); - printf(" %d", n_prefix); + printf(" %d", n_prefixOut); printf("\n"); } } @@ -16009,7 +16464,7 @@ test_xmlStringCurrentChar(void) { int ret_val; xmlParserCtxtPtr ctxt; /* the XML parser context */ int n_ctxt; - xmlChar * cur; /* pointer to the beginning of the char */ + const xmlChar * cur; /* pointer to the beginning of the char */ int n_cur; int * len; /* pointer to the length of the char read */ int n_len; @@ -16022,11 +16477,11 @@ test_xmlStringCurrentChar(void) { cur = gen_const_xmlChar_ptr(n_cur, 1); len = gen_int_ptr(n_len, 2); - ret_val = xmlStringCurrentChar(ctxt, (const xmlChar *)cur, len); + ret_val = xmlStringCurrentChar(ctxt, cur, len); desret_int(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 1); + des_const_xmlChar_ptr(n_cur, cur, 1); des_int_ptr(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -16055,7 +16510,7 @@ test_xmlStringDecodeEntities(void) { xmlChar * ret_val; xmlParserCtxtPtr ctxt; /* the parser context */ int n_ctxt; - xmlChar * str; /* the input string */ + const xmlChar * str; /* the input string */ int n_str; int what; /* combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF */ int n_what; @@ -16080,11 +16535,11 @@ test_xmlStringDecodeEntities(void) { end2 = gen_xmlChar(n_end2, 4); end3 = gen_xmlChar(n_end3, 5); - ret_val = xmlStringDecodeEntities(ctxt, (const xmlChar *)str, what, end, end2, end3); + ret_val = xmlStringDecodeEntities(ctxt, str, what, end, end2, end3); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_int(n_what, what, 2); des_xmlChar(n_end, end, 3); des_xmlChar(n_end2, end2, 4); @@ -16122,7 +16577,7 @@ test_xmlStringLenDecodeEntities(void) { xmlChar * ret_val; xmlParserCtxtPtr ctxt; /* the parser context */ int n_ctxt; - xmlChar * str; /* the input string */ + const xmlChar * str; /* the input string */ int n_str; int len; /* the string length */ int n_len; @@ -16154,11 +16609,11 @@ test_xmlStringLenDecodeEntities(void) { (len > xmlStrlen(BAD_CAST str))) len = 0; - ret_val = xmlStringLenDecodeEntities(ctxt, (const xmlChar *)str, len, what, end, end2, end3); + ret_val = xmlStringLenDecodeEntities(ctxt, str, len, what, end, end2, end3); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_int(n_len, len, 2); des_int(n_what, what, 3); des_xmlChar(n_end, end, 4); @@ -16231,13 +16686,52 @@ test_xmlSwitchEncoding(void) { static int -test_xmlSwitchInputEncoding(void) { +test_xmlSwitchEncodingName(void) { int test_ret = 0; int mem_base; int ret_val; xmlParserCtxtPtr ctxt; /* the parser context */ int n_ctxt; + const char * encoding; /* the encoding name */ + int n_encoding; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + encoding = gen_const_char_ptr(n_encoding, 1); + + ret_val = xmlSwitchEncodingName(ctxt, encoding); + desret_int(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_const_char_ptr(n_encoding, encoding, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlSwitchEncodingName", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_encoding); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + +static int +test_xmlSwitchInputEncoding(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlParserCtxtPtr ctxt; /* the parser context, only for error reporting */ + int n_ctxt; xmlParserInputPtr input; /* the input stream */ int n_input; xmlCharEncodingHandlerPtr handler; /* the encoding handler */ @@ -16318,7 +16812,7 @@ static int test_parserInternals(void) { int test_ret = 0; - if (quiet == 0) printf("Testing parserInternals : 30 of 87 functions ...\n"); + if (quiet == 0) printf("Testing parserInternals : 32 of 89 functions ...\n"); test_ret += test_inputPop(); test_ret += test_inputPush(); test_ret += test_namePop(); @@ -16332,6 +16826,7 @@ test_parserInternals(void) { test_ret += test_xmlCreateFileParserCtxt(); test_ret += test_xmlCreateMemoryParserCtxt(); test_ret += test_xmlCreateURLParserCtxt(); + test_ret += test_xmlCtxtErrMemory(); test_ret += test_xmlCurrentChar(); test_ret += test_xmlIsLetter(); test_ret += test_xmlNewEntityInputStream(); @@ -16348,6 +16843,7 @@ test_parserInternals(void) { test_ret += test_xmlStringDecodeEntities(); test_ret += test_xmlStringLenDecodeEntities(); test_ret += test_xmlSwitchEncoding(); + test_ret += test_xmlSwitchEncodingName(); test_ret += test_xmlSwitchInputEncoding(); test_ret += test_xmlSwitchToEncoding(); @@ -16355,6 +16851,75 @@ test_parserInternals(void) { printf("Module parserInternals: %d errors\n", test_ret); return(test_ret); } +#ifdef LIBXML_PATTERN_ENABLED + +#define gen_nb_xmlPatternPtr_ptr 1 +#define gen_xmlPatternPtr_ptr(no, nr) NULL +#define des_xmlPatternPtr_ptr(no, val, nr) +#endif + + +static int +test_xmlPatternCompileSafe(void) { + int test_ret = 0; + +#if defined(LIBXML_PATTERN_ENABLED) + int mem_base; + int ret_val; + const xmlChar * pattern; /* the pattern to compile */ + int n_pattern; + xmlDict * dict; /* an optional dictionary for interned strings */ + int n_dict; + int flags; /* compilation flags, see xmlPatternFlags */ + int n_flags; + const xmlChar ** namespaces; /* the prefix definitions, array of [URI, prefix] or NULL */ + int n_namespaces; + xmlPatternPtr * patternOut; /* output pattern */ + int n_patternOut; + + for (n_pattern = 0;n_pattern < gen_nb_const_xmlChar_ptr;n_pattern++) { + for (n_dict = 0;n_dict < gen_nb_xmlDictPtr;n_dict++) { + for (n_flags = 0;n_flags < gen_nb_int;n_flags++) { + for (n_namespaces = 0;n_namespaces < gen_nb_const_xmlChar_ptr_ptr;n_namespaces++) { + for (n_patternOut = 0;n_patternOut < gen_nb_xmlPatternPtr_ptr;n_patternOut++) { + mem_base = xmlMemBlocks(); + pattern = gen_const_xmlChar_ptr(n_pattern, 0); + dict = gen_xmlDictPtr(n_dict, 1); + flags = gen_int(n_flags, 2); + namespaces = gen_const_xmlChar_ptr_ptr(n_namespaces, 3); + patternOut = gen_xmlPatternPtr_ptr(n_patternOut, 4); + + ret_val = xmlPatternCompileSafe(pattern, dict, flags, namespaces, patternOut); + desret_int(ret_val); + call_tests++; + des_const_xmlChar_ptr(n_pattern, pattern, 0); + des_xmlDictPtr(n_dict, dict, 1); + des_int(n_flags, flags, 2); + des_const_xmlChar_ptr_ptr(n_namespaces, namespaces, 3); + des_xmlPatternPtr_ptr(n_patternOut, patternOut, 4); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlPatternCompileSafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_pattern); + printf(" %d", n_dict); + printf(" %d", n_flags); + printf(" %d", n_namespaces); + printf(" %d", n_patternOut); + printf("\n"); + } + } + } + } + } + } + function_tests++; +#endif + + return(test_ret); +} + static int test_xmlPatternFromRoot(void) { @@ -16603,9 +17168,9 @@ test_xmlStreamPush(void) { int ret_val; xmlStreamCtxtPtr stream; /* the stream context */ int n_stream; - xmlChar * name; /* the current name */ + const xmlChar * name; /* the current name */ int n_name; - xmlChar * ns; /* the namespace name */ + const xmlChar * ns; /* the namespace name */ int n_ns; for (n_stream = 0;n_stream < gen_nb_xmlStreamCtxtPtr;n_stream++) { @@ -16616,12 +17181,12 @@ test_xmlStreamPush(void) { name = gen_const_xmlChar_ptr(n_name, 1); ns = gen_const_xmlChar_ptr(n_ns, 2); - ret_val = xmlStreamPush(stream, (const xmlChar *)name, (const xmlChar *)ns); + ret_val = xmlStreamPush(stream, name, ns); desret_int(ret_val); call_tests++; des_xmlStreamCtxtPtr(n_stream, stream, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ns, (const xmlChar *)ns, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ns, ns, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStreamPush", @@ -16651,9 +17216,9 @@ test_xmlStreamPushAttr(void) { int ret_val; xmlStreamCtxtPtr stream; /* the stream context */ int n_stream; - xmlChar * name; /* the current name */ + const xmlChar * name; /* the current name */ int n_name; - xmlChar * ns; /* the namespace name */ + const xmlChar * ns; /* the namespace name */ int n_ns; for (n_stream = 0;n_stream < gen_nb_xmlStreamCtxtPtr;n_stream++) { @@ -16664,12 +17229,12 @@ test_xmlStreamPushAttr(void) { name = gen_const_xmlChar_ptr(n_name, 1); ns = gen_const_xmlChar_ptr(n_ns, 2); - ret_val = xmlStreamPushAttr(stream, (const xmlChar *)name, (const xmlChar *)ns); + ret_val = xmlStreamPushAttr(stream, name, ns); desret_int(ret_val); call_tests++; des_xmlStreamCtxtPtr(n_stream, stream, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ns, (const xmlChar *)ns, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ns, ns, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStreamPushAttr", @@ -16699,9 +17264,9 @@ test_xmlStreamPushNode(void) { int ret_val; xmlStreamCtxtPtr stream; /* the stream context */ int n_stream; - xmlChar * name; /* the current name */ + const xmlChar * name; /* the current name */ int n_name; - xmlChar * ns; /* the namespace name */ + const xmlChar * ns; /* the namespace name */ int n_ns; int nodeType; /* the type of the node being pushed */ int n_nodeType; @@ -16716,12 +17281,12 @@ test_xmlStreamPushNode(void) { ns = gen_const_xmlChar_ptr(n_ns, 2); nodeType = gen_int(n_nodeType, 3); - ret_val = xmlStreamPushNode(stream, (const xmlChar *)name, (const xmlChar *)ns, nodeType); + ret_val = xmlStreamPushNode(stream, name, ns, nodeType); desret_int(ret_val); call_tests++; des_xmlStreamCtxtPtr(n_stream, stream, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ns, (const xmlChar *)ns, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ns, ns, 2); des_int(n_nodeType, nodeType, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -16782,7 +17347,8 @@ static int test_pattern(void) { int test_ret = 0; - if (quiet == 0) printf("Testing pattern : 10 of 15 functions ...\n"); + if (quiet == 0) printf("Testing pattern : 11 of 16 functions ...\n"); + test_ret += test_xmlPatternCompileSafe(); test_ret += test_xmlPatternFromRoot(); test_ret += test_xmlPatternGetStreamCtxt(); test_ret += test_xmlPatternMatch(); @@ -17092,7 +17658,7 @@ test_xmlRelaxNGNewMemParserCtxt(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlRelaxNGParserCtxtPtr ret_val; - char * buffer; /* a pointer to a char array containing the schemas */ + const char * buffer; /* a pointer to a char array containing the schemas */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -17106,10 +17672,10 @@ test_xmlRelaxNGNewMemParserCtxt(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlRelaxNGNewMemParserCtxt((const char *)buffer, size); + ret_val = xmlRelaxNGNewMemParserCtxt(buffer, size); desret_xmlRelaxNGParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -17136,17 +17702,17 @@ test_xmlRelaxNGNewParserCtxt(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlRelaxNGParserCtxtPtr ret_val; - char * URL; /* the location of the schema */ + const char * URL; /* the location of the schema */ int n_URL; for (n_URL = 0;n_URL < gen_nb_const_char_ptr;n_URL++) { mem_base = xmlMemBlocks(); URL = gen_const_char_ptr(n_URL, 0); - ret_val = xmlRelaxNGNewParserCtxt((const char *)URL); + ret_val = xmlRelaxNGNewParserCtxt(URL); desret_xmlRelaxNGParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_URL, (const char *)URL, 0); + des_const_char_ptr(n_URL, URL, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlRelaxNGNewParserCtxt", @@ -17369,7 +17935,7 @@ test_xmlRelaxNGValidatePushCData(void) { int ret_val; xmlRelaxNGValidCtxtPtr ctxt; /* the RelaxNG validation context */ int n_ctxt; - xmlChar * data; /* some character data read */ + const xmlChar * data; /* some character data read */ int n_data; int len; /* the length of the data */ int n_len; @@ -17385,11 +17951,11 @@ test_xmlRelaxNGValidatePushCData(void) { (len > xmlStrlen(BAD_CAST data))) len = 0; - ret_val = xmlRelaxNGValidatePushCData(ctxt, (const xmlChar *)data, len); + ret_val = xmlRelaxNGValidatePushCData(ctxt, data, len); desret_int(ret_val); call_tests++; des_xmlRelaxNGValidCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_data, (const xmlChar *)data, 1); + des_const_xmlChar_ptr(n_data, data, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -17751,30 +18317,30 @@ test_xmlAddNextSibling(void) { int mem_base; xmlNodePtr ret_val; - xmlNodePtr cur; /* the child node */ + xmlNodePtr prev; /* the target node */ + int n_prev; + xmlNodePtr cur; /* the new node */ int n_cur; - xmlNodePtr elem; /* the new node */ - int n_elem; - for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { - for (n_elem = 0;n_elem < gen_nb_xmlNodePtr_in;n_elem++) { + for (n_prev = 0;n_prev < gen_nb_xmlNodePtr;n_prev++) { + for (n_cur = 0;n_cur < gen_nb_xmlNodePtr_in;n_cur++) { mem_base = xmlMemBlocks(); - cur = gen_xmlNodePtr(n_cur, 0); - elem = gen_xmlNodePtr_in(n_elem, 1); + prev = gen_xmlNodePtr(n_prev, 0); + cur = gen_xmlNodePtr_in(n_cur, 1); - ret_val = xmlAddNextSibling(cur, elem); - if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; } + ret_val = xmlAddNextSibling(prev, cur); + if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; } desret_xmlNodePtr(ret_val); call_tests++; - des_xmlNodePtr(n_cur, cur, 0); - des_xmlNodePtr_in(n_elem, elem, 1); + des_xmlNodePtr(n_prev, prev, 0); + des_xmlNodePtr_in(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAddNextSibling", xmlMemBlocks() - mem_base); test_ret++; + printf(" %d", n_prev); printf(" %d", n_cur); - printf(" %d", n_elem); printf("\n"); } } @@ -17792,30 +18358,30 @@ test_xmlAddPrevSibling(void) { #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) int mem_base; xmlNodePtr ret_val; - xmlNodePtr cur; /* the child node */ + xmlNodePtr next; /* the target node */ + int n_next; + xmlNodePtr cur; /* the new node */ int n_cur; - xmlNodePtr elem; /* the new node */ - int n_elem; - for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { - for (n_elem = 0;n_elem < gen_nb_xmlNodePtr_in;n_elem++) { + for (n_next = 0;n_next < gen_nb_xmlNodePtr;n_next++) { + for (n_cur = 0;n_cur < gen_nb_xmlNodePtr_in;n_cur++) { mem_base = xmlMemBlocks(); - cur = gen_xmlNodePtr(n_cur, 0); - elem = gen_xmlNodePtr_in(n_elem, 1); + next = gen_xmlNodePtr(n_next, 0); + cur = gen_xmlNodePtr_in(n_cur, 1); - ret_val = xmlAddPrevSibling(cur, elem); - if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; } + ret_val = xmlAddPrevSibling(next, cur); + if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; } desret_xmlNodePtr(ret_val); call_tests++; - des_xmlNodePtr(n_cur, cur, 0); - des_xmlNodePtr_in(n_elem, elem, 1); + des_xmlNodePtr(n_next, next, 0); + des_xmlNodePtr_in(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAddPrevSibling", xmlMemBlocks() - mem_base); test_ret++; + printf(" %d", n_next); printf(" %d", n_cur); - printf(" %d", n_elem); printf("\n"); } } @@ -17833,30 +18399,30 @@ test_xmlAddSibling(void) { int mem_base; xmlNodePtr ret_val; - xmlNodePtr cur; /* the child node */ + xmlNodePtr node; /* the target node */ + int n_node; + xmlNodePtr cur; /* the new node */ int n_cur; - xmlNodePtr elem; /* the new node */ - int n_elem; - for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { - for (n_elem = 0;n_elem < gen_nb_xmlNodePtr_in;n_elem++) { + for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { + for (n_cur = 0;n_cur < gen_nb_xmlNodePtr_in;n_cur++) { mem_base = xmlMemBlocks(); - cur = gen_xmlNodePtr(n_cur, 0); - elem = gen_xmlNodePtr_in(n_elem, 1); + node = gen_xmlNodePtr(n_node, 0); + cur = gen_xmlNodePtr_in(n_cur, 1); - ret_val = xmlAddSibling(cur, elem); - if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; } + ret_val = xmlAddSibling(node, cur); + if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; } desret_xmlNodePtr(ret_val); call_tests++; - des_xmlNodePtr(n_cur, cur, 0); - des_xmlNodePtr_in(n_elem, elem, 1); + des_xmlNodePtr(n_node, node, 0); + des_xmlNodePtr_in(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAddSibling", xmlMemBlocks() - mem_base); test_ret++; + printf(" %d", n_node); printf(" %d", n_cur); - printf(" %d", n_elem); printf("\n"); } } @@ -17880,7 +18446,7 @@ test_xmlAttrSerializeTxtContent(void) { int n_doc; xmlAttrPtr attr; /* the attribute node */ int n_attr; - xmlChar * string; /* the text content */ + const xmlChar * string; /* the text content */ int n_string; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -17893,12 +18459,12 @@ test_xmlAttrSerializeTxtContent(void) { attr = gen_xmlAttrPtr(n_attr, 2); string = gen_const_xmlChar_ptr(n_string, 3); - xmlAttrSerializeTxtContent(buf, doc, attr, (const xmlChar *)string); + xmlAttrSerializeTxtContent(buf, doc, attr, string); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlAttrPtr(n_attr, attr, 2); - des_const_xmlChar_ptr(n_string, (const xmlChar *)string, 3); + des_const_xmlChar_ptr(n_string, string, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlAttrSerializeTxtContent", @@ -17932,17 +18498,17 @@ test_xmlBufContent(void) { int mem_base; xmlChar * ret_val; - xmlBuf * buf; /* the buffer */ + const xmlBuf * buf; /* the buffer */ int n_buf; for (n_buf = 0;n_buf < gen_nb_const_xmlBuf_ptr;n_buf++) { mem_base = xmlMemBlocks(); buf = gen_const_xmlBuf_ptr(n_buf, 0); - ret_val = xmlBufContent((const xmlBuf *)buf); + ret_val = xmlBufContent(buf); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlBuf_ptr(n_buf, (const xmlBuf *)buf, 0); + des_const_xmlBuf_ptr(n_buf, buf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufContent", @@ -18006,7 +18572,7 @@ test_xmlBufGetNodeContent(void) { int ret_val; xmlBufPtr buf; /* a buffer xmlBufPtr */ int n_buf; - xmlNode * cur; /* the node being read */ + const xmlNode * cur; /* the node being read */ int n_cur; for (n_buf = 0;n_buf < gen_nb_xmlBufPtr;n_buf++) { @@ -18015,11 +18581,11 @@ test_xmlBufGetNodeContent(void) { buf = gen_xmlBufPtr(n_buf, 0); cur = gen_const_xmlNode_ptr(n_cur, 1); - ret_val = xmlBufGetNodeContent(buf, (const xmlNode *)cur); + ret_val = xmlBufGetNodeContent(buf, cur); desret_int(ret_val); call_tests++; des_xmlBufPtr(n_buf, buf, 0); - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 1); + des_const_xmlNode_ptr(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufGetNodeContent", @@ -18075,7 +18641,7 @@ test_xmlBufferAdd(void) { int ret_val; xmlBufferPtr buf; /* the buffer to dump */ int n_buf; - xmlChar * str; /* the #xmlChar string */ + const xmlChar * str; /* the #xmlChar string */ int n_str; int len; /* the number of #xmlChar to add */ int n_len; @@ -18091,11 +18657,11 @@ test_xmlBufferAdd(void) { (len > xmlStrlen(BAD_CAST str))) len = 0; - ret_val = xmlBufferAdd(buf, (const xmlChar *)str, len); + ret_val = xmlBufferAdd(buf, str, len); desret_int(ret_val); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -18124,7 +18690,7 @@ test_xmlBufferAddHead(void) { int ret_val; xmlBufferPtr buf; /* the buffer */ int n_buf; - xmlChar * str; /* the #xmlChar string */ + const xmlChar * str; /* the #xmlChar string */ int n_str; int len; /* the number of #xmlChar to add */ int n_len; @@ -18140,11 +18706,11 @@ test_xmlBufferAddHead(void) { (len > xmlStrlen(BAD_CAST str))) len = 0; - ret_val = xmlBufferAddHead(buf, (const xmlChar *)str, len); + ret_val = xmlBufferAddHead(buf, str, len); desret_int(ret_val); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -18173,7 +18739,7 @@ test_xmlBufferCCat(void) { int ret_val; xmlBufferPtr buf; /* the buffer to dump */ int n_buf; - char * str; /* the C char string */ + const char * str; /* the C char string */ int n_str; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -18182,11 +18748,11 @@ test_xmlBufferCCat(void) { buf = gen_xmlBufferPtr(n_buf, 0); str = gen_const_char_ptr(n_str, 1); - ret_val = xmlBufferCCat(buf, (const char *)str); + ret_val = xmlBufferCCat(buf, str); desret_int(ret_val); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_char_ptr(n_str, (const char *)str, 1); + des_const_char_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferCCat", @@ -18212,7 +18778,7 @@ test_xmlBufferCat(void) { int ret_val; xmlBufferPtr buf; /* the buffer to add to */ int n_buf; - xmlChar * str; /* the #xmlChar string */ + const xmlChar * str; /* the #xmlChar string */ int n_str; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -18221,11 +18787,11 @@ test_xmlBufferCat(void) { buf = gen_xmlBufferPtr(n_buf, 0); str = gen_const_xmlChar_ptr(n_str, 1); - ret_val = xmlBufferCat(buf, (const xmlChar *)str); + ret_val = xmlBufferCat(buf, str); desret_int(ret_val); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferCat", @@ -18253,17 +18819,17 @@ test_xmlBufferContent(void) { int mem_base; const xmlChar * ret_val; - xmlBuffer * buf; /* the buffer */ + const xmlBuffer * buf; /* the buffer */ int n_buf; for (n_buf = 0;n_buf < gen_nb_const_xmlBuffer_ptr;n_buf++) { mem_base = xmlMemBlocks(); buf = gen_const_xmlBuffer_ptr(n_buf, 0); - ret_val = xmlBufferContent((const xmlBuffer *)buf); + ret_val = xmlBufferContent(buf); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlBuffer_ptr(n_buf, (const xmlBuffer *)buf, 0); + des_const_xmlBuffer_ptr(n_buf, buf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferContent", @@ -18431,17 +18997,17 @@ test_xmlBufferLength(void) { int mem_base; int ret_val; - xmlBuffer * buf; /* the buffer */ + const xmlBuffer * buf; /* the buffer */ int n_buf; for (n_buf = 0;n_buf < gen_nb_const_xmlBuffer_ptr;n_buf++) { mem_base = xmlMemBlocks(); buf = gen_const_xmlBuffer_ptr(n_buf, 0); - ret_val = xmlBufferLength((const xmlBuffer *)buf); + ret_val = xmlBufferLength(buf); desret_int(ret_val); call_tests++; - des_const_xmlBuffer_ptr(n_buf, (const xmlBuffer *)buf, 0); + des_const_xmlBuffer_ptr(n_buf, buf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferLength", @@ -18579,7 +19145,7 @@ test_xmlBufferWriteCHAR(void) { int mem_base; xmlBufferPtr buf; /* the XML buffer */ int n_buf; - xmlChar * string; /* the string to add */ + const xmlChar * string; /* the string to add */ int n_string; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -18588,10 +19154,10 @@ test_xmlBufferWriteCHAR(void) { buf = gen_xmlBufferPtr(n_buf, 0); string = gen_const_xmlChar_ptr(n_string, 1); - xmlBufferWriteCHAR(buf, (const xmlChar *)string); + xmlBufferWriteCHAR(buf, string); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_xmlChar_ptr(n_string, (const xmlChar *)string, 1); + des_const_xmlChar_ptr(n_string, string, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferWriteCHAR", @@ -18616,7 +19182,7 @@ test_xmlBufferWriteChar(void) { int mem_base; xmlBufferPtr buf; /* the XML buffer output */ int n_buf; - char * string; /* the string to add */ + const char * string; /* the string to add */ int n_string; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -18625,10 +19191,10 @@ test_xmlBufferWriteChar(void) { buf = gen_xmlBufferPtr(n_buf, 0); string = gen_const_char_ptr(n_string, 1); - xmlBufferWriteChar(buf, (const char *)string); + xmlBufferWriteChar(buf, string); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_char_ptr(n_string, (const char *)string, 1); + des_const_char_ptr(n_string, string, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferWriteChar", @@ -18653,7 +19219,7 @@ test_xmlBufferWriteQuotedString(void) { int mem_base; xmlBufferPtr buf; /* the XML buffer output */ int n_buf; - xmlChar * string; /* the string to add */ + const xmlChar * string; /* the string to add */ int n_string; for (n_buf = 0;n_buf < gen_nb_xmlBufferPtr;n_buf++) { @@ -18662,10 +19228,10 @@ test_xmlBufferWriteQuotedString(void) { buf = gen_xmlBufferPtr(n_buf, 0); string = gen_const_xmlChar_ptr(n_string, 1); - xmlBufferWriteQuotedString(buf, (const xmlChar *)string); + xmlBufferWriteQuotedString(buf, string); call_tests++; des_xmlBufferPtr(n_buf, buf, 0); - des_const_xmlChar_ptr(n_string, (const xmlChar *)string, 1); + des_const_xmlChar_ptr(n_string, string, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBufferWriteQuotedString", @@ -18689,9 +19255,9 @@ test_xmlBuildQName(void) { int mem_base; xmlChar * ret_val; - xmlChar * ncname; /* the Name */ + const xmlChar * ncname; /* the Name */ int n_ncname; - xmlChar * prefix; /* the prefix */ + const xmlChar * prefix; /* the prefix */ int n_prefix; xmlChar * memory; /* preallocated memory */ int n_memory; @@ -18711,15 +19277,15 @@ test_xmlBuildQName(void) { (len > xmlStrlen(BAD_CAST prefix))) len = 0; - ret_val = xmlBuildQName((const xmlChar *)ncname, (const xmlChar *)prefix, memory, len); + ret_val = xmlBuildQName(ncname, prefix, memory, len); if ((ret_val != NULL) && (ret_val != ncname) && (ret_val != prefix) && (ret_val != memory)) xmlFree(ret_val); ret_val = NULL; desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_ncname, (const xmlChar *)ncname, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); + des_const_xmlChar_ptr(n_ncname, ncname, 0); + des_const_xmlChar_ptr(n_prefix, prefix, 1); des_xmlChar_ptr(n_memory, memory, 2); des_int(n_len, len, 3); xmlResetLastError(); @@ -18825,7 +19391,7 @@ test_xmlCopyDtd(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; xmlDtdPtr ret_val; - xmlDtdPtr dtd; /* the dtd */ + xmlDtdPtr dtd; /* the DTD */ int n_dtd; for (n_dtd = 0;n_dtd < gen_nb_xmlDtdPtr;n_dtd++) { @@ -19073,13 +19639,13 @@ test_xmlCreateIntSubset(void) { int mem_base; xmlDtdPtr ret_val; - xmlDocPtr doc; /* the document pointer */ + xmlDocPtr doc; /* the document pointer (optional) */ int n_doc; - xmlChar * name; /* the DTD name */ + const xmlChar * name; /* the DTD name (optional) */ int n_name; - xmlChar * ExternalID; /* the external (PUBLIC) ID */ + const xmlChar * ExternalID; /* the external (PUBLIC) ID (optional) */ int n_ExternalID; - xmlChar * SystemID; /* the system ID */ + const xmlChar * SystemID; /* the system ID (optional) */ int n_SystemID; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -19092,13 +19658,13 @@ test_xmlCreateIntSubset(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 2); SystemID = gen_const_xmlChar_ptr(n_SystemID, 3); - ret_val = xmlCreateIntSubset(doc, (const xmlChar *)name, (const xmlChar *)ExternalID, (const xmlChar *)SystemID); + ret_val = xmlCreateIntSubset(doc, name, ExternalID, SystemID); desret_xmlDtdPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 2); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 2); + des_const_xmlChar_ptr(n_SystemID, SystemID, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCreateIntSubset", @@ -19583,7 +20149,7 @@ test_xmlDocDumpFormatMemoryEnc(void) { int n_doc_txt_ptr; int * doc_txt_len; /* Length of the generated XML text */ int n_doc_txt_len; - char * txt_encoding; /* Character encoding to use when generating XML text */ + const char * txt_encoding; /* Character encoding to use when generating XML text */ int n_txt_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -19600,12 +20166,12 @@ test_xmlDocDumpFormatMemoryEnc(void) { txt_encoding = gen_const_char_ptr(n_txt_encoding, 3); format = gen_int(n_format, 4); - xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, (const char *)txt_encoding, format); + xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, txt_encoding, format); call_tests++; des_xmlDocPtr(n_out_doc, out_doc, 0); des_xmlChar_ptr_ptr(n_doc_txt_ptr, doc_txt_ptr, 1); des_int_ptr(n_doc_txt_len, doc_txt_len, 2); - des_const_char_ptr(n_txt_encoding, (const char *)txt_encoding, 3); + des_const_char_ptr(n_txt_encoding, txt_encoding, 3); des_int(n_format, format, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -19689,7 +20255,7 @@ test_xmlDocDumpMemoryEnc(void) { int n_doc_txt_ptr; int * doc_txt_len; /* Length of the generated XML text */ int n_doc_txt_len; - char * txt_encoding; /* Character encoding to use when generating XML text */ + const char * txt_encoding; /* Character encoding to use when generating XML text */ int n_txt_encoding; for (n_out_doc = 0;n_out_doc < gen_nb_xmlDocPtr;n_out_doc++) { @@ -19702,12 +20268,12 @@ test_xmlDocDumpMemoryEnc(void) { doc_txt_len = gen_int_ptr(n_doc_txt_len, 2); txt_encoding = gen_const_char_ptr(n_txt_encoding, 3); - xmlDocDumpMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, (const char *)txt_encoding); + xmlDocDumpMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, txt_encoding); call_tests++; des_xmlDocPtr(n_out_doc, out_doc, 0); des_xmlChar_ptr_ptr(n_doc_txt_ptr, doc_txt_ptr, 1); des_int_ptr(n_doc_txt_len, doc_txt_len, 2); - des_const_char_ptr(n_txt_encoding, (const char *)txt_encoding, 3); + des_const_char_ptr(n_txt_encoding, txt_encoding, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDocDumpMemoryEnc", @@ -19784,17 +20350,17 @@ test_xmlDocGetRootElement(void) { int mem_base; xmlNodePtr ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* the document */ int n_doc; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { mem_base = xmlMemBlocks(); doc = gen_const_xmlDoc_ptr(n_doc, 0); - ret_val = xmlDocGetRootElement((const xmlDoc *)doc); + ret_val = xmlDocGetRootElement(doc); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); + des_const_xmlDoc_ptr(n_doc, doc, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlDocGetRootElement", @@ -19988,17 +20554,17 @@ test_xmlGetDocCompressMode(void) { int mem_base; int ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* the document */ int n_doc; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { mem_base = xmlMemBlocks(); doc = gen_const_xmlDoc_ptr(n_doc, 0); - ret_val = xmlGetDocCompressMode((const xmlDoc *)doc); + ret_val = xmlGetDocCompressMode(doc); desret_int(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); + des_const_xmlDoc_ptr(n_doc, doc, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDocCompressMode", @@ -20020,17 +20586,17 @@ test_xmlGetIntSubset(void) { int mem_base; xmlDtdPtr ret_val; - xmlDoc * doc; /* the document pointer */ + const xmlDoc * doc; /* the document pointer */ int n_doc; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { mem_base = xmlMemBlocks(); doc = gen_const_xmlDoc_ptr(n_doc, 0); - ret_val = xmlGetIntSubset((const xmlDoc *)doc); + ret_val = xmlGetIntSubset(doc); desret_xmlDtdPtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); + des_const_xmlDoc_ptr(n_doc, doc, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetIntSubset", @@ -20052,17 +20618,17 @@ test_xmlGetLastChild(void) { int mem_base; xmlNodePtr ret_val; - xmlNode * parent; /* the parent node */ + const xmlNode * parent; /* the parent node */ int n_parent; for (n_parent = 0;n_parent < gen_nb_const_xmlNode_ptr;n_parent++) { mem_base = xmlMemBlocks(); parent = gen_const_xmlNode_ptr(n_parent, 0); - ret_val = xmlGetLastChild((const xmlNode *)parent); + ret_val = xmlGetLastChild(parent); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_parent, (const xmlNode *)parent, 0); + des_const_xmlNode_ptr(n_parent, parent, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetLastChild", @@ -20084,17 +20650,17 @@ test_xmlGetLineNo(void) { int mem_base; long ret_val; - xmlNode * node; /* valid node */ + const xmlNode * node; /* valid node */ int n_node; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { mem_base = xmlMemBlocks(); node = gen_const_xmlNode_ptr(n_node, 0); - ret_val = xmlGetLineNo((const xmlNode *)node); + ret_val = xmlGetLineNo(node); desret_long(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); + des_const_xmlNode_ptr(n_node, node, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetLineNo", @@ -20116,9 +20682,9 @@ test_xmlGetNoNsProp(void) { int mem_base; xmlChar * ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { @@ -20127,11 +20693,11 @@ test_xmlGetNoNsProp(void) { node = gen_const_xmlNode_ptr(n_node, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetNoNsProp((const xmlNode *)node, (const xmlChar *)name); + ret_val = xmlGetNoNsProp(node, name); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetNoNsProp", @@ -20156,17 +20722,17 @@ test_xmlGetNodePath(void) { #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) int mem_base; xmlChar * ret_val; - xmlNode * node; /* a node */ + const xmlNode * node; /* a node */ int n_node; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { mem_base = xmlMemBlocks(); node = gen_const_xmlNode_ptr(n_node, 0); - ret_val = xmlGetNodePath((const xmlNode *)node); + ret_val = xmlGetNodePath(node); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); + des_const_xmlNode_ptr(n_node, node, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetNodePath", @@ -20193,17 +20759,27 @@ test_xmlGetNsList(void) { } +static int +test_xmlGetNsListSafe(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlGetNsProp(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * nameSpace; /* the URI of the namespace */ + const xmlChar * nameSpace; /* the URI of the namespace */ int n_nameSpace; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { @@ -20214,12 +20790,12 @@ test_xmlGetNsProp(void) { name = gen_const_xmlChar_ptr(n_name, 1); nameSpace = gen_const_xmlChar_ptr(n_nameSpace, 2); - ret_val = xmlGetNsProp((const xmlNode *)node, (const xmlChar *)name, (const xmlChar *)nameSpace); + ret_val = xmlGetNsProp(node, name, nameSpace); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_nameSpace, (const xmlChar *)nameSpace, 2); + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_nameSpace, nameSpace, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetNsProp", @@ -20245,9 +20821,9 @@ test_xmlGetProp(void) { int mem_base; xmlChar * ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { @@ -20256,11 +20832,11 @@ test_xmlGetProp(void) { node = gen_const_xmlNode_ptr(n_node, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetProp((const xmlNode *)node, (const xmlChar *)name); + ret_val = xmlGetProp(node, name); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetProp", @@ -20284,11 +20860,11 @@ test_xmlHasNsProp(void) { int mem_base; xmlAttrPtr ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * nameSpace; /* the URI of the namespace */ + const xmlChar * nameSpace; /* the URI of the namespace */ int n_nameSpace; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { @@ -20299,12 +20875,12 @@ test_xmlHasNsProp(void) { name = gen_const_xmlChar_ptr(n_name, 1); nameSpace = gen_const_xmlChar_ptr(n_nameSpace, 2); - ret_val = xmlHasNsProp((const xmlNode *)node, (const xmlChar *)name, (const xmlChar *)nameSpace); + ret_val = xmlHasNsProp(node, name, nameSpace); desret_xmlAttrPtr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_nameSpace, (const xmlChar *)nameSpace, 2); + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_nameSpace, nameSpace, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHasNsProp", @@ -20330,9 +20906,9 @@ test_xmlHasProp(void) { int mem_base; xmlAttrPtr ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { @@ -20341,11 +20917,11 @@ test_xmlHasProp(void) { node = gen_const_xmlNode_ptr(n_node, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlHasProp((const xmlNode *)node, (const xmlChar *)name); + ret_val = xmlHasProp(node, name); desret_xmlAttrPtr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlHasProp", @@ -20369,17 +20945,17 @@ test_xmlIsBlankNode(void) { int mem_base; int ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { mem_base = xmlMemBlocks(); node = gen_const_xmlNode_ptr(n_node, 0); - ret_val = xmlIsBlankNode((const xmlNode *)node); + ret_val = xmlIsBlankNode(node); desret_int(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); + des_const_xmlNode_ptr(n_node, node, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlIsBlankNode", @@ -20401,9 +20977,9 @@ test_xmlIsXHTML(void) { int mem_base; int ret_val; - xmlChar * systemID; /* the system identifier */ + const xmlChar * systemID; /* the system identifier */ int n_systemID; - xmlChar * publicID; /* the public identifier */ + const xmlChar * publicID; /* the public identifier */ int n_publicID; for (n_systemID = 0;n_systemID < gen_nb_const_xmlChar_ptr;n_systemID++) { @@ -20412,11 +20988,11 @@ test_xmlIsXHTML(void) { systemID = gen_const_xmlChar_ptr(n_systemID, 0); publicID = gen_const_xmlChar_ptr(n_publicID, 1); - ret_val = xmlIsXHTML((const xmlChar *)systemID, (const xmlChar *)publicID); + ret_val = xmlIsXHTML(systemID, publicID); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_systemID, (const xmlChar *)systemID, 0); - des_const_xmlChar_ptr(n_publicID, (const xmlChar *)publicID, 1); + des_const_xmlChar_ptr(n_systemID, systemID, 0); + des_const_xmlChar_ptr(n_publicID, publicID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlIsXHTML", @@ -20474,11 +21050,11 @@ test_xmlNewCDataBlock(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document (optional) */ int n_doc; - xmlChar * content; /* the CDATA block content content */ + const xmlChar * content; /* raw text content (optional) */ int n_content; - int len; /* the length of the block */ + int len; /* size of text content */ int n_len; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20492,11 +21068,11 @@ test_xmlNewCDataBlock(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - ret_val = xmlNewCDataBlock(doc, (const xmlChar *)content, len); + ret_val = xmlNewCDataBlock(doc, content, len); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -20523,9 +21099,9 @@ test_xmlNewCharRef(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document (optional) */ int n_doc; - xmlChar * name; /* the char ref string, starting with # or "&# ... ;" */ + const xmlChar * name; /* the entity name */ int n_name; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20534,11 +21110,11 @@ test_xmlNewCharRef(void) { doc = gen_xmlDocPtr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlNewCharRef(doc, (const xmlChar *)name); + ret_val = xmlNewCharRef(doc, name); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewCharRef", @@ -20566,11 +21142,11 @@ test_xmlNewChild(void) { xmlNodePtr ret_val; xmlNodePtr parent; /* the parent node */ int n_parent; - xmlNsPtr ns; /* a namespace if any */ + xmlNsPtr ns; /* a namespace (optional) */ int n_ns; - xmlChar * name; /* the name of the child */ + const xmlChar * name; /* the name of the child */ int n_name; - xmlChar * content; /* the XML content of the child if any. */ + const xmlChar * content; /* text content with XML references (optional) */ int n_content; for (n_parent = 0;n_parent < gen_nb_xmlNodePtr;n_parent++) { @@ -20583,13 +21159,13 @@ test_xmlNewChild(void) { name = gen_const_xmlChar_ptr(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlNewChild(parent, ns, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewChild(parent, ns, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlNodePtr(n_parent, parent, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewChild", @@ -20619,17 +21195,17 @@ test_xmlNewComment(void) { int mem_base; xmlNodePtr ret_val; - xmlChar * content; /* the comment content */ + const xmlChar * content; /* the comment content (optional) */ int n_content; for (n_content = 0;n_content < gen_nb_const_xmlChar_ptr;n_content++) { mem_base = xmlMemBlocks(); content = gen_const_xmlChar_ptr(n_content, 0); - ret_val = xmlNewComment((const xmlChar *)content); + ret_val = xmlNewComment(content); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 0); + des_const_xmlChar_ptr(n_content, content, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewComment", @@ -20651,17 +21227,17 @@ test_xmlNewDoc(void) { int mem_base; xmlDocPtr ret_val; - xmlChar * version; /* xmlChar string giving the version of XML "1.0" */ + const xmlChar * version; /* XML version string like "1.0" (optional) */ int n_version; for (n_version = 0;n_version < gen_nb_const_xmlChar_ptr;n_version++) { mem_base = xmlMemBlocks(); version = gen_const_xmlChar_ptr(n_version, 0); - ret_val = xmlNewDoc((const xmlChar *)version); + ret_val = xmlNewDoc(version); desret_xmlDocPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_version, (const xmlChar *)version, 0); + des_const_xmlChar_ptr(n_version, version, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDoc", @@ -20685,7 +21261,7 @@ test_xmlNewDocComment(void) { xmlNodePtr ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * content; /* the comment content */ + const xmlChar * content; /* the comment content */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20694,11 +21270,11 @@ test_xmlNewDocComment(void) { doc = gen_xmlDocPtr(n_doc, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlNewDocComment(doc, (const xmlChar *)content); + ret_val = xmlNewDocComment(doc, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocComment", @@ -20723,7 +21299,7 @@ test_xmlNewDocFragment(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document owning the fragment */ + xmlDocPtr doc; /* the target document (optional) */ int n_doc; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20756,13 +21332,13 @@ test_xmlNewDocNode(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document */ int n_doc; - xmlNsPtr ns; /* namespace if any */ + xmlNsPtr ns; /* namespace (optional) */ int n_ns; - xmlChar * name; /* the node name */ + const xmlChar * name; /* the node name */ int n_name; - xmlChar * content; /* the XML text content if any */ + const xmlChar * content; /* text content with XML references (optional) */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20775,13 +21351,13 @@ test_xmlNewDocNode(void) { name = gen_const_xmlChar_ptr(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlNewDocNode(doc, ns, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewDocNode(doc, ns, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocNode", @@ -20809,13 +21385,13 @@ test_xmlNewDocNodeEatName(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document */ int n_doc; - xmlNsPtr ns; /* namespace if any */ + xmlNsPtr ns; /* namespace (optional) */ int n_ns; xmlChar * name; /* the node name */ int n_name; - xmlChar * content; /* the XML text content if any */ + const xmlChar * content; /* text content with XML references (optional) */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20828,13 +21404,13 @@ test_xmlNewDocNodeEatName(void) { name = gen_eaten_name(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlNewDocNodeEatName(doc, ns, name, (const xmlChar *)content); + ret_val = xmlNewDocNodeEatName(doc, ns, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNsPtr(n_ns, ns, 1); des_eaten_name(n_name, name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocNodeEatName", @@ -20862,11 +21438,11 @@ test_xmlNewDocPI(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the target document */ + xmlDocPtr doc; /* the target document (optional) */ int n_doc; - xmlChar * name; /* the processing instruction name */ + const xmlChar * name; /* the processing instruction target */ int n_name; - xmlChar * content; /* the PI content */ + const xmlChar * content; /* the PI content (optional) */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20877,12 +21453,12 @@ test_xmlNewDocPI(void) { name = gen_const_xmlChar_ptr(n_name, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlNewDocPI(doc, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewDocPI(doc, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocPI", @@ -20908,11 +21484,11 @@ test_xmlNewDocProp(void) { int mem_base; xmlAttrPtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document (optional) */ int n_doc; - xmlChar * name; /* the name of the attribute */ + const xmlChar * name; /* the name of the attribute */ int n_name; - xmlChar * value; /* the value of the attribute */ + const xmlChar * value; /* attribute value with XML references (optional) */ int n_value; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20923,12 +21499,12 @@ test_xmlNewDocProp(void) { name = gen_const_xmlChar_ptr(n_name, 1); value = gen_const_xmlChar_ptr(n_value, 2); - ret_val = xmlNewDocProp(doc, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlNewDocProp(doc, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_value, value, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocProp", @@ -20956,13 +21532,13 @@ test_xmlNewDocRawNode(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document */ int n_doc; - xmlNsPtr ns; /* namespace if any */ + xmlNsPtr ns; /* namespace (optional) */ int n_ns; - xmlChar * name; /* the node name */ + const xmlChar * name; /* the node name */ int n_name; - xmlChar * content; /* the text content if any */ + const xmlChar * content; /* raw text content (optional) */ int n_content; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -20975,13 +21551,13 @@ test_xmlNewDocRawNode(void) { name = gen_const_xmlChar_ptr(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlNewDocRawNode(doc, ns, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewDocRawNode(doc, ns, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocRawNode", @@ -21011,9 +21587,9 @@ test_xmlNewDocText(void) { int mem_base; xmlNodePtr ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* the target document */ int n_doc; - xmlChar * content; /* the text content */ + const xmlChar * content; /* raw text content (optional) */ int n_content; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -21022,11 +21598,11 @@ test_xmlNewDocText(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlNewDocText((const xmlDoc *)doc, (const xmlChar *)content); + ret_val = xmlNewDocText(doc, content); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDocText", @@ -21050,11 +21626,11 @@ test_xmlNewDocTextLen(void) { int mem_base; xmlNodePtr ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* the target document */ int n_doc; - xmlChar * content; /* the text content */ + const xmlChar * content; /* raw text content (optional) */ int n_content; - int len; /* the text len. */ + int len; /* size of text content */ int n_len; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -21068,11 +21644,11 @@ test_xmlNewDocTextLen(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - ret_val = xmlNewDocTextLen(doc, (const xmlChar *)content, len); + ret_val = xmlNewDocTextLen(doc, content, len); desret_xmlNodePtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -21099,13 +21675,13 @@ test_xmlNewDtd(void) { int mem_base; xmlDtdPtr ret_val; - xmlDocPtr doc; /* the document pointer */ + xmlDocPtr doc; /* the document pointer (optional) */ int n_doc; - xmlChar * name; /* the DTD name */ + const xmlChar * name; /* the DTD name (optional) */ int n_name; - xmlChar * ExternalID; /* the external ID */ + const xmlChar * ExternalID; /* the external ID (optional) */ int n_ExternalID; - xmlChar * SystemID; /* the system ID */ + const xmlChar * SystemID; /* the system ID (optional) */ int n_SystemID; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -21118,13 +21694,13 @@ test_xmlNewDtd(void) { ExternalID = gen_const_xmlChar_ptr(n_ExternalID, 2); SystemID = gen_const_xmlChar_ptr(n_SystemID, 3); - ret_val = xmlNewDtd(doc, (const xmlChar *)name, (const xmlChar *)ExternalID, (const xmlChar *)SystemID); + ret_val = xmlNewDtd(doc, name, ExternalID, SystemID); desret_xmlDtdPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ExternalID, (const xmlChar *)ExternalID, 2); - des_const_xmlChar_ptr(n_SystemID, (const xmlChar *)SystemID, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ExternalID, ExternalID, 2); + des_const_xmlChar_ptr(n_SystemID, SystemID, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewDtd", @@ -21152,9 +21728,9 @@ test_xmlNewNode(void) { int mem_base; xmlNodePtr ret_val; - xmlNsPtr ns; /* namespace if any */ + xmlNsPtr ns; /* namespace (optional) */ int n_ns; - xmlChar * name; /* the node name */ + const xmlChar * name; /* the node name */ int n_name; for (n_ns = 0;n_ns < gen_nb_xmlNsPtr;n_ns++) { @@ -21163,11 +21739,11 @@ test_xmlNewNode(void) { ns = gen_xmlNsPtr(n_ns, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlNewNode(ns, (const xmlChar *)name); + ret_val = xmlNewNode(ns, name); desret_xmlNodePtr(ret_val); call_tests++; des_xmlNsPtr(n_ns, ns, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewNode", @@ -21191,7 +21767,7 @@ test_xmlNewNodeEatName(void) { int mem_base; xmlNodePtr ret_val; - xmlNsPtr ns; /* namespace if any */ + xmlNsPtr ns; /* namespace (optional) */ int n_ns; xmlChar * name; /* the node name */ int n_name; @@ -21230,11 +21806,11 @@ test_xmlNewNs(void) { int mem_base; xmlNsPtr ret_val; - xmlNodePtr node; /* the element carrying the namespace */ + xmlNodePtr node; /* the element carrying the namespace (optional) */ int n_node; - xmlChar * href; /* the URI associated */ + const xmlChar * href; /* the URI associated */ int n_href; - xmlChar * prefix; /* the prefix for the namespace */ + const xmlChar * prefix; /* the prefix for the namespace (optional) */ int n_prefix; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -21245,13 +21821,13 @@ test_xmlNewNs(void) { href = gen_const_xmlChar_ptr(n_href, 1); prefix = gen_const_xmlChar_ptr(n_prefix, 2); - ret_val = xmlNewNs(node, (const xmlChar *)href, (const xmlChar *)prefix); + ret_val = xmlNewNs(node, href, prefix); if ((node == NULL) && (ret_val != NULL)) xmlFreeNs(ret_val); desret_xmlNsPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_href, (const xmlChar *)href, 1); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 2); + des_const_xmlChar_ptr(n_href, href, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewNs", @@ -21277,13 +21853,13 @@ test_xmlNewNsProp(void) { int mem_base; xmlAttrPtr ret_val; - xmlNodePtr node; /* the holding node */ + xmlNodePtr node; /* the parent node (optional) */ int n_node; - xmlNsPtr ns; /* the namespace */ + xmlNsPtr ns; /* the namespace (optional) */ int n_ns; - xmlChar * name; /* the name of the attribute */ + const xmlChar * name; /* the local name of the attribute */ int n_name; - xmlChar * value; /* the value of the attribute */ + const xmlChar * value; /* the value of the attribute (optional) */ int n_value; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -21296,13 +21872,13 @@ test_xmlNewNsProp(void) { name = gen_const_xmlChar_ptr(n_name, 2); value = gen_const_xmlChar_ptr(n_value, 3); - ret_val = xmlNewNsProp(node, ns, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlNewNsProp(node, ns, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_value, value, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewNsProp", @@ -21330,13 +21906,13 @@ test_xmlNewNsPropEatName(void) { int mem_base; xmlAttrPtr ret_val; - xmlNodePtr node; /* the holding node */ + xmlNodePtr node; /* the parent node (optional) */ int n_node; - xmlNsPtr ns; /* the namespace */ + xmlNsPtr ns; /* the namespace (optional) */ int n_ns; - xmlChar * name; /* the name of the attribute */ + xmlChar * name; /* the local name of the attribute */ int n_name; - xmlChar * value; /* the value of the attribute */ + const xmlChar * value; /* the value of the attribute (optional) */ int n_value; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -21349,13 +21925,13 @@ test_xmlNewNsPropEatName(void) { name = gen_eaten_name(n_name, 2); value = gen_const_xmlChar_ptr(n_value, 3); - ret_val = xmlNewNsPropEatName(node, ns, name, (const xmlChar *)value); + ret_val = xmlNewNsPropEatName(node, ns, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); des_xmlNsPtr(n_ns, ns, 1); des_eaten_name(n_name, name, 2); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 3); + des_const_xmlChar_ptr(n_value, value, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewNsPropEatName", @@ -21383,9 +21959,9 @@ test_xmlNewPI(void) { int mem_base; xmlNodePtr ret_val; - xmlChar * name; /* the processing instruction name */ + const xmlChar * name; /* the processing instruction target */ int n_name; - xmlChar * content; /* the PI content */ + const xmlChar * content; /* the PI content (optional) */ int n_content; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { @@ -21394,11 +21970,11 @@ test_xmlNewPI(void) { name = gen_const_xmlChar_ptr(n_name, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlNewPI((const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewPI(name, content); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_name, name, 0); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewPI", @@ -21424,11 +22000,11 @@ test_xmlNewProp(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; xmlAttrPtr ret_val; - xmlNodePtr node; /* the holding node */ + xmlNodePtr node; /* the parent node (optional) */ int n_node; - xmlChar * name; /* the name of the attribute */ + const xmlChar * name; /* the name of the attribute */ int n_name; - xmlChar * value; /* the value of the attribute */ + const xmlChar * value; /* the value of the attribute (optional) */ int n_value; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -21439,12 +22015,12 @@ test_xmlNewProp(void) { name = gen_const_xmlChar_ptr(n_name, 1); value = gen_const_xmlChar_ptr(n_value, 2); - ret_val = xmlNewProp(node, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlNewProp(node, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_value, value, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewProp", @@ -21472,9 +22048,9 @@ test_xmlNewReference(void) { int mem_base; xmlNodePtr ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* the target document (optional) */ int n_doc; - xmlChar * name; /* the reference name, or the reference string with & and ; */ + const xmlChar * name; /* the entity name */ int n_name; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -21483,11 +22059,11 @@ test_xmlNewReference(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlNewReference((const xmlDoc *)doc, (const xmlChar *)name); + ret_val = xmlNewReference(doc, name); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewReference", @@ -21511,17 +22087,17 @@ test_xmlNewText(void) { int mem_base; xmlNodePtr ret_val; - xmlChar * content; /* the text content */ + const xmlChar * content; /* raw text content (optional) */ int n_content; for (n_content = 0;n_content < gen_nb_const_xmlChar_ptr;n_content++) { mem_base = xmlMemBlocks(); content = gen_const_xmlChar_ptr(n_content, 0); - ret_val = xmlNewText((const xmlChar *)content); + ret_val = xmlNewText(content); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 0); + des_const_xmlChar_ptr(n_content, content, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewText", @@ -21547,11 +22123,11 @@ test_xmlNewTextChild(void) { xmlNodePtr ret_val; xmlNodePtr parent; /* the parent node */ int n_parent; - xmlNsPtr ns; /* a namespace if any */ + xmlNsPtr ns; /* a namespace (optional) */ int n_ns; - xmlChar * name; /* the name of the child */ + const xmlChar * name; /* the name of the child */ int n_name; - xmlChar * content; /* the text content of the child if any. */ + const xmlChar * content; /* raw text content of the child (optional) */ int n_content; for (n_parent = 0;n_parent < gen_nb_xmlNodePtr;n_parent++) { @@ -21564,13 +22140,13 @@ test_xmlNewTextChild(void) { name = gen_const_xmlChar_ptr(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlNewTextChild(parent, ns, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlNewTextChild(parent, ns, name, content); desret_xmlNodePtr(ret_val); call_tests++; des_xmlNodePtr(n_parent, parent, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNewTextChild", @@ -21600,9 +22176,9 @@ test_xmlNewTextLen(void) { int mem_base; xmlNodePtr ret_val; - xmlChar * content; /* the text content */ + const xmlChar * content; /* raw text content (optional) */ int n_content; - int len; /* the text len. */ + int len; /* size of text content */ int n_len; for (n_content = 0;n_content < gen_nb_const_xmlChar_ptr;n_content++) { @@ -21614,10 +22190,10 @@ test_xmlNewTextLen(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - ret_val = xmlNewTextLen((const xmlChar *)content, len); + ret_val = xmlNewTextLen(content, len); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 0); + des_const_xmlChar_ptr(n_content, content, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -21675,9 +22251,10 @@ test_xmlNodeAddContent(void) { int test_ret = 0; int mem_base; + int ret_val; xmlNodePtr cur; /* the node being modified */ int n_cur; - xmlChar * content; /* extra content */ + const xmlChar * content; /* extra content */ int n_content; for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { @@ -21686,10 +22263,11 @@ test_xmlNodeAddContent(void) { cur = gen_xmlNodePtr(n_cur, 0); content = gen_const_xmlChar_ptr(n_content, 1); - xmlNodeAddContent(cur, (const xmlChar *)content); + ret_val = xmlNodeAddContent(cur, content); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeAddContent", @@ -21712,9 +22290,10 @@ test_xmlNodeAddContentLen(void) { int test_ret = 0; int mem_base; + int ret_val; xmlNodePtr cur; /* the node being modified */ int n_cur; - xmlChar * content; /* extra content */ + const xmlChar * content; /* extra content */ int n_content; int len; /* the size of @content */ int n_len; @@ -21730,10 +22309,11 @@ test_xmlNodeAddContentLen(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - xmlNodeAddContentLen(cur, (const xmlChar *)content, len); + ret_val = xmlNodeAddContentLen(cur, content, len); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -21762,7 +22342,7 @@ test_xmlNodeBufGetContent(void) { int ret_val; xmlBufferPtr buffer; /* a buffer */ int n_buffer; - xmlNode * cur; /* the node being read */ + const xmlNode * cur; /* the node being read */ int n_cur; for (n_buffer = 0;n_buffer < gen_nb_xmlBufferPtr;n_buffer++) { @@ -21771,11 +22351,11 @@ test_xmlNodeBufGetContent(void) { buffer = gen_xmlBufferPtr(n_buffer, 0); cur = gen_const_xmlNode_ptr(n_cur, 1); - ret_val = xmlNodeBufGetContent(buffer, (const xmlNode *)cur); + ret_val = xmlNodeBufGetContent(buffer, cur); desret_int(ret_val); call_tests++; des_xmlBufferPtr(n_buffer, buffer, 0); - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 1); + des_const_xmlNode_ptr(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeBufGetContent", @@ -21871,7 +22451,7 @@ test_xmlNodeDumpOutput(void) { int n_level; int format; /* is formatting allowed */ int n_format; - char * encoding; /* an optional encoding string */ + const char * encoding; /* an optional encoding string */ int n_encoding; for (n_buf = 0;n_buf < gen_nb_xmlOutputBufferPtr;n_buf++) { @@ -21888,14 +22468,14 @@ test_xmlNodeDumpOutput(void) { format = gen_int(n_format, 4); encoding = gen_const_char_ptr(n_encoding, 5); - xmlNodeDumpOutput(buf, doc, cur, level, format, (const char *)encoding); + xmlNodeDumpOutput(buf, doc, cur, level, format, encoding); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_cur, cur, 2); des_int(n_level, level, 3); des_int(n_format, format, 4); - des_const_char_ptr(n_encoding, (const char *)encoding, 5); + des_const_char_ptr(n_encoding, encoding, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeDumpOutput", @@ -21922,15 +22502,68 @@ test_xmlNodeDumpOutput(void) { } +static int +test_xmlNodeGetAttrValue(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + const xmlNode * node; /* the node */ + int n_node; + const xmlChar * name; /* the attribute name */ + int n_name; + const xmlChar * nsUri; /* the URI of the namespace */ + int n_nsUri; + xmlChar ** out; /* the returned string */ + int n_out; + + for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { + for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { + for (n_nsUri = 0;n_nsUri < gen_nb_const_xmlChar_ptr;n_nsUri++) { + for (n_out = 0;n_out < gen_nb_xmlChar_ptr_ptr;n_out++) { + mem_base = xmlMemBlocks(); + node = gen_const_xmlNode_ptr(n_node, 0); + name = gen_const_xmlChar_ptr(n_name, 1); + nsUri = gen_const_xmlChar_ptr(n_nsUri, 2); + out = gen_xmlChar_ptr_ptr(n_out, 3); + + ret_val = xmlNodeGetAttrValue(node, name, nsUri, out); + desret_int(ret_val); + call_tests++; + des_const_xmlNode_ptr(n_node, node, 0); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_nsUri, nsUri, 2); + des_xmlChar_ptr_ptr(n_out, out, 3); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlNodeGetAttrValue", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_node); + printf(" %d", n_name); + printf(" %d", n_nsUri); + printf(" %d", n_out); + printf("\n"); + } + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlNodeGetBase(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlDoc * doc; /* the document the node pertains to */ + const xmlDoc * doc; /* the document the node pertains to */ int n_doc; - xmlNode * cur; /* the node being checked */ + const xmlNode * cur; /* the node being checked */ int n_cur; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -21939,11 +22572,11 @@ test_xmlNodeGetBase(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); cur = gen_const_xmlNode_ptr(n_cur, 1); - ret_val = xmlNodeGetBase((const xmlDoc *)doc, (const xmlNode *)cur); + ret_val = xmlNodeGetBase(doc, cur); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlNode_ptr(n_cur, cur, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeGetBase", @@ -21961,23 +22594,69 @@ test_xmlNodeGetBase(void) { } +static int +test_xmlNodeGetBaseSafe(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + const xmlDoc * doc; /* the document the node pertains to */ + int n_doc; + const xmlNode * cur; /* the node being checked */ + int n_cur; + xmlChar ** baseOut; /* pointer to base */ + int n_baseOut; + + for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { + for (n_cur = 0;n_cur < gen_nb_const_xmlNode_ptr;n_cur++) { + for (n_baseOut = 0;n_baseOut < gen_nb_xmlChar_ptr_ptr;n_baseOut++) { + mem_base = xmlMemBlocks(); + doc = gen_const_xmlDoc_ptr(n_doc, 0); + cur = gen_const_xmlNode_ptr(n_cur, 1); + baseOut = gen_xmlChar_ptr_ptr(n_baseOut, 2); + + ret_val = xmlNodeGetBaseSafe(doc, cur, baseOut); + desret_int(ret_val); + call_tests++; + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlNode_ptr(n_cur, cur, 1); + des_xmlChar_ptr_ptr(n_baseOut, baseOut, 2); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlNodeGetBaseSafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_doc); + printf(" %d", n_cur); + printf(" %d", n_baseOut); + printf("\n"); + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlNodeGetContent(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlNode * cur; /* the node being read */ + const xmlNode * cur; /* the node being read */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlNode_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlNode_ptr(n_cur, 0); - ret_val = xmlNodeGetContent((const xmlNode *)cur); + ret_val = xmlNodeGetContent(cur); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 0); + des_const_xmlNode_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeGetContent", @@ -21999,17 +22678,17 @@ test_xmlNodeGetLang(void) { int mem_base; xmlChar * ret_val; - xmlNode * cur; /* the node being checked */ + const xmlNode * cur; /* the node being checked */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlNode_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlNode_ptr(n_cur, 0); - ret_val = xmlNodeGetLang((const xmlNode *)cur); + ret_val = xmlNodeGetLang(cur); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 0); + des_const_xmlNode_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeGetLang", @@ -22031,17 +22710,17 @@ test_xmlNodeGetSpacePreserve(void) { int mem_base; int ret_val; - xmlNode * cur; /* the node being checked */ + const xmlNode * cur; /* the node being checked */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlNode_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlNode_ptr(n_cur, 0); - ret_val = xmlNodeGetSpacePreserve((const xmlNode *)cur); + ret_val = xmlNodeGetSpacePreserve(cur); desret_int(ret_val); call_tests++; - des_const_xmlNode_ptr(n_cur, (const xmlNode *)cur, 0); + des_const_xmlNode_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeGetSpacePreserve", @@ -22063,17 +22742,17 @@ test_xmlNodeIsText(void) { int mem_base; int ret_val; - xmlNode * node; /* the node */ + const xmlNode * node; /* the node */ int n_node; for (n_node = 0;n_node < gen_nb_const_xmlNode_ptr;n_node++) { mem_base = xmlMemBlocks(); node = gen_const_xmlNode_ptr(n_node, 0); - ret_val = xmlNodeIsText((const xmlNode *)node); + ret_val = xmlNodeIsText(node); desret_int(ret_val); call_tests++; - des_const_xmlNode_ptr(n_node, (const xmlNode *)node, 0); + des_const_xmlNode_ptr(n_node, node, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeIsText", @@ -22096,11 +22775,11 @@ test_xmlNodeListGetRawString(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; xmlChar * ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* a document (optional) */ int n_doc; - xmlNode * list; /* a Node list */ + const xmlNode * list; /* a node list of attribute children (optional) */ int n_list; - int inLine; /* should we replace entity contents or show their external form */ + int inLine; /* whether entity references are substituted */ int n_inLine; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -22111,11 +22790,11 @@ test_xmlNodeListGetRawString(void) { list = gen_const_xmlNode_ptr(n_list, 1); inLine = gen_int(n_inLine, 2); - ret_val = xmlNodeListGetRawString((const xmlDoc *)doc, (const xmlNode *)list, inLine); + ret_val = xmlNodeListGetRawString(doc, list, inLine); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlNode_ptr(n_list, (const xmlNode *)list, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlNode_ptr(n_list, list, 1); des_int(n_inLine, inLine, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -22143,11 +22822,11 @@ test_xmlNodeListGetString(void) { int mem_base; xmlChar * ret_val; - xmlDocPtr doc; /* the document */ + xmlDocPtr doc; /* a document (optional) */ int n_doc; - xmlNode * list; /* a Node list */ + const xmlNode * list; /* a node list of attribute children (optional) */ int n_list; - int inLine; /* should we replace entity contents or show their external form */ + int inLine; /* whether entity references are substituted */ int n_inLine; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -22158,11 +22837,11 @@ test_xmlNodeListGetString(void) { list = gen_const_xmlNode_ptr(n_list, 1); inLine = gen_int(n_inLine, 2); - ret_val = xmlNodeListGetString(doc, (const xmlNode *)list, inLine); + ret_val = xmlNodeListGetString(doc, list, inLine); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlNode_ptr(n_list, (const xmlNode *)list, 1); + des_const_xmlNode_ptr(n_list, list, 1); des_int(n_inLine, inLine, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -22189,9 +22868,10 @@ test_xmlNodeSetBase(void) { #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) int mem_base; + int ret_val; xmlNodePtr cur; /* the node being changed */ int n_cur; - xmlChar * uri; /* the new base URI */ + const xmlChar * uri; /* the new base URI */ int n_uri; for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { @@ -22200,10 +22880,11 @@ test_xmlNodeSetBase(void) { cur = gen_xmlNodePtr(n_cur, 0); uri = gen_const_xmlChar_ptr(n_uri, 1); - xmlNodeSetBase(cur, (const xmlChar *)uri); + ret_val = xmlNodeSetBase(cur, uri); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_uri, (const xmlChar *)uri, 1); + des_const_xmlChar_ptr(n_uri, uri, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeSetBase", @@ -22227,9 +22908,10 @@ test_xmlNodeSetContent(void) { int test_ret = 0; int mem_base; + int ret_val; xmlNodePtr cur; /* the node being modified */ int n_cur; - xmlChar * content; /* the new value of the content */ + const xmlChar * content; /* the new value of the content */ int n_content; for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { @@ -22238,10 +22920,11 @@ test_xmlNodeSetContent(void) { cur = gen_xmlNodePtr(n_cur, 0); content = gen_const_xmlChar_ptr(n_content, 1); - xmlNodeSetContent(cur, (const xmlChar *)content); + ret_val = xmlNodeSetContent(cur, content); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeSetContent", @@ -22265,9 +22948,10 @@ test_xmlNodeSetContentLen(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; + int ret_val; xmlNodePtr cur; /* the node being modified */ int n_cur; - xmlChar * content; /* the new value of the content */ + const xmlChar * content; /* the new value of the content */ int n_content; int len; /* the size of @content */ int n_len; @@ -22283,10 +22967,11 @@ test_xmlNodeSetContentLen(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - xmlNodeSetContentLen(cur, (const xmlChar *)content, len); + ret_val = xmlNodeSetContentLen(cur, content, len); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -22314,9 +22999,10 @@ test_xmlNodeSetLang(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; + int ret_val; xmlNodePtr cur; /* the node being changed */ int n_cur; - xmlChar * lang; /* the language description */ + const xmlChar * lang; /* the language description */ int n_lang; for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { @@ -22325,10 +23011,11 @@ test_xmlNodeSetLang(void) { cur = gen_xmlNodePtr(n_cur, 0); lang = gen_const_xmlChar_ptr(n_lang, 1); - xmlNodeSetLang(cur, (const xmlChar *)lang); + ret_val = xmlNodeSetLang(cur, lang); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_lang, (const xmlChar *)lang, 1); + des_const_xmlChar_ptr(n_lang, lang, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeSetLang", @@ -22355,7 +23042,7 @@ test_xmlNodeSetName(void) { int mem_base; xmlNodePtr cur; /* the node being changed */ int n_cur; - xmlChar * name; /* the new tag name */ + const xmlChar * name; /* the new tag name */ int n_name; for (n_cur = 0;n_cur < gen_nb_xmlNodePtr;n_cur++) { @@ -22364,10 +23051,10 @@ test_xmlNodeSetName(void) { cur = gen_xmlNodePtr(n_cur, 0); name = gen_const_xmlChar_ptr(n_name, 1); - xmlNodeSetName(cur, (const xmlChar *)name); + xmlNodeSetName(cur, name); call_tests++; des_xmlNodePtr(n_cur, cur, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNodeSetName", @@ -22392,6 +23079,7 @@ test_xmlNodeSetSpacePreserve(void) { #if defined(LIBXML_TREE_ENABLED) int mem_base; + int ret_val; xmlNodePtr cur; /* the node being changed */ int n_cur; int val; /* the xml:space value ("0": default, 1: "preserve") */ @@ -22403,7 +23091,8 @@ test_xmlNodeSetSpacePreserve(void) { cur = gen_xmlNodePtr(n_cur, 0); val = gen_int(n_val, 1); - xmlNodeSetSpacePreserve(cur, val); + ret_val = xmlNodeSetSpacePreserve(cur, val); + desret_int(ret_val); call_tests++; des_xmlNodePtr(n_cur, cur, 0); des_int(n_val, val, 1); @@ -22554,7 +23243,7 @@ test_xmlReplaceNode(void) { xmlNodePtr ret_val; xmlNodePtr old; /* the old node */ int n_old; - xmlNodePtr cur; /* the node */ + xmlNodePtr cur; /* the node (optional) */ int n_cur; for (n_old = 0;n_old < gen_nb_xmlNodePtr;n_old++) { @@ -22645,7 +23334,7 @@ test_xmlSaveFileEnc(void) { int n_filename; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the name of an encoding (or NULL) */ + const char * encoding; /* the name of an encoding (or NULL) */ int n_encoding; for (n_filename = 0;n_filename < gen_nb_fileoutput;n_filename++) { @@ -22656,12 +23345,12 @@ test_xmlSaveFileEnc(void) { cur = gen_xmlDocPtr(n_cur, 1); encoding = gen_const_char_ptr(n_encoding, 2); - ret_val = xmlSaveFileEnc(filename, cur, (const char *)encoding); + ret_val = xmlSaveFileEnc(filename, cur, encoding); desret_int(ret_val); call_tests++; des_fileoutput(n_filename, filename, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSaveFileEnc", @@ -22693,7 +23382,7 @@ test_xmlSaveFileTo(void) { int n_buf; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the encoding if any assuming the I/O layer handles the transcoding */ + const char * encoding; /* the encoding if any assuming the I/O layer handles the transcoding */ int n_encoding; for (n_buf = 0;n_buf < gen_nb_xmlOutputBufferPtr;n_buf++) { @@ -22704,13 +23393,13 @@ test_xmlSaveFileTo(void) { cur = gen_xmlDocPtr(n_cur, 1); encoding = gen_const_char_ptr(n_encoding, 2); - ret_val = xmlSaveFileTo(buf, cur, (const char *)encoding); + ret_val = xmlSaveFileTo(buf, cur, encoding); buf = NULL; desret_int(ret_val); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSaveFileTo", @@ -22790,7 +23479,7 @@ test_xmlSaveFormatFileEnc(void) { int n_filename; xmlDocPtr cur; /* the document being saved */ int n_cur; - char * encoding; /* the name of the encoding to use or NULL. */ + const char * encoding; /* the name of the encoding to use or NULL. */ int n_encoding; int format; /* should formatting spaces be added. */ int n_format; @@ -22805,12 +23494,12 @@ test_xmlSaveFormatFileEnc(void) { encoding = gen_const_char_ptr(n_encoding, 2); format = gen_int(n_format, 3); - ret_val = xmlSaveFormatFileEnc(filename, cur, (const char *)encoding, format); + ret_val = xmlSaveFormatFileEnc(filename, cur, encoding, format); desret_int(ret_val); call_tests++; des_fileoutput(n_filename, filename, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_format, format, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -22845,7 +23534,7 @@ test_xmlSaveFormatFileTo(void) { int n_buf; xmlDocPtr cur; /* the document */ int n_cur; - char * encoding; /* the encoding if any assuming the I/O layer handles the transcoding */ + const char * encoding; /* the encoding if any assuming the I/O layer handles the transcoding */ int n_encoding; int format; /* should formatting spaces been added */ int n_format; @@ -22860,13 +23549,13 @@ test_xmlSaveFormatFileTo(void) { encoding = gen_const_char_ptr(n_encoding, 2); format = gen_int(n_format, 3); - ret_val = xmlSaveFormatFileTo(buf, cur, (const char *)encoding, format); + ret_val = xmlSaveFormatFileTo(buf, cur, encoding, format); buf = NULL; desret_int(ret_val); call_tests++; des_xmlOutputBufferPtr(n_buf, buf, 0); des_xmlDocPtr(n_cur, cur, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_int(n_format, format, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -22900,7 +23589,7 @@ test_xmlSearchNs(void) { int n_doc; xmlNodePtr node; /* the current node */ int n_node; - xmlChar * nameSpace; /* the namespace prefix */ + const xmlChar * nameSpace; /* the namespace prefix */ int n_nameSpace; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -22911,12 +23600,12 @@ test_xmlSearchNs(void) { node = gen_xmlNodePtr(n_node, 1); nameSpace = gen_const_xmlChar_ptr(n_nameSpace, 2); - ret_val = xmlSearchNs(doc, node, (const xmlChar *)nameSpace); + ret_val = xmlSearchNs(doc, node, nameSpace); desret_xmlNsPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNodePtr(n_node, node, 1); - des_const_xmlChar_ptr(n_nameSpace, (const xmlChar *)nameSpace, 2); + des_const_xmlChar_ptr(n_nameSpace, nameSpace, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSearchNs", @@ -22946,7 +23635,7 @@ test_xmlSearchNsByHref(void) { int n_doc; xmlNodePtr node; /* the current node */ int n_node; - xmlChar * href; /* the namespace value */ + const xmlChar * href; /* the namespace value */ int n_href; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -22957,12 +23646,12 @@ test_xmlSearchNsByHref(void) { node = gen_xmlNodePtr(n_node, 1); href = gen_const_xmlChar_ptr(n_href, 2); - ret_val = xmlSearchNsByHref(doc, node, (const xmlChar *)href); + ret_val = xmlSearchNsByHref(doc, node, href); desret_xmlNsPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNodePtr(n_node, node, 1); - des_const_xmlChar_ptr(n_href, (const xmlChar *)href, 2); + des_const_xmlChar_ptr(n_href, href, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSearchNsByHref", @@ -23086,7 +23775,7 @@ test_xmlSetNs(void) { int mem_base; xmlNodePtr node; /* a node in the document */ int n_node; - xmlNsPtr ns; /* a namespace pointer */ + xmlNsPtr ns; /* a namespace pointer (optional) */ int n_ns; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -23127,9 +23816,9 @@ test_xmlSetNsProp(void) { int n_node; xmlNsPtr ns; /* the namespace definition */ int n_ns; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * value; /* the attribute value */ + const xmlChar * value; /* the attribute value */ int n_value; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -23142,13 +23831,13 @@ test_xmlSetNsProp(void) { name = gen_const_xmlChar_ptr(n_name, 2); value = gen_const_xmlChar_ptr(n_value, 3); - ret_val = xmlSetNsProp(node, ns, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlSetNsProp(node, ns, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_value, value, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSetNsProp", @@ -23180,9 +23869,9 @@ test_xmlSetProp(void) { xmlAttrPtr ret_val; xmlNodePtr node; /* the node */ int n_node; - xmlChar * name; /* the attribute name (a QName) */ + const xmlChar * name; /* the attribute name (a QName) */ int n_name; - xmlChar * value; /* the attribute value */ + const xmlChar * value; /* the attribute value */ int n_value; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -23193,12 +23882,12 @@ test_xmlSetProp(void) { name = gen_const_xmlChar_ptr(n_name, 1); value = gen_const_xmlChar_ptr(n_value, 2); - ret_val = xmlSetProp(node, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlSetProp(node, name, value); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_value, value, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSetProp", @@ -23225,7 +23914,7 @@ test_xmlSplitQName2(void) { int mem_base; xmlChar * ret_val; - xmlChar * name; /* the full QName */ + const xmlChar * name; /* the full QName */ int n_name; xmlChar ** prefix; /* a xmlChar ** */ int n_prefix; @@ -23236,10 +23925,10 @@ test_xmlSplitQName2(void) { name = gen_const_xmlChar_ptr(n_name, 0); prefix = gen_xmlChar_ptr_ptr(n_prefix, 1); - ret_val = xmlSplitQName2((const xmlChar *)name, prefix); + ret_val = xmlSplitQName2(name, prefix); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); des_xmlChar_ptr_ptr(n_prefix, prefix, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23264,7 +23953,7 @@ test_xmlSplitQName3(void) { int mem_base; const xmlChar * ret_val; - xmlChar * name; /* the full QName */ + const xmlChar * name; /* the full QName */ int n_name; int * len; /* an int * */ int n_len; @@ -23275,10 +23964,10 @@ test_xmlSplitQName3(void) { name = gen_const_xmlChar_ptr(n_name, 0); len = gen_int_ptr(n_len, 1); - ret_val = xmlSplitQName3((const xmlChar *)name, len); + ret_val = xmlSplitQName3(name, len); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); des_int_ptr(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23303,9 +23992,9 @@ test_xmlStringGetNodeList(void) { int mem_base; xmlNodePtr ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* a document (optional) */ int n_doc; - xmlChar * value; /* the value of the attribute */ + const xmlChar * value; /* an attribute value */ int n_value; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -23314,11 +24003,11 @@ test_xmlStringGetNodeList(void) { doc = gen_const_xmlDoc_ptr(n_doc, 0); value = gen_const_xmlChar_ptr(n_value, 1); - ret_val = xmlStringGetNodeList((const xmlDoc *)doc, (const xmlChar *)value); + ret_val = xmlStringGetNodeList(doc, value); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_value, value, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStringGetNodeList", @@ -23342,11 +24031,11 @@ test_xmlStringLenGetNodeList(void) { int mem_base; xmlNodePtr ret_val; - xmlDoc * doc; /* the document */ + const xmlDoc * doc; /* a document (optional) */ int n_doc; - xmlChar * value; /* the value of the text */ + const xmlChar * value; /* an attribute value */ int n_value; - int len; /* the length of the string value */ + int len; /* maximum length of the attribute value */ int n_len; for (n_doc = 0;n_doc < gen_nb_const_xmlDoc_ptr;n_doc++) { @@ -23360,11 +24049,11 @@ test_xmlStringLenGetNodeList(void) { (len > xmlStrlen(BAD_CAST value))) len = 0; - ret_val = xmlStringLenGetNodeList((const xmlDoc *)doc, (const xmlChar *)value, len); + ret_val = xmlStringLenGetNodeList(doc, value, len); desret_xmlNodePtr(ret_val); call_tests++; - des_const_xmlDoc_ptr(n_doc, (const xmlDoc *)doc, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlDoc_ptr(n_doc, doc, 0); + des_const_xmlChar_ptr(n_value, value, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23393,7 +24082,7 @@ test_xmlTextConcat(void) { int ret_val; xmlNodePtr node; /* the node */ int n_node; - xmlChar * content; /* the content */ + const xmlChar * content; /* the content */ int n_content; int len; /* @content length */ int n_len; @@ -23409,11 +24098,11 @@ test_xmlTextConcat(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - ret_val = xmlTextConcat(node, (const xmlChar *)content, len); + ret_val = xmlTextConcat(node, content, len); desret_int(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23452,9 +24141,10 @@ test_xmlTextMerge(void) { second = gen_xmlNodePtr_in(n_second, 1); ret_val = xmlTextMerge(first, second); - if ((first != NULL) && (first->type != XML_TEXT_NODE)) { + if (ret_val == NULL) { xmlUnlinkNode(second); - xmlFreeNode(second) ; second = NULL ; } + xmlFreeNode(second) ; second = NULL ; + ret_val = first; } desret_xmlNodePtr(ret_val); call_tests++; des_xmlNodePtr_in(n_first, first, 0); @@ -23571,7 +24261,7 @@ test_xmlUnsetNsProp(void) { int n_node; xmlNsPtr ns; /* the namespace definition */ int n_ns; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -23582,12 +24272,12 @@ test_xmlUnsetNsProp(void) { ns = gen_xmlNsPtr(n_ns, 1); name = gen_const_xmlChar_ptr(n_name, 2); - ret_val = xmlUnsetNsProp(node, ns, (const xmlChar *)name); + ret_val = xmlUnsetNsProp(node, ns, name); desret_int(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); des_xmlNsPtr(n_ns, ns, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_name, name, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUnsetNsProp", @@ -23617,7 +24307,7 @@ test_xmlUnsetProp(void) { int ret_val; xmlNodePtr node; /* the node */ int n_node; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_node = 0;n_node < gen_nb_xmlNodePtr;n_node++) { @@ -23626,11 +24316,11 @@ test_xmlUnsetProp(void) { node = gen_xmlNodePtr(n_node, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlUnsetProp(node, (const xmlChar *)name); + ret_val = xmlUnsetProp(node, name); desret_int(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUnsetProp", @@ -23656,7 +24346,7 @@ test_xmlValidateNCName(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; int ret_val; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; int space; /* allow spaces in front and end of the string */ int n_space; @@ -23667,10 +24357,10 @@ test_xmlValidateNCName(void) { value = gen_const_xmlChar_ptr(n_value, 0); space = gen_int(n_space, 1); - ret_val = xmlValidateNCName((const xmlChar *)value, space); + ret_val = xmlValidateNCName(value, space); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); des_int(n_space, space, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23698,7 +24388,7 @@ test_xmlValidateNMToken(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; int ret_val; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; int space; /* allow spaces in front and end of the string */ int n_space; @@ -23709,10 +24399,10 @@ test_xmlValidateNMToken(void) { value = gen_const_xmlChar_ptr(n_value, 0); space = gen_int(n_space, 1); - ret_val = xmlValidateNMToken((const xmlChar *)value, space); + ret_val = xmlValidateNMToken(value, space); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); des_int(n_space, space, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23741,7 +24431,7 @@ test_xmlValidateName(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; int ret_val; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; int space; /* allow spaces in front and end of the string */ int n_space; @@ -23752,10 +24442,10 @@ test_xmlValidateName(void) { value = gen_const_xmlChar_ptr(n_value, 0); space = gen_int(n_space, 1); - ret_val = xmlValidateName((const xmlChar *)value, space); + ret_val = xmlValidateName(value, space); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); des_int(n_space, space, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23784,7 +24474,7 @@ test_xmlValidateQName(void) { #ifdef LIBXML_TREE_ENABLED int mem_base; int ret_val; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; int space; /* allow spaces in front and end of the string */ int n_space; @@ -23795,10 +24485,10 @@ test_xmlValidateQName(void) { value = gen_const_xmlChar_ptr(n_value, 0); space = gen_int(n_space, 1); - ret_val = xmlValidateQName((const xmlChar *)value, space); + ret_val = xmlValidateQName(value, space); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); des_int(n_space, space, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -23822,7 +24512,7 @@ static int test_tree(void) { int test_ret = 0; - if (quiet == 0) printf("Testing tree : 144 of 170 functions ...\n"); + if (quiet == 0) printf("Testing tree : 146 of 173 functions ...\n"); test_ret += test_xmlAddChild(); test_ret += test_xmlAddChildList(); test_ret += test_xmlAddNextSibling(); @@ -23891,6 +24581,7 @@ test_tree(void) { test_ret += test_xmlGetNoNsProp(); test_ret += test_xmlGetNodePath(); test_ret += test_xmlGetNsList(); + test_ret += test_xmlGetNsListSafe(); test_ret += test_xmlGetNsProp(); test_ret += test_xmlGetProp(); test_ret += test_xmlHasNsProp(); @@ -23930,7 +24621,9 @@ test_tree(void) { test_ret += test_xmlNodeBufGetContent(); test_ret += test_xmlNodeDump(); test_ret += test_xmlNodeDumpOutput(); + test_ret += test_xmlNodeGetAttrValue(); test_ret += test_xmlNodeGetBase(); + test_ret += test_xmlNodeGetBaseSafe(); test_ret += test_xmlNodeGetContent(); test_ret += test_xmlNodeGetLang(); test_ret += test_xmlNodeGetSpacePreserve(); @@ -23990,9 +24683,9 @@ test_xmlBuildRelativeURI(void) { int mem_base; xmlChar * ret_val; - xmlChar * URI; /* the URI reference under consideration */ + const xmlChar * URI; /* the URI reference under consideration */ int n_URI; - xmlChar * base; /* the base value */ + const xmlChar * base; /* the base value */ int n_base; for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { @@ -24001,11 +24694,11 @@ test_xmlBuildRelativeURI(void) { URI = gen_const_xmlChar_ptr(n_URI, 0); base = gen_const_xmlChar_ptr(n_base, 1); - ret_val = xmlBuildRelativeURI((const xmlChar *)URI, (const xmlChar *)base); + ret_val = xmlBuildRelativeURI(URI, base); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 0); - des_const_xmlChar_ptr(n_base, (const xmlChar *)base, 1); + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_base, base, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBuildRelativeURI", @@ -24023,15 +24716,61 @@ test_xmlBuildRelativeURI(void) { } +static int +test_xmlBuildRelativeURISafe(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + const xmlChar * URI; /* the URI reference under consideration */ + int n_URI; + const xmlChar * base; /* the base value */ + int n_base; + xmlChar ** valPtr; /* pointer to result URI */ + int n_valPtr; + + for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { + for (n_base = 0;n_base < gen_nb_const_xmlChar_ptr;n_base++) { + for (n_valPtr = 0;n_valPtr < gen_nb_xmlChar_ptr_ptr;n_valPtr++) { + mem_base = xmlMemBlocks(); + URI = gen_const_xmlChar_ptr(n_URI, 0); + base = gen_const_xmlChar_ptr(n_base, 1); + valPtr = gen_xmlChar_ptr_ptr(n_valPtr, 2); + + ret_val = xmlBuildRelativeURISafe(URI, base, valPtr); + desret_int(ret_val); + call_tests++; + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_base, base, 1); + des_xmlChar_ptr_ptr(n_valPtr, valPtr, 2); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlBuildRelativeURISafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_URI); + printf(" %d", n_base); + printf(" %d", n_valPtr); + printf("\n"); + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlBuildURI(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlChar * URI; /* the URI instance found in the document */ + const xmlChar * URI; /* the URI instance found in the document */ int n_URI; - xmlChar * base; /* the base value */ + const xmlChar * base; /* the base value */ int n_base; for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { @@ -24040,11 +24779,11 @@ test_xmlBuildURI(void) { URI = gen_const_xmlChar_ptr(n_URI, 0); base = gen_const_xmlChar_ptr(n_base, 1); - ret_val = xmlBuildURI((const xmlChar *)URI, (const xmlChar *)base); + ret_val = xmlBuildURI(URI, base); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_URI, (const xmlChar *)URI, 0); - des_const_xmlChar_ptr(n_base, (const xmlChar *)base, 1); + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_base, base, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlBuildURI", @@ -24062,23 +24801,69 @@ test_xmlBuildURI(void) { } +static int +test_xmlBuildURISafe(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + const xmlChar * URI; /* the URI instance found in the document */ + int n_URI; + const xmlChar * base; /* the base value */ + int n_base; + xmlChar ** valPtr; /* pointer to result URI */ + int n_valPtr; + + for (n_URI = 0;n_URI < gen_nb_const_xmlChar_ptr;n_URI++) { + for (n_base = 0;n_base < gen_nb_const_xmlChar_ptr;n_base++) { + for (n_valPtr = 0;n_valPtr < gen_nb_xmlChar_ptr_ptr;n_valPtr++) { + mem_base = xmlMemBlocks(); + URI = gen_const_xmlChar_ptr(n_URI, 0); + base = gen_const_xmlChar_ptr(n_base, 1); + valPtr = gen_xmlChar_ptr_ptr(n_valPtr, 2); + + ret_val = xmlBuildURISafe(URI, base, valPtr); + desret_int(ret_val); + call_tests++; + des_const_xmlChar_ptr(n_URI, URI, 0); + des_const_xmlChar_ptr(n_base, base, 1); + des_xmlChar_ptr_ptr(n_valPtr, valPtr, 2); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlBuildURISafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_URI); + printf(" %d", n_base); + printf(" %d", n_valPtr); + printf("\n"); + } + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCanonicPath(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlChar * path; /* the resource locator in a filesystem notation */ + const xmlChar * path; /* the resource locator in a filesystem notation */ int n_path; for (n_path = 0;n_path < gen_nb_const_xmlChar_ptr;n_path++) { mem_base = xmlMemBlocks(); path = gen_const_xmlChar_ptr(n_path, 0); - ret_val = xmlCanonicPath((const xmlChar *)path); + ret_val = xmlCanonicPath(path); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_path, (const xmlChar *)path, 0); + des_const_xmlChar_ptr(n_path, path, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCanonicPath", @@ -24168,7 +24953,7 @@ test_xmlParseURIReference(void) { int ret_val; xmlURIPtr uri; /* pointer to an URI structure */ int n_uri; - char * str; /* the string to analyze */ + const char * str; /* the string to analyze */ int n_str; for (n_uri = 0;n_uri < gen_nb_xmlURIPtr;n_uri++) { @@ -24177,11 +24962,11 @@ test_xmlParseURIReference(void) { uri = gen_xmlURIPtr(n_uri, 0); str = gen_const_char_ptr(n_str, 1); - ret_val = xmlParseURIReference(uri, (const char *)str); + ret_val = xmlParseURIReference(uri, str); desret_int(ret_val); call_tests++; des_xmlURIPtr(n_uri, uri, 0); - des_const_char_ptr(n_str, (const char *)str, 1); + des_const_char_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParseURIReference", @@ -24199,23 +24984,66 @@ test_xmlParseURIReference(void) { } +#define gen_nb_xmlURIPtr_ptr 1 +#define gen_xmlURIPtr_ptr(no, nr) NULL +#define des_xmlURIPtr_ptr(no, val, nr) + +static int +test_xmlParseURISafe(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + const char * str; /* the URI string to analyze */ + int n_str; + xmlURIPtr * uriOut; /* optional pointer to parsed URI */ + int n_uriOut; + + for (n_str = 0;n_str < gen_nb_filepath;n_str++) { + for (n_uriOut = 0;n_uriOut < gen_nb_xmlURIPtr_ptr;n_uriOut++) { + mem_base = xmlMemBlocks(); + str = gen_filepath(n_str, 0); + uriOut = gen_xmlURIPtr_ptr(n_uriOut, 1); + + ret_val = xmlParseURISafe(str, uriOut); + desret_int(ret_val); + call_tests++; + des_filepath(n_str, str, 0); + des_xmlURIPtr_ptr(n_uriOut, uriOut, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlParseURISafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_str); + printf(" %d", n_uriOut); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlPathToURI(void) { int test_ret = 0; int mem_base; xmlChar * ret_val; - xmlChar * path; /* the resource locator in a filesystem notation */ + const xmlChar * path; /* the resource locator in a filesystem notation */ int n_path; for (n_path = 0;n_path < gen_nb_const_xmlChar_ptr;n_path++) { mem_base = xmlMemBlocks(); path = gen_const_xmlChar_ptr(n_path, 0); - ret_val = xmlPathToURI((const xmlChar *)path); + ret_val = xmlPathToURI(path); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_path, (const xmlChar *)path, 0); + des_const_xmlChar_ptr(n_path, path, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlPathToURI", @@ -24306,17 +25134,17 @@ test_xmlURIEscape(void) { int mem_base; xmlChar * ret_val; - xmlChar * str; /* the string of the URI to escape */ + const xmlChar * str; /* the string of the URI to escape */ int n_str; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { mem_base = xmlMemBlocks(); str = gen_const_xmlChar_ptr(n_str, 0); - ret_val = xmlURIEscape((const xmlChar *)str); + ret_val = xmlURIEscape(str); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlURIEscape", @@ -24338,9 +25166,9 @@ test_xmlURIEscapeStr(void) { int mem_base; xmlChar * ret_val; - xmlChar * str; /* string to escape */ + const xmlChar * str; /* string to escape */ int n_str; - xmlChar * list; /* exception list string of chars not to escape */ + const xmlChar * list; /* exception list string of chars not to escape */ int n_list; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { @@ -24349,11 +25177,11 @@ test_xmlURIEscapeStr(void) { str = gen_const_xmlChar_ptr(n_str, 0); list = gen_const_xmlChar_ptr(n_list, 1); - ret_val = xmlURIEscapeStr((const xmlChar *)str, (const xmlChar *)list); + ret_val = xmlURIEscapeStr(str, list); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); - des_const_xmlChar_ptr(n_list, (const xmlChar *)list, 1); + des_const_xmlChar_ptr(n_str, str, 0); + des_const_xmlChar_ptr(n_list, list, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlURIEscapeStr", @@ -24384,15 +25212,18 @@ static int test_uri(void) { int test_ret = 0; - if (quiet == 0) printf("Testing uri : 10 of 15 functions ...\n"); + if (quiet == 0) printf("Testing uri : 13 of 18 functions ...\n"); test_ret += test_xmlBuildRelativeURI(); + test_ret += test_xmlBuildRelativeURISafe(); test_ret += test_xmlBuildURI(); + test_ret += test_xmlBuildURISafe(); test_ret += test_xmlCanonicPath(); test_ret += test_xmlCreateURI(); test_ret += test_xmlNormalizeURIPath(); test_ret += test_xmlParseURI(); test_ret += test_xmlParseURIRaw(); test_ret += test_xmlParseURIReference(); + test_ret += test_xmlParseURISafe(); test_ret += test_xmlPathToURI(); test_ret += test_xmlPrintURI(); test_ret += test_xmlSaveUri(); @@ -24415,17 +25246,17 @@ test_xmlAddAttributeDecl(void) { int n_ctxt; xmlDtdPtr dtd; /* pointer to the DTD */ int n_dtd; - xmlChar * elem; /* the element name */ + const xmlChar * elem; /* the element name */ int n_elem; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * ns; /* the attribute namespace prefix */ + const xmlChar * ns; /* the attribute namespace prefix */ int n_ns; xmlAttributeType type; /* the attribute type */ int n_type; xmlAttributeDefault def; /* the attribute default type */ int n_def; - xmlChar * defaultValue; /* the attribute default value */ + const xmlChar * defaultValue; /* the attribute default value */ int n_defaultValue; xmlEnumerationPtr tree; /* if it's an enumeration, the associated list */ int n_tree; @@ -24450,17 +25281,17 @@ test_xmlAddAttributeDecl(void) { defaultValue = gen_const_xmlChar_ptr(n_defaultValue, 7); tree = gen_xmlEnumerationPtr(n_tree, 8); - ret_val = xmlAddAttributeDecl(ctxt, dtd, (const xmlChar *)elem, (const xmlChar *)name, (const xmlChar *)ns, type, def, (const xmlChar *)defaultValue, tree); + ret_val = xmlAddAttributeDecl(ctxt, dtd, elem, name, ns, type, def, defaultValue, tree); desret_xmlAttributePtr(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDtdPtr(n_dtd, dtd, 1); - des_const_xmlChar_ptr(n_elem, (const xmlChar *)elem, 2); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 3); - des_const_xmlChar_ptr(n_ns, (const xmlChar *)ns, 4); + des_const_xmlChar_ptr(n_elem, elem, 2); + des_const_xmlChar_ptr(n_name, name, 3); + des_const_xmlChar_ptr(n_ns, ns, 4); des_xmlAttributeType(n_type, type, 5); des_xmlAttributeDefault(n_def, def, 6); - des_const_xmlChar_ptr(n_defaultValue, (const xmlChar *)defaultValue, 7); + des_const_xmlChar_ptr(n_defaultValue, defaultValue, 7); des_xmlEnumerationPtr(n_tree, tree, 8); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -24503,7 +25334,7 @@ test_xmlAddElementDecl(void) { int n_ctxt; xmlDtdPtr dtd; /* pointer to the DTD */ int n_dtd; - xmlChar * name; /* the entity name */ + const xmlChar * name; /* the entity name */ int n_name; xmlElementTypeVal type; /* the element type */ int n_type; @@ -24522,12 +25353,12 @@ test_xmlAddElementDecl(void) { type = gen_xmlElementTypeVal(n_type, 3); content = gen_xmlElementContentPtr(n_content, 4); - ret_val = xmlAddElementDecl(ctxt, dtd, (const xmlChar *)name, type, content); + ret_val = xmlAddElementDecl(ctxt, dtd, name, type, content); desret_xmlElementPtr(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDtdPtr(n_dtd, dtd, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_name, name, 2); des_xmlElementTypeVal(n_type, type, 3); des_xmlElementContentPtr(n_content, content, 4); xmlResetLastError(); @@ -24563,6 +25394,45 @@ test_xmlAddID(void) { } +static int +test_xmlAddIDSafe(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlAttrPtr attr; /* the attribute holding the ID */ + int n_attr; + const xmlChar * value; /* the attribute (ID) value */ + int n_value; + + for (n_attr = 0;n_attr < gen_nb_xmlAttrPtr;n_attr++) { + for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { + mem_base = xmlMemBlocks(); + attr = gen_xmlAttrPtr(n_attr, 0); + value = gen_const_xmlChar_ptr(n_value, 1); + + ret_val = xmlAddIDSafe(attr, value); + desret_int(ret_val); + call_tests++; + des_xmlAttrPtr(n_attr, attr, 0); + des_const_xmlChar_ptr(n_value, value, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlAddIDSafe", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_attr); + printf(" %d", n_value); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlAddNotationDecl(void) { int test_ret = 0; @@ -24970,9 +25840,9 @@ test_xmlGetDtdAttrDesc(void) { xmlAttributePtr ret_val; xmlDtdPtr dtd; /* a pointer to the DtD to search */ int n_dtd; - xmlChar * elem; /* the element name */ + const xmlChar * elem; /* the element name */ int n_elem; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; for (n_dtd = 0;n_dtd < gen_nb_xmlDtdPtr;n_dtd++) { @@ -24983,12 +25853,12 @@ test_xmlGetDtdAttrDesc(void) { elem = gen_const_xmlChar_ptr(n_elem, 1); name = gen_const_xmlChar_ptr(n_name, 2); - ret_val = xmlGetDtdAttrDesc(dtd, (const xmlChar *)elem, (const xmlChar *)name); + ret_val = xmlGetDtdAttrDesc(dtd, elem, name); desret_xmlAttributePtr(ret_val); call_tests++; des_xmlDtdPtr(n_dtd, dtd, 0); - des_const_xmlChar_ptr(n_elem, (const xmlChar *)elem, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_elem, elem, 1); + des_const_xmlChar_ptr(n_name, name, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDtdAttrDesc", @@ -25016,7 +25886,7 @@ test_xmlGetDtdElementDesc(void) { xmlElementPtr ret_val; xmlDtdPtr dtd; /* a pointer to the DtD to search */ int n_dtd; - xmlChar * name; /* the element name */ + const xmlChar * name; /* the element name */ int n_name; for (n_dtd = 0;n_dtd < gen_nb_xmlDtdPtr;n_dtd++) { @@ -25025,11 +25895,11 @@ test_xmlGetDtdElementDesc(void) { dtd = gen_xmlDtdPtr(n_dtd, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlGetDtdElementDesc(dtd, (const xmlChar *)name); + ret_val = xmlGetDtdElementDesc(dtd, name); desret_xmlElementPtr(ret_val); call_tests++; des_xmlDtdPtr(n_dtd, dtd, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDtdElementDesc", @@ -25065,11 +25935,11 @@ test_xmlGetDtdQAttrDesc(void) { xmlAttributePtr ret_val; xmlDtdPtr dtd; /* a pointer to the DtD to search */ int n_dtd; - xmlChar * elem; /* the element name */ + const xmlChar * elem; /* the element name */ int n_elem; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * prefix; /* the attribute namespace prefix */ + const xmlChar * prefix; /* the attribute namespace prefix */ int n_prefix; for (n_dtd = 0;n_dtd < gen_nb_xmlDtdPtr;n_dtd++) { @@ -25082,13 +25952,13 @@ test_xmlGetDtdQAttrDesc(void) { name = gen_const_xmlChar_ptr(n_name, 2); prefix = gen_const_xmlChar_ptr(n_prefix, 3); - ret_val = xmlGetDtdQAttrDesc(dtd, (const xmlChar *)elem, (const xmlChar *)name, (const xmlChar *)prefix); + ret_val = xmlGetDtdQAttrDesc(dtd, elem, name, prefix); desret_xmlAttributePtr(ret_val); call_tests++; des_xmlDtdPtr(n_dtd, dtd, 0); - des_const_xmlChar_ptr(n_elem, (const xmlChar *)elem, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 3); + des_const_xmlChar_ptr(n_elem, elem, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_prefix, prefix, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDtdQAttrDesc", @@ -25118,9 +25988,9 @@ test_xmlGetDtdQElementDesc(void) { xmlElementPtr ret_val; xmlDtdPtr dtd; /* a pointer to the DtD to search */ int n_dtd; - xmlChar * name; /* the element name */ + const xmlChar * name; /* the element name */ int n_name; - xmlChar * prefix; /* the element namespace prefix */ + const xmlChar * prefix; /* the element namespace prefix */ int n_prefix; for (n_dtd = 0;n_dtd < gen_nb_xmlDtdPtr;n_dtd++) { @@ -25131,12 +26001,12 @@ test_xmlGetDtdQElementDesc(void) { name = gen_const_xmlChar_ptr(n_name, 1); prefix = gen_const_xmlChar_ptr(n_prefix, 2); - ret_val = xmlGetDtdQElementDesc(dtd, (const xmlChar *)name, (const xmlChar *)prefix); + ret_val = xmlGetDtdQElementDesc(dtd, name, prefix); desret_xmlElementPtr(ret_val); call_tests++; des_xmlDtdPtr(n_dtd, dtd, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetDtdQElementDesc", @@ -25164,7 +26034,7 @@ test_xmlGetID(void) { xmlAttrPtr ret_val; xmlDocPtr doc; /* pointer to the document */ int n_doc; - xmlChar * ID; /* the ID value */ + const xmlChar * ID; /* the ID value */ int n_ID; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -25173,11 +26043,11 @@ test_xmlGetID(void) { doc = gen_xmlDocPtr(n_doc, 0); ID = gen_const_xmlChar_ptr(n_ID, 1); - ret_val = xmlGetID(doc, (const xmlChar *)ID); + ret_val = xmlGetID(doc, ID); desret_xmlAttrPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_ID, (const xmlChar *)ID, 1); + des_const_xmlChar_ptr(n_ID, ID, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlGetID", @@ -25259,7 +26129,7 @@ test_xmlIsMixedElement(void) { int ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * name; /* the element name */ + const xmlChar * name; /* the element name */ int n_name; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -25268,11 +26138,11 @@ test_xmlIsMixedElement(void) { doc = gen_xmlDocPtr(n_doc, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlIsMixedElement(doc, (const xmlChar *)name); + ret_val = xmlIsMixedElement(doc, name); desret_int(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlIsMixedElement", @@ -25344,7 +26214,7 @@ test_xmlNewDocElementContent(void) { xmlElementContentPtr ret_val; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * name; /* the subelement name or NULL */ + const xmlChar * name; /* the subelement name or NULL */ int n_name; xmlElementContentType type; /* the type of element content decl */ int n_type; @@ -25357,12 +26227,12 @@ test_xmlNewDocElementContent(void) { name = gen_const_xmlChar_ptr(n_name, 1); type = gen_xmlElementContentType(n_type, 2); - ret_val = xmlNewDocElementContent(doc, (const xmlChar *)name, type); + ret_val = xmlNewDocElementContent(doc, name, type); xmlFreeDocElementContent(doc, ret_val); ret_val = NULL; desret_xmlElementContentPtr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_xmlElementContentType(n_type, type, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -25389,7 +26259,7 @@ test_xmlNewElementContent(void) { int mem_base; xmlElementContentPtr ret_val; - xmlChar * name; /* the subelement name or NULL */ + const xmlChar * name; /* the subelement name or NULL */ int n_name; xmlElementContentType type; /* the type of element content decl */ int n_type; @@ -25400,10 +26270,10 @@ test_xmlNewElementContent(void) { name = gen_const_xmlChar_ptr(n_name, 0); type = gen_xmlElementContentType(n_type, 1); - ret_val = xmlNewElementContent((const xmlChar *)name, type); + ret_val = xmlNewElementContent(name, type); desret_xmlElementContentPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); des_xmlElementContentType(n_type, type, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -25663,9 +26533,9 @@ test_xmlValidCtxtNormalizeAttributeValue(void) { int n_doc; xmlNodePtr elem; /* the parent */ int n_elem; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * value; /* the attribute value */ + const xmlChar * value; /* the attribute value */ int n_value; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -25680,14 +26550,14 @@ test_xmlValidCtxtNormalizeAttributeValue(void) { name = gen_const_xmlChar_ptr(n_name, 3); value = gen_const_xmlChar_ptr(n_value, 4); - ret_val = xmlValidCtxtNormalizeAttributeValue(ctxt, doc, elem, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlValidCtxtNormalizeAttributeValue(ctxt, doc, elem, name, value); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_elem, elem, 2); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 3); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 4); + des_const_xmlChar_ptr(n_name, name, 3); + des_const_xmlChar_ptr(n_value, value, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidCtxtNormalizeAttributeValue", @@ -25726,7 +26596,7 @@ test_xmlValidGetPotentialChildren(void) { int ret_val; xmlElementContent * ctree; /* an element content tree */ int n_ctree; - xmlChar ** names; /* an array to store the list of child names */ + const xmlChar ** names; /* an array to store the list of child names */ int n_names; int * len; /* a pointer to the number of element in the list */ int n_len; @@ -25743,11 +26613,11 @@ test_xmlValidGetPotentialChildren(void) { len = gen_int_ptr(n_len, 2); max = gen_int(n_max, 3); - ret_val = xmlValidGetPotentialChildren(ctree, (const xmlChar **)names, len, max); + ret_val = xmlValidGetPotentialChildren(ctree, names, len, max); desret_int(ret_val); call_tests++; des_xmlElementContent_ptr(n_ctree, ctree, 0); - des_const_xmlChar_ptr_ptr(n_names, (const xmlChar **)names, 1); + des_const_xmlChar_ptr_ptr(n_names, names, 1); des_int_ptr(n_len, len, 2); des_int(n_max, max, 3); xmlResetLastError(); @@ -25785,7 +26655,7 @@ test_xmlValidGetValidElements(void) { int n_prev; xmlNode * next; /* an element to insert next */ int n_next; - xmlChar ** names; /* an array to store the list of child names */ + const xmlChar ** names; /* an array to store the list of child names */ int n_names; int max; /* the size of the array */ int n_max; @@ -25800,12 +26670,12 @@ test_xmlValidGetValidElements(void) { names = gen_const_xmlChar_ptr_ptr(n_names, 2); max = gen_int(n_max, 3); - ret_val = xmlValidGetValidElements(prev, next, (const xmlChar **)names, max); + ret_val = xmlValidGetValidElements(prev, next, names, max); desret_int(ret_val); call_tests++; des_xmlNodePtr(n_prev, prev, 0); des_xmlNodePtr(n_next, next, 1); - des_const_xmlChar_ptr_ptr(n_names, (const xmlChar **)names, 2); + des_const_xmlChar_ptr_ptr(n_names, names, 2); des_int(n_max, max, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -25841,9 +26711,9 @@ test_xmlValidNormalizeAttributeValue(void) { int n_doc; xmlNodePtr elem; /* the parent */ int n_elem; - xmlChar * name; /* the attribute name */ + const xmlChar * name; /* the attribute name */ int n_name; - xmlChar * value; /* the attribute value */ + const xmlChar * value; /* the attribute value */ int n_value; for (n_doc = 0;n_doc < gen_nb_xmlDocPtr;n_doc++) { @@ -25856,13 +26726,13 @@ test_xmlValidNormalizeAttributeValue(void) { name = gen_const_xmlChar_ptr(n_name, 2); value = gen_const_xmlChar_ptr(n_value, 3); - ret_val = xmlValidNormalizeAttributeValue(doc, elem, (const xmlChar *)name, (const xmlChar *)value); + ret_val = xmlValidNormalizeAttributeValue(doc, elem, name, value); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlDocPtr(n_doc, doc, 0); des_xmlNodePtr(n_elem, elem, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_value, value, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidNormalizeAttributeValue", @@ -25942,7 +26812,7 @@ test_xmlValidateAttributeValue(void) { int ret_val; xmlAttributeType type; /* an attribute type */ int n_type; - xmlChar * value; /* an attribute value */ + const xmlChar * value; /* an attribute value */ int n_value; for (n_type = 0;n_type < gen_nb_xmlAttributeType;n_type++) { @@ -25951,11 +26821,11 @@ test_xmlValidateAttributeValue(void) { type = gen_xmlAttributeType(n_type, 0); value = gen_const_xmlChar_ptr(n_value, 1); - ret_val = xmlValidateAttributeValue(type, (const xmlChar *)value); + ret_val = xmlValidateAttributeValue(type, value); desret_int(ret_val); call_tests++; des_xmlAttributeType(n_type, type, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateAttributeValue", @@ -26248,17 +27118,17 @@ test_xmlValidateNameValue(void) { #if defined(LIBXML_VALID_ENABLED) int mem_base; int ret_val; - xmlChar * value; /* an Name value */ + const xmlChar * value; /* an Name value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlValidateNameValue((const xmlChar *)value); + ret_val = xmlValidateNameValue(value); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateNameValue", @@ -26282,17 +27152,17 @@ test_xmlValidateNamesValue(void) { #if defined(LIBXML_VALID_ENABLED) int mem_base; int ret_val; - xmlChar * value; /* an Names value */ + const xmlChar * value; /* an Names value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlValidateNamesValue((const xmlChar *)value); + ret_val = xmlValidateNamesValue(value); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateNamesValue", @@ -26316,17 +27186,17 @@ test_xmlValidateNmtokenValue(void) { #if defined(LIBXML_VALID_ENABLED) int mem_base; int ret_val; - xmlChar * value; /* an Nmtoken value */ + const xmlChar * value; /* an Nmtoken value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlValidateNmtokenValue((const xmlChar *)value); + ret_val = xmlValidateNmtokenValue(value); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateNmtokenValue", @@ -26350,17 +27220,17 @@ test_xmlValidateNmtokensValue(void) { #if defined(LIBXML_VALID_ENABLED) int mem_base; int ret_val; - xmlChar * value; /* an Nmtokens value */ + const xmlChar * value; /* an Nmtokens value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlValidateNmtokensValue((const xmlChar *)value); + ret_val = xmlValidateNmtokensValue(value); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateNmtokensValue", @@ -26436,7 +27306,7 @@ test_xmlValidateNotationUse(void) { int n_ctxt; xmlDocPtr doc; /* the document */ int n_doc; - xmlChar * notationName; /* the notation name to check */ + const xmlChar * notationName; /* the notation name to check */ int n_notationName; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -26447,12 +27317,12 @@ test_xmlValidateNotationUse(void) { doc = gen_xmlDocPtr(n_doc, 1); notationName = gen_const_xmlChar_ptr(n_notationName, 2); - ret_val = xmlValidateNotationUse(ctxt, doc, (const xmlChar *)notationName); + ret_val = xmlValidateNotationUse(ctxt, doc, notationName); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); - des_const_xmlChar_ptr(n_notationName, (const xmlChar *)notationName, 2); + des_const_xmlChar_ptr(n_notationName, notationName, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateNotationUse", @@ -26488,7 +27358,7 @@ test_xmlValidateOneAttribute(void) { int n_elem; xmlAttrPtr attr; /* an attribute instance */ int n_attr; - xmlChar * value; /* the attribute value (without entities processing) */ + const xmlChar * value; /* the attribute value (without entities processing) */ int n_value; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -26503,14 +27373,14 @@ test_xmlValidateOneAttribute(void) { attr = gen_xmlAttrPtr(n_attr, 3); value = gen_const_xmlChar_ptr(n_value, 4); - ret_val = xmlValidateOneAttribute(ctxt, doc, elem, attr, (const xmlChar *)value); + ret_val = xmlValidateOneAttribute(ctxt, doc, elem, attr, value); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_elem, elem, 2); des_xmlAttrPtr(n_attr, attr, 3); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 4); + des_const_xmlChar_ptr(n_value, value, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateOneAttribute", @@ -26596,11 +27466,11 @@ test_xmlValidateOneNamespace(void) { int n_doc; xmlNodePtr elem; /* an element instance */ int n_elem; - xmlChar * prefix; /* the namespace prefix */ + const xmlChar * prefix; /* the namespace prefix */ int n_prefix; xmlNsPtr ns; /* an namespace declaration instance */ int n_ns; - xmlChar * value; /* the attribute value (without entities processing) */ + const xmlChar * value; /* the attribute value (without entities processing) */ int n_value; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -26617,15 +27487,15 @@ test_xmlValidateOneNamespace(void) { ns = gen_xmlNsPtr(n_ns, 4); value = gen_const_xmlChar_ptr(n_value, 5); - ret_val = xmlValidateOneNamespace(ctxt, doc, elem, (const xmlChar *)prefix, ns, (const xmlChar *)value); + ret_val = xmlValidateOneNamespace(ctxt, doc, elem, prefix, ns, value); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_elem, elem, 2); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 3); + des_const_xmlChar_ptr(n_prefix, prefix, 3); des_xmlNsPtr(n_ns, ns, 4); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 5); + des_const_xmlChar_ptr(n_value, value, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidateOneNamespace", @@ -26665,7 +27535,7 @@ test_xmlValidatePopElement(void) { int n_doc; xmlNodePtr elem; /* an element instance */ int n_elem; - xmlChar * qname; /* the qualified name as appearing in the serialization */ + const xmlChar * qname; /* the qualified name as appearing in the serialization */ int n_qname; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -26678,13 +27548,13 @@ test_xmlValidatePopElement(void) { elem = gen_xmlNodePtr(n_elem, 2); qname = gen_const_xmlChar_ptr(n_qname, 3); - ret_val = xmlValidatePopElement(ctxt, doc, elem, (const xmlChar *)qname); + ret_val = xmlValidatePopElement(ctxt, doc, elem, qname); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_elem, elem, 2); - des_const_xmlChar_ptr(n_qname, (const xmlChar *)qname, 3); + des_const_xmlChar_ptr(n_qname, qname, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidatePopElement", @@ -26716,7 +27586,7 @@ test_xmlValidatePushCData(void) { int ret_val; xmlValidCtxtPtr ctxt; /* the validation context */ int n_ctxt; - xmlChar * data; /* some character data read */ + const xmlChar * data; /* some character data read */ int n_data; int len; /* the length of the data */ int n_len; @@ -26732,11 +27602,11 @@ test_xmlValidatePushCData(void) { (len > xmlStrlen(BAD_CAST data))) len = 0; - ret_val = xmlValidatePushCData(ctxt, (const xmlChar *)data, len); + ret_val = xmlValidatePushCData(ctxt, data, len); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_data, (const xmlChar *)data, 1); + des_const_xmlChar_ptr(n_data, data, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -26771,7 +27641,7 @@ test_xmlValidatePushElement(void) { int n_doc; xmlNodePtr elem; /* an element instance */ int n_elem; - xmlChar * qname; /* the qualified name as appearing in the serialization */ + const xmlChar * qname; /* the qualified name as appearing in the serialization */ int n_qname; for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) { @@ -26784,13 +27654,13 @@ test_xmlValidatePushElement(void) { elem = gen_xmlNodePtr(n_elem, 2); qname = gen_const_xmlChar_ptr(n_qname, 3); - ret_val = xmlValidatePushElement(ctxt, doc, elem, (const xmlChar *)qname); + ret_val = xmlValidatePushElement(ctxt, doc, elem, qname); desret_int(ret_val); call_tests++; des_xmlValidCtxtPtr(n_ctxt, ctxt, 0); des_xmlDocPtr(n_doc, doc, 1); des_xmlNodePtr(n_elem, elem, 2); - des_const_xmlChar_ptr(n_qname, (const xmlChar *)qname, 3); + des_const_xmlChar_ptr(n_qname, qname, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlValidatePushElement", @@ -26857,10 +27727,11 @@ static int test_valid(void) { int test_ret = 0; - if (quiet == 0) printf("Testing valid : 50 of 70 functions ...\n"); + if (quiet == 0) printf("Testing valid : 51 of 71 functions ...\n"); test_ret += test_xmlAddAttributeDecl(); test_ret += test_xmlAddElementDecl(); test_ret += test_xmlAddID(); + test_ret += test_xmlAddIDSafe(); test_ret += test_xmlAddNotationDecl(); test_ret += test_xmlAddRef(); test_ret += test_xmlCopyAttributeTable(); @@ -26924,6 +27795,47 @@ test_valid(void) { printf("Module valid: %d errors\n", test_ret); return(test_ret); } +#ifdef LIBXML_XINCLUDE_ENABLED + +#define gen_nb_xmlXIncludeCtxtPtr 1 +#define gen_xmlXIncludeCtxtPtr(no, nr) NULL +#define des_xmlXIncludeCtxtPtr(no, val, nr) +#endif + + +static int +test_xmlXIncludeGetLastError(void) { + int test_ret = 0; + +#if defined(LIBXML_XINCLUDE_ENABLED) + int mem_base; + int ret_val; + xmlXIncludeCtxtPtr ctxt; /* an XInclude processing context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlXIncludeCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlXIncludeCtxtPtr(n_ctxt, 0); + + ret_val = xmlXIncludeGetLastError(ctxt); + desret_int(ret_val); + call_tests++; + des_xmlXIncludeCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlXIncludeGetLastError", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; +#endif + + return(test_ret); +} + static int test_xmlXIncludeNewContext(void) { @@ -27057,13 +27969,6 @@ test_xmlXIncludeProcessFlagsData(void) { return(test_ret); } -#ifdef LIBXML_XINCLUDE_ENABLED - -#define gen_nb_xmlXIncludeCtxtPtr 1 -#define gen_xmlXIncludeCtxtPtr(no, nr) NULL -#define des_xmlXIncludeCtxtPtr(no, val, nr) -#endif - static int test_xmlXIncludeProcessNode(void) { @@ -27229,6 +28134,16 @@ test_xmlXIncludeProcessTreeFlagsData(void) { } +static int +test_xmlXIncludeSetErrorHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlXIncludeSetFlags(void) { int test_ret = 0; @@ -27273,7 +28188,8 @@ static int test_xinclude(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xinclude : 8 of 10 functions ...\n"); + if (quiet == 0) printf("Testing xinclude : 9 of 12 functions ...\n"); + test_ret += test_xmlXIncludeGetLastError(); test_ret += test_xmlXIncludeNewContext(); test_ret += test_xmlXIncludeProcess(); test_ret += test_xmlXIncludeProcessFlags(); @@ -27282,6 +28198,7 @@ test_xinclude(void) { test_ret += test_xmlXIncludeProcessTree(); test_ret += test_xmlXIncludeProcessTreeFlags(); test_ret += test_xmlXIncludeProcessTreeFlagsData(); + test_ret += test_xmlXIncludeSetErrorHandler(); test_ret += test_xmlXIncludeSetFlags(); if (test_ret != 0) @@ -27329,7 +28246,7 @@ test_xmlAllocParserInputBuffer(void) { int mem_base; xmlParserInputBufferPtr ret_val; - xmlCharEncoding enc; /* the charset encoding if known */ + xmlCharEncoding enc; /* the charset encoding if known (deprecated) */ int n_enc; for (n_enc = 0;n_enc < gen_nb_xmlCharEncoding;n_enc++) { @@ -27361,17 +28278,17 @@ test_xmlCheckFilename(void) { int mem_base; int ret_val; - char * path; /* the path to check */ + const char * path; /* the path to check */ int n_path; for (n_path = 0;n_path < gen_nb_const_char_ptr;n_path++) { mem_base = xmlMemBlocks(); path = gen_const_char_ptr(n_path, 0); - ret_val = xmlCheckFilename((const char *)path); + ret_val = xmlCheckFilename(path); desret_int(ret_val); call_tests++; - des_const_char_ptr(n_path, (const char *)path, 0); + des_const_char_ptr(n_path, path, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCheckFilename", @@ -27924,7 +28841,7 @@ test_xmlNoNetExternalEntityLoader(void) { xmlParserInputPtr ret_val; const char * URL; /* the URL for the entity to load */ int n_URL; - char * ID; /* the System ID for the entity to load */ + const char * ID; /* the System ID for the entity to load */ int n_ID; xmlParserCtxtPtr ctxt; /* the context in which the entity is called or NULL */ int n_ctxt; @@ -27937,11 +28854,11 @@ test_xmlNoNetExternalEntityLoader(void) { ID = gen_const_char_ptr(n_ID, 1); ctxt = gen_xmlParserCtxtPtr(n_ctxt, 2); - ret_val = xmlNoNetExternalEntityLoader(URL, (const char *)ID, ctxt); + ret_val = xmlNoNetExternalEntityLoader(URL, ID, ctxt); desret_xmlParserInputPtr(ret_val); call_tests++; des_filepath(n_URL, URL, 0); - des_const_char_ptr(n_ID, (const char *)ID, 1); + des_const_char_ptr(n_ID, ID, 1); des_xmlParserCtxtPtr(n_ctxt, ctxt, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -27968,17 +28885,17 @@ test_xmlNormalizeWindowsPath(void) { int mem_base; xmlChar * ret_val; - xmlChar * path; /* the input file path */ + const xmlChar * path; /* the input file path */ int n_path; for (n_path = 0;n_path < gen_nb_const_xmlChar_ptr;n_path++) { mem_base = xmlMemBlocks(); path = gen_const_xmlChar_ptr(n_path, 0); - ret_val = xmlNormalizeWindowsPath((const xmlChar *)path); + ret_val = xmlNormalizeWindowsPath(path); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_path, (const xmlChar *)path, 0); + des_const_xmlChar_ptr(n_path, path, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlNormalizeWindowsPath", @@ -28264,7 +29181,7 @@ test_xmlOutputBufferWrite(void) { int n_out; int len; /* the size in bytes of the array. */ int n_len; - char * buf; /* an char array */ + const char * buf; /* an char array */ int n_buf; for (n_out = 0;n_out < gen_nb_xmlOutputBufferPtr;n_out++) { @@ -28278,12 +29195,12 @@ test_xmlOutputBufferWrite(void) { (len > xmlStrlen(BAD_CAST buf))) len = 0; - ret_val = xmlOutputBufferWrite(out, len, (const char *)buf); + ret_val = xmlOutputBufferWrite(out, len, buf); desret_int(ret_val); call_tests++; des_xmlOutputBufferPtr(n_out, out, 0); des_int(n_len, len, 1); - des_const_char_ptr(n_buf, (const char *)buf, 2); + des_const_char_ptr(n_buf, buf, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlOutputBufferWrite", @@ -28323,7 +29240,7 @@ test_xmlOutputBufferWriteString(void) { int ret_val; xmlOutputBufferPtr out; /* a buffered parser output */ int n_out; - char * str; /* a zero terminated C string */ + const char * str; /* a zero terminated C string */ int n_str; for (n_out = 0;n_out < gen_nb_xmlOutputBufferPtr;n_out++) { @@ -28332,11 +29249,11 @@ test_xmlOutputBufferWriteString(void) { out = gen_xmlOutputBufferPtr(n_out, 0); str = gen_const_char_ptr(n_str, 1); - ret_val = xmlOutputBufferWriteString(out, (const char *)str); + ret_val = xmlOutputBufferWriteString(out, str); desret_int(ret_val); call_tests++; des_xmlOutputBufferPtr(n_out, out, 0); - des_const_char_ptr(n_str, (const char *)str, 1); + des_const_char_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlOutputBufferWriteString", @@ -28373,7 +29290,7 @@ test_xmlParserInputBufferCreateFd(void) { xmlParserInputBufferPtr ret_val; int fd; /* a file descriptor number */ int n_fd; - xmlCharEncoding enc; /* the charset encoding if known */ + xmlCharEncoding enc; /* the charset encoding if known (deprecated) */ int n_enc; for (n_fd = 0;n_fd < gen_nb_int;n_fd++) { @@ -28413,7 +29330,7 @@ test_xmlParserInputBufferCreateFile(void) { xmlParserInputBufferPtr ret_val; FILE * file; /* a FILE* */ int n_file; - xmlCharEncoding enc; /* the charset encoding if known */ + xmlCharEncoding enc; /* the charset encoding if known (deprecated) */ int n_enc; for (n_file = 0;n_file < gen_nb_FILE_ptr;n_file++) { @@ -28499,11 +29416,11 @@ test_xmlParserInputBufferCreateMem(void) { int mem_base; xmlParserInputBufferPtr ret_val; - char * mem; /* the memory input */ + const char * mem; /* the memory input */ int n_mem; int size; /* the length of the memory block */ int n_size; - xmlCharEncoding enc; /* the charset encoding if known */ + xmlCharEncoding enc; /* the charset encoding if known (deprecated) */ int n_enc; for (n_mem = 0;n_mem < gen_nb_const_char_ptr;n_mem++) { @@ -28517,10 +29434,10 @@ test_xmlParserInputBufferCreateMem(void) { (size > xmlStrlen(BAD_CAST mem))) size = 0; - ret_val = xmlParserInputBufferCreateMem((const char *)mem, size, enc); + ret_val = xmlParserInputBufferCreateMem(mem, size, enc); desret_xmlParserInputBufferPtr(ret_val); call_tests++; - des_const_char_ptr(n_mem, (const char *)mem, 0); + des_const_char_ptr(n_mem, mem, 0); des_int(n_size, size, 1); des_xmlCharEncoding(n_enc, enc, 2); xmlResetLastError(); @@ -28548,7 +29465,7 @@ test_xmlParserInputBufferCreateStatic(void) { int mem_base; xmlParserInputBufferPtr ret_val; - char * mem; /* the memory input */ + const char * mem; /* the memory input */ int n_mem; int size; /* the length of the memory block */ int n_size; @@ -28566,10 +29483,10 @@ test_xmlParserInputBufferCreateStatic(void) { (size > xmlStrlen(BAD_CAST mem))) size = 0; - ret_val = xmlParserInputBufferCreateStatic((const char *)mem, size, enc); + ret_val = xmlParserInputBufferCreateStatic(mem, size, enc); desret_xmlParserInputBufferPtr(ret_val); call_tests++; - des_const_char_ptr(n_mem, (const char *)mem, 0); + des_const_char_ptr(n_mem, mem, 0); des_int(n_size, size, 1); des_xmlCharEncoding(n_enc, enc, 2); xmlResetLastError(); @@ -28640,7 +29557,7 @@ test_xmlParserInputBufferPush(void) { int n_in; int len; /* the size in bytes of the array. */ int n_len; - char * buf; /* an char array */ + const char * buf; /* an char array */ int n_buf; for (n_in = 0;n_in < gen_nb_xmlParserInputBufferPtr;n_in++) { @@ -28654,12 +29571,12 @@ test_xmlParserInputBufferPush(void) { (len > xmlStrlen(BAD_CAST buf))) len = 0; - ret_val = xmlParserInputBufferPush(in, len, (const char *)buf); + ret_val = xmlParserInputBufferPush(in, len, buf); desret_int(ret_val); call_tests++; des_xmlParserInputBufferPtr(n_in, in, 0); des_int(n_len, len, 1); - des_const_char_ptr(n_buf, (const char *)buf, 2); + des_const_char_ptr(n_buf, buf, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlParserInputBufferPush", @@ -29284,7 +30201,7 @@ test_xmlCopyError(void) { int mem_base; int ret_val; - xmlError * from; /* a source error */ + const xmlError * from; /* a source error */ int n_from; xmlErrorPtr to; /* a target error */ int n_to; @@ -29295,10 +30212,10 @@ test_xmlCopyError(void) { from = gen_const_xmlError_ptr(n_from, 0); to = gen_xmlErrorPtr(n_to, 1); - ret_val = xmlCopyError((const xmlError *)from, to); + ret_val = xmlCopyError(from, to); desret_int(ret_val); call_tests++; - des_const_xmlError_ptr(n_from, (const xmlError *)from, 0); + des_const_xmlError_ptr(n_from, from, 0); des_xmlErrorPtr(n_to, to, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -29357,6 +30274,16 @@ test_xmlCtxtResetLastError(void) { } +static int +test_xmlFormatError(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlGetLastError(void) { int test_ret = 0; @@ -29555,11 +30482,12 @@ static int test_xmlerror(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xmlerror : 7 of 17 functions ...\n"); + if (quiet == 0) printf("Testing xmlerror : 7 of 18 functions ...\n"); test_ret += test_initGenericErrorDefaultFunc(); test_ret += test_xmlCopyError(); test_ret += test_xmlCtxtGetLastError(); test_ret += test_xmlCtxtResetLastError(); + test_ret += test_xmlFormatError(); test_ret += test_xmlGetLastError(); test_ret += test_xmlParserError(); test_ret += test_xmlParserPrintFileContext(); @@ -29639,7 +30567,7 @@ test_xmlModuleSymbol(void) { int ret_val; xmlModulePtr module; /* the module */ int n_module; - char * name; /* the name of the symbol */ + const char * name; /* the name of the symbol */ int n_name; void ** symbol; /* the resulting symbol address */ int n_symbol; @@ -29652,11 +30580,11 @@ test_xmlModuleSymbol(void) { name = gen_const_char_ptr(n_name, 1); symbol = gen_void_ptr_ptr(n_symbol, 2); - ret_val = xmlModuleSymbol(module, (const char *)name, symbol); + ret_val = xmlModuleSymbol(module, name, symbol); desret_int(ret_val); call_tests++; des_xmlModulePtr(n_module, module, 0); - des_const_char_ptr(n_name, (const char *)name, 1); + des_const_char_ptr(n_name, name, 1); des_void_ptr_ptr(n_symbol, symbol, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -29773,11 +30701,11 @@ test_xmlReaderForDoc(void) { #if defined(LIBXML_READER_ENABLED) int mem_base; xmlTextReaderPtr ret_val; - xmlChar * cur; /* a pointer to a zero terminated string */ + const xmlChar * cur; /* a pointer to a zero terminated string */ int n_cur; const char * URL; /* the base URL to use for the document */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -29792,12 +30720,12 @@ test_xmlReaderForDoc(void) { encoding = gen_const_char_ptr(n_encoding, 2); options = gen_parseroptions(n_options, 3); - ret_val = xmlReaderForDoc((const xmlChar *)cur, URL, (const char *)encoding, options); + ret_val = xmlReaderForDoc(cur, URL, encoding, options); desret_xmlTextReaderPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); des_filepath(n_URL, URL, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_parseroptions(n_options, options, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -29830,7 +30758,7 @@ test_xmlReaderForFile(void) { xmlTextReaderPtr ret_val; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -29843,11 +30771,11 @@ test_xmlReaderForFile(void) { encoding = gen_const_char_ptr(n_encoding, 1); options = gen_parseroptions(n_options, 2); - ret_val = xmlReaderForFile(filename, (const char *)encoding, options); + ret_val = xmlReaderForFile(filename, encoding, options); desret_xmlTextReaderPtr(ret_val); call_tests++; des_filepath(n_filename, filename, 0); - des_const_char_ptr(n_encoding, (const char *)encoding, 1); + des_const_char_ptr(n_encoding, encoding, 1); des_parseroptions(n_options, options, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -29876,13 +30804,13 @@ test_xmlReaderForMemory(void) { #if defined(LIBXML_READER_ENABLED) int mem_base; xmlTextReaderPtr ret_val; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; const char * URL; /* the base URL to use for the document */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -29902,13 +30830,13 @@ test_xmlReaderForMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlReaderForMemory((const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = xmlReaderForMemory(buffer, size, URL, encoding, options); desret_xmlTextReaderPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_parseroptions(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -29943,11 +30871,11 @@ test_xmlReaderNewDoc(void) { int ret_val; xmlTextReaderPtr reader; /* an XML reader */ int n_reader; - xmlChar * cur; /* a pointer to a zero terminated string */ + const xmlChar * cur; /* a pointer to a zero terminated string */ int n_cur; const char * URL; /* the base URL to use for the document */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -29964,13 +30892,13 @@ test_xmlReaderNewDoc(void) { encoding = gen_const_char_ptr(n_encoding, 3); options = gen_parseroptions(n_options, 4); - ret_val = xmlReaderNewDoc(reader, (const xmlChar *)cur, URL, (const char *)encoding, options); + ret_val = xmlReaderNewDoc(reader, cur, URL, encoding, options); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 1); + des_const_xmlChar_ptr(n_cur, cur, 1); des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_parseroptions(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -30007,7 +30935,7 @@ test_xmlReaderNewFile(void) { int n_reader; const char * filename; /* a file or URL */ int n_filename; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -30022,12 +30950,12 @@ test_xmlReaderNewFile(void) { encoding = gen_const_char_ptr(n_encoding, 2); options = gen_parseroptions(n_options, 3); - ret_val = xmlReaderNewFile(reader, filename, (const char *)encoding, options); + ret_val = xmlReaderNewFile(reader, filename, encoding, options); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); des_filepath(n_filename, filename, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); + des_const_char_ptr(n_encoding, encoding, 2); des_parseroptions(n_options, options, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -30060,13 +30988,13 @@ test_xmlReaderNewMemory(void) { int ret_val; xmlTextReaderPtr reader; /* an XML reader */ int n_reader; - char * buffer; /* a pointer to a char array */ + const char * buffer; /* a pointer to a char array */ int n_buffer; int size; /* the size of the array */ int n_size; const char * URL; /* the base URL to use for the document */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -30088,14 +31016,14 @@ test_xmlReaderNewMemory(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlReaderNewMemory(reader, (const char *)buffer, size, URL, (const char *)encoding, options); + ret_val = xmlReaderNewMemory(reader, buffer, size, URL, encoding, options); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_char_ptr(n_buffer, (const char *)buffer, 1); + des_const_char_ptr(n_buffer, buffer, 1); des_int(n_size, size, 2); des_filepath(n_URL, URL, 3); - des_const_char_ptr(n_encoding, (const char *)encoding, 4); + des_const_char_ptr(n_encoding, encoding, 4); des_parseroptions(n_options, options, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -30547,7 +31475,7 @@ test_xmlTextReaderConstString(void) { const xmlChar * ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * str; /* the string to intern. */ + const xmlChar * str; /* the string to intern. */ int n_str; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -30556,11 +31484,11 @@ test_xmlTextReaderConstString(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); str = gen_const_xmlChar_ptr(n_str, 1); - ret_val = xmlTextReaderConstString(reader, (const xmlChar *)str); + ret_val = xmlTextReaderConstString(reader, str); desret_const_xmlChar_ptr(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderConstString", @@ -30826,7 +31754,7 @@ test_xmlTextReaderGetAttribute(void) { xmlChar * ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * name; /* the qualified name of the attribute. */ + const xmlChar * name; /* the qualified name of the attribute. */ int n_name; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -30835,11 +31763,11 @@ test_xmlTextReaderGetAttribute(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextReaderGetAttribute(reader, (const xmlChar *)name); + ret_val = xmlTextReaderGetAttribute(reader, name); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderGetAttribute", @@ -30908,9 +31836,9 @@ test_xmlTextReaderGetAttributeNs(void) { xmlChar * ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * localName; /* the local name of the attribute. */ + const xmlChar * localName; /* the local name of the attribute. */ int n_localName; - xmlChar * namespaceURI; /* the namespace URI of the attribute. */ + const xmlChar * namespaceURI; /* the namespace URI of the attribute. */ int n_namespaceURI; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -30921,12 +31849,12 @@ test_xmlTextReaderGetAttributeNs(void) { localName = gen_const_xmlChar_ptr(n_localName, 1); namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 2); - ret_val = xmlTextReaderGetAttributeNs(reader, (const xmlChar *)localName, (const xmlChar *)namespaceURI); + ret_val = xmlTextReaderGetAttributeNs(reader, localName, namespaceURI); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_localName, (const xmlChar *)localName, 1); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 2); + des_const_xmlChar_ptr(n_localName, localName, 1); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderGetAttributeNs", @@ -31000,6 +31928,16 @@ test_xmlTextReaderGetErrorHandler(void) { } +static int +test_xmlTextReaderGetLastError(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlTextReaderGetParserColumnNumber(void) { int test_ret = 0; @@ -31465,7 +32403,7 @@ test_xmlTextReaderLookupNamespace(void) { xmlChar * ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * prefix; /* the prefix whose namespace URI is to be resolved. To return the default namespace, specify NULL */ + const xmlChar * prefix; /* the prefix whose namespace URI is to be resolved. To return the default namespace, specify NULL */ int n_prefix; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -31474,11 +32412,11 @@ test_xmlTextReaderLookupNamespace(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); prefix = gen_const_xmlChar_ptr(n_prefix, 1); - ret_val = xmlTextReaderLookupNamespace(reader, (const xmlChar *)prefix); + ret_val = xmlTextReaderLookupNamespace(reader, prefix); desret_xmlChar_ptr(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderLookupNamespace", @@ -31506,7 +32444,7 @@ test_xmlTextReaderMoveToAttribute(void) { int ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * name; /* the qualified name of the attribute. */ + const xmlChar * name; /* the qualified name of the attribute. */ int n_name; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -31515,11 +32453,11 @@ test_xmlTextReaderMoveToAttribute(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextReaderMoveToAttribute(reader, (const xmlChar *)name); + ret_val = xmlTextReaderMoveToAttribute(reader, name); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderMoveToAttribute", @@ -31588,9 +32526,9 @@ test_xmlTextReaderMoveToAttributeNs(void) { int ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * localName; /* the local name of the attribute. */ + const xmlChar * localName; /* the local name of the attribute. */ int n_localName; - xmlChar * namespaceURI; /* the namespace URI of the attribute. */ + const xmlChar * namespaceURI; /* the namespace URI of the attribute. */ int n_namespaceURI; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -31601,12 +32539,12 @@ test_xmlTextReaderMoveToAttributeNs(void) { localName = gen_const_xmlChar_ptr(n_localName, 1); namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 2); - ret_val = xmlTextReaderMoveToAttributeNs(reader, (const xmlChar *)localName, (const xmlChar *)namespaceURI); + ret_val = xmlTextReaderMoveToAttributeNs(reader, localName, namespaceURI); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_localName, (const xmlChar *)localName, 1); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 2); + des_const_xmlChar_ptr(n_localName, localName, 1); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderMoveToAttributeNs", @@ -32011,9 +32949,9 @@ test_xmlTextReaderPreservePattern(void) { int ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - xmlChar * pattern; /* an XPath subset pattern */ + const xmlChar * pattern; /* an XPath subset pattern */ int n_pattern; - xmlChar ** namespaces; /* the prefix definitions, array of [URI, prefix] or NULL */ + const xmlChar ** namespaces; /* the prefix definitions, array of [URI, prefix] or NULL */ int n_namespaces; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -32024,12 +32962,12 @@ test_xmlTextReaderPreservePattern(void) { pattern = gen_const_xmlChar_ptr(n_pattern, 1); namespaces = gen_const_xmlChar_ptr_ptr(n_namespaces, 2); - ret_val = xmlTextReaderPreservePattern(reader, (const xmlChar *)pattern, (const xmlChar **)namespaces); + ret_val = xmlTextReaderPreservePattern(reader, pattern, namespaces); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_xmlChar_ptr(n_pattern, (const xmlChar *)pattern, 1); - des_const_xmlChar_ptr_ptr(n_namespaces, (const xmlChar **)namespaces, 2); + des_const_xmlChar_ptr(n_pattern, pattern, 1); + des_const_xmlChar_ptr_ptr(n_namespaces, namespaces, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderPreservePattern", @@ -32237,7 +33175,7 @@ test_xmlTextReaderRelaxNGValidate(void) { int ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - char * rng; /* the path to a RelaxNG schema or NULL */ + const char * rng; /* the path to a RelaxNG schema or NULL */ int n_rng; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -32246,11 +33184,11 @@ test_xmlTextReaderRelaxNGValidate(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); rng = gen_const_char_ptr(n_rng, 1); - ret_val = xmlTextReaderRelaxNGValidate(reader, (const char *)rng); + ret_val = xmlTextReaderRelaxNGValidate(reader, rng); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_char_ptr(n_rng, (const char *)rng, 1); + des_const_char_ptr(n_rng, rng, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextReaderRelaxNGValidate", @@ -32325,7 +33263,7 @@ test_xmlTextReaderSchemaValidate(void) { int ret_val; xmlTextReaderPtr reader; /* the xmlTextReaderPtr used */ int n_reader; - char * xsd; /* the path to a W3C XSD schema or NULL */ + const char * xsd; /* the path to a W3C XSD schema or NULL */ int n_xsd; for (n_reader = 0;n_reader < gen_nb_xmlTextReaderPtr;n_reader++) { @@ -32333,11 +33271,11 @@ test_xmlTextReaderSchemaValidate(void) { reader = gen_xmlTextReaderPtr(n_reader, 0); xsd = gen_const_char_ptr(n_xsd, 1); - ret_val = xmlTextReaderSchemaValidate(reader, (const char *)xsd); + ret_val = xmlTextReaderSchemaValidate(reader, xsd); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); - des_const_char_ptr(n_xsd, (const char *)xsd, 1); + des_const_char_ptr(n_xsd, xsd, 1); xmlResetLastError(); } } @@ -32528,7 +33466,7 @@ test_xmlTextReaderSetup(void) { int n_input; const char * URL; /* the base URL to use for the document */ int n_URL; - char * encoding; /* the document encoding, or NULL */ + const char * encoding; /* the document encoding, or NULL */ int n_encoding; int options; /* a combination of xmlParserOption */ int n_options; @@ -32545,12 +33483,12 @@ test_xmlTextReaderSetup(void) { encoding = gen_const_char_ptr(n_encoding, 3); options = gen_parseroptions(n_options, 4); - ret_val = xmlTextReaderSetup(reader, input, URL, (const char *)encoding, options); + ret_val = xmlTextReaderSetup(reader, input, URL, encoding, options); desret_int(ret_val); call_tests++; des_xmlTextReaderPtr(n_reader, reader, 0); des_filepath(n_URL, URL, 2); - des_const_char_ptr(n_encoding, (const char *)encoding, 3); + des_const_char_ptr(n_encoding, encoding, 3); des_parseroptions(n_options, options, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -32681,7 +33619,7 @@ static int test_xmlreader(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xmlreader : 76 of 87 functions ...\n"); + if (quiet == 0) printf("Testing xmlreader : 76 of 88 functions ...\n"); test_ret += test_xmlNewTextReader(); test_ret += test_xmlNewTextReaderFilename(); test_ret += test_xmlReaderForDoc(); @@ -32714,6 +33652,7 @@ test_xmlreader(void) { test_ret += test_xmlTextReaderGetAttributeNo(); test_ret += test_xmlTextReaderGetAttributeNs(); test_ret += test_xmlTextReaderGetErrorHandler(); + test_ret += test_xmlTextReaderGetLastError(); test_ret += test_xmlTextReaderGetParserColumnNumber(); test_ret += test_xmlTextReaderGetParserLineNumber(); test_ret += test_xmlTextReaderGetParserProp(); @@ -32895,7 +33834,7 @@ test_xmlExpGetLanguage(void) { int n_ctxt; xmlExpNodePtr exp; /* the expression */ int n_exp; - xmlChar ** langList; /* where to store the tokens */ + const xmlChar ** langList; /* where to store the tokens */ int n_langList; int len; /* the allocated length of @list */ int n_len; @@ -32910,12 +33849,12 @@ test_xmlExpGetLanguage(void) { langList = gen_const_xmlChar_ptr_ptr(n_langList, 2); len = gen_int(n_len, 3); - ret_val = xmlExpGetLanguage(ctxt, exp, (const xmlChar **)langList, len); + ret_val = xmlExpGetLanguage(ctxt, exp, langList, len); desret_int(ret_val); call_tests++; des_xmlExpCtxtPtr(n_ctxt, ctxt, 0); des_xmlExpNodePtr(n_exp, exp, 1); - des_const_xmlChar_ptr_ptr(n_langList, (const xmlChar **)langList, 2); + des_const_xmlChar_ptr_ptr(n_langList, langList, 2); des_int(n_len, len, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -32950,7 +33889,7 @@ test_xmlExpGetStart(void) { int n_ctxt; xmlExpNodePtr exp; /* the expression */ int n_exp; - xmlChar ** tokList; /* where to store the tokens */ + const xmlChar ** tokList; /* where to store the tokens */ int n_tokList; int len; /* the allocated length of @list */ int n_len; @@ -32965,12 +33904,12 @@ test_xmlExpGetStart(void) { tokList = gen_const_xmlChar_ptr_ptr(n_tokList, 2); len = gen_int(n_len, 3); - ret_val = xmlExpGetStart(ctxt, exp, (const xmlChar **)tokList, len); + ret_val = xmlExpGetStart(ctxt, exp, tokList, len); desret_int(ret_val); call_tests++; des_xmlExpCtxtPtr(n_ctxt, ctxt, 0); des_xmlExpNodePtr(n_exp, exp, 1); - des_const_xmlChar_ptr_ptr(n_tokList, (const xmlChar **)tokList, 2); + des_const_xmlChar_ptr_ptr(n_tokList, tokList, 2); des_int(n_len, len, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -33228,7 +34167,7 @@ test_xmlRegExecErrInfo(void) { int ret_val; xmlRegExecCtxtPtr exec; /* a regexp execution context generating an error */ int n_exec; - xmlChar ** string; /* return value for the error string */ + const xmlChar ** string; /* return value for the error string */ int n_string; int * nbval; /* pointer to the number of accepted values IN/OUT */ int n_nbval; @@ -33253,11 +34192,11 @@ test_xmlRegExecErrInfo(void) { values = gen_xmlChar_ptr_ptr(n_values, 4); terminal = gen_int_ptr(n_terminal, 5); - ret_val = xmlRegExecErrInfo(exec, (const xmlChar **)string, nbval, nbneg, values, terminal); + ret_val = xmlRegExecErrInfo(exec, string, nbval, nbneg, values, terminal); desret_int(ret_val); call_tests++; des_xmlRegExecCtxtPtr(n_exec, exec, 0); - des_const_xmlChar_ptr_ptr(n_string, (const xmlChar **)string, 1); + des_const_xmlChar_ptr_ptr(n_string, string, 1); des_int_ptr(n_nbval, nbval, 2); des_int_ptr(n_nbneg, nbneg, 3); des_xmlChar_ptr_ptr(n_values, values, 4); @@ -33359,7 +34298,7 @@ test_xmlRegExecPushString(void) { int ret_val; xmlRegExecCtxtPtr exec; /* a regexp execution context or NULL to indicate the end */ int n_exec; - xmlChar * value; /* a string token input */ + const xmlChar * value; /* a string token input */ int n_value; void * data; /* data associated to the token to reuse in callbacks */ int n_data; @@ -33372,11 +34311,11 @@ test_xmlRegExecPushString(void) { value = gen_const_xmlChar_ptr(n_value, 1); data = gen_userdata(n_data, 2); - ret_val = xmlRegExecPushString(exec, (const xmlChar *)value, data); + ret_val = xmlRegExecPushString(exec, value, data); desret_int(ret_val); call_tests++; des_xmlRegExecCtxtPtr(n_exec, exec, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_userdata(n_data, data, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -33407,9 +34346,9 @@ test_xmlRegExecPushString2(void) { int ret_val; xmlRegExecCtxtPtr exec; /* a regexp execution context or NULL to indicate the end */ int n_exec; - xmlChar * value; /* the first string token input */ + const xmlChar * value; /* the first string token input */ int n_value; - xmlChar * value2; /* the second string token input */ + const xmlChar * value2; /* the second string token input */ int n_value2; void * data; /* data associated to the token to reuse in callbacks */ int n_data; @@ -33424,12 +34363,12 @@ test_xmlRegExecPushString2(void) { value2 = gen_const_xmlChar_ptr(n_value2, 2); data = gen_userdata(n_data, 3); - ret_val = xmlRegExecPushString2(exec, (const xmlChar *)value, (const xmlChar *)value2, data); + ret_val = xmlRegExecPushString2(exec, value, value2, data); desret_int(ret_val); call_tests++; des_xmlRegExecCtxtPtr(n_exec, exec, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); - des_const_xmlChar_ptr(n_value2, (const xmlChar *)value2, 2); + des_const_xmlChar_ptr(n_value, value, 1); + des_const_xmlChar_ptr(n_value2, value2, 2); des_userdata(n_data, data, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -33489,7 +34428,7 @@ test_xmlRegexpExec(void) { int ret_val; xmlRegexpPtr comp; /* the compiled regular expression */ int n_comp; - xmlChar * content; /* the value to check against the regular expression */ + const xmlChar * content; /* the value to check against the regular expression */ int n_content; for (n_comp = 0;n_comp < gen_nb_xmlRegexpPtr;n_comp++) { @@ -33498,11 +34437,11 @@ test_xmlRegexpExec(void) { comp = gen_xmlRegexpPtr(n_comp, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlRegexpExec(comp, (const xmlChar *)content); + ret_val = xmlRegexpExec(comp, content); desret_int(ret_val); call_tests++; des_xmlRegexpPtr(n_comp, comp, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlRegexpExec", @@ -33712,6 +34651,40 @@ test_xmlSaveDoc(void) { } +static int +test_xmlSaveFinish(void) { + int test_ret = 0; + +#if defined(LIBXML_OUTPUT_ENABLED) + int mem_base; + int ret_val; + xmlSaveCtxtPtr ctxt; /* a document saving context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlSaveCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlSaveCtxtPtr(n_ctxt, 0); + + ret_val = xmlSaveFinish(ctxt); + desret_int(ret_val); + call_tests++; + des_xmlSaveCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlSaveFinish", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; +#endif + + return(test_ret); +} + + static int test_xmlSaveFlush(void) { int test_ret = 0; @@ -33912,17 +34885,17 @@ test_xmlThrDefTreeIndentString(void) { #if defined(LIBXML_OUTPUT_ENABLED) int mem_base; const char * ret_val; - char * v; /* */ + const char * v; /* */ int n_v; for (n_v = 0;n_v < gen_nb_const_char_ptr;n_v++) { mem_base = xmlMemBlocks(); v = gen_const_char_ptr(n_v, 0); - ret_val = xmlThrDefTreeIndentString((const char *)v); + ret_val = xmlThrDefTreeIndentString(v); desret_const_char_ptr(ret_val); call_tests++; - des_const_char_ptr(n_v, (const char *)v, 0); + des_const_char_ptr(n_v, v, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlThrDefTreeIndentString", @@ -33942,9 +34915,10 @@ static int test_xmlsave(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xmlsave : 7 of 13 functions ...\n"); + if (quiet == 0) printf("Testing xmlsave : 8 of 14 functions ...\n"); test_ret += test_xmlSaveClose(); test_ret += test_xmlSaveDoc(); + test_ret += test_xmlSaveFinish(); test_ret += test_xmlSaveFlush(); test_ret += test_xmlSaveSetAttrEscape(); test_ret += test_xmlSaveSetEscape(); @@ -34206,7 +35180,7 @@ test_xmlSchemaNewMemParserCtxt(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlSchemaParserCtxtPtr ret_val; - char * buffer; /* a pointer to a char array containing the schemas */ + const char * buffer; /* a pointer to a char array containing the schemas */ int n_buffer; int size; /* the size of the array */ int n_size; @@ -34220,10 +35194,10 @@ test_xmlSchemaNewMemParserCtxt(void) { (size > xmlStrlen(BAD_CAST buffer))) size = 0; - ret_val = xmlSchemaNewMemParserCtxt((const char *)buffer, size); + ret_val = xmlSchemaNewMemParserCtxt(buffer, size); desret_xmlSchemaParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_buffer, (const char *)buffer, 0); + des_const_char_ptr(n_buffer, buffer, 0); des_int(n_size, size, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -34250,17 +35224,17 @@ test_xmlSchemaNewParserCtxt(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlSchemaParserCtxtPtr ret_val; - char * URL; /* the location of the schema */ + const char * URL; /* the location of the schema */ int n_URL; for (n_URL = 0;n_URL < gen_nb_const_char_ptr;n_URL++) { mem_base = xmlMemBlocks(); URL = gen_const_char_ptr(n_URL, 0); - ret_val = xmlSchemaNewParserCtxt((const char *)URL); + ret_val = xmlSchemaNewParserCtxt(URL); desret_xmlSchemaParserCtxtPtr(ret_val); call_tests++; - des_const_char_ptr(n_URL, (const char *)URL, 0); + des_const_char_ptr(n_URL, URL, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaNewParserCtxt", @@ -34799,7 +35773,7 @@ test_xmlSchemaCheckFacet(void) { int n_typeDecl; xmlSchemaParserCtxtPtr pctxt; /* the schema parser context or NULL */ int n_pctxt; - xmlChar * name; /* the optional name of the type */ + const xmlChar * name; /* the optional name of the type */ int n_name; for (n_facet = 0;n_facet < gen_nb_xmlSchemaFacetPtr;n_facet++) { @@ -34812,13 +35786,13 @@ test_xmlSchemaCheckFacet(void) { pctxt = gen_xmlSchemaParserCtxtPtr(n_pctxt, 2); name = gen_const_xmlChar_ptr(n_name, 3); - ret_val = xmlSchemaCheckFacet(facet, typeDecl, pctxt, (const xmlChar *)name); + ret_val = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name); desret_int(ret_val); call_tests++; des_xmlSchemaFacetPtr(n_facet, facet, 0); des_xmlSchemaTypePtr(n_typeDecl, typeDecl, 1); des_xmlSchemaParserCtxtPtr(n_pctxt, pctxt, 2); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 3); + des_const_xmlChar_ptr(n_name, name, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaCheckFacet", @@ -34865,17 +35839,17 @@ test_xmlSchemaCollapseString(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlChar * ret_val; - xmlChar * value; /* a value */ + const xmlChar * value; /* a value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlSchemaCollapseString((const xmlChar *)value); + ret_val = xmlSchemaCollapseString(value); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaCollapseString", @@ -35073,7 +36047,7 @@ test_xmlSchemaGetCanonValue(void) { int ret_val; xmlSchemaValPtr val; /* the precomputed value */ int n_val; - xmlChar ** retValue; /* the returned value */ + const xmlChar ** retValue; /* the returned value */ int n_retValue; for (n_val = 0;n_val < gen_nb_xmlSchemaValPtr;n_val++) { @@ -35082,11 +36056,11 @@ test_xmlSchemaGetCanonValue(void) { val = gen_xmlSchemaValPtr(n_val, 0); retValue = gen_const_xmlChar_ptr_ptr(n_retValue, 1); - ret_val = xmlSchemaGetCanonValue(val, (const xmlChar **)retValue); + ret_val = xmlSchemaGetCanonValue(val, retValue); desret_int(ret_val); call_tests++; des_xmlSchemaValPtr(n_val, val, 0); - des_const_xmlChar_ptr_ptr(n_retValue, (const xmlChar **)retValue, 1); + des_const_xmlChar_ptr_ptr(n_retValue, retValue, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaGetCanonValue", @@ -35114,7 +36088,7 @@ test_xmlSchemaGetCanonValueWhtsp(void) { int ret_val; xmlSchemaValPtr val; /* the precomputed value */ int n_val; - xmlChar ** retValue; /* the returned value */ + const xmlChar ** retValue; /* the returned value */ int n_retValue; xmlSchemaWhitespaceValueType ws; /* the whitespace type of the value */ int n_ws; @@ -35127,11 +36101,11 @@ test_xmlSchemaGetCanonValueWhtsp(void) { retValue = gen_const_xmlChar_ptr_ptr(n_retValue, 1); ws = gen_xmlSchemaWhitespaceValueType(n_ws, 2); - ret_val = xmlSchemaGetCanonValueWhtsp(val, (const xmlChar **)retValue, ws); + ret_val = xmlSchemaGetCanonValueWhtsp(val, retValue, ws); desret_int(ret_val); call_tests++; des_xmlSchemaValPtr(n_val, val, 0); - des_const_xmlChar_ptr_ptr(n_retValue, (const xmlChar **)retValue, 1); + des_const_xmlChar_ptr_ptr(n_retValue, retValue, 1); des_xmlSchemaWhitespaceValueType(n_ws, ws, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -35194,9 +36168,9 @@ test_xmlSchemaGetPredefinedType(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlSchemaTypePtr ret_val; - xmlChar * name; /* the type name */ + const xmlChar * name; /* the type name */ int n_name; - xmlChar * ns; /* the URI of the namespace usually "http://www.w3.org/2001/XMLSchema" */ + const xmlChar * ns; /* the URI of the namespace usually "http://www.w3.org/2001/XMLSchema" */ int n_ns; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { @@ -35205,11 +36179,11 @@ test_xmlSchemaGetPredefinedType(void) { name = gen_const_xmlChar_ptr(n_name, 0); ns = gen_const_xmlChar_ptr(n_ns, 1); - ret_val = xmlSchemaGetPredefinedType((const xmlChar *)name, (const xmlChar *)ns); + ret_val = xmlSchemaGetPredefinedType(name, ns); desret_xmlSchemaTypePtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); - des_const_xmlChar_ptr(n_ns, (const xmlChar *)ns, 1); + des_const_xmlChar_ptr(n_name, name, 0); + des_const_xmlChar_ptr(n_ns, ns, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaGetPredefinedType", @@ -35378,7 +36352,7 @@ test_xmlSchemaValPredefTypeNode(void) { int ret_val; xmlSchemaTypePtr type; /* the predefined type */ int n_type; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; xmlSchemaValPtr * val; /* the return computed value */ int n_val; @@ -35395,11 +36369,11 @@ test_xmlSchemaValPredefTypeNode(void) { val = gen_xmlSchemaValPtr_ptr(n_val, 2); node = gen_xmlNodePtr(n_node, 3); - ret_val = xmlSchemaValPredefTypeNode(type, (const xmlChar *)value, val, node); + ret_val = xmlSchemaValPredefTypeNode(type, value, val, node); desret_int(ret_val); call_tests++; des_xmlSchemaTypePtr(n_type, type, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_xmlSchemaValPtr_ptr(n_val, val, 2); des_xmlNodePtr(n_node, node, 3); xmlResetLastError(); @@ -35433,7 +36407,7 @@ test_xmlSchemaValPredefTypeNodeNoNorm(void) { int ret_val; xmlSchemaTypePtr type; /* the predefined type */ int n_type; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; xmlSchemaValPtr * val; /* the return computed value */ int n_val; @@ -35450,11 +36424,11 @@ test_xmlSchemaValPredefTypeNodeNoNorm(void) { val = gen_xmlSchemaValPtr_ptr(n_val, 2); node = gen_xmlNodePtr(n_node, 3); - ret_val = xmlSchemaValPredefTypeNodeNoNorm(type, (const xmlChar *)value, val, node); + ret_val = xmlSchemaValPredefTypeNodeNoNorm(type, value, val, node); desret_int(ret_val); call_tests++; des_xmlSchemaTypePtr(n_type, type, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_xmlSchemaValPtr_ptr(n_val, val, 2); des_xmlNodePtr(n_node, node, 3); xmlResetLastError(); @@ -35490,7 +36464,7 @@ test_xmlSchemaValidateFacet(void) { int n_base; xmlSchemaFacetPtr facet; /* the facet to check */ int n_facet; - xmlChar * value; /* the lexical repr of the value to validate */ + const xmlChar * value; /* the lexical repr of the value to validate */ int n_value; xmlSchemaValPtr val; /* the precomputed value */ int n_val; @@ -35505,12 +36479,12 @@ test_xmlSchemaValidateFacet(void) { value = gen_const_xmlChar_ptr(n_value, 2); val = gen_xmlSchemaValPtr(n_val, 3); - ret_val = xmlSchemaValidateFacet(base, facet, (const xmlChar *)value, val); + ret_val = xmlSchemaValidateFacet(base, facet, value, val); desret_int(ret_val); call_tests++; des_xmlSchemaTypePtr(n_base, base, 0); des_xmlSchemaFacetPtr(n_facet, facet, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_value, value, 2); des_xmlSchemaValPtr(n_val, val, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -35547,7 +36521,7 @@ test_xmlSchemaValidateFacetWhtsp(void) { int n_fws; xmlSchemaValType valType; /* the built-in type of the value */ int n_valType; - xmlChar * value; /* the lexical (or normalized for pattern) repr of the value to validate */ + const xmlChar * value; /* the lexical (or normalized for pattern) repr of the value to validate */ int n_value; xmlSchemaValPtr val; /* the precomputed value */ int n_val; @@ -35568,13 +36542,13 @@ test_xmlSchemaValidateFacetWhtsp(void) { val = gen_xmlSchemaValPtr(n_val, 4); ws = gen_xmlSchemaWhitespaceValueType(n_ws, 5); - ret_val = xmlSchemaValidateFacetWhtsp(facet, fws, valType, (const xmlChar *)value, val, ws); + ret_val = xmlSchemaValidateFacetWhtsp(facet, fws, valType, value, val, ws); desret_int(ret_val); call_tests++; des_xmlSchemaFacetPtr(n_facet, facet, 0); des_xmlSchemaWhitespaceValueType(n_fws, fws, 1); des_xmlSchemaValType(n_valType, valType, 2); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 3); + des_const_xmlChar_ptr(n_value, value, 3); des_xmlSchemaValPtr(n_val, val, 4); des_xmlSchemaWhitespaceValueType(n_ws, ws, 5); xmlResetLastError(); @@ -35614,7 +36588,7 @@ test_xmlSchemaValidateLengthFacet(void) { int n_type; xmlSchemaFacetPtr facet; /* the facet to check */ int n_facet; - xmlChar * value; /* the lexical repr. of the value to be validated */ + const xmlChar * value; /* the lexical repr. of the value to be validated */ int n_value; xmlSchemaValPtr val; /* the precomputed value */ int n_val; @@ -35633,12 +36607,12 @@ test_xmlSchemaValidateLengthFacet(void) { val = gen_xmlSchemaValPtr(n_val, 3); length = gen_unsigned_long_ptr(n_length, 4); - ret_val = xmlSchemaValidateLengthFacet(type, facet, (const xmlChar *)value, val, length); + ret_val = xmlSchemaValidateLengthFacet(type, facet, value, val, length); desret_int(ret_val); call_tests++; des_xmlSchemaTypePtr(n_type, type, 0); des_xmlSchemaFacetPtr(n_facet, facet, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_value, value, 2); des_xmlSchemaValPtr(n_val, val, 3); des_unsigned_long_ptr(n_length, length, 4); xmlResetLastError(); @@ -35676,7 +36650,7 @@ test_xmlSchemaValidateLengthFacetWhtsp(void) { int n_facet; xmlSchemaValType valType; /* the built-in type */ int n_valType; - xmlChar * value; /* the lexical repr. of the value to be validated */ + const xmlChar * value; /* the lexical repr. of the value to be validated */ int n_value; xmlSchemaValPtr val; /* the precomputed value */ int n_val; @@ -35699,12 +36673,12 @@ test_xmlSchemaValidateLengthFacetWhtsp(void) { length = gen_unsigned_long_ptr(n_length, 4); ws = gen_xmlSchemaWhitespaceValueType(n_ws, 5); - ret_val = xmlSchemaValidateLengthFacetWhtsp(facet, valType, (const xmlChar *)value, val, length, ws); + ret_val = xmlSchemaValidateLengthFacetWhtsp(facet, valType, value, val, length, ws); desret_int(ret_val); call_tests++; des_xmlSchemaFacetPtr(n_facet, facet, 0); des_xmlSchemaValType(n_valType, valType, 1); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 2); + des_const_xmlChar_ptr(n_value, value, 2); des_xmlSchemaValPtr(n_val, val, 3); des_unsigned_long_ptr(n_length, length, 4); des_xmlSchemaWhitespaceValueType(n_ws, ws, 5); @@ -35743,7 +36717,7 @@ test_xmlSchemaValidateListSimpleTypeFacet(void) { int ret_val; xmlSchemaFacetPtr facet; /* the facet to check */ int n_facet; - xmlChar * value; /* the lexical repr of the value to validate */ + const xmlChar * value; /* the lexical repr of the value to validate */ int n_value; unsigned long actualLen; /* the number of list items */ int n_actualLen; @@ -35760,11 +36734,11 @@ test_xmlSchemaValidateListSimpleTypeFacet(void) { actualLen = gen_unsigned_long(n_actualLen, 2); expectedLen = gen_unsigned_long_ptr(n_expectedLen, 3); - ret_val = xmlSchemaValidateListSimpleTypeFacet(facet, (const xmlChar *)value, actualLen, expectedLen); + ret_val = xmlSchemaValidateListSimpleTypeFacet(facet, value, actualLen, expectedLen); desret_int(ret_val); call_tests++; des_xmlSchemaFacetPtr(n_facet, facet, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_unsigned_long(n_actualLen, actualLen, 2); des_unsigned_long_ptr(n_expectedLen, expectedLen, 3); xmlResetLastError(); @@ -35798,7 +36772,7 @@ test_xmlSchemaValidatePredefinedType(void) { int ret_val; xmlSchemaTypePtr type; /* the predefined type */ int n_type; - xmlChar * value; /* the value to check */ + const xmlChar * value; /* the value to check */ int n_value; xmlSchemaValPtr * val; /* the return computed value */ int n_val; @@ -35811,11 +36785,11 @@ test_xmlSchemaValidatePredefinedType(void) { value = gen_const_xmlChar_ptr(n_value, 1); val = gen_xmlSchemaValPtr_ptr(n_val, 2); - ret_val = xmlSchemaValidatePredefinedType(type, (const xmlChar *)value, val); + ret_val = xmlSchemaValidatePredefinedType(type, value, val); desret_int(ret_val); call_tests++; des_xmlSchemaTypePtr(n_type, type, 0); - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 1); + des_const_xmlChar_ptr(n_value, value, 1); des_xmlSchemaValPtr_ptr(n_val, val, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -35963,17 +36937,17 @@ test_xmlSchemaWhiteSpaceReplace(void) { #if defined(LIBXML_SCHEMAS_ENABLED) int mem_base; xmlChar * ret_val; - xmlChar * value; /* a value */ + const xmlChar * value; /* a value */ int n_value; for (n_value = 0;n_value < gen_nb_const_xmlChar_ptr;n_value++) { mem_base = xmlMemBlocks(); value = gen_const_xmlChar_ptr(n_value, 0); - ret_val = xmlSchemaWhiteSpaceReplace((const xmlChar *)value); + ret_val = xmlSchemaWhiteSpaceReplace(value); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_value, (const xmlChar *)value, 0); + des_const_xmlChar_ptr(n_value, value, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlSchemaWhiteSpaceReplace", @@ -36038,17 +37012,17 @@ test_xmlCharStrdup(void) { int mem_base; xmlChar * ret_val; - char * cur; /* the input char * */ + const char * cur; /* the input char * */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_char_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_char_ptr(n_cur, 0); - ret_val = xmlCharStrdup((const char *)cur); + ret_val = xmlCharStrdup(cur); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_char_ptr(n_cur, (const char *)cur, 0); + des_const_char_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCharStrdup", @@ -36070,7 +37044,7 @@ test_xmlCharStrndup(void) { int mem_base; xmlChar * ret_val; - char * cur; /* the input char * */ + const char * cur; /* the input char * */ int n_cur; int len; /* the len of @cur */ int n_len; @@ -36084,10 +37058,10 @@ test_xmlCharStrndup(void) { (len > xmlStrlen(BAD_CAST cur))) len = 0; - ret_val = xmlCharStrndup((const char *)cur, len); + ret_val = xmlCharStrndup(cur, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_char_ptr(n_cur, (const char *)cur, 0); + des_const_char_ptr(n_cur, cur, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36112,17 +37086,17 @@ test_xmlCheckUTF8(void) { int mem_base; int ret_val; - unsigned char * utf; /* Pointer to putative UTF-8 encoded string. */ + const unsigned char * utf; /* Pointer to putative UTF-8 encoded string. */ int n_utf; for (n_utf = 0;n_utf < gen_nb_const_unsigned_char_ptr;n_utf++) { mem_base = xmlMemBlocks(); utf = gen_const_unsigned_char_ptr(n_utf, 0); - ret_val = xmlCheckUTF8((const unsigned char *)utf); + ret_val = xmlCheckUTF8(utf); desret_int(ret_val); call_tests++; - des_const_unsigned_char_ptr(n_utf, (const unsigned char *)utf, 0); + des_const_unsigned_char_ptr(n_utf, utf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlCheckUTF8", @@ -36144,7 +37118,7 @@ test_xmlGetUTF8Char(void) { int mem_base; int ret_val; - unsigned char * utf; /* a sequence of UTF-8 encoded bytes */ + const unsigned char * utf; /* a sequence of UTF-8 encoded bytes */ int n_utf; int * len; /* a pointer to the minimum number of bytes present in the sequence. This is used to assure the next character is completely contained within the sequence. */ int n_len; @@ -36155,10 +37129,10 @@ test_xmlGetUTF8Char(void) { utf = gen_const_unsigned_char_ptr(n_utf, 0); len = gen_int_ptr(n_len, 1); - ret_val = xmlGetUTF8Char((const unsigned char *)utf, len); + ret_val = xmlGetUTF8Char(utf, len); desret_int(ret_val); call_tests++; - des_const_unsigned_char_ptr(n_utf, (const unsigned char *)utf, 0); + des_const_unsigned_char_ptr(n_utf, utf, 0); des_int_ptr(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36183,9 +37157,9 @@ test_xmlStrEqual(void) { int mem_base; int ret_val; - xmlChar * str1; /* the first xmlChar * */ + const xmlChar * str1; /* the first xmlChar * */ int n_str1; - xmlChar * str2; /* the second xmlChar * */ + const xmlChar * str2; /* the second xmlChar * */ int n_str2; for (n_str1 = 0;n_str1 < gen_nb_const_xmlChar_ptr;n_str1++) { @@ -36194,11 +37168,11 @@ test_xmlStrEqual(void) { str1 = gen_const_xmlChar_ptr(n_str1, 0); str2 = gen_const_xmlChar_ptr(n_str2, 1); - ret_val = xmlStrEqual((const xmlChar *)str1, (const xmlChar *)str2); + ret_val = xmlStrEqual(str1, str2); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrEqual", @@ -36232,11 +37206,11 @@ test_xmlStrQEqual(void) { int mem_base; int ret_val; - xmlChar * pref; /* the prefix of the QName */ + const xmlChar * pref; /* the prefix of the QName */ int n_pref; - xmlChar * name; /* the localname of the QName */ + const xmlChar * name; /* the localname of the QName */ int n_name; - xmlChar * str; /* the second xmlChar * */ + const xmlChar * str; /* the second xmlChar * */ int n_str; for (n_pref = 0;n_pref < gen_nb_const_xmlChar_ptr;n_pref++) { @@ -36247,12 +37221,12 @@ test_xmlStrQEqual(void) { name = gen_const_xmlChar_ptr(n_name, 1); str = gen_const_xmlChar_ptr(n_str, 2); - ret_val = xmlStrQEqual((const xmlChar *)pref, (const xmlChar *)name, (const xmlChar *)str); + ret_val = xmlStrQEqual(pref, name, str); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_pref, (const xmlChar *)pref, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 2); + des_const_xmlChar_ptr(n_pref, pref, 0); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_str, str, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrQEqual", @@ -36288,9 +37262,9 @@ test_xmlStrcasecmp(void) { int mem_base; int ret_val; - xmlChar * str1; /* the first xmlChar * */ + const xmlChar * str1; /* the first xmlChar * */ int n_str1; - xmlChar * str2; /* the second xmlChar * */ + const xmlChar * str2; /* the second xmlChar * */ int n_str2; for (n_str1 = 0;n_str1 < gen_nb_const_xmlChar_ptr;n_str1++) { @@ -36299,11 +37273,11 @@ test_xmlStrcasecmp(void) { str1 = gen_const_xmlChar_ptr(n_str1, 0); str2 = gen_const_xmlChar_ptr(n_str2, 1); - ret_val = xmlStrcasecmp((const xmlChar *)str1, (const xmlChar *)str2); + ret_val = xmlStrcasecmp(str1, str2); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrcasecmp", @@ -36327,9 +37301,9 @@ test_xmlStrcasestr(void) { int mem_base; const xmlChar * ret_val; - xmlChar * str; /* the xmlChar * array (haystack) */ + const xmlChar * str; /* the xmlChar * array (haystack) */ int n_str; - xmlChar * val; /* the xmlChar to search (needle) */ + const xmlChar * val; /* the xmlChar to search (needle) */ int n_val; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { @@ -36338,11 +37312,11 @@ test_xmlStrcasestr(void) { str = gen_const_xmlChar_ptr(n_str, 0); val = gen_const_xmlChar_ptr(n_val, 1); - ret_val = xmlStrcasestr((const xmlChar *)str, (const xmlChar *)val); + ret_val = xmlStrcasestr(str, val); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); - des_const_xmlChar_ptr(n_val, (const xmlChar *)val, 1); + des_const_xmlChar_ptr(n_str, str, 0); + des_const_xmlChar_ptr(n_val, val, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrcasestr", @@ -36366,7 +37340,7 @@ test_xmlStrchr(void) { int mem_base; const xmlChar * ret_val; - xmlChar * str; /* the xmlChar * array */ + const xmlChar * str; /* the xmlChar * array */ int n_str; xmlChar val; /* the xmlChar to search */ int n_val; @@ -36377,10 +37351,10 @@ test_xmlStrchr(void) { str = gen_const_xmlChar_ptr(n_str, 0); val = gen_xmlChar(n_val, 1); - ret_val = xmlStrchr((const xmlChar *)str, val); + ret_val = xmlStrchr(str, val); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); des_xmlChar(n_val, val, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36405,9 +37379,9 @@ test_xmlStrcmp(void) { int mem_base; int ret_val; - xmlChar * str1; /* the first xmlChar * */ + const xmlChar * str1; /* the first xmlChar * */ int n_str1; - xmlChar * str2; /* the second xmlChar * */ + const xmlChar * str2; /* the second xmlChar * */ int n_str2; for (n_str1 = 0;n_str1 < gen_nb_const_xmlChar_ptr;n_str1++) { @@ -36416,11 +37390,11 @@ test_xmlStrcmp(void) { str1 = gen_const_xmlChar_ptr(n_str1, 0); str2 = gen_const_xmlChar_ptr(n_str2, 1); - ret_val = xmlStrcmp((const xmlChar *)str1, (const xmlChar *)str2); + ret_val = xmlStrcmp(str1, str2); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrcmp", @@ -36444,17 +37418,17 @@ test_xmlStrdup(void) { int mem_base; xmlChar * ret_val; - xmlChar * cur; /* the input xmlChar * */ + const xmlChar * cur; /* the input xmlChar * */ int n_cur; for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) { mem_base = xmlMemBlocks(); cur = gen_const_xmlChar_ptr(n_cur, 0); - ret_val = xmlStrdup((const xmlChar *)cur); + ret_val = xmlStrdup(cur); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrdup", @@ -36476,17 +37450,17 @@ test_xmlStrlen(void) { int mem_base; int ret_val; - xmlChar * str; /* the xmlChar * array */ + const xmlChar * str; /* the xmlChar * array */ int n_str; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { mem_base = xmlMemBlocks(); str = gen_const_xmlChar_ptr(n_str, 0); - ret_val = xmlStrlen((const xmlChar *)str); + ret_val = xmlStrlen(str); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrlen", @@ -36508,9 +37482,9 @@ test_xmlStrncasecmp(void) { int mem_base; int ret_val; - xmlChar * str1; /* the first xmlChar * */ + const xmlChar * str1; /* the first xmlChar * */ int n_str1; - xmlChar * str2; /* the second xmlChar * */ + const xmlChar * str2; /* the second xmlChar * */ int n_str2; int len; /* the max comparison length */ int n_len; @@ -36526,11 +37500,11 @@ test_xmlStrncasecmp(void) { (len > xmlStrlen(BAD_CAST str2))) len = 0; - ret_val = xmlStrncasecmp((const xmlChar *)str1, (const xmlChar *)str2, len); + ret_val = xmlStrncasecmp(str1, str2, len); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36557,9 +37531,9 @@ test_xmlStrncatNew(void) { int mem_base; xmlChar * ret_val; - xmlChar * str1; /* first xmlChar string */ + const xmlChar * str1; /* first xmlChar string */ int n_str1; - xmlChar * str2; /* second xmlChar string */ + const xmlChar * str2; /* second xmlChar string */ int n_str2; int len; /* the len of @str2 or < 0 */ int n_len; @@ -36575,11 +37549,11 @@ test_xmlStrncatNew(void) { (len > xmlStrlen(BAD_CAST str2))) len = 0; - ret_val = xmlStrncatNew((const xmlChar *)str1, (const xmlChar *)str2, len); + ret_val = xmlStrncatNew(str1, str2, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36606,9 +37580,9 @@ test_xmlStrncmp(void) { int mem_base; int ret_val; - xmlChar * str1; /* the first xmlChar * */ + const xmlChar * str1; /* the first xmlChar * */ int n_str1; - xmlChar * str2; /* the second xmlChar * */ + const xmlChar * str2; /* the second xmlChar * */ int n_str2; int len; /* the max comparison length */ int n_len; @@ -36624,11 +37598,11 @@ test_xmlStrncmp(void) { (len > xmlStrlen(BAD_CAST str2))) len = 0; - ret_val = xmlStrncmp((const xmlChar *)str1, (const xmlChar *)str2, len); + ret_val = xmlStrncmp(str1, str2, len); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str1, (const xmlChar *)str1, 0); - des_const_xmlChar_ptr(n_str2, (const xmlChar *)str2, 1); + des_const_xmlChar_ptr(n_str1, str1, 0); + des_const_xmlChar_ptr(n_str2, str2, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36655,7 +37629,7 @@ test_xmlStrndup(void) { int mem_base; xmlChar * ret_val; - xmlChar * cur; /* the input xmlChar * */ + const xmlChar * cur; /* the input xmlChar * */ int n_cur; int len; /* the len of @cur */ int n_len; @@ -36669,10 +37643,10 @@ test_xmlStrndup(void) { (len > xmlStrlen(BAD_CAST cur))) len = 0; - ret_val = xmlStrndup((const xmlChar *)cur, len); + ret_val = xmlStrndup(cur, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0); + des_const_xmlChar_ptr(n_cur, cur, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36697,9 +37671,9 @@ test_xmlStrstr(void) { int mem_base; const xmlChar * ret_val; - xmlChar * str; /* the xmlChar * array (haystack) */ + const xmlChar * str; /* the xmlChar * array (haystack) */ int n_str; - xmlChar * val; /* the xmlChar to search (needle) */ + const xmlChar * val; /* the xmlChar to search (needle) */ int n_val; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { @@ -36708,11 +37682,11 @@ test_xmlStrstr(void) { str = gen_const_xmlChar_ptr(n_str, 0); val = gen_const_xmlChar_ptr(n_val, 1); - ret_val = xmlStrstr((const xmlChar *)str, (const xmlChar *)val); + ret_val = xmlStrstr(str, val); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); - des_const_xmlChar_ptr(n_val, (const xmlChar *)val, 1); + des_const_xmlChar_ptr(n_str, str, 0); + des_const_xmlChar_ptr(n_val, val, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlStrstr", @@ -36736,7 +37710,7 @@ test_xmlStrsub(void) { int mem_base; xmlChar * ret_val; - xmlChar * str; /* the xmlChar * array (haystack) */ + const xmlChar * str; /* the xmlChar * array (haystack) */ int n_str; int start; /* the index of the first char (zero based) */ int n_start; @@ -36757,10 +37731,10 @@ test_xmlStrsub(void) { (len > xmlStrlen(BAD_CAST str))) len = 0; - ret_val = xmlStrsub((const xmlChar *)str, start, len); + ret_val = xmlStrsub(str, start, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); des_int(n_start, start, 1); des_int(n_len, len, 2); xmlResetLastError(); @@ -36788,9 +37762,9 @@ test_xmlUTF8Charcmp(void) { int mem_base; int ret_val; - xmlChar * utf1; /* pointer to first UTF8 char */ + const xmlChar * utf1; /* pointer to first UTF8 char */ int n_utf1; - xmlChar * utf2; /* pointer to second UTF8 char */ + const xmlChar * utf2; /* pointer to second UTF8 char */ int n_utf2; for (n_utf1 = 0;n_utf1 < gen_nb_const_xmlChar_ptr;n_utf1++) { @@ -36799,11 +37773,11 @@ test_xmlUTF8Charcmp(void) { utf1 = gen_const_xmlChar_ptr(n_utf1, 0); utf2 = gen_const_xmlChar_ptr(n_utf2, 1); - ret_val = xmlUTF8Charcmp((const xmlChar *)utf1, (const xmlChar *)utf2); + ret_val = xmlUTF8Charcmp(utf1, utf2); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf1, (const xmlChar *)utf1, 0); - des_const_xmlChar_ptr(n_utf2, (const xmlChar *)utf2, 1); + des_const_xmlChar_ptr(n_utf1, utf1, 0); + des_const_xmlChar_ptr(n_utf2, utf2, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUTF8Charcmp", @@ -36827,17 +37801,17 @@ test_xmlUTF8Size(void) { int mem_base; int ret_val; - xmlChar * utf; /* pointer to the UTF8 character */ + const xmlChar * utf; /* pointer to the UTF8 character */ int n_utf; for (n_utf = 0;n_utf < gen_nb_const_xmlChar_ptr;n_utf++) { mem_base = xmlMemBlocks(); utf = gen_const_xmlChar_ptr(n_utf, 0); - ret_val = xmlUTF8Size((const xmlChar *)utf); + ret_val = xmlUTF8Size(utf); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUTF8Size", @@ -36859,17 +37833,17 @@ test_xmlUTF8Strlen(void) { int mem_base; int ret_val; - xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ + const xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ int n_utf; for (n_utf = 0;n_utf < gen_nb_const_xmlChar_ptr;n_utf++) { mem_base = xmlMemBlocks(); utf = gen_const_xmlChar_ptr(n_utf, 0); - ret_val = xmlUTF8Strlen((const xmlChar *)utf); + ret_val = xmlUTF8Strlen(utf); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUTF8Strlen", @@ -36891,9 +37865,9 @@ test_xmlUTF8Strloc(void) { int mem_base; int ret_val; - xmlChar * utf; /* the input UTF8 * */ + const xmlChar * utf; /* the input UTF8 * */ int n_utf; - xmlChar * utfchar; /* the UTF8 character to be found */ + const xmlChar * utfchar; /* the UTF8 character to be found */ int n_utfchar; for (n_utf = 0;n_utf < gen_nb_const_xmlChar_ptr;n_utf++) { @@ -36902,11 +37876,11 @@ test_xmlUTF8Strloc(void) { utf = gen_const_xmlChar_ptr(n_utf, 0); utfchar = gen_const_xmlChar_ptr(n_utfchar, 1); - ret_val = xmlUTF8Strloc((const xmlChar *)utf, (const xmlChar *)utfchar); + ret_val = xmlUTF8Strloc(utf, utfchar); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); - des_const_xmlChar_ptr(n_utfchar, (const xmlChar *)utfchar, 1); + des_const_xmlChar_ptr(n_utf, utf, 0); + des_const_xmlChar_ptr(n_utfchar, utfchar, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUTF8Strloc", @@ -36930,7 +37904,7 @@ test_xmlUTF8Strndup(void) { int mem_base; xmlChar * ret_val; - xmlChar * utf; /* the input UTF8 * */ + const xmlChar * utf; /* the input UTF8 * */ int n_utf; int len; /* the len of @utf (in chars) */ int n_len; @@ -36944,10 +37918,10 @@ test_xmlUTF8Strndup(void) { (len > xmlStrlen(BAD_CAST utf))) len = 0; - ret_val = xmlUTF8Strndup((const xmlChar *)utf, len); + ret_val = xmlUTF8Strndup(utf, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -36972,7 +37946,7 @@ test_xmlUTF8Strpos(void) { int mem_base; const xmlChar * ret_val; - xmlChar * utf; /* the input UTF8 * */ + const xmlChar * utf; /* the input UTF8 * */ int n_utf; int pos; /* the position of the desired UTF8 char (in chars) */ int n_pos; @@ -36983,10 +37957,10 @@ test_xmlUTF8Strpos(void) { utf = gen_const_xmlChar_ptr(n_utf, 0); pos = gen_int(n_pos, 1); - ret_val = xmlUTF8Strpos((const xmlChar *)utf, pos); + ret_val = xmlUTF8Strpos(utf, pos); desret_const_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); des_int(n_pos, pos, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -37011,7 +37985,7 @@ test_xmlUTF8Strsize(void) { int mem_base; int ret_val; - xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ + const xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ int n_utf; int len; /* the number of characters in the array */ int n_len; @@ -37025,10 +37999,10 @@ test_xmlUTF8Strsize(void) { (len > xmlStrlen(BAD_CAST utf))) len = 0; - ret_val = xmlUTF8Strsize((const xmlChar *)utf, len); + ret_val = xmlUTF8Strsize(utf, len); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); des_int(n_len, len, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -37053,7 +38027,7 @@ test_xmlUTF8Strsub(void) { int mem_base; xmlChar * ret_val; - xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ + const xmlChar * utf; /* a sequence of UTF-8 encoded bytes */ int n_utf; int start; /* relative pos of first char */ int n_start; @@ -37074,10 +38048,10 @@ test_xmlUTF8Strsub(void) { (len > xmlStrlen(BAD_CAST utf))) len = 0; - ret_val = xmlUTF8Strsub((const xmlChar *)utf, start, len); + ret_val = xmlUTF8Strsub(utf, start, len); desret_xmlChar_ptr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_utf, (const xmlChar *)utf, 0); + des_const_xmlChar_ptr(n_utf, utf, 0); des_int(n_start, start, 1); des_int(n_len, len, 2); xmlResetLastError(); @@ -37452,7 +38426,7 @@ test_xmlUCSIsBlock(void) { int ret_val; int code; /* UCS code point */ int n_code; - char * block; /* UCS block name */ + const char * block; /* UCS block name */ int n_block; for (n_code = 0;n_code < gen_nb_int;n_code++) { @@ -37461,11 +38435,11 @@ test_xmlUCSIsBlock(void) { code = gen_int(n_code, 0); block = gen_const_char_ptr(n_block, 1); - ret_val = xmlUCSIsBlock(code, (const char *)block); + ret_val = xmlUCSIsBlock(code, block); desret_int(ret_val); call_tests++; des_int(n_code, code, 0); - des_const_char_ptr(n_block, (const char *)block, 1); + des_const_char_ptr(n_block, block, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUCSIsBlock", @@ -38037,7 +39011,7 @@ test_xmlUCSIsCat(void) { int ret_val; int code; /* UCS code point */ int n_code; - char * cat; /* UCS Category name */ + const char * cat; /* UCS Category name */ int n_cat; for (n_code = 0;n_code < gen_nb_int;n_code++) { @@ -38046,11 +39020,11 @@ test_xmlUCSIsCat(void) { code = gen_int(n_code, 0); cat = gen_const_char_ptr(n_cat, 1); - ret_val = xmlUCSIsCat(code, (const char *)cat); + ret_val = xmlUCSIsCat(code, cat); desret_int(ret_val); call_tests++; des_int(n_code, code, 0); - des_const_char_ptr(n_cat, (const char *)cat, 1); + des_const_char_ptr(n_cat, cat, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlUCSIsCat", @@ -43178,6 +44152,40 @@ test_xmlNewTextWriterTree(void) { } +static int +test_xmlTextWriterClose(void) { + int test_ret = 0; + +#if defined(LIBXML_WRITER_ENABLED) + int mem_base; + int ret_val; + xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ + int n_writer; + + for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { + mem_base = xmlMemBlocks(); + writer = gen_xmlTextWriterPtr(n_writer, 0); + + ret_val = xmlTextWriterClose(writer); + desret_int(ret_val); + call_tests++; + des_xmlTextWriterPtr(n_writer, writer, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlTextWriterClose", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_writer); + printf("\n"); + } + } + function_tests++; +#endif + + return(test_ret); +} + + static int test_xmlTextWriterEndAttribute(void) { int test_ret = 0; @@ -43636,7 +44644,7 @@ test_xmlTextWriterSetIndentString(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * str; /* the xmlChar string */ + const xmlChar * str; /* the xmlChar string */ int n_str; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43645,11 +44653,11 @@ test_xmlTextWriterSetIndentString(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); str = gen_const_xmlChar_ptr(n_str, 1); - ret_val = xmlTextWriterSetIndentString(writer, (const xmlChar *)str); + ret_val = xmlTextWriterSetIndentString(writer, str); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterSetIndentString", @@ -43718,7 +44726,7 @@ test_xmlTextWriterStartAttribute(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* element name */ + const xmlChar * name; /* element name */ int n_name; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43727,11 +44735,11 @@ test_xmlTextWriterStartAttribute(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextWriterStartAttribute(writer, (const xmlChar *)name); + ret_val = xmlTextWriterStartAttribute(writer, name); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartAttribute", @@ -43759,11 +44767,11 @@ test_xmlTextWriterStartAttributeNS(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * prefix; /* namespace prefix or NULL */ + const xmlChar * prefix; /* namespace prefix or NULL */ int n_prefix; - xmlChar * name; /* element local name */ + const xmlChar * name; /* element local name */ int n_name; - xmlChar * namespaceURI; /* namespace URI or NULL */ + const xmlChar * namespaceURI; /* namespace URI or NULL */ int n_namespaceURI; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43776,13 +44784,13 @@ test_xmlTextWriterStartAttributeNS(void) { name = gen_const_xmlChar_ptr(n_name, 2); namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 3); - ret_val = xmlTextWriterStartAttributeNS(writer, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)namespaceURI); + ret_val = xmlTextWriterStartAttributeNS(writer, prefix, name, namespaceURI); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 3); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartAttributeNS", @@ -43882,11 +44890,11 @@ test_xmlTextWriterStartDTD(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD */ + const xmlChar * name; /* the name of the DTD */ int n_name; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43899,13 +44907,13 @@ test_xmlTextWriterStartDTD(void) { pubid = gen_const_xmlChar_ptr(n_pubid, 2); sysid = gen_const_xmlChar_ptr(n_sysid, 3); - ret_val = xmlTextWriterStartDTD(writer, (const xmlChar *)name, (const xmlChar *)pubid, (const xmlChar *)sysid); + ret_val = xmlTextWriterStartDTD(writer, name, pubid, sysid); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 2); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_pubid, pubid, 2); + des_const_xmlChar_ptr(n_sysid, sysid, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartDTD", @@ -43937,7 +44945,7 @@ test_xmlTextWriterStartDTDAttlist(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD ATTLIST */ + const xmlChar * name; /* the name of the DTD ATTLIST */ int n_name; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43946,11 +44954,11 @@ test_xmlTextWriterStartDTDAttlist(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextWriterStartDTDAttlist(writer, (const xmlChar *)name); + ret_val = xmlTextWriterStartDTDAttlist(writer, name); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartDTDAttlist", @@ -43978,7 +44986,7 @@ test_xmlTextWriterStartDTDElement(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD element */ + const xmlChar * name; /* the name of the DTD element */ int n_name; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -43987,11 +44995,11 @@ test_xmlTextWriterStartDTDElement(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextWriterStartDTDElement(writer, (const xmlChar *)name); + ret_val = xmlTextWriterStartDTDElement(writer, name); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartDTDElement", @@ -44021,7 +45029,7 @@ test_xmlTextWriterStartDTDEntity(void) { int n_writer; int pe; /* TRUE if this is a parameter entity, FALSE if not */ int n_pe; - xmlChar * name; /* the name of the DTD ATTLIST */ + const xmlChar * name; /* the name of the DTD ATTLIST */ int n_name; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44032,12 +45040,12 @@ test_xmlTextWriterStartDTDEntity(void) { pe = gen_int(n_pe, 1); name = gen_const_xmlChar_ptr(n_name, 2); - ret_val = xmlTextWriterStartDTDEntity(writer, pe, (const xmlChar *)name); + ret_val = xmlTextWriterStartDTDEntity(writer, pe, name); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); des_int(n_pe, pe, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); + des_const_xmlChar_ptr(n_name, name, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartDTDEntity", @@ -44067,11 +45075,11 @@ test_xmlTextWriterStartDocument(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - char * version; /* the xml version ("1.0") or NULL for default ("1.0") */ + const char * version; /* the xml version ("1.0") or NULL for default ("1.0") */ int n_version; - char * encoding; /* the encoding or NULL for default */ + const char * encoding; /* the encoding or NULL for default */ int n_encoding; - char * standalone; /* "yes" or "no" or NULL for default */ + const char * standalone; /* "yes" or "no" or NULL for default */ int n_standalone; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44084,13 +45092,13 @@ test_xmlTextWriterStartDocument(void) { encoding = gen_const_char_ptr(n_encoding, 2); standalone = gen_const_char_ptr(n_standalone, 3); - ret_val = xmlTextWriterStartDocument(writer, (const char *)version, (const char *)encoding, (const char *)standalone); + ret_val = xmlTextWriterStartDocument(writer, version, encoding, standalone); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_char_ptr(n_version, (const char *)version, 1); - des_const_char_ptr(n_encoding, (const char *)encoding, 2); - des_const_char_ptr(n_standalone, (const char *)standalone, 3); + des_const_char_ptr(n_version, version, 1); + des_const_char_ptr(n_encoding, encoding, 2); + des_const_char_ptr(n_standalone, standalone, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartDocument", @@ -44122,7 +45130,7 @@ test_xmlTextWriterStartElement(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* element name */ + const xmlChar * name; /* element name */ int n_name; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44131,11 +45139,11 @@ test_xmlTextWriterStartElement(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlTextWriterStartElement(writer, (const xmlChar *)name); + ret_val = xmlTextWriterStartElement(writer, name); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartElement", @@ -44163,11 +45171,11 @@ test_xmlTextWriterStartElementNS(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * prefix; /* namespace prefix or NULL */ + const xmlChar * prefix; /* namespace prefix or NULL */ int n_prefix; - xmlChar * name; /* element local name */ + const xmlChar * name; /* element local name */ int n_name; - xmlChar * namespaceURI; /* namespace URI or NULL */ + const xmlChar * namespaceURI; /* namespace URI or NULL */ int n_namespaceURI; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44180,13 +45188,13 @@ test_xmlTextWriterStartElementNS(void) { name = gen_const_xmlChar_ptr(n_name, 2); namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 3); - ret_val = xmlTextWriterStartElementNS(writer, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)namespaceURI); + ret_val = xmlTextWriterStartElementNS(writer, prefix, name, namespaceURI); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 3); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartElementNS", @@ -44218,7 +45226,7 @@ test_xmlTextWriterStartPI(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * target; /* PI target */ + const xmlChar * target; /* PI target */ int n_target; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44227,11 +45235,11 @@ test_xmlTextWriterStartPI(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); target = gen_const_xmlChar_ptr(n_target, 1); - ret_val = xmlTextWriterStartPI(writer, (const xmlChar *)target); + ret_val = xmlTextWriterStartPI(writer, target); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_target, (const xmlChar *)target, 1); + des_const_xmlChar_ptr(n_target, target, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterStartPI", @@ -44259,9 +45267,9 @@ test_xmlTextWriterWriteAttribute(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* attribute name */ + const xmlChar * name; /* attribute name */ int n_name; - xmlChar * content; /* attribute content */ + const xmlChar * content; /* attribute content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44272,12 +45280,12 @@ test_xmlTextWriterWriteAttribute(void) { name = gen_const_xmlChar_ptr(n_name, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlTextWriterWriteAttribute(writer, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlTextWriterWriteAttribute(writer, name, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteAttribute", @@ -44307,13 +45315,13 @@ test_xmlTextWriterWriteAttributeNS(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * prefix; /* namespace prefix */ + const xmlChar * prefix; /* namespace prefix */ int n_prefix; - xmlChar * name; /* attribute local name */ + const xmlChar * name; /* attribute local name */ int n_name; - xmlChar * namespaceURI; /* namespace URI */ + const xmlChar * namespaceURI; /* namespace URI */ int n_namespaceURI; - xmlChar * content; /* attribute content */ + const xmlChar * content; /* attribute content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44328,14 +45336,14 @@ test_xmlTextWriterWriteAttributeNS(void) { namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 3); content = gen_const_xmlChar_ptr(n_content, 4); - ret_val = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)namespaceURI, (const xmlChar *)content); + ret_val = xmlTextWriterWriteAttributeNS(writer, prefix, name, namespaceURI, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 3); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 4); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 3); + des_const_xmlChar_ptr(n_content, content, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteAttributeNS", @@ -44369,7 +45377,7 @@ test_xmlTextWriterWriteBase64(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - char * data; /* binary data */ + const char * data; /* binary data */ int n_data; int start; /* the position within the data of the first byte to encode */ int n_start; @@ -44392,11 +45400,11 @@ test_xmlTextWriterWriteBase64(void) { (len > xmlStrlen(BAD_CAST data))) len = 0; - ret_val = xmlTextWriterWriteBase64(writer, (const char *)data, start, len); + ret_val = xmlTextWriterWriteBase64(writer, data, start, len); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_char_ptr(n_data, (const char *)data, 1); + des_const_char_ptr(n_data, data, 1); des_int(n_start, start, 2); des_int(n_len, len, 3); xmlResetLastError(); @@ -44430,7 +45438,7 @@ test_xmlTextWriterWriteBinHex(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - char * data; /* binary data */ + const char * data; /* binary data */ int n_data; int start; /* the position within the data of the first byte to encode */ int n_start; @@ -44453,11 +45461,11 @@ test_xmlTextWriterWriteBinHex(void) { (len > xmlStrlen(BAD_CAST data))) len = 0; - ret_val = xmlTextWriterWriteBinHex(writer, (const char *)data, start, len); + ret_val = xmlTextWriterWriteBinHex(writer, data, start, len); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_char_ptr(n_data, (const char *)data, 1); + des_const_char_ptr(n_data, data, 1); des_int(n_start, start, 2); des_int(n_len, len, 3); xmlResetLastError(); @@ -44491,7 +45499,7 @@ test_xmlTextWriterWriteCDATA(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * content; /* CDATA content */ + const xmlChar * content; /* CDATA content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44500,11 +45508,11 @@ test_xmlTextWriterWriteCDATA(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlTextWriterWriteCDATA(writer, (const xmlChar *)content); + ret_val = xmlTextWriterWriteCDATA(writer, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteCDATA", @@ -44532,7 +45540,7 @@ test_xmlTextWriterWriteComment(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * content; /* comment string */ + const xmlChar * content; /* comment string */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44541,11 +45549,11 @@ test_xmlTextWriterWriteComment(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlTextWriterWriteComment(writer, (const xmlChar *)content); + ret_val = xmlTextWriterWriteComment(writer, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteComment", @@ -44573,13 +45581,13 @@ test_xmlTextWriterWriteDTD(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD */ + const xmlChar * name; /* the name of the DTD */ int n_name; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; - xmlChar * subset; /* string content of the DTD */ + const xmlChar * subset; /* string content of the DTD */ int n_subset; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44594,14 +45602,14 @@ test_xmlTextWriterWriteDTD(void) { sysid = gen_const_xmlChar_ptr(n_sysid, 3); subset = gen_const_xmlChar_ptr(n_subset, 4); - ret_val = xmlTextWriterWriteDTD(writer, (const xmlChar *)name, (const xmlChar *)pubid, (const xmlChar *)sysid, (const xmlChar *)subset); + ret_val = xmlTextWriterWriteDTD(writer, name, pubid, sysid, subset); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 2); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 3); - des_const_xmlChar_ptr(n_subset, (const xmlChar *)subset, 4); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_pubid, pubid, 2); + des_const_xmlChar_ptr(n_sysid, sysid, 3); + des_const_xmlChar_ptr(n_subset, subset, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTD", @@ -44635,9 +45643,9 @@ test_xmlTextWriterWriteDTDAttlist(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD ATTLIST */ + const xmlChar * name; /* the name of the DTD ATTLIST */ int n_name; - xmlChar * content; /* content of the ATTLIST */ + const xmlChar * content; /* content of the ATTLIST */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44648,12 +45656,12 @@ test_xmlTextWriterWriteDTDAttlist(void) { name = gen_const_xmlChar_ptr(n_name, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlTextWriterWriteDTDAttlist(writer, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlTextWriterWriteDTDAttlist(writer, name, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDAttlist", @@ -44683,9 +45691,9 @@ test_xmlTextWriterWriteDTDElement(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the DTD element */ + const xmlChar * name; /* the name of the DTD element */ int n_name; - xmlChar * content; /* content of the element */ + const xmlChar * content; /* content of the element */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44696,12 +45704,12 @@ test_xmlTextWriterWriteDTDElement(void) { name = gen_const_xmlChar_ptr(n_name, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlTextWriterWriteDTDElement(writer, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlTextWriterWriteDTDElement(writer, name, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDElement", @@ -44733,15 +45741,15 @@ test_xmlTextWriterWriteDTDEntity(void) { int n_writer; int pe; /* TRUE if this is a parameter entity, FALSE if not */ int n_pe; - xmlChar * name; /* the name of the DTD entity */ + const xmlChar * name; /* the name of the DTD entity */ int n_name; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; - xmlChar * ndataid; /* the xml notation name. */ + const xmlChar * ndataid; /* the xml notation name. */ int n_ndataid; - xmlChar * content; /* content of the entity */ + const xmlChar * content; /* content of the entity */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44760,16 +45768,16 @@ test_xmlTextWriterWriteDTDEntity(void) { ndataid = gen_const_xmlChar_ptr(n_ndataid, 5); content = gen_const_xmlChar_ptr(n_content, 6); - ret_val = xmlTextWriterWriteDTDEntity(writer, pe, (const xmlChar *)name, (const xmlChar *)pubid, (const xmlChar *)sysid, (const xmlChar *)ndataid, (const xmlChar *)content); + ret_val = xmlTextWriterWriteDTDEntity(writer, pe, name, pubid, sysid, ndataid, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); des_int(n_pe, pe, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 3); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 4); - des_const_xmlChar_ptr(n_ndataid, (const xmlChar *)ndataid, 5); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 6); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_pubid, pubid, 3); + des_const_xmlChar_ptr(n_sysid, sysid, 4); + des_const_xmlChar_ptr(n_ndataid, ndataid, 5); + des_const_xmlChar_ptr(n_content, content, 6); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDEntity", @@ -44809,13 +45817,13 @@ test_xmlTextWriterWriteDTDExternalEntity(void) { int n_writer; int pe; /* TRUE if this is a parameter entity, FALSE if not */ int n_pe; - xmlChar * name; /* the name of the DTD entity */ + const xmlChar * name; /* the name of the DTD entity */ int n_name; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; - xmlChar * ndataid; /* the xml notation name. */ + const xmlChar * ndataid; /* the xml notation name. */ int n_ndataid; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44832,15 +45840,15 @@ test_xmlTextWriterWriteDTDExternalEntity(void) { sysid = gen_const_xmlChar_ptr(n_sysid, 4); ndataid = gen_const_xmlChar_ptr(n_ndataid, 5); - ret_val = xmlTextWriterWriteDTDExternalEntity(writer, pe, (const xmlChar *)name, (const xmlChar *)pubid, (const xmlChar *)sysid, (const xmlChar *)ndataid); + ret_val = xmlTextWriterWriteDTDExternalEntity(writer, pe, name, pubid, sysid, ndataid); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); des_int(n_pe, pe, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 3); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 4); - des_const_xmlChar_ptr(n_ndataid, (const xmlChar *)ndataid, 5); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_pubid, pubid, 3); + des_const_xmlChar_ptr(n_sysid, sysid, 4); + des_const_xmlChar_ptr(n_ndataid, ndataid, 5); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDExternalEntity", @@ -44876,11 +45884,11 @@ test_xmlTextWriterWriteDTDExternalEntityContents(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; - xmlChar * ndataid; /* the xml notation name. */ + const xmlChar * ndataid; /* the xml notation name. */ int n_ndataid; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44893,13 +45901,13 @@ test_xmlTextWriterWriteDTDExternalEntityContents(void) { sysid = gen_const_xmlChar_ptr(n_sysid, 2); ndataid = gen_const_xmlChar_ptr(n_ndataid, 3); - ret_val = xmlTextWriterWriteDTDExternalEntityContents(writer, (const xmlChar *)pubid, (const xmlChar *)sysid, (const xmlChar *)ndataid); + ret_val = xmlTextWriterWriteDTDExternalEntityContents(writer, pubid, sysid, ndataid); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 1); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 2); - des_const_xmlChar_ptr(n_ndataid, (const xmlChar *)ndataid, 3); + des_const_xmlChar_ptr(n_pubid, pubid, 1); + des_const_xmlChar_ptr(n_sysid, sysid, 2); + des_const_xmlChar_ptr(n_ndataid, ndataid, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDExternalEntityContents", @@ -44933,9 +45941,9 @@ test_xmlTextWriterWriteDTDInternalEntity(void) { int n_writer; int pe; /* TRUE if this is a parameter entity, FALSE if not */ int n_pe; - xmlChar * name; /* the name of the DTD entity */ + const xmlChar * name; /* the name of the DTD entity */ int n_name; - xmlChar * content; /* content of the entity */ + const xmlChar * content; /* content of the entity */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -44948,13 +45956,13 @@ test_xmlTextWriterWriteDTDInternalEntity(void) { name = gen_const_xmlChar_ptr(n_name, 2); content = gen_const_xmlChar_ptr(n_content, 3); - ret_val = xmlTextWriterWriteDTDInternalEntity(writer, pe, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlTextWriterWriteDTDInternalEntity(writer, pe, name, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); des_int(n_pe, pe, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 3); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_content, content, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDInternalEntity", @@ -44986,11 +45994,11 @@ test_xmlTextWriterWriteDTDNotation(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* the name of the xml notation */ + const xmlChar * name; /* the name of the xml notation */ int n_name; - xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ + const xmlChar * pubid; /* the public identifier, which is an alternative to the system identifier */ int n_pubid; - xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ + const xmlChar * sysid; /* the system identifier, which is the URI of the DTD */ int n_sysid; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45003,13 +46011,13 @@ test_xmlTextWriterWriteDTDNotation(void) { pubid = gen_const_xmlChar_ptr(n_pubid, 2); sysid = gen_const_xmlChar_ptr(n_sysid, 3); - ret_val = xmlTextWriterWriteDTDNotation(writer, (const xmlChar *)name, (const xmlChar *)pubid, (const xmlChar *)sysid); + ret_val = xmlTextWriterWriteDTDNotation(writer, name, pubid, sysid); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_pubid, (const xmlChar *)pubid, 2); - des_const_xmlChar_ptr(n_sysid, (const xmlChar *)sysid, 3); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_pubid, pubid, 2); + des_const_xmlChar_ptr(n_sysid, sysid, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteDTDNotation", @@ -45041,9 +46049,9 @@ test_xmlTextWriterWriteElement(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * name; /* element name */ + const xmlChar * name; /* element name */ int n_name; - xmlChar * content; /* element content */ + const xmlChar * content; /* element content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45054,12 +46062,12 @@ test_xmlTextWriterWriteElement(void) { name = gen_const_xmlChar_ptr(n_name, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlTextWriterWriteElement(writer, (const xmlChar *)name, (const xmlChar *)content); + ret_val = xmlTextWriterWriteElement(writer, name, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteElement", @@ -45089,13 +46097,13 @@ test_xmlTextWriterWriteElementNS(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * prefix; /* namespace prefix */ + const xmlChar * prefix; /* namespace prefix */ int n_prefix; - xmlChar * name; /* element local name */ + const xmlChar * name; /* element local name */ int n_name; - xmlChar * namespaceURI; /* namespace URI */ + const xmlChar * namespaceURI; /* namespace URI */ int n_namespaceURI; - xmlChar * content; /* element content */ + const xmlChar * content; /* element content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45110,14 +46118,14 @@ test_xmlTextWriterWriteElementNS(void) { namespaceURI = gen_const_xmlChar_ptr(n_namespaceURI, 3); content = gen_const_xmlChar_ptr(n_content, 4); - ret_val = xmlTextWriterWriteElementNS(writer, (const xmlChar *)prefix, (const xmlChar *)name, (const xmlChar *)namespaceURI, (const xmlChar *)content); + ret_val = xmlTextWriterWriteElementNS(writer, prefix, name, namespaceURI, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 2); - des_const_xmlChar_ptr(n_namespaceURI, (const xmlChar *)namespaceURI, 3); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 4); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_name, name, 2); + des_const_xmlChar_ptr(n_namespaceURI, namespaceURI, 3); + des_const_xmlChar_ptr(n_content, content, 4); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteElementNS", @@ -45281,9 +46289,9 @@ test_xmlTextWriterWritePI(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * target; /* PI target */ + const xmlChar * target; /* PI target */ int n_target; - xmlChar * content; /* PI content */ + const xmlChar * content; /* PI content */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45294,12 +46302,12 @@ test_xmlTextWriterWritePI(void) { target = gen_const_xmlChar_ptr(n_target, 1); content = gen_const_xmlChar_ptr(n_content, 2); - ret_val = xmlTextWriterWritePI(writer, (const xmlChar *)target, (const xmlChar *)content); + ret_val = xmlTextWriterWritePI(writer, target, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_target, (const xmlChar *)target, 1); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 2); + des_const_xmlChar_ptr(n_target, target, 1); + des_const_xmlChar_ptr(n_content, content, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWritePI", @@ -45329,7 +46337,7 @@ test_xmlTextWriterWriteRaw(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * content; /* text string */ + const xmlChar * content; /* text string */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45338,11 +46346,11 @@ test_xmlTextWriterWriteRaw(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlTextWriterWriteRaw(writer, (const xmlChar *)content); + ret_val = xmlTextWriterWriteRaw(writer, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteRaw", @@ -45370,7 +46378,7 @@ test_xmlTextWriterWriteRawLen(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * content; /* text string */ + const xmlChar * content; /* text string */ int n_content; int len; /* length of the text string */ int n_len; @@ -45386,11 +46394,11 @@ test_xmlTextWriterWriteRawLen(void) { (len > xmlStrlen(BAD_CAST content))) len = 0; - ret_val = xmlTextWriterWriteRawLen(writer, (const xmlChar *)content, len); + ret_val = xmlTextWriterWriteRawLen(writer, content, len); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); des_int(n_len, len, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -45421,7 +46429,7 @@ test_xmlTextWriterWriteString(void) { int ret_val; xmlTextWriterPtr writer; /* the xmlTextWriterPtr */ int n_writer; - xmlChar * content; /* text string */ + const xmlChar * content; /* text string */ int n_content; for (n_writer = 0;n_writer < gen_nb_xmlTextWriterPtr;n_writer++) { @@ -45430,11 +46438,11 @@ test_xmlTextWriterWriteString(void) { writer = gen_xmlTextWriterPtr(n_writer, 0); content = gen_const_xmlChar_ptr(n_content, 1); - ret_val = xmlTextWriterWriteString(writer, (const xmlChar *)content); + ret_val = xmlTextWriterWriteString(writer, content); desret_int(ret_val); call_tests++; des_xmlTextWriterPtr(n_writer, writer, 0); - des_const_xmlChar_ptr(n_content, (const xmlChar *)content, 1); + des_const_xmlChar_ptr(n_content, content, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlTextWriterWriteString", @@ -45586,12 +46594,13 @@ static int test_xmlwriter(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xmlwriter : 52 of 80 functions ...\n"); + if (quiet == 0) printf("Testing xmlwriter : 53 of 81 functions ...\n"); test_ret += test_xmlNewTextWriter(); test_ret += test_xmlNewTextWriterFilename(); test_ret += test_xmlNewTextWriterMemory(); test_ret += test_xmlNewTextWriterPushParser(); test_ret += test_xmlNewTextWriterTree(); + test_ret += test_xmlTextWriterClose(); test_ret += test_xmlTextWriterEndAttribute(); test_ret += test_xmlTextWriterEndCDATA(); test_ret += test_xmlTextWriterEndComment(); @@ -45984,17 +46993,17 @@ test_xmlXPathCastStringToBoolean(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; int ret_val; - xmlChar * val; /* a string */ + const xmlChar * val; /* a string */ int n_val; for (n_val = 0;n_val < gen_nb_const_xmlChar_ptr;n_val++) { mem_base = xmlMemBlocks(); val = gen_const_xmlChar_ptr(n_val, 0); - ret_val = xmlXPathCastStringToBoolean((const xmlChar *)val); + ret_val = xmlXPathCastStringToBoolean(val); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_val, (const xmlChar *)val, 0); + des_const_xmlChar_ptr(n_val, val, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathCastStringToBoolean", @@ -46018,17 +47027,17 @@ test_xmlXPathCastStringToNumber(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; double ret_val; - xmlChar * val; /* a string */ + const xmlChar * val; /* a string */ int n_val; for (n_val = 0;n_val < gen_nb_const_xmlChar_ptr;n_val++) { mem_base = xmlMemBlocks(); val = gen_const_xmlChar_ptr(n_val, 0); - ret_val = xmlXPathCastStringToNumber((const xmlChar *)val); + ret_val = xmlXPathCastStringToNumber(val); desret_double(ret_val); call_tests++; - des_const_xmlChar_ptr(n_val, (const xmlChar *)val, 0); + des_const_xmlChar_ptr(n_val, val, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathCastStringToNumber", @@ -46471,7 +47480,7 @@ test_xmlXPathEval(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; xmlXPathObjectPtr ret_val; - xmlChar * str; /* the XPath expression */ + const xmlChar * str; /* the XPath expression */ int n_str; xmlXPathContextPtr ctx; /* the XPath context */ int n_ctx; @@ -46482,10 +47491,10 @@ test_xmlXPathEval(void) { str = gen_const_xmlChar_ptr(n_str, 0); ctx = gen_xmlXPathContextPtr(n_ctx, 1); - ret_val = xmlXPathEval((const xmlChar *)str, ctx); + ret_val = xmlXPathEval(str, ctx); desret_xmlXPathObjectPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); des_xmlXPathContextPtr(n_ctx, ctx, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -46512,7 +47521,7 @@ test_xmlXPathEvalExpression(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; xmlXPathObjectPtr ret_val; - xmlChar * str; /* the XPath expression */ + const xmlChar * str; /* the XPath expression */ int n_str; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; @@ -46523,10 +47532,10 @@ test_xmlXPathEvalExpression(void) { str = gen_const_xmlChar_ptr(n_str, 0); ctxt = gen_xmlXPathContextPtr(n_ctxt, 1); - ret_val = xmlXPathEvalExpression((const xmlChar *)str, ctxt); + ret_val = xmlXPathEvalExpression(str, ctxt); desret_xmlXPathObjectPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); des_xmlXPathContextPtr(n_ctxt, ctxt, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -46699,7 +47708,7 @@ test_xmlXPathNodeEval(void) { xmlXPathObjectPtr ret_val; xmlNodePtr node; /* the node to to use as the context node */ int n_node; - xmlChar * str; /* the XPath expression */ + const xmlChar * str; /* the XPath expression */ int n_str; xmlXPathContextPtr ctx; /* the XPath context */ int n_ctx; @@ -46712,11 +47721,11 @@ test_xmlXPathNodeEval(void) { str = gen_const_xmlChar_ptr(n_str, 1); ctx = gen_xmlXPathContextPtr(n_ctx, 2); - ret_val = xmlXPathNodeEval(node, (const xmlChar *)str, ctx); + ret_val = xmlXPathNodeEval(node, str, ctx); desret_xmlXPathObjectPtr(ret_val); call_tests++; des_xmlNodePtr(n_node, node, 0); - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1); + des_const_xmlChar_ptr(n_str, str, 1); des_xmlXPathContextPtr(n_ctx, ctx, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -46880,11 +47889,21 @@ test_xmlXPathSetContextNode(void) { return(test_ret); } + +static int +test_xmlXPathSetErrorHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + static int test_xpath(void) { int test_ret = 0; - if (quiet == 0) printf("Testing xpath : 32 of 40 functions ...\n"); + if (quiet == 0) printf("Testing xpath : 32 of 41 functions ...\n"); test_ret += test_xmlXPathCastBooleanToNumber(); test_ret += test_xmlXPathCastBooleanToString(); test_ret += test_xmlXPathCastNodeSetToBoolean(); @@ -46920,6 +47939,7 @@ test_xpath(void) { test_ret += test_xmlXPathObjectCopy(); test_ret += test_xmlXPathOrderDocElems(); test_ret += test_xmlXPathSetContextNode(); + test_ret += test_xmlXPathSetErrorHandler(); if (test_ret != 0) printf("Module xpath: %d errors\n", test_ret); @@ -47558,26 +48578,26 @@ test_xmlXPathErr(void) { int mem_base; xmlXPathParserContextPtr ctxt; /* a XPath parser context */ int n_ctxt; - int error; /* the error code */ - int n_error; + int code; /* the error code */ + int n_code; for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathParserContextPtr;n_ctxt++) { - for (n_error = 0;n_error < gen_nb_int;n_error++) { + for (n_code = 0;n_code < gen_nb_int;n_code++) { mem_base = xmlMemBlocks(); ctxt = gen_xmlXPathParserContextPtr(n_ctxt, 0); - error = gen_int(n_error, 1); + code = gen_int(n_code, 1); - xmlXPathErr(ctxt, error); + xmlXPathErr(ctxt, code); call_tests++; des_xmlXPathParserContextPtr(n_ctxt, ctxt, 0); - des_int(n_error, error, 1); + des_int(n_code, code, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathErr", xmlMemBlocks() - mem_base); test_ret++; printf(" %d", n_ctxt); - printf(" %d", n_error); + printf(" %d", n_code); printf("\n"); } } @@ -47888,17 +48908,17 @@ test_xmlXPathIsNodeType(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; int ret_val; - xmlChar * name; /* a name string */ + const xmlChar * name; /* a name string */ int n_name; for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) { mem_base = xmlMemBlocks(); name = gen_const_xmlChar_ptr(n_name, 0); - ret_val = xmlXPathIsNodeType((const xmlChar *)name); + ret_val = xmlXPathIsNodeType(name); desret_int(ret_val); call_tests++; - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 0); + des_const_xmlChar_ptr(n_name, name, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathIsNodeType", @@ -48258,17 +49278,17 @@ test_xmlXPathNewCString(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; xmlXPathObjectPtr ret_val; - char * val; /* the char * value */ + const char * val; /* the char * value */ int n_val; for (n_val = 0;n_val < gen_nb_const_char_ptr;n_val++) { mem_base = xmlMemBlocks(); val = gen_const_char_ptr(n_val, 0); - ret_val = xmlXPathNewCString((const char *)val); + ret_val = xmlXPathNewCString(val); desret_xmlXPathObjectPtr(ret_val); call_tests++; - des_const_char_ptr(n_val, (const char *)val, 0); + des_const_char_ptr(n_val, val, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathNewCString", @@ -48404,17 +49424,17 @@ test_xmlXPathNewString(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; xmlXPathObjectPtr ret_val; - xmlChar * val; /* the xmlChar * value */ + const xmlChar * val; /* the xmlChar * value */ int n_val; for (n_val = 0;n_val < gen_nb_const_xmlChar_ptr;n_val++) { mem_base = xmlMemBlocks(); val = gen_const_xmlChar_ptr(n_val, 0); - ret_val = xmlXPathNewString((const xmlChar *)val); + ret_val = xmlXPathNewString(val); desret_xmlXPathObjectPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_val, (const xmlChar *)val, 0); + des_const_xmlChar_ptr(n_val, val, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathNewString", @@ -49571,7 +50591,7 @@ test_xmlXPathNsLookup(void) { const xmlChar * ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * prefix; /* the namespace prefix value */ + const xmlChar * prefix; /* the namespace prefix value */ int n_prefix; for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathContextPtr;n_ctxt++) { @@ -49580,11 +50600,11 @@ test_xmlXPathNsLookup(void) { ctxt = gen_xmlXPathContextPtr(n_ctxt, 0); prefix = gen_const_xmlChar_ptr(n_prefix, 1); - ret_val = xmlXPathNsLookup(ctxt, (const xmlChar *)prefix); + ret_val = xmlXPathNsLookup(ctxt, prefix); desret_const_xmlChar_ptr(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); + des_const_xmlChar_ptr(n_prefix, prefix, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathNsLookup", @@ -49990,9 +51010,9 @@ test_xmlXPathRegisterNs(void) { int ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * prefix; /* the namespace prefix cannot be NULL or empty string */ + const xmlChar * prefix; /* the namespace prefix cannot be NULL or empty string */ int n_prefix; - xmlChar * ns_uri; /* the namespace name */ + const xmlChar * ns_uri; /* the namespace name */ int n_ns_uri; for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathContextPtr;n_ctxt++) { @@ -50003,12 +51023,12 @@ test_xmlXPathRegisterNs(void) { prefix = gen_const_xmlChar_ptr(n_prefix, 1); ns_uri = gen_const_xmlChar_ptr(n_ns_uri, 2); - ret_val = xmlXPathRegisterNs(ctxt, (const xmlChar *)prefix, (const xmlChar *)ns_uri); + ret_val = xmlXPathRegisterNs(ctxt, prefix, ns_uri); desret_int(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_prefix, (const xmlChar *)prefix, 1); - des_const_xmlChar_ptr(n_ns_uri, (const xmlChar *)ns_uri, 2); + des_const_xmlChar_ptr(n_prefix, prefix, 1); + des_const_xmlChar_ptr(n_ns_uri, ns_uri, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathRegisterNs", @@ -50038,7 +51058,7 @@ test_xmlXPathRegisterVariable(void) { int ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * name; /* the variable name */ + const xmlChar * name; /* the variable name */ int n_name; xmlXPathObjectPtr value; /* the variable value or NULL */ int n_value; @@ -50051,11 +51071,11 @@ test_xmlXPathRegisterVariable(void) { name = gen_const_xmlChar_ptr(n_name, 1); value = gen_xmlXPathObjectPtr(n_value, 2); - ret_val = xmlXPathRegisterVariable(ctxt, (const xmlChar *)name, value); + ret_val = xmlXPathRegisterVariable(ctxt, name, value); desret_int(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); des_xmlXPathObjectPtr(n_value, value, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -50096,9 +51116,9 @@ test_xmlXPathRegisterVariableNS(void) { int ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * name; /* the variable name */ + const xmlChar * name; /* the variable name */ int n_name; - xmlChar * ns_uri; /* the variable namespace URI */ + const xmlChar * ns_uri; /* the variable namespace URI */ int n_ns_uri; xmlXPathObjectPtr value; /* the variable value or NULL */ int n_value; @@ -50113,12 +51133,12 @@ test_xmlXPathRegisterVariableNS(void) { ns_uri = gen_const_xmlChar_ptr(n_ns_uri, 2); value = gen_xmlXPathObjectPtr(n_value, 3); - ret_val = xmlXPathRegisterVariableNS(ctxt, (const xmlChar *)name, (const xmlChar *)ns_uri, value); + ret_val = xmlXPathRegisterVariableNS(ctxt, name, ns_uri, value); desret_int(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ns_uri, (const xmlChar *)ns_uri, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ns_uri, ns_uri, 2); des_xmlXPathObjectPtr(n_value, value, 3); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { @@ -50355,17 +51375,17 @@ test_xmlXPathStringEvalNumber(void) { #if defined(LIBXML_XPATH_ENABLED) int mem_base; double ret_val; - xmlChar * str; /* A string to scan */ + const xmlChar * str; /* A string to scan */ int n_str; for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) { mem_base = xmlMemBlocks(); str = gen_const_xmlChar_ptr(n_str, 0); - ret_val = xmlXPathStringEvalNumber((const xmlChar *)str); + ret_val = xmlXPathStringEvalNumber(str); desret_double(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathStringEvalNumber", @@ -50849,7 +51869,7 @@ test_xmlXPathVariableLookup(void) { xmlXPathObjectPtr ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * name; /* the variable name */ + const xmlChar * name; /* the variable name */ int n_name; for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathContextPtr;n_ctxt++) { @@ -50858,11 +51878,11 @@ test_xmlXPathVariableLookup(void) { ctxt = gen_xmlXPathContextPtr(n_ctxt, 0); name = gen_const_xmlChar_ptr(n_name, 1); - ret_val = xmlXPathVariableLookup(ctxt, (const xmlChar *)name); + ret_val = xmlXPathVariableLookup(ctxt, name); desret_xmlXPathObjectPtr(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); + des_const_xmlChar_ptr(n_name, name, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathVariableLookup", @@ -50890,9 +51910,9 @@ test_xmlXPathVariableLookupNS(void) { xmlXPathObjectPtr ret_val; xmlXPathContextPtr ctxt; /* the XPath context */ int n_ctxt; - xmlChar * name; /* the variable name */ + const xmlChar * name; /* the variable name */ int n_name; - xmlChar * ns_uri; /* the variable namespace URI */ + const xmlChar * ns_uri; /* the variable namespace URI */ int n_ns_uri; for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathContextPtr;n_ctxt++) { @@ -50903,12 +51923,12 @@ test_xmlXPathVariableLookupNS(void) { name = gen_const_xmlChar_ptr(n_name, 1); ns_uri = gen_const_xmlChar_ptr(n_ns_uri, 2); - ret_val = xmlXPathVariableLookupNS(ctxt, (const xmlChar *)name, (const xmlChar *)ns_uri); + ret_val = xmlXPathVariableLookupNS(ctxt, name, ns_uri); desret_xmlXPathObjectPtr(ret_val); call_tests++; des_xmlXPathContextPtr(n_ctxt, ctxt, 0); - des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1); - des_const_xmlChar_ptr(n_ns_uri, (const xmlChar *)ns_uri, 2); + des_const_xmlChar_ptr(n_name, name, 1); + des_const_xmlChar_ptr(n_ns_uri, ns_uri, 2); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { printf("Leak of %d blocks found in xmlXPathVariableLookupNS", @@ -51248,7 +52268,7 @@ test_xmlXPtrEval(void) { #if defined(LIBXML_XPTR_ENABLED) int mem_base; xmlXPathObjectPtr ret_val; - xmlChar * str; /* the XPointer expression */ + const xmlChar * str; /* the XPointer expression */ int n_str; xmlXPathContextPtr ctx; /* the XPointer context */ int n_ctx; @@ -51259,10 +52279,10 @@ test_xmlXPtrEval(void) { str = gen_const_xmlChar_ptr(n_str, 0); ctx = gen_xmlXPathContextPtr(n_ctx, 1); - ret_val = xmlXPtrEval((const xmlChar *)str, ctx); + ret_val = xmlXPtrEval(str, ctx); desret_xmlXPathObjectPtr(ret_val); call_tests++; - des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0); + des_const_xmlChar_ptr(n_str, str, 0); des_xmlXPathContextPtr(n_ctx, ctx, 1); xmlResetLastError(); if (mem_base != xmlMemBlocks()) { diff --git a/testchar.c b/testchar.c index f4b2f4f..13887cd 100644 --- a/testchar.c +++ b/testchar.c @@ -310,9 +310,9 @@ static int testCharRangeByte1(xmlParserCtxtPtr ctxt) { c = testCurrentChar(ctxt, &len); if (c < 0) continue; - if ((i == 0) || (i >= 0x80)) { + if (i >= 0x80) { /* we must see an error there */ - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Byte 0x%02X\n", i); return(1); @@ -349,7 +349,7 @@ static int testCharRangeByte2(xmlParserCtxtPtr ctxt) { /* if first bit of first char is set, then second bit must too */ if ((i & 0x80) && ((i & 0x40) == 0)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X\n", i, j); @@ -362,7 +362,7 @@ static int testCharRangeByte2(xmlParserCtxtPtr ctxt) { * bits must be 10 */ else if ((i & 0x80) && ((j & 0xC0) != 0x80)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X: %d\n", i, j, c); @@ -375,7 +375,7 @@ static int testCharRangeByte2(xmlParserCtxtPtr ctxt) { * than 0x80, i.e. one of bits 5 to 1 of i must be set */ else if ((i & 0x80) && ((i & 0x1E) == 0)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X: %d\n", i, j, c); @@ -388,7 +388,7 @@ static int testCharRangeByte2(xmlParserCtxtPtr ctxt) { * at least 3 bytes, but we give only 2 ! */ else if ((i & 0xE0) == 0xE0) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x00\n", i, j); @@ -446,7 +446,7 @@ static int testCharRangeByte3(xmlParserCtxtPtr ctxt) { * at least 4 bytes, but we give only 3 ! */ if ((i & 0xF0) == 0xF0) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", i, j, K, data[3]); @@ -458,7 +458,7 @@ static int testCharRangeByte3(xmlParserCtxtPtr ctxt) { * The second and the third bytes must start with 10 */ else if (((j & 0xC0) != 0x80) || ((K & 0xC0) != 0x80)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X\n", i, j, K); @@ -472,7 +472,7 @@ static int testCharRangeByte3(xmlParserCtxtPtr ctxt) { * the 6th byte of data[1] must be set */ else if (((i & 0xF) == 0) && ((j & 0x20) == 0)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X\n", i, j, K); @@ -484,7 +484,7 @@ static int testCharRangeByte3(xmlParserCtxtPtr ctxt) { * There are values that are not allowed in UTF-8 */ else if ((value > 0xD7FF) && (value <0xE000)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char 0x%04X for Bytes 0x%02X 0x%02X 0x%02X\n", value, i, j, K); @@ -548,7 +548,7 @@ static int testCharRangeByte4(xmlParserCtxtPtr ctxt) { * at least 5 bytes, but we give only 4 ! */ if ((i & 0xF8) == 0xF8) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", i, j, K, data[3]); @@ -561,7 +561,7 @@ static int testCharRangeByte4(xmlParserCtxtPtr ctxt) { */ else if (((j & 0xC0) != 0x80) || ((K & 0xC0) != 0x80) || ((L & 0xC0) != 0x80)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", i, j, K, L); @@ -575,7 +575,7 @@ static int testCharRangeByte4(xmlParserCtxtPtr ctxt) { * the 6 or 5th byte of j must be set */ else if (((i & 0x7) == 0) && ((j & 0x30) == 0)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", i, j, K, L); @@ -588,7 +588,7 @@ static int testCharRangeByte4(xmlParserCtxtPtr ctxt) { */ else if (((value > 0xD7FF) && (value < 0xE000)) || (value > 0x10FFFF)) { - if (lastError != XML_ERR_INVALID_CHAR) { + if (lastError != XML_ERR_INVALID_ENCODING) { fprintf(stderr, "Failed to detect invalid char 0x%04X for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n", value, i, j, K, L); diff --git a/testdict.c b/testdict.c index ffbbc94..94f18c2 100644 --- a/testdict.c +++ b/testdict.c @@ -7,9 +7,14 @@ /**** dictionary tests ****/ #ifdef __clang__ - #define ATTRIBUTE_NO_SANITIZE_INTEGER \ - __attribute__ ((no_sanitize("unsigned-integer-overflow"))) \ - __attribute__ ((no_sanitize("unsigned-shift-base"))) + #if __clang_major__ >= 12 + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + __attribute__ ((no_sanitize("unsigned-integer-overflow"))) \ + __attribute__ ((no_sanitize("unsigned-shift-base"))) + #else + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + __attribute__ ((no_sanitize("unsigned-integer-overflow"))) + #endif #else #define ATTRIBUTE_NO_SANITIZE_INTEGER #endif diff --git a/testlimits.c b/testlimits.c index 78d62fb..7144b9a 100644 --- a/testlimits.c +++ b/testlimits.c @@ -389,279 +389,11 @@ testExternalEntityLoader(const char *URL, const char *ID, return(ret); } -/* - * Trapping the error messages at the generic level to grab the equivalent of - * stderr messages on CLI tools. - */ -static char testErrors[32769]; -static int testErrorsSize = 0; - -static void -channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { - va_list args; - int res; - - if (testErrorsSize >= 32768) - return; - va_start(args, msg); - res = vsnprintf(&testErrors[testErrorsSize], - 32768 - testErrorsSize, - msg, args); - va_end(args); - if (testErrorsSize + res >= 32768) { - /* buffer is full */ - testErrorsSize = 32768; - testErrors[testErrorsSize] = 0; - } else { - testErrorsSize += res; - } - testErrors[testErrorsSize] = 0; -} - -/** - * xmlParserPrintFileContext: - * @input: an xmlParserInputPtr input - * - * Displays current context within the input content for error tracking - */ - -static void -xmlParserPrintFileContextInternal(xmlParserInputPtr input , - xmlGenericErrorFunc chanl, void *data ) { - const xmlChar *cur, *base; - unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ - xmlChar content[81]; /* space for 80 chars + line terminator */ - xmlChar *ctnt; - - if (input == NULL) return; - cur = input->cur; - base = input->base; - /* skip backwards over any end-of-lines */ - while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { - cur--; - } - n = 0; - /* search backwards for beginning-of-line (to max buff size) */ - while ((n++ < (sizeof(content)-1)) && (cur > base) && - (*(cur) != '\n') && (*(cur) != '\r')) - cur--; - if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; - /* calculate the error position in terms of the current position */ - col = input->cur - cur; - /* search forward for end-of-line (to max buff size) */ - n = 0; - ctnt = content; - /* copy selected text to our buffer */ - while ((*cur != 0) && (*(cur) != '\n') && - (*(cur) != '\r') && (n < sizeof(content)-1)) { - *ctnt++ = *cur++; - n++; - } - *ctnt = 0; - /* print out the selected text */ - chanl(data ,"%s\n", content); - /* create blank line with problem pointer */ - n = 0; - ctnt = content; - /* (leave buffer space for pointer + line terminator) */ - while ((nfile; - line = err->line; - code = err->code; - domain = err->domain; - level = err->level; - node = err->node; - if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || - (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || - (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { - ctxt = err->ctxt; - } - str = err->message; - - if (code == XML_ERR_OK) - return; - - if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) - name = node->name; - - /* - * Maintain the compatibility with the legacy error handling - */ - if (ctxt != NULL) { - input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && - (ctxt->inputNr > 1)) { - cur = input; - input = ctxt->inputTab[ctxt->inputNr - 2]; - } - if (input != NULL) { - if (input->filename) - channel(data, "%s:%d: ", input->filename, input->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", input->line); - } - } else { - if (file != NULL) - channel(data, "%s:%d: ", file, line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", line); - } - if (name != NULL) { - channel(data, "element %s: ", name); - } - if (code == XML_ERR_OK) - return; - switch (domain) { - case XML_FROM_PARSER: - channel(data, "parser "); - break; - case XML_FROM_NAMESPACE: - channel(data, "namespace "); - break; - case XML_FROM_DTD: - case XML_FROM_VALID: - channel(data, "validity "); - break; - case XML_FROM_HTML: - channel(data, "HTML parser "); - break; - case XML_FROM_MEMORY: - channel(data, "memory "); - break; - case XML_FROM_OUTPUT: - channel(data, "output "); - break; - case XML_FROM_IO: - channel(data, "I/O "); - break; - case XML_FROM_XINCLUDE: - channel(data, "XInclude "); - break; - case XML_FROM_XPATH: - channel(data, "XPath "); - break; - case XML_FROM_XPOINTER: - channel(data, "parser "); - break; - case XML_FROM_REGEXP: - channel(data, "regexp "); - break; - case XML_FROM_MODULE: - channel(data, "module "); - break; - case XML_FROM_SCHEMASV: - channel(data, "Schemas validity "); - break; - case XML_FROM_SCHEMASP: - channel(data, "Schemas parser "); - break; - case XML_FROM_RELAXNGP: - channel(data, "Relax-NG parser "); - break; - case XML_FROM_RELAXNGV: - channel(data, "Relax-NG validity "); - break; - case XML_FROM_CATALOG: - channel(data, "Catalog "); - break; - case XML_FROM_C14N: - channel(data, "C14N "); - break; - case XML_FROM_XSLT: - channel(data, "XSLT "); - break; - default: - break; - } - if (code == XML_ERR_OK) - return; - switch (level) { - case XML_ERR_NONE: - channel(data, ": "); - break; - case XML_ERR_WARNING: - channel(data, "warning : "); - break; - case XML_ERR_ERROR: - channel(data, "error : "); - break; - case XML_ERR_FATAL: - channel(data, "error : "); - break; - } - if (code == XML_ERR_OK) - return; - if (str != NULL) { - int len; - len = xmlStrlen((const xmlChar *)str); - if ((len > 0) && (str[len - 1] != '\n')) - channel(data, "%s\n", str); - else - channel(data, "%s", str); - } else { - channel(data, "%s\n", "out of memory error"); - } - if (code == XML_ERR_OK) - return; - - if (ctxt != NULL) { - xmlParserPrintFileContextInternal(input, channel, data); - if (cur != NULL) { - if (cur->filename) - channel(data, "%s:%d: \n", cur->filename, cur->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: \n", cur->line); - xmlParserPrintFileContextInternal(cur, channel, data); - } - } - if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && - (err->int1 < 100) && - (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { - xmlChar buf[150]; - int i; - - channel(data, "%s\n", err->str1); - for (i=0;i < err->int1;i++) - buf[i] = ' '; - buf[i++] = '^'; - buf[i] = 0; - channel(data, "%s\n", buf); - } -} - static void initializeLibxml2(void) { xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); xmlInitParser(); xmlSetExternalEntityLoader(testExternalEntityLoader); - xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); /* * register the new I/O handlers */ @@ -1261,7 +993,7 @@ saxTest(const char *filename, size_t limit, int options, int fail) { fprintf(stderr, "Failed to create parser context\n"); return(1); } - doc = xmlCtxtReadFile(ctxt, filename, NULL, options); + doc = xmlCtxtReadFile(ctxt, filename, NULL, options | XML_PARSE_NOERROR); if (doc != NULL) { fprintf(stderr, "SAX parsing generated a document !\n"); @@ -1308,7 +1040,7 @@ readerTest(const char *filename, size_t limit, int options, int fail) { nb_tests++; maxlen = limit; - reader = xmlReaderForFile(filename , NULL, options); + reader = xmlReaderForFile(filename , NULL, options | XML_PARSE_NOERROR); if (reader == NULL) { fprintf(stderr, "Failed to open '%s' test\n", filename); return(1); diff --git a/testparser.c b/testparser.c index 705e613..d19e9ea 100644 --- a/testparser.c +++ b/testparser.c @@ -5,8 +5,12 @@ */ #include +#include +#include #include +#include + static int testStandaloneWithEncoding(void) { xmlDocPtr doc; @@ -27,6 +31,80 @@ testStandaloneWithEncoding(void) { return err; } +static int +testUnsupportedEncoding(void) { + xmlDocPtr doc; + const xmlError *error; + int err = 0; + + xmlResetLastError(); + + doc = xmlReadDoc(BAD_CAST "", NULL, "#unsupported", + XML_PARSE_NOWARNING); + if (doc == NULL) { + fprintf(stderr, "xmlReadDoc failed with unsupported encoding\n"); + err = 1; + } + xmlFreeDoc(doc); + + error = xmlGetLastError(); + if (error->code != XML_ERR_UNSUPPORTED_ENCODING || + error->level != XML_ERR_WARNING || + strcmp(error->message, "Unsupported encoding: #unsupported\n") != 0) + { + fprintf(stderr, "xmlReadDoc failed to raise correct error\n"); + err = 1; + } + + return err; +} + +static int +testNodeGetContent(void) { + xmlDocPtr doc; + xmlChar *content; + int err = 0; + + doc = xmlReadDoc(BAD_CAST "", NULL, NULL, 0); + xmlAddChild(doc->children, xmlNewReference(doc, BAD_CAST "lt")); + content = xmlNodeGetContent((xmlNodePtr) doc); + if (strcmp((char *) content, "<") != 0) { + fprintf(stderr, "xmlNodeGetContent failed\n"); + err = 1; + } + xmlFree(content); + xmlFreeDoc(doc); + + return err; +} + +#ifdef LIBXML_SAX1_ENABLED +static int +testBalancedChunk(void) { + xmlNodePtr list; + xmlNodePtr elem; + int ret; + int err = 0; + + ret = xmlParseBalancedChunkMemory(NULL, NULL, NULL, 0, + BAD_CAST "start abc end", &list); + + if ((ret != XML_ERR_OK) || + (list == NULL) || + ((elem = list->next) == NULL) || + (elem->type != XML_ELEMENT_NODE) || + (elem->nsDef == NULL) || + (!xmlStrEqual(elem->nsDef->href, XML_XML_NAMESPACE))) { + fprintf(stderr, "xmlParseBalancedChunkMemory failed\n"); + err = 1; + } + + xmlFreeNodeList(list); + + return(err); +} +#endif + #ifdef LIBXML_PUSH_ENABLED static int testHugePush(void) { @@ -85,9 +163,8 @@ testHugeEncodedChunk(void) { return err; } -#endif -#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_PUSH_ENABLED) +#ifdef LIBXML_HTML_ENABLED static int testHtmlPushWithEncoding(void) { htmlParserCtxtPtr ctxt; @@ -116,19 +193,226 @@ testHtmlPushWithEncoding(void) { return err; } #endif +#endif + +#ifdef LIBXML_READER_ENABLED +static int +testReaderEncoding(void) { + xmlBuffer *buf; + xmlTextReader *reader; + xmlChar *xml; + const xmlChar *encoding; + int err = 0; + int i; + + buf = xmlBufferCreate(); + xmlBufferCCat(buf, "\n"); + xmlBufferCCat(buf, ""); + for (i = 0; i < 8192; i++) + xmlBufferCCat(buf, "x"); + xmlBufferCCat(buf, ""); + xml = xmlBufferDetach(buf); + xmlBufferFree(buf); + + reader = xmlReaderForDoc(BAD_CAST xml, NULL, NULL, 0); + xmlTextReaderRead(reader); + encoding = xmlTextReaderConstEncoding(reader); + + if (!xmlStrEqual(encoding, BAD_CAST "ISO-8859-1")) { + fprintf(stderr, "testReaderEncoding failed\n"); + err = 1; + } + + xmlFreeTextReader(reader); + xmlFree(xml); + return err; +} + +static int +testReaderContent(void) { + xmlTextReader *reader; + const xmlChar *xml = BAD_CAST "xyz"; + xmlChar *string; + int err = 0; + + reader = xmlReaderForDoc(xml, NULL, NULL, 0); + xmlTextReaderRead(reader); + + string = xmlTextReaderReadOuterXml(reader); + if (!xmlStrEqual(string, xml)) { + fprintf(stderr, "xmlTextReaderReadOuterXml failed\n"); + err = 1; + } + xmlFree(string); + + string = xmlTextReaderReadInnerXml(reader); + if (!xmlStrEqual(string, BAD_CAST "xyz")) { + fprintf(stderr, "xmlTextReaderReadInnerXml failed\n"); + err = 1; + } + xmlFree(string); + + string = xmlTextReaderReadString(reader); + if (!xmlStrEqual(string, BAD_CAST "xyz")) { + fprintf(stderr, "xmlTextReaderReadString failed\n"); + err = 1; + } + xmlFree(string); + + xmlFreeTextReader(reader); + return err; +} + +#ifdef LIBXML_XINCLUDE_ENABLED +typedef struct { + char *message; + int code; +} testReaderErrorCtxt; + +static void +testReaderError(void *arg, const char *msg, + xmlParserSeverities severity ATTRIBUTE_UNUSED, + xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED) { + testReaderErrorCtxt *ctxt = arg; + + if (ctxt->message != NULL) + xmlFree(ctxt->message); + ctxt->message = xmlMemStrdup(msg); +} + +static void +testStructuredReaderError(void *arg, const xmlError *error) { + testReaderErrorCtxt *ctxt = arg; + + if (ctxt->message != NULL) + xmlFree(ctxt->message); + ctxt->message = xmlMemStrdup(error->message); + ctxt->code = error->code; +} + +static int +testReaderXIncludeError(void) { + /* + * Test whether XInclude errors are reported to the custom error + * handler of a reader. + */ + const char *doc = + "\n" + " \n" + "\n"; + xmlTextReader *reader; + testReaderErrorCtxt errorCtxt; + int err = 0; + + reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE); + xmlTextReaderSetErrorHandler(reader, testReaderError, &errorCtxt); + errorCtxt.message = NULL; + errorCtxt.code = 0; + while (xmlTextReaderRead(reader) > 0) + ; + + if (errorCtxt.message == NULL || + strstr(errorCtxt.message, "href or xpointer") == NULL) { + fprintf(stderr, "xmlTextReaderSetErrorHandler failed\n"); + err = 1; + } + + xmlFree(errorCtxt.message); + xmlFreeTextReader(reader); + + reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE); + xmlTextReaderSetStructuredErrorHandler(reader, testStructuredReaderError, + &errorCtxt); + errorCtxt.message = NULL; + errorCtxt.code = 0; + while (xmlTextReaderRead(reader) > 0) + ; + + if (errorCtxt.code != XML_XINCLUDE_NO_HREF || + errorCtxt.message == NULL || + strstr(errorCtxt.message, "href or xpointer") == NULL) { + fprintf(stderr, "xmlTextReaderSetStructuredErrorHandler failed\n"); + err = 1; + } + + xmlFree(errorCtxt.message); + xmlFreeTextReader(reader); + + return err; +} +#endif +#endif + +#ifdef LIBXML_WRITER_ENABLED +static int +testWriterIOWrite(void *ctxt, const char *data, int len) { + (void) ctxt; + (void) data; + + return len; +} + +static int +testWriterIOClose(void *ctxt) { + (void) ctxt; + + return XML_IO_ENAMETOOLONG; +} + +static int +testWriterClose(void){ + xmlOutputBufferPtr out; + xmlTextWriterPtr writer; + int err = 0; + int result; + + out = xmlOutputBufferCreateIO(testWriterIOWrite, testWriterIOClose, + NULL, NULL); + writer = xmlNewTextWriter(out); + xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + xmlTextWriterStartElement(writer, BAD_CAST "elem"); + xmlTextWriterEndElement(writer); + xmlTextWriterEndDocument(writer); + result = xmlTextWriterClose(writer); + + if (result != XML_IO_ENAMETOOLONG) { + fprintf(stderr, "xmlTextWriterClose reported wrong error %d\n", + result); + err = 1; + } + + xmlFreeTextWriter(writer); + return err; +} +#endif int main(void) { int err = 0; err |= testStandaloneWithEncoding(); + err |= testUnsupportedEncoding(); + err |= testNodeGetContent(); +#ifdef LIBXML_SAX1_ENABLED + err |= testBalancedChunk(); +#endif #ifdef LIBXML_PUSH_ENABLED err |= testHugePush(); err |= testHugeEncodedChunk(); -#endif -#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_PUSH_ENABLED) +#ifdef LIBXML_HTML_ENABLED err |= testHtmlPushWithEncoding(); #endif +#endif +#ifdef LIBXML_READER_ENABLED + err |= testReaderEncoding(); + err |= testReaderContent(); +#ifdef LIBXML_XINCLUDE_ENABLED + err |= testReaderXIncludeError(); +#endif +#endif +#ifdef LIBXML_WRITER_ENABLED + err |= testWriterClose(); +#endif return err; } diff --git a/testrecurse.c b/testrecurse.c index 5290bb2..4e69ccf 100644 --- a/testrecurse.c +++ b/testrecurse.c @@ -359,279 +359,11 @@ testExternalEntityLoader(const char *URL, const char *ID, return(ret); } -/* - * Trapping the error messages at the generic level to grab the equivalent of - * stderr messages on CLI tools. - */ -static char testErrors[32769]; -static int testErrorsSize = 0; - -static void -channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { - va_list args; - int res; - - if (testErrorsSize >= 32768) - return; - va_start(args, msg); - res = vsnprintf(&testErrors[testErrorsSize], - 32768 - testErrorsSize, - msg, args); - va_end(args); - if (testErrorsSize + res >= 32768) { - /* buffer is full */ - testErrorsSize = 32768; - testErrors[testErrorsSize] = 0; - } else { - testErrorsSize += res; - } - testErrors[testErrorsSize] = 0; -} - -/** - * xmlParserPrintFileContext: - * @input: an xmlParserInputPtr input - * - * Displays current context within the input content for error tracking - */ - -static void -xmlParserPrintFileContextInternal(xmlParserInputPtr input , - xmlGenericErrorFunc chanl, void *data ) { - const xmlChar *cur, *base; - unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ - xmlChar content[81]; /* space for 80 chars + line terminator */ - xmlChar *ctnt; - - if (input == NULL) return; - cur = input->cur; - base = input->base; - /* skip backwards over any end-of-lines */ - while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { - cur--; - } - n = 0; - /* search backwards for beginning-of-line (to max buff size) */ - while ((n++ < (sizeof(content)-1)) && (cur > base) && - (*(cur) != '\n') && (*(cur) != '\r')) - cur--; - if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; - /* calculate the error position in terms of the current position */ - col = input->cur - cur; - /* search forward for end-of-line (to max buff size) */ - n = 0; - ctnt = content; - /* copy selected text to our buffer */ - while ((*cur != 0) && (*(cur) != '\n') && - (*(cur) != '\r') && (n < sizeof(content)-1)) { - *ctnt++ = *cur++; - n++; - } - *ctnt = 0; - /* print out the selected text */ - chanl(data ,"%s\n", content); - /* create blank line with problem pointer */ - n = 0; - ctnt = content; - /* (leave buffer space for pointer + line terminator) */ - while ((nfile; - line = err->line; - code = err->code; - domain = err->domain; - level = err->level; - node = err->node; - if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || - (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || - (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { - ctxt = err->ctxt; - } - str = err->message; - - if (code == XML_ERR_OK) - return; - - if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) - name = node->name; - - /* - * Maintain the compatibility with the legacy error handling - */ - if (ctxt != NULL) { - input = ctxt->input; - if ((input != NULL) && (input->filename == NULL) && - (ctxt->inputNr > 1)) { - cur = input; - input = ctxt->inputTab[ctxt->inputNr - 2]; - } - if (input != NULL) { - if (input->filename) - channel(data, "%s:%d: ", input->filename, input->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", input->line); - } - } else { - if (file != NULL) - channel(data, "%s:%d: ", file, line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: ", line); - } - if (name != NULL) { - channel(data, "element %s: ", name); - } - if (code == XML_ERR_OK) - return; - switch (domain) { - case XML_FROM_PARSER: - channel(data, "parser "); - break; - case XML_FROM_NAMESPACE: - channel(data, "namespace "); - break; - case XML_FROM_DTD: - case XML_FROM_VALID: - channel(data, "validity "); - break; - case XML_FROM_HTML: - channel(data, "HTML parser "); - break; - case XML_FROM_MEMORY: - channel(data, "memory "); - break; - case XML_FROM_OUTPUT: - channel(data, "output "); - break; - case XML_FROM_IO: - channel(data, "I/O "); - break; - case XML_FROM_XINCLUDE: - channel(data, "XInclude "); - break; - case XML_FROM_XPATH: - channel(data, "XPath "); - break; - case XML_FROM_XPOINTER: - channel(data, "parser "); - break; - case XML_FROM_REGEXP: - channel(data, "regexp "); - break; - case XML_FROM_MODULE: - channel(data, "module "); - break; - case XML_FROM_SCHEMASV: - channel(data, "Schemas validity "); - break; - case XML_FROM_SCHEMASP: - channel(data, "Schemas parser "); - break; - case XML_FROM_RELAXNGP: - channel(data, "Relax-NG parser "); - break; - case XML_FROM_RELAXNGV: - channel(data, "Relax-NG validity "); - break; - case XML_FROM_CATALOG: - channel(data, "Catalog "); - break; - case XML_FROM_C14N: - channel(data, "C14N "); - break; - case XML_FROM_XSLT: - channel(data, "XSLT "); - break; - default: - break; - } - if (code == XML_ERR_OK) - return; - switch (level) { - case XML_ERR_NONE: - channel(data, ": "); - break; - case XML_ERR_WARNING: - channel(data, "warning : "); - break; - case XML_ERR_ERROR: - channel(data, "error : "); - break; - case XML_ERR_FATAL: - channel(data, "error : "); - break; - } - if (code == XML_ERR_OK) - return; - if (str != NULL) { - int len; - len = xmlStrlen((const xmlChar *)str); - if ((len > 0) && (str[len - 1] != '\n')) - channel(data, "%s\n", str); - else - channel(data, "%s", str); - } else { - channel(data, "%s\n", "out of memory error"); - } - if (code == XML_ERR_OK) - return; - - if (ctxt != NULL) { - xmlParserPrintFileContextInternal(input, channel, data); - if (cur != NULL) { - if (cur->filename) - channel(data, "%s:%d: \n", cur->filename, cur->line); - else if ((line != 0) && (domain == XML_FROM_PARSER)) - channel(data, "Entity: line %d: \n", cur->line); - xmlParserPrintFileContextInternal(cur, channel, data); - } - } - if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && - (err->int1 < 100) && - (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { - xmlChar buf[150]; - int i; - - channel(data, "%s\n", err->str1); - for (i=0;i < err->int1;i++) - buf[i] = ' '; - buf[i++] = '^'; - buf[i] = 0; - channel(data, "%s\n", buf); - } -} - static void initializeLibxml2(void) { xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); xmlInitParser(); xmlSetExternalEntityLoader(testExternalEntityLoader); - xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); /* * register the new I/O handlers */ @@ -693,10 +425,6 @@ static char *resultFilename(const char *filename, const char *out, out = ""; strncpy(suffixbuff,suffix,499); -#ifdef VMS - if(strstr(base,".") && suffixbuff[0]=='.') - suffixbuff[0]='_'; -#endif if (snprintf(res, 499, "%s%s%s", out, base, suffixbuff) >= 499) res[499] = 0; @@ -761,7 +489,7 @@ recursiveDetectTest(const char *filename, * without XML_PARSE_NOENT. The validation result doesn't matter * anyway. */ - int parserOptions = XML_PARSE_DTDVALID; + int parserOptions = XML_PARSE_DTDVALID | XML_PARSE_NOERROR; nb_tests++; @@ -774,7 +502,7 @@ recursiveDetectTest(const char *filename, * base of the test, parse with the old API */ doc = xmlCtxtReadFile(ctxt, filename, NULL, parserOptions); - if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_ENTITY_LOOP)) { + if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_RESOURCE_LIMIT)) { fprintf(stderr, "Failed to detect recursion in %s\n", filename); xmlFreeParserCtxt(ctxt); xmlFreeDoc(doc); @@ -1118,8 +846,6 @@ launchTests(testDescPtr tst) { } else { mem = xmlMemUsed(); extraMemoryFromResolver = 0; - testErrorsSize = 0; - testErrors[0] = 0; res = tst->func(globbuf.gl_pathv[i], result, error, tst->options | XML_PARSE_COMPACT); xmlResetLastError(); @@ -1138,7 +864,6 @@ launchTests(testDescPtr tst) { err++; } } - testErrorsSize = 0; } if (result) free(result); @@ -1147,8 +872,6 @@ launchTests(testDescPtr tst) { } globfree(&globbuf); } else { - testErrorsSize = 0; - testErrors[0] = 0; extraMemoryFromResolver = 0; res = tst->func(NULL, NULL, NULL, tst->options); if (res != 0) { diff --git a/threads.c b/threads.c index 461f4a5..36347c2 100644 --- a/threads.c +++ b/threads.c @@ -30,6 +30,7 @@ #include "private/dict.h" #include "private/enc.h" #include "private/globals.h" +#include "private/io.h" #include "private/memory.h" #include "private/threads.h" #include "private/xpath.h" @@ -498,9 +499,8 @@ xmlGlobalInitMutexLock(void) { if (global_init_lock == NULL) { cs = malloc(sizeof(CRITICAL_SECTION)); if (cs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGlobalInitMutexLock: out of memory\n"); - return; + fprintf(stderr, "libxml2: xmlInitParser: out of memory\n"); + abort(); } InitializeCriticalSection(cs); @@ -583,19 +583,15 @@ xmlInitParser(void) { atexit(xmlCleanupParser); #endif - xmlInitMemoryInternal(); /* Should come second */ + xmlInitRandom(); /* Required by xmlInitGlobalsInternal */ + xmlInitMemoryInternal(); xmlInitGlobalsInternal(); - xmlInitRandom(); xmlInitDictInternal(); xmlInitEncodingInternal(); #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) xmlInitXPathInternal(); #endif - - xmlRegisterDefaultInputCallbacks(); -#ifdef LIBXML_OUTPUT_ENABLED - xmlRegisterDefaultOutputCallbacks(); -#endif /* LIBXML_OUTPUT_ENABLED */ + xmlInitIOCallbacks(); xmlParserInnerInitialized = 1; } @@ -644,11 +640,6 @@ xmlCleanupParser(void) { /* These functions should never call xmlFree. */ - xmlCleanupInputCallbacks(); -#ifdef LIBXML_OUTPUT_ENABLED - xmlCleanupOutputCallbacks(); -#endif - xmlCleanupDictInternal(); xmlCleanupRandom(); xmlCleanupGlobalsInternal(); diff --git a/tree.c b/tree.c index dc3ac4f..75f7569 100644 --- a/tree.c +++ b/tree.c @@ -55,58 +55,23 @@ int __xmlRegisterCallbacks = 0; * * ************************************************************************/ +static xmlNodePtr +xmlNewEntityRef(xmlDocPtr doc, xmlChar *name); + static xmlNsPtr -xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns); +xmlNewReconciledNs(xmlNodePtr tree, xmlNsPtr ns); + +static xmlAttrPtr +xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name, + const xmlChar *nsName, int useDTD); static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop); -/************************************************************************ - * * - * Tree memory error handler * - * * - ************************************************************************/ -/** - * xmlTreeErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ static void -xmlTreeErrMemory(const char *extra) -{ - __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra); -} +xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree); -/** - * xmlTreeErr: - * @code: the error number - * @extra: extra information - * - * Handle an out of memory condition - */ static void -xmlTreeErr(int code, xmlNodePtr node, const char *extra) -{ - const char *msg = NULL; - - switch(code) { - case XML_TREE_INVALID_HEX: - msg = "invalid hexadecimal character value\n"; - break; - case XML_TREE_INVALID_DEC: - msg = "invalid decimal character value\n"; - break; - case XML_TREE_UNTERMINATED_ENTITY: - msg = "unterminated entity reference %15s\n"; - break; - case XML_TREE_NOT_UTF8: - msg = "string is not in UTF-8\n"; - break; - default: - msg = "unexpected error number\n"; - } - __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra); -} +xmlUnlinkNodeInternal(xmlNodePtr cur); /************************************************************************ * * @@ -122,20 +87,6 @@ const xmlChar xmlStringTextNoenc[] = const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 }; static int xmlCompressMode = 0; -static int xmlCheckDTD = 1; - -#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \ - xmlNodePtr ulccur = (n)->children; \ - if (ulccur == NULL) { \ - (n)->last = NULL; \ - } else { \ - while (ulccur->next != NULL) { \ - ulccur->parent = (n); \ - ulccur = ulccur->next; \ - } \ - ulccur->parent = (n); \ - (n)->last = ulccur; \ -}} #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \ (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0)) @@ -222,15 +173,19 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, if (ncname == NULL) return(NULL); if (prefix == NULL) return((xmlChar *) ncname); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Make allocation more likely */ + if (len > 8) + len = 8; +#endif + lenn = strlen((char *) ncname); lenp = strlen((char *) prefix); if ((memory == NULL) || (len < lenn + lenp + 2)) { ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); - if (ret == NULL) { - xmlTreeErrMemory("building QName"); + if (ret == NULL) return(NULL); - } } else { ret = memory; } @@ -246,6 +201,8 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, * @name: the full QName * @prefix: a xmlChar ** * + * DEPRECATED: This function doesn't report malloc failures. + * * parse an XML qualified name string * * [NS 5] QName ::= (Prefix ':')? LocalPart @@ -267,13 +224,6 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) { *prefix = NULL; if (name == NULL) return(NULL); -#ifndef XML_XML_NAMESPACE - /* xml: prefix is not really a namespace */ - if ((name[0] == 'x') && (name[1] == 'm') && - (name[2] == 'l') && (name[3] == ':')) - return(NULL); -#endif - /* nasty but valid */ if (name[0] == ':') return(NULL); @@ -285,17 +235,14 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) { while ((name[len] != 0) && (name[len] != ':')) len++; - if (name[len] == 0) + if ((name[len] == 0) || (name[len+1] == 0)) return(NULL); *prefix = xmlStrndup(name, len); - if (*prefix == NULL) { - xmlTreeErrMemory("QName split"); + if (*prefix == NULL) return(NULL); - } ret = xmlStrdup(&name[len + 1]); if (ret == NULL) { - xmlTreeErrMemory("QName split"); if (*prefix != NULL) { xmlFree(*prefix); *prefix = NULL; @@ -336,7 +283,7 @@ xmlSplitQName3(const xmlChar *name, int *len) { while ((name[l] != 0) && (name[l] != ':')) l++; - if (name[l] == 0) + if ((name[l] == 0) || (name[l+1] == 0)) return(NULL); *len = l; @@ -344,6 +291,53 @@ xmlSplitQName3(const xmlChar *name, int *len) { return(&name[l+1]); } +/** + * xmlSplitQName4: + * @name: the full QName + * @prefixPtr: pointer to resulting prefix + * + * Parse a QName. The return value points to the start of the local + * name in the input string. If the QName has a prefix, it will be + * allocated and stored in @prefixPtr. This string must be freed by + * the caller. If there's no prefix, @prefixPtr is set to NULL. + * + * Returns the local name or NULL if a memory allocation failed. + */ +const xmlChar * +xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr) { + xmlChar *prefix; + int l = 0; + + if ((name == NULL) || (prefixPtr == NULL)) + return(NULL); + + *prefixPtr = NULL; + + /* nasty but valid */ + if (name[0] == ':') + return(name); + + /* + * we are not trying to validate but just to cut, and yes it will + * work even if this is as set of UTF-8 encoded chars + */ + while ((name[l] != 0) && (name[l] != ':')) + l++; + + /* + * TODO: What about names with multiple colons? + */ + if ((name[l] == 0) || (name[l+1] == 0)) + return(name); + + prefix = xmlStrndup(name, l); + if (prefix == NULL) + return(NULL); + + *prefixPtr = prefix; + return(&name[l+1]); +} + /************************************************************************ * * * Check Name, NCName and QName strings * @@ -708,19 +702,21 @@ xmlGetBufferAllocationScheme(void) { /** * xmlNewNs: - * @node: the element carrying the namespace + * @node: the element carrying the namespace (optional) * @href: the URI associated - * @prefix: the prefix for the namespace + * @prefix: the prefix for the namespace (optional) * - * Creation of a new Namespace. This function will refuse to create - * a namespace with a similar prefix than an existing one present on this - * node. - * Note that for a default namespace, @prefix should be NULL. + * Create a new namespace. For a default namespace, @prefix should be + * NULL. The namespace URI in @href is not checked. You should make sure + * to pass a valid URI. * - * We use href==NULL in the case of an element creation where the namespace - * was not defined. + * If @node is provided, it must be an element node. The namespace will + * be appended to the node's namespace declarations. It is an error if + * the node already has a definition for the prefix or default + * namespace. * - * Returns a new namespace pointer or NULL + * Returns a new namespace pointer or NULL if arguments are invalid, + * the prefix is already in use or a memory allocation failed. */ xmlNsPtr xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { @@ -729,35 +725,25 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) return(NULL); - if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { - /* xml namespace is predefined, no need to add it */ - if (xmlStrEqual(href, XML_XML_NAMESPACE)) - return(NULL); - - /* - * Problem, this is an attempt to bind xml prefix to a wrong - * namespace, which breaks - * Namespace constraint: Reserved Prefixes and Namespace Names - * from XML namespace. But documents authors may not care in - * their context so let's proceed. - */ - } - /* * Allocate a new Namespace and fill the fields. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("building namespace"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_LOCAL_NAMESPACE; - if (href != NULL) + if (href != NULL) { cur->href = xmlStrdup(href); - if (prefix != NULL) + if (cur->href == NULL) + goto error; + } + if (prefix != NULL) { cur->prefix = xmlStrdup(prefix); + if (cur->prefix == NULL) + goto error; + } /* * Add it at the end to preserve parsing order ... @@ -769,31 +755,32 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { } else { xmlNsPtr prev = node->nsDef; - if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } + if ((xmlStrEqual(prev->prefix, cur->prefix)) && + (prev->href != NULL)) + goto error; while (prev->next != NULL) { prev = prev->next; - if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } + if ((xmlStrEqual(prev->prefix, cur->prefix)) && + (prev->href != NULL)) + goto error; } prev->next = cur; } } return(cur); + +error: + xmlFreeNs(cur); + return(NULL); } /** * xmlSetNs: * @node: a node in the document - * @ns: a namespace pointer + * @ns: a namespace pointer (optional) * - * Associate a namespace to a node, a posteriori. + * Set the namespace of an element or attribute node. Passing a NULL + * namespace unsets the namespace. */ void xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { @@ -809,7 +796,7 @@ xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { * xmlFreeNs: * @cur: the namespace pointer * - * Free up the structures associated to a namespace + * Free an xmlNs object. */ void xmlFreeNs(xmlNsPtr cur) { @@ -825,7 +812,7 @@ xmlFreeNs(xmlNsPtr cur) { * xmlFreeNsList: * @cur: the first namespace pointer * - * Free up all the structures associated to the chained namespaces. + * Free a list of xmlNs objects. */ void xmlFreeNsList(xmlNsPtr cur) { @@ -842,15 +829,21 @@ xmlFreeNsList(xmlNsPtr cur) { /** * xmlNewDtd: - * @doc: the document pointer - * @name: the DTD name - * @ExternalID: the external ID - * @SystemID: the system ID + * @doc: the document pointer (optional) + * @name: the DTD name (optional) + * @ExternalID: the external ID (optional) + * @SystemID: the system ID (optional) + * + * Create a DTD node. * - * Creation of a new DTD for the external subset. To create an - * internal subset, use xmlCreateIntSubset(). + * If a document is provided, it is an error if it already has an + * external subset. If the document has no external subset, it + * will be set to the created DTD. * - * Returns a pointer to the new DTD structure + * To create an internal subset, use xmlCreateIntSubset(). + * + * Returns a pointer to the new DTD object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlDtdPtr xmlNewDtd(xmlDocPtr doc, const xmlChar *name, @@ -865,19 +858,26 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name, * Allocate a new DTD and fill the fields. */ cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlTreeErrMemory("building DTD"); + if (cur == NULL) return(NULL); - } memset(cur, 0 , sizeof(xmlDtd)); cur->type = XML_DTD_NODE; - if (name != NULL) + if (name != NULL) { cur->name = xmlStrdup(name); - if (ExternalID != NULL) + if (cur->name == NULL) + goto error; + } + if (ExternalID != NULL) { cur->ExternalID = xmlStrdup(ExternalID); - if (SystemID != NULL) + if (cur->ExternalID == NULL) + goto error; + } + if (SystemID != NULL) { cur->SystemID = xmlStrdup(SystemID); + if (cur->SystemID == NULL) + goto error; + } if (doc != NULL) doc->extSubset = cur; cur->doc = doc; @@ -885,16 +885,20 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name, if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeDtd(cur); + return(NULL); } /** * xmlGetIntSubset: * @doc: the document pointer * - * Get the internal subset of a document - * Returns a pointer to the DTD structure or NULL if not found + * Get the internal subset of a document. + * + * Returns a pointer to the DTD object or NULL if not found. */ - xmlDtdPtr xmlGetIntSubset(const xmlDoc *doc) { xmlNodePtr cur; @@ -912,63 +916,55 @@ xmlGetIntSubset(const xmlDoc *doc) { /** * xmlCreateIntSubset: - * @doc: the document pointer - * @name: the DTD name - * @ExternalID: the external (PUBLIC) ID - * @SystemID: the system ID + * @doc: the document pointer (optional) + * @name: the DTD name (optional) + * @ExternalID: the external (PUBLIC) ID (optional) + * @SystemID: the system ID (optional) * - * Create the internal subset of a document - * Returns a pointer to the new DTD structure + * Create a DTD node. + * + * If a document is provided and it already has an internal subset, + * the existing DTD object is returned without creating a new object. + * If the document has no internal subset, it will be set to the + * created DTD. + * + * Returns a pointer to the new or existing DTD object or NULL if + * arguments are invalid or a memory allocation failed. */ xmlDtdPtr xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { xmlDtdPtr cur; - if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { - return(NULL); + if (doc != NULL) { + cur = xmlGetIntSubset(doc); + if (cur != NULL) + return(cur); } /* * Allocate a new DTD and fill the fields. */ cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlTreeErrMemory("building internal subset"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlDtd)); cur->type = XML_DTD_NODE; if (name != NULL) { cur->name = xmlStrdup(name); - if (cur->name == NULL) { - xmlTreeErrMemory("building internal subset"); - xmlFree(cur); - return(NULL); - } + if (cur->name == NULL) + goto error; } if (ExternalID != NULL) { cur->ExternalID = xmlStrdup(ExternalID); - if (cur->ExternalID == NULL) { - xmlTreeErrMemory("building internal subset"); - if (cur->name != NULL) - xmlFree((char *)cur->name); - xmlFree(cur); - return(NULL); - } + if (cur->ExternalID == NULL) + goto error; } if (SystemID != NULL) { cur->SystemID = xmlStrdup(SystemID); - if (cur->SystemID == NULL) { - xmlTreeErrMemory("building internal subset"); - if (cur->name != NULL) - xmlFree((char *)cur->name); - if (cur->ExternalID != NULL) - xmlFree((char *)cur->ExternalID); - xmlFree(cur); - return(NULL); - } + if (cur->SystemID == NULL) + goto error; } if (doc != NULL) { doc->intSubset = cur; @@ -1012,6 +1008,10 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeDtd(cur); + return(NULL); } /** @@ -1026,42 +1026,6 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ xmlFree((char *)(str)); - -/** - * DICT_COPY: - * @str: a string - * - * Copy a string using a "dict" dictionary in the current scope, - * if available. - */ -#define DICT_COPY(str, cpy) \ - if (str) { \ - if (dict) { \ - if (xmlDictOwns(dict, (const xmlChar *)(str))) \ - cpy = (xmlChar *) (str); \ - else \ - cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \ - } else \ - cpy = xmlStrdup((const xmlChar *)(str)); } - -/** - * DICT_CONST_COPY: - * @str: a string - * - * Copy a string using a "dict" dictionary in the current scope, - * if available. - */ -#define DICT_CONST_COPY(str, cpy) \ - if (str) { \ - if (dict) { \ - if (xmlDictOwns(dict, (const xmlChar *)(str))) \ - cpy = (const xmlChar *) (str); \ - else \ - cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \ - } else \ - cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); } - - /** * xmlFreeDtd: * @cur: the DTD structure to free up @@ -1089,11 +1053,10 @@ xmlFreeDtd(xmlDtdPtr cur) { */ while (c != NULL) { next = c->next; - if ((c->type != XML_NOTATION_NODE) && - (c->type != XML_ELEMENT_DECL) && + if ((c->type != XML_ELEMENT_DECL) && (c->type != XML_ATTRIBUTE_DECL) && (c->type != XML_ENTITY_DECL)) { - xmlUnlinkNode(c); + xmlUnlinkNodeInternal(c); xmlFreeNode(c); } c = next; @@ -1120,11 +1083,11 @@ xmlFreeDtd(xmlDtdPtr cur) { /** * xmlNewDoc: - * @version: xmlChar string giving the version of XML "1.0" + * @version: XML version string like "1.0" (optional) * - * Creates a new XML document + * Creates a new XML document. If version is NULL, "1.0" is used. * - * Returns a new document + * Returns a new document or NULL if a memory allocation failed. */ xmlDocPtr xmlNewDoc(const xmlChar *version) { @@ -1137,16 +1100,13 @@ xmlNewDoc(const xmlChar *version) { * Allocate a new document and fill the fields. */ cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); - if (cur == NULL) { - xmlTreeErrMemory("building doc"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlDoc)); cur->type = XML_DOCUMENT_NODE; cur->version = xmlStrdup(version); if (cur->version == NULL) { - xmlTreeErrMemory("building doc"); xmlFree(cur); return(NULL); } @@ -1171,7 +1131,7 @@ xmlNewDoc(const xmlChar *version) { * xmlFreeDoc: * @cur: pointer to the document * - * Free up all the structures used by a document, tree included. + * Free a document including all children and associated DTDs. */ void xmlFreeDoc(xmlDocPtr cur) { @@ -1182,7 +1142,7 @@ xmlFreeDoc(xmlDocPtr cur) { return; } - if (cur != NULL) dict = cur->dict; + dict = cur->dict; if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); @@ -1199,12 +1159,12 @@ xmlFreeDoc(xmlDocPtr cur) { if (intSubset == extSubset) extSubset = NULL; if (extSubset != NULL) { - xmlUnlinkNode((xmlNodePtr) cur->extSubset); + xmlUnlinkNodeInternal((xmlNodePtr) cur->extSubset); cur->extSubset = NULL; xmlFreeDtd(extSubset); } if (intSubset != NULL) { - xmlUnlinkNode((xmlNodePtr) cur->intSubset); + xmlUnlinkNodeInternal((xmlNodePtr) cur->intSubset); cur->intSubset = NULL; xmlFreeDtd(intSubset); } @@ -1221,38 +1181,52 @@ xmlFreeDoc(xmlDocPtr cur) { } /** - * xmlStringLenGetNodeList: - * @doc: the document - * @value: the value of the text - * @len: the length of the string value + * xmlNodeParseContentInternal: + * @doc: a document (optional) + * @parent: an element or attribute (optional) + * @value: an attribute value + * @len: maximum length of the attribute value + * @listPtr: pointer to the resulting node list (optional) + * + * See xmlNodeParseContent. * - * Parse the value string and build the node list associated. Should - * produce a flat tree with only TEXTs and ENTITY_REFs. - * Returns a pointer to the first child + * Returns 0 on success, -1 if a memory allocation failed. */ -xmlNodePtr -xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { - xmlNodePtr ret = NULL, last = NULL; +static int +xmlNodeParseContentInternal(const xmlDoc *doc, xmlNodePtr parent, + const xmlChar *value, int len, + xmlNodePtr *listPtr) { + xmlNodePtr head = NULL, last = NULL; xmlNodePtr node; - xmlChar *val; - const xmlChar *cur, *end; + xmlChar *val = NULL; + const xmlChar *cur; const xmlChar *q; xmlEntityPtr ent; xmlBufPtr buf; + int remaining; + + if (listPtr != NULL) + *listPtr = NULL; + + if (len < 0) + remaining = INT_MAX; + else + remaining = len; + + if (value == NULL) + goto done; - if (value == NULL) return(NULL); cur = value; - end = cur + len; - buf = xmlBufCreateSize(0); - if (buf == NULL) return(NULL); + buf = xmlBufCreateSize(64); + if (buf == NULL) + return(-1); xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); q = cur; - while ((cur < end) && (*cur != 0)) { + while ((remaining > 0) && (*cur != 0)) { if (cur[0] == '&') { int charval = 0; - xmlChar tmp; /* * Save the current text. @@ -1260,25 +1234,15 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { if (cur != q) { if (xmlBufAdd(buf, q, cur - q)) goto out; + q = cur; } - q = cur; - if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) { + + if ((remaining > 2) && (cur[1] == '#') && (cur[2] == 'x')) { + int tmp = 0; + cur += 3; - if (cur < end) - tmp = *cur; - else - tmp = 0; - while (tmp != ';') { /* Non input consuming loop */ - /* - * If you find an integer overflow here when fuzzing, - * the bug is probably elsewhere. This function should - * only receive entities that were already validated by - * the parser, typically by xmlParseAttValueComplex - * calling xmlStringDecodeEntities. - * - * So it's better *not* to check for overflow to - * potentially discover new bugs. - */ + remaining -= 3; + while ((remaining > 0) && ((tmp = *cur) != ';')) { if ((tmp >= '0') && (tmp <= '9')) charval = charval * 16 + (tmp - '0'); else if ((tmp >= 'a') && (tmp <= 'f')) @@ -1286,142 +1250,147 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { else if ((tmp >= 'A') && (tmp <= 'F')) charval = charval * 16 + (tmp - 'A') + 10; else { - xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, - NULL); charval = 0; break; } + if (charval > 0x110000) + charval = 0x110000; cur++; - if (cur < end) - tmp = *cur; - else - tmp = 0; + remaining--; } - if (tmp == ';') + if (tmp == ';') { cur++; + remaining--; + } q = cur; - } else if ((cur + 1 < end) && (cur[1] == '#')) { + } else if ((remaining > 1) && (cur[1] == '#')) { + int tmp = 0; + cur += 2; - if (cur < end) - tmp = *cur; - else - tmp = 0; - while (tmp != ';') { /* Non input consuming loops */ - /* Don't check for integer overflow, see above. */ + remaining -= 2; + while ((remaining > 0) && ((tmp = *cur) != ';')) { if ((tmp >= '0') && (tmp <= '9')) charval = charval * 10 + (tmp - '0'); else { - xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, - NULL); charval = 0; break; } + if (charval > 0x110000) + charval = 0x110000; cur++; - if (cur < end) - tmp = *cur; - else - tmp = 0; + remaining--; } - if (tmp == ';') + if (tmp == ';') { cur++; + remaining--; + } q = cur; } else { /* * Read the entity string */ cur++; + remaining--; q = cur; - while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++; - if ((cur >= end) || (*cur == 0)) { - xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc, - (const char *) q); - goto out; - } + while ((remaining > 0) && (*cur != 0) && (*cur != ';')) { + cur++; + remaining--; + } + if ((remaining <= 0) || (*cur == 0)) + break; if (cur != q) { - /* - * Predefined entities don't generate nodes - */ val = xmlStrndup(q, cur - q); + if (val == NULL) + goto out; ent = xmlGetDocEntity(doc, val); if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { - + /* + * Predefined entities don't generate nodes + */ if (xmlBufCat(buf, ent->content)) goto out; - } else { /* * Flush buffer so far */ if (!xmlBufIsEmpty(buf)) { node = xmlNewDocText(doc, NULL); - if (node == NULL) { - if (val != NULL) xmlFree(val); + if (node == NULL) goto out; - } node->content = xmlBufDetach(buf); + node->parent = parent; if (last == NULL) { - last = ret = node; + head = node; } else { - last = xmlAddNextSibling(last, node); + last->next = node; + node->prev = last; } + last = node; + } + + if ((ent != NULL) && + ((ent->flags & XML_ENT_PARSED) == 0) && + ((ent->flags & XML_ENT_EXPANDING) == 0) && + (ent->content != NULL)) { + int res; + + ent->flags |= XML_ENT_EXPANDING; + res = xmlNodeParseContentInternal(doc, + (xmlNodePtr) ent, ent->content, -1, NULL); + ent->flags &= ~XML_ENT_EXPANDING; + if (res < 0) + goto out; + ent->flags |= XML_ENT_PARSED; } /* * Create a new REFERENCE_REF node */ - node = xmlNewReference(doc, val); - if (node == NULL) { - if (val != NULL) xmlFree(val); + node = xmlNewEntityRef((xmlDocPtr) doc, val); + val = NULL; + if (node == NULL) goto out; - } - else if ((ent != NULL) && - ((ent->flags & XML_ENT_PARSED) == 0) && - ((ent->flags & XML_ENT_EXPANDING) == 0)) { - xmlNodePtr temp; - - /* - * The entity should have been checked already, - * but set the flag anyway to avoid recursion. - */ - ent->flags |= XML_ENT_EXPANDING; - ent->children = xmlStringGetNodeList(doc, - (const xmlChar*)node->content); - ent->owner = 1; - ent->flags &= ~XML_ENT_EXPANDING; - ent->flags |= XML_ENT_PARSED; - temp = ent->children; - while (temp) { - temp->parent = (xmlNodePtr)ent; - ent->last = temp; - temp = temp->next; - } - } + node->parent = parent; + node->last = (xmlNodePtr) ent; + if (ent != NULL) { + node->children = (xmlNodePtr) ent; + node->content = ent->content; + } + if (last == NULL) { - last = ret = node; + head = node; } else { - last = xmlAddNextSibling(last, node); + last->next = node; + node->prev = last; } + last = node; } xmlFree(val); + val = NULL; } cur++; + remaining--; q = cur; } if (charval != 0) { xmlChar buffer[10]; int l; + if (charval >= 0x110000) + charval = 0xFFFD; /* replacement character */ + l = xmlCopyCharMultiByte(buffer, charval); buffer[l] = 0; if (xmlBufCat(buf, buffer)) goto out; - charval = 0; } - } else + } else { cur++; + remaining--; + } } if (cur != q) { @@ -1434,398 +1403,250 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { if (!xmlBufIsEmpty(buf)) { node = xmlNewDocText(doc, NULL); - if (node == NULL) goto out; + if (node == NULL) + goto out; + node->parent = parent; node->content = xmlBufDetach(buf); if (last == NULL) { - ret = node; + head = node; } else { - xmlAddNextSibling(last, node); + last->next = node; + node->prev = last; } - } else if (ret == NULL) { - ret = xmlNewDocText(doc, BAD_CAST ""); + last = node; + } else if (head == NULL) { + head = xmlNewDocText(doc, BAD_CAST ""); + if (head == NULL) + goto out; + head->parent = parent; + last = head; } + xmlBufFree(buf); + +done: + if (parent != NULL) { + if (parent->children != NULL) + xmlFreeNodeList(parent->children); + parent->children = head; + parent->last = last; + } + + if (listPtr != NULL) + *listPtr = head; + + return(0); + out: xmlBufFree(buf); + if (val != NULL) + xmlFree(val); + if (head != NULL) + xmlFreeNodeList(head); + return(-1); +} + +/** + * xmlNodeParseContent: + * @node: an element or attribute + * @content: text content with XML references + * @len: maximum length of content + * + * Parse content and replace the node's children with the resulting + * node list. + * + * @content is expected to be a valid XML attribute value possibly + * containing character and entity references. Syntax errors + * and references to undeclared entities are ignored silently. + * Only references are handled, nested elements, comments or PIs are + * not. + * + * Returns 0 on success, -1 if a memory allocation failed. + */ +int +xmlNodeParseContent(xmlNodePtr node, const xmlChar *content, int len) { + return(xmlNodeParseContentInternal(node->doc, node, content, len, NULL)); +} + +/** + * xmlStringLenGetNodeList: + * @doc: a document (optional) + * @value: an attribute value + * @len: maximum length of the attribute value + * + * DEPRECATED: Use xmlNodeSetContentLen. + * + * See xmlStringGetNodeList. + * + * Returns a pointer to the first child or NULL if a memory + * allocation failed. + */ +xmlNodePtr +xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { + xmlNodePtr ret; + + xmlNodeParseContentInternal(doc, NULL, value, len, &ret); return(ret); } /** * xmlStringGetNodeList: - * @doc: the document - * @value: the value of the attribute + * @doc: a document (optional) + * @value: an attribute value + * + * DEPRECATED: Use xmlNodeSetContent. + * + * Parse an attribute value and build a node list containing only + * text and entity reference nodes. The resulting nodes will be + * associated with the document if provided. The document is also + * used to look up entities. * - * Parse the value string and build the node list associated. Should - * produce a flat tree with only TEXTs and ENTITY_REFs. - * Returns a pointer to the first child + * The input is not validated. Syntax errors or references to + * undeclared entities will be ignored silently with unspecified + * results. + * + * Returns a pointer to the first child or NULL if a memory + * allocation failed. */ xmlNodePtr xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { - xmlNodePtr ret = NULL, head = NULL, last = NULL; - xmlNodePtr node; - xmlChar *val = NULL; - const xmlChar *cur = value; - const xmlChar *q; - xmlEntityPtr ent; + xmlNodePtr ret; + + xmlNodeParseContentInternal(doc, NULL, value, -1, &ret); + return(ret); +} + +/** + * xmlNodeListGetStringInternal: + * @doc: a document (optional) + * @node: a node list + * @escMode: escape mode (0 = no, 1 = elem, 2 = attr, 3 = raw) + * + * Returns a pointer to the string. + */ +static xmlChar * +xmlNodeListGetStringInternal(xmlDocPtr doc, const xmlNode *node, int escMode) { xmlBufPtr buf; + xmlChar *ret; - if (value == NULL) return(NULL); + if (node == NULL) + return(xmlStrdup(BAD_CAST "")); - buf = xmlBufCreateSize(0); - if (buf == NULL) return(NULL); - xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); + if ((escMode == 0) && + ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) && + (node->next == NULL)) { + if (node->content == NULL) + return(xmlStrdup(BAD_CAST "")); + return(xmlStrdup(node->content)); + } - q = cur; - while (*cur != 0) { - if (cur[0] == '&') { - int charval = 0; - xmlChar tmp; + buf = xmlBufCreateSize(64); + if (buf == NULL) + return(NULL); - /* - * Save the current text. - */ - if (cur != q) { - if (xmlBufAdd(buf, q, cur - q)) - goto out; - } - q = cur; - if ((cur[1] == '#') && (cur[2] == 'x')) { - cur += 3; - tmp = *cur; - while (tmp != ';') { /* Non input consuming loop */ - /* Don't check for integer overflow, see above. */ - if ((tmp >= '0') && (tmp <= '9')) - charval = charval * 16 + (tmp - '0'); - else if ((tmp >= 'a') && (tmp <= 'f')) - charval = charval * 16 + (tmp - 'a') + 10; - else if ((tmp >= 'A') && (tmp <= 'F')) - charval = charval * 16 + (tmp - 'A') + 10; - else { - xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, - NULL); - charval = 0; - break; - } - cur++; - tmp = *cur; - } - if (tmp == ';') - cur++; - q = cur; - } else if (cur[1] == '#') { - cur += 2; - tmp = *cur; - while (tmp != ';') { /* Non input consuming loops */ - /* Don't check for integer overflow, see above. */ - if ((tmp >= '0') && (tmp <= '9')) - charval = charval * 10 + (tmp - '0'); - else { - xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, - NULL); - charval = 0; - break; - } - cur++; - tmp = *cur; - } - if (tmp == ';') - cur++; - q = cur; - } else { - /* - * Read the entity string - */ - cur++; - q = cur; - while ((*cur != 0) && (*cur != ';')) cur++; - if (*cur == 0) { - xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, - (xmlNodePtr) doc, (const char *) q); - goto out; - } - if (cur != q) { - /* - * Predefined entities don't generate nodes - */ - val = xmlStrndup(q, cur - q); - ent = xmlGetDocEntity(doc, val); - if ((ent != NULL) && - (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { - - if (xmlBufCat(buf, ent->content)) - goto out; - - } else { - /* - * Flush buffer so far - */ - if (!xmlBufIsEmpty(buf)) { - node = xmlNewDocText(doc, NULL); - if (node == NULL) - goto out; - node->content = xmlBufDetach(buf); - - if (last == NULL) { - last = head = node; - } else { - last = xmlAddNextSibling(last, node); - } - } - - /* - * Create a new REFERENCE_REF node - */ - node = xmlNewReference(doc, val); - if (node == NULL) - goto out; - if ((ent != NULL) && - ((ent->flags & XML_ENT_PARSED) == 0) && - ((ent->flags & XML_ENT_EXPANDING) == 0)) { - xmlNodePtr temp; - - /* - * The entity should have been checked already, - * but set the flag anyway to avoid recursion. - */ - ent->flags |= XML_ENT_EXPANDING; - ent->children = xmlStringGetNodeList(doc, - (const xmlChar*)node->content); - ent->owner = 1; - ent->flags &= ~XML_ENT_EXPANDING; - ent->flags |= XML_ENT_PARSED; - temp = ent->children; - while (temp) { - temp->parent = (xmlNodePtr)ent; - ent->last = temp; - temp = temp->next; - } - } - if (last == NULL) { - last = head = node; - } else { - last = xmlAddNextSibling(last, node); - } - } - xmlFree(val); - val = NULL; - } - cur++; - q = cur; - } - if (charval != 0) { - xmlChar buffer[10]; - int len; - - len = xmlCopyCharMultiByte(buffer, charval); - buffer[len] = 0; - - if (xmlBufCat(buf, buffer)) - goto out; - charval = 0; - } - } else - cur++; - } - if ((cur != q) || (head == NULL)) { - /* - * Handle the last piece of text. - */ - xmlBufAdd(buf, q, cur - q); - } - - if (!xmlBufIsEmpty(buf)) { - node = xmlNewDocText(doc, NULL); - if (node == NULL) - goto out; - node->content = xmlBufDetach(buf); + while (node != NULL) { + if ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) { + if (node->content != NULL) { + if (escMode == 0) { + xmlBufCat(buf, node->content); + } else { + xmlChar *encoded; + + if (escMode == 1) + encoded = xmlEncodeEntitiesReentrant(doc, + node->content); + else if (escMode == 2) + encoded = xmlEncodeAttributeEntities(doc, + node->content); + else + encoded = xmlEncodeSpecialChars(doc, node->content); + if (encoded == NULL) + goto error; + xmlBufCat(buf, encoded); + xmlFree(encoded); + } + } + } else if (node->type == XML_ENTITY_REF_NODE) { + if (escMode == 0) { + xmlBufGetNodeContent(buf, node); + } else { + xmlBufAdd(buf, BAD_CAST "&", 1); + xmlBufCat(buf, node->name); + xmlBufAdd(buf, BAD_CAST ";", 1); + } + } - if (last == NULL) { - head = node; - } else { - xmlAddNextSibling(last, node); - } + node = node->next; } - ret = head; - head = NULL; - -out: + ret = xmlBufDetach(buf); xmlBufFree(buf); - if (val != NULL) xmlFree(val); - if (head != NULL) xmlFreeNodeList(head); return(ret); + +error: + xmlBufFree(buf); + return(NULL); } /** * xmlNodeListGetString: - * @doc: the document - * @list: a Node list - * @inLine: should we replace entity contents or show their external form + * @doc: a document (optional) + * @list: a node list of attribute children (optional) + * @inLine: whether entity references are substituted * - * Build the string equivalent to the text contained in the Node list - * made of TEXTs and ENTITY_REFs + * Serializes attribute children (text and entity reference nodes) + * into a string. An empty list produces an empty string. * - * Returns a pointer to the string copy, the caller must free it with xmlFree(). + * If @inLine is true, entity references will be substituted. + * Otherwise, entity references will be kept and special characters + * like '&' as well as non-ASCII chars will be escaped. See + * xmlNodeListGetRawString for an alternative option. + * + * Returns a string or NULL if a memory allocation failed. */ xmlChar * xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine) { - const xmlNode *node = list; - xmlChar *ret = NULL; - xmlEntityPtr ent; - int attr; - - if (list == NULL) - return (NULL); - if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE)) - attr = 1; - else - attr = 0; - - while (node != NULL) { - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) { - if (inLine) { - ret = xmlStrcat(ret, node->content); - } else { - xmlChar *buffer; + int escMode; - if (attr) - buffer = xmlEncodeAttributeEntities(doc, node->content); - else - buffer = xmlEncodeEntitiesReentrant(doc, node->content); - if (buffer != NULL) { - ret = xmlStrcat(ret, buffer); - xmlFree(buffer); - } - } - } else if (node->type == XML_ENTITY_REF_NODE) { - if (inLine) { - ent = xmlGetDocEntity(doc, node->name); - if (ent != NULL) { - xmlChar *buffer; - - /* an entity content can be any "well balanced chunk", - * i.e. the result of the content [43] production: - * http://www.w3.org/TR/REC-xml#NT-content. - * So it can contain text, CDATA section or nested - * entity reference nodes (among others). - * -> we recursive call xmlNodeListGetString() - * which handles these types */ - buffer = xmlNodeListGetString(doc, ent->children, 1); - if (buffer != NULL) { - ret = xmlStrcat(ret, buffer); - xmlFree(buffer); - } - } else { - ret = xmlStrcat(ret, node->content); - } - } else { - xmlChar buf[2]; - - buf[0] = '&'; - buf[1] = 0; - ret = xmlStrncat(ret, buf, 1); - ret = xmlStrcat(ret, node->name); - buf[0] = ';'; - buf[1] = 0; - ret = xmlStrncat(ret, buf, 1); - } - } -#if 0 - else { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNodeListString : invalid node type %d\n", - node->type); - } -#endif - node = node->next; + if (inLine) { + escMode = 0; + } else { + if ((list != NULL) && + (list->parent != NULL) && + (list->parent->type == XML_ATTRIBUTE_NODE)) + escMode = 2; + else + escMode = 1; } - return (ret); + + return(xmlNodeListGetStringInternal(doc, list, escMode)); } #ifdef LIBXML_TREE_ENABLED /** * xmlNodeListGetRawString: - * @doc: the document - * @list: a Node list - * @inLine: should we replace entity contents or show their external form + * @doc: a document (optional) + * @list: a node list of attribute children (optional) + * @inLine: whether entity references are substituted + * + * Serializes attribute children (text and entity reference nodes) + * into a string. An empty list produces an empty string. * - * Builds the string equivalent to the text contained in the Node list - * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString() - * this function doesn't do any character encoding handling. + * If @inLine is true, entity references will be substituted. + * Otherwise, entity references will be kept and special characters + * like '&' will be escaped. * - * Returns a pointer to the string copy, the caller must free it with xmlFree(). + * Returns a string or NULL if a memory allocation failed. */ xmlChar * xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine) { - const xmlNode *node = list; - xmlChar *ret = NULL; - xmlEntityPtr ent; - - if (list == NULL) - return (NULL); - - while (node != NULL) { - if ((node->type == XML_TEXT_NODE) || - (node->type == XML_CDATA_SECTION_NODE)) { - if (inLine) { - ret = xmlStrcat(ret, node->content); - } else { - xmlChar *buffer; - - buffer = xmlEncodeSpecialChars(doc, node->content); - if (buffer != NULL) { - ret = xmlStrcat(ret, buffer); - xmlFree(buffer); - } - } - } else if (node->type == XML_ENTITY_REF_NODE) { - if (inLine) { - ent = xmlGetDocEntity(doc, node->name); - if (ent != NULL) { - xmlChar *buffer; - - /* an entity content can be any "well balanced chunk", - * i.e. the result of the content [43] production: - * http://www.w3.org/TR/REC-xml#NT-content. - * So it can contain text, CDATA section or nested - * entity reference nodes (among others). - * -> we recursive call xmlNodeListGetRawString() - * which handles these types */ - buffer = - xmlNodeListGetRawString(doc, ent->children, 1); - if (buffer != NULL) { - ret = xmlStrcat(ret, buffer); - xmlFree(buffer); - } - } else { - ret = xmlStrcat(ret, node->content); - } - } else { - xmlChar buf[2]; - - buf[0] = '&'; - buf[1] = 0; - ret = xmlStrncat(ret, buf, 1); - ret = xmlStrcat(ret, node->name); - buf[0] = ';'; - buf[1] = 0; - ret = xmlStrncat(ret, buf, 1); - } - } -#if 0 - else { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNodeListString : invalid node type %d\n", - node->type); - } -#endif - node = node->next; - } - return (ret); + int escMode = inLine ? 0 : 3; + return(xmlNodeListGetStringInternal((xmlDocPtr) doc, list, escMode)); } #endif /* LIBXML_TREE_ENABLED */ @@ -1855,7 +1676,6 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, (node->doc->dict == NULL) || (!(xmlDictOwns(node->doc->dict, name))))) xmlFree((xmlChar *) name); - xmlTreeErrMemory("building attribute"); return (NULL); } memset(cur, 0, sizeof(xmlAttr)); @@ -1873,6 +1693,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; } else cur->name = name; @@ -1880,6 +1702,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, xmlNodePtr tmp; cur->children = xmlNewDocText(doc, value); + if (cur->children == NULL) + goto error; cur->last = NULL; tmp = cur->children; while (tmp != NULL) { @@ -1888,6 +1712,15 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, cur->last = tmp; tmp = tmp->next; } + + if (doc != NULL) { + int res = xmlIsID(doc, node, cur); + + if (res < 0) + goto error; + if ((res == 1) && (xmlAddIDSafe(cur, value) < 0)) + goto error; + } } /* @@ -1906,25 +1739,33 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, } } - if ((value != NULL) && (node != NULL) && - (xmlIsID(node->doc, node, cur) == 1)) - xmlAddID(NULL, node->doc, value, cur); - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr) cur); return (cur); + +error: + xmlFreeProp(cur); + return(NULL); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) /** * xmlNewProp: - * @node: the holding node + * @node: the parent node (optional) * @name: the name of the attribute - * @value: the value of the attribute + * @value: the value of the attribute (optional) + * + * Create an attribute node. + * + * If provided, @value should be a raw, unescaped string. + * + * If @node is provided, the created attribute will be appended without + * checking for duplicate names. It is an error if @node is not an + * element. * - * Create a new property carried by a node. - * Returns a pointer to the attribute + * Returns a pointer to the attribute or NULL if arguments are invalid + * or a memory allocation failed. */ xmlAttrPtr xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { @@ -1939,13 +1780,21 @@ xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { /** * xmlNewNsProp: - * @node: the holding node - * @ns: the namespace - * @name: the name of the attribute - * @value: the value of the attribute + * @node: the parent node (optional) + * @ns: the namespace (optional) + * @name: the local name of the attribute + * @value: the value of the attribute (optional) + * + * Create an attribute object. + * + * If provided, @value should be a raw, unescaped string. + * + * If @node is provided, the created attribute will be appended without + * checking for duplicate names. It is an error if @node is not an + * element. * - * Create a new property tagged with a namespace and carried by a node. - * Returns a pointer to the attribute + * Returns a pointer to the attribute or NULL if arguments are invalid + * or a memory allocation failed. */ xmlAttrPtr xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, @@ -1960,13 +1809,17 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, /** * xmlNewNsPropEatName: - * @node: the holding node - * @ns: the namespace - * @name: the name of the attribute - * @value: the value of the attribute + * @node: the parent node (optional) + * @ns: the namespace (optional) + * @name: the local name of the attribute + * @value: the value of the attribute (optional) + * + * Like xmlNewNsProp, but the @name string will be used directly + * without making a copy. Takes ownership of @name which will also + * be freed on error. * - * Create a new property tagged with a namespace and carried by a node. - * Returns a pointer to the attribute + * Returns a pointer to the attribute or NULL if arguments are invalid + * or a memory allocation failed. */ xmlAttrPtr xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name, @@ -1981,17 +1834,19 @@ xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name, /** * xmlNewDocProp: - * @doc: the document + * @doc: the target document (optional) * @name: the name of the attribute - * @value: the value of the attribute + * @value: attribute value with XML references (optional) + * + * Create an attribute object. * - * Create a new property carried by a document. - * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need - * entities support. + * If provided, @value is expected to be a valid XML attribute value + * possibly containing character and entity references. Syntax errors + * and references to undeclared entities are ignored silently. + * If you want to pass a raw string, see xmlNewProp. * - * Returns a pointer to the attribute + * Returns a pointer to the attribute or NULL if arguments are invalid + * or a memory allocation failed. */ xmlAttrPtr xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { @@ -2005,10 +1860,8 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { * Allocate a new property and fill the fields. */ cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); - if (cur == NULL) { - xmlTreeErrMemory("building attribute"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlAttr)); cur->type = XML_ATTRIBUTE_NODE; @@ -2016,32 +1869,28 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { cur->name = xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; cur->doc = doc; if (value != NULL) { - xmlNodePtr tmp; - - cur->children = xmlStringGetNodeList(doc, value); - cur->last = NULL; - - tmp = cur->children; - while (tmp != NULL) { - tmp->parent = (xmlNodePtr) cur; - if (tmp->next == NULL) - cur->last = tmp; - tmp = tmp->next; - } + if (xmlNodeParseContent((xmlNodePtr) cur, value, -1) < 0) + goto error; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeProp(cur); + return(NULL); } /** * xmlFreePropList: - * @cur: the first property in the list + * @cur: the first attribute in the list * - * Free a property and all its siblings, all the children are freed too. + * Free an attribute list including all children. */ void xmlFreePropList(xmlAttrPtr cur) { @@ -2058,7 +1907,7 @@ xmlFreePropList(xmlAttrPtr cur) { * xmlFreeProp: * @cur: an attribute * - * Free one attribute, all the content is freed too + * Free an attribute including all children. */ void xmlFreeProp(xmlAttrPtr cur) { @@ -2083,10 +1932,14 @@ xmlFreeProp(xmlAttrPtr cur) { * xmlRemoveProp: * @cur: an attribute * - * Unlink and free one attribute, all the content is freed too - * Note this doesn't work for namespace definition attributes + * Unlink and free an attribute including all children. + * + * Note this doesn't work for namespace declarations. * - * Returns 0 if success and -1 in case of error. + * The attribute must have a non-NULL parent pointer. + * + * Returns 0 on success or -1 if the attribute was not found or + * arguments are invalid. */ int xmlRemoveProp(xmlAttrPtr cur) { @@ -2120,12 +1973,14 @@ xmlRemoveProp(xmlAttrPtr cur) { /** * xmlNewDocPI: - * @doc: the target document - * @name: the processing instruction name - * @content: the PI content + * @doc: the target document (optional) + * @name: the processing instruction target + * @content: the PI content (optional) * - * Creation of a processing instruction element. - * Returns a pointer to the new node object. + * Create a processing instruction object. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { @@ -2139,37 +1994,44 @@ xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building PI"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_PI_NODE; + cur->doc = doc; if ((doc != NULL) && (doc->dict != NULL)) cur->name = xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } - cur->doc = doc; if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** * xmlNewPI: - * @name: the processing instruction name - * @content: the PI content + * @name: the processing instruction target + * @content: the PI content (optional) * - * Creation of a processing instruction element. + * Create a processing instruction node. * * Use of this function is DISCOURAGED in favor of xmlNewDocPI. * - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewPI(const xmlChar *name, const xmlChar *content) { @@ -2178,116 +2040,122 @@ xmlNewPI(const xmlChar *name, const xmlChar *content) { /** * xmlNewNode: - * @ns: namespace if any + * @ns: namespace (optional) * @name: the node name * - * Creation of a new node element. @ns is optional (NULL). + * Create an element node. * * Use of this function is DISCOURAGED in favor of xmlNewDocNode. * - * Returns a pointer to the new node object. Uses xmlStrdup() to make - * copy of @name. + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewNode(xmlNsPtr ns, const xmlChar *name) { - xmlNodePtr cur; - - if (name == NULL) { - return(NULL); - } - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building node"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ELEMENT_NODE; - - cur->name = xmlStrdup(name); - cur->ns = ns; - - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) - xmlRegisterNodeDefaultValue(cur); - return(cur); + return(xmlNewDocNode(NULL, ns, name, NULL)); } /** * xmlNewNodeEatName: - * @ns: namespace if any + * @ns: namespace (optional) * @name: the node name * - * Creation of a new node element. @ns is optional (NULL). + * Create an element node. * * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName. * - * Returns a pointer to the new node object, with pointer @name as - * new node's name. Use xmlNewNode() if a copy of @name string is - * is needed as new node's name. + * Like xmlNewNode, but the @name string will be used directly + * without making a copy. Takes ownership of @name which will also + * be freed on error. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { - xmlNodePtr cur; + return(xmlNewDocNodeEatName(NULL, ns, name, NULL)); +} - if (name == NULL) { - return(NULL); - } +static xmlNodePtr +xmlNewElem(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, + const xmlChar *content) { + xmlNodePtr cur; - /* - * Allocate a new node and fill the fields. - */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building node"); - /* we can't check here that name comes from the doc dictionary */ + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ELEMENT_NODE; + cur->type = XML_ELEMENT_NODE; + cur->doc = doc; cur->name = name; cur->ns = ns; + if (content != NULL) { + if (xmlNodeParseContent(cur, content, -1) < 0) { + /* Don't free name on error */ + xmlFree(cur); + return(NULL); + } + } + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); + return(cur); } /** * xmlNewDocNode: - * @doc: the document - * @ns: namespace if any + * @doc: the target document + * @ns: namespace (optional) * @name: the node name - * @content: the XML text content if any + * @content: text content with XML references (optional) + * + * Create an element node. * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). - * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't - * need entities support. + * If provided, @content is expected to be a valid XML attribute value + * possibly containing character and entity references. Syntax errors + * and references to undeclared entities are ignored silently. + * Only references are handled, nested elements, comments or PIs are + * not. See xmlNewDocRawNode for an alternative. * - * Returns a pointer to the new node object. + * General notes on object creation: + * + * Each node and all its children are associated with the same + * document. The document should be provided when creating nodes to + * avoid a performance penalty when adding the node to a document + * tree. Note that a document only owns nodes reachable from the root + * node. Unlinked subtrees must be freed manually. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content) { xmlNodePtr cur; + xmlChar *copy; - if ((doc != NULL) && (doc->dict != NULL)) - cur = xmlNewNodeEatName(ns, (xmlChar *) - xmlDictLookup(doc->dict, name, -1)); - else - cur = xmlNewNode(ns, name); - if (cur != NULL) { - cur->doc = doc; - if (content != NULL) { - cur->children = xmlStringGetNodeList(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - } + if (name == NULL) + return(NULL); + + if ((doc != NULL) && (doc->dict != NULL)) { + const xmlChar *dictName = xmlDictLookup(doc->dict, name, -1); + + if (dictName == NULL) + return(NULL); + return(xmlNewElem(doc, ns, dictName, content)); + } + + copy = xmlStrdup(name); + if (copy == NULL) + return(NULL); + + cur = xmlNewElem(doc, ns, copy, content); + if (cur == NULL) { + xmlFree(copy); + return(NULL); } return(cur); @@ -2295,54 +2163,55 @@ xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, /** * xmlNewDocNodeEatName: - * @doc: the document - * @ns: namespace if any + * @doc: the target document + * @ns: namespace (optional) * @name: the node name - * @content: the XML text content if any + * @content: text content with XML references (optional) + * + * Create an element node. * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). - * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't - * need entities support. + * Like xmlNewDocNode, but the @name string will be used directly + * without making a copy. Takes ownership of @name which will also + * be freed on error. * - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns, - xmlChar *name, const xmlChar *content) { + xmlChar *name, const xmlChar *content) { xmlNodePtr cur; - cur = xmlNewNodeEatName(ns, name); - if (cur != NULL) { - cur->doc = doc; - if (content != NULL) { - cur->children = xmlStringGetNodeList(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - } - } else { - /* if name don't come from the doc dictionary free it here */ - if ((name != NULL) && - ((doc == NULL) || (doc->dict == NULL) || - (!(xmlDictOwns(doc->dict, name))))) - xmlFree(name); + if (name == NULL) + return(NULL); + + cur = xmlNewElem(doc, ns, name, content); + if (cur == NULL) { + /* if name doesn't come from the doc dictionary free it here */ + if ((doc == NULL) || + (doc->dict == NULL) || + (!xmlDictOwns(doc->dict, name))) + xmlFree(name); + return(NULL); } + return(cur); } #ifdef LIBXML_TREE_ENABLED /** * xmlNewDocRawNode: - * @doc: the document - * @ns: namespace if any + * @doc: the target document + * @ns: namespace (optional) * @name: the node name - * @content: the text content if any + * @content: raw text content (optional) + * + * Create an element node. * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). + * If provided, @value should be a raw, unescaped string. * - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns, @@ -2353,8 +2222,17 @@ xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns, if (cur != NULL) { cur->doc = doc; if (content != NULL) { - cur->children = xmlNewDocText(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) + xmlNodePtr text; + + text = xmlNewDocText(doc, content); + if (text == NULL) { + xmlFreeNode(cur); + return(NULL); + } + + cur->children = text; + cur->last = text; + text->parent = cur; } } return(cur); @@ -2362,10 +2240,12 @@ xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns, /** * xmlNewDocFragment: - * @doc: the document owning the fragment + * @doc: the target document (optional) * - * Creation of a new Fragment node. - * Returns a pointer to the new node object. + * Create a document fragment node. + * + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewDocFragment(xmlDocPtr doc) { @@ -2375,10 +2255,8 @@ xmlNewDocFragment(xmlDocPtr doc) { * Allocate a new DocumentFragment node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building fragment"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_DOCUMENT_FRAG_NODE; @@ -2392,13 +2270,14 @@ xmlNewDocFragment(xmlDocPtr doc) { /** * xmlNewText: - * @content: the text content + * @content: raw text content (optional) * - * Creation of a new text node. + * Create a text node. * * Use of this function is DISCOURAGED in favor of xmlNewDocText. * - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewText(const xmlChar *content) { @@ -2408,83 +2287,77 @@ xmlNewText(const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building text"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_TEXT_NODE; cur->name = xmlStringText; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } #ifdef LIBXML_TREE_ENABLED /** * xmlNewTextChild: * @parent: the parent node - * @ns: a namespace if any + * @ns: a namespace (optional) * @name: the name of the child - * @content: the text content of the child if any. + * @content: raw text content of the child (optional) + * + * Create a new child element and append it to a parent element. + * + * If @ns is NULL, the newly created element inherits the namespace + * of the parent. * - * Creation of a new child element, added at the end of @parent children list. - * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly - * created element inherits the namespace of @parent. If @content is non NULL, - * a child TEXT node will be created containing the string @content. - * NOTE: Use xmlNewChild() if @content will contain entities that need to be - * preserved. Use this function, xmlNewTextChild(), if you need to ensure that - * reserved XML chars that might appear in @content, such as the ampersand, - * greater-than or less-than signs, are automatically replaced by their XML - * escaped entity representations. + * If @content is provided, a text node will be added to the child + * element, see xmlNewDocRawNode. * - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if arguments + * are invalid or a memory allocation failed. */ xmlNodePtr xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content) { xmlNodePtr cur, prev; - if (parent == NULL) { + if ((parent == NULL) || (name == NULL)) return(NULL); - } - if (name == NULL) { - return(NULL); - } + switch (parent->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: + break; - /* - * Allocate a new node - */ - if (parent->type == XML_ELEMENT_NODE) { - if (ns == NULL) - cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content); - else - cur = xmlNewDocRawNode(parent->doc, ns, name, content); - } else if ((parent->type == XML_DOCUMENT_NODE) || - (parent->type == XML_HTML_DOCUMENT_NODE)) { - if (ns == NULL) - cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content); - else - cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content); - } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { - cur = xmlNewDocRawNode( parent->doc, ns, name, content); - } else { - return(NULL); + case XML_ELEMENT_NODE: + if (ns == NULL) + ns = parent->ns; + break; + + default: + return(NULL); } - if (cur == NULL) return(NULL); + + cur = xmlNewDocRawNode(parent->doc, ns, name, content); + if (cur == NULL) + return(NULL); /* * add the new element at the end of the children list. */ - cur->type = XML_ELEMENT_NODE; cur->parent = parent; - cur->doc = parent->doc; if (parent->children == NULL) { parent->children = cur; parent->last = cur; @@ -2500,55 +2373,92 @@ xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns, #endif /* LIBXML_TREE_ENABLED */ /** - * xmlNewCharRef: - * @doc: the document - * @name: the char ref string, starting with # or "&# ... ;" + * xmlNewEntityRef: + * @doc: the target document (optional) + * @name: the entity name * - * Creation of a new character reference node. - * Returns a pointer to the new node object. + * Create an empty entity reference node. This function doesn't attempt + * to look up the entity in @doc. + * + * @name is consumed. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ -xmlNodePtr -xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { +static xmlNodePtr +xmlNewEntityRef(xmlDocPtr doc, xmlChar *name) { xmlNodePtr cur; - if (name == NULL) - return(NULL); - /* * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); if (cur == NULL) { - xmlTreeErrMemory("building character reference"); + xmlFree(name); return(NULL); } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ENTITY_REF_NODE; - cur->doc = doc; + cur->name = name; + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue(cur); + + return(cur); +} + +/** + * xmlNewCharRef: + * @doc: the target document (optional) + * @name: the entity name + * + * This function is MISNAMED. It doesn't create a character reference + * but an entity reference. + * + * Create an empty entity reference node. This function doesn't attempt + * to look up the entity in @doc. + * + * Entity names like '&entity;' are handled as well. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. + */ +xmlNodePtr +xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { + xmlChar *copy; + + if (name == NULL) + return(NULL); + if (name[0] == '&') { int len; name++; len = xmlStrlen(name); if (name[len - 1] == ';') - cur->name = xmlStrndup(name, len - 1); + copy = xmlStrndup(name, len - 1); else - cur->name = xmlStrndup(name, len); + copy = xmlStrndup(name, len); } else - cur->name = xmlStrdup(name); + copy = xmlStrdup(name); + if (copy == NULL) + return(NULL); - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) - xmlRegisterNodeDefaultValue(cur); - return(cur); + return(xmlNewEntityRef(doc, copy)); } /** * xmlNewReference: - * @doc: the document - * @name: the reference name, or the reference string with & and ; + * @doc: the target document (optional) + * @name: the entity name + * + * Create a new entity reference node, linking the result with the + * entity in @doc if found. * - * Creation of a new reference node. - * Returns a pointer to the new node object. + * Entity names like '&entity;' are handled as well. + * + * Returns a pointer to the new node object or NULL if arguments are + * invalid or a memory allocation failed. */ xmlNodePtr xmlNewReference(const xmlDoc *doc, const xmlChar *name) { @@ -2562,10 +2472,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building reference"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ENTITY_REF_NODE; @@ -2580,6 +2488,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { cur->name = xmlStrndup(name, len); } else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; ent = xmlGetDocEntity(doc, cur->name); if (ent != NULL) { @@ -2596,15 +2506,21 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** * xmlNewDocText: - * @doc: the document - * @content: the text content + * @doc: the target document + * @content: raw text content (optional) * - * Creation of a new text node within a document. - * Returns a pointer to the new node object. + * Create a new text node. + * + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewDocText(const xmlDoc *doc, const xmlChar *content) { @@ -2617,13 +2533,13 @@ xmlNewDocText(const xmlDoc *doc, const xmlChar *content) { /** * xmlNewTextLen: - * @content: the text content - * @len: the text len. + * @content: raw text content (optional) + * @len: size of text content * * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen. * - * Creation of a new text node with an extra parameter for the content's length - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewTextLen(const xmlChar *content, int len) { @@ -2633,16 +2549,18 @@ xmlNewTextLen(const xmlChar *content, int len) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building text"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_TEXT_NODE; cur->name = xmlStringText; if (content != NULL) { cur->content = xmlStrndup(content, len); + if (cur->content == NULL) { + xmlFreeNode(cur); + return(NULL); + } } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) @@ -2652,13 +2570,14 @@ xmlNewTextLen(const xmlChar *content, int len) { /** * xmlNewDocTextLen: - * @doc: the document - * @content: the text content - * @len: the text len. + * @doc: the target document + * @content: raw text content (optional) + * @len: size of text content + * + * Create a new text node. * - * Creation of a new text node with an extra content length parameter. The - * text node pertain to a given document. - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) { @@ -2671,12 +2590,14 @@ xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) { /** * xmlNewComment: - * @content: the comment content + * @content: the comment content (optional) * * Use of this function is DISCOURAGED in favor of xmlNewDocComment. * - * Creation of a new node containing a comment. - * Returns a pointer to the new node object. + * Create a comment node. + * + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewComment(const xmlChar *content) { @@ -2686,31 +2607,37 @@ xmlNewComment(const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building comment"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_COMMENT_NODE; cur->name = xmlStringComment; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** * xmlNewCDataBlock: - * @doc: the document - * @content: the CDATA block content content - * @len: the length of the block + * @doc: the target document (optional) + * @content: raw text content (optional) + * @len: size of text content + * + * Create a CDATA section node. * - * Creation of a new node containing a CDATA block. - * Returns a pointer to the new node object. + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { @@ -2720,16 +2647,18 @@ xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building CDATA"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_CDATA_SECTION_NODE; cur->doc = doc; if (content != NULL) { cur->content = xmlStrndup(content, len); + if (cur->content == NULL) { + xmlFree(cur); + return(NULL); + } } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) @@ -2742,8 +2671,10 @@ xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { * @doc: the document * @content: the comment content * - * Creation of a new node containing a comment within a document. - * Returns a pointer to the new node object. + * Create a comment node. + * + * Returns a pointer to the new node object or NULL if a memory + * allocation failed. */ xmlNodePtr xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) { @@ -2754,164 +2685,293 @@ xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) { return(cur); } -static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) { - const xmlChar *newValue = oldValue; - if (oldValue) { - int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1); - if (oldDictOwnsOldValue) { +static void +xmlRemoveEntity(xmlEntityPtr ent) { + xmlDocPtr doc = ent->doc; + xmlDtdPtr intSubset, extSubset; + + if (doc == NULL) + return; + intSubset = doc->intSubset; + extSubset = doc->extSubset; + + if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) || + (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) || + (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY)) { + if (intSubset != NULL) { + if (xmlHashLookup(intSubset->entities, ent->name) == ent) + xmlHashRemoveEntry(intSubset->entities, ent->name, NULL); + } + if (extSubset != NULL) { + if (xmlHashLookup(extSubset->entities, ent->name) == ent) + xmlHashRemoveEntry(extSubset->entities, ent->name, NULL); + } + } else if ((ent->etype == XML_INTERNAL_PARAMETER_ENTITY) || + (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY)) { + if (intSubset != NULL) { + if (xmlHashLookup(intSubset->pentities, ent->name) == ent) + xmlHashRemoveEntry(intSubset->entities, ent->name, NULL); + } + if (extSubset != NULL) { + if (xmlHashLookup(extSubset->pentities, ent->name) == ent) + xmlHashRemoveEntry(extSubset->entities, ent->name, NULL); + } + } +} + +static int +xmlNodeSetDoc(xmlNodePtr node, xmlDocPtr doc) { + xmlDocPtr oldDoc; + xmlDictPtr oldDict, newDict; + int ret = 0; + + /* + * Remove name and content from old dictionary + */ + + oldDoc = node->doc; + oldDict = oldDoc ? oldDoc->dict : NULL; + newDict = doc ? doc->dict : NULL; + + if ((oldDict != NULL) && (oldDict != newDict)) { + if ((node->name != NULL) && + ((node->type == XML_ELEMENT_NODE) || + (node->type == XML_ATTRIBUTE_NODE) || + (node->type == XML_PI_NODE) || + (node->type == XML_ENTITY_REF_NODE)) && + (xmlDictOwns(oldDict, node->name))) { if (newDict) - newValue = xmlDictLookup(newDict, oldValue, -1); + node->name = xmlDictLookup(newDict, node->name, -1); else - newValue = xmlStrdup(oldValue); + node->name = xmlStrdup(node->name); + if (node->name == NULL) + ret = -1; + } + + if ((node->content != NULL) && + ((node->type == XML_TEXT_NODE) || + (node->type == XML_CDATA_SECTION_NODE)) && + (xmlDictOwns(oldDict, node->content))) { + node->content = xmlStrdup(node->content); + if (node->content == NULL) + ret = -1; + } + } + + switch (node->type) { + case XML_ATTRIBUTE_NODE: { + xmlAttrPtr attr = (xmlAttrPtr) node; + + /* + * Handle IDs + * + * TODO: ID attributes should also be added to the new + * document, but it's not clear how to handle clashes. + */ + if (attr->atype == XML_ATTRIBUTE_ID) + xmlRemoveID(oldDoc, attr); + + break; } + + case XML_ENTITY_REF_NODE: + /* + * Handle entity references + */ + node->children = NULL; + node->last = NULL; + node->content = NULL; + + if ((doc != NULL) && + ((doc->intSubset != NULL) || (doc->extSubset != NULL))) { + xmlEntityPtr ent; + + /* + * Assign new entity node if available + */ + ent = xmlGetDocEntity(doc, node->name); + if (ent != NULL) { + node->children = (xmlNodePtr) ent; + node->last = (xmlNodePtr) ent; + node->content = ent->content; + } + } + + break; + + case XML_DTD_NODE: + if (oldDoc != NULL) { + if (oldDoc->intSubset == (xmlDtdPtr) node) + oldDoc->intSubset = NULL; + if (oldDoc->extSubset == (xmlDtdPtr) node) + oldDoc->extSubset = NULL; + } + + break; + + case XML_ENTITY_DECL: + xmlRemoveEntity((xmlEntityPtr) node); + break; + + /* + * TODO: + * - Remove element decls from doc->elements + * - Remove attribtue decls form doc->attributes + */ + + default: + break; } - return newValue; + + /* + * Set new document + */ + node->doc = doc; + + return(ret); } /** * xmlSetTreeDoc: - * @tree: the top element - * @doc: the document + * @tree: root of a subtree + * @doc: new document + * + * This is an internal function which shouldn't be used. It is + * invoked by functions like xmlAddChild, xmlAddSibling or + * xmlReplaceNode. @tree must be the root node of an unlinked + * subtree. + * + * Associate all nodes in a tree with a new document. + * + * Also copy strings from the old document's dictionary and + * remove ID attributes from the old ID table. * - * update all nodes under the tree to point to the right document + * Returns 0 on success. If a memory allocation fails, returns -1. + * The whole tree will be updated on failure but some strings + * may be lost. */ -void +int xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { - xmlAttrPtr prop; + int ret = 0; if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL)) - return; - if (tree->doc != doc) { - xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL; - xmlDictPtr newDict = doc ? doc->dict : NULL; - - if(tree->type == XML_ELEMENT_NODE) { - prop = tree->properties; - while (prop != NULL) { - if (prop->atype == XML_ATTRIBUTE_ID) { - xmlRemoveID(tree->doc, prop); - } + return(0); + if (tree->doc == doc) + return(0); - if (prop->doc != doc) { - xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL; - prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name); - prop->doc = doc; - } - xmlSetListDoc(prop->children, doc); + if (tree->type == XML_ELEMENT_NODE) { + xmlAttrPtr prop = tree->properties; - /* - * TODO: ID attributes should be also added to the new - * document, but this breaks things like xmlReplaceNode. - * The underlying problem is that xmlRemoveID is only called - * if a node is destroyed, not if it's unlinked. - */ -#if 0 - if (xmlIsID(doc, tree, prop)) { - xmlChar *idVal = xmlNodeListGetString(doc, prop->children, - 1); - xmlAddID(NULL, doc, idVal, prop); - } -#endif + while (prop != NULL) { + if (prop->children != NULL) { + if (xmlSetListDoc(prop->children, doc) < 0) + ret = -1; + } - prop = prop->next; - } - } - if (tree->type == XML_ENTITY_REF_NODE) { - /* - * Clear 'children' which points to the entity declaration - * from the original document. - */ - tree->children = NULL; - } else if (tree->children != NULL) { - xmlSetListDoc(tree->children, doc); + if (xmlNodeSetDoc((xmlNodePtr) prop, doc) < 0) + ret = -1; + + prop = prop->next; } + } - tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name); - tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content); - /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */ - tree->doc = doc; + if ((tree->children != NULL) && + (tree->type != XML_ENTITY_REF_NODE)) { + if (xmlSetListDoc(tree->children, doc) < 0) + ret = -1; } + + if (xmlNodeSetDoc(tree, doc) < 0) + ret = -1; + + return(ret); } /** * xmlSetListDoc: - * @list: the first element - * @doc: the document + * @list: a node list + * @doc: new document + * + * Associate all subtrees in @list with a new document. * - * update all nodes in the list to point to the right document + * Internal function, see xmlSetTreeDoc. + * + * Returns 0 on success. If a memory allocation fails, returns -1. + * All subtrees will be updated on failure but some strings + * may be lost. */ -void +int xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) { xmlNodePtr cur; + int ret = 0; if ((list == NULL) || (list->type == XML_NAMESPACE_DECL)) - return; + return(0); + cur = list; while (cur != NULL) { - if (cur->doc != doc) - xmlSetTreeDoc(cur, doc); + if (cur->doc != doc) { + if (xmlSetTreeDoc(cur, doc) < 0) + ret = -1; + } cur = cur->next; } + + return(ret); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) /** * xmlNewChild: * @parent: the parent node - * @ns: a namespace if any + * @ns: a namespace (optional) * @name: the name of the child - * @content: the XML content of the child if any. + * @content: text content with XML references (optional) * - * Creation of a new child element, added at the end of @parent children list. - * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly - * created element inherits the namespace of @parent. If @content is non NULL, - * a child list containing the TEXTs and ENTITY_REFs node will be created. - * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity - * references. XML special chars must be escaped first by using - * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used. + * Create a new child element and append it to a parent element. * - * Returns a pointer to the new node object. + * If @ns is NULL, the newly created element inherits the namespace + * of the parent. + * + * If provided, @content is expected to be a valid XML attribute + * value possibly containing character and entity references. Text + * and entity reference node will be added to the child element, + * see xmlNewDocNode. + * + * Returns a pointer to the new node object or NULL if arguments + * are invalid or a memory allocation failed. */ xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content) { xmlNodePtr cur, prev; - if (parent == NULL) { + if ((parent == NULL) || (name == NULL)) return(NULL); - } - if (name == NULL) { - return(NULL); - } + switch (parent->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_DOCUMENT_FRAG_NODE: + break; - /* - * Allocate a new node - */ - if (parent->type == XML_ELEMENT_NODE) { - if (ns == NULL) - cur = xmlNewDocNode(parent->doc, parent->ns, name, content); - else - cur = xmlNewDocNode(parent->doc, ns, name, content); - } else if ((parent->type == XML_DOCUMENT_NODE) || - (parent->type == XML_HTML_DOCUMENT_NODE)) { - if (ns == NULL) - cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content); - else - cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content); - } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { - cur = xmlNewDocNode( parent->doc, ns, name, content); - } else { - return(NULL); + case XML_ELEMENT_NODE: + if (ns == NULL) + ns = parent->ns; + break; + + default: + return(NULL); } - if (cur == NULL) return(NULL); + + cur = xmlNewDocNode(parent->doc, ns, name, content); + if (cur == NULL) + return(NULL); /* * add the new element at the end of the children list. */ - cur->type = XML_ELEMENT_NODE; cur->parent = parent; - cur->doc = parent->doc; if (parent->children == NULL) { parent->children = cur; parent->last = cur; @@ -2926,261 +2986,274 @@ xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, } #endif /* LIBXML_TREE_ENABLED */ -/** - * xmlAddPropSibling: - * @prev: the attribute to which @prop is added after - * @cur: the base attribute passed to calling function - * @prop: the new attribute - * - * Add a new attribute after @prev using @cur as base attribute. - * When inserting before @cur, @prev is passed as @cur->prev. - * When inserting after @cur, @prev is passed as @cur. - * If an existing attribute is found it is destroyed prior to adding @prop. - * - * See the note regarding namespaces in xmlAddChild. - * - * Returns the attribute being inserted or NULL in case of error. - */ +static void +xmlTextSetContent(xmlNodePtr text, xmlChar *content) { + if ((text->content != NULL) && + (text->content != (xmlChar *) &text->properties)) { + xmlDocPtr doc = text->doc; + + if ((doc == NULL) || + (doc->dict == NULL) || + (!xmlDictOwns(doc->dict, text->content))) + xmlFree(text->content); + } + + text->content = content; + text->properties = NULL; +} + +static int +xmlTextAddContent(xmlNodePtr text, const xmlChar *content, int len) { + xmlChar *merged; + + if (content == NULL) + return(0); + + merged = xmlStrncatNew(text->content, content, len); + if (merged == NULL) + return(-1); + + xmlTextSetContent(text, merged); + return(0); +} + static xmlNodePtr -xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) { - xmlAttrPtr attr; +xmlInsertProp(xmlDocPtr doc, xmlNodePtr cur, xmlNodePtr parent, + xmlNodePtr prev, xmlNodePtr next) { + xmlAttrPtr attr; - if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) || - (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) || - ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE))) - return(NULL); + if (((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)) || + ((next != NULL) && (next->type != XML_ATTRIBUTE_NODE))) + return(NULL); - /* check if an attribute with the same name exists */ - if (prop->ns == NULL) - attr = xmlHasNsProp(cur->parent, prop->name, NULL); - else - attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href); + /* check if an attribute with the same name exists */ + attr = xmlGetPropNodeInternal(parent, cur->name, + cur->ns ? cur->ns->href : NULL, 0); - if (prop->doc != cur->doc) { - xmlSetTreeDoc(prop, cur->doc); - } - prop->parent = cur->parent; - prop->prev = prev; - if (prev != NULL) { - prop->next = prev->next; - prev->next = prop; - if (prop->next) - prop->next->prev = prop; - } else { - prop->next = cur; - cur->prev = prop; + xmlUnlinkNodeInternal(cur); + + if (cur->doc != doc) { + if (xmlSetTreeDoc(cur, doc) < 0) + return(NULL); + } + + cur->parent = parent; + cur->prev = prev; + cur->next = next; + + if (prev == NULL) { + if (parent != NULL) + parent->properties = (xmlAttrPtr) cur; + } else { + prev->next = cur; + } + if (next != NULL) { + next->prev = cur; + } + + if ((attr != NULL) && (attr != (xmlAttrPtr) cur)) { + /* different instance, destroy it (attributes must be unique) */ + xmlRemoveProp((xmlAttrPtr) attr); + } + + return cur; +} + +static xmlNodePtr +xmlInsertNode(xmlDocPtr doc, xmlNodePtr cur, xmlNodePtr parent, + xmlNodePtr prev, xmlNodePtr next, int coalesce) { + xmlNodePtr oldParent; + + if (cur->type == XML_ATTRIBUTE_NODE) + return xmlInsertProp(doc, cur, parent, prev, next); + + /* + * Coalesce text nodes + */ + if ((coalesce) && (cur->type == XML_TEXT_NODE)) { + if ((prev != NULL) && (prev->type == XML_TEXT_NODE) && + (prev->name == cur->name)) { + if (xmlTextAddContent(prev, cur->content, -1) < 0) + return(NULL); + xmlUnlinkNodeInternal(cur); + xmlFreeNode(cur); + return(prev); } - if (prop->prev == NULL && prop->parent != NULL) - prop->parent->properties = (xmlAttrPtr) prop; - if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) { - /* different instance, destroy it (attributes must be unique) */ - xmlRemoveProp((xmlAttrPtr) attr); + + if ((next != NULL) && (next->type == XML_TEXT_NODE) && + (next->name == cur->name)) { + if (cur->content != NULL) { + xmlChar *merged; + + merged = xmlStrncatNew(cur->content, next->content, -1); + if (merged == NULL) + return(NULL); + xmlTextSetContent(next, merged); + } + + xmlUnlinkNodeInternal(cur); + xmlFreeNode(cur); + return(next); } - return prop; + } + + /* Unlink */ + oldParent = cur->parent; + if (oldParent != NULL) { + if (oldParent->children == cur) + oldParent->children = cur->next; + if (oldParent->last == cur) + oldParent->last = cur->prev; + } + if (cur->next != NULL) + cur->next->prev = cur->prev; + if (cur->prev != NULL) + cur->prev->next = cur->next; + + if (cur->doc != doc) { + if (xmlSetTreeDoc(cur, doc) < 0) { + /* + * We shouldn't make any modifications to the inserted + * tree if a memory allocation fails, but that's hard to + * implement. The tree has been moved to the target + * document now but some contents are corrupted. + * Unlinking is the best we can do. + */ + cur->parent = NULL; + cur->prev = NULL; + cur->next = NULL; + return(NULL); + } + } + + cur->parent = parent; + cur->prev = prev; + cur->next = next; + + if (prev == NULL) { + if (parent != NULL) + parent->children = cur; + } else { + prev->next = cur; + } + if (next == NULL) { + if (parent != NULL) + parent->last = cur; + } else { + next->prev = cur; + } + + return(cur); } /** * xmlAddNextSibling: - * @cur: the child node - * @elem: the new node + * @prev: the target node + * @cur: the new node * - * Add a new node @elem as the next sibling of @cur - * If the new node was already inserted in a document it is - * first unlinked from its existing context. - * As a result of text merging @elem may be freed. - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. + * Unlinks @cur and inserts it as next sibling after @prev. * - * See the note regarding namespaces in xmlAddChild. + * Unlike xmlAddChild this function does not merge text nodes. * - * Returns the new node or NULL in case of error. + * If @cur is an attribute node, it is inserted after attribute + * @prev. If the attribute list contains an attribute with a name + * matching @cur, the old attribute is destroyed. + * + * See the notes in xmlAddChild. + * + * Returns @cur or a sibling if @cur was merged. Returns NULL + * if arguments are invalid or a memory allocation failed. */ xmlNodePtr -xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { - if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - - if (cur == elem) { +xmlAddNextSibling(xmlNodePtr prev, xmlNodePtr cur) { + if ((prev == NULL) || (prev->type == XML_NAMESPACE_DECL) || + (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) || + (cur == prev)) return(NULL); - } - - xmlUnlinkNode(elem); - if (elem->type == XML_TEXT_NODE) { - if (cur->type == XML_TEXT_NODE) { - xmlNodeAddContent(cur, elem->content); - xmlFreeNode(elem); - return(cur); - } - if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) && - (cur->name == cur->next->name)) { - xmlChar *tmp; - - tmp = xmlStrdup(elem->content); - tmp = xmlStrcat(tmp, cur->next->content); - xmlNodeSetContent(cur->next, tmp); - xmlFree(tmp); - xmlFreeNode(elem); - return(cur->next); - } - } else if (elem->type == XML_ATTRIBUTE_NODE) { - return xmlAddPropSibling(cur, cur, elem); - } + if (cur == prev->next) + return(cur); - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - elem->parent = cur->parent; - elem->prev = cur; - elem->next = cur->next; - cur->next = elem; - if (elem->next != NULL) - elem->next->prev = elem; - if ((elem->parent != NULL) && (elem->parent->last == cur)) - elem->parent->last = elem; - return(elem); + return(xmlInsertNode(prev->doc, cur, prev->parent, prev, prev->next, 0)); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) /** * xmlAddPrevSibling: - * @cur: the child node - * @elem: the new node + * @next: the target node + * @cur: the new node + * + * Unlinks @cur and inserts it as previous sibling before @next. * - * Add a new node @elem as the previous sibling of @cur - * merging adjacent TEXT nodes (@elem may be freed) - * If the new node was already inserted in a document it is - * first unlinked from its existing context. - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. + * Unlike xmlAddChild this function does not merge text nodes. * - * See the note regarding namespaces in xmlAddChild. + * If @cur is an attribute node, it is inserted before attribute + * @next. If the attribute list contains an attribute with a name + * matching @cur, the old attribute is destroyed. * - * Returns the new node or NULL in case of error. + * See the notes in xmlAddChild. + * + * Returns @cur or a sibling if @cur was merged. Returns NULL + * if arguments are invalid or a memory allocation failed. */ xmlNodePtr -xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { - if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { +xmlAddPrevSibling(xmlNodePtr next, xmlNodePtr cur) { + if ((next == NULL) || (next->type == XML_NAMESPACE_DECL) || + (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) || + (cur == next)) return(NULL); - } - - if (cur == elem) { - return(NULL); - } - xmlUnlinkNode(elem); + if (cur == next->prev) + return(cur); - if (elem->type == XML_TEXT_NODE) { - if (cur->type == XML_TEXT_NODE) { - xmlChar *tmp; - - tmp = xmlStrdup(elem->content); - tmp = xmlStrcat(tmp, cur->content); - xmlNodeSetContent(cur, tmp); - xmlFree(tmp); - xmlFreeNode(elem); - return(cur); - } - if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) && - (cur->name == cur->prev->name)) { - xmlNodeAddContent(cur->prev, elem->content); - xmlFreeNode(elem); - return(cur->prev); - } - } else if (elem->type == XML_ATTRIBUTE_NODE) { - return xmlAddPropSibling(cur->prev, cur, elem); - } - - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - elem->parent = cur->parent; - elem->next = cur; - elem->prev = cur->prev; - cur->prev = elem; - if (elem->prev != NULL) - elem->prev->next = elem; - if ((elem->parent != NULL) && (elem->parent->children == cur)) { - elem->parent->children = elem; - } - return(elem); + return(xmlInsertNode(next->doc, cur, next->parent, next->prev, next, 0)); } #endif /* LIBXML_TREE_ENABLED */ /** * xmlAddSibling: - * @cur: the child node - * @elem: the new node + * @node: the target node + * @cur: the new node * - * Add a new element @elem to the list of siblings of @cur - * merging adjacent TEXT nodes (@elem may be freed) - * If the new element was already inserted in a document it is - * first unlinked from its existing context. + * Unlinks @cur and inserts it as last sibling of @node. * - * See the note regarding namespaces in xmlAddChild. + * If @cur is a text node, it may be merged with an adjacent text + * node and freed. In this case the text node containing the merged + * content is returned. * - * Returns the new element or NULL in case of error. + * If @cur is an attribute node, it is appended to the attribute + * list containing @node. If the attribute list contains an attribute + * with a name matching @cur, the old attribute is destroyed. + * + * See the notes in xmlAddChild. + * + * Returns @cur or a sibling if @cur was merged. Returns NULL + * if arguments are invalid or a memory allocation failed. */ xmlNodePtr -xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { - xmlNodePtr parent; - - if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - - if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - - if (cur == elem) { +xmlAddSibling(xmlNodePtr node, xmlNodePtr cur) { + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || + (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) || + (cur == node)) return(NULL); - } /* * Constant time is we can rely on the ->parent->last to find * the last sibling. */ - if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) && - (cur->parent->children != NULL) && - (cur->parent->last != NULL) && - (cur->parent->last->next == NULL)) { - cur = cur->parent->last; + if ((node->type != XML_ATTRIBUTE_NODE) && (node->parent != NULL)) { + if (node->parent->last != NULL) + node = node->parent->last; } else { - while (cur->next != NULL) cur = cur->next; - } - - xmlUnlinkNode(elem); - - if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) && - (cur->name == elem->name)) { - xmlNodeAddContent(cur, elem->content); - xmlFreeNode(elem); - return(cur); - } else if (elem->type == XML_ATTRIBUTE_NODE) { - return xmlAddPropSibling(cur, cur, elem); + while (node->next != NULL) + node = node->next; } - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - parent = cur->parent; - elem->prev = cur; - elem->next = NULL; - elem->parent = parent; - cur->next = elem; - if (parent != NULL) - parent->last = elem; + if (cur == node) + return(cur); - return(elem); + return(xmlInsertNode(node->doc, cur, node->parent, node, NULL, 1)); } /** @@ -3188,16 +3261,17 @@ xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { * @parent: the parent node * @cur: the first node in the list * - * Add a list of node at the end of the child list of the parent - * merging adjacent TEXT nodes (@cur may be freed) + * Append a node list to another node. * - * See the note regarding namespaces in xmlAddChild. + * See xmlAddChild. * * Returns the last child or NULL in case of error. */ xmlNodePtr xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { + xmlNodePtr iter; xmlNodePtr prev; + int oom; if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { return(NULL); @@ -3207,9 +3281,15 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { return(NULL); } - if ((cur->doc != NULL) && (parent->doc != NULL) && - (cur->doc != parent->doc)) { + oom = 0; + for (iter = cur; iter != NULL; iter = iter->next) { + if (iter->doc != parent->doc) { + if (xmlSetTreeDoc(iter, parent->doc) < 0) + oom = 1; + } } + if (oom) + return(NULL); /* * add the first element at the end of the children list. @@ -3218,40 +3298,36 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { if (parent->children == NULL) { parent->children = cur; } else { + prev = parent->last; + /* * If cur and parent->last both are TEXT nodes, then merge them. */ if ((cur->type == XML_TEXT_NODE) && - (parent->last->type == XML_TEXT_NODE) && - (cur->name == parent->last->name)) { - xmlNodeAddContent(parent->last, cur->content); + (prev->type == XML_TEXT_NODE) && + (cur->name == prev->name)) { + xmlNodePtr next; + + if (xmlTextAddContent(prev, cur->content, -1) < 0) + return(NULL); + next = cur->next; + xmlFreeNode(cur); /* * if it's the only child, nothing more to be done. */ - if (cur->next == NULL) { - xmlFreeNode(cur); - return(parent->last); - } - prev = cur; - cur = cur->next; - xmlFreeNode(prev); + if (next == NULL) + return(prev); + cur = next; } - prev = parent->last; + prev->next = cur; cur->prev = prev; } while (cur->next != NULL) { cur->parent = parent; - if (cur->doc != parent->doc) { - xmlSetTreeDoc(cur, parent->doc); - } cur = cur->next; } cur->parent = parent; - /* the parent may not be linked to a doc ! */ - if (cur->doc != parent->doc) { - xmlSetTreeDoc(cur, parent->doc); - } parent->last = cur; return(cur); @@ -3262,130 +3338,87 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { * @parent: the parent node * @cur: the child node * - * Add a new node to @parent, at the end of the child (or property) list - * merging adjacent TEXT nodes (in which case @cur is freed) - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. + * Unlink @cur and append it to the children of @parent. * - * All tree manipulation functions can safely move nodes within a document. - * But when moving nodes from one document to another, references to - * namespaces in element or attribute nodes are NOT fixed. In this case, - * you MUST call xmlReconciliateNs after the move operation to avoid - * memory errors. + * If @cur is a text node, it may be merged with an adjacent text + * node and freed. In this case the text node containing the merged + * content is returned. * - * Returns the child or NULL in case of error. + * If @cur is an attribute node, it is appended to the attributes of + * @parent. If the attribute list contains an attribute with a name + * matching @elem, the old attribute is destroyed. + * + * General notes: + * + * Move operations like xmlAddChild can cause element or attribute + * nodes to reference namespaces that aren't declared in one of + * their ancestors. This can lead to use-after-free errors if the + * elements containing the declarations are freed later, especially + * when moving nodes from one document to another. You should + * consider calling xmlReconciliateNs after a move operation to + * normalize namespaces. Another option is to call + * xmlDOMWrapAdoptNode with the target parent before moving a node. + * + * For the most part, move operations don't check whether the + * resulting tree structure is valid. Users must make sure that + * parent nodes only receive children of valid types. Inserted + * child nodes must never be an ancestor of the parent node to + * avoid cycles in the tree structure. In general, only + * document, document fragments, elements and attributes + * should be used as parent nodes. + * + * When moving a node between documents and a memory allocation + * fails, the node's content will be corrupted and it will be + * unlinked. In this case, the node must be freed manually. + * + * Moving DTDs between documents isn't supported. + * + * Returns @elem or a sibling if @elem was merged. Returns NULL + * if arguments are invalid or a memory allocation failed. */ xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { xmlNodePtr prev; - if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - - if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { - return(NULL); - } - - if (parent == cur) { - return(NULL); - } - /* - * If cur is a TEXT node, merge its content with adjacent TEXT nodes - * cur is then freed. - */ - if (cur->type == XML_TEXT_NODE) { - if ((parent->type == XML_TEXT_NODE) && - (parent->content != NULL) && - (parent->name == cur->name)) { - xmlNodeAddContent(parent, cur->content); - xmlFreeNode(cur); - return(parent); - } - if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) && - (parent->last->name == cur->name) && - (parent->last != cur)) { - xmlNodeAddContent(parent->last, cur->content); - xmlFreeNode(cur); - return(parent->last); - } - } + if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL) || + (cur == NULL) || (cur->type == XML_NAMESPACE_DECL) || + (parent == cur)) + return(NULL); /* - * add the new element at the end of the children list. + * If parent is a text node, call xmlTextAddContent. This + * undocumented quirk should probably be removed. */ - prev = cur->parent; - cur->parent = parent; - if (cur->doc != parent->doc) { - xmlSetTreeDoc(cur, parent->doc); + if (parent->type == XML_TEXT_NODE) { + if (xmlTextAddContent(parent, cur->content, -1) < 0) + return(NULL); + xmlFreeNode(cur); + return(parent); } - /* this check prevents a loop on tree-traversions if a developer - * tries to add a node to its parent multiple times - */ - if (prev == parent) - return(cur); - /* - * Coalescing - */ - if ((parent->type == XML_TEXT_NODE) && - (parent->content != NULL) && - (parent != cur)) { - xmlNodeAddContent(parent, cur->content); - xmlFreeNode(cur); - return(parent); - } if (cur->type == XML_ATTRIBUTE_NODE) { - if (parent->type != XML_ELEMENT_NODE) - return(NULL); - if (parent->properties != NULL) { - /* check if an attribute with the same name exists */ - xmlAttrPtr lastattr; - - if (cur->ns == NULL) - lastattr = xmlHasNsProp(parent, cur->name, NULL); - else - lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href); - if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) { - /* different instance, destroy it (attributes must be unique) */ - xmlUnlinkNode((xmlNodePtr) lastattr); - xmlFreeProp(lastattr); - } - if (lastattr == (xmlAttrPtr) cur) - return(cur); - - } - if (parent->properties == NULL) { - parent->properties = (xmlAttrPtr) cur; - } else { - /* find the end */ - xmlAttrPtr lastattr = parent->properties; - while (lastattr->next != NULL) { - lastattr = lastattr->next; - } - lastattr->next = (xmlAttrPtr) cur; - ((xmlAttrPtr) cur)->prev = lastattr; - } + prev = (xmlNodePtr) parent->properties; + if (prev != NULL) { + while (prev->next != NULL) + prev = prev->next; + } } else { - if (parent->children == NULL) { - parent->children = cur; - parent->last = cur; - } else { - prev = parent->last; - prev->next = cur; - cur->prev = prev; - parent->last = cur; - } + prev = parent->last; } - return(cur); + + if (cur == prev) + return(cur); + + return(xmlInsertNode(parent->doc, cur, parent, prev, NULL, 1)); } /** * xmlGetLastChild: * @parent: the parent node * - * Search the last child of a node. - * Returns the last child or NULL if none. + * Find the last child of a node. + * + * Returns the last child or NULL if parent has no children. */ xmlNodePtr xmlGetLastChild(const xmlNode *parent) { @@ -3404,13 +3437,12 @@ xmlGetLastChild(const xmlNode *parent) { * xmlChildElementCount: * @parent: the parent node * - * Finds the current number of child nodes of that element which are - * element nodes. - * Note the handling of entities references is different than in - * the W3C DOM element traversal spec since we don't have back reference - * from entities content to entities references. + * Count the number of child nodes which are elements. * - * Returns the count of element child or 0 if not available + * Note that entity references are not expanded. + * + * Returns the number of element children or 0 if arguments are + * invalid. */ unsigned long xmlChildElementCount(xmlNodePtr parent) { @@ -3421,10 +3453,10 @@ xmlChildElementCount(xmlNodePtr parent) { return(0); switch (parent->type) { case XML_ELEMENT_NODE: - case XML_ENTITY_NODE: case XML_DOCUMENT_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_HTML_DOCUMENT_NODE: + case XML_ENTITY_DECL: cur = parent->children; break; default: @@ -3442,12 +3474,11 @@ xmlChildElementCount(xmlNodePtr parent) { * xmlFirstElementChild: * @parent: the parent node * - * Finds the first child node of that element which is a Element node - * Note the handling of entities references is different than in - * the W3C DOM element traversal spec since we don't have back reference - * from entities content to entities references. + * Find the first child node which is an element. * - * Returns the first element child or NULL if not available + * Note that entity references are not expanded. + * + * Returns the first element or NULL if parent has no children. */ xmlNodePtr xmlFirstElementChild(xmlNodePtr parent) { @@ -3457,10 +3488,10 @@ xmlFirstElementChild(xmlNodePtr parent) { return(NULL); switch (parent->type) { case XML_ELEMENT_NODE: - case XML_ENTITY_NODE: case XML_DOCUMENT_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_HTML_DOCUMENT_NODE: + case XML_ENTITY_DECL: cur = parent->children; break; default: @@ -3478,12 +3509,11 @@ xmlFirstElementChild(xmlNodePtr parent) { * xmlLastElementChild: * @parent: the parent node * - * Finds the last child node of that element which is a Element node - * Note the handling of entities references is different than in - * the W3C DOM element traversal spec since we don't have back reference - * from entities content to entities references. + * Find the last child node which is an element. * - * Returns the last element child or NULL if not available + * Note that entity references are not expanded. + * + * Returns the last element or NULL if parent has no children. */ xmlNodePtr xmlLastElementChild(xmlNodePtr parent) { @@ -3493,10 +3523,10 @@ xmlLastElementChild(xmlNodePtr parent) { return(NULL); switch (parent->type) { case XML_ELEMENT_NODE: - case XML_ENTITY_NODE: case XML_DOCUMENT_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_HTML_DOCUMENT_NODE: + case XML_ENTITY_DECL: cur = parent->last; break; default: @@ -3514,13 +3544,11 @@ xmlLastElementChild(xmlNodePtr parent) { * xmlPreviousElementSibling: * @node: the current node * - * Finds the first closest previous sibling of the node which is an - * element node. - * Note the handling of entities references is different than in - * the W3C DOM element traversal spec since we don't have back reference - * from entities content to entities references. + * Find the closest preceding sibling which is a element. * - * Returns the previous element sibling or NULL if not available + * Note that entity references are not expanded. + * + * Returns the sibling or NULL if no sibling was found. */ xmlNodePtr xmlPreviousElementSibling(xmlNodePtr node) { @@ -3531,7 +3559,6 @@ xmlPreviousElementSibling(xmlNodePtr node) { case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: case XML_XINCLUDE_START: @@ -3553,13 +3580,11 @@ xmlPreviousElementSibling(xmlNodePtr node) { * xmlNextElementSibling: * @node: the current node * - * Finds the first closest next sibling of the node which is an - * element node. - * Note the handling of entities references is different than in - * the W3C DOM element traversal spec since we don't have back reference - * from entities content to entities references. + * Find the closest following sibling which is a element. + * + * Note that entity references are not expanded. * - * Returns the next element sibling or NULL if not available + * Returns the sibling or NULL if no sibling was found. */ xmlNodePtr xmlNextElementSibling(xmlNodePtr node) { @@ -3570,7 +3595,6 @@ xmlNextElementSibling(xmlNodePtr node) { case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: case XML_DTD_NODE: @@ -3595,8 +3619,7 @@ xmlNextElementSibling(xmlNodePtr node) { * xmlFreeNodeList: * @cur: the first node in the list * - * Free a node and all its siblings, this is a recursive behaviour, all - * the children are freed too. + * Free a node list including all children. */ void xmlFreeNodeList(xmlNodePtr cur) { @@ -3626,8 +3649,14 @@ xmlFreeNodeList(xmlNodePtr cur) { if ((cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { xmlFreeDoc((xmlDocPtr) cur); - } else if (cur->type != XML_DTD_NODE) { - + } else if (cur->type == XML_DTD_NODE) { + /* + * TODO: We should consider freeing the DTD if it isn't + * referenced from doc->intSubset or doc->extSubset. + */ + cur->prev = NULL; + cur->next = NULL; + } else { if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue(cur); @@ -3678,8 +3707,10 @@ xmlFreeNodeList(xmlNodePtr cur) { * xmlFreeNode: * @cur: the node * - * Free a node, this is a recursive behaviour, all the children are freed too. - * This doesn't unlink the child from the list, use xmlUnlinkNode() first. + * Free a node including all the children. + * + * This doesn't unlink the node from the tree. Call xmlUnlinkNode first + * unless @cur is a root node. */ void xmlFreeNode(xmlNodePtr cur) { @@ -3742,54 +3773,16 @@ xmlFreeNode(xmlNodePtr cur) { } /** - * xmlUnlinkNode: + * xmlUnlinkNodeInternal: * @cur: the node * - * Unlink a node from it's current context, the node is not freed - * If one need to free the node, use xmlFreeNode() routine after the - * unlink to discard it. - * Note that namespace nodes can't be unlinked as they do not have - * pointer to their parent. + * Unlink a node from its tree. + * + * This function only unlinks the node from the tree. It doesn't + * clear references to DTD nodes. */ -void -xmlUnlinkNode(xmlNodePtr cur) { - if (cur == NULL) { - return; - } - if (cur->type == XML_NAMESPACE_DECL) - return; - if (cur->type == XML_DTD_NODE) { - xmlDocPtr doc; - doc = cur->doc; - if (doc != NULL) { - if (doc->intSubset == (xmlDtdPtr) cur) - doc->intSubset = NULL; - if (doc->extSubset == (xmlDtdPtr) cur) - doc->extSubset = NULL; - } - } - if (cur->type == XML_ENTITY_DECL) { - xmlDocPtr doc; - doc = cur->doc; - if (doc != NULL) { - if (doc->intSubset != NULL) { - if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur) - xmlHashRemoveEntry(doc->intSubset->entities, cur->name, - NULL); - if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur) - xmlHashRemoveEntry(doc->intSubset->pentities, cur->name, - NULL); - } - if (doc->extSubset != NULL) { - if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur) - xmlHashRemoveEntry(doc->extSubset->entities, cur->name, - NULL); - if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur) - xmlHashRemoveEntry(doc->extSubset->pentities, cur->name, - NULL); - } - } - } +static void +xmlUnlinkNodeInternal(xmlNodePtr cur) { if (cur->parent != NULL) { xmlNodePtr parent; parent = cur->parent; @@ -3804,26 +3797,67 @@ xmlUnlinkNode(xmlNodePtr cur) { } cur->parent = NULL; } + if (cur->next != NULL) cur->next->prev = cur->prev; if (cur->prev != NULL) cur->prev->next = cur->next; - cur->next = cur->prev = NULL; + cur->next = NULL; + cur->prev = NULL; +} + +/** + * xmlUnlinkNode: + * @cur: the node + * + * Unlink a node from its tree. + * + * The node is not freed. Unless it is reinserted, it must be managed + * manually and freed eventually by calling xmlFreeNode. + */ +void +xmlUnlinkNode(xmlNodePtr cur) { + if (cur == NULL) + return; + + if (cur->type == XML_NAMESPACE_DECL) + return; + + if (cur->type == XML_DTD_NODE) { + xmlDocPtr doc = cur->doc; + + if (doc != NULL) { + if (doc->intSubset == (xmlDtdPtr) cur) + doc->intSubset = NULL; + if (doc->extSubset == (xmlDtdPtr) cur) + doc->extSubset = NULL; + } + } + + if (cur->type == XML_ENTITY_DECL) + xmlRemoveEntity((xmlEntityPtr) cur); + + xmlUnlinkNodeInternal(cur); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) /** * xmlReplaceNode: * @old: the old node - * @cur: the node + * @cur: the node (optional) + * + * Unlink the old node. If @cur is provided, it is unlinked and + * inserted in place of @old. + * + * It is an error if @old has no parent. * - * Unlink the old node from its current context, prune the new one - * at the same place. If @cur was already inserted in a document it is - * first unlinked from its existing context. + * Unlike xmlAddChild, this function doesn't merge text nodes or + * delete duplicate attributes. * - * See the note regarding namespaces in xmlAddChild. + * See the notes in xmlAddChild. * - * Returns the @old node + * Returns @old or NULL if arguments are invalid or a memory + * allocation failed. */ xmlNodePtr xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { @@ -3833,20 +3867,19 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { return(NULL); } if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { + /* Don't call xmlUnlinkNodeInternal to handle DTDs. */ xmlUnlinkNode(old); return(old); } - if (cur == old) { - return(old); - } if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { return(old); } if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { return(old); } - xmlUnlinkNode(cur); - xmlSetTreeDoc(cur, old->doc); + xmlUnlinkNodeInternal(cur); + if (xmlSetTreeDoc(cur, old->doc) < 0) + return(NULL); cur->parent = old->parent; cur->next = old->next; if (cur->next != NULL) @@ -3881,9 +3914,10 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { * xmlCopyNamespace: * @cur: the namespace * - * Do a copy of the namespace. + * Copy a namespace. * - * Returns: a new #xmlNsPtr, or NULL in case of error. + * Returns the copied namespace or NULL if a memory allocation + * failed. */ xmlNsPtr xmlCopyNamespace(xmlNsPtr cur) { @@ -3904,9 +3938,10 @@ xmlCopyNamespace(xmlNsPtr cur) { * xmlCopyNamespaceList: * @cur: the first namespace * - * Do a copy of an namespace list. + * Copy a namespace list. * - * Returns: a new #xmlNsPtr, or NULL in case of error. + * Returns the head of the copied list or NULL if a memory + * allocation failed. */ xmlNsPtr xmlCopyNamespaceList(xmlNsPtr cur) { @@ -3932,7 +3967,7 @@ xmlCopyNamespaceList(xmlNsPtr cur) { static xmlAttrPtr xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { - xmlAttrPtr ret; + xmlAttrPtr ret = NULL; if (cur == NULL) return(NULL); if ((target != NULL) && (target->type != XML_ELEMENT_NODE)) @@ -3952,15 +3987,20 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { if ((cur->ns != NULL) && (target != NULL)) { xmlNsPtr ns; + int res; - ns = xmlSearchNs(target->doc, target, cur->ns->prefix); + res = xmlSearchNsSafe(target, cur->ns->prefix, &ns); + if (res < 0) + goto error; if (ns == NULL) { /* * Humm, we are copying an element whose namespace is defined * out of the new tree scope. Search it in the original tree * and add it at the top of the new tree */ - ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix); + res = xmlSearchNsSafe(cur->parent, cur->ns->prefix, &ns); + if (res < 0) + goto error; if (ns != NULL) { xmlNodePtr root = target; xmlNodePtr pred = NULL; @@ -3974,6 +4014,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { root = pred; } ret->ns = xmlNewNs(root, ns->href, ns->prefix); + if (ret->ns == NULL) + goto error; } } else { /* @@ -3989,7 +4031,9 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { * we are in trouble: we need a new reconciled namespace. * This is expensive */ - ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns); + ret->ns = xmlNewReconciledNs(target, cur->ns); + if (ret->ns == NULL) + goto error; } } @@ -4000,6 +4044,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { xmlNodePtr tmp; ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret); + if (ret->children == NULL) + goto error; ret->last = NULL; tmp = ret->children; while (tmp != NULL) { @@ -4012,20 +4058,32 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { /* * Try to handle IDs */ - if ((target!= NULL) && (cur!= NULL) && + if ((target != NULL) && (cur != NULL) && (target->doc != NULL) && (cur->doc != NULL) && - (cur->doc->ids != NULL) && (cur->parent != NULL)) { - if (xmlIsID(cur->doc, cur->parent, cur)) { + (cur->doc->ids != NULL) && + (cur->parent != NULL) && + (cur->children != NULL)) { + int res = xmlIsID(cur->doc, cur->parent, cur); + + if (res < 0) + goto error; + if (res != 0) { xmlChar *id; - id = xmlNodeListGetString(cur->doc, cur->children, 1); - if (id != NULL) { - xmlAddID(NULL, target->doc, id, ret); - xmlFree(id); - } + id = xmlNodeGetContent((xmlNodePtr) cur); + if (id == NULL) + goto error; + res = xmlAddIDSafe(ret, id); + xmlFree(id); + if (res < 0) + goto error; } } return(ret); + +error: + xmlFreeProp(ret); + return(NULL); } /** @@ -4033,9 +4091,14 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { * @target: the element where the attribute will be grafted * @cur: the attribute * - * Do a copy of the attribute. + * Create a copy of the attribute. This function sets the parent + * pointer of the copy to @target but doesn't set the attribute on + * the target element. Users should consider to set the attribute + * by calling xmlAddChild afterwards or reset the parent pointer to + * NULL. * - * Returns: a new #xmlAttrPtr, or NULL in case of error. + * Returns the copied attribute or NULL if a memory allocation + * failed. */ xmlAttrPtr xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { @@ -4047,9 +4110,12 @@ xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { * @target: the element where the attributes will be grafted * @cur: the first attribute * - * Do a copy of an attribute list. + * Create a copy of an attribute list. This function sets the + * parent pointers of the copied attributes to @target but doesn't + * set the attributes on the target element. * - * Returns: a new #xmlAttrPtr, or NULL in case of error. + * Returns the head of the copied list or NULL if a memory + * allocation failed. */ xmlAttrPtr xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) { @@ -4095,6 +4161,17 @@ xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) { * namespace info, but don't recurse on children. */ +/** + * xmlStaticCopyNode: + * @node: source node + * @doc: target document + * @parent: target parent + * @extended: flags + * + * Copy a node. + * + * Returns the copy or NULL if a memory allocation failed. + */ xmlNodePtr xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, int extended) { @@ -4107,7 +4184,6 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, case XML_ELEMENT_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: case XML_XINCLUDE_START: @@ -4123,12 +4199,7 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, #ifdef LIBXML_TREE_ENABLED return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended)); #endif /* LIBXML_TREE_ENABLED */ - case XML_DOCUMENT_TYPE_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: + default: return(NULL); } @@ -4136,10 +4207,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, * Allocate a new node and fill the fields. */ ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (ret == NULL) { - xmlTreeErrMemory("copying node"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlNode)); ret->type = node->type; @@ -4156,6 +4225,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, ret->name = xmlDictLookup(doc->dict, node->name, -1); else ret->name = xmlStrdup(node->name); + if (ret->name == NULL) + goto error; } if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL) && @@ -4163,45 +4234,29 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, (node->type != XML_XINCLUDE_END) && (node->type != XML_XINCLUDE_START)) { ret->content = xmlStrdup(node->content); + if (ret->content == NULL) + goto error; }else{ if (node->type == XML_ELEMENT_NODE) ret->line = node->line; } - if (parent != NULL) { - xmlNodePtr tmp; - - /* - * this is a tricky part for the node register thing: - * in case ret does get coalesced in xmlAddChild - * the deregister-node callback is called; so we register ret now already - */ - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) - xmlRegisterNodeDefaultValue((xmlNodePtr)ret); - - /* - * Note that since ret->parent is already set, xmlAddChild will - * return early and not actually insert the node. It will only - * coalesce text nodes and unnecessarily call xmlSetTreeDoc. - * Assuming that the subtree to be copied always has its text - * nodes coalesced, the somewhat confusing call to xmlAddChild - * could be removed. - */ - tmp = xmlAddChild(parent, ret); - /* node could have coalesced */ - if (tmp != ret) - return(tmp); - } if (!extended) goto out; if (((node->type == XML_ELEMENT_NODE) || - (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) + (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) { ret->nsDef = xmlCopyNamespaceList(node->nsDef); + if (ret->nsDef == NULL) + goto error; + } - if (node->ns != NULL) { - xmlNsPtr ns; + if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL)) { + xmlNsPtr ns = NULL; + int res; - ns = xmlSearchNs(doc, ret, node->ns->prefix); + res = xmlSearchNsSafe(ret, node->ns->prefix, &ns); + if (res < 0) + goto error; if (ns == NULL) { /* * Humm, we are copying an element whose namespace is defined @@ -4211,15 +4266,19 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, * TODO: Searching the original tree seems unnecessary. We * already have a namespace URI. */ - ns = xmlSearchNs(node->doc, node, node->ns->prefix); + res = xmlSearchNsSafe(node, node->ns->prefix, &ns); + if (res < 0) + goto error; if (ns != NULL) { xmlNodePtr root = ret; while (root->parent != NULL) root = root->parent; ret->ns = xmlNewNs(root, ns->href, ns->prefix); } else { - ret->ns = xmlNewReconciledNs(doc, ret, node->ns); + ret->ns = xmlNewReconciledNs(ret, node->ns); } + if (ret->ns == NULL) + goto error; } else { /* * reference the existing namespace definition in our own tree. @@ -4227,9 +4286,11 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, ret->ns = ns; } } - if (((node->type == XML_ELEMENT_NODE) || - (node->type == XML_XINCLUDE_START)) && (node->properties != NULL)) + if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) { ret->properties = xmlCopyPropList(ret, node->properties); + if (ret->properties == NULL) + goto error; + } if (node->type == XML_ENTITY_REF_NODE) { if ((doc == NULL) || (node->doc != doc)) { /* @@ -4250,10 +4311,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, insert = ret; while (cur != NULL) { xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2); - if (copy == NULL) { - xmlFreeNode(ret); - return(NULL); - } + if (copy == NULL) + goto error; /* Check for coalesced text nodes */ if (insert->last != copy) { @@ -4290,13 +4349,27 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, } out: - /* if parent != NULL we already registered the node above */ - if ((parent == NULL) && - ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))) + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)ret); return(ret); + +error: + xmlFreeNode(ret); + return(NULL); } +/** + * xmlStaticCopyNodeList: + * @node: node to copy + * @doc: target document + * @parent: target node (optional) + * + * Copy a node list. If @parent is provided, sets the parent pointer + * of the copied nodes, but doesn't update the children and last + * pointer of @parent. + * + * Returns a the copy or NULL in case of error. + */ xmlNodePtr xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { xmlNodePtr ret = NULL; @@ -4305,23 +4378,44 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { int linkedSubset = 0; while (node != NULL) { + xmlNodePtr next = node->next; + #ifdef LIBXML_TREE_ENABLED if (node->type == XML_DTD_NODE ) { if (doc == NULL) { - node = node->next; + node = next; continue; } if ((doc->intSubset == NULL) && (newSubset == NULL)) { q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); if (q == NULL) goto error; - q->doc = doc; + /* Can't fail on DTD */ + xmlSetTreeDoc(q, doc); q->parent = parent; newSubset = (xmlDtdPtr) q; - xmlAddChild(parent, q); } else { + /* + * We don't allow multiple internal subsets in a document, + * so we move the DTD instead of creating a copy. + */ linkedSubset = 1; q = (xmlNodePtr) doc->intSubset; - xmlAddChild(parent, q); + /* Unlink */ + if (q->prev == NULL) { + if (q->parent != NULL) + q->parent->children = q->next; + } else { + q->prev->next = q->next; + } + if (q->next == NULL) { + if (q->parent != NULL) + q->parent->last = q->prev; + } else { + q->next->prev = q->prev; + } + q->parent = parent; + q->next = NULL; + q->prev = NULL; } } else #endif /* LIBXML_TREE_ENABLED */ @@ -4336,15 +4430,19 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { q->prev = p; p = q; } - node = node->next; + node = next; } if ((doc != NULL) && (newSubset != NULL)) doc->intSubset = newSubset; return(ret); error: - if (linkedSubset != 0) - xmlUnlinkNode((xmlNodePtr) doc->intSubset); xmlFreeNodeList(ret); + if (newSubset != NULL) + xmlFreeDtd(newSubset); + if (linkedSubset != 0) { + doc->intSubset->next = NULL; + doc->intSubset->prev = NULL; + } return(NULL); } @@ -4355,9 +4453,11 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { * when applicable) * if 2 copy properties and namespaces (when applicable) * - * Do a copy of the node. + * Copy a node. * - * Returns: a new #xmlNodePtr, or NULL in case of error. + * Use of this function is DISCOURAGED in favor of xmlDocCopyNode. + * + * Returns the copied node or NULL if a memory allocation failed. */ xmlNodePtr xmlCopyNode(xmlNodePtr node, int extended) { @@ -4375,9 +4475,9 @@ xmlCopyNode(xmlNodePtr node, int extended) { * when applicable) * if 2 copy properties and namespaces (when applicable) * - * Do a copy of the node to a given document. + * Copy a node into another document. * - * Returns: a new #xmlNodePtr, or NULL in case of error. + * Returns the copied node or NULL if a memory allocation failed. */ xmlNodePtr xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) { @@ -4392,9 +4492,10 @@ xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) { * @doc: the target document * @node: the first node in the list. * - * Do a recursive copy of the node list. + * Copy a node list and all children into a new document. * - * Returns: a new #xmlNodePtr, or NULL in case of error. + * Returns the head of the copied list or NULL if a memory + * allocation failed. */ xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) { xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL); @@ -4405,10 +4506,12 @@ xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) { * xmlCopyNodeList: * @node: the first node in the list. * - * Do a recursive copy of the node list. - * Use xmlDocCopyNodeList() if possible to ensure string interning. + * Copy a node list and all children. + * + * Use of this function is DISCOURAGED in favor of xmlDocCopyNodeList. * - * Returns: a new #xmlNodePtr, or NULL in case of error. + * Returns the head of the copied list or NULL if a memory + * allocation failed. */ xmlNodePtr xmlCopyNodeList(xmlNodePtr node) { xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL); @@ -4418,11 +4521,11 @@ xmlNodePtr xmlCopyNodeList(xmlNodePtr node) { #if defined(LIBXML_TREE_ENABLED) /** * xmlCopyDtd: - * @dtd: the dtd + * @dtd: the DTD * - * Do a copy of the dtd. + * Copy a DTD. * - * Returns: a new #xmlDtdPtr, or NULL in case of error. + * Returns the copied DTD or NULL if a memory allocation failed. */ xmlDtdPtr xmlCopyDtd(xmlDtdPtr dtd) { @@ -4432,21 +4535,36 @@ xmlCopyDtd(xmlDtdPtr dtd) { if (dtd == NULL) return(NULL); ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID); if (ret == NULL) return(NULL); - if (dtd->entities != NULL) + if (dtd->entities != NULL) { ret->entities = (void *) xmlCopyEntitiesTable( (xmlEntitiesTablePtr) dtd->entities); - if (dtd->notations != NULL) + if (ret->entities == NULL) + goto error; + } + if (dtd->notations != NULL) { ret->notations = (void *) xmlCopyNotationTable( (xmlNotationTablePtr) dtd->notations); - if (dtd->elements != NULL) + if (ret->notations == NULL) + goto error; + } + if (dtd->elements != NULL) { ret->elements = (void *) xmlCopyElementTable( (xmlElementTablePtr) dtd->elements); - if (dtd->attributes != NULL) + if (ret->elements == NULL) + goto error; + } + if (dtd->attributes != NULL) { ret->attributes = (void *) xmlCopyAttributeTable( (xmlAttributeTablePtr) dtd->attributes); - if (dtd->pentities != NULL) + if (ret->attributes == NULL) + goto error; + } + if (dtd->pentities != NULL) { ret->pentities = (void *) xmlCopyEntitiesTable( (xmlEntitiesTablePtr) dtd->pentities); + if (ret->pentities == NULL) + goto error; + } cur = dtd->children; while (cur != NULL) { @@ -4478,6 +4596,8 @@ xmlCopyDtd(xmlDtdPtr dtd) { xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix); } else if (cur->type == XML_COMMENT_NODE) { q = xmlCopyNode(cur, 0); + if (q == NULL) + goto error; } if (q == NULL) { @@ -4499,6 +4619,10 @@ xmlCopyDtd(xmlDtdPtr dtd) { } return(ret); + +error: + xmlFreeDtd(ret); + return(NULL); } #endif @@ -4508,10 +4632,11 @@ xmlCopyDtd(xmlDtdPtr dtd) { * @doc: the document * @recursive: if not zero do a recursive copy. * - * Do a copy of the document info. If recursive, the content tree will + * Copy a document. If recursive, the content tree will * be copied too as well as DTD, namespaces and entities. * - * Returns: a new #xmlDocPtr, or NULL in case of error. + * Returns the copied document or NULL if a memory allocation + * failed. */ xmlDocPtr xmlCopyDoc(xmlDocPtr doc, int recursive) { @@ -4521,12 +4646,21 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { ret = xmlNewDoc(doc->version); if (ret == NULL) return(NULL); ret->type = doc->type; - if (doc->name != NULL) + if (doc->name != NULL) { ret->name = xmlMemStrdup(doc->name); - if (doc->encoding != NULL) + if (ret->name == NULL) + goto error; + } + if (doc->encoding != NULL) { ret->encoding = xmlStrdup(doc->encoding); - if (doc->URL != NULL) + if (ret->encoding == NULL) + goto error; + } + if (doc->URL != NULL) { ret->URL = xmlStrdup(doc->URL); + if (ret->URL == NULL) + goto error; + } ret->charset = doc->charset; ret->compression = doc->compression; ret->standalone = doc->standalone; @@ -4537,21 +4671,24 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { #ifdef LIBXML_TREE_ENABLED if (doc->intSubset != NULL) { ret->intSubset = xmlCopyDtd(doc->intSubset); - if (ret->intSubset == NULL) { - xmlFreeDoc(ret); - return(NULL); - } + if (ret->intSubset == NULL) + goto error; + /* Can't fail on DTD */ xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret); - ret->intSubset->parent = ret; } #endif - if (doc->oldNs != NULL) + if (doc->oldNs != NULL) { ret->oldNs = xmlCopyNamespaceList(doc->oldNs); + if (ret->oldNs == NULL) + goto error; + } if (doc->children != NULL) { xmlNodePtr tmp; ret->children = xmlStaticCopyNodeList(doc->children, ret, (xmlNodePtr)ret); + if (ret->children == NULL) + goto error; ret->last = NULL; tmp = ret->children; while (tmp != NULL) { @@ -4561,6 +4698,10 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { } } return(ret); + +error: + xmlFreeDoc(ret); + return(NULL); } #endif /* LIBXML_TREE_ENABLED */ @@ -4663,13 +4804,10 @@ xmlGetNodePath(const xmlNode *node) buf_len = 500; buffer = (xmlChar *) xmlMallocAtomic(buf_len); - if (buffer == NULL) { - xmlTreeErrMemory("getting node path"); + if (buffer == NULL) return (NULL); - } buf = (xmlChar *) xmlMallocAtomic(buf_len); if (buf == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buffer); return (NULL); } @@ -4856,7 +4994,6 @@ xmlGetNodePath(const xmlNode *node) 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20; temp = (xmlChar *) xmlRealloc(buffer, buf_len); if (temp == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buf); xmlFree(buffer); return (NULL); @@ -4864,7 +5001,6 @@ xmlGetNodePath(const xmlNode *node) buffer = temp; temp = (xmlChar *) xmlRealloc(buf, buf_len); if (temp == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buf); xmlFree(buffer); return (NULL); @@ -4892,7 +5028,7 @@ xmlGetNodePath(const xmlNode *node) * Get the root element of the document (doc->children is a list * containing possibly comments, PIs, etc ...). * - * Returns the #xmlNodePtr for the root or NULL + * Returns the root element or NULL if no element was found. */ xmlNodePtr xmlDocGetRootElement(const xmlDoc *doc) { @@ -4918,7 +5054,10 @@ xmlDocGetRootElement(const xmlDoc *doc) { * Set the root element of the document (doc->children is a list * containing possibly comments, PIs, etc ...). * - * Returns the old root element if any was found, NULL if root was NULL + * @root must be an element node. It is unlinked before insertion. + * + * Returns the unlinked old root element or NULL if the document + * didn't have a root element or a memory allocation failed. */ xmlNodePtr xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { @@ -4927,15 +5066,18 @@ xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { if (doc == NULL) return(NULL); if ((root == NULL) || (root->type == XML_NAMESPACE_DECL)) return(NULL); - xmlUnlinkNode(root); - xmlSetTreeDoc(root, doc); - root->parent = (xmlNodePtr) doc; old = doc->children; while (old != NULL) { if (old->type == XML_ELEMENT_NODE) break; old = old->next; } + if (old == root) + return(old); + xmlUnlinkNodeInternal(root); + if (xmlSetTreeDoc(root, doc) < 0) + return(NULL); + root->parent = (xmlNodePtr) doc; if (old == NULL) { if (doc->children == NULL) { doc->children = root; @@ -4958,40 +5100,27 @@ xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { * * Set the language of a node, i.e. the values of the xml:lang * attribute. + * + * Return 0 on success, 1 if arguments are invalid, -1 if a + * memory allocation failed. */ -void +int xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { xmlNsPtr ns; + xmlAttrPtr attr; + int res; - if (cur == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - break; - } - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); - if (ns == NULL) - return; - xmlSetNsProp(cur, ns, BAD_CAST "lang", lang); + if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) + return(1); + + res = xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns); + if (res != 0) + return(res); + attr = xmlSetNsProp(cur, ns, BAD_CAST "lang", lang); + if (attr == NULL) + return(-1); + + return(0); } #endif /* LIBXML_TREE_ENABLED */ @@ -5008,15 +5137,22 @@ xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { xmlChar * xmlNodeGetLang(const xmlNode *cur) { xmlChar *lang; + int res; if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) return(NULL); + while (cur != NULL) { - lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE); + res = xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE, + &lang); + if (res < 0) + return(NULL); if (lang != NULL) return(lang); + cur = cur->parent; } + return(NULL); } @@ -5029,47 +5165,34 @@ xmlNodeGetLang(const xmlNode *cur) { * * Set (or reset) the space preserving behaviour of a node, i.e. the * value of the xml:space attribute. + * + * Return 0 on success, 1 if arguments are invalid, -1 if a + * memory allocation failed. */ -void +int xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) { xmlNsPtr ns; + xmlAttrPtr attr; + const char *string; + int res; - if (cur == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - break; - } - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); - if (ns == NULL) - return; - switch (val) { - case 0: - xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default"); - break; - case 1: - xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve"); - break; - } + if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) + return(1); + + res = xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns); + if (res != 0) + return(res); + + if (val == 0) + string = "default"; + else + string = "preserve"; + + attr = xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST string); + if (attr == NULL) + return(-1); + + return(0); } #endif /* LIBXML_TREE_ENABLED */ @@ -5086,11 +5209,16 @@ xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) { int xmlNodeGetSpacePreserve(const xmlNode *cur) { xmlChar *space; + int res; if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) return(-1); + while (cur != NULL) { - space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE); + res = xmlNodeGetAttrValue(cur, BAD_CAST "space", XML_XML_NAMESPACE, + &space); + if (res < 0) + return(-1); if (space != NULL) { if (xmlStrEqual(space, BAD_CAST "preserve")) { xmlFree(space); @@ -5102,8 +5230,10 @@ xmlNodeGetSpacePreserve(const xmlNode *cur) { } xmlFree(space); } + cur = cur->parent; } + return(-1); } @@ -5119,51 +5249,39 @@ void xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { xmlDocPtr doc; xmlDictPtr dict; - const xmlChar *freeme = NULL; + const xmlChar *copy; + const xmlChar *oldName; if (cur == NULL) return; if (name == NULL) return; switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: case XML_PI_NODE: case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_DTD_NODE: - case XML_DOCUMENT_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: break; + default: + return; } + doc = cur->doc; if (doc != NULL) dict = doc->dict; else dict = NULL; - if (dict != NULL) { - if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name))) - freeme = cur->name; - cur->name = xmlDictLookup(dict, name, -1); - } else { - if (cur->name != NULL) - freeme = cur->name; - cur->name = xmlStrdup(name); - } - if (freeme) - xmlFree((xmlChar *) freeme); + if (dict != NULL) + copy = xmlDictLookup(dict, name, -1); + else + copy = xmlStrdup(name); + if (copy == NULL) + return; + + oldName = cur->name; + cur->name = copy; + if ((oldName != NULL) && + ((dict == NULL) || (!xmlDictOwns(dict, oldName)))) + xmlFree((xmlChar *) oldName); } #endif @@ -5175,31 +5293,17 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { * * Set (or reset) the base URI of a node, i.e. the value of the * xml:base attribute. + * + * Returns 0 on success, -1 on error. */ -void +int xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { xmlNsPtr ns; xmlChar* fixed; - if (cur == NULL) return; + if (cur == NULL) + return(-1); switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: break; @@ -5209,31 +5313,40 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { if (doc->URL != NULL) xmlFree((xmlChar *) doc->URL); - if (uri == NULL) + if (uri == NULL) { doc->URL = NULL; - else + } else { doc->URL = xmlPathToURI(uri); - return; + if (doc->URL == NULL) + return(-1); + } + return(0); } + default: + return(-1); } - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); + xmlSearchNsByHrefSafe(cur, XML_XML_NAMESPACE, &ns); if (ns == NULL) - return; + return(-1); fixed = xmlPathToURI(uri); - if (fixed != NULL) { - xmlSetNsProp(cur, ns, BAD_CAST "base", fixed); - xmlFree(fixed); - } else { - xmlSetNsProp(cur, ns, BAD_CAST "base", uri); + if (fixed == NULL) + return(-1); + if (xmlSetNsProp(cur, ns, BAD_CAST "base", fixed) == NULL) { + xmlFree(fixed); + return(-1); } + xmlFree(fixed); + + return(0); } #endif /* LIBXML_TREE_ENABLED */ /** - * xmlNodeGetBase: + * xmlNodeGetBaseSafe: * @doc: the document the node pertains to * @cur: the node being checked + * @baseOut: pointer to base * * Searches for the BASE URL. The code should work on both XML * and HTML document even if base mechanisms are completely different. @@ -5244,19 +5357,27 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { * However it does not return the document base (5.1.3), use * doc->URL in this case * - * Returns a pointer to the base URL, or NULL if not found - * It's up to the caller to free the memory with xmlFree(). + * Available since 2.13.0. + * + * Return 0 in case of success, 1 if a URI or argument is invalid, -1 if a + * memory allocation failed. */ -xmlChar * -xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { - xmlChar *oldbase = NULL; +int +xmlNodeGetBaseSafe(const xmlDoc *doc, const xmlNode *cur, xmlChar **baseOut) { + xmlChar *ret = NULL; xmlChar *base, *newbase; + int res; + if (baseOut == NULL) + return(1); + *baseOut = NULL; if ((cur == NULL) && (doc == NULL)) - return(NULL); + return(1); if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL)) - return(NULL); - if (doc == NULL) doc = cur->doc; + return(1); + if (doc == NULL) + doc = cur->doc; + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { cur = doc->children; while ((cur != NULL) && (cur->name != NULL)) { @@ -5273,50 +5394,91 @@ xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { continue; } if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) { - return(xmlGetProp(cur, BAD_CAST "href")); + if (xmlNodeGetAttrValue(cur, BAD_CAST "href", NULL, &ret) < 0) + return(-1); + if (ret == NULL) + return(1); + goto found; } cur = cur->next; } - return(NULL); + return(0); } + while (cur != NULL) { if (cur->type == XML_ENTITY_DECL) { xmlEntityPtr ent = (xmlEntityPtr) cur; - return(xmlStrdup(ent->URI)); + + if (ent->URI == NULL) + break; + xmlFree(ret); + ret = xmlStrdup(ent->URI); + if (ret == NULL) + return(-1); + goto found; } if (cur->type == XML_ELEMENT_NODE) { - base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); + if (xmlNodeGetAttrValue(cur, BAD_CAST "base", XML_XML_NAMESPACE, + &base) < 0) { + xmlFree(ret); + return(-1); + } if (base != NULL) { - if (oldbase != NULL) { - newbase = xmlBuildURI(oldbase, base); - if (newbase != NULL) { - xmlFree(oldbase); - xmlFree(base); - oldbase = newbase; - } else { - xmlFree(oldbase); - xmlFree(base); - return(NULL); - } + if (ret != NULL) { + res = xmlBuildURISafe(ret, base, &newbase); + xmlFree(ret); + xmlFree(base); + if (res != 0) + return(res); + ret = newbase; } else { - oldbase = base; + ret = base; } - if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) || - (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) || - (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4))) - return(oldbase); + if ((!xmlStrncmp(ret, BAD_CAST "http://", 7)) || + (!xmlStrncmp(ret, BAD_CAST "ftp://", 6)) || + (!xmlStrncmp(ret, BAD_CAST "urn:", 4))) + goto found; } } cur = cur->parent; } + if ((doc != NULL) && (doc->URL != NULL)) { - if (oldbase == NULL) - return(xmlStrdup(doc->URL)); - newbase = xmlBuildURI(oldbase, doc->URL); - xmlFree(oldbase); - return(newbase); + if (ret == NULL) { + ret = xmlStrdup(doc->URL); + if (ret == NULL) + return(-1); + } else { + res = xmlBuildURISafe(ret, doc->URL, &newbase); + xmlFree(ret); + if (res != 0) + return(res); + ret = newbase; + } } - return(oldbase); + +found: + *baseOut = ret; + return(0); +} + +/** + * xmlNodeGetBase: + * @doc: the document the node pertains to + * @cur: the node being checked + * + * See xmlNodeGetBaseSafe. This function doesn't allow to distinguish + * memory allocation failures from a non-existing base. + * + * Returns a pointer to the base URL, or NULL if not found + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { + xmlChar *base; + + xmlNodeGetBaseSafe(doc, cur, &base); + return(base); } /** @@ -5347,6 +5509,69 @@ xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur) return(0); } +static void +xmlBufGetEntityRefContent(xmlBufPtr buf, const xmlNode *ref) { + xmlEntityPtr ent; + + if (ref->children != NULL) { + ent = (xmlEntityPtr) ref->children; + } else { + /* lookup entity declaration */ + ent = xmlGetDocEntity(ref->doc, ref->name); + if (ent == NULL) + return; + } + + /* + * The parser should always expand predefined entities but it's + * possible to create references to predefined entities using + * the tree API. + */ + if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) { + xmlBufCat(buf, ent->content); + return; + } + + if (ent->flags & XML_ENT_EXPANDING) + return; + + ent->flags |= XML_ENT_EXPANDING; + xmlBufGetChildContent(buf, (xmlNodePtr) ent); + ent->flags &= ~XML_ENT_EXPANDING; +} + +static void +xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree) { + const xmlNode *cur = tree->children; + + while (cur != NULL) { + switch (cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + xmlBufCat(buf, cur->content); + break; + + case XML_ENTITY_REF_NODE: + xmlBufGetEntityRefContent(buf, cur); + break; + + default: + if (cur->children != NULL) { + cur = cur->children; + continue; + } + break; + } + + while (cur->next == NULL) { + cur = cur->parent; + if (cur == tree) + return; + } + cur = cur->next; + } +} + /** * xmlBufGetNodeContent: * @buf: a buffer xmlBufPtr @@ -5363,127 +5588,38 @@ xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur) int xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur) { - if ((cur == NULL) || (buf == NULL)) return(-1); + if ((cur == NULL) || (buf == NULL)) + return(-1); + switch (cur->type) { - case XML_CDATA_SECTION_NODE: - case XML_TEXT_NODE: - xmlBufCat(buf, cur->content); - break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE:{ - const xmlNode *tmp = cur; - - while (tmp != NULL) { - switch (tmp->type) { - case XML_CDATA_SECTION_NODE: - case XML_TEXT_NODE: - if (tmp->content != NULL) - xmlBufCat(buf, tmp->content); - break; - case XML_ENTITY_REF_NODE: - xmlBufGetNodeContent(buf, tmp); - break; - default: - break; - } - /* - * Skip to next node - */ - if (tmp->children != NULL) { - if (tmp->children->type != XML_ENTITY_DECL) { - tmp = tmp->children; - continue; - } - } - if (tmp == cur) - break; - - if (tmp->next != NULL) { - tmp = tmp->next; - continue; - } - - do { - tmp = tmp->parent; - if (tmp == NULL) - break; - if (tmp == cur) { - tmp = NULL; - break; - } - if (tmp->next != NULL) { - tmp = tmp->next; - break; - } - } while (tmp != NULL); - } - break; - } - case XML_ATTRIBUTE_NODE:{ - xmlAttrPtr attr = (xmlAttrPtr) cur; - xmlNodePtr tmp = attr->children; + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_ENTITY_DECL: + xmlBufGetChildContent(buf, cur); + break; - while (tmp != NULL) { - if (tmp->type == XML_TEXT_NODE) - xmlBufCat(buf, tmp->content); - else - xmlBufGetNodeContent(buf, tmp); - tmp = tmp->next; - } - break; - } + case XML_CDATA_SECTION_NODE: + case XML_TEXT_NODE: case XML_COMMENT_NODE: case XML_PI_NODE: xmlBufCat(buf, cur->content); break; - case XML_ENTITY_REF_NODE:{ - xmlEntityPtr ent; - xmlNodePtr tmp; - - /* lookup entity declaration */ - ent = xmlGetDocEntity(cur->doc, cur->name); - if (ent == NULL) - return(-1); - /* an entity content can be any "well balanced chunk", - * i.e. the result of the content [43] production: - * http://www.w3.org/TR/REC-xml#NT-content - * -> we iterate through child nodes and recursive call - * xmlNodeGetContent() which handles all possible node types */ - tmp = ent->children; - while (tmp) { - xmlBufGetNodeContent(buf, tmp); - tmp = tmp->next; - } - break; - } - case XML_ENTITY_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: + case XML_ENTITY_REF_NODE: + xmlBufGetEntityRefContent(buf, cur); break; - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: - cur = cur->children; - while (cur!= NULL) { - if ((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_TEXT_NODE) || - (cur->type == XML_CDATA_SECTION_NODE)) { - xmlBufGetNodeContent(buf, cur); - } - cur = cur->next; - } - break; + case XML_NAMESPACE_DECL: xmlBufCat(buf, ((xmlNsPtr) cur)->href); break; - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: + + default: break; } + return(0); } @@ -5501,163 +5637,131 @@ xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur) xmlChar * xmlNodeGetContent(const xmlNode *cur) { + xmlBufPtr buf; + xmlChar *ret; + if (cur == NULL) return (NULL); + switch (cur->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + case XML_ENTITY_REF_NODE: + break; + case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE:{ - xmlBufPtr buf; - xmlChar *ret; - - buf = xmlBufCreateSize(64); - if (buf == NULL) - return (NULL); - xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); - xmlBufGetNodeContent(buf, cur); - ret = xmlBufDetach(buf); - xmlBufFree(buf); - return (ret); - } + case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: - return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur)); - case XML_COMMENT_NODE: - case XML_PI_NODE: - if (cur->content != NULL) - return (xmlStrdup(cur->content)); - return (NULL); - case XML_ENTITY_REF_NODE:{ - xmlEntityPtr ent; - xmlBufPtr buf; - xmlChar *ret; - - /* lookup entity declaration */ - ent = xmlGetDocEntity(cur->doc, cur->name); - if (ent == NULL) - return (NULL); - - buf = xmlBufCreate(); - if (buf == NULL) - return (NULL); - xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); - - xmlBufGetNodeContent(buf, cur); - - ret = xmlBufDetach(buf); - xmlBufFree(buf); - return (ret); + case XML_ENTITY_DECL: { + xmlNodePtr children = cur->children; + + if (children == NULL) + return(xmlStrdup(BAD_CAST "")); + + /* Optimization for single text children */ + if (((children->type == XML_TEXT_NODE) || + (children->type == XML_CDATA_SECTION_NODE)) && + (children->next == NULL)) { + if (children->content == NULL) + return(xmlStrdup(BAD_CAST "")); + return(xmlStrdup(children->content)); } - case XML_ENTITY_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return (NULL); - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: { - xmlBufPtr buf; - xmlChar *ret; - - buf = xmlBufCreate(); - if (buf == NULL) - return (NULL); - xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); - xmlBufGetNodeContent(buf, (xmlNodePtr) cur); - - ret = xmlBufDetach(buf); - xmlBufFree(buf); - return (ret); - } - case XML_NAMESPACE_DECL: { - xmlChar *tmp; + break; + } - tmp = xmlStrdup(((xmlNsPtr) cur)->href); - return (tmp); - } - case XML_ELEMENT_DECL: - /* TODO !!! */ - return (NULL); - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - return (NULL); - case XML_ENTITY_DECL: - /* TODO !!! */ - return (NULL); case XML_CDATA_SECTION_NODE: case XML_TEXT_NODE: + case XML_COMMENT_NODE: + case XML_PI_NODE: if (cur->content != NULL) - return (xmlStrdup(cur->content)); - return (NULL); + return(xmlStrdup(cur->content)); + else + return(xmlStrdup(BAD_CAST "")); + + case XML_NAMESPACE_DECL: + return(xmlStrdup(((xmlNsPtr) cur)->href)); + + default: + return(NULL); } - return (NULL); + + buf = xmlBufCreateSize(64); + if (buf == NULL) + return (NULL); + xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); + xmlBufGetNodeContent(buf, cur); + ret = xmlBufDetach(buf); + xmlBufFree(buf); + + return(ret); } -/** - * xmlNodeSetContent: - * @cur: the node being modified - * @content: the new value of the content - * - * Replace the content of a node. - * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars(). - */ -void -xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { +static int +xmlNodeSetContentInternal(xmlNodePtr cur, const xmlChar *content, int len) { if (cur == NULL) { - return; + return(1); } switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringGetNodeList(cur->doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) + if (xmlNodeParseContent(cur, content, len) < 0) + return(-1); break; + case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: case XML_PI_NODE: - case XML_COMMENT_NODE: - if ((cur->content != NULL) && - (cur->content != (xmlChar *) &(cur->properties))) { - if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && - (xmlDictOwns(cur->doc->dict, cur->content)))) - xmlFree(cur->content); - } - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->last = cur->children = NULL; + case XML_COMMENT_NODE: { + xmlChar *copy = NULL; + if (content != NULL) { - cur->content = xmlStrdup(content); - } else - cur->content = NULL; - cur->properties = NULL; - break; - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - break; - case XML_NOTATION_NODE: - break; - case XML_DTD_NODE: - break; - case XML_NAMESPACE_DECL: - break; - case XML_ELEMENT_DECL: - /* TODO !!! */ - break; - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - break; - case XML_ENTITY_DECL: - /* TODO !!! */ + if (len < 0) + copy = xmlStrdup(content); + else + copy = xmlStrndup(content, len); + if (copy == NULL) + return(-1); + } + + xmlTextSetContent(cur, copy); break; + } + + default: + break; } + + return(0); +} + +/** + * xmlNodeSetContent: + * @cur: the node being modified + * @content: the new value of the content + * + * Replace the text content of a node. + * + * Sets the raw text content of text, CDATA, comment or PI nodes. + * + * For element and attribute nodes, removes all children and + * replaces them by parsing @content which is expected to be a + * valid XML attribute value possibly containing character and + * entity references. Syntax errors and references to undeclared + * entities are ignored silently. Unfortunately, there isn't an + * API to pass raw content directly. An inefficient work-around + * is to escape the content with xmlEncodeSpecialChars before + * passing it. A better trick is clearing the old content + * with xmlNodeSetContent(node, NULL) first and then calling + * xmlNodeAddContent(node, content). Unlike this function, + * xmlNodeAddContent accepts raw text. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. + */ +int +xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { + return(xmlNodeSetContentInternal(cur, content, -1)); } #ifdef LIBXML_TREE_ENABLED @@ -5667,63 +5771,13 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { * @content: the new value of the content * @len: the size of @content * - * Replace the content of a node. - * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars(). + * See xmlNodeSetContent. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { - if (cur == NULL) { - return; - } - switch (cur->type) { - case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringLenGetNodeList(cur->doc, content, len); - UPDATE_LAST_CHILD_AND_PARENT(cur) - break; - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_NOTATION_NODE: - if ((cur->content != NULL) && - (cur->content != (xmlChar *) &(cur->properties))) { - if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && - (xmlDictOwns(cur->doc->dict, cur->content)))) - xmlFree(cur->content); - } - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = cur->last = NULL; - if (content != NULL) { - cur->content = xmlStrndup(content, len); - } else - cur->content = NULL; - cur->properties = NULL; - break; - case XML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - break; - case XML_ELEMENT_DECL: - /* TODO !!! */ - break; - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - break; - case XML_ENTITY_DECL: - /* TODO !!! */ - break; - } + return(xmlNodeSetContentInternal(cur, content, len)); } #endif /* LIBXML_TREE_ENABLED */ @@ -5737,63 +5791,43 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be * raw text, so unescaped XML special chars are allowed, entity * references are not supported. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { - if (cur == NULL) { - return; - } - if (len <= 0) return; + if (cur == NULL) + return(1); + if ((content == NULL) || (len <= 0)) + return(0); + switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: { - xmlNodePtr last, newNode, tmp; + xmlNodePtr newNode, tmp; - last = cur->last; newNode = xmlNewDocTextLen(cur->doc, content, len); - if (newNode != NULL) { - tmp = xmlAddChild(cur, newNode); - if (tmp != newNode) - return; - if ((last != NULL) && (last->next == newNode)) { - xmlTextMerge(last, newNode); - } - } + if (newNode == NULL) + return(-1); + tmp = xmlAddChild(cur, newNode); + if (tmp == NULL) { + xmlFreeNode(newNode); + return(-1); + } break; } case XML_ATTRIBUTE_NODE: break; case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_NOTATION_NODE: - if (content != NULL) { - if ((cur->content == (xmlChar *) &(cur->properties)) || - ((cur->doc != NULL) && (cur->doc->dict != NULL) && - xmlDictOwns(cur->doc->dict, cur->content))) { - cur->content = xmlStrncatNew(cur->content, content, len); - cur->properties = NULL; - } else { - cur->content = xmlStrncat(cur->content, content, len); - } - } - break; - case XML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - break; - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - break; + case XML_PI_NODE: + case XML_COMMENT_NODE: + return(xmlTextAddContent(cur, content, len)); + default: + break; } + + return(0); } /** @@ -5805,17 +5839,12 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be * raw text, so unescaped XML special chars are allowed, entity * references are not supported. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { - int len; - - if (cur == NULL) { - return; - } - if (content == NULL) return; - len = xmlStrlen(content); - xmlNodeAddContentLen(cur, content, len); + return(xmlNodeAddContentLen(cur, content, xmlStrlen(content))); } /** @@ -5823,53 +5852,66 @@ xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { * @first: the first text node * @second: the second text node being merged * - * Merge two text nodes into one - * Returns the first text node augmented + * Merge the second text node into the first. The second node is + * unlinked and freed. + * + * Returns the first text node augmented or NULL in case of error. */ xmlNodePtr xmlTextMerge(xmlNodePtr first, xmlNodePtr second) { - if (first == NULL) return(second); - if (second == NULL) return(first); - if (first->type != XML_TEXT_NODE) return(first); - if (second->type != XML_TEXT_NODE) return(first); - if (second->name != first->name) - return(first); - xmlNodeAddContent(first, second->content); - xmlUnlinkNode(second); + if ((first == NULL) || (first->type != XML_TEXT_NODE) || + (second == NULL) || (second->type != XML_TEXT_NODE) || + (first == second) || + (first->name != second->name)) + return(NULL); + + if (xmlTextAddContent(first, second->content, -1) < 0) + return(NULL); + + xmlUnlinkNodeInternal(second); xmlFreeNode(second); return(first); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) /** - * xmlGetNsList: + * xmlGetNsListSafe: * @doc: the document * @node: the current node + * @out: the returned namespace array + * + * Find all in-scope namespaces of a node. @out returns a NULL + * terminated array of namespace pointers that must be freed by + * the caller. * - * Search all the namespace applying to a given element. - * Returns an NULL terminated array of all the #xmlNsPtr found - * that need to be freed by the caller or NULL if no - * namespace if defined + * Available since 2.13.0. + * + * Returns 0 on success, 1 if no namespaces were found, -1 if a + * memory allocation failed. */ -xmlNsPtr * -xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) +int +xmlGetNsListSafe(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node, + xmlNsPtr **out) { xmlNsPtr cur; - xmlNsPtr *ret = NULL; + xmlNsPtr *namespaces = NULL; int nbns = 0; int maxns = 0; int i; + if (out == NULL) + return(1); + *out = NULL; if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) - return(NULL); + return(1); while (node != NULL) { if (node->type == XML_ELEMENT_NODE) { cur = node->nsDef; while (cur != NULL) { for (i = 0; i < nbns; i++) { - if ((cur->prefix == ret[i]->prefix) || - (xmlStrEqual(cur->prefix, ret[i]->prefix))) + if ((cur->prefix == namespaces[i]->prefix) || + (xmlStrEqual(cur->prefix, namespaces[i]->prefix))) break; } if (i >= nbns) { @@ -5877,18 +5919,17 @@ xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) xmlNsPtr *tmp; maxns = maxns ? maxns * 2 : 10; - tmp = (xmlNsPtr *) xmlRealloc(ret, + tmp = (xmlNsPtr *) xmlRealloc(namespaces, (maxns + 1) * sizeof(xmlNsPtr)); if (tmp == NULL) { - xmlTreeErrMemory("getting namespace list"); - xmlFree(ret); - return (NULL); + xmlFree(namespaces); + return(-1); } - ret = tmp; + namespaces = tmp; } - ret[nbns++] = cur; - ret[nbns] = NULL; + namespaces[nbns++] = cur; + namespaces[nbns] = NULL; } cur = cur->next; @@ -5896,40 +5937,161 @@ xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) } node = node->parent; } - return (ret); + + *out = namespaces; + return((namespaces == NULL) ? 1 : 0); +} + +/** + * xmlGetNsList: + * @doc: the document + * @node: the current node + * + * Find all in-scope namespaces of a node. + * + * Use xmlGetNsListSafe for better error reporting. + * + * Returns a NULL terminated array of namespace pointers that must + * be freed by the caller or NULL if no namespaces were found or + * a memory allocation failed. + */ +xmlNsPtr * +xmlGetNsList(const xmlDoc *doc, const xmlNode *node) +{ + xmlNsPtr *ret; + + xmlGetNsListSafe(doc, node, &ret); + return(ret); } #endif /* LIBXML_TREE_ENABLED */ +static xmlNsPtr +xmlNewXmlNs(void) { + xmlNsPtr ns; + + ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + if (ns == NULL) + return(NULL); + memset(ns, 0, sizeof(xmlNs)); + ns->type = XML_LOCAL_NAMESPACE; + ns->href = xmlStrdup(XML_XML_NAMESPACE); + if (ns->href == NULL) { + xmlFreeNs(ns); + return(NULL); + } + ns->prefix = xmlStrdup(BAD_CAST "xml"); + if (ns->prefix == NULL) { + xmlFreeNs(ns); + return(NULL); + } + + return(ns); +} + /* * xmlTreeEnsureXMLDecl: * @doc: the doc * * Ensures that there is an XML namespace declaration on the doc. * -* Returns the XML ns-struct or NULL on API and internal errors. +* Returns the XML ns-struct or NULL if a memory allocation failed. */ static xmlNsPtr xmlTreeEnsureXMLDecl(xmlDocPtr doc) { - if (doc == NULL) - return (NULL); - if (doc->oldNs != NULL) - return (doc->oldNs); - { - xmlNsPtr ns; - ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (ns == NULL) { - xmlTreeErrMemory( - "allocating the XML namespace"); - return (NULL); - } - memset(ns, 0, sizeof(xmlNs)); - ns->type = XML_LOCAL_NAMESPACE; - ns->href = xmlStrdup(XML_XML_NAMESPACE); - ns->prefix = xmlStrdup((const xmlChar *)"xml"); - doc->oldNs = ns; + xmlNsPtr ns; + + ns = doc->oldNs; + if (ns != NULL) return (ns); + + ns = xmlNewXmlNs(); + doc->oldNs = ns; + + return(ns); +} + +/** + * xmlSearchNsSafe: + * @node: a node + * @prefix: a namespace prefix + * @out: pointer to resulting namespace + * + * Search a namespace with @prefix in scope of @node. + * + * Returns 0 on success, -1 if a memory allocation failed, 1 on + * other errors. + */ +int +xmlSearchNsSafe(xmlNodePtr node, const xmlChar *prefix, + xmlNsPtr *out) { + xmlNsPtr cur; + xmlDocPtr doc; + xmlNodePtr orig = node; + xmlNodePtr parent; + + if (out == NULL) + return(1); + *out = NULL; + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) + return(1); + + doc = node->doc; + + if ((doc != NULL) && (IS_STR_XML(prefix))) { + cur = xmlTreeEnsureXMLDecl(doc); + if (cur == NULL) + return(-1); + *out = cur; + return(0); + } + + while (node->type != XML_ELEMENT_NODE) { + node = node->parent; + if (node == NULL) + return(0); + } + + parent = node; + + while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) { + cur = node->nsDef; + while (cur != NULL) { + if ((xmlStrEqual(cur->prefix, prefix)) && + (cur->href != NULL)) { + *out = cur; + return(0); + } + cur = cur->next; + } + if (orig != node) { + cur = node->ns; + if ((cur != NULL) && + (xmlStrEqual(cur->prefix, prefix)) && + (cur->href != NULL)) { + *out = cur; + return(0); + } + } + + node = node->parent; + } + + /* + * The XML-1.0 namespace is normally held on the document + * element. In this case exceptionally create it on the + * node element. + */ + if ((doc == NULL) && (IS_STR_XML(prefix))) { + cur = xmlNewXmlNs(); + if (cur == NULL) + return(-1); + cur->next = parent->nsDef; + parent->nsDef = cur; + *out = cur; } + + return(0); } /** @@ -5946,82 +6108,17 @@ xmlTreeEnsureXMLDecl(xmlDocPtr doc) * the namespace within those you will be in troubles !!! A warning * is generated to cover this case. * - * Returns the namespace pointer or NULL. + * Returns the namespace pointer or NULL if no namespace was found or + * a memory allocation failed. Allocations can only fail if the "xml" + * namespace is queried. */ xmlNsPtr -xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { - +xmlSearchNs(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, + const xmlChar *nameSpace) { xmlNsPtr cur; - const xmlNode *orig = node; - if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL); - if ((nameSpace != NULL) && - (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) { - if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { - /* - * The XML-1.0 namespace is normally held on the root - * element. In this case exceptionally create it on the - * node element. - */ - cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("searching namespace"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNs)); - cur->type = XML_LOCAL_NAMESPACE; - cur->href = xmlStrdup(XML_XML_NAMESPACE); - cur->prefix = xmlStrdup((const xmlChar *)"xml"); - cur->next = node->nsDef; - node->nsDef = cur; - return(cur); - } - if (doc == NULL) { - doc = node->doc; - if (doc == NULL) - return(NULL); - } - /* - * Return the XML namespace declaration held by the doc. - */ - if (doc->oldNs == NULL) - return(xmlTreeEnsureXMLDecl(doc)); - else - return(doc->oldNs); - } - while (node != NULL) { - if ((node->type == XML_ENTITY_REF_NODE) || - (node->type == XML_ENTITY_NODE) || - (node->type == XML_ENTITY_DECL)) - return(NULL); - if (node->type == XML_ELEMENT_NODE) { - cur = node->nsDef; - while (cur != NULL) { - if ((cur->prefix == NULL) && (nameSpace == NULL) && - (cur->href != NULL)) - return(cur); - if ((cur->prefix != NULL) && (nameSpace != NULL) && - (cur->href != NULL) && - (xmlStrEqual(cur->prefix, nameSpace))) - return(cur); - cur = cur->next; - } - if (orig != node) { - cur = node->ns; - if (cur != NULL) { - if ((cur->prefix == NULL) && (nameSpace == NULL) && - (cur->href != NULL)) - return(cur); - if ((cur->prefix != NULL) && (nameSpace != NULL) && - (cur->href != NULL) && - (xmlStrEqual(cur->prefix, nameSpace))) - return(cur); - } - } - } - node = node->parent; - } - return(NULL); + xmlSearchNsSafe(node, nameSpace, &cur); + return(cur); } /** @@ -6044,7 +6141,6 @@ xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, while ((node != NULL) && (node != ancestor)) { if ((node->type == XML_ENTITY_REF_NODE) || - (node->type == XML_ENTITY_NODE) || (node->type == XML_ENTITY_DECL)) return (-1); if (node->type == XML_ELEMENT_NODE) { @@ -6068,92 +6164,117 @@ xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, } /** - * xmlSearchNsByHref: - * @doc: the document - * @node: the current node - * @href: the namespace value + * xmlSearchNsByHrefSafe: + * @node: a node + * @href: a namespace URI + * @out: pointer to resulting namespace * - * Search a Ns aliasing a given URI. Recurse on the parents until it finds - * the defined namespace or return NULL otherwise. - * Returns the namespace pointer or NULL. + * Search a namespace matching @URI in scope of @node. + * + * Returns 0 on success, -1 if a memory allocation failed, 1 on + * other errors. */ -xmlNsPtr -xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) -{ +int +xmlSearchNsByHrefSafe(xmlNodePtr node, const xmlChar *href, + xmlNsPtr *out) { xmlNsPtr cur; + xmlDocPtr doc; xmlNodePtr orig = node; + xmlNodePtr parent; int is_attr; - if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL)) - return (NULL); - if (xmlStrEqual(href, XML_XML_NAMESPACE)) { - /* - * Only the document can hold the XML spec namespace. - */ - if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { - /* - * The XML-1.0 namespace is normally held on the root - * element. In this case exceptionally create it on the - * node element. - */ - cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("searching namespace"); - return (NULL); - } - memset(cur, 0, sizeof(xmlNs)); - cur->type = XML_LOCAL_NAMESPACE; - cur->href = xmlStrdup(XML_XML_NAMESPACE); - cur->prefix = xmlStrdup((const xmlChar *) "xml"); - cur->next = node->nsDef; - node->nsDef = cur; - return (cur); - } - if (doc == NULL) { - doc = node->doc; - if (doc == NULL) - return(NULL); - } - /* - * Return the XML namespace declaration held by the doc. - */ - if (doc->oldNs == NULL) - return(xmlTreeEnsureXMLDecl(doc)); - else - return(doc->oldNs); + if (out == NULL) + return(1); + *out = NULL; + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) + return(1); + + doc = node->doc; + + if ((doc != NULL) && (xmlStrEqual(href, XML_XML_NAMESPACE))) { + cur = xmlTreeEnsureXMLDecl(doc); + if (cur == NULL) + return(-1); + *out = cur; + return(0); } + is_attr = (node->type == XML_ATTRIBUTE_NODE); - while (node != NULL) { - if ((node->type == XML_ENTITY_REF_NODE) || - (node->type == XML_ENTITY_NODE) || - (node->type == XML_ENTITY_DECL)) - return (NULL); - if (node->type == XML_ELEMENT_NODE) { - cur = node->nsDef; - while (cur != NULL) { - if ((cur->href != NULL) && (href != NULL) && - (xmlStrEqual(cur->href, href))) { - if (((!is_attr) || (cur->prefix != NULL)) && - (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) - return (cur); + + while (node->type != XML_ELEMENT_NODE) { + node = node->parent; + if (node == NULL) + return(0); + } + + parent = node; + + while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) { + cur = node->nsDef; + while (cur != NULL) { + if (xmlStrEqual(cur->href, href)) { + if (((!is_attr) || (cur->prefix != NULL)) && + (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) { + *out = cur; + return(0); } - cur = cur->next; } - if (orig != node) { - cur = node->ns; - if (cur != NULL) { - if ((cur->href != NULL) && (href != NULL) && - (xmlStrEqual(cur->href, href))) { - if (((!is_attr) || (cur->prefix != NULL)) && - (xmlNsInScope(doc, orig, node, cur->prefix) == 1)) - return (cur); + cur = cur->next; + } + if (orig != node) { + cur = node->ns; + if (cur != NULL) { + if (xmlStrEqual(cur->href, href)) { + if (((!is_attr) || (cur->prefix != NULL)) && + (xmlNsInScope(doc, orig, node, + cur->prefix) == 1)) { + *out = cur; + return(0); } } } } + node = node->parent; } - return (NULL); + + /* + * The XML-1.0 namespace is normally held on the document + * element. In this case exceptionally create it on the + * node element. + */ + if ((doc == NULL) && (xmlStrEqual(href, XML_XML_NAMESPACE))) { + cur = xmlNewXmlNs(); + if (cur == NULL) + return(-1); + cur->next = parent->nsDef; + parent->nsDef = cur; + *out = cur; + } + + return(0); +} + +/** + * xmlSearchNsByHref: + * @doc: the document + * @node: the current node + * @href: the namespace value + * + * Search a Ns aliasing a given URI. Recurse on the parents until it finds + * the defined namespace or return NULL otherwise. + * + * Returns the namespace pointer or NULL if no namespace was found or + * a memory allocation failed. Allocations can only fail if the "xml" + * namespace is queried. + */ +xmlNsPtr +xmlSearchNsByHref(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, + const xmlChar * href) { + xmlNsPtr cur; + + xmlSearchNsByHrefSafe(node, href, &cur); + return(cur); } /** @@ -6170,10 +6291,11 @@ xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) * Returns the (new) namespace definition or NULL in case of error */ static xmlNsPtr -xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { +xmlNewReconciledNs(xmlNodePtr tree, xmlNsPtr ns) { xmlNsPtr def; xmlChar prefix[50]; int counter = 1; + int res; if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) { return(NULL); @@ -6184,7 +6306,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { /* * Search an existing namespace definition inherited. */ - def = xmlSearchNsByHref(doc, tree, ns->href); + res = xmlSearchNsByHrefSafe(tree, ns->href, &def); + if (res < 0) + return(NULL); if (def != NULL) return(def); @@ -6197,7 +6321,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { else snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix); - def = xmlSearchNs(doc, tree, prefix); + res = xmlSearchNsSafe(tree, prefix, &def); + if (res < 0) + return(NULL); while (def != NULL) { if (counter > 1000) return(NULL); if (ns->prefix == NULL) @@ -6205,7 +6331,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { else snprintf((char *) prefix, sizeof(prefix), "%.20s%d", (char *)ns->prefix, counter++); - def = xmlSearchNs(doc, tree, prefix); + res = xmlSearchNsSafe(tree, prefix, &def); + if (res < 0) + return(NULL); } /* @@ -6216,6 +6344,12 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { } #ifdef LIBXML_TREE_ENABLED + +typedef struct { + xmlNsPtr oldNs; + xmlNsPtr newNs; +} xmlNsCache; + /** * xmlReconciliateNs: * @doc: the document @@ -6228,12 +6362,12 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { * as possible the function try to reuse the existing namespaces found in * the new environment. If not possible the new namespaces are redeclared * on @tree at the top of the given subtree. - * Returns the number of namespace declarations created or -1 in case of error. + * + * Returns 0 on success or -1 in case of error. */ int xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { - xmlNsPtr *oldNs = NULL; - xmlNsPtr *newNs = NULL; + xmlNsCache *cache = NULL; int sizeCache = 0; int nbCache = 0; @@ -6243,35 +6377,15 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { int ret = 0, i; if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1); - if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1); if (node->doc != doc) return(-1); while (node != NULL) { /* * Reconciliate the node namespace */ if (node->ns != NULL) { - /* - * initialize the cache if needed - */ - if (sizeCache == 0) { - sizeCache = 10; - oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - return(-1); - } - newNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(oldNs); - return(-1); - } - } - for (i = 0;i < nbCache;i++) { - if (oldNs[i] == node->ns) { - node->ns = newNs[i]; + for (i = 0; i < nbCache; i++) { + if (cache[i].oldNs == node->ns) { + node->ns = cache[i].newNs; break; } } @@ -6279,32 +6393,31 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { /* * OK we need to recreate a new namespace definition */ - n = xmlNewReconciledNs(doc, tree, node->ns); - if (n != NULL) { /* :-( what if else ??? */ + n = xmlNewReconciledNs(tree, node->ns); + if (n == NULL) { + ret = -1; + } else { /* * check if we need to grow the cache buffers. */ if (sizeCache <= nbCache) { - sizeCache *= 2; - oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(newNs); - return(-1); - } - newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(oldNs); - return(-1); - } + xmlNsCache *tmp; + size_t newSize = sizeCache ? sizeCache * 2 : 10; + + tmp = xmlRealloc(cache, newSize * sizeof(tmp[0])); + if (tmp == NULL) { + ret = -1; + } else { + cache = tmp; + sizeCache = newSize; + } } - newNs[nbCache] = n; - oldNs[nbCache++] = node->ns; - node->ns = n; + if (nbCache < sizeCache) { + cache[nbCache].newNs = n; + cache[nbCache++].oldNs = node->ns; + } } + node->ns = n; } } /* @@ -6314,28 +6427,9 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { attr = node->properties; while (attr != NULL) { if (attr->ns != NULL) { - /* - * initialize the cache if needed - */ - if (sizeCache == 0) { - sizeCache = 10; - oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - return(-1); - } - newNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(oldNs); - return(-1); - } - } - for (i = 0;i < nbCache;i++) { - if (oldNs[i] == attr->ns) { - attr->ns = newNs[i]; + for (i = 0; i < nbCache; i++) { + if (cache[i].oldNs == attr->ns) { + attr->ns = cache[i].newNs; break; } } @@ -6343,32 +6437,33 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { /* * OK we need to recreate a new namespace definition */ - n = xmlNewReconciledNs(doc, tree, attr->ns); - if (n != NULL) { /* :-( what if else ??? */ + n = xmlNewReconciledNs(tree, attr->ns); + if (n == NULL) { + ret = -1; + } else { /* * check if we need to grow the cache buffers. */ if (sizeCache <= nbCache) { - sizeCache *= 2; - oldNs = (xmlNsPtr *) xmlRealloc(oldNs, - sizeCache * sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(newNs); - return(-1); - } - newNs = (xmlNsPtr *) xmlRealloc(newNs, - sizeCache * sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); - xmlFree(oldNs); - return(-1); - } + xmlNsCache *tmp; + size_t newSize = sizeCache ? + sizeCache * 2 : 10; + + tmp = xmlRealloc(cache, + newSize * sizeof(tmp[0])); + if (tmp == NULL) { + ret = -1; + } else { + cache = tmp; + sizeCache = newSize; + } + } + if (nbCache < sizeCache) { + cache[nbCache].newNs = n; + cache[nbCache++].oldNs = attr->ns; } - newNs[nbCache] = n; - oldNs[nbCache++] = attr->ns; - attr->ns = n; } + attr->ns = n; } } attr = attr->next; @@ -6404,10 +6499,8 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { } else break; } - if (oldNs != NULL) - xmlFree(oldNs); - if (newNs != NULL) - xmlFree(newNs); + if (cache != NULL) + xmlFree(cache); return(ret); } #endif /* LIBXML_TREE_ENABLED */ @@ -6469,7 +6562,11 @@ xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name, */ if ((node->ns != NULL) && (node->ns->prefix != NULL)) { tmpstr = xmlStrdup(node->ns->prefix); + if (tmpstr == NULL) + return(NULL); tmpstr = xmlStrcat(tmpstr, BAD_CAST ":"); + if (tmpstr == NULL) + return(NULL); tmpstr = xmlStrcat(tmpstr, node->name); if (tmpstr == NULL) return(NULL); @@ -6545,28 +6642,7 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop) if (prop == NULL) return(NULL); if (prop->type == XML_ATTRIBUTE_NODE) { - /* - * Note that we return at least the empty string. - * TODO: Do we really always want that? - */ - if (prop->children != NULL) { - if ((prop->children->next == NULL) && - ((prop->children->type == XML_TEXT_NODE) || - (prop->children->type == XML_CDATA_SECTION_NODE))) - { - /* - * Optimization for the common case: only 1 text node. - */ - return(xmlStrdup(prop->children->content)); - } else { - xmlChar *ret; - - ret = xmlNodeListGetString(prop->doc, prop->children, 1); - if (ret != NULL) - return(ret); - } - } - return(xmlStrdup((xmlChar *)"")); + return(xmlNodeGetContent((xmlNodePtr) prop)); } else if (prop->type == XML_ATTRIBUTE_DECL) { return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue)); } @@ -6580,10 +6656,11 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop) * * Search an attribute associated to a node * This function also looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * * Returns the attribute or the attribute declaration or NULL if - * neither was found. + * neither was found. Also returns NULL if a memory allocation failed + * making this function unreliable. */ xmlAttrPtr xmlHasProp(const xmlNode *node, const xmlChar *name) { @@ -6602,7 +6679,6 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) { } prop = prop->next; } - if (!xmlCheckDTD) return(NULL); /* * Check if there is a default declaration in the internal @@ -6634,16 +6710,53 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) { * This attribute has to be anchored in the namespace specified. * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * Note that a namespace of NULL indicates to use the default namespace. * - * Returns the attribute or the attribute declaration or NULL - * if neither was found. + * Returns the attribute or the attribute declaration or NULL if + * neither was found. Also returns NULL if a memory allocation failed + * making this function unreliable. */ xmlAttrPtr xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { - return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD)); + return(xmlGetPropNodeInternal(node, name, nameSpace, 1)); +} + +/** + * xmlNodeGetAttrValue: + * @node: the node + * @name: the attribute name + * @nsUri: the URI of the namespace + * @out: the returned string + * + * Search and get the value of an attribute associated to a node + * This attribute has to be anchored in the namespace specified. + * This does the entity substitution. The returned value must be + * freed by the caller. + * + * Available since 2.13.0. + * + * Returns 0 on success, 1 if no attribute was found, -1 if a + * memory allocation failed. + */ +int +xmlNodeGetAttrValue(const xmlNode *node, const xmlChar *name, + const xmlChar *nsUri, xmlChar **out) { + xmlAttrPtr prop; + + if (out == NULL) + return(1); + *out = NULL; + + prop = xmlGetPropNodeInternal(node, name, nsUri, 0); + if (prop == NULL) + return(1); + + *out = xmlGetPropNodeValueInternal(prop); + if (*out == NULL) + return(-1); + return(0); } /** @@ -6654,13 +6767,17 @@ xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) * Search and get the value of an attribute associated to a node * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * NOTE: this function acts independently of namespaces associated + * default declaration values. + * + * NOTE: This function acts independently of namespaces associated * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp() * for namespace aware processing. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetProp(const xmlNode *node, const xmlChar *name) { @@ -6680,18 +6797,21 @@ xmlGetProp(const xmlNode *node, const xmlChar *name) { * Search and get the value of an attribute associated to a node * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * This function is similar to xmlGetProp except it will accept only * an attribute in no namespace. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD); + prop = xmlGetPropNodeInternal(node, name, NULL, 1); if (prop == NULL) return(NULL); return(xmlGetPropNodeValueInternal(prop)); @@ -6707,16 +6827,19 @@ xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) { * This attribute has to be anchored in the namespace specified. * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD); + prop = xmlGetPropNodeInternal(node, name, nameSpace, 1); if (prop == NULL) return(NULL); return(xmlGetPropNodeValueInternal(prop)); @@ -6739,7 +6862,7 @@ xmlUnsetProp(xmlNodePtr node, const xmlChar *name) { prop = xmlGetPropNodeInternal(node, name, NULL, 0); if (prop == NULL) return(-1); - xmlUnlinkNode((xmlNodePtr) prop); + xmlUnlinkNodeInternal((xmlNodePtr) prop); xmlFreeProp(prop); return(0); } @@ -6757,10 +6880,11 @@ int xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + prop = xmlGetPropNodeInternal(node, name, + (ns != NULL) ? ns->href : NULL, 0); if (prop == NULL) return(-1); - xmlUnlinkNode((xmlNodePtr) prop); + xmlUnlinkNodeInternal((xmlNodePtr) prop); xmlFreeProp(prop); return(0); } @@ -6783,8 +6907,10 @@ xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { */ xmlAttrPtr xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { - int len; - const xmlChar *nqname; + xmlNsPtr ns = NULL; + const xmlChar *localname; + xmlChar *prefix; + int res; if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE)) return(NULL); @@ -6792,16 +6918,19 @@ xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { /* * handle QNames */ - nqname = xmlSplitQName3(name, &len); - if (nqname != NULL) { - xmlNsPtr ns; - xmlChar *prefix = xmlStrndup(name, len); - ns = xmlSearchNs(node->doc, node, prefix); - if (prefix != NULL) - xmlFree(prefix); - if (ns != NULL) - return(xmlSetNsProp(node, ns, nqname, value)); + localname = xmlSplitQName4(name, &prefix); + if (localname == NULL) + return(NULL); + + if (prefix != NULL) { + res = xmlSearchNsSafe(node, prefix, &ns); + xmlFree(prefix); + if (res < 0) + return(NULL); + if (ns != NULL) + return(xmlSetNsProp(node, ns, localname, value)); } + return(xmlSetNsProp(node, NULL, name, value)); } @@ -6825,11 +6954,22 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, if (ns && (ns->href == NULL)) return(NULL); - prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + if (name == NULL) + return(NULL); + prop = xmlGetPropNodeInternal(node, name, + (ns != NULL) ? ns->href : NULL, 0); if (prop != NULL) { + xmlNodePtr children = NULL; + /* * Modify the attribute's value. */ + if (value != NULL) { + children = xmlNewDocText(node->doc, value); + if (children == NULL) + return(NULL); + } + if (prop->atype == XML_ATTRIBUTE_ID) { xmlRemoveID(node->doc, prop); prop->atype = XML_ATTRIBUTE_ID; @@ -6842,7 +6982,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, if (value != NULL) { xmlNodePtr tmp; - prop->children = xmlNewDocText(node->doc, value); + prop->children = children; prop->last = NULL; tmp = prop->children; while (tmp != NULL) { @@ -6852,8 +6992,10 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, tmp = tmp->next; } } - if (prop->atype == XML_ATTRIBUTE_ID) - xmlAddID(NULL, node->doc, value, prop); + if ((prop->atype == XML_ATTRIBUTE_ID) && + (xmlAddIDSafe(prop, value) < 0)) { + return(NULL); + } return(prop); } /* @@ -6912,33 +7054,25 @@ xmlIsBlankNode(const xmlNode *node) { * @content: the content * @len: @content length * - * Concat the given string at the end of the existing node content + * Concat the given string at the end of the existing node content. + * + * If @len is -1, the string length will be calculated. * * Returns -1 in case of error, 0 otherwise */ int xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) { - if (node == NULL) return(-1); + if (node == NULL) + return(-1); if ((node->type != XML_TEXT_NODE) && (node->type != XML_CDATA_SECTION_NODE) && (node->type != XML_COMMENT_NODE) && - (node->type != XML_PI_NODE)) { + (node->type != XML_PI_NODE)) return(-1); - } - /* need to check if content is currently in the dictionary */ - if ((node->content == (xmlChar *) &(node->properties)) || - ((node->doc != NULL) && (node->doc->dict != NULL) && - xmlDictOwns(node->doc->dict, node->content))) { - node->content = xmlStrncatNew(node->content, content, len); - } else { - node->content = xmlStrncat(node->content, content, len); - } - node->properties = NULL; - if (node->content == NULL) - return(-1); - return(0); + + return(xmlTextAddContent(node, content, len)); } /************************************************************************ @@ -6958,16 +7092,13 @@ xmlBufferCreate(void) { xmlBufferPtr ret; ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlTreeErrMemory("creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->size = xmlDefaultBufferSize; ret->alloc = xmlBufferAllocScheme; ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlTreeErrMemory("creating buffer"); xmlFree(ret); return(NULL); } @@ -6990,17 +7121,14 @@ xmlBufferCreateSize(size_t size) { if (size >= UINT_MAX) return(NULL); ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlTreeErrMemory("creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->alloc = xmlBufferAllocScheme; ret->size = (size ? size + 1 : 0); /* +1 for ending null */ if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlTreeErrMemory("creating buffer"); xmlFree(ret); return(NULL); } @@ -7178,10 +7306,8 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { if (len < buf->size - buf->use) return(0); - if (len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if (len >= UINT_MAX - buf->use) return(-1); - } if (buf->size > (size_t) len) { size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2; @@ -7194,18 +7320,14 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { size_t start_buf = buf->content - buf->contentIO; newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size); - if (newbuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (newbuf == NULL) return(-1); - } buf->contentIO = newbuf; buf->content = newbuf + start_buf; } else { newbuf = (xmlChar *) xmlRealloc(buf->content, size); - if (newbuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (newbuf == NULL) return(-1); - } buf->content = newbuf; } buf->size = size; @@ -7295,10 +7417,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) if (size < buf->size) return 1; - if (size > UINT_MAX - 10) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if (size > UINT_MAX - 10) return 0; - } /* figure out new size */ switch (buf->alloc){ @@ -7306,19 +7426,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) case XML_BUFFER_ALLOC_DOUBLEIT: /*take care of empty case*/ if (buf->size == 0) - newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); + newSize = size + 10; else newSize = buf->size; while (size > newSize) { - if (newSize > UINT_MAX / 2) { - xmlTreeErrMemory("growing buffer"); + if (newSize > UINT_MAX / 2) return 0; - } newSize *= 2; } break; case XML_BUFFER_ALLOC_EXACT: - newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); + newSize = size + 10; break; case XML_BUFFER_ALLOC_HYBRID: if (buf->use < BASE_BUFFER_SIZE) @@ -7326,17 +7444,15 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) else { newSize = buf->size; while (size > newSize) { - if (newSize > UINT_MAX / 2) { - xmlTreeErrMemory("growing buffer"); + if (newSize > UINT_MAX / 2) return 0; - } newSize *= 2; } } break; default: - newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); + newSize = size + 10; break; } @@ -7351,10 +7467,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) buf->size += start_buf; } else { rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize); - if (rebuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (rebuf == NULL) return 0; - } buf->contentIO = rebuf; buf->content = rebuf + start_buf; } @@ -7378,10 +7492,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) rebuf[buf->use] = 0; } } - if (rebuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (rebuf == NULL) return 0; - } buf->content = rebuf; } buf->size = newSize; @@ -7421,15 +7533,11 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { /* Note that both buf->size and buf->use can be zero here. */ if ((unsigned) len >= buf->size - buf->use) { - if ((unsigned) len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if ((unsigned) len >= UINT_MAX - buf->use) return XML_ERR_NO_MEMORY; - } needSize = buf->use + len + 1; - if (!xmlBufferResize(buf, needSize)){ - xmlTreeErrMemory("growing buffer"); + if (!xmlBufferResize(buf, needSize)) return XML_ERR_NO_MEMORY; - } } memmove(&buf->content[buf->use], str, len); @@ -7486,15 +7594,11 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { } /* Note that both buf->size and buf->use can be zero here. */ if ((unsigned) len >= buf->size - buf->use) { - if ((unsigned) len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if ((unsigned) len >= UINT_MAX - buf->use) return(-1); - } needSize = buf->use + len + 1; - if (!xmlBufferResize(buf, needSize)){ - xmlTreeErrMemory("growing buffer"); - return XML_ERR_NO_MEMORY; - } + if (!xmlBufferResize(buf, needSize)) + return(-1); } memmove(&buf->content[len], &buf->content[0], buf->use); @@ -7647,6 +7751,8 @@ xmlSetDocCompressMode (xmlDocPtr doc, int mode) { /** * xmlGetCompressMode: * + * DEPRECATED: Use xmlGetDocCompressMode + * * get the default compression mode used, ZLIB based. * Returns 0 (uncompressed) to 9 (max compression) */ @@ -7660,6 +7766,8 @@ xmlGetCompressMode(void) * xmlSetCompressMode: * @mode: the compression ratio * + * DEPRECATED: Use xmlSetDocCompressMode + * * set the default compression mode used, ZLIB based * Correct values: 0 (uncompressed) to 9 (max compression) */ @@ -7767,10 +7875,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, * Create the ns-map. */ map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap)); - if (map == NULL) { - xmlTreeErrMemory("allocating namespace map"); - return (NULL); - } + if (map == NULL) + return(NULL); memset(map, 0, sizeof(struct xmlNsMap)); *nsmap = map; } @@ -7787,10 +7893,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, * Create a new item. */ ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem)); - if (ret == NULL) { - xmlTreeErrMemory("allocating namespace map item"); - return (NULL); - } + if (ret == NULL) + return(NULL); memset(ret, 0, sizeof(struct xmlNsMapItem)); } @@ -7882,10 +7986,8 @@ xmlDOMWrapNewCtxt(void) xmlDOMWrapCtxtPtr ret; ret = xmlMalloc(sizeof(xmlDOMWrapCtxt)); - if (ret == NULL) { - xmlTreeErrMemory("allocating DOM-wrapper context"); + if (ret == NULL) return (NULL); - } memset(ret, 0, sizeof(xmlDOMWrapCtxt)); return (ret); } @@ -8001,39 +8103,6 @@ xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map, return (0); } -/* -* XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict; -* otherwise copy it, when it was in the source-dict. -*/ -#define XML_TREE_ADOPT_STR(str) \ - if (adoptStr && (str != NULL)) { \ - if (destDoc->dict) { \ - const xmlChar *old = str; \ - str = xmlDictLookup(destDoc->dict, str, -1); \ - if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \ - (!xmlDictOwns(sourceDoc->dict, old))) \ - xmlFree((char *)old); \ - } else if ((sourceDoc) && (sourceDoc->dict) && \ - xmlDictOwns(sourceDoc->dict, str)) { \ - str = BAD_CAST xmlStrdup(str); \ - } \ - } - -/* -* XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then -* put it in dest-dict or copy it. -*/ -#define XML_TREE_ADOPT_STR_2(str) \ - if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \ - (sourceDoc->dict != NULL) && \ - xmlDictOwns(sourceDoc->dict, cur->content)) { \ - if (destDoc->dict) \ - cur->content = (xmlChar *) \ - xmlDictLookup(destDoc->dict, cur->content, -1); \ - else \ - cur->content = xmlStrdup(BAD_CAST cur->content); \ - } - /* * xmlDOMWrapNSNormAddNsMapItem2: * @@ -8045,23 +8114,18 @@ static int xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number, xmlNsPtr oldNs, xmlNsPtr newNs) { - if (*list == NULL) { - *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr)); - if (*list == NULL) { - xmlTreeErrMemory("alloc ns map item"); - return(-1); - } - *size = 3; - *number = 0; - } else if ((*number) >= (*size)) { - *size *= 2; - *list = (xmlNsPtr *) xmlRealloc(*list, - (*size) * 2 * sizeof(xmlNsPtr)); - if (*list == NULL) { - xmlTreeErrMemory("realloc ns map item"); - return(-1); - } + if (*number >= *size) { + xmlNsPtr *tmp; + size_t newSize; + + newSize = *size ? *size * 2 : 3; + tmp = xmlRealloc(*list, newSize * 2 * sizeof(tmp[0])); + if (tmp == NULL) + return(-1); + *list = tmp; + *size = newSize; } + (*list)[2 * (*number)] = oldNs; (*list)[2 * (*number) +1] = newNs; (*number)++; @@ -8090,7 +8154,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr node, int options ATTRIBUTE_UNUSED) { xmlNsPtr *list = NULL; - int sizeList, nbList, i, j; + int sizeList = 0, nbList = 0, ret = 0, i, j; xmlNsPtr ns; if ((node == NULL) || (doc == NULL) || (node->doc != doc)) @@ -8106,7 +8170,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, case XML_ENTITY_REF_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - xmlUnlinkNode(node); + xmlUnlinkNodeInternal(node); return (0); case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: @@ -8114,7 +8178,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, default: return (1); } - xmlUnlinkNode(node); + xmlUnlinkNodeInternal(node); /* * Save out-of-scope ns-references in doc->oldNs. */ @@ -8126,7 +8190,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, do { if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList, &nbList, ns, ns) == -1) - goto internal_error; + ret = -1; ns = ns->next; } while (ns != NULL); } @@ -8156,7 +8220,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, ns = xmlDOMWrapStoreNs(doc, node->ns->href, node->ns->prefix); if (ns == NULL) - goto internal_error; + ret = -1; } if (ns != NULL) { /* @@ -8164,7 +8228,7 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, */ if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList, &nbList, node->ns, ns) == -1) - goto internal_error; + ret = -1; } node->ns = ns; } @@ -8189,19 +8253,22 @@ xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, if (node->next != NULL) node = node->next; else { + int type = node->type; + node = node->parent; - goto next_sibling; + if ((type == XML_ATTRIBUTE_NODE) && + (node != NULL) && + (node->children != NULL)) { + node = node->children; + } else { + goto next_sibling; + } } } while (node != NULL); if (list != NULL) xmlFree(list); - return (0); - -internal_error: - if (list != NULL) - xmlFree(list); - return (-1); + return (ret); } /* @@ -8299,8 +8366,7 @@ xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node, out = prev; prev = cur; } - } else if ((cur->type == XML_ENTITY_NODE) || - (cur->type == XML_ENTITY_DECL)) + } else if (cur->type == XML_ENTITY_DECL) return (0); cur = cur->parent; } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur)); @@ -8362,8 +8428,7 @@ xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node, ns = ns->next; } while (ns != NULL); } - } else if ((cur->type == XML_ENTITY_NODE) || - (cur->type == XML_ENTITY_DECL)) + } else if (cur->type == XML_ENTITY_DECL) return (0); cur = cur->parent; } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur)); @@ -8547,7 +8612,6 @@ xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc, */ if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, XML_TREE_NSMAP_DOC) == NULL) { - xmlFreeNs(tmpns); return (-1); } *retNs = tmpns; @@ -8577,7 +8641,6 @@ xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc, } } if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) { - xmlFreeNs(tmpns); return (-1); } *retNs = tmpns; @@ -8622,7 +8685,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, int optRemoveRedundantNS = ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0; xmlNsPtr *listRedund = NULL; - int sizeRedund = 0, nbRedund = 0, ret, i, j; + int sizeRedund = 0, nbRedund = 0, ret = 0, i, j; if ((elem == NULL) || (elem->doc == NULL) || (elem->type != XML_ELEMENT_NODE)) @@ -8651,7 +8714,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, */ if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, elem->parent) == -1) - goto internal_error; + ret = -1; } parnsdone = 1; } @@ -8673,16 +8736,18 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, * Add it to the list of redundant ns-decls. */ if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund, - &sizeRedund, &nbRedund, ns, mi->newNs) == -1) - goto internal_error; - /* - * Remove the ns-decl from the element-node. - */ - if (prevns) - prevns->next = ns->next; - else - cur->nsDef = ns->next; - goto next_ns_decl; + &sizeRedund, &nbRedund, ns, mi->newNs) == -1) { + ret = -1; + } else { + /* + * Remove the ns-decl from the element-node. + */ + if (prevns) + prevns->next = ns->next; + else + cur->nsDef = ns->next; + goto next_ns_decl; + } } } } @@ -8712,7 +8777,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, */ if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns, depth) == NULL) - goto internal_error; + ret = -1; prevns = ns; next_ns_decl: @@ -8732,7 +8797,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, ((xmlNodePtr) elem->parent->doc != elem->parent)) { if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, elem->parent) == -1) - goto internal_error; + ret = -1; } parnsdone = 1; } @@ -8771,7 +8836,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, &nsMap, depth, ancestorsOnly, (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) - goto internal_error; + ret = -1; cur->ns = ns; ns_end: @@ -8831,11 +8896,6 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, } } while (cur != NULL); - ret = 0; - goto exit; -internal_error: - ret = -1; -exit: if (listRedund) { for (i = 0, j = 0; i < nbRedund; i++, j += 2) { xmlFreeNs(listRedund[j]); @@ -8871,7 +8931,7 @@ xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED, */ static int xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, - xmlDocPtr sourceDoc, + xmlDocPtr sourceDoc ATTRIBUTE_UNUSED, xmlNodePtr node, xmlDocPtr destDoc, xmlNodePtr destParent, @@ -8882,21 +8942,12 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, xmlNsMapPtr nsMap = NULL; xmlNsMapItemPtr mi; xmlNsPtr ns = NULL; - int depth = -1, adoptStr = 1; + int depth = -1; /* gather @parent's ns-decls. */ int parnsdone; /* @ancestorsOnly should be set per option. */ int ancestorsOnly = 0; - /* - * Optimize string adoption for equal or none dicts. - */ - if ((sourceDoc != NULL) && - (sourceDoc->dict == destDoc->dict)) - adoptStr = 0; - else - adoptStr = 1; - /* * Get the ns-map from the context if available. */ @@ -8916,40 +8967,21 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, parnsdone = 0; cur = node; - if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL)) - goto internal_error; while (cur != NULL) { - /* - * Paranoid source-doc sanity check. - */ - if (cur->doc != sourceDoc) { - /* - * We'll assume XIncluded nodes if the doc differs. - * TODO: Do we need to reconciliate XIncluded nodes? - * This here skips XIncluded nodes and tries to handle - * broken sequences. - */ - if (cur->next == NULL) - goto leave_node; - do { - cur = cur->next; - if ((cur->type == XML_XINCLUDE_END) || - (cur->doc == node->doc)) - break; - } while (cur->next != NULL); + if (cur->doc != destDoc) { + if (xmlNodeSetDoc(cur, destDoc) < 0) + ret = -1; + } - if (cur->doc != node->doc) - goto leave_node; - } - cur->doc = destDoc; switch (cur->type) { case XML_XINCLUDE_START: case XML_XINCLUDE_END: /* * TODO */ - return (-1); + ret = -1; + goto leave_node; case XML_ELEMENT_NODE: curElem = cur; depth++; @@ -8970,14 +9002,12 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, */ if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1) - goto internal_error; + ret = -1; parnsdone = 1; } for (ns = cur->nsDef; ns != NULL; ns = ns->next) { /* * NOTE: ns->prefix and ns->href are never in the dict. - * XML_TREE_ADOPT_STR(ns->prefix) - * XML_TREE_ADOPT_STR(ns->href) */ /* * Does it shadow any ns-decl? @@ -8999,7 +9029,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, */ if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns, depth) == NULL) - goto internal_error; + ret = -1; } } /* Falls through. */ @@ -9011,7 +9041,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, if (! parnsdone) { if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1) - goto internal_error; + ret = -1; parnsdone = 1; } /* @@ -9045,7 +9075,7 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, */ if (xmlDOMWrapNsMapAddItem(&nsMap, -1, cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL) - goto internal_error; + ret = -1; cur->ns = ns; } else { /* @@ -9059,15 +9089,11 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, ancestorsOnly, /* ns-decls must be prefixed for attributes. */ (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1) - goto internal_error; + ret = -1; cur->ns = ns; } + ns_end: - /* - * Further node properties. - * TODO: Is this all? - */ - XML_TREE_ADOPT_STR(cur->name) if (cur->type == XML_ELEMENT_NODE) { cur->psvi = NULL; cur->line = 0; @@ -9082,55 +9108,16 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, cur = (xmlNodePtr) cur->properties; continue; } - } else { - /* - * Attributes. - */ - if ((sourceDoc != NULL) && - (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID)) - { - xmlRemoveID(sourceDoc, (xmlAttrPtr) cur); - } - ((xmlAttrPtr) cur)->atype = 0; - ((xmlAttrPtr) cur)->psvi = NULL; } break; case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: - /* - * This puts the content in the dest dict, only if - * it was previously in the source dict. - */ - XML_TREE_ADOPT_STR_2(cur->content) - goto leave_node; - case XML_ENTITY_REF_NODE: - /* - * Remove reference to the entity-node. - */ - cur->content = NULL; - cur->children = NULL; - cur->last = NULL; - if ((destDoc->intSubset) || (destDoc->extSubset)) { - xmlEntityPtr ent; - /* - * Assign new entity-node if available. - */ - ent = xmlGetDocEntity(destDoc, cur->name); - if (ent != NULL) { - cur->content = ent->content; - cur->children = (xmlNodePtr) ent; - cur->last = (xmlNodePtr) ent; - } - } - goto leave_node; case XML_PI_NODE: - XML_TREE_ADOPT_STR(cur->name) - XML_TREE_ADOPT_STR_2(cur->content) - break; case XML_COMMENT_NODE: - break; + case XML_ENTITY_REF_NODE: + goto leave_node; default: - goto internal_error; + ret = -1; } /* * Walk the tree. @@ -9181,12 +9168,6 @@ xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt, } } - goto exit; - -internal_error: - ret = -1; - -exit: /* * Cleanup. */ @@ -9248,7 +9229,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, int options ATTRIBUTE_UNUSED) { int ret = 0; - xmlNodePtr cur, curElem = NULL; + xmlNodePtr cur, cloneElem = NULL; xmlNsMapPtr nsMap = NULL; xmlNsMapItemPtr mi; xmlNsPtr ns; @@ -9266,7 +9247,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL; xmlDictPtr dict; /* The destination dict */ - if ((node == NULL) || (resNode == NULL) || (destDoc == NULL)) + if ((node == NULL) || (resNode == NULL) || (destDoc == NULL) || + ((destParent != NULL) && (destParent->doc != destDoc))) return(-1); /* * TODO: Initially we support only element-nodes. @@ -9298,9 +9280,6 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, *resNode = NULL; cur = node; - if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL)) - return(-1); - while (cur != NULL) { if (cur->doc != sourceDoc) { /* @@ -9328,15 +9307,12 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, case XML_PI_NODE: case XML_DOCUMENT_FRAG_NODE: case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: /* * Nodes of xmlNode structure. */ clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (clone == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node"); + if (clone == NULL) goto internal_error; - } memset(clone, 0, sizeof(xmlNode)); /* * Set hierarchical links. @@ -9348,6 +9324,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, clone->prev = prevClone; } else parentClone->children = clone; + parentClone->last = clone; } else resultClone = clone; @@ -9358,10 +9335,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, */ /* Use xmlRealloc to avoid -Warray-bounds warning */ clone = (xmlNodePtr) xmlRealloc(NULL, sizeof(xmlAttr)); - if (clone == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node"); + if (clone == NULL) goto internal_error; - } memset(clone, 0, sizeof(xmlAttr)); /* * Set hierarchical links. @@ -9402,7 +9377,12 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, else if (cur->name == xmlStringComment) clone->name = xmlStringComment; else if (cur->name != NULL) { - DICT_CONST_COPY(cur->name, clone->name); + if (dict != NULL) + clone->name = xmlDictLookup(dict, cur->name, -1); + else + clone->name = xmlStrdup(cur->name); + if (clone->name == NULL) + goto internal_error; } switch (cur->type) { @@ -9413,7 +9393,7 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, */ return (-1); case XML_ELEMENT_NODE: - curElem = cur; + cloneElem = clone; depth++; /* * Namespace declarations. @@ -9439,18 +9419,25 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, * Create a new xmlNs. */ cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cloneNs == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): " - "allocating namespace"); - return(-1); - } + if (cloneNs == NULL) + goto internal_error; memset(cloneNs, 0, sizeof(xmlNs)); cloneNs->type = XML_LOCAL_NAMESPACE; - if (ns->href != NULL) + if (ns->href != NULL) { cloneNs->href = xmlStrdup(ns->href); - if (ns->prefix != NULL) + if (cloneNs->href == NULL) { + xmlFreeNs(cloneNs); + goto internal_error; + } + } + if (ns->prefix != NULL) { cloneNs->prefix = xmlStrdup(ns->prefix); + if (cloneNs->prefix == NULL) { + xmlFreeNs(cloneNs); + goto internal_error; + } + } *cloneNsDefSlot = cloneNs; cloneNsDefSlot = &(cloneNs->next); @@ -9496,15 +9483,18 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, /* IDs will be processed further down. */ /* cur->ns will be processed further down. */ break; + case XML_PI_NODE: + case XML_COMMENT_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: /* * Note that this will also cover the values of attributes. */ - DICT_COPY(cur->content, clone->content); - goto leave_node; - case XML_ENTITY_NODE: - /* TODO: What to do here? */ + if (cur->content != NULL) { + clone->content = xmlStrdup(cur->content); + if (clone->content == NULL) + goto internal_error; + } goto leave_node; case XML_ENTITY_REF_NODE: if (sourceDoc != destDoc) { @@ -9530,12 +9520,6 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, clone->last = cur->last; } goto leave_node; - case XML_PI_NODE: - DICT_COPY(cur->content, clone->content); - goto leave_node; - case XML_COMMENT_NODE: - DICT_COPY(cur->content, clone->content); - goto leave_node; default: goto internal_error; } @@ -9595,8 +9579,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, * Acquire a normalized ns-decl and add it to the map. */ if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc, - /* ns-decls on curElem or on destDoc->oldNs */ - destParent ? curElem : NULL, + /* ns-decls on cloneElem or on destDoc->oldNs */ + destParent ? cloneElem : NULL, cur->ns, &ns, &nsMap, depth, /* if we need to search only in the ancestor-axis */ @@ -9617,19 +9601,22 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, if ((clone->type == XML_ATTRIBUTE_NODE) && (clone->parent != NULL)) { - if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) { + int res; + res = xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone); + if (res < 0) + goto internal_error; + if (res == 1) { xmlChar *idVal; - idVal = xmlNodeListGetString(cur->doc, cur->children, 1); - if (idVal != NULL) { - if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) { - /* TODO: error message. */ - xmlFree(idVal); - goto internal_error; - } - xmlFree(idVal); - } + idVal = xmlNodeGetContent(cur); + if (idVal == NULL) + goto internal_error; + if (xmlAddIDSafe((xmlAttrPtr) cur, idVal) < 0) { + xmlFree(idVal); + goto internal_error; + } + xmlFree(idVal); } } /* @@ -9694,11 +9681,6 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, prevClone = clone; cur = cur->next; } else if (cur->type != XML_ATTRIBUTE_NODE) { - /* - * Set clone->last. - */ - if (clone->parent != NULL) - clone->parent->last = clone; clone = clone->parent; if (clone != NULL) parentClone = clone->parent; @@ -9767,19 +9749,22 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, */ static int xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt, - xmlDocPtr sourceDoc, + xmlDocPtr sourceDoc ATTRIBUTE_UNUSED, xmlAttrPtr attr, xmlDocPtr destDoc, xmlNodePtr destParent, int options ATTRIBUTE_UNUSED) { - xmlNodePtr cur; - int adoptStr = 1; + int ret = 0; if ((attr == NULL) || (destDoc == NULL)) return (-1); - attr->doc = destDoc; + if (attr->doc != destDoc) { + if (xmlSetTreeDoc((xmlNodePtr) attr, destDoc) < 0) + ret = -1; + } + if (attr->ns != NULL) { xmlNsPtr ns = NULL; @@ -9800,75 +9785,18 @@ xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt, */ if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href, &ns, 1) == -1) - goto internal_error; + ret = -1; if (ns == NULL) { ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent, attr->ns->href, attr->ns->prefix, 1); } } if (ns == NULL) - goto internal_error; + ret = -1; attr->ns = ns; } - XML_TREE_ADOPT_STR(attr->name); - attr->atype = 0; - attr->psvi = NULL; - /* - * Walk content. - */ - if (attr->children == NULL) - return (0); - cur = attr->children; - if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL)) - goto internal_error; - while (cur != NULL) { - cur->doc = destDoc; - switch (cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - XML_TREE_ADOPT_STR_2(cur->content) - break; - case XML_ENTITY_REF_NODE: - /* - * Remove reference to the entity-node. - */ - cur->content = NULL; - cur->children = NULL; - cur->last = NULL; - if ((destDoc->intSubset) || (destDoc->extSubset)) { - xmlEntityPtr ent; - /* - * Assign new entity-node if available. - */ - ent = xmlGetDocEntity(destDoc, cur->name); - if (ent != NULL) { - cur->content = ent->content; - cur->children = (xmlNodePtr) ent; - cur->last = (xmlNodePtr) ent; - } - } - break; - default: - break; - } - if (cur->children != NULL) { - cur = cur->children; - continue; - } -next_sibling: - if (cur == (xmlNodePtr) attr) - break; - if (cur->next != NULL) - cur = cur->next; - else { - cur = cur->parent; - goto next_sibling; - } - } - return (0); -internal_error: - return (-1); + return (ret); } /* @@ -9906,6 +9834,8 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, xmlNodePtr destParent, int options) { + int ret = 0; + if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (destDoc == NULL) || ((destParent != NULL) && (destParent->doc != destDoc))) @@ -9913,17 +9843,18 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, /* * Check node->doc sanity. */ - if ((node->doc != NULL) && (sourceDoc != NULL) && - (node->doc != sourceDoc)) { - /* - * Might be an XIncluded node. - */ + if (sourceDoc == NULL) { + sourceDoc = node->doc; + } else if (node->doc != sourceDoc) { return (-1); } - if (sourceDoc == NULL) - sourceDoc = node->doc; + + /* + * TODO: Shouldn't this be allowed? + */ if (sourceDoc == destDoc) return (-1); + switch (node->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: @@ -9943,7 +9874,7 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, * Unlink only if @node was not already added to @destParent. */ if ((node->parent != NULL) && (destParent != node->parent)) - xmlUnlinkNode(node); + xmlUnlinkNodeInternal(node); if (node->type == XML_ELEMENT_NODE) { return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node, @@ -9952,52 +9883,12 @@ xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt, return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc, (xmlAttrPtr) node, destDoc, destParent, options)); } else { - xmlNodePtr cur = node; - int adoptStr = 1; - - cur->doc = destDoc; - /* - * Optimize string adoption. - */ - if ((sourceDoc != NULL) && - (sourceDoc->dict == destDoc->dict)) - adoptStr = 0; - switch (node->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - XML_TREE_ADOPT_STR_2(node->content) - break; - case XML_ENTITY_REF_NODE: - /* - * Remove reference to the entity-node. - */ - node->content = NULL; - node->children = NULL; - node->last = NULL; - if ((destDoc->intSubset) || (destDoc->extSubset)) { - xmlEntityPtr ent; - /* - * Assign new entity-node if available. - */ - ent = xmlGetDocEntity(destDoc, node->name); - if (ent != NULL) { - node->content = ent->content; - node->children = (xmlNodePtr) ent; - node->last = (xmlNodePtr) ent; - } - } - XML_TREE_ADOPT_STR(node->name) - break; - case XML_PI_NODE: { - XML_TREE_ADOPT_STR(node->name) - XML_TREE_ADOPT_STR_2(node->content) - break; - } - default: - break; - } + if (node->doc != destDoc) { + if (xmlNodeSetDoc(node, destDoc) < 0) + ret = -1; + } } - return (0); + return (ret); } /************************************************************************ @@ -10055,6 +9946,8 @@ xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) { * xmlRegisterNodeDefault: * @func: function pointer to the new RegisterNodeFunc * + * DEPRECATED: don't use + * * Registers a callback for node creation * * Returns the old value of the registration function @@ -10073,6 +9966,8 @@ xmlRegisterNodeDefault(xmlRegisterNodeFunc func) * xmlDeregisterNodeDefault: * @func: function pointer to the new DeregisterNodeFunc * + * DEPRECATED: don't use + * * Registers a callback for node destruction * * Returns the previous value of the deregistration function diff --git a/trio.c b/trio.c deleted file mode 100644 index 31b3b37..0000000 --- a/trio.c +++ /dev/null @@ -1,6892 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************* - * - * A note to trio contributors: - * - * Avoid heap allocation at all costs to ensure that the trio functions - * are async-safe. The exceptions are the printf/fprintf functions, which - * uses fputc, and the asprintf functions and the modifier, which - * by design are required to allocate form the heap. - * - ************************************************************************/ - -/* - * TODO: - * - Scan is probably too permissive about its modifiers. - * - C escapes in %#[] ? - * - Multibyte characters (done for format parsing, except scan groups) - * - Complex numbers? (C99 _Complex) - * - Boolean values? (C99 _Bool) - * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used - * to print the mantissa, e.g. NaN(0xc000000000000000) - * - Should we support the GNU %a alloc modifier? GNU has an ugly hack - * for %a, because C99 used %a for other purposes. If specified as - * %as or %a[ it is interpreted as the alloc modifier, otherwise as - * the C99 hex-float. This means that you cannot scan %as as a hex-float - * immediately followed by an 's'. - * - Scanning of collating symbols. - */ - -/************************************************************************* - * Trio include files - */ -#include "triodef.h" -#include "trio.h" -#include "triop.h" -#include "trionan.h" -#if !defined(TRIO_MINIMAL) -# include "triostr.h" -#endif - -/************************************************************************** - * - * Definitions - * - *************************************************************************/ - -#include -#include -#include - -#if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \ - || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \ - && !defined(_WIN32_WCE) -# define TRIO_COMPILER_SUPPORTS_MULTIBYTE -# if !defined(MB_LEN_MAX) -# define MB_LEN_MAX 6 -# endif -#endif - -#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB) -# define TRIO_COMPILER_SUPPORTS_MSVC_INT -#endif - -#if defined(_WIN32_WCE) -#include -#endif - -/************************************************************************* - * Generic definitions - */ - -#if !(defined(DEBUG) || defined(NDEBUG)) -# define NDEBUG -#endif - -#include -#include -#if !defined(TRIO_COMPILER_SUPPORTS_C99) -# define isblank(x) (((x)==32) || ((x)==9)) -#endif -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif -#include -#include - -#ifndef NULL -# define NULL 0 -#endif -#define NIL ((char)0) -#ifndef FALSE -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#define BOOLEAN_T int - -/* mincore() can be used for debugging purposes */ -#define VALID(x) (NULL != (x)) - -#if TRIO_ERRORS - /* - * Encode the error code and the position. This is decoded - * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. - */ -# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) -#else -# define TRIO_ERROR_RETURN(x,y) (-1) -#endif - -#ifndef VA_LIST_IS_ARRAY -#define TRIO_VA_LIST_PTR va_list * -#define TRIO_VA_LIST_ADDR(l) (&(l)) -#define TRIO_VA_LIST_DEREF(l) (*(l)) -#else -#define TRIO_VA_LIST_PTR va_list -#define TRIO_VA_LIST_ADDR(l) (l) -#define TRIO_VA_LIST_DEREF(l) (l) -#endif - -typedef unsigned long trio_flags_t; - - -/************************************************************************* - * Platform specific definitions - */ -#if defined(TRIO_PLATFORM_UNIX) || defined(TRIO_PLATFORM_OS400) -# include -# include -# include -# define USE_LOCALE -#endif /* TRIO_PLATFORM_UNIX */ -#if defined(TRIO_PLATFORM_VMS) -# include -#endif -#if defined(TRIO_PLATFORM_WIN32) -# if defined(_WIN32_WCE) -# include -# else -# include -# define read _read -# define write _write -# endif -#endif /* TRIO_PLATFORM_WIN32 */ - -#if TRIO_WIDECHAR -# if defined(TRIO_COMPILER_SUPPORTS_ISO94) -# include -# include -typedef wchar_t trio_wchar_t; -typedef wint_t trio_wint_t; -# else -typedef char trio_wchar_t; -typedef int trio_wint_t; -# define WCONST(x) L ## x -# define WEOF EOF -# define iswalnum(x) isalnum(x) -# define iswalpha(x) isalpha(x) -# define iswblank(x) isblank(x) -# define iswcntrl(x) iscntrl(x) -# define iswdigit(x) isdigit(x) -# define iswgraph(x) isgraph(x) -# define iswlower(x) islower(x) -# define iswprint(x) isprint(x) -# define iswpunct(x) ispunct(x) -# define iswspace(x) isspace(x) -# define iswupper(x) isupper(x) -# define iswxdigit(x) isxdigit(x) -# endif -#endif - - -/************************************************************************* - * Compiler dependent definitions - */ - -/* Support for long long */ -#ifndef __cplusplus -# if !defined(USE_LONGLONG) -# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__) -# define USE_LONGLONG -# elif defined(TRIO_COMPILER_SUNPRO) -# define USE_LONGLONG -# elif defined(_LONG_LONG) || defined(_LONGLONG) -# define USE_LONGLONG -# endif -# endif -#endif - -/* The extra long numbers */ -#if defined(USE_LONGLONG) -typedef signed long long int trio_longlong_t; -typedef unsigned long long int trio_ulonglong_t; -#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT) -typedef signed __int64 trio_longlong_t; -typedef unsigned __int64 trio_ulonglong_t; -#else -typedef TRIO_SIGNED long int trio_longlong_t; -typedef unsigned long int trio_ulonglong_t; -#endif - -/* Maximal and fixed integer types */ -#if defined(TRIO_COMPILER_SUPPORTS_C99) && !defined( __VMS ) -# include -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98) || defined( __VMS ) -# include -#ifdef __VMS -typedef long long int intmax_t; -typedef unsigned long long int uintmax_t; -#endif -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT) -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -typedef __int8 trio_int8_t; -typedef __int16 trio_int16_t; -typedef __int32 trio_int32_t; -typedef __int64 trio_int64_t; -#else -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -# if defined(TRIO_INT8_T) -typedef TRIO_INT8_T trio_int8_t; -# else -typedef TRIO_SIGNED char trio_int8_t; -# endif -# if defined(TRIO_INT16_T) -typedef TRIO_INT16_T trio_int16_t; -# else -typedef TRIO_SIGNED short trio_int16_t; -# endif -# if defined(TRIO_INT32_T) -typedef TRIO_INT32_T trio_int32_t; -# else -typedef TRIO_SIGNED int trio_int32_t; -# endif -# if defined(TRIO_INT64_T) -typedef TRIO_INT64_T trio_int64_t; -# else -typedef trio_longlong_t trio_int64_t; -# endif -#endif - -#if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \ - || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \ - && !defined(_WIN32_WCE) -# define floorl(x) floor((double)(x)) -# define fmodl(x,y) fmod((double)(x),(double)(y)) -# define powl(x,y) pow((double)(x),(double)(y)) -#endif - -#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x)) - -/************************************************************************* - * Internal Definitions - */ - -#ifndef DECIMAL_DIG -# define DECIMAL_DIG DBL_DIG -#endif - -/* Long double sizes */ -#ifdef LDBL_DIG -# define MAX_MANTISSA_DIGITS LDBL_DIG -# define MAX_EXPONENT_DIGITS 4 -# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP -#else -# define MAX_MANTISSA_DIGITS DECIMAL_DIG -# define MAX_EXPONENT_DIGITS 3 -# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP -#endif - -#if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG) -# undef LDBL_DIG -# undef LDBL_MANT_DIG -# undef LDBL_EPSILON -# define LDBL_DIG DBL_DIG -# define LDBL_MANT_DIG DBL_MANT_DIG -# define LDBL_EPSILON DBL_EPSILON -#endif - -/* The maximal number of digits is for base 2 */ -#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT) -/* The width of a pointer. The number of bits in a hex digit is 4 */ -#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4) - -/* Infinite and Not-A-Number for floating-point */ -#define INFINITE_LOWER "inf" -#define INFINITE_UPPER "INF" -#define LONG_INFINITE_LOWER "infinite" -#define LONG_INFINITE_UPPER "INFINITE" -#define NAN_LOWER "nan" -#define NAN_UPPER "NAN" - -#if !defined(HAVE_ISASCII) && !defined(isascii) -#ifndef __VMS -# define isascii(x) ((unsigned int)(x) < 128) -#endif -#endif - -/* Various constants */ -enum { - TYPE_PRINT = 1, - TYPE_SCAN = 2, - - /* Flags. FLAGS_LAST must be less than ULONG_MAX */ - FLAGS_NEW = 0, - FLAGS_STICKY = 1, - FLAGS_SPACE = 2 * FLAGS_STICKY, - FLAGS_SHOWSIGN = 2 * FLAGS_SPACE, - FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN, - FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST, - FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE, - FLAGS_SHORTSHORT = 2 * FLAGS_SHORT, - FLAGS_LONG = 2 * FLAGS_SHORTSHORT, - FLAGS_QUAD = 2 * FLAGS_LONG, - FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD, - FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE, - FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T, - FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T, - FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T, - FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING, - FLAGS_UPPER = 2 * FLAGS_UNSIGNED, - FLAGS_WIDTH = 2 * FLAGS_UPPER, - FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH, - FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER, - FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION, - FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER, - FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE, - FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER, - FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E, - FLAGS_QUOTE = 2 * FLAGS_FLOAT_G, - FLAGS_WIDECHAR = 2 * FLAGS_QUOTE, - FLAGS_ALLOC = 2 * FLAGS_WIDECHAR, - FLAGS_IGNORE = 2 * FLAGS_ALLOC, - FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE, - FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER, - FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER, - FLAGS_LAST = FLAGS_FIXED_SIZE, - /* Reused flags */ - FLAGS_EXCLUDE = FLAGS_SHORT, - FLAGS_USER_DEFINED = FLAGS_IGNORE, - FLAGS_ROUNDING = FLAGS_INTMAX_T, - /* Compounded flags */ - FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T, - FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT, - - NO_POSITION = -1, - NO_WIDTH = 0, - NO_PRECISION = -1, - NO_SIZE = -1, - - /* Do not change these */ - NO_BASE = -1, - MIN_BASE = 2, - MAX_BASE = 36, - BASE_BINARY = 2, - BASE_OCTAL = 8, - BASE_DECIMAL = 10, - BASE_HEX = 16, - - /* Maximal number of allowed parameters */ - MAX_PARAMETERS = 64, - /* Maximal number of characters in class */ - MAX_CHARACTER_CLASS = UCHAR_MAX + 1, - - /* Maximal string lengths for user-defined specifiers */ - MAX_USER_NAME = 64, - MAX_USER_DATA = 256, - - /* Maximal length of locale separator strings */ - MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX, - /* Maximal number of integers in grouping */ - MAX_LOCALE_GROUPS = 64, - - /* Initial size of asprintf buffer */ - DYNAMIC_START_SIZE = 32 -}; - -#define NO_GROUPING ((int)CHAR_MAX) - -/* Fundamental formatting parameter types */ -#define FORMAT_UNKNOWN 0 -#define FORMAT_INT 1 -#define FORMAT_DOUBLE 2 -#define FORMAT_CHAR 3 -#define FORMAT_STRING 4 -#define FORMAT_POINTER 5 -#define FORMAT_COUNT 6 -#define FORMAT_PARAMETER 7 -#define FORMAT_GROUP 8 -#if TRIO_GNU -# define FORMAT_ERRNO 9 -#endif -#if TRIO_EXTENSION -# define FORMAT_USER_DEFINED 10 -#endif - -/* Character constants */ -#define CHAR_IDENTIFIER '%' -#define CHAR_BACKSLASH '\\' -#define CHAR_QUOTE '\"' -#define CHAR_ADJUST ' ' - -/* Character class expressions */ -#define CLASS_ALNUM "[:alnum:]" -#define CLASS_ALPHA "[:alpha:]" -#define CLASS_BLANK "[:blank:]" -#define CLASS_CNTRL "[:cntrl:]" -#define CLASS_DIGIT "[:digit:]" -#define CLASS_GRAPH "[:graph:]" -#define CLASS_LOWER "[:lower:]" -#define CLASS_PRINT "[:print:]" -#define CLASS_PUNCT "[:punct:]" -#define CLASS_SPACE "[:space:]" -#define CLASS_UPPER "[:upper:]" -#define CLASS_XDIGIT "[:xdigit:]" - -/* - * SPECIFIERS: - * - * - * a Hex-float - * A Hex-float - * c Character - * C Widechar character (wint_t) - * d Decimal - * e Float - * E Float - * F Float - * F Float - * g Float - * G Float - * i Integer - * m Error message - * n Count - * o Octal - * p Pointer - * s String - * S Widechar string (wchar_t *) - * u Unsigned - * x Hex - * X Hex - * [] Group - * <> User-defined - * - * Reserved: - * - * D Binary Coded Decimal %D(length,precision) (OS/390) - */ -#define SPECIFIER_CHAR 'c' -#define SPECIFIER_STRING 's' -#define SPECIFIER_DECIMAL 'd' -#define SPECIFIER_INTEGER 'i' -#define SPECIFIER_UNSIGNED 'u' -#define SPECIFIER_OCTAL 'o' -#define SPECIFIER_HEX 'x' -#define SPECIFIER_HEX_UPPER 'X' -#define SPECIFIER_FLOAT_E 'e' -#define SPECIFIER_FLOAT_E_UPPER 'E' -#define SPECIFIER_FLOAT_F 'f' -#define SPECIFIER_FLOAT_F_UPPER 'F' -#define SPECIFIER_FLOAT_G 'g' -#define SPECIFIER_FLOAT_G_UPPER 'G' -#define SPECIFIER_POINTER 'p' -#define SPECIFIER_GROUP '[' -#define SPECIFIER_UNGROUP ']' -#define SPECIFIER_COUNT 'n' -#if TRIO_UNIX98 -# define SPECIFIER_CHAR_UPPER 'C' -# define SPECIFIER_STRING_UPPER 'S' -#endif -#if TRIO_C99 -# define SPECIFIER_HEXFLOAT 'a' -# define SPECIFIER_HEXFLOAT_UPPER 'A' -#endif -#if TRIO_GNU -# define SPECIFIER_ERRNO 'm' -#endif -#if TRIO_EXTENSION -# define SPECIFIER_BINARY 'b' -# define SPECIFIER_BINARY_UPPER 'B' -# define SPECIFIER_USER_DEFINED_BEGIN '<' -# define SPECIFIER_USER_DEFINED_END '>' -# define SPECIFIER_USER_DEFINED_SEPARATOR ':' -#endif - -/* - * QUALIFIERS: - * - * - * Numbers = d,i,o,u,x,X - * Float = a,A,e,E,f,F,g,G - * String = s - * Char = c - * - * - * 9$ Position - * Use the 9th parameter. 9 can be any number between 1 and - * the maximal argument - * - * 9 Width - * Set width to 9. 9 can be any number, but must not be postfixed - * by '$' - * - * h Short - * Numbers: - * (unsigned) short int - * - * hh Short short - * Numbers: - * (unsigned) char - * - * l Long - * Numbers: - * (unsigned) long int - * String: - * as the S specifier - * Char: - * as the C specifier - * - * ll Long Long - * Numbers: - * (unsigned) long long int - * - * L Long Double - * Float - * long double - * - * # Alternative - * Float: - * Decimal-point is always present - * String: - * non-printable characters are handled as \number - * - * Spacing - * - * + Sign - * - * - Alignment - * - * . Precision - * - * * Parameter - * print: use parameter - * scan: no parameter (ignore) - * - * q Quad - * - * Z size_t - * - * w Widechar - * - * ' Thousands/quote - * Numbers: - * Integer part grouped in thousands - * Binary numbers: - * Number grouped in nibbles (4 bits) - * String: - * Quoted string - * - * j intmax_t - * t prtdiff_t - * z size_t - * - * ! Sticky - * @ Parameter (for both print and scan) - * - * I n-bit Integer - * Numbers: - * The following options exists - * I8 = 8-bit integer - * I16 = 16-bit integer - * I32 = 32-bit integer - * I64 = 64-bit integer - */ -#define QUALIFIER_POSITION '$' -#define QUALIFIER_SHORT 'h' -#define QUALIFIER_LONG 'l' -#define QUALIFIER_LONG_UPPER 'L' -#define QUALIFIER_ALTERNATIVE '#' -#define QUALIFIER_SPACE ' ' -#define QUALIFIER_PLUS '+' -#define QUALIFIER_MINUS '-' -#define QUALIFIER_DOT '.' -#define QUALIFIER_STAR '*' -#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */ -#if TRIO_C99 -# define QUALIFIER_SIZE_T 'z' -# define QUALIFIER_PTRDIFF_T 't' -# define QUALIFIER_INTMAX_T 'j' -#endif -#if TRIO_BSD || TRIO_GNU -# define QUALIFIER_QUAD 'q' -#endif -#if TRIO_GNU -# define QUALIFIER_SIZE_T_UPPER 'Z' -#endif -#if TRIO_MISC -# define QUALIFIER_WIDECHAR 'w' -#endif -#if TRIO_MICROSOFT -# define QUALIFIER_FIXED_SIZE 'I' -#endif -#if TRIO_EXTENSION -# define QUALIFIER_QUOTE '\'' -# define QUALIFIER_STICKY '!' -# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */ -# define QUALIFIER_PARAM '@' /* Experimental */ -# define QUALIFIER_COLON ':' /* For scanlists */ -# define QUALIFIER_EQUAL '=' /* For scanlists */ -# define QUALIFIER_ROUNDING_UPPER 'R' -#endif - - -/************************************************************************* - * - * Internal Structures - * - *************************************************************************/ - -/* Parameters */ -typedef struct { - /* An indication of which entry in the data union is used */ - int type; - /* The flags */ - trio_flags_t flags; - /* The width qualifier */ - int width; - /* The precision qualifier */ - int precision; - /* The base qualifier */ - int base; - /* The size for the variable size qualifier */ - int varsize; - /* The marker of the end of the specifier */ - int indexAfterSpecifier; - /* The data from the argument list */ - union { - char *string; -#if TRIO_WIDECHAR - trio_wchar_t *wstring; -#endif - trio_pointer_t pointer; - union { - trio_intmax_t as_signed; - trio_uintmax_t as_unsigned; - } number; - double doubleNumber; - double *doublePointer; - trio_long_double_t longdoubleNumber; - trio_long_double_t *longdoublePointer; - int errorNumber; - } data; - /* For the user-defined specifier */ - char user_name[MAX_USER_NAME]; - char user_data[MAX_USER_DATA]; -} trio_parameter_t; - -/* Container for customized functions */ -typedef struct { - union { - trio_outstream_t out; - trio_instream_t in; - } stream; - trio_pointer_t closure; -} trio_custom_t; - -/* General trio "class" */ -typedef struct _trio_class_t { - /* - * The function to write characters to a stream. - */ - void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int)); - /* - * The function to read characters from a stream. - */ - void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *)); - /* - * The current location in the stream. - */ - trio_pointer_t location; - /* - * The character currently being processed. - */ - int current; - /* - * The number of characters that would have been written/read - * if there had been sufficient space. - */ - int processed; - /* - * The number of characters that are actually written/read. - * Processed and committed will only differ for the *nprintf - * and *nscanf functions. - */ - int committed; - /* - * The upper limit of characters that may be written/read. - */ - int max; - /* - * The last output error that was detected. - */ - int error; -} trio_class_t; - -/* References (for user-defined callbacks) */ -typedef struct _trio_reference_t { - trio_class_t *data; - trio_parameter_t *parameter; -} trio_reference_t; - -/* Registered entries (for user-defined callbacks) */ -typedef struct _trio_userdef_t { - struct _trio_userdef_t *next; - trio_callback_t callback; - char *name; -} trio_userdef_t; - -/************************************************************************* - * - * Internal Variables - * - *************************************************************************/ - -static TRIO_CONST char rcsid[] = "@(#)$Id$"; - -/* - * Need this to workaround a parser bug in HP C/iX compiler that fails - * to resolves macro definitions that includes type 'long double', - * e.g: va_arg(arg_ptr, long double) - */ -#if defined(TRIO_PLATFORM_MPEIX) -static TRIO_CONST trio_long_double_t ___dummy_long_double = 0; -#endif - -static TRIO_CONST char internalNullString[] = "(nil)"; - -#if defined(USE_LOCALE) -static struct lconv *internalLocaleValues = NULL; -#endif - -/* - * UNIX98 says "in a locale where the radix character is not defined, - * the radix character defaults to a period (.)" - */ -static int internalDecimalPointLength = 1; -static int internalThousandSeparatorLength = 1; -static char internalDecimalPoint = '.'; -static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = "."; -static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ","; -static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING }; - -static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static BOOLEAN_T internalDigitsUnconverted = TRUE; -static int internalDigitArray[128]; -#if TRIO_EXTENSION -static BOOLEAN_T internalCollationUnconverted = TRUE; -static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS]; -#endif - -#if TRIO_EXTENSION -static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL; -static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL; -static trio_userdef_t *internalUserDef = NULL; -#endif - - -/************************************************************************* - * - * Internal Functions - * - ************************************************************************/ - -#if defined(TRIO_MINIMAL) -# define TRIO_STRING_PUBLIC static -# include "triostr.c" -#endif /* defined(TRIO_MINIMAL) */ - -/************************************************************************* - * TrioIsQualifier - * - * Description: - * Remember to add all new qualifiers to this function. - * QUALIFIER_POSITION must not be added. - */ -TRIO_PRIVATE BOOLEAN_T -TrioIsQualifier -TRIO_ARGS1((character), - TRIO_CONST char character) -{ - /* QUALIFIER_POSITION is not included */ - switch (character) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case QUALIFIER_PLUS: - case QUALIFIER_MINUS: - case QUALIFIER_SPACE: - case QUALIFIER_DOT: - case QUALIFIER_STAR: - case QUALIFIER_ALTERNATIVE: - case QUALIFIER_SHORT: - case QUALIFIER_LONG: - case QUALIFIER_LONG_UPPER: - case QUALIFIER_CIRCUMFLEX: -#if defined(QUALIFIER_SIZE_T) - case QUALIFIER_SIZE_T: -#endif -#if defined(QUALIFIER_PTRDIFF_T) - case QUALIFIER_PTRDIFF_T: -#endif -#if defined(QUALIFIER_INTMAX_T) - case QUALIFIER_INTMAX_T: -#endif -#if defined(QUALIFIER_QUAD) - case QUALIFIER_QUAD: -#endif -#if defined(QUALIFIER_SIZE_T_UPPER) - case QUALIFIER_SIZE_T_UPPER: -#endif -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: -#endif -#if defined(QUALIFIER_QUOTE) - case QUALIFIER_QUOTE: -#endif -#if defined(QUALIFIER_STICKY) - case QUALIFIER_STICKY: -#endif -#if defined(QUALIFIER_VARSIZE) - case QUALIFIER_VARSIZE: -#endif -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: -#endif -#if defined(QUALIFIER_FIXED_SIZE) - case QUALIFIER_FIXED_SIZE: -#endif -#if defined(QUALIFIER_ROUNDING_UPPER) - case QUALIFIER_ROUNDING_UPPER: -#endif - return TRUE; - default: - return FALSE; - } -} - -/************************************************************************* - * TrioSetLocale - */ -#if defined(USE_LOCALE) -TRIO_PRIVATE void -TrioSetLocale(TRIO_NOARGS) -{ - internalLocaleValues = (struct lconv *)localeconv(); - if (internalLocaleValues) - { - if ((internalLocaleValues->decimal_point) && - (internalLocaleValues->decimal_point[0] != NIL)) - { - internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = internalLocaleValues->decimal_point[0]; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - internalLocaleValues->decimal_point); - } - } - if ((internalLocaleValues->thousands_sep) && - (internalLocaleValues->thousands_sep[0] != NIL)) - { - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - internalLocaleValues->thousands_sep); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); - } - if ((internalLocaleValues->grouping) && - (internalLocaleValues->grouping[0] != NIL)) - { - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - internalLocaleValues->grouping); - } - } -} -#endif /* defined(USE_LOCALE) */ - -TRIO_PRIVATE int -TrioCalcThousandSeparatorLength -TRIO_ARGS1((digits), - int digits) -{ -#if TRIO_EXTENSION - int count = 0; - int step = NO_GROUPING; - char *groupingPointer = internalGrouping; - - while (digits > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer == 0) - { - /* Repeat last group */ - if (step == NO_GROUPING) - { - /* Error in locale */ - break; /* while */ - } - } - else - { - step = *groupingPointer++; - } - if (digits > step) - count += internalThousandSeparatorLength; - digits -= step; - } - return count; -#else - return 0; -#endif -} - -TRIO_PRIVATE BOOLEAN_T -TrioFollowedBySeparator -TRIO_ARGS1((position), - int position) -{ -#if TRIO_EXTENSION - int step = 0; - char *groupingPointer = internalGrouping; - - position--; - if (position == 0) - return FALSE; - while (position > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer != 0) - { - step = *groupingPointer++; - } - if (step == 0) - break; - position -= step; - } - return (position == 0); -#else - return FALSE; -#endif -} - -/************************************************************************* - * TrioGetPosition - * - * Get the %n$ position. - */ -TRIO_PRIVATE int -TrioGetPosition -TRIO_ARGS2((format, indexPointer), - TRIO_CONST char *format, - int *indexPointer) -{ -#if TRIO_UNIX98 - char *tmpformat; - int number = 0; - int index = *indexPointer; - - number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL); - index = (int)(tmpformat - format); - if ((number != 0) && (QUALIFIER_POSITION == format[index++])) - { - *indexPointer = index; - /* - * number is decreased by 1, because n$ starts from 1, whereas - * the array it is indexing starts from 0. - */ - return number - 1; - } -#endif - return NO_POSITION; -} - -#if TRIO_EXTENSION -/************************************************************************* - * TrioFindNamespace - * - * Find registered user-defined specifier. - * The prev argument is used for optimization only. - */ -TRIO_PRIVATE trio_userdef_t * -TrioFindNamespace -TRIO_ARGS2((name, prev), - TRIO_CONST char *name, - trio_userdef_t **prev) -{ - trio_userdef_t *def; - - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - for (def = internalUserDef; def; def = def->next) - { - /* Case-sensitive string comparison */ - if (trio_equal_case(def->name, name)) - break; - - if (prev) - *prev = def; - } - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - - return def; -} -#endif - -/************************************************************************* - * TrioPower - * - * Description: - * Calculate pow(base, exponent), where number and exponent are integers. - */ -TRIO_PRIVATE trio_long_double_t -TrioPower -TRIO_ARGS2((number, exponent), - int number, - int exponent) -{ - trio_long_double_t result; - - if (number == 10) - { - switch (exponent) - { - /* Speed up calculation of common cases */ - case 0: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1); - break; - case 1: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0); - break; - case 2: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1); - break; - case 3: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2); - break; - case 4: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3); - break; - case 5: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4); - break; - case 6: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5); - break; - case 7: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6); - break; - case 8: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7); - break; - case 9: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8); - break; - default: - result = powl((trio_long_double_t)number, - (trio_long_double_t)exponent); - break; - } - } - else - { - return powl((trio_long_double_t)number, (trio_long_double_t)exponent); - } - return result; -} - -/************************************************************************* - * TrioLogarithm - */ -TRIO_PRIVATE double -TrioLogarithm -TRIO_ARGS2((number, base), - double number, - int base) -{ - double result; - - if (number <= 0.0) - { - /* xlC crashes on log(0) */ - result = (number == 0.0) ? trio_ninf() : trio_nan(); - } - else - { - if (base == 10) - { - result = log10(number); - } - else - { - result = log10(number) / log10((double)base); - } - } - return result; -} - -/************************************************************************* - * TrioLogarithmBase - */ -TRIO_PRIVATE double -TrioLogarithmBase -TRIO_ARGS1((base), - int base) -{ - switch (base) - { - case BASE_BINARY : return 1.0; - case BASE_OCTAL : return 3.0; - case BASE_DECIMAL: return 3.321928094887362345; - case BASE_HEX : return 4.0; - default : return TrioLogarithm((double)base, 2); - } -} - -/************************************************************************* - * TrioParse - * - * Description: - * Parse the format string - */ -TRIO_PRIVATE int -TrioParse -TRIO_ARGS5((type, format, parameters, arglist, argarray), - int type, - TRIO_CONST char *format, - trio_parameter_t *parameters, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - /* Count the number of times a parameter is referenced */ - unsigned short usedEntries[MAX_PARAMETERS]; - /* Parameter counters */ - int parameterPosition; - int currentParam; - int maxParam = -1; - /* Utility variables */ - trio_flags_t flags; - int width; - int precision; - int varsize; - int base; - int index; /* Index into formatting string */ - int dots; /* Count number of dots in modifier part */ - BOOLEAN_T positional; /* Does the specifier have a positional? */ - BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ - /* - * indices specifies the order in which the parameters must be - * read from the va_args (this is necessary to handle positionals) - */ - int indices[MAX_PARAMETERS]; - int pos = 0; - /* Various variables */ - char ch; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int save_errno; - int i = -1; - int num; - char *tmpformat; - - /* One and only one of arglist and argarray must be used */ - assert((arglist != NULL) ^ (argarray != NULL)); - - /* - * The 'parameters' array is not initialized, but we need to - * know which entries we have used. - */ - memset(usedEntries, 0, sizeof(usedEntries)); - - save_errno = errno; - index = 0; - parameterPosition = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - /* - * Multibyte characters cannot be legal specifiers or - * modifiers, so we skip over them. - */ - charlen = mblen(&format[index], MB_LEN_MAX); - index += (charlen > 0) ? charlen : 1; - continue; /* while */ - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (CHAR_IDENTIFIER == format[index++]) - { - if (CHAR_IDENTIFIER == format[index]) - { - index++; - continue; /* while */ - } - - flags = FLAGS_NEW; - dots = 0; - currentParam = TrioGetPosition(format, &index); - positional = (NO_POSITION != currentParam); - if (!positional) - { - /* We have no positional, get the next counter */ - currentParam = parameterPosition; - } - if(currentParam >= MAX_PARAMETERS) - { - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index); - } - - if (currentParam > maxParam) - maxParam = currentParam; - - /* Default values */ - width = NO_WIDTH; - precision = NO_PRECISION; - base = NO_BASE; - varsize = NO_SIZE; - - while (TrioIsQualifier(format[index])) - { - ch = format[index++]; - - switch (ch) - { - case QUALIFIER_SPACE: - flags |= FLAGS_SPACE; - break; - - case QUALIFIER_PLUS: - flags |= FLAGS_SHOWSIGN; - break; - - case QUALIFIER_MINUS: - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - break; - - case QUALIFIER_ALTERNATIVE: - flags |= FLAGS_ALTERNATIVE; - break; - - case QUALIFIER_DOT: - if (dots == 0) /* Precision */ - { - dots++; - - /* Skip if no precision */ - if (QUALIFIER_DOT == format[index]) - break; - - /* After the first dot we have the precision */ - flags |= FLAGS_PRECISION; - if ((QUALIFIER_STAR == format[index]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[index]) -#endif - ) - { - index++; - flags |= FLAGS_PRECISION_PARAMETER; - - precision = TrioGetPosition(format, &index); - if (precision == NO_POSITION) - { - parameterPosition++; - if (positional) - precision = parameterPosition; - else - { - precision = currentParam; - currentParam = precision + 1; - } - } - else - { - if (! positional) - currentParam = precision + 1; - if (width > maxParam) - maxParam = precision; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - precision = trio_to_long(&format[index], - &tmpformat, - BASE_DECIMAL); - index = (int)(tmpformat - format); - } - } - else if (dots == 1) /* Base */ - { - dots++; - - /* After the second dot we have the base */ - flags |= FLAGS_BASE; - if ((QUALIFIER_STAR == format[index]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[index]) -#endif - ) - { - index++; - flags |= FLAGS_BASE_PARAMETER; - base = TrioGetPosition(format, &index); - if (base == NO_POSITION) - { - parameterPosition++; - if (positional) - base = parameterPosition; - else - { - base = currentParam; - currentParam = base + 1; - } - } - else - { - if (! positional) - currentParam = base + 1; - if (base > maxParam) - maxParam = base; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - base = trio_to_long(&format[index], - &tmpformat, - BASE_DECIMAL); - if (base > MAX_BASE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - index = (int)(tmpformat - format); - } - } - else - { - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - break; /* QUALIFIER_DOT */ - -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: - type = TYPE_PRINT; - /* FALLTHROUGH */ -#endif - case QUALIFIER_STAR: - /* This has different meanings for print and scan */ - if (TYPE_PRINT == type) - { - /* Read with from parameter */ - flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER); - width = TrioGetPosition(format, &index); - if (width == NO_POSITION) - { - parameterPosition++; - if (positional) - width = parameterPosition; - else - { - width = currentParam; - currentParam = width + 1; - } - } - else - { - if (! positional) - currentParam = width + 1; - if (width > maxParam) - maxParam = width; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - /* Scan, but do not store result */ - flags |= FLAGS_IGNORE; - } - - break; /* QUALIFIER_STAR */ - - case '0': - if (! (flags & FLAGS_LEFTADJUST)) - flags |= FLAGS_NILPADDING; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - flags |= FLAGS_WIDTH; - /* &format[index - 1] is used to "rewind" the read - * character from format - */ - width = trio_to_long(&format[index - 1], - &tmpformat, - BASE_DECIMAL); - index = (int)(tmpformat - format); - break; - - case QUALIFIER_SHORT: - if (flags & FLAGS_SHORTSHORT) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - else if (flags & FLAGS_SHORT) - flags |= FLAGS_SHORTSHORT; - else - flags |= FLAGS_SHORT; - break; - - case QUALIFIER_LONG: - if (flags & FLAGS_QUAD) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - else if (flags & FLAGS_LONG) - flags |= FLAGS_QUAD; - else - flags |= FLAGS_LONG; - break; - - case QUALIFIER_LONG_UPPER: - flags |= FLAGS_LONGDOUBLE; - break; - -#if defined(QUALIFIER_SIZE_T) - case QUALIFIER_SIZE_T: - flags |= FLAGS_SIZE_T; - /* Modify flags for later truncation of number */ - if (sizeof(size_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(size_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_PTRDIFF_T) - case QUALIFIER_PTRDIFF_T: - flags |= FLAGS_PTRDIFF_T; - if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(ptrdiff_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_INTMAX_T) - case QUALIFIER_INTMAX_T: - flags |= FLAGS_INTMAX_T; - if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(trio_intmax_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_QUAD) - case QUALIFIER_QUAD: - flags |= FLAGS_QUAD; - break; -#endif - -#if defined(QUALIFIER_FIXED_SIZE) - case QUALIFIER_FIXED_SIZE: - if (flags & FLAGS_FIXED_SIZE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE | - FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER)) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - if ((format[index] == '6') && - (format[index + 1] == '4')) - { - varsize = sizeof(trio_int64_t); - index += 2; - } - else if ((format[index] == '3') && - (format[index + 1] == '2')) - { - varsize = sizeof(trio_int32_t); - index += 2; - } - else if ((format[index] == '1') && - (format[index + 1] == '6')) - { - varsize = sizeof(trio_int16_t); - index += 2; - } - else if (format[index] == '8') - { - varsize = sizeof(trio_int8_t); - index++; - } - else - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - flags |= FLAGS_FIXED_SIZE; - break; -#endif - -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: - flags |= FLAGS_WIDECHAR; - break; -#endif - -#if defined(QUALIFIER_SIZE_T_UPPER) - case QUALIFIER_SIZE_T_UPPER: - break; -#endif - -#if defined(QUALIFIER_QUOTE) - case QUALIFIER_QUOTE: - flags |= FLAGS_QUOTE; - break; -#endif - -#if defined(QUALIFIER_STICKY) - case QUALIFIER_STICKY: - flags |= FLAGS_STICKY; - gotSticky = TRUE; - break; -#endif - -#if defined(QUALIFIER_VARSIZE) - case QUALIFIER_VARSIZE: - flags |= FLAGS_VARSIZE_PARAMETER; - parameterPosition++; - if (positional) - varsize = parameterPosition; - else - { - varsize = currentParam; - currentParam = varsize + 1; - } - if (currentParam > maxParam) - maxParam = currentParam; - break; -#endif - -#if defined(QUALIFIER_ROUNDING_UPPER) - case QUALIFIER_ROUNDING_UPPER: - flags |= FLAGS_ROUNDING; - break; -#endif - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - } /* while qualifier */ - - /* - * Parameters only need the type and value. The value is - * read later. - */ - if (flags & FLAGS_WIDTH_PARAMETER) - { - usedEntries[width] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[width] = pos; - width = pos++; - } - if (flags & FLAGS_PRECISION_PARAMETER) - { - usedEntries[precision] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[precision] = pos; - precision = pos++; - } - if (flags & FLAGS_BASE_PARAMETER) - { - usedEntries[base] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[base] = pos; - base = pos++; - } - if (flags & FLAGS_VARSIZE_PARAMETER) - { - usedEntries[varsize] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[varsize] = pos; - varsize = pos++; - } - - indices[currentParam] = pos; - - switch (format[index++]) - { -#if defined(SPECIFIER_CHAR_UPPER) - case SPECIFIER_CHAR_UPPER: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_CHAR: - if (flags & FLAGS_LONG) - flags |= FLAGS_WIDECHAR; - else if (flags & FLAGS_SHORT) - flags &= ~FLAGS_WIDECHAR; - parameters[pos].type = FORMAT_CHAR; - break; - -#if defined(SPECIFIER_STRING_UPPER) - case SPECIFIER_STRING_UPPER: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_STRING: - if (flags & FLAGS_LONG) - flags |= FLAGS_WIDECHAR; - else if (flags & FLAGS_SHORT) - flags &= ~FLAGS_WIDECHAR; - parameters[pos].type = FORMAT_STRING; - break; - - case SPECIFIER_GROUP: - if (TYPE_SCAN == type) - { - int depth = 1; - parameters[pos].type = FORMAT_GROUP; - if (format[index] == QUALIFIER_CIRCUMFLEX) - index++; - if (format[index] == SPECIFIER_UNGROUP) - index++; - if (format[index] == QUALIFIER_MINUS) - index++; - /* Skip nested brackets */ - while (format[index] != NIL) - { - if (format[index] == SPECIFIER_GROUP) - { - depth++; - } - else if (format[index] == SPECIFIER_UNGROUP) - { - if (--depth <= 0) - { - index++; - break; - } - } - index++; - } - } - break; - - case SPECIFIER_INTEGER: - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_UNSIGNED: - flags |= FLAGS_UNSIGNED; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_DECIMAL: - /* Disable base modifier */ - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_DECIMAL; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_OCTAL: - flags |= FLAGS_UNSIGNED; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_OCTAL; - parameters[pos].type = FORMAT_INT; - break; - -#if defined(SPECIFIER_BINARY) - case SPECIFIER_BINARY_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_BINARY: - flags |= FLAGS_NILPADDING; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_BINARY; - parameters[pos].type = FORMAT_INT; - break; -#endif - - case SPECIFIER_HEX_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_HEX: - flags |= FLAGS_UNSIGNED; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_HEX; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_FLOAT_E_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_E: - flags |= FLAGS_FLOAT_E; - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_FLOAT_G_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_G: - flags |= FLAGS_FLOAT_G; - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_FLOAT_F_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_F: - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_POINTER: - if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(trio_pointer_t) == sizeof(long)) - flags |= FLAGS_LONG; - parameters[pos].type = FORMAT_POINTER; - break; - - case SPECIFIER_COUNT: - parameters[pos].type = FORMAT_COUNT; - break; - -#if defined(SPECIFIER_HEXFLOAT) -# if defined(SPECIFIER_HEXFLOAT_UPPER) - case SPECIFIER_HEXFLOAT_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_HEXFLOAT: - base = BASE_HEX; - parameters[pos].type = FORMAT_DOUBLE; - break; -#endif - -#if defined(FORMAT_ERRNO) - case SPECIFIER_ERRNO: - parameters[pos].type = FORMAT_ERRNO; - break; -#endif - -#if defined(SPECIFIER_USER_DEFINED_BEGIN) - case SPECIFIER_USER_DEFINED_BEGIN: - { - unsigned int max; - int without_namespace = TRUE; - - parameters[pos].type = FORMAT_USER_DEFINED; - parameters[pos].user_name[0] = NIL; - tmpformat = (char *)&format[index]; - - while ((ch = format[index])) - { - index++; - if (ch == SPECIFIER_USER_DEFINED_END) - { - if (without_namespace) - { - /* We must get the handle first */ - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].indexAfterSpecifier = index; - parameters[pos].flags = FLAGS_USER_DEFINED; - /* Adjust parameters for insertion of new one */ - pos++; - usedEntries[currentParam] += 1; - parameters[pos].type = FORMAT_USER_DEFINED; - currentParam++; - indices[currentParam] = pos; - if (currentParam > maxParam) - maxParam = currentParam; - } - /* Copy the user data */ - max = (unsigned int)(&format[index] - tmpformat); - if (max > MAX_USER_DATA) - max = MAX_USER_DATA; - trio_copy_max(parameters[pos].user_data, - max, - tmpformat); - break; /* while */ - } - if (ch == SPECIFIER_USER_DEFINED_SEPARATOR) - { - without_namespace = FALSE; - /* Copy the namespace for later looking-up */ - max = (int)(&format[index] - tmpformat); - if (max > MAX_USER_NAME) - max = MAX_USER_NAME; - trio_copy_max(parameters[pos].user_name, - max, - tmpformat); - tmpformat = (char *)&format[index]; - } - } - if (ch != SPECIFIER_USER_DEFINED_END) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - break; -#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */ - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - - /* Count the number of times this entry has been used */ - usedEntries[currentParam] += 1; - - /* Find last sticky parameters */ - if (gotSticky && !(flags & FLAGS_STICKY)) - { - for (i = pos - 1; i >= 0; i--) - { - if (parameters[i].type == FORMAT_PARAMETER) - continue; - if ((parameters[i].flags & FLAGS_STICKY) && - (parameters[i].type == parameters[pos].type)) - { - /* Do not overwrite current qualifiers */ - flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY); - if (width == NO_WIDTH) - width = parameters[i].width; - if (precision == NO_PRECISION) - precision = parameters[i].precision; - if (base == NO_BASE) - base = parameters[i].base; - break; - } - } - } - - parameters[pos].indexAfterSpecifier = index; - parameters[pos].flags = flags; - parameters[pos].width = width; - parameters[pos].precision = precision; - parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base; - parameters[pos].varsize = varsize; - pos++; - - if (! positional) - parameterPosition++; - - } /* if identifier */ - - } /* while format characters left */ - - for (num = 0; num <= maxParam; num++) - { - if (usedEntries[num] != 1) - { - if (usedEntries[num] == 0) /* gap detected */ - return TRIO_ERROR_RETURN(TRIO_EGAP, num); - else /* double references detected */ - return TRIO_ERROR_RETURN(TRIO_EDBLREF, num); - } - - i = indices[num]; - - /* - * FORMAT_PARAMETERS are only present if they must be read, - * so it makes no sense to check the ignore flag (besides, - * the flags variable is not set for that particular type) - */ - if ((parameters[i].type != FORMAT_PARAMETER) && - (parameters[i].flags & FLAGS_IGNORE)) - continue; /* for all arguments */ - - /* - * The stack arguments are read according to ANSI C89 - * default argument promotions: - * - * char = int - * short = int - * unsigned char = unsigned int - * unsigned short = unsigned int - * float = double - * - * In addition to the ANSI C89 these types are read (the - * default argument promotions of C99 has not been - * considered yet) - * - * long long - * long double - * size_t - * ptrdiff_t - * intmax_t - */ - switch (parameters[i].type) - { - case FORMAT_GROUP: - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - parameters[i].data.wstring = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_wchar_t *) - : (trio_wchar_t *)(argarray[num]); - } - else -#endif - { - parameters[i].data.string = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), char *) - : (char *)(argarray[num]); - } - break; - -#if defined(FORMAT_USER_DEFINED) - case FORMAT_USER_DEFINED: -#endif - case FORMAT_POINTER: - case FORMAT_COUNT: - case FORMAT_UNKNOWN: - parameters[i].data.pointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t ) - : argarray[num]; - break; - - case FORMAT_CHAR: - case FORMAT_INT: - if (TYPE_SCAN == type) - { - if (argarray == NULL) - parameters[i].data.pointer = - (trio_pointer_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.pointer = - (trio_pointer_t)((char *)argarray[num]); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.pointer = - (trio_pointer_t)((short *)argarray[num]); - else - parameters[i].data.pointer = - (trio_pointer_t)((int *)argarray[num]); - } - } - else - { -#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE) - if (parameters[i].flags - & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE)) - { - if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER) - { - /* - * Variable sizes are mapped onto the fixed sizes, in - * accordance with integer promotion. - * - * Please note that this may not be portable, as we - * only guess the size, not the layout of the numbers. - * For example, if int is little-endian, and long is - * big-endian, then this will fail. - */ - varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned; - } - else - { - /* Used for the I modifiers */ - varsize = parameters[i].varsize; - } - parameters[i].flags &= ~FLAGS_ALL_VARSIZES; - - if (varsize <= (int)sizeof(int)) - ; - else if (varsize <= (int)sizeof(long)) - parameters[i].flags |= FLAGS_LONG; -#if defined(QUALIFIER_INTMAX_T) - else if (varsize <= (int)sizeof(trio_longlong_t)) - parameters[i].flags |= FLAGS_QUAD; - else - parameters[i].flags |= FLAGS_INTMAX_T; -#else - else - parameters[i].flags |= FLAGS_QUAD; -#endif - } -#endif /* defined(QUALIFIER_VARSIZE) */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (parameters[i].flags & FLAGS_SIZE_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), size_t) - : (trio_uintmax_t)(*((size_t *)argarray[num])); - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (parameters[i].flags & FLAGS_PTRDIFF_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), ptrdiff_t) - : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num])); - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (parameters[i].flags & FLAGS_INTMAX_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_intmax_t) - : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num])); - else -#endif - if (parameters[i].flags & FLAGS_QUAD) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_ulonglong_t) - : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num])); - else if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), long) - : (trio_uintmax_t)(*((long *)argarray[num])); - else - { - if (argarray == NULL) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num])); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num])); - else - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num])); - } - } - } - break; - - case FORMAT_PARAMETER: - /* - * The parameter for the user-defined specifier is a pointer, - * whereas the rest (width, precision, base) uses an integer. - */ - if (parameters[i].flags & FLAGS_USER_DEFINED) - parameters[i].data.pointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t ) - : argarray[num]; - else - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int) - : (trio_uintmax_t)(*((int *)argarray[num])); - break; - - case FORMAT_DOUBLE: - if (TYPE_SCAN == type) - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoublePointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t *) - : (trio_long_double_t *)argarray[num]; - else - { - if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.doublePointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), double *) - : (double *)argarray[num]; - else - parameters[i].data.doublePointer = (argarray == NULL) - ? (double *)va_arg(TRIO_VA_LIST_DEREF(arglist), float *) - : (double *)((float *)argarray[num]); - } - } - else - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoubleNumber = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t) - : (trio_long_double_t)(*((trio_long_double_t *)argarray[num])); - else - { - if (argarray == NULL) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)va_arg(TRIO_VA_LIST_DEREF(arglist), double); - else - { - if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((float *)argarray[num])); - else - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((double *)argarray[num])); - } - } - } - break; - -#if defined(FORMAT_ERRNO) - case FORMAT_ERRNO: - parameters[i].data.errorNumber = save_errno; - break; -#endif - - default: - break; - } - } /* for all specifiers */ - return num; -} - - -/************************************************************************* - * - * FORMATTING - * - ************************************************************************/ - - -/************************************************************************* - * TrioWriteNumber - * - * Description: - * Output a number. - * The complexity of this function is a result of the complexity - * of the dependencies of the flags. - */ -TRIO_PRIVATE void -TrioWriteNumber -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_uintmax_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - BOOLEAN_T isNegative; - BOOLEAN_T isNumberZero; - BOOLEAN_T isPrecisionZero; - BOOLEAN_T ignoreNumber; - char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; - char *bufferend; - char *pointer; - TRIO_CONST char *digits; - int i; - int length; - char *p; - int count; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - if (base == NO_BASE) - base = BASE_DECIMAL; - - isNumberZero = (number == 0); - isPrecisionZero = (precision == 0); - ignoreNumber = (isNumberZero - && isPrecisionZero - && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL))); - - if (flags & FLAGS_UNSIGNED) - { - isNegative = FALSE; - flags &= ~FLAGS_SHOWSIGN; - } - else - { - isNegative = ((trio_intmax_t)number < 0); - if (isNegative) - number = -((trio_intmax_t)number); - } - - if (flags & FLAGS_QUAD) - number &= (trio_ulonglong_t)-1; - else if (flags & FLAGS_LONG) - number &= (unsigned long)-1; - else - number &= (unsigned int)-1; - - /* Build number */ - pointer = bufferend = &buffer[sizeof(buffer) - 1]; - *pointer-- = NIL; - for (i = 1; i < (int)sizeof(buffer); i++) - { - *pointer-- = digits[number % base]; - number /= base; - if (number == 0) - break; - - if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1)) - { - /* - * We are building the number from the least significant - * to the most significant digit, so we have to copy the - * thousand separator backwards - */ - length = internalThousandSeparatorLength; - if (((int)(pointer - buffer) - length) > 0) - { - p = &internalThousandSeparator[length - 1]; - while (length-- > 0) - *pointer-- = *p--; - } - } - } - - if (! ignoreNumber) - { - /* Adjust width */ - width -= (bufferend - pointer) - 1; - } - - /* Adjust precision */ - if (NO_PRECISION != precision) - { - precision -= (bufferend - pointer) - 1; - if (precision < 0) - precision = 0; - flags |= FLAGS_NILPADDING; - } - - /* Calculate padding */ - count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION))) - ? precision - : 0; - - /* Adjust width further */ - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - width--; - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - case BASE_HEX: - width -= 2; - break; - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - width--; - break; - default: - break; - } - } - - /* Output prefixes spaces if needed */ - if (! ((flags & FLAGS_LEFTADJUST) || - ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION)))) - { - while (width-- > count) - self->OutStream(self, CHAR_ADJUST); - } - - /* width has been adjusted for signs and alternatives */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - - /* Prefix is not written when the value is zero */ - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b'); - break; - - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - self->OutStream(self, '0'); - break; - - case BASE_HEX: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - break; - - default: - break; - } /* switch base */ - } - - /* Output prefixed zero padding if needed */ - if (flags & FLAGS_NILPADDING) - { - if (precision == NO_PRECISION) - precision = width; - while (precision-- > 0) - { - self->OutStream(self, '0'); - width--; - } - } - - if (! ignoreNumber) - { - /* Output the number itself */ - while (*(++pointer)) - { - self->OutStream(self, *pointer); - } - } - - /* Output trailing spaces if needed */ - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } -} - -/************************************************************************* - * TrioWriteStringCharacter - * - * Description: - * Output a single character of a string - */ -TRIO_PRIVATE void -TrioWriteStringCharacter -TRIO_ARGS3((self, ch, flags), - trio_class_t *self, - int ch, - trio_flags_t flags) -{ - if (flags & FLAGS_ALTERNATIVE) - { - if (! isprint(ch)) - { - /* - * Non-printable characters are converted to C escapes or - * \number, if no C escape exists. - */ - self->OutStream(self, CHAR_BACKSLASH); - switch (ch) - { - case '\007': self->OutStream(self, 'a'); break; - case '\b': self->OutStream(self, 'b'); break; - case '\f': self->OutStream(self, 'f'); break; - case '\n': self->OutStream(self, 'n'); break; - case '\r': self->OutStream(self, 'r'); break; - case '\t': self->OutStream(self, 't'); break; - case '\v': self->OutStream(self, 'v'); break; - case '\\': self->OutStream(self, '\\'); break; - default: - self->OutStream(self, 'x'); - TrioWriteNumber(self, (trio_uintmax_t)ch, - FLAGS_UNSIGNED | FLAGS_NILPADDING, - 2, 2, BASE_HEX); - break; - } - } - else if (ch == CHAR_BACKSLASH) - { - self->OutStream(self, CHAR_BACKSLASH); - self->OutStream(self, CHAR_BACKSLASH); - } - else - { - self->OutStream(self, ch); - } - } - else - { - self->OutStream(self, ch); - } -} - -/************************************************************************* - * TrioWriteString - * - * Description: - * Output a string - */ -TRIO_PRIVATE void -TrioWriteString -TRIO_ARGS5((self, string, flags, width, precision), - trio_class_t *self, - TRIO_CONST char *string, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int ch; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - - if (string == NULL) - { - string = internalNullString; - length = sizeof(internalNullString) - 1; - /* Disable quoting for the null pointer */ - flags &= (~FLAGS_QUOTE); - width = 0; - } - else - { - length = trio_length(string); - } - if ((NO_PRECISION != precision) && - (precision < length)) - { - length = precision; - } - width -= length; - - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length-- > 0) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -} - -/************************************************************************* - * TrioWriteWideStringCharacter - * - * Description: - * Output a wide string as a multi-byte sequence - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE int -TrioWriteWideStringCharacter -TRIO_ARGS4((self, wch, flags, width), - trio_class_t *self, - trio_wchar_t wch, - trio_flags_t flags, - int width) -{ - int size; - int i; - int ch; - char *string; - char buffer[MB_LEN_MAX + 1]; - - if (width == NO_WIDTH) - width = sizeof(buffer); - - size = wctomb(buffer, wch); - if ((size <= 0) || (size > width) || (buffer[0] == NIL)) - return 0; - - string = buffer; - i = size; - while ((width >= i) && (width-- > 0) && (i-- > 0)) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - return size; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioWriteWideString - * - * Description: - * Output a wide character string as a multi-byte string - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE void -TrioWriteWideString -TRIO_ARGS5((self, wstring, flags, width, precision), - trio_class_t *self, - TRIO_CONST trio_wchar_t *wstring, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int size; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - if (wstring == NULL) - { - TrioWriteString(self, NULL, flags, width, precision); - return; - } - - if (NO_PRECISION == precision) - { - length = INT_MAX; - } - else - { - length = precision; - width -= length; - } - - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length > 0) - { - size = TrioWriteWideStringCharacter(self, *wstring++, flags, length); - if (size == 0) - break; /* while */ - length -= size; - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioWriteDouble - * - * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm - * - * "5.2.4.2.2 paragraph #4 - * - * The accuracy [...] is implementation defined, as is the accuracy - * of the conversion between floating-point internal representations - * and string representations performed by the library routine in - * " - */ -/* FIXME: handle all instances of constant long-double number (L) - * and *l() math functions. - */ -TRIO_PRIVATE void -TrioWriteDouble -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_long_double_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - trio_long_double_t integerNumber; - trio_long_double_t fractionNumber; - trio_long_double_t workNumber; - int integerDigits; - int fractionDigits; - int exponentDigits; - int baseDigits; - int integerThreshold; - int fractionThreshold; - int expectedWidth; - int exponent = 0; - unsigned int uExponent = 0; - int exponentBase; - trio_long_double_t dblBase; - trio_long_double_t dblIntegerBase; - trio_long_double_t dblFractionBase; - trio_long_double_t integerAdjust; - trio_long_double_t fractionAdjust; - BOOLEAN_T isNegative; - BOOLEAN_T isExponentNegative = FALSE; - BOOLEAN_T requireTwoDigitExponent; - BOOLEAN_T isHex; - TRIO_CONST char *digits; - char *groupingPointer; - int i; - int index; - BOOLEAN_T hasOnlyZeroes; - int zeroes = 0; - register int trailingZeroes; - BOOLEAN_T keepTrailingZeroes; - BOOLEAN_T keepDecimalPoint; - trio_long_double_t epsilon; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - /* Determine sign and look for special quantities */ - switch (trio_fpclassify_and_signbit(number, &isNegative)) - { - case TRIO_FP_NAN: - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? NAN_UPPER - : NAN_LOWER, - flags, width, precision); - return; - - case TRIO_FP_INFINITE: - if (isNegative) - { - /* Negative infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? "-" INFINITE_UPPER - : "-" INFINITE_LOWER, - flags, width, precision); - return; - } - else - { - /* Positive infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? INFINITE_UPPER - : INFINITE_LOWER, - flags, width, precision); - return; - } - - default: - /* Finitude */ - break; - } - - /* Normal numbers */ - if (flags & FLAGS_LONGDOUBLE) - { - baseDigits = (base == 10) - ? LDBL_DIG - : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = LDBL_EPSILON; - } - else if (flags & FLAGS_SHORT) - { - baseDigits = (base == BASE_DECIMAL) - ? FLT_DIG - : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base)); - epsilon = FLT_EPSILON; - } - else - { - baseDigits = (base == BASE_DECIMAL) - ? DBL_DIG - : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = DBL_EPSILON; - } - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - isHex = (base == BASE_HEX); - if (base == NO_BASE) - base = BASE_DECIMAL; - dblBase = (trio_long_double_t)base; - keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) || - ( (flags & FLAGS_FLOAT_G) && - !(flags & FLAGS_ALTERNATIVE) ) ); - - if (flags & FLAGS_ROUNDING) - precision = baseDigits; - - if (precision == NO_PRECISION) - { - if (isHex) - { - keepTrailingZeroes = FALSE; - precision = FLT_MANT_DIG; - } - else - { - precision = FLT_DIG; - } - } - - if (isNegative) - number = -number; - - if (isHex) - flags |= FLAGS_FLOAT_E; - - if (flags & FLAGS_FLOAT_G) - { - if (precision == 0) - precision = 1; - - if ((number < 1.0E-4) || (number > powl(base, - (trio_long_double_t)precision))) - { - /* Use scientific notation */ - flags |= FLAGS_FLOAT_E; - } - else if (number < 1.0) - { - /* - * Use normal notation. If the integer part of the number is - * zero, then adjust the precision to include leading fractional - * zeros. - */ - workNumber = TrioLogarithm(number, base); - workNumber = TRIO_FABS(workNumber); - if (workNumber - floorl(workNumber) < 0.001) - workNumber--; - zeroes = (int)floorl(workNumber); - } - } - - if (flags & FLAGS_FLOAT_E) - { - /* Scale the number */ - workNumber = TrioLogarithm(number, base); - if (trio_isinf(workNumber) == -1) - { - exponent = 0; - /* Undo setting */ - if (flags & FLAGS_FLOAT_G) - flags &= ~FLAGS_FLOAT_E; - } - else - { - exponent = (int)floorl(workNumber); - number /= powl(dblBase, (trio_long_double_t)exponent); - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ - /* No thousand separators */ - flags &= ~FLAGS_QUOTE; - } - } - - integerNumber = floorl(number); - fractionNumber = number - integerNumber; - - /* - * Truncated number. - * - * Precision is number of significant digits for FLOAT_G - * and number of fractional digits for others. - */ - integerDigits = (integerNumber > epsilon) - ? 1 + (int)TrioLogarithm(integerNumber, base) - : 1; - fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0)) - ? precision - integerDigits - : zeroes + precision; - - dblFractionBase = TrioPower(base, fractionDigits); - - workNumber = number + 0.5 / dblFractionBase; - if (floorl(number) != floorl(workNumber)) - { - if (flags & FLAGS_FLOAT_E) - { - /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */ - exponent++; - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ - workNumber = (number + 0.5 / dblFractionBase) / dblBase; - integerNumber = floorl(workNumber); - fractionNumber = workNumber - integerNumber; - } - else - { - /* Adjust if number was rounded up one digit (ie. 99 to 100) */ - integerNumber = floorl(number + 0.5); - fractionNumber = 0.0; - integerDigits = (integerNumber > epsilon) - ? 1 + (int)TrioLogarithm(integerNumber, base) - : 1; - } - } - - /* Estimate accuracy */ - integerAdjust = fractionAdjust = 0.5; - if (flags & FLAGS_ROUNDING) - { - if (integerDigits > baseDigits) - { - integerThreshold = baseDigits; - fractionDigits = 0; - dblFractionBase = 1.0; - fractionThreshold = 0; - precision = 0; /* Disable decimal-point */ - integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1); - fractionAdjust = 0.0; - } - else - { - integerThreshold = integerDigits; - fractionThreshold = fractionDigits - integerThreshold; - fractionAdjust = 1.0; - } - } - else - { - integerThreshold = INT_MAX; - fractionThreshold = INT_MAX; - } - - /* - * Calculate expected width. - * sign + integer part + thousands separators + decimal point - * + fraction + exponent - */ - fractionAdjust /= dblFractionBase; - hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon); - keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) || - !((precision == 0) || - (!keepTrailingZeroes && hasOnlyZeroes)) ); - if (flags & FLAGS_FLOAT_E) - { - exponentDigits = (uExponent == 0) - ? 1 - : (int)ceil(TrioLogarithm((double)(uExponent + 1), - (isHex) ? 10.0 : base)); - } - else - exponentDigits = 0; - requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1)); - - expectedWidth = integerDigits + fractionDigits - + (keepDecimalPoint - ? internalDecimalPointLength - : 0) - + ((flags & FLAGS_QUOTE) - ? TrioCalcThousandSeparatorLength(integerDigits) - : 0); - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - expectedWidth += sizeof("-") - 1; - if (exponentDigits > 0) - expectedWidth += exponentDigits + - ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1); - if (isHex) - expectedWidth += sizeof("0X") - 1; - - /* Output prefixing */ - if (flags & FLAGS_NILPADDING) - { - /* Leading zeros must be after sign */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, '0'); - } - } - } - else - { - /* Leading spaces must be before sign */ - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - } - - /* Output the integer part and thousand separators */ - dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1); - for (i = 0; i < integerDigits; i++) - { - workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase)); - if (i > integerThreshold) - { - /* Beyond accuracy */ - self->OutStream(self, digits[0]); - } - else - { - self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]); - } - dblIntegerBase *= dblBase; - - if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) - && TrioFollowedBySeparator(integerDigits - i)) - { - for (groupingPointer = internalThousandSeparator; - *groupingPointer != NIL; - groupingPointer++) - { - self->OutStream(self, *groupingPointer); - } - } - } - - /* Insert decimal point and build the fraction part */ - trailingZeroes = 0; - - if (keepDecimalPoint) - { - if (internalDecimalPoint) - { - self->OutStream(self, internalDecimalPoint); - } - else - { - for (i = 0; i < internalDecimalPointLength; i++) - { - self->OutStream(self, internalDecimalPointString[i]); - } - } - } - - for (i = 0; i < fractionDigits; i++) - { - if ((integerDigits > integerThreshold) || (i > fractionThreshold)) - { - /* Beyond accuracy */ - trailingZeroes++; - } - else - { - fractionNumber *= dblBase; - fractionAdjust *= dblBase; - workNumber = floorl(fractionNumber + fractionAdjust); - fractionNumber -= workNumber; - index = (int)fmodl(workNumber, dblBase); - if (index == 0) - { - trailingZeroes++; - } - else - { - while (trailingZeroes > 0) - { - /* Not trailing zeroes after all */ - self->OutStream(self, digits[0]); - trailingZeroes--; - } - self->OutStream(self, digits[index]); - } - } - } - - if (keepTrailingZeroes) - { - while (trailingZeroes > 0) - { - self->OutStream(self, digits[0]); - trailingZeroes--; - } - } - - /* Output exponent */ - if (exponentDigits > 0) - { - self->OutStream(self, - isHex - ? ((flags & FLAGS_UPPER) ? 'P' : 'p') - : ((flags & FLAGS_UPPER) ? 'E' : 'e')); - self->OutStream(self, (isExponentNegative) ? '-' : '+'); - - /* The exponent must contain at least two digits */ - if (requireTwoDigitExponent) - self->OutStream(self, '0'); - - if (isHex) - base = 10.0; - exponentBase = (int)TrioPower(base, exponentDigits - 1); - for (i = 0; i < exponentDigits; i++) - { - self->OutStream(self, digits[(uExponent / exponentBase) % base]); - exponentBase /= base; - } - } - /* Output trailing spaces */ - if (flags & FLAGS_LEFTADJUST) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } -} - -/************************************************************************* - * TrioFormatProcess - * - * Description: - * This is the main engine for formatting output - */ -TRIO_PRIVATE int -TrioFormatProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int i; - TRIO_CONST char *string; - trio_pointer_t pointer; - trio_flags_t flags; - int width; - int precision; - int base; - int index; - - index = 0; - i = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - charlen = mblen(&format[index], MB_LEN_MAX); - /* - * Only valid multibyte characters are handled here. Invalid - * multibyte characters (charlen == -1) are handled as normal - * characters. - */ - if (charlen != -1) - { - while (charlen-- > 0) - { - data->OutStream(data, format[index++]); - } - continue; /* while characters left in formatting string */ - } - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (CHAR_IDENTIFIER == format[index]) - { - if (CHAR_IDENTIFIER == format[index + 1]) - { - data->OutStream(data, CHAR_IDENTIFIER); - index += 2; - } - else - { - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - i++; - - flags = parameters[i].flags; - - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - if (width < 0) - { - /* - * A negative width is the same as the - flag and - * a positive width. - */ - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - width = -width; - } - } - - /* Find precision */ - if (flags & FLAGS_PRECISION) - { - precision = parameters[i].precision; - if (flags & FLAGS_PRECISION_PARAMETER) - { - /* Get precision from parameter list */ - precision = (int)parameters[precision].data.number.as_signed; - if (precision < 0) - { - /* - * A negative precision is the same as no - * precision - */ - precision = NO_PRECISION; - } - } - } - else - { - precision = NO_PRECISION; - } - - /* Find base */ - base = parameters[i].base; - if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = (int)parameters[base].data.number.as_signed; - } - - switch (parameters[i].type) - { - case FORMAT_CHAR: - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); - if (! (flags & FLAGS_LEFTADJUST)) - { - while (--width > 0) - data->OutStream(data, CHAR_ADJUST); - } -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideStringCharacter(data, - (trio_wchar_t)parameters[i].data.number.as_signed, - flags, - NO_WIDTH); - } - else -#endif - { - TrioWriteStringCharacter(data, - (int)parameters[i].data.number.as_signed, - flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while(--width > 0) - data->OutStream(data, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); - - break; /* FORMAT_CHAR */ - - case FORMAT_INT: - TrioWriteNumber(data, - parameters[i].data.number.as_unsigned, - flags, - width, - precision, - base); - - break; /* FORMAT_INT */ - - case FORMAT_DOUBLE: - TrioWriteDouble(data, - parameters[i].data.longdoubleNumber, - flags, - width, - precision, - base); - break; /* FORMAT_DOUBLE */ - - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideString(data, - parameters[i].data.wstring, - flags, - width, - precision); - } - else -#endif - { - TrioWriteString(data, - parameters[i].data.string, - flags, - width, - precision); - } - break; /* FORMAT_STRING */ - - case FORMAT_POINTER: - { - trio_reference_t reference; - - reference.data = data; - reference.parameter = ¶meters[i]; - trio_print_pointer(&reference, parameters[i].data.pointer); - } - break; /* FORMAT_POINTER */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - /* - * C99 paragraph 7.19.6.1.8 says "the number of - * characters written to the output stream so far by - * this call", which is data->committed - */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)data->committed; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)data->committed; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)data->committed; - } - else - { - *(int *)pointer = (int)data->committed; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - -#if defined(FORMAT_ERRNO) - case FORMAT_ERRNO: - string = trio_error(parameters[i].data.errorNumber); - if (string) - { - TrioWriteString(data, - string, - flags, - width, - precision); - } - else - { - data->OutStream(data, '#'); - TrioWriteNumber(data, - (trio_uintmax_t)parameters[i].data.errorNumber, - flags, - width, - precision, - BASE_DECIMAL); - } - break; /* FORMAT_ERRNO */ -#endif /* defined(FORMAT_ERRNO) */ - -#if defined(FORMAT_USER_DEFINED) - case FORMAT_USER_DEFINED: - { - trio_reference_t reference; - trio_userdef_t *def = NULL; - - if (parameters[i].user_name[0] == NIL) - { - /* Use handle */ - if ((i > 0) || - (parameters[i - 1].type == FORMAT_PARAMETER)) - def = (trio_userdef_t *)parameters[i - 1].data.pointer; - } - else - { - /* Look up namespace */ - def = TrioFindNamespace(parameters[i].user_name, NULL); - } - if (def) { - reference.data = data; - reference.parameter = ¶meters[i]; - def->callback(&reference); - } - } - break; -#endif /* defined(FORMAT_USER_DEFINED) */ - - default: - break; - } /* switch parameter type */ - - /* Prepare for next */ - index = parameters[i].indexAfterSpecifier; - i++; - } - } - else /* not identifier */ - { - data->OutStream(data, format[index++]); - } - } - return data->processed; -} - -/************************************************************************* - * TrioFormatRef - */ -TRIO_PRIVATE int -TrioFormatRef -TRIO_ARGS4((reference, format, arglist, argarray), - trio_reference_t *reference, - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(reference->data, format, parameters); - if (reference->data->error != 0) - { - status = reference->data->error; - } - return status; -} - -/************************************************************************* - * TrioFormat - */ -TRIO_PRIVATE int -TrioFormat -TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray), - trio_pointer_t destination, - size_t destinationSize, - void (*OutStream) TRIO_PROTO((trio_class_t *, int)), - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_class_t data; - trio_parameter_t parameters[MAX_PARAMETERS]; - - assert(VALID(OutStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.OutStream = OutStream; - data.location = destination; - data.max = destinationSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioOutStreamFile - */ -TRIO_PRIVATE void -TrioOutStreamFile -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - FILE *file; - - assert(VALID(self)); - assert(VALID(self->location)); - - file = (FILE *)self->location; - self->processed++; - if (fputc(output, file) == EOF) - { - self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->committed++; - } -} - -/************************************************************************* - * TrioOutStreamFileDescriptor - */ -TRIO_PRIVATE void -TrioOutStreamFileDescriptor -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int fd; - char ch; - - assert(VALID(self)); - - fd = *((int *)self->location); - ch = (char)output; - self->processed++; - if (write(fd, &ch, sizeof(char)) == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - } - else - { - self->committed++; - } -} - -/************************************************************************* - * TrioOutStreamCustom - */ -TRIO_PRIVATE void -TrioOutStreamCustom -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int status; - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - data = (trio_custom_t *)self->location; - if (data->stream.out) - { - status = (data->stream.out)(data->closure, output); - if (status >= 0) - { - self->committed++; - } - else - { - if (self->error == 0) - { - self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status); - } - } - } - self->processed++; -} - -/************************************************************************* - * TrioOutStreamString - */ -TRIO_PRIVATE void -TrioOutStreamString -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - **buffer = (char)output; - (*buffer)++; - self->processed++; - self->committed++; -} - -/************************************************************************* - * TrioOutStreamStringMax - */ -TRIO_PRIVATE void -TrioOutStreamStringMax -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - - if (self->processed < self->max) - { - **buffer = (char)output; - (*buffer)++; - self->committed++; - } - self->processed++; -} - -/************************************************************************* - * TrioOutStreamStringDynamic - */ -TRIO_PRIVATE void -TrioOutStreamStringDynamic -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - assert(VALID(self)); - assert(VALID(self->location)); - - if (self->error == 0) - { - trio_xstring_append_char((trio_string_t *)self->location, - (char)output); - self->committed++; - } - /* The processed variable must always be increased */ - self->processed++; -} - -/************************************************************************* - * - * Formatted printing functions - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_printf.h" -#endif -/** @addtogroup Printf - @{ -*/ - -/************************************************************************* - * printf - */ - -/** - Print to standard output stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_printf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_printfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t * args) -{ - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args); -} - -/************************************************************************* - * fprintf - */ - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_fprintf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vfprintf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_fprintfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t * args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args); -} - -/************************************************************************* - * dprintf - */ - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_dprintf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vdprintf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_dprintfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args); -} - -/************************************************************************* - * cprintf - */ -TRIO_PUBLIC int -trio_cprintf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.out = stream; - data.closure = closure; - status = TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vcprintf -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_cprintfv -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - void **args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args); -} - -/************************************************************************* - * sprintf - */ - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintf -TRIO_VARGS3((buffer, format, va_alist), - char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; /* Terminate with NIL character */ - TRIO_VA_END(args); - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsprintf -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintfv -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args); - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintf - */ - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintf -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - if (max > 0) - *buffer = NIL; - TRIO_VA_END(args); - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsnprintf -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - if (max > 0) - *buffer = NIL; - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintfv -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, NULL, args); - if (max > 0) - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintfcat - * Appends the new string to the buffer string overwriting the '\0' - * character at the end of buffer. - */ -TRIO_PUBLIC int -trio_snprintfcat -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - size_t buf_len; - - TRIO_VA_START(args, format); - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - *buffer = NIL; - return status; -} - -TRIO_PUBLIC int -trio_vsnprintfcat -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - size_t buf_len; - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; - return status; -} - -/************************************************************************* - * trio_aprintf - */ - -/* Deprecated */ -TRIO_PUBLIC char * -trio_aprintf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - TRIO_VA_START(args, format); - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} - -/* Deprecated */ -TRIO_PUBLIC char * -trio_vaprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} - -TRIO_PUBLIC int -trio_asprintf -TRIO_VARGS3((result, format, va_alist), - char **result, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - TRIO_VA_START(args, format); - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} - -TRIO_PUBLIC int -trio_vasprintf -TRIO_ARGS3((result, format, args), - char **result, - TRIO_CONST char *format, - va_list args) -{ - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} - -/** @} End of Printf documentation module */ - -/************************************************************************* - * - * CALLBACK - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_register.h" -#endif -/** - @addtogroup UserDefined - @{ -*/ - -#if TRIO_EXTENSION - -/************************************************************************* - * trio_register - */ - -/** - Register new user-defined specifier. - - @param callback - @param name - @return Handle. - */ -TRIO_PUBLIC trio_pointer_t -trio_register -TRIO_ARGS2((callback, name), - trio_callback_t callback, - TRIO_CONST char *name) -{ - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - if (callback == NULL) - return NULL; - - if (name) - { - /* Handle built-in namespaces */ - if (name[0] == ':') - { - if (trio_equal(name, ":enter")) - { - internalEnterCriticalRegion = callback; - } - else if (trio_equal(name, ":leave")) - { - internalLeaveCriticalRegion = callback; - } - return NULL; - } - - /* Bail out if namespace is too long */ - if (trio_length(name) >= MAX_USER_NAME) - return NULL; - - /* Bail out if namespace already is registered */ - def = TrioFindNamespace(name, &prev); - if (def) - return NULL; - } - - def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t)); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (name) - { - /* Link into internal list */ - if (prev == NULL) - internalUserDef = def; - else - prev->next = def; - } - /* Initialize */ - def->callback = callback; - def->name = (name == NULL) - ? NULL - : trio_duplicate(name); - def->next = NULL; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - return (trio_pointer_t)def; -} - -/** - Unregister an existing user-defined specifier. - - @param handle - */ -void -trio_unregister -TRIO_ARGS1((handle), - trio_pointer_t handle) -{ - trio_userdef_t *self = (trio_userdef_t *)handle; - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - assert(VALID(self)); - - if (self->name) - { - def = TrioFindNamespace(self->name, &prev); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (prev == NULL) - internalUserDef = NULL; - else - prev->next = def->next; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - trio_destroy(self->name); - } - TRIO_FREE(self); -} - -/************************************************************************* - * trio_get_format [public] - */ -TRIO_CONST char * -trio_get_format -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if defined(FORMAT_USER_DEFINED) - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return (((trio_reference_t *)ref)->parameter->user_data); -} - -/************************************************************************* - * trio_get_argument [public] - */ -trio_pointer_t -trio_get_argument -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if defined(FORMAT_USER_DEFINED) - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return ((trio_reference_t *)ref)->parameter->data.pointer; -} - -/************************************************************************* - * trio_get_width / trio_set_width [public] - */ -int -trio_get_width -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return ((trio_reference_t *)ref)->parameter->width; -} - -void -trio_set_width -TRIO_ARGS2((ref, width), - trio_pointer_t ref, - int width) -{ - ((trio_reference_t *)ref)->parameter->width = width; -} - -/************************************************************************* - * trio_get_precision / trio_set_precision [public] - */ -int -trio_get_precision -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->precision); -} - -void -trio_set_precision -TRIO_ARGS2((ref, precision), - trio_pointer_t ref, - int precision) -{ - ((trio_reference_t *)ref)->parameter->precision = precision; -} - -/************************************************************************* - * trio_get_base / trio_set_base [public] - */ -int -trio_get_base -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->base); -} - -void -trio_set_base -TRIO_ARGS2((ref, base), - trio_pointer_t ref, - int base) -{ - ((trio_reference_t *)ref)->parameter->base = base; -} - -/************************************************************************* - * trio_get_long / trio_set_long [public] - */ -int -trio_get_long -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG) - ? TRUE - : FALSE; -} - -void -trio_set_long -TRIO_ARGS2((ref, is_long), - trio_pointer_t ref, - int is_long) -{ - if (is_long) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG; -} - -/************************************************************************* - * trio_get_longlong / trio_set_longlong [public] - */ -int -trio_get_longlong -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD) - ? TRUE - : FALSE; -} - -void -trio_set_longlong -TRIO_ARGS2((ref, is_longlong), - trio_pointer_t ref, - int is_longlong) -{ - if (is_longlong) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD; -} - -/************************************************************************* - * trio_get_longdouble / trio_set_longdouble [public] - */ -int -trio_get_longdouble -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE) - ? TRUE - : FALSE; -} - -void -trio_set_longdouble -TRIO_ARGS2((ref, is_longdouble), - trio_pointer_t ref, - int is_longdouble) -{ - if (is_longdouble) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE; -} - -/************************************************************************* - * trio_get_short / trio_set_short [public] - */ -int -trio_get_short -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT) - ? TRUE - : FALSE; -} - -void -trio_set_short -TRIO_ARGS2((ref, is_short), - trio_pointer_t ref, - int is_short) -{ - if (is_short) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT; -} - -/************************************************************************* - * trio_get_shortshort / trio_set_shortshort [public] - */ -int -trio_get_shortshort -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT) - ? TRUE - : FALSE; -} - -void -trio_set_shortshort -TRIO_ARGS2((ref, is_shortshort), - trio_pointer_t ref, - int is_shortshort) -{ - if (is_shortshort) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT; -} - -/************************************************************************* - * trio_get_alternative / trio_set_alternative [public] - */ -int -trio_get_alternative -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE) - ? TRUE - : FALSE; -} - -void -trio_set_alternative -TRIO_ARGS2((ref, is_alternative), - trio_pointer_t ref, - int is_alternative) -{ - if (is_alternative) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE; -} - -/************************************************************************* - * trio_get_alignment / trio_set_alignment [public] - */ -int -trio_get_alignment -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST) - ? TRUE - : FALSE; -} - -void -trio_set_alignment -TRIO_ARGS2((ref, is_leftaligned), - trio_pointer_t ref, - int is_leftaligned) -{ - if (is_leftaligned) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST; -} - -/************************************************************************* - * trio_get_spacing /trio_set_spacing [public] - */ -int -trio_get_spacing -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE) - ? TRUE - : FALSE; -} - -void -trio_set_spacing -TRIO_ARGS2((ref, is_space), - trio_pointer_t ref, - int is_space) -{ - if (is_space) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE; -} - -/************************************************************************* - * trio_get_sign / trio_set_sign [public] - */ -int -trio_get_sign -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN) - ? TRUE - : FALSE; -} - -void -trio_set_sign -TRIO_ARGS2((ref, is_sign), - trio_pointer_t ref, - int is_sign) -{ - if (is_sign) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN; -} - -/************************************************************************* - * trio_get_padding / trio_set_padding [public] - */ -int -trio_get_padding -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING) - ? TRUE - : FALSE; -} - -void -trio_set_padding -TRIO_ARGS2((ref, is_padding), - trio_pointer_t ref, - int is_padding) -{ - if (is_padding) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING; -} - -/************************************************************************* - * trio_get_quote / trio_set_quote [public] - */ -int -trio_get_quote -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE) - ? TRUE - : FALSE; -} - -void -trio_set_quote -TRIO_ARGS2((ref, is_quote), - trio_pointer_t ref, - int is_quote) -{ - if (is_quote) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE; -} - -/************************************************************************* - * trio_get_upper / trio_set_upper [public] - */ -int -trio_get_upper -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER) - ? TRUE - : FALSE; -} - -void -trio_set_upper -TRIO_ARGS2((ref, is_upper), - trio_pointer_t ref, - int is_upper) -{ - if (is_upper) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER; -} - -/************************************************************************* - * trio_get_largest / trio_set_largest [public] - */ -#if TRIO_C99 -int -trio_get_largest -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T) - ? TRUE - : FALSE; -} - -void -trio_set_largest -TRIO_ARGS2((ref, is_largest), - trio_pointer_t ref, - int is_largest) -{ - if (is_largest) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T; -} -#endif - -/************************************************************************* - * trio_get_ptrdiff / trio_set_ptrdiff [public] - */ -int -trio_get_ptrdiff -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T) - ? TRUE - : FALSE; -} - -void -trio_set_ptrdiff -TRIO_ARGS2((ref, is_ptrdiff), - trio_pointer_t ref, - int is_ptrdiff) -{ - if (is_ptrdiff) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T; -} - -/************************************************************************* - * trio_get_size / trio_set_size [public] - */ -#if TRIO_C99 -int -trio_get_size -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T) - ? TRUE - : FALSE; -} - -void -trio_set_size -TRIO_ARGS2((ref, is_size), - trio_pointer_t ref, - int is_size) -{ - if (is_size) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T; -} -#endif - -/************************************************************************* - * trio_print_int [public] - */ -void -trio_print_int -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_uint [public] - */ -void -trio_print_uint -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - unsigned int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags | FLAGS_UNSIGNED, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_double [public] - */ -void -trio_print_double -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - double number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteDouble(self->data, - number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_string [public] - */ -void -trio_print_string -TRIO_ARGS2((ref, string), - trio_pointer_t ref, - char *string) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteString(self->data, - string, - self->parameter->flags, - self->parameter->width, - self->parameter->precision); -} - -/************************************************************************* - * trio_print_ref [public] - */ -int -trio_print_ref -TRIO_VARGS3((ref, format, va_alist), - trio_pointer_t ref, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list arglist; - - assert(VALID(format)); - - TRIO_VA_START(arglist, format); - status = TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL); - TRIO_VA_END(arglist); - return status; -} - -/************************************************************************* - * trio_vprint_ref [public] - */ -int -trio_vprint_ref -TRIO_ARGS3((ref, format, arglist), - trio_pointer_t ref, - TRIO_CONST char *format, - va_list arglist) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL); -} - -/************************************************************************* - * trio_printv_ref [public] - */ -int -trio_printv_ref -TRIO_ARGS3((ref, format, argarray), - trio_pointer_t ref, - TRIO_CONST char *format, - trio_pointer_t *argarray) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray); -} - -#endif /* TRIO_EXTENSION */ - -/************************************************************************* - * trio_print_pointer [public] - */ -void -trio_print_pointer -TRIO_ARGS2((ref, pointer), - trio_pointer_t ref, - trio_pointer_t pointer) -{ - trio_reference_t *self = (trio_reference_t *)ref; - trio_flags_t flags; - trio_uintmax_t number; - - if (NULL == pointer) - { - TRIO_CONST char *string = internalNullString; - while (*string) - self->data->OutStream(self->data, *string++); - } - else - { - /* - * The subtraction of the null pointer is a workaround - * to avoid a compiler warning. The performance overhead - * is negligible (and likely to be removed by an - * optimizing compiler). The (char *) casting is done - * to please ANSI C++. - */ - number = (trio_uintmax_t)((char *)pointer - (char *)0); - /* Shrink to size of pointer */ - number &= (trio_uintmax_t)-1; - flags = self->parameter->flags; - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | - FLAGS_NILPADDING); - TrioWriteNumber(self->data, - number, - flags, - POINTER_WIDTH, - NO_PRECISION, - BASE_HEX); - } -} - -/** @} End of UserDefined documentation module */ - -/************************************************************************* - * - * LOCALES - * - ************************************************************************/ - -/************************************************************************* - * trio_locale_set_decimal_point - * - * Decimal point can only be one character. The input argument is a - * string to enable multibyte characters. At most MB_LEN_MAX characters - * will be used. - */ -TRIO_PUBLIC void -trio_locale_set_decimal_point -TRIO_ARGS1((decimalPoint), - char *decimalPoint) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - internalDecimalPointLength = trio_length(decimalPoint); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = *decimalPoint; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - decimalPoint); - } -} - -/************************************************************************* - * trio_locale_set_thousand_separator - * - * See trio_locale_set_decimal_point - */ -TRIO_PUBLIC void -trio_locale_set_thousand_separator -TRIO_ARGS1((thousandSeparator), - char *thousandSeparator) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - thousandSeparator); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); -} - -/************************************************************************* - * trio_locale_set_grouping - * - * Array of bytes. Reversed order. - * - * CHAR_MAX : No further grouping - * 0 : Repeat last group for the remaining digits (not necessary - * as C strings are zero-terminated) - * n : Set current group to n - * - * Same order as the grouping attribute in LC_NUMERIC. - */ -TRIO_PUBLIC void -trio_locale_set_grouping -TRIO_ARGS1((grouping), - char *grouping) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - grouping); -} - - -/************************************************************************* - * - * SCANNING - * - ************************************************************************/ - -/************************************************************************* - * TrioSkipWhitespaces - */ -TRIO_PRIVATE int -TrioSkipWhitespaces -TRIO_ARGS1((self), - trio_class_t *self) -{ - int ch; - - ch = self->current; - while (isspace(ch)) - { - self->InStream(self, &ch); - } - return ch; -} - -/************************************************************************* - * TrioGetCollation - */ -#if TRIO_EXTENSION -TRIO_PRIVATE void -TrioGetCollation(TRIO_NOARGS) -{ - int i; - int j; - int k; - char first[2]; - char second[2]; - - /* This is computationally expensive */ - first[1] = NIL; - second[1] = NIL; - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - { - k = 0; - first[0] = (char)i; - for (j = 0; j < MAX_CHARACTER_CLASS; j++) - { - second[0] = (char)j; - if (trio_equal_locale(first, second)) - internalCollationArray[i][k++] = (char)j; - } - internalCollationArray[i][k] = NIL; - } -} -#endif - -/************************************************************************* - * TrioGetCharacterClass - * - * FIXME: - * multibyte - */ -TRIO_PRIVATE int -TrioGetCharacterClass -TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass), - TRIO_CONST char *format, - int *indexPointer, - trio_flags_t *flagsPointer, - int *characterclass) -{ - int index = *indexPointer; - int i; - char ch; - char range_begin; - char range_end; - - *flagsPointer &= ~FLAGS_EXCLUDE; - - if (format[index] == QUALIFIER_CIRCUMFLEX) - { - *flagsPointer |= FLAGS_EXCLUDE; - index++; - } - /* - * If the ungroup character is at the beginning of the scanlist, - * it will be part of the class, and a second ungroup character - * must follow to end the group. - */ - if (format[index] == SPECIFIER_UNGROUP) - { - characterclass[(int)SPECIFIER_UNGROUP]++; - index++; - } - /* - * Minus is used to specify ranges. To include minus in the class, - * it must be at the beginning of the list - */ - if (format[index] == QUALIFIER_MINUS) - { - characterclass[(int)QUALIFIER_MINUS]++; - index++; - } - /* Collect characters */ - for (ch = format[index]; - (ch != SPECIFIER_UNGROUP) && (ch != NIL); - ch = format[++index]) - { - switch (ch) - { - case QUALIFIER_MINUS: /* Scanlist ranges */ - - /* - * Both C99 and UNIX98 describes ranges as implementation- - * defined. - * - * We support the following behaviour (although this may - * change as we become wiser) - * - only increasing ranges, ie. [a-b] but not [b-a] - * - transitive ranges, ie. [a-b-c] == [a-c] - * - trailing minus, ie. [a-] is interpreted as an 'a' - * and a '-' - * - duplicates (although we can easily convert these - * into errors) - */ - range_begin = format[index - 1]; - range_end = format[++index]; - if (range_end == SPECIFIER_UNGROUP) - { - /* Trailing minus is included */ - characterclass[(int)ch]++; - ch = range_end; - break; /* for */ - } - if (range_end == NIL) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - if (range_begin > range_end) - return TRIO_ERROR_RETURN(TRIO_ERANGE, index); - - for (i = (int)range_begin; i <= (int)range_end; i++) - characterclass[i]++; - - ch = range_end; - break; - -#if TRIO_EXTENSION - - case SPECIFIER_GROUP: - - switch (format[index + 1]) - { - case QUALIFIER_DOT: /* Collating symbol */ - /* - * FIXME: This will be easier to implement when multibyte - * characters have been implemented. Until now, we ignore - * this feature. - */ - for (i = index + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_DOT) - break; /* for */ - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - index = i; - break; - - case QUALIFIER_EQUAL: /* Equivalence class expressions */ - { - unsigned int j; - unsigned int k; - - if (internalCollationUnconverted) - { - /* Lazy evaluation of collation array */ - TrioGetCollation(); - internalCollationUnconverted = FALSE; - } - for (i = index + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_EQUAL) - break; /* for */ - else - { - /* Mark any equivalent character */ - k = (unsigned int)format[i]; - for (j = 0; internalCollationArray[k][j] != NIL; j++) - characterclass[(int)internalCollationArray[k][j]]++; - } - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - index = i; - } - break; - - case QUALIFIER_COLON: /* Character class expressions */ - - if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalnum(i)) - characterclass[i]++; - index += sizeof(CLASS_ALNUM) - 1; - } - else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalpha(i)) - characterclass[i]++; - index += sizeof(CLASS_ALPHA) - 1; - } - else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (iscntrl(i)) - characterclass[i]++; - index += sizeof(CLASS_CNTRL) - 1; - } - else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isdigit(i)) - characterclass[i]++; - index += sizeof(CLASS_DIGIT) - 1; - } - else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isgraph(i)) - characterclass[i]++; - index += sizeof(CLASS_GRAPH) - 1; - } - else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (islower(i)) - characterclass[i]++; - index += sizeof(CLASS_LOWER) - 1; - } - else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isprint(i)) - characterclass[i]++; - index += sizeof(CLASS_PRINT) - 1; - } - else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (ispunct(i)) - characterclass[i]++; - index += sizeof(CLASS_PUNCT) - 1; - } - else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isspace(i)) - characterclass[i]++; - index += sizeof(CLASS_SPACE) - 1; - } - else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isupper(i)) - characterclass[i]++; - index += sizeof(CLASS_UPPER) - 1; - } - else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isxdigit(i)) - characterclass[i]++; - index += sizeof(CLASS_XDIGIT) - 1; - } - else - { - characterclass[(int)ch]++; - } - break; - - default: - characterclass[(int)ch]++; - break; - } - break; - -#endif /* TRIO_EXTENSION */ - - default: - characterclass[(int)ch]++; - break; - } - } - return 0; -} - -/************************************************************************* - * TrioReadNumber - * - * We implement our own number conversion in preference of strtol and - * strtoul, because we must handle 'long long' and thousand separators. - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadNumber -TRIO_ARGS5((self, target, flags, width, base), - trio_class_t *self, - trio_uintmax_t *target, - trio_flags_t flags, - int width, - int base) -{ - trio_uintmax_t number = 0; - int digit; - int count; - BOOLEAN_T isNegative = FALSE; - BOOLEAN_T gotNumber = FALSE; - int j; - - assert(VALID(self)); - assert(VALID(self->InStream)); - assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE)); - - if (internalDigitsUnconverted) - { - /* Lazy evaluation of digits array */ - memset(internalDigitArray, -1, sizeof(internalDigitArray)); - for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++) - { - internalDigitArray[(int)internalDigitsLower[j]] = j; - internalDigitArray[(int)internalDigitsUpper[j]] = j; - } - internalDigitsUnconverted = FALSE; - } - - TrioSkipWhitespaces(self); - - if (!(flags & FLAGS_UNSIGNED)) - { - /* Leading sign */ - if (self->current == '+') - { - self->InStream(self, NULL); - } - else if (self->current == '-') - { - self->InStream(self, NULL); - isNegative = TRUE; - } - } - - count = self->processed; - - if (flags & FLAGS_ALTERNATIVE) - { - switch (base) - { - case NO_BASE: - case BASE_OCTAL: - case BASE_HEX: - case BASE_BINARY: - if (self->current == '0') - { - self->InStream(self, NULL); - if (self->current) - { - if ((base == BASE_HEX) && - (trio_to_upper(self->current) == 'X')) - { - self->InStream(self, NULL); - } - else if ((base == BASE_BINARY) && - (trio_to_upper(self->current) == 'B')) - { - self->InStream(self, NULL); - } - } - } - else - return FALSE; - break; - default: - break; - } - } - - while (((width == NO_WIDTH) || (self->processed - count < width)) && - (! ((self->current == EOF) || isspace(self->current)))) - { - if (isascii(self->current)) - { - digit = internalDigitArray[self->current]; - /* Abort if digit is not allowed in the specified base */ - if ((digit == -1) || (digit >= base)) - break; - } - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, NULL); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } - else - break; - - number *= base; - number += digit; - gotNumber = TRUE; /* we need at least one digit */ - - self->InStream(self, NULL); - } - - /* Was anything read at all? */ - if (!gotNumber) - return FALSE; - - if (target) - *target = (isNegative) ? -((trio_intmax_t)number) : number; - return TRUE; -} - -/************************************************************************* - * TrioReadChar - */ -TRIO_PRIVATE int -TrioReadChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - char ch; - trio_uintmax_t number; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - ch = (char)self->current; - self->InStream(self, NULL); - if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH)) - { - switch (self->current) - { - case '\\': ch = '\\'; break; - case 'a': ch = '\007'; break; - case 'b': ch = '\b'; break; - case 'f': ch = '\f'; break; - case 'n': ch = '\n'; break; - case 'r': ch = '\r'; break; - case 't': ch = '\t'; break; - case 'v': ch = '\v'; break; - default: - if (isdigit(self->current)) - { - /* Read octal number */ - if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL)) - return 0; - ch = (char)number; - } - else if (trio_to_upper(self->current) == 'X') - { - /* Read hexadecimal number */ - self->InStream(self, NULL); - if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX)) - return 0; - ch = (char)number; - } - else - { - ch = (char)self->current; - } - break; - } - } - - if (target) - target[i] = ch; - } - return i + 1; -} - -/************************************************************************* - * TrioReadString - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - i++) - { - if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0) - break; /* for */ - } - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadWideChar - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE int -TrioReadWideChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int j; - int size; - int amount = 0; - trio_wchar_t wch; - char buffer[MB_LEN_MAX + 1]; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - if (isascii(self->current)) - { - if (TrioReadChar(self, buffer, flags, 1) == 0) - return 0; - buffer[1] = NIL; - } - else - { - /* - * Collect a multibyte character, by enlarging buffer until - * it contains a fully legal multibyte character, or the - * buffer is full. - */ - j = 0; - do - { - buffer[j++] = (char)self->current; - buffer[j] = NIL; - self->InStream(self, NULL); - } - while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j)); - } - if (target) - { - size = mbtowc(&wch, buffer, sizeof(buffer)); - if (size > 0) - target[i] = wch; - } - amount += size; - self->InStream(self, NULL); - } - return amount; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioReadWideString - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE BOOLEAN_T -TrioReadWideString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int size; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - ) - { - size = TrioReadWideChar(self, &target[i], flags, 1); - if (size == 0) - break; /* for */ - - i += size; - } - if (target) - target[i] = WCONST('\0'); - return TRUE; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioReadGroup - * - * FIXME: characterclass does not work with multibyte characters - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadGroup -TRIO_ARGS5((self, target, characterclass, flags, width), - trio_class_t *self, - char *target, - int *characterclass, - trio_flags_t flags, - int width) -{ - int ch; - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - ch = self->current; - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((ch == EOF) || - (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0)))); - i++) - { - if (target) - target[i] = (char)ch; - self->InStream(self, &ch); - } - - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadDouble - * - * FIXME: - * add long double - * handle base - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadDouble -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_pointer_t target, - trio_flags_t flags, - int width) -{ - int ch; - char doubleString[512]; - int index = 0; - int start; - int j; - BOOLEAN_T isHex = FALSE; - - doubleString[0] = 0; - - if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1)) - width = sizeof(doubleString) - 1; - - TrioSkipWhitespaces(self); - - /* - * Read entire double number from stream. trio_to_double requires - * a string as input, but InStream can be anything, so we have to - * collect all characters. - */ - ch = self->current; - if ((ch == '+') || (ch == '-')) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - width--; - } - - start = index; - switch (ch) - { - case 'n': - case 'N': - /* Not-a-number */ - if (index != 0) - break; - /* FALLTHROUGH */ - case 'i': - case 'I': - /* Infinity */ - while (isalpha(ch) && (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - doubleString[index] = NIL; - - /* Case insensitive string comparison */ - if (trio_equal(&doubleString[start], INFINITE_UPPER) || - trio_equal(&doubleString[start], LONG_INFINITE_UPPER)) - { - if (flags & FLAGS_LONGDOUBLE) - { - if ((start == 1) && (doubleString[0] == '-')) - { - *((trio_long_double_t *)target) = trio_ninf(); - } - else - { - *((trio_long_double_t *)target) = trio_pinf(); - } - } - else - { - if ((start == 1) && (doubleString[0] == '-')) - { - *((double *)target) = trio_ninf(); - } - else - { - *((double *)target) = trio_pinf(); - } - } - return TRUE; - } - if (trio_equal(doubleString, NAN_UPPER)) - { - /* NaN must not have a preceding + nor - */ - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_nan(); - } - else - { - *((double *)target) = trio_nan(); - } - return TRUE; - } - return FALSE; - - case '0': - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - if (trio_to_upper(ch) == 'X') - { - isHex = TRUE; - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - break; - - default: - break; - } - - while ((ch != EOF) && (index - start < width)) - { - /* Integer part */ - if (isHex ? isxdigit(ch) : isdigit(ch)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, &ch); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } - else - break; /* while */ - } - if (ch == '.') - { - /* Decimal part */ - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - while ((isHex ? isxdigit(ch) : isdigit(ch)) && - (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) - { - /* Exponent */ - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - if ((ch == '+') || (ch == '-')) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - while (isdigit(ch) && (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - } - } - - if ((index == start) || (*doubleString == NIL)) - return FALSE; - - doubleString[index] = 0; - - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL); - } - else - { - *((double *)target) = trio_to_double(doubleString, NULL); - } - return TRUE; -} - -/************************************************************************* - * TrioReadPointer - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadPointer -TRIO_ARGS3((self, target, flags), - trio_class_t *self, - trio_pointer_t *target, - trio_flags_t flags) -{ - trio_uintmax_t number; - char buffer[sizeof(internalNullString)]; - - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); - - if (TrioReadNumber(self, - &number, - flags, - POINTER_WIDTH, - BASE_HEX)) - { - /* - * The strange assignment of number is a workaround for a compiler - * warning - */ - if (target) - *target = (char *)0 + number; - return TRUE; - } - else if (TrioReadString(self, - (flags & FLAGS_IGNORE) - ? NULL - : buffer, - 0, - sizeof(internalNullString) - 1)) - { - if (trio_equal_case(buffer, internalNullString)) - { - if (target) - *target = NULL; - return TRUE; - } - } - return FALSE; -} - -/************************************************************************* - * TrioScanProcess - */ -TRIO_PRIVATE int -TrioScanProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; - int cnt; -#endif - int assignment; - int ch; - int index; /* Index of format string */ - int i; /* Index of current parameter */ - trio_flags_t flags; - int width; - int base; - trio_pointer_t pointer; - - assignment = 0; - i = 0; - index = 0; - data->InStream(data, &ch); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - charlen = mblen(&format[index], MB_LEN_MAX); - if (charlen != -1) - { - /* Compare multibyte characters in format string */ - for (cnt = 0; cnt < charlen - 1; cnt++) - { - if (ch != format[index + cnt]) - { - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - data->InStream(data, &ch); - } - continue; /* while characters left in formatting string */ - } - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - - if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT)) - { - return (assignment > 0) ? assignment : EOF; - } - - if (CHAR_IDENTIFIER == format[index]) - { - if (CHAR_IDENTIFIER == format[index + 1]) - { - /* Two % in format matches one % in input stream */ - if (CHAR_IDENTIFIER == ch) - { - data->InStream(data, &ch); - index += 2; - continue; /* while format chars left */ - } - else - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - i++; - - flags = parameters[i].flags; - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - } - /* Find base */ - base = parameters[i].base; - if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = (int)parameters[base].data.number.as_signed; - } - - switch (parameters[i].type) - { - case FORMAT_INT: - { - trio_uintmax_t number; - - if (0 == base) - base = BASE_DECIMAL; - - if (!TrioReadNumber(data, - &number, - flags, - width, - base)) - return assignment; - - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - - pointer = parameters[i].data.pointer; -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)number; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)number; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)number; - else -#endif - if (flags & FLAGS_QUAD) - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number; - else if (flags & FLAGS_LONG) - *(long int *)pointer = (long int)number; - else if (flags & FLAGS_SHORT) - *(short int *)pointer = (short int)number; - else - *(int *)pointer = (int)number; - } - } - break; /* FORMAT_INT */ - - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (!TrioReadWideString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - width)) - return assignment; - } - else -#endif - { - if (!TrioReadString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - width)) - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_STRING */ - - case FORMAT_DOUBLE: - { - trio_pointer_t pointer; - - if (flags & FLAGS_IGNORE) - { - pointer = NULL; - } - else - { - pointer = (flags & FLAGS_LONGDOUBLE) - ? (trio_pointer_t)parameters[i].data.longdoublePointer - : (trio_pointer_t)parameters[i].data.doublePointer; - } - if (!TrioReadDouble(data, pointer, flags, width)) - { - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - } - break; /* FORMAT_DOUBLE */ - } - case FORMAT_GROUP: - { - int characterclass[MAX_CHARACTER_CLASS + 1]; - int rc; - - /* Skip over modifiers */ - while (format[index] != SPECIFIER_GROUP) - { - index++; - } - /* Skip over group specifier */ - index++; - - memset(characterclass, 0, sizeof(characterclass)); - rc = TrioGetCharacterClass(format, - &index, - &flags, - characterclass); - if (rc < 0) - return rc; - - if (!TrioReadGroup(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - characterclass, - flags, - parameters[i].width)) - return assignment; - if (!(flags & FLAGS_IGNORE)) - assignment++; - } - break; /* FORMAT_GROUP */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - int count = data->committed; - if (ch != EOF) - count--; /* a character is read, but is not consumed yet */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)count; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)count; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)count; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)count; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)count; - } - else - { - *(int *)pointer = (int)count; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_CHAR: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (TrioReadWideChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - return assignment; - } - else -#endif - { - if (TrioReadChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_CHAR */ - - case FORMAT_POINTER: - if (!TrioReadPointer(data, - (flags & FLAGS_IGNORE) - ? NULL - : (trio_pointer_t *)parameters[i].data.pointer, - flags)) - return assignment; - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_POINTER */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - - default: - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - ch = data->current; - index = parameters[i].indexAfterSpecifier; - i++; - } - else /* Not an % identifier */ - { - if (isspace((int)format[index])) - { - /* Whitespaces may match any amount of whitespaces */ - ch = TrioSkipWhitespaces(data); - } - else if (ch == format[index]) - { - data->InStream(data, &ch); - } - else - return assignment; - - index++; - } - } - return assignment; -} - -/************************************************************************* - * TrioScan - */ -TRIO_PRIVATE int -TrioScan -TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray), - trio_pointer_t source, - size_t sourceSize, - void (*InStream) TRIO_PROTO((trio_class_t *, int *)), - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - trio_class_t data; - - assert(VALID(InStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.InStream = InStream; - data.location = (trio_pointer_t)source; - data.max = sourceSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioScanProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioInStreamFile - */ -TRIO_PRIVATE void -TrioInStreamFile -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - FILE *file; - - assert(VALID(self)); - assert(VALID(self->location)); - assert(VALID(file)); - - file = (FILE *)self->location; - - self->current = fgetc(file); - if (self->current == EOF) - { - self->error = (ferror(file)) - ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0) - : TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamFileDescriptor - */ -TRIO_PRIVATE void -TrioInStreamFileDescriptor -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - int fd; - int size; - unsigned char input; - - assert(VALID(self)); - assert(VALID(self->location)); - - fd = *((int *)self->location); - - size = read(fd, &input, sizeof(char)); - if (size == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - self->current = EOF; - } - else - { - self->current = (size == 0) ? EOF : input; - } - if (self->current != EOF) - { - self->committed++; - self->processed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamCustom - */ -TRIO_PRIVATE void -TrioInStreamCustom -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - data = (trio_custom_t *)self->location; - - self->current = (data->stream.in == NULL) - ? NIL - : (data->stream.in)(data->closure); - - if (self->current == NIL) - { - self->current = EOF; - } - else - { - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamString - */ -TRIO_PRIVATE void -TrioInStreamString -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - unsigned char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (unsigned char **)self->location; - self->current = (*buffer)[0]; - if (self->current == NIL) - { - self->current = EOF; - } - else - { - (*buffer)++; - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * - * Formatted scanning functions - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_scanf.h" -#endif -/** @addtogroup Scanf - @{ -*/ - -/************************************************************************* - * scanf - */ - -/** - Scan characters from standard input stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -TRIO_PUBLIC int -trio_scanf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vscanf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_scanfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, NULL, args); -} - -/************************************************************************* - * fscanf - */ -TRIO_PUBLIC int -trio_fscanf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vfscanf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_fscanfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, NULL, args); -} - -/************************************************************************* - * dscanf - */ -TRIO_PUBLIC int -trio_dscanf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vdscanf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_dscanfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, NULL, args); -} - -/************************************************************************* - * cscanf - */ -TRIO_PUBLIC int -trio_cscanf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.in = stream; - data.closure = closure; - status = TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vcscanf -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_cscanfv -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args); -} - -/************************************************************************* - * sscanf - */ -TRIO_PUBLIC int -trio_sscanf -TRIO_VARGS3((buffer, format, va_alist), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vsscanf -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_sscanfv -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, NULL, args); -} - -/** @} End of Scanf documentation module */ - -/************************************************************************* - * trio_strerror - */ -TRIO_PUBLIC TRIO_CONST char * -trio_strerror -TRIO_ARGS1((errorcode), - int errorcode) -{ - /* Textual versions of the error codes */ - switch (TRIO_ERROR_CODE(errorcode)) - { - case TRIO_EOF: - return "End of file"; - case TRIO_EINVAL: - return "Invalid argument"; - case TRIO_ETOOMANY: - return "Too many arguments"; - case TRIO_EDBLREF: - return "Double reference"; - case TRIO_EGAP: - return "Reference gap"; - case TRIO_ENOMEM: - return "Out of memory"; - case TRIO_ERANGE: - return "Invalid range"; - case TRIO_ECUSTOM: - return "Custom error"; - default: - return "Unknown"; - } -} diff --git a/trio.h b/trio.h deleted file mode 100644 index dcf96b6..0000000 --- a/trio.h +++ /dev/null @@ -1,230 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************* - * - * http://ctrio.sourceforge.net/ - * - ************************************************************************/ - -#ifndef TRIO_TRIO_H -#define TRIO_TRIO_H - -#if !defined(WITHOUT_TRIO) - -/* - * Use autoconf defines if present. Packages using trio must define - * HAVE_CONFIG_H as a compiler option themselves. - */ -#if defined(TRIO_HAVE_CONFIG_H) -# include "config.h" -#endif - -#include "triodef.h" - -#include -#include -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Error codes. - * - * Remember to add a textual description to trio_strerror. - */ -enum { - TRIO_EOF = 1, - TRIO_EINVAL = 2, - TRIO_ETOOMANY = 3, - TRIO_EDBLREF = 4, - TRIO_EGAP = 5, - TRIO_ENOMEM = 6, - TRIO_ERANGE = 7, - TRIO_ERRNO = 8, - TRIO_ECUSTOM = 9 -}; - -/* Error macros */ -#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) -#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) -#define TRIO_ERROR_NAME(x) trio_strerror(x) - -typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int)); -typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t)); - -TRIO_CONST char *trio_strerror TRIO_PROTO((int)); - -/************************************************************************* - * Print Functions - */ - -int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...)); -int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); -int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args)); - -int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); -int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); -int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); - -int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); -int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); -int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); - -int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, ...)); -int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, va_list args)); -int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, void **args)); - -int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...)); -int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args)); -int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args)); - -int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); -int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - va_list args)); -int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - void **args)); - -int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); -int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - va_list args)); - -char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...)); -char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); - -int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...)); -int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args)); - -/************************************************************************* - * Scan Functions - */ -int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...)); -int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args)); -int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args)); - -int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); -int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); -int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); - -int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); -int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); -int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); - -int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, ...)); -int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, va_list args)); -int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, void **args)); - -int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...)); -int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args)); -int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args)); - -/************************************************************************* - * Locale Functions - */ -void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint)); -void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator)); -void trio_locale_set_grouping TRIO_PROTO((char *grouping)); - -/************************************************************************* - * Renaming - */ -#ifdef TRIO_REPLACE_STDIO -/* Replace the functions */ -#ifndef HAVE_PRINTF -# undef printf -# define printf trio_printf -#endif -#ifndef HAVE_VPRINTF -# undef vprintf -# define vprintf trio_vprintf -#endif -#ifndef HAVE_FPRINTF -# undef fprintf -# define fprintf trio_fprintf -#endif -#ifndef HAVE_VFPRINTF -# undef vfprintf -# define vfprintf trio_vfprintf -#endif -#ifndef HAVE_SPRINTF -# undef sprintf -# define sprintf trio_sprintf -#endif -#ifndef HAVE_VSPRINTF -# undef vsprintf -# define vsprintf trio_vsprintf -#endif -#ifndef HAVE_SNPRINTF -# undef snprintf -# define snprintf trio_snprintf -#endif -#ifndef HAVE_VSNPRINTF -# undef vsnprintf -# define vsnprintf trio_vsnprintf -#endif -#ifndef HAVE_SCANF -# undef scanf -# define scanf trio_scanf -#endif -#ifndef HAVE_VSCANF -# undef vscanf -# define vscanf trio_vscanf -#endif -#ifndef HAVE_FSCANF -# undef fscanf -# define fscanf trio_fscanf -#endif -#ifndef HAVE_VFSCANF -# undef vfscanf -# define vfscanf trio_vfscanf -#endif -#ifndef HAVE_SSCANF -# undef sscanf -# define sscanf trio_sscanf -#endif -#ifndef HAVE_VSSCANF -# undef vsscanf -# define vsscanf trio_vsscanf -#endif -/* These aren't stdio functions, but we make them look similar */ -#define dprintf trio_dprintf -#define vdprintf trio_vdprintf -#define aprintf trio_aprintf -#define vaprintf trio_vaprintf -#define asprintf trio_asprintf -#define vasprintf trio_vasprintf -#define dscanf trio_dscanf -#define vdscanf trio_vdscanf -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* WITHOUT_TRIO */ - -#endif /* TRIO_TRIO_H */ diff --git a/triodef.h b/triodef.h deleted file mode 100644 index e101f6d..0000000 --- a/triodef.h +++ /dev/null @@ -1,228 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_TRIODEF_H -#define TRIO_TRIODEF_H - -/************************************************************************* - * Platform and compiler support detection - */ -#if defined(__GNUC__) -# define TRIO_COMPILER_GCC -#elif defined(__SUNPRO_C) -# define TRIO_COMPILER_SUNPRO -#elif defined(__SUNPRO_CC) -# define TRIO_COMPILER_SUNPRO -# define __SUNPRO_C __SUNPRO_CC -#elif defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__) -# define TRIO_COMPILER_XLC -#elif defined(_AIX) && !defined(__GNUC__) -# define TRIO_COMPILER_XLC /* Workaround for old xlc */ -#elif defined(__DECC) || defined(__DECCXX) -# define TRIO_COMPILER_DECC -#elif defined(__osf__) && defined(__LANGUAGE_C__) -# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */ -#elif defined(_MSC_VER) -# define TRIO_COMPILER_MSVC -#elif defined(__BORLANDC__) -# define TRIO_COMPILER_BCB -#endif - -#if defined(VMS) || defined(__VMS) -/* - * VMS is placed first to avoid identifying the platform as Unix - * based on the DECC compiler later on. - */ -# define TRIO_PLATFORM_VMS -#elif defined(__OS400__) -# define TRIO_PLATFORM_OS400 -#elif defined(unix) || defined(__unix) || defined(__unix__) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_XLC) || defined(_AIX) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_DECC) || defined(__osf___) -# define TRIO_PLATFORM_UNIX -#elif defined(__NetBSD__) -# define TRIO_PLATFORM_UNIX -#elif defined(__Lynx__) -# define TRIO_PLATFORM_UNIX -#elif defined(__QNX__) -# define TRIO_PLATFORM_UNIX -# define TRIO_PLATFORM_QNX -#elif defined(__CYGWIN__) -# define TRIO_PLATFORM_UNIX -#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32) -# define TRIO_PLATFORM_WIN32 -#elif defined(mpeix) || defined(__mpexl) -# define TRIO_PLATFORM_MPEIX -#endif - -#if defined(_AIX) -# define TRIO_PLATFORM_AIX -#elif defined(__hpux) -# define TRIO_PLATFORM_HPUX -#elif defined(sun) || defined(__sun__) -# if defined(__SVR4) || defined(__svr4__) -# define TRIO_PLATFORM_SOLARIS -# else -# define TRIO_PLATFORM_SUNOS -# endif -#endif - -#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) -# define TRIO_COMPILER_SUPPORTS_C89 -# if defined(__STDC_VERSION__) -# define TRIO_COMPILER_SUPPORTS_C90 -# if (__STDC_VERSION__ >= 199409L) -# define TRIO_COMPILER_SUPPORTS_C94 -# endif -# if (__STDC_VERSION__ >= 199901L) -# define TRIO_COMPILER_SUPPORTS_C99 -# endif -# elif defined(TRIO_COMPILER_SUNPRO) -# if (__SUNPRO_C >= 0x420) -# define TRIO_COMPILER_SUPPORTS_C94 -# endif -# endif -#elif defined(TRIO_COMPILER_XLC) && defined(__EXTENDED__) -# define TRIO_COMPILER_SUPPORTS_C89 -# define TRIO_COMPILER_SUPPORTS_C90 -# define TRIO_COMPILER_SUPPORTS_C94 -#endif - -#if defined(_XOPEN_SOURCE) -# if defined(_XOPEN_SOURCE_EXTENDED) -# define TRIO_COMPILER_SUPPORTS_UNIX95 -# endif -# if (_XOPEN_VERSION >= 500) -# define TRIO_COMPILER_SUPPORTS_UNIX98 -# endif -# if (_XOPEN_VERSION >= 600) -# define TRIO_COMPILER_SUPPORTS_UNIX01 -# endif -#endif - -/************************************************************************* - * Generic defines - */ - -#if !defined(TRIO_PUBLIC) -# define TRIO_PUBLIC -#endif -#if !defined(TRIO_PRIVATE) -# define TRIO_PRIVATE static -#endif - -#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus)) -# define TRIO_COMPILER_ANCIENT -#endif - -#if defined(TRIO_COMPILER_ANCIENT) -# define TRIO_CONST -# define TRIO_VOLATILE -# define TRIO_SIGNED -typedef double trio_long_double_t; -typedef char * trio_pointer_t; -# define TRIO_SUFFIX_LONG(x) x -# define TRIO_PROTO(x) () -# define TRIO_NOARGS -# define TRIO_ARGS1(list,a1) list a1; -# define TRIO_ARGS2(list,a1,a2) list a1; a2; -# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3; -# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4; -# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5; -# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6; -# define TRIO_VARGS2(list,a1,a2) list a1; a2 -# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3 -# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4 -# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5 -# define TRIO_VA_DECL va_dcl -# define TRIO_VA_START(x,y) va_start(x) -# define TRIO_VA_END(x) va_end(x) -#else /* ANSI C */ -# define TRIO_CONST const -# define TRIO_VOLATILE volatile -# define TRIO_SIGNED signed -typedef long double trio_long_double_t; -typedef void * trio_pointer_t; -# define TRIO_SUFFIX_LONG(x) x ## L -# define TRIO_PROTO(x) x -# define TRIO_NOARGS void -# define TRIO_ARGS1(list,a1) (a1) -# define TRIO_ARGS2(list,a1,a2) (a1,a2) -# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3) -# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4) -# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5) -# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6) -# define TRIO_VARGS2 TRIO_ARGS2 -# define TRIO_VARGS3 TRIO_ARGS3 -# define TRIO_VARGS4 TRIO_ARGS4 -# define TRIO_VARGS5 TRIO_ARGS5 -# define TRIO_VA_DECL ... -# define TRIO_VA_START(x,y) va_start(x,y) -# define TRIO_VA_END(x) va_end(x) -#endif - -#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus) -# define TRIO_INLINE inline -#elif defined(TRIO_COMPILER_GCC) -# define TRIO_INLINE __inline__ -#elif defined(TRIO_COMPILER_MSVC) -# define TRIO_INLINE _inline -#elif defined(TRIO_COMPILER_BCB) -# define TRIO_INLINE __inline -#else -# define TRIO_INLINE -#endif - -/************************************************************************* - * Workarounds - */ - -#if defined(TRIO_PLATFORM_VMS) -/* - * Computations done with constants at compile time can trigger these - * even when compiling with IEEE enabled. - */ -# pragma message disable (UNDERFLOW, FLOATOVERFL) - -# if (__CRTL_VER < 80000000) -/* - * Although the compiler supports C99 language constructs, the C - * run-time library does not contain all C99 functions. - * - * This was the case for 70300022. Update the 80000000 value when - * it has been accurately determined what version of the library - * supports C99. - */ -# if defined(TRIO_COMPILER_SUPPORTS_C99) -# undef TRIO_COMPILER_SUPPORTS_C99 -# endif -# endif -#endif - -/* - * Not all preprocessors supports the LL token. - */ -#if defined(TRIO_COMPILER_BCB) -#else -# define TRIO_COMPILER_SUPPORTS_LL -#endif - -#endif /* TRIO_TRIODEF_H */ diff --git a/trionan.c b/trionan.c deleted file mode 100644 index 8767a9f..0000000 --- a/trionan.c +++ /dev/null @@ -1,914 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************ - * - * Functions to handle special quantities in floating-point numbers - * (that is, NaNs and infinity). They provide the capability to detect - * and fabricate special quantities. - * - * Although written to be as portable as possible, it can never be - * guaranteed to work on all platforms, as not all hardware supports - * special quantities. - * - * The approach used here (approximately) is to: - * - * 1. Use C99 functionality when available. - * 2. Use IEEE 754 bit-patterns if possible. - * 3. Use platform-specific techniques. - * - ************************************************************************/ - -/* - * TODO: - * o Put all the magic into trio_fpclassify_and_signbit(), and use this from - * trio_isnan() etc. - */ - -/************************************************************************* - * Include files - */ -#include "triodef.h" -#include "trionan.h" - -#include -#include -#include -#include -#if defined(TRIO_PLATFORM_UNIX) -# include -#endif -#if defined(TRIO_COMPILER_DECC) -# if defined(__linux__) -# include -# else -# include -# endif -#endif -#include - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_nan.h" -#endif -/** @addtogroup SpecialQuantities - @{ -*/ - -/************************************************************************* - * Definitions - */ - -#define TRIO_TRUE (1 == 1) -#define TRIO_FALSE (0 == 1) - -/* - * We must enable IEEE floating-point on Alpha - */ -#if defined(__alpha) && !defined(_IEEE_FP) -# if defined(TRIO_COMPILER_DECC) -# if defined(TRIO_PLATFORM_VMS) -# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" -# else -# if !defined(_CFE) -# error "Must be compiled with option -ieee" -# endif -# endif -# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__)) -# error "Must be compiled with option -mieee" -# endif -#endif /* __alpha && ! _IEEE_FP */ - -/* - * In ANSI/IEEE 754-1985 64-bits double format numbers have the - * following properties (amongst others) - * - * o FLT_RADIX == 2: binary encoding - * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used - * to indicate special numbers (e.g. NaN and Infinity), so the - * maximum exponent is 10 bits wide (2^10 == 1024). - * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because - * numbers are normalized the initial binary 1 is represented - * implicitly (the so-called "hidden bit"), which leaves us with - * the ability to represent 53 bits wide mantissa. - */ -#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53) -# define USE_IEEE_754 -#endif - - -/************************************************************************* - * Constants - */ - -static TRIO_CONST char rcsid[] = "@(#)$Id$"; - -#if defined(USE_IEEE_754) - -/* - * Endian-agnostic indexing macro. - * - * The value of internalEndianMagic, when converted into a 64-bit - * integer, becomes 0x0706050403020100 (we could have used a 64-bit - * integer value instead of a double, but not all platforms supports - * that type). The value is automatically encoded with the correct - * endianness by the compiler, which means that we can support any - * kind of endianness. The individual bytes are then used as an index - * for the IEEE 754 bit-patterns and masks. - */ -#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) - -#if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590) -static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275; -#else -static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; -#endif - -/* Mask for the exponent */ -static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Mask for the mantissa */ -static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { - 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* Mask for the sign bit */ -static TRIO_CONST unsigned char ieee_754_sign_mask[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for negative zero */ -static TRIO_CONST unsigned char ieee_754_negzero_array[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for infinity */ -static TRIO_CONST unsigned char ieee_754_infinity_array[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for quiet NaN */ -static TRIO_CONST unsigned char ieee_754_qnan_array[] = { - 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - -/************************************************************************* - * Functions - */ - -/* - * trio_make_double - */ -TRIO_PRIVATE double -trio_make_double -TRIO_ARGS1((values), - TRIO_CONST unsigned char *values) -{ - TRIO_VOLATILE double result; - int i; - - for (i = 0; i < (int)sizeof(double); i++) { - ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; - } - return result; -} - -/* - * trio_is_special_quantity - */ -TRIO_PRIVATE int -trio_is_special_quantity -TRIO_ARGS2((number, has_mantissa), - double number, - int *has_mantissa) -{ - unsigned int i; - unsigned char current; - int is_special_quantity = TRIO_TRUE; - - *has_mantissa = 0; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; - is_special_quantity - &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); - *has_mantissa |= (current & ieee_754_mantissa_mask[i]); - } - return is_special_quantity; -} - -/* - * trio_is_negative - */ -TRIO_PRIVATE int -trio_is_negative -TRIO_ARGS1((number), - double number) -{ - unsigned int i; - int is_negative = TRIO_FALSE; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] - & ieee_754_sign_mask[i]); - } - return is_negative; -} - -#endif /* USE_IEEE_754 */ - - -/** - Generate negative zero. - - @return Floating-point representation of negative zero. -*/ -TRIO_PUBLIC double -trio_nzero(TRIO_NOARGS) -{ -#if defined(USE_IEEE_754) - return trio_make_double(ieee_754_negzero_array); -#else - TRIO_VOLATILE double zero = 0.0; - - return -zero; -#endif -} - -/** - Generate positive infinity. - - @return Floating-point representation of positive infinity. -*/ -TRIO_PUBLIC double -trio_pinf(TRIO_NOARGS) -{ - /* Cache the result */ - static double result = 0.0; - - if (result == 0.0) { - -#if defined(INFINITY) && defined(__STDC_IEC_559__) - result = (double)INFINITY; - -#elif defined(USE_IEEE_754) - result = trio_make_double(ieee_754_infinity_array); - -#else - /* - * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used - * as infinity. Otherwise we have to resort to an overflow - * operation to generate infinity. - */ -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - result = HUGE_VAL; - if (HUGE_VAL == DBL_MAX) { - /* Force overflow */ - result += HUGE_VAL; - } - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - -#endif - } - return result; -} - -/** - Generate negative infinity. - - @return Floating-point value of negative infinity. -*/ -TRIO_PUBLIC double -trio_ninf(TRIO_NOARGS) -{ - static double result = 0.0; - - if (result == 0.0) { - /* - * Negative infinity is calculated by negating positive infinity, - * which can be done because it is legal to do calculations on - * infinity (for example, 1 / infinity == 0). - */ - result = -trio_pinf(); - } - return result; -} - -/** - Generate NaN. - - @return Floating-point representation of NaN. -*/ -TRIO_PUBLIC double -trio_nan(TRIO_NOARGS) -{ - /* Cache the result */ - static double result = 0.0; - - if (result == 0.0) { - -#if defined(TRIO_COMPILER_SUPPORTS_C99) - result = nan(""); - -#elif defined(NAN) && defined(__STDC_IEC_559__) - result = (double)NAN; - -#elif defined(USE_IEEE_754) - result = trio_make_double(ieee_754_qnan_array); - -#else - /* - * There are several ways to generate NaN. The one used here is - * to divide infinity by infinity. I would have preferred to add - * negative infinity to positive infinity, but that yields wrong - * result (infinity) on FreeBSD. - * - * This may fail if the hardware does not support NaN, or if - * the Invalid Operation floating-point exception is unmasked. - */ -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - result = trio_pinf() / trio_pinf(); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - -#endif - } - return result; -} - -/** - Check for NaN. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a NaN. -*/ -TRIO_PUBLIC int -trio_isnan -TRIO_ARGS1((number), - double number) -{ -#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \ - || defined(TRIO_COMPILER_SUPPORTS_UNIX95) - /* - * C99 defines isnan() as a macro. UNIX95 defines isnan() as a - * function. This function was already present in XPG4, but this - * is a bit tricky to detect with compiler defines, so we choose - * the conservative approach and only use it for UNIX95. - */ - return isnan(number); - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _isnan() - * function. - */ - return _isnan(number) ? TRIO_TRUE : TRIO_FALSE; - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. A NaN must have a special exponent - * pattern, and a non-empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = trio_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && has_mantissa); - -#else - /* - * Fallback solution - */ - int status; - double integral, fraction; - -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - status = (/* - * NaN is the only number which does not compare to itself - */ - ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || - /* - * Fallback solution if NaN compares to NaN - */ - ((number != 0.0) && - (fraction = modf(number, &integral), - integral == fraction))); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - return status; - -#endif -} - -/** - Check for infinity. - - @param number An arbitrary floating-point number. - @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. -*/ -TRIO_PUBLIC int -trio_isinf -TRIO_ARGS1((number), - double number) -{ -#if defined(TRIO_COMPILER_DECC) && !defined(__linux__) - /* - * DECC has an isinf() macro, but it works differently than that - * of C99, so we use the fp_class() function instead. - */ - return ((fp_class(number) == FP_POS_INF) - ? 1 - : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); - -#elif defined(isinf) - /* - * C99 defines isinf() as a macro. - */ - return isinf(number) - ? ((number > 0.0) ? 1 : -1) - : 0; - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() - * function that can be used to detect infinity. - */ - return ((_fpclass(number) == _FPCLASS_PINF) - ? 1 - : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0)); - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. Infinity must have a special exponent - * pattern, and an empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = trio_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && !has_mantissa) - ? ((number < 0.0) ? -1 : 1) - : 0; - -#else - /* - * Fallback solution. - */ - int status; - -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - double infinity = trio_pinf(); - - status = ((number == infinity) - ? 1 - : ((number == -infinity) ? -1 : 0)); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - return status; - -#endif -} - -#if 0 - /* Temporary fix - this routine is not used anywhere */ -/** - Check for finity. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a finite. -*/ -TRIO_PUBLIC int -trio_isfinite -TRIO_ARGS1((number), - double number) -{ -#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite) - /* - * C99 defines isfinite() as a macro. - */ - return isfinite(number); - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder use _finite(). - */ - return _finite(number); - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. For finity we do not care about the - * mantissa. - */ - int dummy; - - return (! trio_is_special_quantity(number, &dummy)); - -#else - /* - * Fallback solution. - */ - return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0)); - -#endif -} - -#endif - -/* - * The sign of NaN is always false - */ -TRIO_PUBLIC int -trio_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ -#if defined(fpclassify) && defined(signbit) - /* - * C99 defines fpclassify() and signbit() as a macros - */ - *is_negative = signbit(number); - switch (fpclassify(number)) { - case FP_NAN: - return TRIO_FP_NAN; - case FP_INFINITE: - return TRIO_FP_INFINITE; - case FP_SUBNORMAL: - return TRIO_FP_SUBNORMAL; - case FP_ZERO: - return TRIO_FP_ZERO; - default: - return TRIO_FP_NORMAL; - } - -#else -# if defined(TRIO_COMPILER_DECC) - /* - * DECC has an fp_class() function. - */ -# define TRIO_FPCLASSIFY(n) fp_class(n) -# define TRIO_QUIET_NAN FP_QNAN -# define TRIO_SIGNALLING_NAN FP_SNAN -# define TRIO_POSITIVE_INFINITY FP_POS_INF -# define TRIO_NEGATIVE_INFINITY FP_NEG_INF -# define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM -# define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM -# define TRIO_POSITIVE_ZERO FP_POS_ZERO -# define TRIO_NEGATIVE_ZERO FP_NEG_ZERO -# define TRIO_POSITIVE_NORMAL FP_POS_NORM -# define TRIO_NEGATIVE_NORMAL FP_NEG_NORM - -# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() - * function. - */ -# define TRIO_FPCLASSIFY(n) _fpclass(n) -# define TRIO_QUIET_NAN _FPCLASS_QNAN -# define TRIO_SIGNALLING_NAN _FPCLASS_SNAN -# define TRIO_POSITIVE_INFINITY _FPCLASS_PINF -# define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF -# define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD -# define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND -# define TRIO_POSITIVE_ZERO _FPCLASS_PZ -# define TRIO_NEGATIVE_ZERO _FPCLASS_NZ -# define TRIO_POSITIVE_NORMAL _FPCLASS_PN -# define TRIO_NEGATIVE_NORMAL _FPCLASS_NN - -# elif defined(FP_PLUS_NORM) - /* - * HP-UX 9.x and 10.x have an fpclassify() function, that is different - * from the C99 fpclassify() macro supported on HP-UX 11.x. - * - * AIX has class() for C, and _class() for C++, which returns the - * same values as the HP-UX fpclassify() function. - */ -# if defined(TRIO_PLATFORM_AIX) -# if defined(__cplusplus) -# define TRIO_FPCLASSIFY(n) _class(n) -# else -# define TRIO_FPCLASSIFY(n) class(n) -# endif -# else -# define TRIO_FPCLASSIFY(n) fpclassify(n) -# endif -# define TRIO_QUIET_NAN FP_QNAN -# define TRIO_SIGNALLING_NAN FP_SNAN -# define TRIO_POSITIVE_INFINITY FP_PLUS_INF -# define TRIO_NEGATIVE_INFINITY FP_MINUS_INF -# define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM -# define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM -# define TRIO_POSITIVE_ZERO FP_PLUS_ZERO -# define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO -# define TRIO_POSITIVE_NORMAL FP_PLUS_NORM -# define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM -# endif - -# if defined(TRIO_FPCLASSIFY) - switch (TRIO_FPCLASSIFY(number)) { - case TRIO_QUIET_NAN: - case TRIO_SIGNALLING_NAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - return TRIO_FP_NAN; - case TRIO_POSITIVE_INFINITY: - *is_negative = TRIO_FALSE; - return TRIO_FP_INFINITE; - case TRIO_NEGATIVE_INFINITY: - *is_negative = TRIO_TRUE; - return TRIO_FP_INFINITE; - case TRIO_POSITIVE_SUBNORMAL: - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - case TRIO_NEGATIVE_SUBNORMAL: - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - case TRIO_POSITIVE_ZERO: - *is_negative = TRIO_FALSE; - return TRIO_FP_ZERO; - case TRIO_NEGATIVE_ZERO: - *is_negative = TRIO_TRUE; - return TRIO_FP_ZERO; - case TRIO_POSITIVE_NORMAL: - *is_negative = TRIO_FALSE; - return TRIO_FP_NORMAL; - case TRIO_NEGATIVE_NORMAL: - *is_negative = TRIO_TRUE; - return TRIO_FP_NORMAL; - default: - /* Just in case... */ - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - } - -# else - /* - * Fallback solution. - */ - int rc; - - if (number == 0.0) { - /* - * In IEEE 754 the sign of zero is ignored in comparisons, so we - * have to handle this as a special case by examining the sign bit - * directly. - */ -# if defined(USE_IEEE_754) - *is_negative = trio_is_negative(number); -# else - *is_negative = TRIO_FALSE; /* FIXME */ -# endif - return TRIO_FP_ZERO; - } - if (trio_isnan(number)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_NAN; - } - if ((rc = trio_isinf(number))) { - *is_negative = (rc == -1); - return TRIO_FP_INFINITE; - } - if ((number > 0.0) && (number < DBL_MIN)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - } - if ((number < 0.0) && (number > -DBL_MIN)) { - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - } - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - -# endif -#endif -} - -/** - Examine the sign of a number. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number has the - sign bit set (i.e. is negative). -*/ -TRIO_PUBLIC int -trio_signbit -TRIO_ARGS1((number), - double number) -{ - int is_negative; - - (void)trio_fpclassify_and_signbit(number, &is_negative); - return is_negative; -} - -#if 0 - /* Temporary fix - this routine is not used in libxml */ -/** - Examine the class of a number. - - @param number An arbitrary floating-point number. - @return Enumerable value indicating the class of @p number -*/ -TRIO_PUBLIC int -trio_fpclassify -TRIO_ARGS1((number), - double number) -{ - int dummy; - - return trio_fpclassify_and_signbit(number, &dummy); -} - -#endif - -/** @} SpecialQuantities */ - -/************************************************************************* - * For test purposes. - * - * Add the following compiler option to include this test code. - * - * Unix : -DSTANDALONE - * VMS : /DEFINE=(STANDALONE) - */ -#if defined(STANDALONE) -# include - -static TRIO_CONST char * -getClassification -TRIO_ARGS1((type), - int type) -{ - switch (type) { - case TRIO_FP_INFINITE: - return "FP_INFINITE"; - case TRIO_FP_NAN: - return "FP_NAN"; - case TRIO_FP_NORMAL: - return "FP_NORMAL"; - case TRIO_FP_SUBNORMAL: - return "FP_SUBNORMAL"; - case TRIO_FP_ZERO: - return "FP_ZERO"; - default: - return "FP_UNKNOWN"; - } -} - -static void -print_class -TRIO_ARGS2((prefix, number), - TRIO_CONST char *prefix, - double number) -{ - printf("%-6s: %s %-15s %g\n", - prefix, - trio_signbit(number) ? "-" : "+", - getClassification(TRIO_FPCLASSIFY(number)), - number); -} - -int main(TRIO_NOARGS) -{ - double my_nan; - double my_pinf; - double my_ninf; -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler) TRIO_PROTO((int)); -# endif - - my_nan = trio_nan(); - my_pinf = trio_pinf(); - my_ninf = trio_ninf(); - - print_class("Nan", my_nan); - print_class("PInf", my_pinf); - print_class("NInf", my_ninf); - print_class("PZero", 0.0); - print_class("NZero", -0.0); - print_class("PNorm", 1.0); - print_class("NNorm", -1.0); - print_class("PSub", 1.01e-307 - 1.00e-307); - print_class("NSub", 1.00e-307 - 1.01e-307); - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf)); - -# if defined(TRIO_PLATFORM_UNIX) - signal_handler = signal(SIGFPE, SIG_IGN); -# endif - - my_pinf = DBL_MAX + DBL_MAX; - my_ninf = -my_pinf; - my_nan = my_pinf / my_pinf; - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf)); - - return 0; -} -#endif diff --git a/trionan.h b/trionan.h deleted file mode 100644 index eac0e6f..0000000 --- a/trionan.h +++ /dev/null @@ -1,84 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_NAN_H -#define TRIO_NAN_H - -#include "triodef.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - TRIO_FP_INFINITE, - TRIO_FP_NAN, - TRIO_FP_NORMAL, - TRIO_FP_SUBNORMAL, - TRIO_FP_ZERO -}; - -/* - * Return NaN (Not-a-Number). - */ -TRIO_PUBLIC double trio_nan TRIO_PROTO((void)); - -/* - * Return positive infinity. - */ -TRIO_PUBLIC double trio_pinf TRIO_PROTO((void)); - -/* - * Return negative infinity. - */ -TRIO_PUBLIC double trio_ninf TRIO_PROTO((void)); - -/* - * Return negative zero. - */ -TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS)); - -/* - * If number is a NaN return non-zero, otherwise return zero. - */ -TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number)); - -/* - * If number is positive infinity return 1, if number is negative - * infinity return -1, otherwise return 0. - */ -TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number)); - -/* - * If number is finite return non-zero, otherwise return zero. - */ -#if 0 - /* Temporary fix - these 2 routines not used in libxml */ -TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number)); - -TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number)); -#endif - -TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number)); - -TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative)); - -#ifdef __cplusplus -} -#endif - -#endif /* TRIO_NAN_H */ diff --git a/triop.h b/triop.h deleted file mode 100644 index 6d486f8..0000000 --- a/triop.h +++ /dev/null @@ -1,150 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2000 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************ - * - * Private functions, types, etc. used for callback functions. - * - * The ref pointer is an opaque type and should remain as such. - * Private data must only be accessible through the getter and - * setter functions. - * - ************************************************************************/ - -#ifndef TRIO_TRIOP_H -#define TRIO_TRIOP_H - -#include "triodef.h" - -#include -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef TRIO_C99 -# define TRIO_C99 1 -#endif -#ifndef TRIO_BSD -# define TRIO_BSD 1 -#endif -#ifndef TRIO_GNU -# define TRIO_GNU 1 -#endif -#ifndef TRIO_MISC -# define TRIO_MISC 1 -#endif -#ifndef TRIO_UNIX98 -# define TRIO_UNIX98 1 -#endif -#ifndef TRIO_MICROSOFT -# define TRIO_MICROSOFT 1 -#endif -#ifndef TRIO_EXTENSION -# define TRIO_EXTENSION 1 -#endif -#ifndef TRIO_WIDECHAR /* Does not work yet. Do not enable */ -# define TRIO_WIDECHAR 0 -#endif -#ifndef TRIO_ERRORS -# define TRIO_ERRORS 1 -#endif - -#ifndef TRIO_MALLOC -# define TRIO_MALLOC(n) malloc(n) -#endif -#ifndef TRIO_REALLOC -# define TRIO_REALLOC(x,n) realloc((x),(n)) -#endif -#ifndef TRIO_FREE -# define TRIO_FREE(x) free(x) -#endif - - -/************************************************************************* - * User-defined specifiers - */ - -typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t)); - -trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name)); -void trio_unregister TRIO_PROTO((trio_pointer_t handle)); - -TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref)); -trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref)); - -/* Modifiers */ -int trio_get_width TRIO_PROTO((trio_pointer_t ref)); -void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width)); -int trio_get_precision TRIO_PROTO((trio_pointer_t ref)); -void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision)); -int trio_get_base TRIO_PROTO((trio_pointer_t ref)); -void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base)); -int trio_get_padding TRIO_PROTO((trio_pointer_t ref)); -void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding)); -int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */ -void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort)); -int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */ -void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short)); -int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */ -void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long)); -int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */ -void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong)); -int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */ -void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble)); -int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */ -void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative)); -int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */ -void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned)); -int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* TRIO_PROTO((space) */ -void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space)); -int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */ -void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign)); -int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */ -void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote)); -int trio_get_upper TRIO_PROTO((trio_pointer_t ref)); -void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper)); -#if TRIO_C99 -int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */ -void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest)); -int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */ -void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff)); -int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */ -void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size)); -#endif - -/* Printing */ -int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...)); -int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args)); -int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args)); - -void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number)); -void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number)); -/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */ -/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */ -void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number)); -void trio_print_string TRIO_PROTO((trio_pointer_t ref, char *string)); -void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer)); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* TRIO_TRIOP_H */ diff --git a/triostr.c b/triostr.c deleted file mode 100644 index 5937a44..0000000 --- a/triostr.c +++ /dev/null @@ -1,2112 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -/************************************************************************* - * Include files - */ - -#include -#include -#include -#include -#include -#include "triodef.h" -#include "triostr.h" - -/************************************************************************* - * Definitions - */ - -#if !defined(TRIO_STRING_PUBLIC) -# define TRIO_STRING_PUBLIC TRIO_PUBLIC -#endif -#if !defined(TRIO_STRING_PRIVATE) -# define TRIO_STRING_PRIVATE TRIO_PRIVATE -#endif - -#if !defined(NULL) -# define NULL 0 -#endif -#if !defined(NIL) -# define NIL ((char)0) -#endif -#if !defined(FALSE) -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#if !defined(BOOLEAN_T) -# define BOOLEAN_T int -#endif - -#ifdef __VMS -# define USE_STRTOD -#elif defined(TRIO_COMPILER_SUPPORTS_C99) -# define USE_STRTOD -# define USE_STRTOF -#elif defined(TRIO_COMPILER_MSVC) -# define USE_STRTOD -#endif - -#if defined(TRIO_PLATFORM_UNIX) -# define USE_STRCASECMP -# define USE_STRNCASECMP -# if defined(TRIO_PLATFORM_SUNOS) -# define USE_SYS_ERRLIST -# else -# define USE_STRERROR -# endif -# if defined(TRIO_PLATFORM_QNX) -# define strcasecmp(x,y) stricmp(x,y) -# define strncasecmp(x,y,n) strnicmp(x,y,n) -# endif -#elif defined(TRIO_PLATFORM_WIN32) -# define USE_STRCASECMP -# if defined(_WIN32_WCE) -# define strcasecmp(x,y) _stricmp(x,y) -# else -# define strcasecmp(x,y) strcmpi(x,y) -# endif -#elif defined(TRIO_PLATFORM_OS400) -# define USE_STRCASECMP -# define USE_STRNCASECMP -# include -#endif - -#if !(defined(TRIO_PLATFORM_SUNOS)) -# define USE_TOLOWER -# define USE_TOUPPER -#endif - -/************************************************************************* - * Structures - */ - -struct _trio_string_t -{ - char *content; - size_t length; - size_t allocated; -}; - -/************************************************************************* - * Constants - */ - -#if !defined(TRIO_MINIMAL) -static TRIO_CONST char rcsid[] = "@(#)$Id$"; -#endif - -/************************************************************************* - * Static String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_static.h" -#endif -/** @addtogroup StaticStrings - @{ -*/ - -/** - Create new string. - - @param size Size of new string. - @return Pointer to string, or NULL if allocation failed. -*/ -TRIO_STRING_PUBLIC char * -trio_create -TRIO_ARGS1((size), - size_t size) -{ - return (char *)TRIO_MALLOC(size); -} - - -/** - Destroy string. - - @param string String to be freed. -*/ -TRIO_STRING_PUBLIC void -trio_destroy -TRIO_ARGS1((string), - char *string) -{ - if (string) - { - TRIO_FREE(string); - } -} - - -/** - Count the number of characters in a string. - - @param string String to measure. - @return Number of characters in @string. -*/ -TRIO_STRING_PUBLIC size_t -trio_length -TRIO_ARGS1((string), - TRIO_CONST char *string) -{ - return strlen(string); -} - - -#if !defined(TRIO_MINIMAL) -/** - Append @p source at the end of @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p target string and @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_append -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - return (strcat(target, source) != NULL); -} -#endif /* !defined(TRIO_MINIMAL) */ - -#if !defined(TRIO_MINIMAL) -/** - Append at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chuck with sufficient room to - contain the @p target string and the @p source string (at most @p max - characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_append_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - size_t length; - - assert(target); - assert(source); - - length = trio_length(target); - - if (max > length) - { - strncat(target, source, max - length - 1); - } - return TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Determine if a string contains a substring. - - @param string String to be searched. - @param substring String to be found. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_contains -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return (0 != strstr(string, substring)); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Copy @p source to @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_copy -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - (void)strcpy(target, source); - return TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Copy at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string (at most @p max characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_copy_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - assert(max > 0); /* Includes != 0 */ - - (void)strncpy(target, source, max - 1); - target[max - 1] = (char)0; - return TRUE; -} - - -/* - * TrioDuplicateMax - */ -TRIO_STRING_PRIVATE char * -TrioDuplicateMax -TRIO_ARGS2((source, size), - TRIO_CONST char *source, - size_t size) -{ - char *target; - - assert(source); - - /* Make room for string plus a terminating zero */ - size++; - target = trio_create(size); - if (target) - { - trio_copy_max(target, size, source); - } - return target; -} - - -/** - Duplicate @p source. - - @param source Source string. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC char * -trio_duplicate -TRIO_ARGS1((source), - TRIO_CONST char *source) -{ - return TrioDuplicateMax(source, trio_length(source)); -} - - -#if !defined(TRIO_MINIMAL) -/** - Duplicate at most @p max characters of @p source. - - @param source Source string. - @param max Maximum number of characters to duplicate. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC char * -trio_duplicate_max TRIO_ARGS2((source, max), - TRIO_CONST char *source, - size_t max) -{ - size_t length; - - assert(source); - assert(max > 0); - - length = trio_length(source); - if (length > max) - { - length = max; - } - return TrioDuplicateMax(source, length); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -#if defined(USE_STRCASECMP) - return (0 == strcasecmp(first, second)); -#else - while ((*first != NIL) && (*second != NIL)) - { - if (trio_to_upper(*first) != trio_to_upper(*second)) - { - break; - } - first++; - second++; - } - return ((*first == NIL) && (*second == NIL)); -#endif - } - return FALSE; -} - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_case -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strcmp(first, second)); - } - return FALSE; -} - - -#if !defined(TRIO_MINIMAL) -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_case_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strncmp(first, second, max)); - } - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Collating characters are considered equal. -*/ -TRIO_STRING_PUBLIC int -trio_equal_locale -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - -#if defined(LC_COLLATE) - return (strcoll(first, second) == 0); -#else - return trio_equal(first, second); -#endif -} - - -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -#if defined(USE_STRNCASECMP) - return (0 == strncasecmp(first, second, max)); -#else - /* Not adequately tested yet */ - size_t cnt = 0; - while ((*first != NIL) && (*second != NIL) && (cnt <= max)) - { - if (trio_to_upper(*first) != trio_to_upper(*second)) - { - break; - } - first++; - second++; - cnt++; - } - return ((cnt == max) || ((*first == NIL) && (*second == NIL))); -#endif - } - return FALSE; -} - - -/** - Provide a textual description of an error code (errno). - - @param error_number Error number. - @return Textual description of @p error_number. -*/ -TRIO_STRING_PUBLIC TRIO_CONST char * -trio_error -TRIO_ARGS1((error_number), - int error_number) -{ -#if defined(USE_STRERROR) - - return strerror(error_number); - -#elif defined(USE_SYS_ERRLIST) - - extern char *sys_errlist[]; - extern int sys_nerr; - - return ((error_number < 0) || (error_number >= sys_nerr)) - ? "unknown" - : sys_errlist[error_number]; - -#else - - return "unknown"; - -#endif -} - - -#if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) -/** - Format the date/time according to @p format. - - @param target Target string. - @param max Maximum number of characters to format. - @param format Formatting string. - @param datetime Date/time structure. - @return Number of formatted characters. - - The formatting string accepts the same specifiers as the standard C - function strftime. -*/ -TRIO_STRING_PUBLIC size_t -trio_format_date_max -TRIO_ARGS4((target, max, format, datetime), - char *target, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(target); - assert(format); - assert(datetime); - assert(max > 0); - - return strftime(target, max, format, datetime); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Calculate a hash value for a string. - - @param string String to be calculated on. - @param type Hash function. - @return Calculated hash value. - - @p type can be one of the following - @li @c TRIO_HASH_PLAIN Plain hash function. -*/ -TRIO_STRING_PUBLIC unsigned long -trio_hash -TRIO_ARGS2((string, type), - TRIO_CONST char *string, - int type) -{ - unsigned long value = 0L; - char ch; - - assert(string); - - switch (type) - { - case TRIO_HASH_PLAIN: - while ( (ch = *string++) != NIL ) - { - value *= 31; - value += (unsigned long)ch; - } - break; - default: - assert(FALSE); - break; - } - return value; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Find first occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @param A pointer to the found character, or NULL if character was not found. - */ -TRIO_STRING_PUBLIC char * -trio_index -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Find last occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @param A pointer to the found character, or NULL if character was not found. - */ -TRIO_STRING_PUBLIC char * -trio_index_last -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Convert the alphabetic letters in the string to lower-case. - - @param target String to be converted. - @return Number of processed characters (converted or not). -*/ -TRIO_STRING_PUBLIC int -trio_lower -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, trio_to_lower); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-insensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -TRIO_STRING_PUBLIC int -trio_match -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern)) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-sensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -TRIO_STRING_PUBLIC int -trio_match_case -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((*string != *pattern) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match_case(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Execute a function on each character in string. - - @param target Target string. - @param source Source string. - @param Function Function to be executed. - @return Number of processed characters. -*/ -TRIO_STRING_PUBLIC size_t -trio_span_function -TRIO_ARGS3((target, source, Function), - char *target, - TRIO_CONST char *source, - int (*Function) TRIO_PROTO((int))) -{ - size_t count = 0; - - assert(target); - assert(source); - assert(Function); - - while (*source != NIL) - { - *target++ = Function(*source++); - count++; - } - return count; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Search for a substring in a string. - - @param string String to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -TRIO_STRING_PUBLIC char * -trio_substring -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return strstr(string, substring); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Search for a substring in the first @p max characters of a string. - - @param string String to be searched. - @param max Maximum characters to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -TRIO_STRING_PUBLIC char * -trio_substring_max -TRIO_ARGS3((string, max, substring), - TRIO_CONST char *string, - size_t max, - TRIO_CONST char *substring) -{ - size_t count; - size_t size; - char *result = NULL; - - assert(string); - assert(substring); - - size = trio_length(substring); - if (size <= max) - { - for (count = 0; count <= max - size; count++) - { - if (trio_equal_max(substring, size, &string[count])) - { - result = (char *)&string[count]; - break; - } - } - } - return result; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Tokenize string. - - @param string String to be tokenized. - @param tokens String containing list of delimiting characters. - @return Start of new token. - - @warning @p string will be destroyed. -*/ -TRIO_STRING_PUBLIC char * -trio_tokenize -TRIO_ARGS2((string, delimiters), - char *string, - TRIO_CONST char *delimiters) -{ - assert(delimiters); - - return strtok(string, delimiters); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - The following Extended Backus-Naur form is used - @verbatim - double ::= [ ] - ( | - | - ) - [ [ ] ] - number ::= 1*( ) - digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) - exponential ::= ( 'e' | 'E' ) - sign ::= ( '-' | '+' ) - decimal_point ::= '.' - @endverbatim -*/ -/* FIXME: Add EBNF for hex-floats */ -TRIO_STRING_PUBLIC trio_long_double_t -trio_to_long_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOLD) - return strtold(source, endp); -#else - int isNegative = FALSE; - int isExponentNegative = FALSE; - trio_long_double_t integer = 0.0; - trio_long_double_t fraction = 0.0; - unsigned long exponent = 0; - trio_long_double_t base; - trio_long_double_t fracdiv = 1.0; - trio_long_double_t value = 0.0; - - /* First try hex-floats */ - if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) - { - base = 16.0; - source += 2; - while (isxdigit((int)*source)) - { - integer *= base; - integer += (isdigit((int)*source) - ? (*source - '0') - : 10 + (trio_to_upper((int)*source) - 'A')); - source++; - } - if (*source == '.') - { - source++; - while (isxdigit((int)*source)) - { - fracdiv /= base; - fraction += fracdiv * (isdigit((int)*source) - ? (*source - '0') - : 10 + (trio_to_upper((int)*source) - 'A')); - source++; - } - if ((*source == 'p') || (*source == 'P')) - { - source++; - if ((*source == '+') || (*source == '-')) - { - isExponentNegative = (*source == '-'); - source++; - } - while (isdigit((int)*source)) - { - exponent *= 10; - exponent += (*source - '0'); - source++; - } - } - } - /* For later use with exponent */ - base = 2.0; - } - else /* Then try normal decimal floats */ - { - base = 10.0; - isNegative = (*source == '-'); - /* Skip sign */ - if ((*source == '+') || (*source == '-')) - source++; - - /* Integer part */ - while (isdigit((int)*source)) - { - integer *= base; - integer += (*source - '0'); - source++; - } - - if (*source == '.') - { - source++; /* skip decimal point */ - while (isdigit((int)*source)) - { - fracdiv /= base; - fraction += (*source - '0') * fracdiv; - source++; - } - } - if ((*source == 'e') - || (*source == 'E') -#if TRIO_MICROSOFT - || (*source == 'd') - || (*source == 'D') -#endif - ) - { - source++; /* Skip exponential indicator */ - isExponentNegative = (*source == '-'); - if ((*source == '+') || (*source == '-')) - source++; - while (isdigit((int)*source)) - { - exponent *= (int)base; - exponent += (*source - '0'); - source++; - } - } - } - - value = integer + fraction; - if (exponent != 0) - { - if (isExponentNegative) - value /= pow(base, (double)exponent); - else - value *= pow(base, (double)exponent); - } - if (isNegative) - value = -value; - - if (endp) - *endp = (char *)source; - return value; -#endif -} - - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -TRIO_STRING_PUBLIC double -trio_to_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOD) - return strtod(source, endp); -#else - return (double)trio_to_long_double(source, endp); -#endif -} - -#if !defined(TRIO_MINIMAL) -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -TRIO_STRING_PUBLIC float -trio_to_float -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOF) - return strtof(source, endp); -#else - return (float)trio_to_long_double(source, endp); -#endif -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert string to signed integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -TRIO_STRING_PUBLIC long -trio_to_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtol(string, endp, base); -} - - -#if !defined(TRIO_MINIMAL) -/** - Convert one alphabetic letter to lower-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -TRIO_STRING_PUBLIC int -trio_to_lower -TRIO_ARGS1((source), - int source) -{ -#if defined(USE_TOLOWER) - - return tolower(source); - -#else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'A') && (source <= (int)'Z')) - ? source - 'A' + 'a' - : source; - -#endif -} -#endif /* !defined(TRIO_MINIMAL) */ - -#if !defined(TRIO_MINIMAL) -/** - Convert string to unsigned integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -TRIO_STRING_PUBLIC unsigned long -trio_to_unsigned_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtoul(string, endp, base); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert one alphabetic letter to upper-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -TRIO_STRING_PUBLIC int -trio_to_upper -TRIO_ARGS1((source), - int source) -{ -#if defined(USE_TOUPPER) - - return toupper(source); - -#else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'a') && (source <= (int)'z')) - ? source - 'a' + 'A' - : source; - -#endif -} - -#if !defined(TRIO_MINIMAL) -/** - Convert the alphabetic letters in the string to upper-case. - - @param target The string to be converted. - @return The number of processed characters (converted or not). -*/ -TRIO_STRING_PUBLIC int -trio_upper -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, trio_to_upper); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** @} End of StaticStrings */ - - -/************************************************************************* - * Dynamic String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_dynamic.h" -#endif -/** @addtogroup DynamicStrings - @{ -*/ - -/* - * TrioStringAlloc - */ -TRIO_STRING_PRIVATE trio_string_t * -TrioStringAlloc(TRIO_NOARGS) -{ - trio_string_t *self; - - self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); - if (self) - { - self->content = NULL; - self->length = 0; - self->allocated = 0; - } - return self; -} - - -/* - * TrioStringGrow - * - * The size of the string will be increased by 'delta' characters. If - * 'delta' is zero, the size will be doubled. - */ -TRIO_STRING_PRIVATE BOOLEAN_T -TrioStringGrow -TRIO_ARGS2((self, delta), - trio_string_t *self, - size_t delta) -{ - BOOLEAN_T status = FALSE; - char *new_content; - size_t new_size; - - new_size = (delta == 0) - ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) - : self->allocated + delta; - - new_content = (char *)TRIO_REALLOC(self->content, new_size); - if (new_content) - { - self->content = new_content; - self->allocated = new_size; - status = TRUE; - } - return status; -} - - -#if !defined(TRIO_MINIMAL) -/* - * TrioStringGrowTo - * - * The size of the string will be increased to 'length' plus one characters. - * If 'length' is less than the original size, the original size will be - * used (that is, the size of the string is never decreased). - */ -TRIO_STRING_PRIVATE BOOLEAN_T -TrioStringGrowTo -TRIO_ARGS2((self, length), - trio_string_t *self, - size_t length) -{ - length++; /* Room for terminating zero */ - return (self->allocated < length) - ? TrioStringGrow(self, length - self->allocated) - : TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Create a new dynamic string. - - @param initial_size Initial size of the buffer. - @return Newly allocated dynamic string, or NULL if memory allocation failed. -*/ -TRIO_STRING_PUBLIC trio_string_t * -trio_string_create -TRIO_ARGS1((initial_size), - int initial_size) -{ - trio_string_t *self; - - self = TrioStringAlloc(); - if (self) - { - if (TrioStringGrow(self, - (size_t)((initial_size > 0) ? initial_size : 1))) - { - self->content[0] = (char)0; - self->allocated = initial_size; - } - else - { - trio_string_destroy(self); - self = NULL; - } - } - return self; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Deallocate the dynamic string and its contents. - - @param self Dynamic string -*/ -TRIO_STRING_PUBLIC void -trio_string_destroy -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self) - { - trio_destroy(self->content); - TRIO_FREE(self); - } -} - - -#if !defined(TRIO_MINIMAL) -/** - Get a pointer to the content. - - @param self Dynamic string. - @param offset Offset into content. - @return Pointer to the content. - - @p Offset can be zero, positive, or negative. If @p offset is zero, - then the start of the content will be returned. If @p offset is positive, - then a pointer to @p offset number of characters from the beginning of the - content is returned. If @p offset is negative, then a pointer to @p offset - number of characters from the ending of the string, starting at the - terminating zero, is returned. -*/ -TRIO_STRING_PUBLIC char * -trio_string_get -TRIO_ARGS2((self, offset), - trio_string_t *self, - int offset) -{ - char *result = NULL; - - assert(self); - - if (self->content != NULL) - { - if (self->length == 0) - { - (void)trio_string_length(self); - } - if (offset >= 0) - { - if (offset > (int)self->length) - { - offset = self->length; - } - } - else - { - offset += self->length + 1; - if (offset < 0) - { - offset = 0; - } - } - result = &(self->content[offset]); - } - return result; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Extract the content. - - @param self Dynamic String - @return Content of dynamic string. - - The content is removed from the dynamic string. This enables destruction - of the dynamic string without deallocation of the content. -*/ -TRIO_STRING_PUBLIC char * -trio_string_extract -TRIO_ARGS1((self), - trio_string_t *self) -{ - char *result; - - assert(self); - - result = self->content; - /* FIXME: Allocate new empty buffer? */ - self->content = NULL; - self->length = self->allocated = 0; - return result; -} - - -#if !defined(TRIO_MINIMAL) -/** - Set the content of the dynamic string. - - @param self Dynamic String - @param buffer The new content. - - Sets the content of the dynamic string to a copy @p buffer. - An existing content will be deallocated first, if necessary. - - @remark - This function will make a copy of @p buffer. - You are responsible for deallocating @p buffer yourself. -*/ -TRIO_STRING_PUBLIC void -trio_xstring_set -TRIO_ARGS2((self, buffer), - trio_string_t *self, - char *buffer) -{ - assert(self); - - trio_destroy(self->content); - self->content = trio_duplicate(buffer); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_string_size - */ -TRIO_STRING_PUBLIC int -trio_string_size -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return self->allocated; -} - - -/* - * trio_string_terminate - */ -TRIO_STRING_PUBLIC void -trio_string_terminate -TRIO_ARGS1((self), - trio_string_t *self) -{ - trio_xstring_append_char(self, 0); -} - - -#if !defined(TRIO_MINIMAL) -/** - Append the second string to the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_string_append -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + other->length; - if (!TrioStringGrowTo(self, length)) - goto error; - trio_copy(&self->content[self->length], other->content); - self->length = length; - return TRUE; - - error: - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_append - */ -TRIO_STRING_PUBLIC int -trio_xstring_append -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + trio_length(other); - if (!TrioStringGrowTo(self, length)) - goto error; - trio_copy(&self->content[self->length], other); - self->length = length; - return TRUE; - - error: - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_xstring_append_char - */ -TRIO_STRING_PUBLIC int -trio_xstring_append_char -TRIO_ARGS2((self, character), - trio_string_t *self, - char character) -{ - assert(self); - - if ((int)self->length >= trio_string_size(self)) - { - if (!TrioStringGrow(self, 0)) - goto error; - } - self->content[self->length] = character; - self->length++; - return TRUE; - - error: - return FALSE; -} - - -#if !defined(TRIO_MINIMAL) -/** - Search for the first occurrence of second parameter in the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_string_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_contains - */ -TRIO_STRING_PUBLIC int -trio_xstring_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_copy - */ -TRIO_STRING_PUBLIC int -trio_string_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_string_append(self, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_copy - */ -TRIO_STRING_PUBLIC int -trio_xstring_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_xstring_append(self, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_duplicate - */ -TRIO_STRING_PUBLIC trio_string_t * -trio_string_duplicate -TRIO_ARGS1((other), - trio_string_t *other) -{ - trio_string_t *self; - - assert(other); - - self = TrioStringAlloc(); - if (self) - { - self->content = TrioDuplicateMax(other->content, other->length); - if (self->content) - { - self->length = other->length; - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_xstring_duplicate - */ -TRIO_STRING_PUBLIC trio_string_t * -trio_xstring_duplicate -TRIO_ARGS1((other), - TRIO_CONST char *other) -{ - trio_string_t *self; - - assert(other); - - self = TrioStringAlloc(); - if (self) - { - self->content = TrioDuplicateMax(other, trio_length(other)); - if (self->content) - { - self->length = trio_length(self->content); - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal - */ -TRIO_STRING_PUBLIC int -trio_string_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_max - */ -TRIO_STRING_PUBLIC int -trio_string_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_max - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_case - */ -TRIO_STRING_PUBLIC int -trio_string_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_case - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_case_max - */ -TRIO_STRING_PUBLIC int -trio_string_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_case_max - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) -/* - * trio_string_format_data_max - */ -TRIO_STRING_PUBLIC size_t -trio_string_format_date_max -TRIO_ARGS4((self, max, format, datetime), - trio_string_t *self, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(self); - - return trio_format_date_max(self->content, max, format, datetime); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_index - */ -TRIO_STRING_PUBLIC char * -trio_string_index -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index(self->content, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_index_last - */ -TRIO_STRING_PUBLIC char * -trio_string_index_last -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index_last(self->content, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_length - */ -TRIO_STRING_PUBLIC int -trio_string_length -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self->length == 0) - { - self->length = trio_length(self->content); - } - return self->length; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_lower - */ -TRIO_STRING_PUBLIC int -trio_string_lower -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_lower(self->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_match - */ -TRIO_STRING_PUBLIC int -trio_string_match -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_match - */ -TRIO_STRING_PUBLIC int -trio_xstring_match -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_match_case - */ -TRIO_STRING_PUBLIC int -trio_string_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_match_case - */ -TRIO_STRING_PUBLIC int -trio_xstring_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_substring - */ -TRIO_STRING_PUBLIC char * -trio_string_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_substring - */ -TRIO_STRING_PUBLIC char * -trio_xstring_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_upper - */ -TRIO_STRING_PUBLIC int -trio_string_upper -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_upper(self->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - -/** @} End of DynamicStrings */ diff --git a/triostr.h b/triostr.h deleted file mode 100644 index 0a0e71a..0000000 --- a/triostr.h +++ /dev/null @@ -1,144 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_TRIOSTR_H -#define TRIO_TRIOSTR_H - -#include -#include -#include -#include -#include "triodef.h" -#include "triop.h" - -enum { - TRIO_HASH_NONE = 0, - TRIO_HASH_PLAIN, - TRIO_HASH_TWOSIGNED -}; - -#if !defined(TRIO_STRING_PUBLIC) -# if !defined(TRIO_PUBLIC) -# define TRIO_PUBLIC -# endif -# define TRIO_STRING_PUBLIC TRIO_PUBLIC -#endif - -/************************************************************************* - * String functions - */ - -TRIO_STRING_PUBLIC int trio_copy_max TRIO_PROTO((char *target, size_t max, const char *source)); -TRIO_STRING_PUBLIC char *trio_create TRIO_PROTO((size_t size)); -TRIO_STRING_PUBLIC void trio_destroy TRIO_PROTO((char *string)); -TRIO_STRING_PUBLIC char *trio_duplicate TRIO_PROTO((const char *source)); -TRIO_STRING_PUBLIC int trio_equal TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_case TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_locale TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_max TRIO_PROTO((const char *first, size_t max, const char *second)); -TRIO_STRING_PUBLIC TRIO_CONST char *trio_error TRIO_PROTO((int)); -TRIO_STRING_PUBLIC size_t trio_length TRIO_PROTO((const char *string)); -TRIO_STRING_PUBLIC double trio_to_double TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC long trio_to_long TRIO_PROTO((const char *source, char **endp, int base)); -TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC int trio_to_upper TRIO_PROTO((int source)); - -#if !defined(TRIO_MINIMAL) - -TRIO_STRING_PUBLIC int trio_append TRIO_PROTO((char *target, const char *source)); -TRIO_STRING_PUBLIC int trio_append_max TRIO_PROTO((char *target, size_t max, const char *source)); -TRIO_STRING_PUBLIC int trio_contains TRIO_PROTO((const char *string, const char *substring)); -TRIO_STRING_PUBLIC int trio_copy TRIO_PROTO((char *target, const char *source)); -TRIO_STRING_PUBLIC char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max)); -TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second)); -#if !defined(_WIN32_WCE) -TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime)); -#endif -TRIO_STRING_PUBLIC unsigned long trio_hash TRIO_PROTO((const char *string, int type)); -TRIO_STRING_PUBLIC char *trio_index TRIO_PROTO((const char *string, int character)); -TRIO_STRING_PUBLIC char *trio_index_last TRIO_PROTO((const char *string, int character)); -TRIO_STRING_PUBLIC int trio_lower TRIO_PROTO((char *target)); -TRIO_STRING_PUBLIC int trio_match TRIO_PROTO((const char *string, const char *pattern)); -TRIO_STRING_PUBLIC int trio_match_case TRIO_PROTO((const char *string, const char *pattern)); -TRIO_STRING_PUBLIC size_t trio_span_function TRIO_PROTO((char *target, const char *source, int (*Function) TRIO_PROTO((int)))); -TRIO_STRING_PUBLIC char *trio_substring TRIO_PROTO((const char *string, const char *substring)); -TRIO_STRING_PUBLIC char *trio_substring_max TRIO_PROTO((const char *string, size_t max, const char *substring)); -TRIO_STRING_PUBLIC float trio_to_float TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC int trio_to_lower TRIO_PROTO((int source)); -TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long TRIO_PROTO((const char *source, char **endp, int base)); -TRIO_STRING_PUBLIC char *trio_tokenize TRIO_PROTO((char *string, const char *delimiters)); -TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target)); - -#endif /* !defined(TRIO_MINIMAL) */ - -/************************************************************************* - * Dynamic string functions - */ - -/* - * Opaque type for dynamic strings - */ - -typedef struct _trio_string_t trio_string_t; - -TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC char *trio_string_extract TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_size TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC void trio_string_terminate TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character)); -TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other)); - -#if !defined(TRIO_MINIMAL) - -TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size)); -TRIO_STRING_PUBLIC char *trio_string_get TRIO_PROTO((trio_string_t *self, int offset)); -TRIO_STRING_PUBLIC void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer)); - -TRIO_STRING_PUBLIC int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC trio_string_t *trio_string_duplicate TRIO_PROTO((trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second)); -TRIO_STRING_PUBLIC int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other)); -#if !defined(_WIN32_WCE) -TRIO_STRING_PUBLIC size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, const char *format, const struct tm *datetime)); -#endif -TRIO_STRING_PUBLIC char *trio_string_index TRIO_PROTO((trio_string_t *self, int character)); -TRIO_STRING_PUBLIC char *trio_string_index_last TRIO_PROTO((trio_string_t *self, int character)); -TRIO_STRING_PUBLIC int trio_string_length TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_lower TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC char *trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_upper TRIO_PROTO((trio_string_t *self)); - -TRIO_STRING_PUBLIC int trio_xstring_append TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_contains TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_copy TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_match TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC char *trio_xstring_substring TRIO_PROTO((trio_string_t *self, const char *other)); - -#endif /* !defined(TRIO_MINIMAL) */ - -#endif /* TRIO_TRIOSTR_H */ diff --git a/uri.c b/uri.c index 03b5a31..370b449 100644 --- a/uri.c +++ b/uri.c @@ -37,23 +37,6 @@ #define PORT_EMPTY 0 #define PORT_EMPTY_SERVER -1 -static void -xmlURIErrMemory(const char *extra) -{ - if (extra) - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_URI, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, - extra, NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_URI, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, - NULL, NULL, NULL, 0, 0, - "Memory allocation failed\n"); -} - static void xmlCleanURI(xmlURIPtr uri); /* @@ -68,7 +51,6 @@ static void xmlCleanURI(xmlURIPtr uri); * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | * "u" | "v" | "w" | "x" | "y" | "z" */ - #define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z')) /* @@ -89,7 +71,6 @@ static void xmlCleanURI(xmlURIPtr uri); /* * alphanum = alpha | digit */ - #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) /* @@ -103,16 +84,15 @@ static void xmlCleanURI(xmlURIPtr uri); /* * unwise = "{" | "}" | "|" | "\" | "^" | "`" */ - #define IS_UNWISE(p) \ (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ ((*(p) == ']')) || ((*(p) == '`'))) + /* * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | * "[" | "]" */ - #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ @@ -121,13 +101,11 @@ static void xmlCleanURI(xmlURIPtr uri); /* * unreserved = alphanum | mark */ - #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) /* * Skip to next pointer char, handle escaped sequences */ - #define NEXT(p) ((*p == '%')? p += 3 : p++) /* @@ -139,7 +117,6 @@ static void xmlCleanURI(xmlURIPtr uri); * * path = [ abs_path | opaque_part ] */ - #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) /************************************************************************ @@ -181,7 +158,7 @@ static void xmlCleanURI(xmlURIPtr uri); /* * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" */ -#define ISA_UNRESERVED(p) \ +#define ISA_STRICTLY_UNRESERVED(p) \ ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \ ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~'))) @@ -194,10 +171,47 @@ static void xmlCleanURI(xmlURIPtr uri); /* * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" */ -#define ISA_PCHAR(p) \ - (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ +#define ISA_PCHAR(u, p) \ + (ISA_UNRESERVED(u, p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ ((*(p) == ':')) || ((*(p) == '@'))) +/* + * From https://www.w3.org/TR/leiri/ + * + * " " / "<" / ">" / '"' / "{" / "}" / "|" + * / "\" / "^" / "`" / %x0-1F / %x7F-D7FF + * / %xE000-FFFD / %x10000-10FFFF + */ +#define ISA_UCSCHAR(p) \ + ((*(p) <= 0x20) || (*(p) >= 0x7F) || (*(p) == '<') || (*(p) == '>') || \ + (*(p) == '"') || (*(p) == '{') || (*(p) == '}') || (*(p) == '|') || \ + (*(p) == '\\') || (*(p) == '^') || (*(p) == '`')) + +#define ISA_UNRESERVED(u, p) (xmlIsUnreserved(u, p)) + +#define XML_URI_ALLOW_UNWISE 1 +#define XML_URI_NO_UNESCAPE 2 +#define XML_URI_ALLOW_UCSCHAR 4 + +static int +xmlIsUnreserved(xmlURIPtr uri, const char *cur) { + if (uri == NULL) + return(0); + + if (ISA_STRICTLY_UNRESERVED(cur)) + return(1); + + if (uri->cleanup & XML_URI_ALLOW_UNWISE) { + if (IS_UNWISE(cur)) + return(1); + } else if (uri->cleanup & XML_URI_ALLOW_UCSCHAR) { + if (ISA_UCSCHAR(cur)) + return(1); + } + + return(0); +} + /** * xmlParse3986Scheme: * @uri: pointer to an URI structure @@ -213,18 +227,17 @@ static int xmlParse3986Scheme(xmlURIPtr uri, const char **str) { const char *cur; - if (str == NULL) - return(-1); - cur = *str; if (!ISA_ALPHA(cur)) - return(2); + return(1); cur++; while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; if (uri != NULL) { if (uri->scheme != NULL) xmlFree(uri->scheme); uri->scheme = STRNDUP(*str, cur - *str); + if (uri->scheme == NULL) + return(-1); } *str = cur; return(0); @@ -250,22 +263,20 @@ xmlParse3986Fragment(xmlURIPtr uri, const char **str) { const char *cur; - if (str == NULL) - return (-1); - cur = *str; - while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || - (*cur == '[') || (*cur == ']') || - ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?') || + (*cur == '[') || (*cur == ']')) NEXT(cur); if (uri != NULL) { if (uri->fragment != NULL) xmlFree(uri->fragment); - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->fragment = STRNDUP(*str, cur - *str); else uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->fragment == NULL) + return (-1); } *str = cur; return (0); @@ -287,21 +298,19 @@ xmlParse3986Query(xmlURIPtr uri, const char **str) { const char *cur; - if (str == NULL) - return (-1); - cur = *str; - while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || - ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?')) NEXT(cur); if (uri != NULL) { if (uri->query != NULL) xmlFree(uri->query); - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->query = STRNDUP(*str, cur - *str); else uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->query == NULL) + return (-1); /* Save the raw bytes of the query as well. * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 @@ -309,6 +318,8 @@ xmlParse3986Query(xmlURIPtr uri, const char **str) if (uri->query_raw != NULL) xmlFree (uri->query_raw); uri->query_raw = STRNDUP (*str, cur - *str); + if (uri->query_raw == NULL) + return (-1); } *str = cur; return (0); @@ -371,16 +382,18 @@ xmlParse3986Userinfo(xmlURIPtr uri, const char **str) const char *cur; cur = *str; - while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || + while (ISA_UNRESERVED(uri, cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur) || (*cur == ':')) NEXT(cur); if (*cur == '@') { if (uri != NULL) { if (uri->user != NULL) xmlFree(uri->user); - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->user = STRNDUP(*str, cur - *str); else uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->user == NULL) + return(-1); } *str = cur; return(0); @@ -485,7 +498,8 @@ xmlParse3986Host(xmlURIPtr uri, const char **str) /* * then this should be a hostname which can be empty */ - while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) + while (ISA_UNRESERVED(uri, cur) || + ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) NEXT(cur); found: if (uri != NULL) { @@ -493,10 +507,12 @@ xmlParse3986Host(xmlURIPtr uri, const char **str) uri->authority = NULL; if (uri->server != NULL) xmlFree(uri->server); if (cur != host) { - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->server = STRNDUP(host, cur - host); else uri->server = xmlURIUnescapeString(host, cur - host, NULL); + if (uri->server == NULL) + return(-1); } else uri->server = NULL; } @@ -527,6 +543,8 @@ xmlParse3986Authority(xmlURIPtr uri, const char **str) * try to parse an userinfo and check for the trailing @ */ ret = xmlParse3986Userinfo(uri, &cur); + if (ret < 0) + return(ret); if ((ret != 0) || (*cur != '@')) cur = *str; else @@ -559,17 +577,17 @@ xmlParse3986Authority(xmlURIPtr uri, const char **str) * Returns 0 or the error code */ static int -xmlParse3986Segment(const char **str, char forbid, int empty) +xmlParse3986Segment(xmlURIPtr uri, const char **str, char forbid, int empty) { const char *cur; cur = *str; - if (!ISA_PCHAR(cur)) { + if (!ISA_PCHAR(uri, cur)) { if (empty) return(0); return(1); } - while (ISA_PCHAR(cur) && (*cur != forbid)) + while (ISA_PCHAR(uri, cur) && (*cur != forbid)) NEXT(cur); *str = cur; return (0); @@ -597,16 +615,18 @@ xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str) while (*cur == '/') { cur++; - ret = xmlParse3986Segment(&cur, 0, 1); + ret = xmlParse3986Segment(uri, &cur, 0, 1); if (ret != 0) return(ret); } if (uri != NULL) { if (uri->path != NULL) xmlFree(uri->path); if (*str != cur) { - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->path = STRNDUP(*str, cur - *str); else uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->path == NULL) + return (-1); } else { uri->path = NULL; } @@ -638,21 +658,23 @@ xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str) if (*cur != '/') return(1); cur++; - ret = xmlParse3986Segment(&cur, 0, 0); + ret = xmlParse3986Segment(uri, &cur, 0, 0); if (ret == 0) { while (*cur == '/') { cur++; - ret = xmlParse3986Segment(&cur, 0, 1); + ret = xmlParse3986Segment(uri, &cur, 0, 1); if (ret != 0) return(ret); } } if (uri != NULL) { if (uri->path != NULL) xmlFree(uri->path); if (cur != *str) { - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->path = STRNDUP(*str, cur - *str); else uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->path == NULL) + return (-1); } else { uri->path = NULL; } @@ -681,20 +703,22 @@ xmlParse3986PathRootless(xmlURIPtr uri, const char **str) cur = *str; - ret = xmlParse3986Segment(&cur, 0, 0); + ret = xmlParse3986Segment(uri, &cur, 0, 0); if (ret != 0) return(ret); while (*cur == '/') { cur++; - ret = xmlParse3986Segment(&cur, 0, 1); + ret = xmlParse3986Segment(uri, &cur, 0, 1); if (ret != 0) return(ret); } if (uri != NULL) { if (uri->path != NULL) xmlFree(uri->path); if (cur != *str) { - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->path = STRNDUP(*str, cur - *str); else uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->path == NULL) + return (-1); } else { uri->path = NULL; } @@ -723,20 +747,22 @@ xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str) cur = *str; - ret = xmlParse3986Segment(&cur, ':', 0); + ret = xmlParse3986Segment(uri, &cur, ':', 0); if (ret != 0) return(ret); while (*cur == '/') { cur++; - ret = xmlParse3986Segment(&cur, 0, 1); + ret = xmlParse3986Segment(uri, &cur, 0, 1); if (ret != 0) return(ret); } if (uri != NULL) { if (uri->path != NULL) xmlFree(uri->path); if (cur != *str) { - if (uri->cleanup & 2) + if (uri->cleanup & XML_URI_NO_UNESCAPE) uri->path = STRNDUP(*str, cur - *str); else uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); + if (uri->path == NULL) + return (-1); } else { uri->path = NULL; } @@ -784,7 +810,7 @@ xmlParse3986HierPart(xmlURIPtr uri, const char **str) } else if (*cur == '/') { ret = xmlParse3986PathAbsolute(uri, &cur); if (ret != 0) return(ret); - } else if (ISA_PCHAR(cur)) { + } else if (ISA_PCHAR(uri, cur)) { ret = xmlParse3986PathRootless(uri, &cur); if (ret != 0) return(ret); } else { @@ -827,7 +853,7 @@ xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) { } else if (*str == '/') { ret = xmlParse3986PathAbsolute(uri, &str); if (ret != 0) return(ret); - } else if (ISA_PCHAR(str)) { + } else if (ISA_PCHAR(uri, str)) { ret = xmlParse3986PathNoScheme(uri, &str); if (ret != 0) return(ret); } else { @@ -922,6 +948,8 @@ xmlParse3986URIReference(xmlURIPtr uri, const char *str) { * it fails. */ ret = xmlParse3986URI(uri, str); + if (ret < 0) + return(ret); if (ret != 0) { xmlCleanURI(uri); ret = xmlParse3986RelativeRef(uri, str); @@ -934,30 +962,58 @@ xmlParse3986URIReference(xmlURIPtr uri, const char *str) { } /** - * xmlParseURI: + * xmlParseURISafe: * @str: the URI string to analyze + * @uriOut: optional pointer to parsed URI * * Parse an URI based on RFC 3986 * * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] * - * Returns a newly built xmlURIPtr or NULL in case of error + * Available since 2.13.0. + * + * Returns 0 on success, an error code (typically 1) if the URI is invalid + * or -1 if a memory allocation failed. */ -xmlURIPtr -xmlParseURI(const char *str) { +int +xmlParseURISafe(const char *str, xmlURIPtr *uriOut) { xmlURIPtr uri; int ret; + if (uriOut == NULL) + return(1); + *uriOut = NULL; if (str == NULL) - return(NULL); + return(1); + uri = xmlCreateURI(); - if (uri != NULL) { - ret = xmlParse3986URIReference(uri, str); - if (ret) { - xmlFreeURI(uri); - return(NULL); - } + if (uri == NULL) + return(-1); + + ret = xmlParse3986URIReference(uri, str); + if (ret) { + xmlFreeURI(uri); + return(ret); } + + *uriOut = uri; + return(0); +} + +/** + * xmlParseURI: + * @str: the URI string to analyze + * + * Parse an URI based on RFC 3986 + * + * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + * + * Returns a newly built xmlURIPtr or NULL in case of error + */ +xmlURIPtr +xmlParseURI(const char *str) { + xmlURIPtr uri; + xmlParseURISafe(str, &uri); return(uri); } @@ -999,7 +1055,7 @@ xmlParseURIRaw(const char *str, int raw) { uri = xmlCreateURI(); if (uri != NULL) { if (raw) { - uri->cleanup |= 2; + uri->cleanup |= XML_URI_NO_UNESCAPE; } ret = xmlParseURIReference(uri, str); if (ret) { @@ -1028,10 +1084,8 @@ xmlCreateURI(void) { xmlURIPtr ret; ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI)); - if (ret == NULL) { - xmlURIErrMemory("creating URI structure\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlURI)); ret->port = PORT_EMPTY; return(ret); @@ -1048,16 +1102,12 @@ xmlSaveUriRealloc(xmlChar *ret, int *max) { xmlChar *temp; int tmp; - if (*max > MAX_URI_LENGTH) { - xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n"); + if (*max > MAX_URI_LENGTH) return(NULL); - } tmp = *max * 2; temp = (xmlChar *) xmlRealloc(ret, (tmp + 1)); - if (temp == NULL) { - xmlURIErrMemory("saving URI\n"); + if (temp == NULL) return(NULL); - } *max = tmp; return(temp); } @@ -1083,10 +1133,8 @@ xmlSaveUri(xmlURIPtr uri) { max = 80; ret = (xmlChar *) xmlMallocAtomic(max + 1); - if (ret == NULL) { - xmlURIErrMemory("saving URI\n"); + if (ret == NULL) return(NULL); - } len = 0; if (uri->scheme != NULL) { @@ -1414,195 +1462,136 @@ xmlFreeURI(xmlURIPtr uri) { * * ************************************************************************/ +static int +xmlIsPathSeparator(int c, int isFile) { + (void) isFile; + + if (c == '/') + return(1); + +#ifdef _WIN32 + if (isFile && (c == '\\')) + return(1); +#endif + + return(0); +} + /** - * xmlNormalizeURIPath: + * xmlNormalizePath: * @path: pointer to the path string + * @isFile: true for filesystem paths, false for URIs * - * Applies the 5 normalization steps to a path string--that is, RFC 2396 - * Section 5.2, steps 6.c through 6.g. - * - * Normalization occurs directly on the string, no new allocation is done + * Normalize a filesystem path or URI. * * Returns 0 or an error code */ -int -xmlNormalizeURIPath(char *path) { +static int +xmlNormalizePath(char *path, int isFile) { char *cur, *out; + int numSeg = 0; if (path == NULL) return(-1); - /* Skip all initial "/" chars. We want to get to the beginning of the - * first non-empty segment. - */ cur = path; - while (cur[0] == '/') - ++cur; - if (cur[0] == '\0') - return(0); - - /* Keep everything we've seen so far. */ - out = cur; - - /* - * Analyze each segment in sequence for cases (c) and (d). - */ - while (cur[0] != '\0') { - /* - * c) All occurrences of "./", where "." is a complete path segment, - * are removed from the buffer string. - */ - if ((cur[0] == '.') && (cur[1] == '/')) { - cur += 2; - /* '//' normalization should be done at this point too */ - while (cur[0] == '/') - cur++; - continue; - } + out = path; - /* - * d) If the buffer string ends with "." as a complete path segment, - * that "." is removed. - */ - if ((cur[0] == '.') && (cur[1] == '\0')) - break; - - /* Otherwise keep the segment. */ - while (cur[0] != '/') { - if (cur[0] == '\0') - goto done_cd; - (out++)[0] = (cur++)[0]; - } - /* normalize // */ - while ((cur[0] == '/') && (cur[1] == '/')) - cur++; + if (*cur == 0) + return(0); - (out++)[0] = (cur++)[0]; + if (xmlIsPathSeparator(*cur, isFile)) { + cur++; + *out++ = '/'; } - done_cd: - out[0] = '\0'; - - /* Reset to the beginning of the first segment for the next sequence. */ - cur = path; - while (cur[0] == '/') - ++cur; - if (cur[0] == '\0') - return(0); - - /* - * Analyze each segment in sequence for cases (e) and (f). - * - * e) All occurrences of "/../", where is a - * complete path segment not equal to "..", are removed from the - * buffer string. Removal of these path segments is performed - * iteratively, removing the leftmost matching pattern on each - * iteration, until no matching pattern remains. - * - * f) If the buffer string ends with "/..", where - * is a complete path segment not equal to "..", that - * "/.." is removed. - * - * To satisfy the "iterative" clause in (e), we need to collapse the - * string every time we find something that needs to be removed. Thus, - * we don't need to keep two pointers into the string: we only need a - * "current position" pointer. - */ - while (1) { - char *segp, *tmp; - - /* At the beginning of each iteration of this loop, "cur" points to - * the first character of the segment we want to examine. - */ - - /* Find the end of the current segment. */ - segp = cur; - while ((segp[0] != '/') && (segp[0] != '\0')) - ++segp; - /* If this is the last segment, we're done (we need at least two - * segments to meet the criteria for the (e) and (f) cases). - */ - if (segp[0] == '\0') - break; - - /* If the first segment is "..", or if the next segment _isn't_ "..", - * keep this segment and try the next one. + while (*cur != 0) { + /* + * At this point, out is either empty or ends with a separator. + * Collapse multiple separators first. */ - ++segp; - if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3)) - || ((segp[0] != '.') || (segp[1] != '.') - || ((segp[2] != '/') && (segp[2] != '\0')))) { - cur = segp; - continue; + while (xmlIsPathSeparator(*cur, isFile)) { +#ifdef _WIN32 + /* Allow two separators at start of path */ + if ((isFile) && (out == path + 1)) + *out++ = '/'; +#endif + cur++; } - /* If we get here, remove this segment and the next one and back up - * to the previous segment (if there is one), to implement the - * "iteratively" clause. It's pretty much impossible to back up - * while maintaining two pointers into the buffer, so just compact - * the whole buffer now. - */ + if (*cur == '.') { + if (cur[1] == 0) { + /* Ignore "." at end of path */ + break; + } else if (xmlIsPathSeparator(cur[1], isFile)) { + /* Skip "./" */ + cur += 2; + continue; + } else if ((cur[1] == '.') && + ((cur[2] == 0) || xmlIsPathSeparator(cur[2], isFile))) { + if (numSeg > 0) { + /* Handle ".." by removing last segment */ + do { + out--; + } while ((out > path) && + !xmlIsPathSeparator(out[-1], isFile)); + numSeg--; + + if (cur[2] == 0) + break; + cur += 3; + continue; + } else if (out[0] == '/') { + /* Ignore extraneous ".." in absolute paths */ + if (cur[2] == 0) + break; + cur += 3; + continue; + } else { + /* Keep "../" at start of relative path */ + numSeg--; + } + } + } - /* If this is the end of the buffer, we're done. */ - if (segp[2] == '\0') { - cur[0] = '\0'; - break; + /* Copy segment */ + while ((*cur != 0) && !xmlIsPathSeparator(*cur, isFile)) { + *out++ = *cur++; } - /* Valgrind complained, strcpy(cur, segp + 3); */ - /* string will overlap, do not use strcpy */ - tmp = cur; - segp += 3; - while ((*tmp++ = *segp++) != 0) - ; - - /* If there are no previous segments, then keep going from here. */ - segp = cur; - while ((segp > path) && ((--segp)[0] == '/')) - ; - if (segp == path) - continue; - - /* "segp" is pointing to the end of a previous segment; find it's - * start. We need to back up to the previous segment and start - * over with that to handle things like "foo/bar/../..". If we - * don't do this, then on the first pass we'll remove the "bar/..", - * but be pointing at the second ".." so we won't realize we can also - * remove the "foo/..". - */ - cur = segp; - while ((cur > path) && (cur[-1] != '/')) - --cur; - } - out[0] = '\0'; - /* - * g) If the resulting buffer string still begins with one or more - * complete path segments of "..", then the reference is - * considered to be in error. Implementations may handle this - * error by retaining these components in the resolved path (i.e., - * treating them as part of the final URI), by removing them from - * the resolved path (i.e., discarding relative levels above the - * root), or by avoiding traversal of the reference. - * - * We discard them from the final path. - */ - if (path[0] == '/') { - cur = path; - while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.') - && ((cur[3] == '/') || (cur[3] == '\0'))) - cur += 3; + /* Copy separator */ + if (*cur != 0) { + cur++; + *out++ = '/'; + } - if (cur != path) { - out = path; - while (cur[0] != '\0') - (out++)[0] = (cur++)[0]; - out[0] = 0; - } + numSeg++; } + /* Keep "." if output is empty and it's a file */ + if ((isFile) && (out <= path)) + *out++ = '.'; + *out = 0; + return(0); } +/** + * xmlNormalizeURIPath: + * @path: pointer to the path string + * + * Applies the 5 normalization steps to a path string--that is, RFC 2396 + * Section 5.2, steps 6.c through 6.g. + * + * Normalization occurs directly on the string, no new allocation is done + * + * Returns 0 or an error code + */ +int +xmlNormalizeURIPath(char *path) { + return(xmlNormalizePath(path, 0)); +} + static int is_hex(char c) { if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || @@ -1637,10 +1626,8 @@ xmlURIUnescapeString(const char *str, int len, char *target) { if (target == NULL) { ret = (char *) xmlMallocAtomic(len + 1); - if (ret == NULL) { - xmlURIErrMemory("unescaping URI value\n"); + if (ret == NULL) return(NULL); - } } else ret = target; in = str; @@ -1680,8 +1667,9 @@ xmlURIUnescapeString(const char *str, int len, char *target) { * @str: string to escape * @list: exception list string of chars not to escape * - * This routine escapes a string to hex, ignoring reserved characters - * (a-z, A-Z, 0-9, "@-_.!~*'()") and the characters in the exception list. + * This routine escapes a string to hex, ignoring unreserved characters + * a-z, A-Z, 0-9, "-._~", a few sub-delims "!*'()", the gen-delim "@" + * (why?) and the characters in the exception list. * * Returns a new escaped string or NULL in case of error. */ @@ -1697,25 +1685,24 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { if (str[0] == 0) return(xmlStrdup(str)); len = xmlStrlen(str); - if (!(len > 0)) return(NULL); len += 20; ret = (xmlChar *) xmlMallocAtomic(len); - if (ret == NULL) { - xmlURIErrMemory("escaping URI value\n"); + if (ret == NULL) return(NULL); - } in = (const xmlChar *) str; out = 0; while(*in != 0) { if (len - out <= 3) { - temp = xmlSaveUriRealloc(ret, &len); + if (len > INT_MAX / 2) + return(NULL); + temp = xmlRealloc(ret, len * 2); if (temp == NULL) { - xmlURIErrMemory("escaping URI value\n"); xmlFree(ret); return(NULL); } ret = temp; + len *= 2; } ch = *in; @@ -1773,7 +1760,7 @@ xmlURIEscape(const xmlChar * str) /* * Allow escaping errors in the unescaped form */ - uri->cleanup = 1; + uri->cleanup = XML_URI_ALLOW_UNWISE; ret2 = xmlParseURIReference(uri, (const char *)str); if (ret2) { xmlFreeURI(uri); @@ -1787,7 +1774,6 @@ xmlURIEscape(const xmlChar * str) ret = NULL; #define NULLCHK(p) if(!p) { \ - xmlURIErrMemory("escaping URI value\n"); \ xmlFreeURI(uri); \ xmlFree(ret); \ return NULL; } \ @@ -1883,10 +1869,132 @@ xmlURIEscape(const xmlChar * str) * * ************************************************************************/ +static int +xmlIsAbsolutePath(const xmlChar *path) { + int c = path[0]; + + if (xmlIsPathSeparator(c, 1)) + return(1); + +#ifdef _WIN32 + if ((((c >= 'A') && (c <= 'Z')) || + ((c >= 'a') && (c <= 'z'))) && + (path[1] == ':')) + return(1); +#endif + + return(0); +} + /** - * xmlBuildURI: + * xmlResolvePath: + * @ref: the filesystem path + * @base: the base value + * @out: pointer to result URI + * + * Resolves a filesystem path from a base path. + * + * Returns 0 on success, -1 if a memory allocation failed or an error + * code if URI or base are invalid. + */ +static int +xmlResolvePath(const xmlChar *escRef, const xmlChar *base, xmlChar **out) { + const xmlChar *fragment; + xmlChar *tmp = NULL; + xmlChar *ref = NULL; + xmlChar *result = NULL; + int ret = -1; + int i; + + if (out == NULL) + return(1); + *out = NULL; + + if ((escRef == NULL) || (escRef[0] == 0)) { + if ((base == NULL) || (base[0] == 0)) + return(1); + ref = xmlStrdup(base); + if (ref == NULL) + goto err_memory; + *out = ref; + return(0); + } + + /* + * If a URI is resolved, we can assume it is a valid URI and not + * a filesystem path. This means we have to unescape the part + * before the fragment. + */ + fragment = xmlStrchr(escRef, '#'); + if (fragment != NULL) { + tmp = xmlStrndup(escRef, fragment - escRef); + if (tmp == NULL) + goto err_memory; + escRef = tmp; + } + + ref = (xmlChar *) xmlURIUnescapeString((char *) escRef, -1, NULL); + if (ref == NULL) + goto err_memory; + + if ((base == NULL) || (base[0] == 0)) + goto done; + + if (xmlIsAbsolutePath(ref)) + goto done; + + /* + * Remove last segment from base + */ + i = xmlStrlen(base); + while ((i > 0) && !xmlIsPathSeparator(base[i-1], 1)) + i--; + + /* + * Concatenate base and ref + */ + if (i > 0) { + int refLen = xmlStrlen(ref); + + result = xmlMalloc(i + refLen + 1); + if (result == NULL) + goto err_memory; + + memcpy(result, base, i); + memcpy(result + i, ref, refLen + 1); + } + + /* + * Normalize + */ + xmlNormalizePath((char *) result, 1); + +done: + if (result == NULL) { + result = ref; + ref = NULL; + } + + if (fragment != NULL) { + result = xmlStrcat(result, fragment); + if (result == NULL) + goto err_memory; + } + + *out = result; + ret = 0; + +err_memory: + xmlFree(tmp); + xmlFree(ref); + return(ret); +} + +/** + * xmlBuildURISafe: * @URI: the URI instance found in the document * @base: the base value + * @valPtr: pointer to result URI * * Computes he final URI of the reference done by checking that * the given URI is valid, and building the final URI using the @@ -1895,17 +2003,22 @@ xmlURIEscape(const xmlChar * str) * * 5.2. Resolving Relative References to Absolute Form * - * Returns a new URI string (to be freed by the caller) or NULL in case - * of error. + * Available since 2.13.0. + * + * Returns 0 on success, -1 if a memory allocation failed or an error + * code if URI or base are invalid. */ -xmlChar * -xmlBuildURI(const xmlChar *URI, const xmlChar *base) { +int +xmlBuildURISafe(const xmlChar *URI, const xmlChar *base, xmlChar **valPtr) { xmlChar *val = NULL; int ret, len, indx, cur, out; xmlURIPtr ref = NULL; xmlURIPtr bas = NULL; xmlURIPtr res = NULL; + if (valPtr == NULL) + return(1); + /* * 1) The URI reference is parsed into the potential four components and * fragment identifier, as described in Section 4.3. @@ -1915,17 +2028,11 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * URI. Should we do that here? */ if (URI == NULL) - ret = -1; - else { - if (*URI) { - ref = xmlCreateURI(); - if (ref == NULL) - goto done; - ret = xmlParseURIReference(ref, (const char *) URI); - } - else - ret = 0; - } + ret = 1; + else if (URI[0] != 0) + ret = xmlParseURISafe((const char *) URI, &ref); + else + ret = 0; if (ret != 0) goto done; if ((ref != NULL) && (ref->scheme != NULL)) { @@ -1933,19 +2040,30 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * The URI is absolute don't modify. */ val = xmlStrdup(URI); + if (val == NULL) + ret = -1; goto done; } - if (base == NULL) - ret = -1; - else { - bas = xmlCreateURI(); - if (bas == NULL) - goto done; - ret = xmlParseURIReference(bas, (const char *) base); + + /* + * If base has no scheme or authority, it is assumed to be a + * filesystem path. + */ + if (xmlStrstr(base, BAD_CAST "://") == NULL) { + xmlFreeURI(ref); + return(xmlResolvePath(URI, base, valPtr)); } + + ret = xmlParseURISafe((const char *) base, &bas); + if (ret < 0) + goto done; if (ret != 0) { - if (ref) + if (ref) { + ret = 0; val = xmlSaveUri(ref); + if (val == NULL) + ret = -1; + } goto done; } if (ref == NULL) { @@ -1957,6 +2075,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { bas->fragment = NULL; } val = xmlSaveUri(bas); + if (val == NULL) + ret = -1; goto done; } @@ -1972,35 +2092,62 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * defined while still treating this as a reference to the current * document. */ + ret = -1; res = xmlCreateURI(); if (res == NULL) goto done; if ((ref->scheme == NULL) && (ref->path == NULL) && ((ref->authority == NULL) && (ref->server == NULL) && (ref->port == PORT_EMPTY))) { - if (bas->scheme != NULL) + if (bas->scheme != NULL) { res->scheme = xmlMemStrdup(bas->scheme); - if (bas->authority != NULL) + if (res->scheme == NULL) + goto done; + } + if (bas->authority != NULL) { res->authority = xmlMemStrdup(bas->authority); - else { - if (bas->server != NULL) + if (res->authority == NULL) + goto done; + } else { + if (bas->server != NULL) { res->server = xmlMemStrdup(bas->server); - if (bas->user != NULL) + if (res->server == NULL) + goto done; + } + if (bas->user != NULL) { res->user = xmlMemStrdup(bas->user); + if (res->user == NULL) + goto done; + } res->port = bas->port; } - if (bas->path != NULL) + if (bas->path != NULL) { res->path = xmlMemStrdup(bas->path); - if (ref->query_raw != NULL) + if (res->path == NULL) + goto done; + } + if (ref->query_raw != NULL) { res->query_raw = xmlMemStrdup (ref->query_raw); - else if (ref->query != NULL) + if (res->query_raw == NULL) + goto done; + } else if (ref->query != NULL) { res->query = xmlMemStrdup(ref->query); - else if (bas->query_raw != NULL) + if (res->query == NULL) + goto done; + } else if (bas->query_raw != NULL) { res->query_raw = xmlMemStrdup(bas->query_raw); - else if (bas->query != NULL) + if (res->query_raw == NULL) + goto done; + } else if (bas->query != NULL) { res->query = xmlMemStrdup(bas->query); - if (ref->fragment != NULL) + if (res->query == NULL) + goto done; + } + if (ref->fragment != NULL) { res->fragment = xmlMemStrdup(ref->fragment); + if (res->fragment == NULL) + goto done; + } goto step_7; } @@ -2012,17 +2159,30 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { */ if (ref->scheme != NULL) { val = xmlSaveUri(ref); + if (val != NULL) + ret = 0; goto done; } - if (bas->scheme != NULL) + if (bas->scheme != NULL) { res->scheme = xmlMemStrdup(bas->scheme); + if (res->scheme == NULL) + goto done; + } - if (ref->query_raw != NULL) + if (ref->query_raw != NULL) { res->query_raw = xmlMemStrdup(ref->query_raw); - else if (ref->query != NULL) + if (res->query_raw == NULL) + goto done; + } else if (ref->query != NULL) { res->query = xmlMemStrdup(ref->query); - if (ref->fragment != NULL) + if (res->query == NULL) + goto done; + } + if (ref->fragment != NULL) { res->fragment = xmlMemStrdup(ref->fragment); + if (res->fragment == NULL) + goto done; + } /* * 4) If the authority component is defined, then the reference is a @@ -2033,26 +2193,45 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { */ if ((ref->authority != NULL) || (ref->server != NULL) || (ref->port != PORT_EMPTY)) { - if (ref->authority != NULL) + if (ref->authority != NULL) { res->authority = xmlMemStrdup(ref->authority); - else { - if (ref->server != NULL) + if (res->authority == NULL) + goto done; + } else { + if (ref->server != NULL) { res->server = xmlMemStrdup(ref->server); - if (ref->user != NULL) + if (res->server == NULL) + goto done; + } + if (ref->user != NULL) { res->user = xmlMemStrdup(ref->user); + if (res->user == NULL) + goto done; + } res->port = ref->port; } - if (ref->path != NULL) + if (ref->path != NULL) { res->path = xmlMemStrdup(ref->path); + if (res->path == NULL) + goto done; + } goto step_7; } - if (bas->authority != NULL) + if (bas->authority != NULL) { res->authority = xmlMemStrdup(bas->authority); - else if ((bas->server != NULL) || (bas->port != PORT_EMPTY)) { - if (bas->server != NULL) + if (res->authority == NULL) + goto done; + } else if ((bas->server != NULL) || (bas->port != PORT_EMPTY)) { + if (bas->server != NULL) { res->server = xmlMemStrdup(bas->server); - if (bas->user != NULL) + if (res->server == NULL) + goto done; + } + if (bas->user != NULL) { res->user = xmlMemStrdup(bas->user); + if (res->user == NULL) + goto done; + } res->port = bas->port; } @@ -2062,6 +2241,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { */ if ((ref->path != NULL) && (ref->path[0] == '/')) { res->path = xmlMemStrdup(ref->path); + if (res->path == NULL) + goto done; goto step_7; } @@ -2080,10 +2261,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { if (bas->path != NULL) len += strlen(bas->path); res->path = (char *) xmlMallocAtomic(len); - if (res->path == NULL) { - xmlURIErrMemory("resolving URI against base\n"); + if (res->path == NULL) goto done; - } res->path[0] = 0; /* @@ -2139,6 +2318,8 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * reference. */ val = xmlSaveUri(res); + if (val != NULL) + ret = 0; done: if (ref != NULL) @@ -2147,13 +2328,38 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { xmlFreeURI(bas); if (res != NULL) xmlFreeURI(res); - return(val); + *valPtr = val; + return(ret); } /** - * xmlBuildRelativeURI: + * xmlBuildURI: + * @URI: the URI instance found in the document + * @base: the base value + * + * Computes he final URI of the reference done by checking that + * the given URI is valid, and building the final URI using the + * base URI. This is processed according to section 5.2 of the + * RFC 2396 + * + * 5.2. Resolving Relative References to Absolute Form + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * of error. + */ +xmlChar * +xmlBuildURI(const xmlChar *URI, const xmlChar *base) { + xmlChar *out; + + xmlBuildURISafe(URI, base, &out); + return(out); +} + +/** + * xmlBuildRelativeURISafe: * @URI: the URI reference under consideration * @base: the base value + * @valPtr: pointer to result URI * * Expresses the URI of the reference in terms relative to the * base. Some examples of this operation include: @@ -2179,14 +2385,17 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * since this routine (for reasonable efficiency) assumes URI has * already been through some validation. * - * Returns a new URI string (to be freed by the caller) or NULL in case - * error. + * Available since 2.13.0. + * + * Returns 0 on success, -1 if a memory allocation failed or an error + * code if URI or base are invalid. */ -xmlChar * -xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) +int +xmlBuildRelativeURISafe(const xmlChar * URI, const xmlChar * base, + xmlChar **valPtr) { xmlChar *val = NULL; - int ret; + int ret = 0; int ix; int nbslash = 0; int len; @@ -2195,39 +2404,58 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) xmlChar *bptr, *uptr, *vptr; int remove_path = 0; + if (valPtr == NULL) + return(1); + *valPtr = NULL; if ((URI == NULL) || (*URI == 0)) - return NULL; + return(1); /* * First parse URI into a standard form */ ref = xmlCreateURI (); - if (ref == NULL) - return NULL; + if (ref == NULL) { + ret = -1; + goto done; + } /* If URI not already in "relative" form */ if (URI[0] != '.') { ret = xmlParseURIReference (ref, (const char *) URI); if (ret != 0) goto done; /* Error in URI, return NULL */ - } else + } else { ref->path = (char *)xmlStrdup(URI); + if (ref->path == NULL) { + ret = -1; + goto done; + } + } /* * Next parse base into the same standard form */ if ((base == NULL) || (*base == 0)) { val = xmlStrdup (URI); + if (val == NULL) + ret = -1; goto done; } bas = xmlCreateURI (); - if (bas == NULL) + if (bas == NULL) { + ret = -1; goto done; + } if (base[0] != '.') { ret = xmlParseURIReference (bas, (const char *) base); if (ret != 0) goto done; /* Error in base, return NULL */ - } else + } else { bas->path = (char *)xmlStrdup(base); + if (bas->path == NULL) { + ret = -1; + goto done; + } + } /* * If the scheme / server on the URI differs from the base, @@ -2239,14 +2467,20 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)) || (bas->port != ref->port))) { val = xmlStrdup (URI); + if (val == NULL) + ret = -1; goto done; } if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) { val = xmlStrdup(BAD_CAST ""); + if (val == NULL) + ret = -1; goto done; } if (bas->path == NULL) { val = xmlStrdup((xmlChar *)ref->path); + if (val == NULL) + ret = -1; goto done; } if (ref->path == NULL) { @@ -2279,6 +2513,8 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) if (bptr[pos] == rptr[pos]) { val = xmlStrdup(BAD_CAST ""); + if (val == NULL) + ret = -1; goto done; /* (I can't imagine why anyone would do this) */ } @@ -2306,6 +2542,8 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) */ if (nbslash == 0 && !uptr[0]) { val = xmlStrdup(BAD_CAST "./"); + if (val == NULL) + ret = -1; goto done; } @@ -2313,9 +2551,12 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) } if (nbslash == 0) { - if (uptr != NULL) + if (uptr != NULL) { /* exception characters from xmlSaveUri */ val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,"); + if (val == NULL) + ret = -1; + } goto done; } @@ -2326,7 +2567,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) */ val = (xmlChar *) xmlMalloc (len + 3 * nbslash); if (val == NULL) { - xmlURIErrMemory("building relative URI\n"); + ret = -1; goto done; } vptr = val; @@ -2358,6 +2599,10 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) vptr = val; /* exception characters from xmlSaveUri */ val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,"); + if (val == NULL) + ret = -1; + else + ret = 0; xmlFree(vptr); done: @@ -2370,153 +2615,75 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base) xmlFreeURI (ref); if (bas != NULL) xmlFreeURI (bas); + if (ret != 0) { + xmlFree(val); + val = NULL; + } + + *valPtr = val; + return(ret); +} + +/* + * xmlBuildRelativeURI: + * @URI: the URI reference under consideration + * @base: the base value + * + * See xmlBuildRelativeURISafe. + * + * Returns a new URI string (to be freed by the caller) or NULL in case + * error. + */ +xmlChar * +xmlBuildRelativeURI(const xmlChar * URI, const xmlChar * base) +{ + xmlChar *val; - return val; + xmlBuildRelativeURISafe(URI, base, &val); + return(val); } /** * xmlCanonicPath: * @path: the resource locator in a filesystem notation * - * Constructs a canonic path from the specified path. + * Prepares a path. * - * Returns a new canonic path, or a duplicate of the path parameter if the - * construction fails. The caller is responsible for freeing the memory occupied + * If the path contains the substring "://", it is considered a + * Legacy Extended IRI. Characters which aren't allowed in URIs are + * escaped. + * + * Otherwise, the path is considered a filesystem path which is + * copied without modification. + * + * The caller is responsible for freeing the memory occupied * by the returned string. If there is insufficient memory available, or the * argument is NULL, the function returns NULL. + * + * Returns the escaped path. */ -#define IS_WINDOWS_PATH(p) \ - ((p != NULL) && \ - (((p[0] >= 'a') && (p[0] <= 'z')) || \ - ((p[0] >= 'A') && (p[0] <= 'Z'))) && \ - (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\'))) xmlChar * xmlCanonicPath(const xmlChar *path) { -/* - * For Windows implementations, additional work needs to be done to - * replace backslashes in pathnames with "forward slashes" - */ -#if defined(_WIN32) - int len = 0; - char *p = NULL; -#endif - xmlURIPtr uri; xmlChar *ret; - const xmlChar *absuri; if (path == NULL) return(NULL); -#if defined(_WIN32) - /* - * We must not change the backslashes to slashes if the the path - * starts with \\?\ - * Those paths can be up to 32k characters long. - * Was added specifically for OpenOffice, those paths can't be converted - * to URIs anyway. - */ - if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') && - (path[3] == '\\') ) - return xmlStrdup((const xmlChar *) path); -#endif - - /* sanitize filename starting with // so it can be used as URI */ - if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/')) - path++; - - if ((uri = xmlParseURI((const char *) path)) != NULL) { - xmlFreeURI(uri); - return xmlStrdup(path); - } - /* Check if this is an "absolute uri" */ - absuri = xmlStrstr(path, BAD_CAST "://"); - if (absuri != NULL) { - int l, j; - unsigned char c; - xmlChar *escURI; - - /* - * this looks like an URI where some parts have not been - * escaped leading to a parsing problem. Check that the first - * part matches a protocol. - */ - l = absuri - path; - /* Bypass if first part (part before the '://') is > 20 chars */ - if ((l <= 0) || (l > 20)) - goto path_processing; - /* Bypass if any non-alpha characters are present in first part */ - for (j = 0;j < l;j++) { - c = path[j]; - if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))) - goto path_processing; - } - - /* Escape all except the characters specified in the supplied path */ - escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;="); - if (escURI != NULL) { - /* Try parsing the escaped path */ - uri = xmlParseURI((const char *) escURI); - /* If successful, return the escaped string */ - if (uri != NULL) { - xmlFreeURI(uri); - return escURI; - } - xmlFree(escURI); - } - } - -path_processing: -/* For Windows implementations, replace backslashes with 'forward slashes' */ -#if defined(_WIN32) - /* - * Create a URI structure - */ - uri = xmlCreateURI(); - if (uri == NULL) { /* Guard against 'out of memory' */ - return(NULL); - } - - len = xmlStrlen(path); - if ((len > 2) && IS_WINDOWS_PATH(path)) { - /* make the scheme 'file' */ - uri->scheme = (char *) xmlStrdup(BAD_CAST "file"); - /* allocate space for leading '/' + path + string terminator */ - uri->path = xmlMallocAtomic(len + 2); - if (uri->path == NULL) { - xmlFreeURI(uri); /* Guard against 'out of memory' */ - return(NULL); - } - /* Put in leading '/' plus path */ - uri->path[0] = '/'; - p = uri->path + 1; - strncpy(p, (char *) path, len + 1); - } else { - uri->path = (char *) xmlStrdup(path); - if (uri->path == NULL) { - xmlFreeURI(uri); - return(NULL); - } - p = uri->path; - } - /* Now change all occurrences of '\' to '/' */ - while (*p != '\0') { - if (*p == '\\') - *p = '/'; - p++; - } - - if (uri->scheme == NULL) { - ret = xmlStrdup((const xmlChar *) uri->path); + if (xmlStrstr(path, BAD_CAST "://") != NULL) { + /* + * Escape all characters except reserved, unreserved and the + * percent sign. + * + * xmlURIEscapeStr already keeps unreserved characters, so we + * pass gen-delims, sub-delims and "%" to ignore. + */ + ret = xmlURIEscapeStr(path, BAD_CAST ":/?#[]@!$&()*+,;='%"); } else { - ret = xmlSaveUri(uri); + ret = xmlStrdup((const xmlChar *) path); } - xmlFreeURI(uri); -#else - ret = xmlStrdup((const xmlChar *) path); -#endif return(ret); } @@ -2534,41 +2701,5 @@ xmlCanonicPath(const xmlChar *path) xmlChar * xmlPathToURI(const xmlChar *path) { - xmlURIPtr uri; - xmlURI temp; - xmlChar *ret, *cal; - - if (path == NULL) - return(NULL); - - if ((uri = xmlParseURI((const char *) path)) != NULL) { - xmlFreeURI(uri); - return xmlStrdup(path); - } - cal = xmlCanonicPath(path); - if (cal == NULL) - return(NULL); -#if defined(_WIN32) - /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?) - If 'cal' is a valid URI already then we are done here, as continuing would make - it invalid. */ - if ((uri = xmlParseURI((const char *) cal)) != NULL) { - xmlFreeURI(uri); - return cal; - } - /* 'cal' can contain a relative path with backslashes. If that is processed - by xmlSaveURI, they will be escaped and the external entity loader machinery - will fail. So convert them to slashes. Misuse 'ret' for walking. */ - ret = cal; - while (*ret != '\0') { - if (*ret == '\\') - *ret = '/'; - ret++; - } -#endif - memset(&temp, 0, sizeof(temp)); - temp.path = (char *) cal; - ret = xmlSaveUri(&temp); - xmlFree(cal); - return(ret); + return(xmlCanonicPath(path)); } diff --git a/valid.c b/valid.c index 76d657d..1b711e6 100644 --- a/valid.c +++ b/valid.c @@ -21,18 +21,16 @@ #include #include #include +#include #include "private/error.h" #include "private/parser.h" +#include "private/regexp.h" +#include "private/save.h" +#include "private/tree.h" static xmlElementPtr -xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, - int create); - -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); +xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name); #ifdef LIBXML_VALID_ENABLED static int @@ -53,31 +51,56 @@ xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type, * Handle an out of memory error */ static void -xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra) +xmlVErrMemory(xmlValidCtxtPtr ctxt) { - xmlGenericErrorFunc channel = NULL; + if (ctxt != NULL) { + if (ctxt->flags & XML_VCTXT_USE_PCTXT) { + xmlCtxtErrMemory(ctxt->userData); + } else { + xmlRaiseMemoryError(NULL, ctxt->error, ctxt->userData, + XML_FROM_VALID, NULL); + } + } else { + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_VALID, NULL); + } +} + +static void +xmlDoErrValid(xmlValidCtxtPtr ctxt, xmlNodePtr node, + xmlParserErrors code, int level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, + const char *msg, ...) { xmlParserCtxtPtr pctxt = NULL; - void *data = NULL; + va_list ap; - if (ctxt != NULL) { - channel = ctxt->error; - data = ctxt->userData; - /* Look up flag to detect if it is part of a parsing - context */ - if (ctxt->flags & XML_VCTXT_USE_PCTXT) { - pctxt = ctxt->userData; - } + if (ctxt == NULL) + return; + if (ctxt->flags & XML_VCTXT_USE_PCTXT) + pctxt = ctxt->userData; + + va_start(ap, msg); + if (pctxt != NULL) { + xmlCtxtVErr(pctxt, node, XML_FROM_VALID, code, level, + str1, str2, str3, int1, msg, ap); + } else { + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + int res; + + if (ctxt != NULL) { + channel = ctxt->error; + data = ctxt->userData; + } + res = xmlVRaiseError(NULL, channel, data, NULL, node, + XML_FROM_VALID, code, level, NULL, 0, + (const char *) str1, (const char *) str2, + (const char *) str2, int1, 0, + msg, ap); + if (res < 0) + xmlVErrMemory(ctxt); } - if (extra) - __xmlRaiseError(NULL, channel, data, - pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY, - XML_ERR_FATAL, NULL, 0, extra, NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, channel, data, - pctxt, NULL, XML_FROM_VALID, XML_ERR_NO_MEMORY, - XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, - "Memory allocation failed\n"); + va_end(ap); } /** @@ -92,29 +115,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error, const char *msg, const char *extra) { - xmlGenericErrorFunc channel = NULL; - xmlParserCtxtPtr pctxt = NULL; - void *data = NULL; - - if (ctxt != NULL) { - channel = ctxt->error; - data = ctxt->userData; - /* Look up flag to detect if it is part of a parsing - context */ - if (ctxt->flags & XML_VCTXT_USE_PCTXT) { - pctxt = ctxt->userData; - } - } - if (extra) - __xmlRaiseError(NULL, channel, data, - pctxt, NULL, XML_FROM_VALID, error, - XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, - msg, extra); - else - __xmlRaiseError(NULL, channel, data, - pctxt, NULL, XML_FROM_VALID, error, - XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0, - "%s", msg); + xmlDoErrValid(ctxt, NULL, error, XML_ERR_ERROR, (const xmlChar *) extra, + NULL, NULL, 0, msg, extra); } #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) @@ -135,25 +137,8 @@ xmlErrValidNode(xmlValidCtxtPtr ctxt, const char *msg, const xmlChar * str1, const xmlChar * str2, const xmlChar * str3) { - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - xmlParserCtxtPtr pctxt = NULL; - void *data = NULL; - - if (ctxt != NULL) { - channel = ctxt->error; - data = ctxt->userData; - /* Look up flag to detect if it is part of a parsing - context */ - if (ctxt->flags & XML_VCTXT_USE_PCTXT) { - pctxt = ctxt->userData; - } - } - __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, - XML_ERR_ERROR, NULL, 0, - (const char *) str1, - (const char *) str2, - (const char *) str3, 0, 0, msg, str1, str2, str3); + xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str2, str3, 0, + msg, str1, str2, str3); } #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ @@ -175,25 +160,8 @@ xmlErrValidNodeNr(xmlValidCtxtPtr ctxt, const char *msg, const xmlChar * str1, int int2, const xmlChar * str3) { - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - xmlParserCtxtPtr pctxt = NULL; - void *data = NULL; - - if (ctxt != NULL) { - channel = ctxt->error; - data = ctxt->userData; - /* Look up flag to detect if it is part of a parsing - context */ - if (ctxt->flags & XML_VCTXT_USE_PCTXT) { - pctxt = ctxt->userData; - } - } - __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, - XML_ERR_ERROR, NULL, 0, - (const char *) str1, - (const char *) str3, - NULL, int2, 0, msg, str1, int2, str3); + xmlDoErrValid(ctxt, node, error, XML_ERR_ERROR, str1, str3, NULL, int2, + msg, str1, int2, str3); } /** @@ -213,25 +181,8 @@ xmlErrValidWarning(xmlValidCtxtPtr ctxt, const char *msg, const xmlChar * str1, const xmlChar * str2, const xmlChar * str3) { - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - xmlParserCtxtPtr pctxt = NULL; - void *data = NULL; - - if (ctxt != NULL) { - channel = ctxt->warning; - data = ctxt->userData; - /* Look up flag to detect if it is part of a parsing - context */ - if (ctxt->flags & XML_VCTXT_USE_PCTXT) { - pctxt = ctxt->userData; - } - } - __xmlRaiseError(schannel, channel, data, pctxt, node, XML_FROM_VALID, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, - (const char *) str2, - (const char *) str3, 0, 0, msg, str1, str2, str3); + xmlDoErrValid(ctxt, node, error, XML_ERR_WARNING, str1, str2, str3, 0, + msg, str1, str2, str3); } @@ -260,7 +211,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) { ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); if (ctxt->vstateTab == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); return(-1); } } @@ -271,7 +222,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) { tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab, 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); if (tmp == NULL) { - xmlVErrMemory(ctxt, "realloc failed"); + xmlVErrMemory(ctxt); return(-1); } ctxt->vstateMax *= 2; @@ -286,6 +237,10 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) { if (elemDecl->contModel != NULL) { ctxt->vstateTab[ctxt->vstateNr].exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL); + if (ctxt->vstateTab[ctxt->vstateNr].exec == NULL) { + xmlVErrMemory(ctxt); + return(-1); + } } else { ctxt->vstateTab[ctxt->vstateNr].exec = NULL; xmlErrValidNode(ctxt, (xmlNodePtr) elemDecl, @@ -367,7 +322,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont, ctxt->vstateTab = (xmlValidState *) xmlMalloc( ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); if (ctxt->vstateTab == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); return(-1); } } @@ -377,7 +332,7 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont, tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab, 2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); if (tmp == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); return(-1); } ctxt->vstateMax *= 2; @@ -425,7 +380,7 @@ nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value) (xmlNodePtr *) xmlMalloc(ctxt->nodeMax * sizeof(ctxt->nodeTab[0])); if (ctxt->nodeTab == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); ctxt->nodeMax = 0; return (0); } @@ -435,7 +390,7 @@ nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value) tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab, ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0])); if (tmp == NULL) { - xmlVErrMemory(ctxt, "realloc failed"); + xmlVErrMemory(ctxt); return (0); } ctxt->nodeMax *= 2; @@ -512,7 +467,7 @@ xmlValidBuildAContentModel(xmlElementContentPtr content, fullname = xmlBuildQName(content->name, content->prefix, fn, 50); if (fullname == NULL) { - xmlVErrMemory(ctxt, "Building content model"); + xmlVErrMemory(ctxt); return(0); } @@ -557,11 +512,13 @@ xmlValidBuildAContentModel(xmlElementContentPtr content, oldstate = ctxt->state; } do { - xmlValidBuildAContentModel(content->c1, ctxt, name); + if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0) + return(0); content = content->c2; } while ((content->type == XML_ELEMENT_CONTENT_SEQ) && (content->ocur == XML_ELEMENT_CONTENT_ONCE)); - xmlValidBuildAContentModel(content, ctxt, name); + if (xmlValidBuildAContentModel(content, ctxt, name) == 0) + return(0); oldend = ctxt->state; ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL); switch (ocur) { @@ -599,13 +556,15 @@ xmlValidBuildAContentModel(xmlElementContentPtr content, */ do { ctxt->state = oldstate; - xmlValidBuildAContentModel(content->c1, ctxt, name); + if (xmlValidBuildAContentModel(content->c1, ctxt, name) == 0) + return(0); xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend); content = content->c2; } while ((content->type == XML_ELEMENT_CONTENT_OR) && (content->ocur == XML_ELEMENT_CONTENT_ONCE)); ctxt->state = oldstate; - xmlValidBuildAContentModel(content, ctxt, name); + if (xmlValidBuildAContentModel(content, ctxt, name) == 0) + return(0); xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldend); ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldend, NULL); switch (ocur) { @@ -637,6 +596,8 @@ xmlValidBuildAContentModel(xmlElementContentPtr content, * @ctxt: a validation context * @elem: an element declaration node * + * DEPRECATED: Internal function, don't use. + * * (Re)Build the automata associated to the content model of this * element * @@ -644,6 +605,7 @@ xmlValidBuildAContentModel(xmlElementContentPtr content, */ int xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { + int ret = 0; if ((ctxt == NULL) || (elem == NULL)) return(0); @@ -662,16 +624,18 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { ctxt->am = xmlNewAutomata(); if (ctxt->am == NULL) { - xmlErrValidNode(ctxt, (xmlNodePtr) elem, - XML_ERR_INTERNAL_ERROR, - "Cannot create automata for element %s\n", - elem->name, NULL, NULL); + xmlVErrMemory(ctxt); return(0); } ctxt->state = xmlAutomataGetInitState(ctxt->am); - xmlValidBuildAContentModel(elem->content, ctxt, elem->name); + if (xmlValidBuildAContentModel(elem->content, ctxt, elem->name) == 0) + goto done; xmlAutomataSetFinalState(ctxt->am, ctxt->state); elem->contModel = xmlAutomataCompile(ctxt->am); + if (elem->contModel == NULL) { + xmlVErrMemory(ctxt); + goto done; + } if (xmlRegexpIsDeterminist(elem->contModel) != 1) { char expr[5000]; expr[0] = 0; @@ -681,15 +645,16 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { "Content model of %s is not deterministic: %s\n", elem->name, BAD_CAST expr, NULL); ctxt->valid = 0; - ctxt->state = NULL; - xmlFreeAutomata(ctxt->am); - ctxt->am = NULL; - return(0); + goto done; } + + ret = 1; + +done: ctxt->state = NULL; xmlFreeAutomata(ctxt->am); ctxt->am = NULL; - return(1); + return(ret); } #endif /* LIBXML_REGEXP_ENABLED */ @@ -710,10 +675,8 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { xmlValidCtxtPtr xmlNewValidCtxt(void) { xmlValidCtxtPtr ret; - if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if ((ret = xmlMalloc(sizeof (xmlValidCtxt))) == NULL) return (NULL); - } (void) memset(ret, 0, sizeof (xmlValidCtxt)); @@ -782,10 +745,8 @@ xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name, return(NULL); } ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); - if (ret == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlElementContent)); ret->type = type; ret->ocur = XML_ELEMENT_CONTENT_ONCE; @@ -807,9 +768,17 @@ xmlNewDocElementContent(xmlDocPtr doc, const xmlChar *name, ret->prefix = xmlDictLookup(dict, name, l); ret->name = xmlDictLookup(dict, tmp, -1); } + if (ret->prefix == NULL) + goto error; } + if (ret->name == NULL) + goto error; } return(ret); + +error: + xmlFreeDocElementContent(doc, ret); + return(NULL); } /** @@ -847,10 +816,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { dict = doc->dict; ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); - if (ret == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlElementContent)); ret->type = cur->type; ret->ocur = cur->ocur; @@ -859,6 +826,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { ret->name = xmlDictLookup(dict, cur->name, -1); else ret->name = xmlStrdup(cur->name); + if (ret->name == NULL) + goto error; } if (cur->prefix != NULL) { @@ -866,20 +835,22 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { ret->prefix = xmlDictLookup(dict, cur->prefix, -1); else ret->prefix = xmlStrdup(cur->prefix); + if (ret->prefix == NULL) + goto error; } - if (cur->c1 != NULL) + if (cur->c1 != NULL) { ret->c1 = xmlCopyDocElementContent(doc, cur->c1); - if (ret->c1 != NULL) + if (ret->c1 == NULL) + goto error; ret->c1->parent = ret; + } if (cur->c2 != NULL) { prev = ret; cur = cur->c2; while (cur != NULL) { tmp = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); - if (tmp == NULL) { - xmlVErrMemory(NULL, "malloc failed"); - return(ret); - } + if (tmp == NULL) + goto error; memset(tmp, 0, sizeof(xmlElementContent)); tmp->type = cur->type; tmp->ocur = cur->ocur; @@ -890,6 +861,8 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { tmp->name = xmlDictLookup(dict, cur->name, -1); else tmp->name = xmlStrdup(cur->name); + if (tmp->name == NULL) + goto error; } if (cur->prefix != NULL) { @@ -897,16 +870,24 @@ xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur) { tmp->prefix = xmlDictLookup(dict, cur->prefix, -1); else tmp->prefix = xmlStrdup(cur->prefix); + if (tmp->prefix == NULL) + goto error; } - if (cur->c1 != NULL) + if (cur->c1 != NULL) { tmp->c1 = xmlCopyDocElementContent(doc,cur->c1); - if (tmp->c1 != NULL) + if (tmp->c1 == NULL) + goto error; tmp->c1->parent = tmp; + } prev = tmp; cur = cur->c2; } } return(ret); + +error: + xmlFreeElementContent(ret); + return(NULL); } /** @@ -1002,105 +983,6 @@ xmlFreeElementContent(xmlElementContentPtr cur) { } #ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlDumpElementOccur: - * @buf: An XML buffer - * @cur: An element table - * - * Dump the occurrence operator of an element. - */ -static void -xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) { - switch (cur->ocur) { - case XML_ELEMENT_CONTENT_ONCE: - break; - case XML_ELEMENT_CONTENT_OPT: - xmlBufferWriteChar(buf, "?"); - break; - case XML_ELEMENT_CONTENT_MULT: - xmlBufferWriteChar(buf, "*"); - break; - case XML_ELEMENT_CONTENT_PLUS: - xmlBufferWriteChar(buf, "+"); - break; - } -} - -/** - * xmlDumpElementContent: - * @buf: An XML buffer - * @content: An element table - * - * This will dump the content of the element table as an XML DTD definition - */ -static void -xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) { - xmlElementContentPtr cur; - - if (content == NULL) return; - - xmlBufferWriteChar(buf, "("); - cur = content; - - do { - if (cur == NULL) return; - - switch (cur->type) { - case XML_ELEMENT_CONTENT_PCDATA: - xmlBufferWriteChar(buf, "#PCDATA"); - break; - case XML_ELEMENT_CONTENT_ELEMENT: - if (cur->prefix != NULL) { - xmlBufferWriteCHAR(buf, cur->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, cur->name); - break; - case XML_ELEMENT_CONTENT_SEQ: - case XML_ELEMENT_CONTENT_OR: - if ((cur != content) && - (cur->parent != NULL) && - ((cur->type != cur->parent->type) || - (cur->ocur != XML_ELEMENT_CONTENT_ONCE))) - xmlBufferWriteChar(buf, "("); - cur = cur->c1; - continue; - default: - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "Internal: ELEMENT cur corrupted invalid type\n", - NULL); - } - - while (cur != content) { - xmlElementContentPtr parent = cur->parent; - - if (parent == NULL) return; - - if (((cur->type == XML_ELEMENT_CONTENT_OR) || - (cur->type == XML_ELEMENT_CONTENT_SEQ)) && - ((cur->type != parent->type) || - (cur->ocur != XML_ELEMENT_CONTENT_ONCE))) - xmlBufferWriteChar(buf, ")"); - xmlDumpElementOccur(buf, cur); - - if (cur == parent->c1) { - if (parent->type == XML_ELEMENT_CONTENT_SEQ) - xmlBufferWriteChar(buf, " , "); - else if (parent->type == XML_ELEMENT_CONTENT_OR) - xmlBufferWriteChar(buf, " | "); - - cur = parent->c2; - break; - } - - cur = parent; - } - } while (cur != content); - - xmlBufferWriteChar(buf, ")"); - xmlDumpElementOccur(buf, content); -} - /** * xmlSprintfElementContent: * @buf: an output buffer @@ -1267,7 +1149,8 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlElementPtr ret; xmlElementTablePtr table; xmlAttributePtr oldAttributes = NULL; - xmlChar *ns, *uqname; + const xmlChar *localName; + xmlChar *prefix = NULL; if (dtd == NULL) { return(NULL); @@ -1279,7 +1162,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, switch (type) { case XML_ELEMENT_TYPE_EMPTY: if (content != NULL) { - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR, "xmlAddElementDecl: content != NULL for EMPTY\n", NULL); return(NULL); @@ -1287,7 +1170,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, break; case XML_ELEMENT_TYPE_ANY: if (content != NULL) { - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR, "xmlAddElementDecl: content != NULL for ANY\n", NULL); return(NULL); @@ -1295,7 +1178,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, break; case XML_ELEMENT_TYPE_MIXED: if (content == NULL) { - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR, "xmlAddElementDecl: content == NULL for MIXED\n", NULL); return(NULL); @@ -1303,25 +1186,24 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, break; case XML_ELEMENT_TYPE_ELEMENT: if (content == NULL) { - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, + xmlErrValid(ctxt, XML_DTD_CONTENT_ERROR, "xmlAddElementDecl: content == NULL for ELEMENT\n", NULL); return(NULL); } break; default: - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, - "Internal: ELEMENT decl corrupted invalid type\n", - NULL); + xmlErrValid(ctxt, XML_ERR_ARGUMENT, + "xmlAddElementDecl: invalid type\n", NULL); return(NULL); } /* * check if name is a QName */ - uqname = xmlSplitQName2(name, &ns); - if (uqname != NULL) - name = uqname; + localName = xmlSplitQName4(name, &prefix); + if (localName == NULL) + goto mem_error; /* * Create the Element table if needed. @@ -1333,28 +1215,22 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, if (dtd->doc != NULL) dict = dtd->doc->dict; table = xmlHashCreateDict(0, dict); + if (table == NULL) + goto mem_error; dtd->elements = (void *) table; } - if (table == NULL) { - xmlVErrMemory(ctxt, - "xmlAddElementDecl: Table creation failed!\n"); - if (uqname != NULL) - xmlFree(uqname); - if (ns != NULL) - xmlFree(ns); - return(NULL); - } /* * lookup old attributes inserted on an undefined element in the * internal subset. */ if ((dtd->doc != NULL) && (dtd->doc->intSubset != NULL)) { - ret = xmlHashLookup2(dtd->doc->intSubset->elements, name, ns); + ret = xmlHashLookup2(dtd->doc->intSubset->elements, localName, prefix); if ((ret != NULL) && (ret->etype == XML_ELEMENT_TYPE_UNDEFINED)) { oldAttributes = ret->attributes; ret->attributes = NULL; - xmlHashRemoveEntry2(dtd->doc->intSubset->elements, name, ns, NULL); + xmlHashRemoveEntry2(dtd->doc->intSubset->elements, localName, prefix, + NULL); xmlFreeElement(ret); } } @@ -1363,7 +1239,7 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, * The element may already be present if one of its attribute * was registered first */ - ret = xmlHashLookup2(table, name, ns); + ret = xmlHashLookup2(table, localName, prefix); if (ret != NULL) { if (ret->etype != XML_ELEMENT_TYPE_UNDEFINED) { #ifdef LIBXML_VALID_ENABLED @@ -1374,61 +1250,42 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, "Redefinition of element %s\n", name, NULL, NULL); #endif /* LIBXML_VALID_ENABLED */ - if (uqname != NULL) - xmlFree(uqname); - if (ns != NULL) - xmlFree(ns); + if (prefix != NULL) + xmlFree(prefix); return(NULL); } - if (ns != NULL) { - xmlFree(ns); - ns = NULL; + if (prefix != NULL) { + xmlFree(prefix); + prefix = NULL; } } else { + int res; + ret = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); - if (ret == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - if (uqname != NULL) - xmlFree(uqname); - if (ns != NULL) - xmlFree(ns); - return(NULL); - } + if (ret == NULL) + goto mem_error; memset(ret, 0, sizeof(xmlElement)); ret->type = XML_ELEMENT_DECL; /* * fill the structure. */ - ret->name = xmlStrdup(name); + ret->name = xmlStrdup(localName); if (ret->name == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - if (uqname != NULL) - xmlFree(uqname); - if (ns != NULL) - xmlFree(ns); xmlFree(ret); - return(NULL); + goto mem_error; } - ret->prefix = ns; + ret->prefix = prefix; + prefix = NULL; /* * Validity Check: * Insertion must not fail */ - if (xmlHashAddEntry2(table, name, ns, ret)) { -#ifdef LIBXML_VALID_ENABLED - /* - * The element is already defined in this DTD. - */ - xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_ELEM_REDEFINED, - "Redefinition of element %s\n", - name, NULL, NULL); -#endif /* LIBXML_VALID_ENABLED */ + res = xmlHashAdd2(table, localName, ret->prefix, ret); + if (res <= 0) { xmlFreeElement(ret); - if (uqname != NULL) - xmlFree(uqname); - return(NULL); + goto mem_error; } /* * For new element, may have attributes from earlier @@ -1446,12 +1303,15 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, * and flag it by setting a special parent value * so the parser doesn't unallocate it. */ - if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) { - ret->content = content; - if (content != NULL) - content->parent = (xmlElementContentPtr) 1; - } else { - ret->content = xmlCopyDocElementContent(dtd->doc, content); + if (content != NULL) { + if ((ctxt != NULL) && (ctxt->flags & XML_VCTXT_USE_PCTXT)) { + ret->content = content; + content->parent = (xmlElementContentPtr) 1; + } else if (content != NULL){ + ret->content = xmlCopyDocElementContent(dtd->doc, content); + if (ret->content == NULL) + goto mem_error; + } } /* @@ -1466,9 +1326,15 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, ret->prev = dtd->last; dtd->last = (xmlNodePtr) ret; } - if (uqname != NULL) - xmlFree(uqname); + if (prefix != NULL) + xmlFree(prefix); return(ret); + +mem_error: + xmlVErrMemory(ctxt); + if (prefix != NULL) + xmlFree(prefix); + return(NULL); } static void @@ -1502,25 +1368,33 @@ xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlElementPtr cur; cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); - if (cur == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlElement)); cur->type = XML_ELEMENT_DECL; cur->etype = elem->etype; - if (elem->name != NULL) + if (elem->name != NULL) { cur->name = xmlStrdup(elem->name); - else - cur->name = NULL; - if (elem->prefix != NULL) + if (cur->name == NULL) + goto error; + } + if (elem->prefix != NULL) { cur->prefix = xmlStrdup(elem->prefix); - else - cur->prefix = NULL; - cur->content = xmlCopyElementContent(elem->content); + if (cur->prefix == NULL) + goto error; + } + if (elem->content != NULL) { + cur->content = xmlCopyElementContent(elem->content); + if (cur->content == NULL) + goto error; + } /* TODO : rebuild the attribute list on the copy */ cur->attributes = NULL; return(cur); + +error: + xmlFreeElement(cur); + return(NULL); } /** @@ -1533,7 +1407,7 @@ xmlCopyElement(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { */ xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table) { - return((xmlElementTablePtr) xmlHashCopy(table, xmlCopyElement)); + return(xmlHashCopySafe(table, xmlCopyElement, xmlFreeElementTableEntry)); } #endif /* LIBXML_TREE_ENABLED */ @@ -1543,59 +1417,22 @@ xmlCopyElementTable(xmlElementTablePtr table) { * @buf: the XML buffer output * @elem: An element table * + * DEPRECATED: Use xmlSaveTree. + * * This will dump the content of the element declaration as an XML * DTD definition */ void xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (elem == NULL)) return; - switch (elem->etype) { - case XML_ELEMENT_TYPE_EMPTY: - xmlBufferWriteChar(buf, "prefix != NULL) { - xmlBufferWriteCHAR(buf, elem->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, elem->name); - xmlBufferWriteChar(buf, " EMPTY>\n"); - break; - case XML_ELEMENT_TYPE_ANY: - xmlBufferWriteChar(buf, "prefix != NULL) { - xmlBufferWriteCHAR(buf, elem->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, elem->name); - xmlBufferWriteChar(buf, " ANY>\n"); - break; - case XML_ELEMENT_TYPE_MIXED: - xmlBufferWriteChar(buf, "prefix != NULL) { - xmlBufferWriteCHAR(buf, elem->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, elem->name); - xmlBufferWriteChar(buf, " "); - xmlDumpElementContent(buf, elem->content); - xmlBufferWriteChar(buf, ">\n"); - break; - case XML_ELEMENT_TYPE_ELEMENT: - xmlBufferWriteChar(buf, "prefix != NULL) { - xmlBufferWriteCHAR(buf, elem->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, elem->name); - xmlBufferWriteChar(buf, " "); - xmlDumpElementContent(buf, elem->content); - xmlBufferWriteChar(buf, ">\n"); - break; - default: - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "Internal: ELEMENT struct corrupted invalid type\n", - NULL); - } + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlSaveTree(save, (xmlNodePtr) elem); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } /** @@ -1607,9 +1444,9 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) { * the arguments. */ static void -xmlDumpElementDeclScan(void *elem, void *buf, +xmlDumpElementDeclScan(void *elem, void *save, const xmlChar *name ATTRIBUTE_UNUSED) { - xmlDumpElementDecl((xmlBufferPtr) buf, (xmlElementPtr) elem); + xmlSaveTree(save, elem); } /** @@ -1617,13 +1454,21 @@ xmlDumpElementDeclScan(void *elem, void *buf, * @buf: the XML buffer output * @table: An element table * + * DEPRECATED: Don't use. + * * This will dump the content of the element table as an XML DTD definition */ void xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (table == NULL)) return; - xmlHashScan(table, xmlDumpElementDeclScan, buf); + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlHashScan(table, xmlDumpElementDeclScan, save); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -1641,14 +1486,18 @@ xmlCreateEnumeration(const xmlChar *name) { xmlEnumerationPtr ret; ret = (xmlEnumerationPtr) xmlMalloc(sizeof(xmlEnumeration)); - if (ret == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlEnumeration)); - if (name != NULL) + if (name != NULL) { ret->name = xmlStrdup(name); + if (ret->name == NULL) { + xmlFree(ret); + return(NULL); + } + } + return(ret); } @@ -1660,12 +1509,14 @@ xmlCreateEnumeration(const xmlChar *name) { */ void xmlFreeEnumeration(xmlEnumerationPtr cur) { - if (cur == NULL) return; + while (cur != NULL) { + xmlEnumerationPtr next = cur->next; - if (cur->next != NULL) xmlFreeEnumeration(cur->next); + xmlFree((xmlChar *) cur->name); + xmlFree(cur); - if (cur->name != NULL) xmlFree((xmlChar *) cur->name); - xmlFree(cur); + cur = next; + } } #ifdef LIBXML_TREE_ENABLED @@ -1680,41 +1531,30 @@ xmlFreeEnumeration(xmlEnumerationPtr cur) { */ xmlEnumerationPtr xmlCopyEnumeration(xmlEnumerationPtr cur) { - xmlEnumerationPtr ret; - - if (cur == NULL) return(NULL); - ret = xmlCreateEnumeration((xmlChar *) cur->name); - if (ret == NULL) return(NULL); + xmlEnumerationPtr ret = NULL; + xmlEnumerationPtr last = NULL; - if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next); - else ret->next = NULL; + while (cur != NULL) { + xmlEnumerationPtr copy = xmlCreateEnumeration(cur->name); - return(ret); -} -#endif /* LIBXML_TREE_ENABLED */ + if (copy == NULL) { + xmlFreeEnumeration(ret); + return(NULL); + } -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlDumpEnumeration: - * @buf: the XML buffer output - * @enum: An enumeration - * - * This will dump the content of the enumeration - */ -static void -xmlDumpEnumeration(xmlBufferPtr buf, xmlEnumerationPtr cur) { - if ((buf == NULL) || (cur == NULL)) - return; + if (ret == NULL) { + ret = last = copy; + } else { + last->next = copy; + last = copy; + } - xmlBufferWriteCHAR(buf, cur->name); - if (cur->next == NULL) - xmlBufferWriteChar(buf, ")"); - else { - xmlBufferWriteChar(buf, " | "); - xmlDumpEnumeration(buf, cur->next); + cur = cur->next; } + + return(ret); } -#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* LIBXML_TREE_ENABLED */ #ifdef LIBXML_VALID_ENABLED /** @@ -1814,10 +1654,11 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, const xmlChar *name, const xmlChar *ns, xmlAttributeType type, xmlAttributeDefault def, const xmlChar *defaultValue, xmlEnumerationPtr tree) { - xmlAttributePtr ret; + xmlAttributePtr ret = NULL; xmlAttributeTablePtr table; xmlElementPtr elemDef; xmlDictPtr dict = NULL; + int res; if (dtd == NULL) { xmlFreeEnumeration(tree); @@ -1860,9 +1701,8 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, case XML_ATTRIBUTE_NOTATION: break; default: - xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, - "Internal: ATTRIBUTE struct corrupted invalid type\n", - NULL); + xmlErrValid(ctxt, XML_ERR_ARGUMENT, + "xmlAddAttributeDecl: invalid type\n", NULL); xmlFreeEnumeration(tree); return(NULL); } @@ -1899,20 +1739,12 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, table = xmlHashCreateDict(0, dict); dtd->attributes = (void *) table; } - if (table == NULL) { - xmlVErrMemory(ctxt, - "xmlAddAttributeDecl: Table creation failed!\n"); - xmlFreeEnumeration(tree); - return(NULL); - } - + if (table == NULL) + goto mem_error; ret = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute)); - if (ret == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - xmlFreeEnumeration(tree); - return(NULL); - } + if (ret == NULL) + goto mem_error; memset(ret, 0, sizeof(xmlAttribute)); ret->type = XML_ATTRIBUTE_DECL; @@ -1928,34 +1760,53 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, ret->doc = dtd->doc; if (dict) { ret->name = xmlDictLookup(dict, name, -1); - ret->prefix = xmlDictLookup(dict, ns, -1); ret->elem = xmlDictLookup(dict, elem, -1); } else { ret->name = xmlStrdup(name); - ret->prefix = xmlStrdup(ns); ret->elem = xmlStrdup(elem); } + if ((ret->name == NULL) || (ret->elem == NULL)) + goto mem_error; + if (ns != NULL) { + if (dict) + ret->prefix = xmlDictLookup(dict, ns, -1); + else + ret->prefix = xmlStrdup(ns); + if (ret->prefix == NULL) + goto mem_error; + } ret->def = def; ret->tree = tree; + tree = NULL; if (defaultValue != NULL) { if (dict) ret->defaultValue = xmlDictLookup(dict, defaultValue, -1); else ret->defaultValue = xmlStrdup(defaultValue); + if (ret->defaultValue == NULL) + goto mem_error; } + elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem); + if (elemDef == NULL) + goto mem_error; + /* * Validity Check: * Search the DTD for previous declarations of the ATTLIST */ - if (xmlHashAddEntry3(table, ret->name, ret->prefix, ret->elem, ret) < 0) { + res = xmlHashAdd3(table, ret->name, ret->prefix, ret->elem, ret); + if (res <= 0) { + if (res < 0) + goto mem_error; #ifdef LIBXML_VALID_ENABLED - /* - * The attribute is already defined in this DTD. - */ - xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, XML_DTD_ATTRIBUTE_REDEFINED, - "Attribute %s of element %s: already defined\n", - name, elem, NULL); + /* + * The attribute is already defined in this DTD. + */ + xmlErrValidWarning(ctxt, (xmlNodePtr) dtd, + XML_DTD_ATTRIBUTE_REDEFINED, + "Attribute %s of element %s: already defined\n", + name, elem, NULL); #endif /* LIBXML_VALID_ENABLED */ xmlFreeAttribute(ret); return(NULL); @@ -1965,48 +1816,44 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, * Validity Check: * Multiple ID per element */ - elemDef = xmlGetDtdElementDesc2(ctxt, dtd, elem, 1); - if (elemDef != NULL) { - #ifdef LIBXML_VALID_ENABLED - if ((type == XML_ATTRIBUTE_ID) && - (xmlScanIDAttributeDecl(NULL, elemDef, 1) != 0)) { - xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID, - "Element %s has too may ID attributes defined : %s\n", - elem, name, NULL); - if (ctxt != NULL) - ctxt->valid = 0; - } + if ((type == XML_ATTRIBUTE_ID) && + (xmlScanIDAttributeDecl(ctxt, elemDef, 1) != 0)) { + xmlErrValidNode(ctxt, (xmlNodePtr) dtd, XML_DTD_MULTIPLE_ID, + "Element %s has too may ID attributes defined : %s\n", + elem, name, NULL); + if (ctxt != NULL) + ctxt->valid = 0; + } #endif /* LIBXML_VALID_ENABLED */ - /* - * Insert namespace default def first they need to be - * processed first. - */ - if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) || - ((ret->prefix != NULL && - (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) { - ret->nexth = elemDef->attributes; - elemDef->attributes = ret; - } else { - xmlAttributePtr tmp = elemDef->attributes; + /* + * Insert namespace default def first they need to be + * processed first. + */ + if ((xmlStrEqual(ret->name, BAD_CAST "xmlns")) || + ((ret->prefix != NULL && + (xmlStrEqual(ret->prefix, BAD_CAST "xmlns"))))) { + ret->nexth = elemDef->attributes; + elemDef->attributes = ret; + } else { + xmlAttributePtr tmp = elemDef->attributes; - while ((tmp != NULL) && - ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) || - ((ret->prefix != NULL && - (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) { - if (tmp->nexth == NULL) - break; - tmp = tmp->nexth; - } - if (tmp != NULL) { - ret->nexth = tmp->nexth; - tmp->nexth = ret; - } else { - ret->nexth = elemDef->attributes; - elemDef->attributes = ret; - } - } + while ((tmp != NULL) && + ((xmlStrEqual(tmp->name, BAD_CAST "xmlns")) || + ((ret->prefix != NULL && + (xmlStrEqual(ret->prefix, BAD_CAST "xmlns")))))) { + if (tmp->nexth == NULL) + break; + tmp = tmp->nexth; + } + if (tmp != NULL) { + ret->nexth = tmp->nexth; + tmp->nexth = ret; + } else { + ret->nexth = elemDef->attributes; + elemDef->attributes = ret; + } } /* @@ -2021,6 +1868,12 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, dtd->last = (xmlNodePtr) ret; } return(ret); + +mem_error: + xmlVErrMemory(ctxt); + xmlFreeEnumeration(tree); + xmlFreeAttribute(ret); + return(NULL); } static void @@ -2054,24 +1907,42 @@ xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlAttributePtr cur; cur = (xmlAttributePtr) xmlMalloc(sizeof(xmlAttribute)); - if (cur == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlAttribute)); cur->type = XML_ATTRIBUTE_DECL; cur->atype = attr->atype; cur->def = attr->def; - cur->tree = xmlCopyEnumeration(attr->tree); - if (attr->elem != NULL) + if (attr->tree != NULL) { + cur->tree = xmlCopyEnumeration(attr->tree); + if (cur->tree == NULL) + goto error; + } + if (attr->elem != NULL) { cur->elem = xmlStrdup(attr->elem); - if (attr->name != NULL) + if (cur->elem == NULL) + goto error; + } + if (attr->name != NULL) { cur->name = xmlStrdup(attr->name); - if (attr->prefix != NULL) + if (cur->name == NULL) + goto error; + } + if (attr->prefix != NULL) { cur->prefix = xmlStrdup(attr->prefix); - if (attr->defaultValue != NULL) + if (cur->prefix == NULL) + goto error; + } + if (attr->defaultValue != NULL) { cur->defaultValue = xmlStrdup(attr->defaultValue); + if (cur->defaultValue == NULL) + goto error; + } return(cur); + +error: + xmlFreeAttribute(cur); + return(NULL); } /** @@ -2084,7 +1955,8 @@ xmlCopyAttribute(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { */ xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table) { - return((xmlAttributeTablePtr) xmlHashCopy(table, xmlCopyAttribute)); + return(xmlHashCopySafe(table, xmlCopyAttribute, + xmlFreeAttributeTableEntry)); } #endif /* LIBXML_TREE_ENABLED */ @@ -2094,81 +1966,22 @@ xmlCopyAttributeTable(xmlAttributeTablePtr table) { * @buf: the XML buffer output * @attr: An attribute declaration * + * DEPRECATED: Use xmlSaveTree. + * * This will dump the content of the attribute declaration as an XML * DTD definition */ void xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (attr == NULL)) return; - xmlBufferWriteChar(buf, "elem); - xmlBufferWriteChar(buf, " "); - if (attr->prefix != NULL) { - xmlBufferWriteCHAR(buf, attr->prefix); - xmlBufferWriteChar(buf, ":"); - } - xmlBufferWriteCHAR(buf, attr->name); - switch (attr->atype) { - case XML_ATTRIBUTE_CDATA: - xmlBufferWriteChar(buf, " CDATA"); - break; - case XML_ATTRIBUTE_ID: - xmlBufferWriteChar(buf, " ID"); - break; - case XML_ATTRIBUTE_IDREF: - xmlBufferWriteChar(buf, " IDREF"); - break; - case XML_ATTRIBUTE_IDREFS: - xmlBufferWriteChar(buf, " IDREFS"); - break; - case XML_ATTRIBUTE_ENTITY: - xmlBufferWriteChar(buf, " ENTITY"); - break; - case XML_ATTRIBUTE_ENTITIES: - xmlBufferWriteChar(buf, " ENTITIES"); - break; - case XML_ATTRIBUTE_NMTOKEN: - xmlBufferWriteChar(buf, " NMTOKEN"); - break; - case XML_ATTRIBUTE_NMTOKENS: - xmlBufferWriteChar(buf, " NMTOKENS"); - break; - case XML_ATTRIBUTE_ENUMERATION: - xmlBufferWriteChar(buf, " ("); - xmlDumpEnumeration(buf, attr->tree); - break; - case XML_ATTRIBUTE_NOTATION: - xmlBufferWriteChar(buf, " NOTATION ("); - xmlDumpEnumeration(buf, attr->tree); - break; - default: - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "Internal: ATTRIBUTE struct corrupted invalid type\n", - NULL); - } - switch (attr->def) { - case XML_ATTRIBUTE_NONE: - break; - case XML_ATTRIBUTE_REQUIRED: - xmlBufferWriteChar(buf, " #REQUIRED"); - break; - case XML_ATTRIBUTE_IMPLIED: - xmlBufferWriteChar(buf, " #IMPLIED"); - break; - case XML_ATTRIBUTE_FIXED: - xmlBufferWriteChar(buf, " #FIXED"); - break; - default: - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "Internal: ATTRIBUTE struct corrupted invalid def\n", - NULL); - } - if (attr->defaultValue != NULL) { - xmlBufferWriteChar(buf, " "); - xmlBufferWriteQuotedString(buf, attr->defaultValue); - } - xmlBufferWriteChar(buf, ">\n"); + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlSaveTree(save, (xmlNodePtr) attr); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } /** @@ -2179,9 +1992,9 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) { * This is used with the hash scan function - just reverses arguments */ static void -xmlDumpAttributeDeclScan(void *attr, void *buf, +xmlDumpAttributeDeclScan(void *attr, void *save, const xmlChar *name ATTRIBUTE_UNUSED) { - xmlDumpAttributeDecl((xmlBufferPtr) buf, (xmlAttributePtr) attr); + xmlSaveTree(save, attr); } /** @@ -2189,13 +2002,21 @@ xmlDumpAttributeDeclScan(void *attr, void *buf, * @buf: the XML buffer output * @table: An attribute table * + * DEPRECATED: Don't use. + * * This will dump the content of the attribute table as an XML DTD definition */ void xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (table == NULL)) return; - xmlHashScan(table, xmlDumpAttributeDeclScan, buf); + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlHashScan(table, xmlDumpAttributeDeclScan, save); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -2239,8 +2060,9 @@ xmlNotationPtr xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, const xmlChar *PublicID, const xmlChar *SystemID) { - xmlNotationPtr ret; + xmlNotationPtr ret = NULL; xmlNotationTablePtr table; + int res; if (dtd == NULL) { return(NULL); @@ -2262,43 +2084,54 @@ xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, dict = dtd->doc->dict; dtd->notations = table = xmlHashCreateDict(0, dict); - } - if (table == NULL) { - xmlVErrMemory(ctxt, - "xmlAddNotationDecl: Table creation failed!\n"); - return(NULL); + if (table == NULL) + goto mem_error; } ret = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); - if (ret == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - return(NULL); - } + if (ret == NULL) + goto mem_error; memset(ret, 0, sizeof(xmlNotation)); /* * fill the structure. */ ret->name = xmlStrdup(name); - if (SystemID != NULL) + if (ret->name == NULL) + goto mem_error; + if (SystemID != NULL) { ret->SystemID = xmlStrdup(SystemID); - if (PublicID != NULL) + if (ret->SystemID == NULL) + goto mem_error; + } + if (PublicID != NULL) { ret->PublicID = xmlStrdup(PublicID); + if (ret->PublicID == NULL) + goto mem_error; + } /* * Validity Check: * Check the DTD for previous declarations of the ATTLIST */ - if (xmlHashAddEntry(table, name, ret)) { + res = xmlHashAdd(table, name, ret); + if (res <= 0) { + if (res < 0) + goto mem_error; #ifdef LIBXML_VALID_ENABLED - xmlErrValid(NULL, XML_DTD_NOTATION_REDEFINED, - "xmlAddNotationDecl: %s already defined\n", - (const char *) name); + xmlErrValid(ctxt, XML_DTD_NOTATION_REDEFINED, + "xmlAddNotationDecl: %s already defined\n", + (const char *) name); #endif /* LIBXML_VALID_ENABLED */ xmlFreeNotation(ret); return(NULL); } return(ret); + +mem_error: + xmlVErrMemory(ctxt); + xmlFreeNotation(ret); + return(NULL); } static void @@ -2332,23 +2165,29 @@ xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { xmlNotationPtr cur; cur = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); - if (cur == NULL) { - xmlVErrMemory(NULL, "malloc failed"); + if (cur == NULL) return(NULL); - } - if (nota->name != NULL) + memset(cur, 0, sizeof(*cur)); + if (nota->name != NULL) { cur->name = xmlStrdup(nota->name); - else - cur->name = NULL; - if (nota->PublicID != NULL) + if (cur->name == NULL) + goto error; + } + if (nota->PublicID != NULL) { cur->PublicID = xmlStrdup(nota->PublicID); - else - cur->PublicID = NULL; - if (nota->SystemID != NULL) + if (cur->PublicID == NULL) + goto error; + } + if (nota->SystemID != NULL) { cur->SystemID = xmlStrdup(nota->SystemID); - else - cur->SystemID = NULL; + if (cur->SystemID == NULL) + goto error; + } return(cur); + +error: + xmlFreeNotation(cur); + return(NULL); } /** @@ -2361,7 +2200,7 @@ xmlCopyNotation(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { */ xmlNotationTablePtr xmlCopyNotationTable(xmlNotationTablePtr table) { - return((xmlNotationTablePtr) xmlHashCopy(table, xmlCopyNotation)); + return(xmlHashCopySafe(table, xmlCopyNotation, xmlFreeNotationTableEntry)); } #endif /* LIBXML_TREE_ENABLED */ @@ -2371,39 +2210,21 @@ xmlCopyNotationTable(xmlNotationTablePtr table) { * @buf: the XML buffer output * @nota: A notation declaration * + * DEPRECATED: Don't use. + * * This will dump the content the notation declaration as an XML DTD definition */ void xmlDumpNotationDecl(xmlBufferPtr buf, xmlNotationPtr nota) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (nota == NULL)) return; - xmlBufferWriteChar(buf, "name); - if (nota->PublicID != NULL) { - xmlBufferWriteChar(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf, nota->PublicID); - if (nota->SystemID != NULL) { - xmlBufferWriteChar(buf, " "); - xmlBufferWriteQuotedString(buf, nota->SystemID); - } - } else { - xmlBufferWriteChar(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf, nota->SystemID); - } - xmlBufferWriteChar(buf, " >\n"); -} -/** - * xmlDumpNotationDeclScan: - * @nota: A notation declaration - * @buf: the XML buffer output - * - * This is called with the hash scan function, and just reverses args - */ -static void -xmlDumpNotationDeclScan(void *nota, void *buf, - const xmlChar *name ATTRIBUTE_UNUSED) { - xmlDumpNotationDecl((xmlBufferPtr) buf, (xmlNotationPtr) nota); + save = xmlSaveToBuffer(buf, NULL, 0); + xmlSaveNotationDecl(save, nota); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } /** @@ -2411,13 +2232,21 @@ xmlDumpNotationDeclScan(void *nota, void *buf, * @buf: the XML buffer output * @table: A notation table * + * DEPRECATED: Don't use. + * * This will dump the content of the notation table as an XML DTD definition */ void xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { + xmlSaveCtxtPtr save; + if ((buf == NULL) || (table == NULL)) return; - xmlHashScan(table, xmlDumpNotationDeclScan, buf); + + save = xmlSaveToBuffer(buf, NULL, 0); + xmlSaveNotationTable(save, table); + if (xmlSaveFinish(save) != XML_ERR_OK) + xmlFree(xmlBufferDetach(buf)); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -2438,35 +2267,6 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ xmlFree((char *)(str)); -/** - * xmlValidNormalizeString: - * @str: a string - * - * Normalize a string in-place. - */ -static void -xmlValidNormalizeString(xmlChar *str) { - xmlChar *dst; - const xmlChar *src; - - if (str == NULL) - return; - src = str; - dst = str; - - while (*src == 0x20) src++; - while (*src != 0) { - if (*src == 0x20) { - while (*src == 0x20) src++; - if (*src != 0) - *dst++ = 0x20; - } else { - *dst++ = *src++; - } - } - *dst = 0; -} - static int xmlIsStreaming(xmlValidCtxtPtr ctxt) { xmlParserCtxtPtr pctxt; @@ -2498,36 +2298,46 @@ xmlFreeID(xmlIDPtr id) { DICT_FREE(id->value) if (id->name != NULL) DICT_FREE(id->name) + if (id->attr != NULL) { + id->attr->id = NULL; + id->attr->atype = 0; + } + xmlFree(id); } /** - * xmlAddID: - * @ctxt: the validation context - * @doc: pointer to the document - * @value: the value name + * xmlAddIDInternal: * @attr: the attribute holding the ID + * @value: the attribute (ID) value + * @idPtr: pointer to resulting ID * * Register a new id declaration * - * Returns NULL if not, otherwise the new xmlIDPtr + * Returns 1 on success, 0 if the ID already exists, -1 if a memory + * allocation fails. */ -xmlIDPtr -xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, - xmlAttrPtr attr) { - xmlIDPtr ret; +static int +xmlAddIDInternal(xmlAttrPtr attr, const xmlChar *value, xmlIDPtr *idPtr) { + xmlDocPtr doc; + xmlIDPtr id; xmlIDTablePtr table; + int ret; - if (doc == NULL) { - return(NULL); - } - if ((value == NULL) || (value[0] == 0)) { - return(NULL); - } - if (attr == NULL) { - return(NULL); - } + if (idPtr != NULL) + *idPtr = NULL; + if ((value == NULL) || (value[0] == 0)) + return(0); + if (attr == NULL) + return(0); + + doc = attr->doc; + if (doc == NULL) + return(0); + + if (attr->id != NULL) + xmlRemoveID(doc, attr); /* * Create the ID table if needed. @@ -2535,57 +2345,109 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, table = (xmlIDTablePtr) doc->ids; if (table == NULL) { doc->ids = table = xmlHashCreateDict(0, doc->dict); - } - if (table == NULL) { - xmlVErrMemory(ctxt, - "xmlAddID: Table creation failed!\n"); - return(NULL); + if (table == NULL) + return(-1); + } else { + id = xmlHashLookup(table, value); + if (id != NULL) { + if (id->attr != NULL) { + id->attr->id = NULL; + id->attr->atype = 0; + } + ret = 0; + goto done; + } } - ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID)); - if (ret == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - return(NULL); - } + id = (xmlIDPtr) xmlMalloc(sizeof(xmlID)); + if (id == NULL) + return(-1); + memset(id, 0, sizeof(*id)); /* * fill the structure. */ - ret->value = xmlStrdup(value); - ret->doc = doc; - if (xmlIsStreaming(ctxt)) { - /* - * Operating in streaming mode, attr is gonna disappear - */ - if (doc->dict != NULL) - ret->name = xmlDictLookup(doc->dict, attr->name, -1); - else - ret->name = xmlStrdup(attr->name); - ret->attr = NULL; - } else { - ret->attr = attr; - ret->name = NULL; + id->doc = doc; + id->value = xmlStrdup(value); + if (id->value == NULL) { + xmlFreeID(id); + return(-1); } - ret->lineno = xmlGetLineNo(attr->parent); - if (xmlHashAddEntry(table, value, ret) < 0) { -#ifdef LIBXML_VALID_ENABLED - /* - * The id is already defined in this DTD. - */ - if (ctxt != NULL) { - xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED, - "ID %s already defined\n", value, NULL, NULL); - } -#endif /* LIBXML_VALID_ENABLED */ - xmlFreeID(ret); - return(NULL); + if (xmlHashAddEntry(table, value, id) < 0) { + xmlFreeID(id); + return(-1); } - if (attr != NULL) - attr->atype = XML_ATTRIBUTE_ID; + + ret = 1; + if (idPtr != NULL) + *idPtr = id; + +done: + id->attr = attr; + id->lineno = xmlGetLineNo(attr->parent); + attr->atype = XML_ATTRIBUTE_ID; + attr->id = id; + return(ret); } +/** + * xmlAddIDSafe: + * @attr: the attribute holding the ID + * @value: the attribute (ID) value + * + * Register a new id declaration + * + * Available since 2.13.0. + * + * Returns 1 on success, 0 if the ID already exists, -1 if a memory + * allocation fails. + */ +int +xmlAddIDSafe(xmlAttrPtr attr, const xmlChar *value) { + return(xmlAddIDInternal(attr, value, NULL)); +} + +/** + * xmlAddID: + * @ctxt: the validation context + * @doc: pointer to the document + * @value: the value name + * @attr: the attribute holding the ID + * + * Register a new id declaration + * + * Returns NULL if not, otherwise the new xmlIDPtr + */ +xmlIDPtr +xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + xmlAttrPtr attr) { + xmlIDPtr id; + int res; + + if ((attr == NULL) || (doc != attr->doc)) + return(NULL); + + res = xmlAddIDInternal(attr, value, &id); + if (res < 0) { + xmlVErrMemory(ctxt); + } +#ifdef LIBXML_VALID_ENABLED + else if (res == 0) { + if (ctxt != NULL) { + /* + * The id is already defined in this DTD. + */ + xmlErrValidNode(ctxt, attr->parent, XML_DTD_ID_REDEFINED, + "ID %s already defined\n", value, NULL, NULL); + } + } +#endif /* LIBXML_VALID_ENABLED */ + + return(id); +} + static void xmlFreeIDTableEntry(void *id, const xmlChar *name ATTRIBUTE_UNUSED) { xmlFreeID((xmlIDPtr) id); @@ -2613,57 +2475,67 @@ xmlFreeIDTable(xmlIDTablePtr table) { * of HTML documents parsed with the HTML parser, then ID detection is * done systematically. * - * Returns 0 or 1 depending on the lookup result + * Returns 0 or 1 depending on the lookup result or -1 if a memory allocation + * failed. */ int xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { - if ((attr == NULL) || (attr->name == NULL)) return(0); - if ((attr->ns != NULL) && (attr->ns->prefix != NULL) && - (!strcmp((char *) attr->name, "id")) && - (!strcmp((char *) attr->ns->prefix, "xml"))) - return(1); - if (doc == NULL) return(0); - if ((doc->intSubset == NULL) && (doc->extSubset == NULL) && - (doc->type != XML_HTML_DOCUMENT_NODE)) { - return(0); - } else if (doc->type == XML_HTML_DOCUMENT_NODE) { - if ((xmlStrEqual(BAD_CAST "id", attr->name)) || - ((xmlStrEqual(BAD_CAST "name", attr->name)) && - ((elem == NULL) || (xmlStrEqual(elem->name, BAD_CAST "a"))))) + if ((attr == NULL) || (attr->name == NULL)) + return(0); + + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { + if (xmlStrEqual(BAD_CAST "id", attr->name)) + return(1); + + if ((elem == NULL) || (elem->type != XML_ELEMENT_NODE)) + return(0); + + if ((xmlStrEqual(BAD_CAST "name", attr->name)) && + (xmlStrEqual(elem->name, BAD_CAST "a"))) return(1); - return(0); - } else if (elem == NULL) { - return(0); } else { xmlAttributePtr attrDecl = NULL; + xmlChar felem[50]; + xmlChar *fullelemname; + const xmlChar *aprefix; - xmlChar felem[50], fattr[50]; - xmlChar *fullelemname, *fullattrname; + if ((attr->ns != NULL) && (attr->ns->prefix != NULL) && + (!strcmp((char *) attr->name, "id")) && + (!strcmp((char *) attr->ns->prefix, "xml"))) + return(1); + + if ((doc == NULL) || + ((doc->intSubset == NULL) && (doc->extSubset == NULL))) + return(0); + + if ((elem == NULL) || + (elem->type != XML_ELEMENT_NODE) || + (elem->name == NULL)) + return(0); fullelemname = (elem->ns != NULL && elem->ns->prefix != NULL) ? xmlBuildQName(elem->name, elem->ns->prefix, felem, 50) : (xmlChar *)elem->name; + if (fullelemname == NULL) + return(-1); - fullattrname = (attr->ns != NULL && attr->ns->prefix != NULL) ? - xmlBuildQName(attr->name, attr->ns->prefix, fattr, 50) : - (xmlChar *)attr->name; + aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL; - if (fullelemname != NULL && fullattrname != NULL) { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullelemname, - fullattrname); + if (fullelemname != NULL) { + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullelemname, + attr->name, aprefix); if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullelemname, - fullattrname); + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullelemname, + attr->name, aprefix); } - if ((fullattrname != fattr) && (fullattrname != attr->name)) - xmlFree(fullattrname); if ((fullelemname != felem) && (fullelemname != elem->name)) xmlFree(fullelemname); if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID)) return(1); } + return(0); } @@ -2678,31 +2550,18 @@ xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { */ int xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { - xmlIDTablePtr table; - xmlIDPtr id; - xmlChar *ID; + xmlIDTablePtr table; if (doc == NULL) return(-1); - if (attr == NULL) return(-1); + if ((attr == NULL) || (attr->id == NULL)) return(-1); table = (xmlIDTablePtr) doc->ids; if (table == NULL) return(-1); - ID = xmlNodeListGetString(doc, attr->children, 1); - if (ID == NULL) - return(-1); - xmlValidNormalizeString(ID); - - id = xmlHashLookup(table, ID); - if (id == NULL || id->attr != attr) { - xmlFree(ID); + if (xmlHashRemoveEntry(table, attr->id->value, xmlFreeIDTableEntry) < 0) return(-1); - } - xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry); - xmlFree(ID); - attr->atype = 0; return(0); } @@ -2847,7 +2706,7 @@ xmlDummyCompare(const void *data0 ATTRIBUTE_UNUSED, xmlRefPtr xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr) { - xmlRefPtr ret; + xmlRefPtr ret = NULL; xmlRefTablePtr table; xmlListPtr ref_list; @@ -2867,28 +2726,28 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, table = (xmlRefTablePtr) doc->refs; if (table == NULL) { doc->refs = table = xmlHashCreateDict(0, doc->dict); - } - if (table == NULL) { - xmlVErrMemory(ctxt, - "xmlAddRef: Table creation failed!\n"); - return(NULL); + if (table == NULL) + goto failed; } ret = (xmlRefPtr) xmlMalloc(sizeof(xmlRef)); - if (ret == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - return(NULL); - } + if (ret == NULL) + goto failed; + memset(ret, 0, sizeof(*ret)); /* * fill the structure. */ ret->value = xmlStrdup(value); + if (ret->value == NULL) + goto failed; if (xmlIsStreaming(ctxt)) { /* * Operating in streaming mode, attr is gonna disappear */ ret->name = xmlStrdup(attr->name); + if (ret->name == NULL) + goto failed; ret->attr = NULL; } else { ret->name = NULL; @@ -2904,28 +2763,22 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, */ if (NULL == (ref_list = xmlHashLookup(table, value))) { - if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) { - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "xmlAddRef: Reference list creation failed!\n", - NULL); + int res; + + if (NULL == (ref_list = xmlListCreate(xmlFreeRef, xmlDummyCompare))) goto failed; - } - if (xmlHashAddEntry(table, value, ref_list) < 0) { + res = xmlHashAdd(table, value, ref_list); + if (res <= 0) { xmlListDelete(ref_list); - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "xmlAddRef: Reference list insertion failed!\n", - NULL); goto failed; } } - if (xmlListAppend(ref_list, ret) != 0) { - xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR, - "xmlAddRef: Reference list insertion failed!\n", - NULL); + if (xmlListAppend(ref_list, ret) != 0) goto failed; - } return(ret); + failed: + xmlVErrMemory(ctxt); if (ret != NULL) { if (ret->value != NULL) xmlFree((char *)ret->value); @@ -2979,12 +2832,15 @@ xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { return(0); } else { xmlAttributePtr attrDecl; + const xmlChar *aprefix; if (elem == NULL) return(0); - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name); + aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL; + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, attr->name, + aprefix); if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, - elem->name, attr->name); + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, attr->name, + aprefix); if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_IDREF || @@ -3047,7 +2903,7 @@ xmlRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) { /*If the list is empty then remove the list entry in the hash */ if (xmlListEmpty(ref_list)) - xmlHashUpdateEntry(table, ID, NULL, xmlFreeRefTableEntry); + xmlHashRemoveEntry(table, ID, xmlFreeRefTableEntry); xmlFree(ID); return(0); } @@ -3095,6 +2951,8 @@ xmlGetRefs(xmlDocPtr doc, const xmlChar *ID) { * * Search the DTD for the description of this element * + * NOTE: A NULL return value can also mean that a memory allocation failed. + * * returns the xmlElementPtr if found or NULL */ @@ -3102,21 +2960,26 @@ xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) { xmlElementTablePtr table; xmlElementPtr cur; - xmlChar *uqname = NULL, *prefix = NULL; + const xmlChar *localname; + xmlChar *prefix; + + if ((dtd == NULL) || (dtd->elements == NULL) || + (name == NULL)) + return(NULL); - if ((dtd == NULL) || (name == NULL)) return(NULL); - if (dtd->elements == NULL) - return(NULL); table = (xmlElementTablePtr) dtd->elements; + if (table == NULL) + return(NULL); - uqname = xmlSplitQName2(name, &prefix); - if (uqname != NULL) - name = uqname; - cur = xmlHashLookup2(table, name, prefix); - if (prefix != NULL) xmlFree(prefix); - if (uqname != NULL) xmlFree(uqname); + localname = xmlSplitQName4(name, &prefix); + if (localname == NULL) + return(NULL); + cur = xmlHashLookup2(table, localname, prefix); + if (prefix != NULL) + xmlFree(prefix); return(cur); } + /** * xmlGetDtdElementDesc2: * @dtd: a pointer to the DtD to search @@ -3129,66 +2992,64 @@ xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) { */ static xmlElementPtr -xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, - int create) { +xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name) { xmlElementTablePtr table; - xmlElementPtr cur; - xmlChar *uqname = NULL, *prefix = NULL; + xmlElementPtr cur = NULL; + const xmlChar *localName; + xmlChar *prefix = NULL; if (dtd == NULL) return(NULL); + + /* + * Create the Element table if needed. + */ if (dtd->elements == NULL) { xmlDictPtr dict = NULL; if (dtd->doc != NULL) dict = dtd->doc->dict; - if (!create) - return(NULL); - /* - * Create the Element table if needed. - */ - table = (xmlElementTablePtr) dtd->elements; - if (table == NULL) { - table = xmlHashCreateDict(0, dict); - dtd->elements = (void *) table; - } - if (table == NULL) { - xmlVErrMemory(ctxt, "element table allocation failed"); - return(NULL); - } + dtd->elements = xmlHashCreateDict(0, dict); + if (dtd->elements == NULL) + goto mem_error; } table = (xmlElementTablePtr) dtd->elements; - uqname = xmlSplitQName2(name, &prefix); - if (uqname != NULL) - name = uqname; - cur = xmlHashLookup2(table, name, prefix); - if ((cur == NULL) && (create)) { + localName = xmlSplitQName4(name, &prefix); + if (localName == NULL) + goto mem_error; + cur = xmlHashLookup2(table, localName, prefix); + if (cur == NULL) { cur = (xmlElementPtr) xmlMalloc(sizeof(xmlElement)); - if (cur == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); - goto error; - } + if (cur == NULL) + goto mem_error; memset(cur, 0, sizeof(xmlElement)); cur->type = XML_ELEMENT_DECL; + cur->doc = dtd->doc; /* * fill the structure. */ - cur->name = xmlStrdup(name); - cur->prefix = xmlStrdup(prefix); + cur->name = xmlStrdup(localName); + if (cur->name == NULL) + goto mem_error; + cur->prefix = prefix; + prefix = NULL; cur->etype = XML_ELEMENT_TYPE_UNDEFINED; - if (xmlHashAddEntry2(table, name, prefix, cur) < 0) { - xmlVErrMemory(ctxt, "adding entry failed"); - xmlFreeElement(cur); - cur = NULL; - } + if (xmlHashAdd2(table, localName, cur->prefix, cur) <= 0) + goto mem_error; } -error: - if (prefix != NULL) xmlFree(prefix); - if (uqname != NULL) xmlFree(uqname); + + if (prefix != NULL) + xmlFree(prefix); return(cur); + +mem_error: + xmlVErrMemory(ctxt); + xmlFree(prefix); + xmlFreeElement(cur); + return(NULL); } /** @@ -3230,23 +3091,23 @@ xmlAttributePtr xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) { xmlAttributeTablePtr table; xmlAttributePtr cur; - xmlChar *uqname = NULL, *prefix = NULL; + const xmlChar *localname; + xmlChar *prefix = NULL; - if (dtd == NULL) return(NULL); - if (dtd->attributes == NULL) return(NULL); + if ((dtd == NULL) || (dtd->attributes == NULL) || + (elem == NULL) || (name == NULL)) + return(NULL); table = (xmlAttributeTablePtr) dtd->attributes; if (table == NULL) return(NULL); - uqname = xmlSplitQName2(name, &prefix); - - if (uqname != NULL) { - cur = xmlHashLookup3(table, uqname, prefix, elem); - if (prefix != NULL) xmlFree(prefix); - if (uqname != NULL) xmlFree(uqname); - } else - cur = xmlHashLookup3(table, name, NULL, elem); + localname = xmlSplitQName4(name, &prefix); + if (localname == NULL) + return(NULL); + cur = xmlHashLookup3(table, localname, prefix, elem); + if (prefix != NULL) + xmlFree(prefix); return(cur); } @@ -3303,6 +3164,8 @@ xmlGetDtdNotationDesc(xmlDtdPtr dtd, const xmlChar *name) { * @doc: the document * @notationName: the notation name to check * + * DEPRECATED: Internal function, don't use. + * * Validate that the given name match a notation declaration. * - [ VC: Notation Declared ] * @@ -3370,6 +3233,35 @@ xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) { #ifdef LIBXML_VALID_ENABLED +/** + * xmlValidNormalizeString: + * @str: a string + * + * Normalize a string in-place. + */ +static void +xmlValidNormalizeString(xmlChar *str) { + xmlChar *dst; + const xmlChar *src; + + if (str == NULL) + return; + src = str; + dst = str; + + while (*src == 0x20) src++; + while (*src != 0) { + if (*src == 0x20) { + while (*src == 0x20) src++; + if (*src != 0) + *dst++ = 0x20; + } else { + *dst++ = *src++; + } + } + *dst = 0; +} + static int xmlIsDocNameStartChar(xmlDocPtr doc, int c) { if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) { @@ -3689,6 +3581,8 @@ xmlValidateNmtokensValue(const xmlChar *value) { * @doc: a document instance * @nota: a notation definition * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single notation definition * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -3745,6 +3639,8 @@ xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type, * @type: an attribute type * @value: an attribute value * + * DEPRECATED: Internal function, don't use. + * * Validate that the given attribute value match the proper production * * [ VC: ID ] @@ -3840,8 +3736,10 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlEntityPtr ent; dup = xmlStrdup(value); - if (dup == NULL) + if (dup == NULL) { + xmlVErrMemory(ctxt); return(0); + } cur = dup; while (*cur != 0) { nam = cur; @@ -3899,6 +3797,8 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @value: the attribute value * @ctxt: the validation context or NULL * + * DEPRECATED: Internal function, don't use. + * * Does the validation related extra step of the normalization of attribute * values: * @@ -3919,6 +3819,8 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { xmlChar *ret; xmlAttributePtr attrDecl = NULL; + const xmlChar *localName; + xmlChar *prefix = NULL; int extsubset = 0; if (doc == NULL) return(NULL); @@ -3926,38 +3828,47 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, if (name == NULL) return(NULL); if (value == NULL) return(NULL); - if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { - xmlChar fn[50]; - xmlChar *fullname; + localName = xmlSplitQName4(name, &prefix); + if (localName == NULL) + goto mem_error; - fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50); - if (fullname == NULL) - return(NULL); - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name); + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { + xmlChar buf[50]; + xmlChar *elemname; + + elemname = xmlBuildQName(elem->name, elem->ns->prefix, buf, 50); + if (elemname == NULL) + goto mem_error; + if (doc->intSubset != NULL) + attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName, + prefix, elemname); if ((attrDecl == NULL) && (doc->extSubset != NULL)) { - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name); + attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName, + prefix, elemname); if (attrDecl != NULL) extsubset = 1; } - if ((fullname != fn) && (fullname != elem->name)) - xmlFree(fullname); + if ((elemname != buf) && (elemname != elem->name)) + xmlFree(elemname); } if ((attrDecl == NULL) && (doc->intSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name); + attrDecl = xmlHashLookup3(doc->intSubset->attributes, localName, + prefix, elem->name); if ((attrDecl == NULL) && (doc->extSubset != NULL)) { - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name); + attrDecl = xmlHashLookup3(doc->extSubset->attributes, localName, + prefix, elem->name); if (attrDecl != NULL) extsubset = 1; } if (attrDecl == NULL) - return(NULL); + goto done; if (attrDecl->atype == XML_ATTRIBUTE_CDATA) - return(NULL); + goto done; ret = xmlStrdup(value); if (ret == NULL) - return(NULL); + goto mem_error; xmlValidNormalizeString(ret); if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, @@ -3965,7 +3876,16 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, name, elem->name, NULL); ctxt->valid = 0; } + + xmlFree(prefix); return(ret); + +mem_error: + xmlVErrMemory(ctxt); + +done: + xmlFree(prefix); + return(NULL); } /** @@ -3975,6 +3895,8 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @name: the attribute name * @value: the attribute value * + * DEPRECATED: Internal function, don't use. + * * Does the validation related extra step of the normalization of attribute * values: * @@ -4038,6 +3960,8 @@ xmlValidateAttributeIdCallback(void *payload, void *data, * @doc: a document instance * @attr: an attribute definition * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single attribute definition * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -4083,13 +4007,23 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, /* One ID per Element Type */ if (attr->atype == XML_ATTRIBUTE_ID) { + xmlElementPtr elem = NULL; + const xmlChar *elemLocalName; + xmlChar *elemPrefix; int nbId; + elemLocalName = xmlSplitQName4(attr->elem, &elemPrefix); + if (elemLocalName == NULL) { + xmlVErrMemory(ctxt); + return(0); + } + /* the trick is that we parse DtD as their own internal subset */ - xmlElementPtr elem = xmlGetDtdElementDesc(doc->intSubset, - attr->elem); + if (doc->intSubset != NULL) + elem = xmlHashLookup2(doc->intSubset->elements, + elemLocalName, elemPrefix); if (elem != NULL) { - nbId = xmlScanIDAttributeDecl(NULL, elem, 0); + nbId = xmlScanIDAttributeDecl(ctxt, elem, 0); } else { xmlAttributeTablePtr table; @@ -4109,22 +4043,28 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, "Element %s has %d ID attribute defined in the internal subset : %s\n", attr->elem, nbId, attr->name); + ret = 0; } else if (doc->extSubset != NULL) { int extId = 0; - elem = xmlGetDtdElementDesc(doc->extSubset, attr->elem); + elem = xmlHashLookup2(doc->extSubset->elements, + elemLocalName, elemPrefix); if (elem != NULL) { - extId = xmlScanIDAttributeDecl(NULL, elem, 0); + extId = xmlScanIDAttributeDecl(ctxt, elem, 0); } if (extId > 1) { xmlErrValidNodeNr(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, "Element %s has %d ID attribute defined in the external subset : %s\n", attr->elem, extId, attr->name); + ret = 0; } else if (extId + nbId > 1) { xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_SUBSET, "Element %s has ID attributes defined in the internal and external subset : %s\n", attr->elem, attr->name, NULL); + ret = 0; } } + + xmlFree(elemPrefix); } /* Validity Constraint: Enumeration */ @@ -4151,6 +4091,8 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @doc: a document instance * @elem: an element definition * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single element definition * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -4166,6 +4108,8 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlElementPtr elem) { int ret = 1; xmlElementPtr tst; + const xmlChar *localName; + xmlChar *prefix; CHECK_DTD; @@ -4229,32 +4173,47 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, } } + localName = xmlSplitQName4(elem->name, &prefix); + if (localName == NULL) { + xmlVErrMemory(ctxt); + return(0); + } + /* VC: Unique Element Type Declaration */ - tst = xmlGetDtdElementDesc(doc->intSubset, elem->name); - if ((tst != NULL ) && (tst != elem) && - ((tst->prefix == elem->prefix) || - (xmlStrEqual(tst->prefix, elem->prefix))) && - (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { - xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, - "Redefinition of element %s\n", - elem->name, NULL, NULL); - ret = 0; + if (doc->intSubset != NULL) { + tst = xmlHashLookup2(doc->intSubset->elements, localName, prefix); + + if ((tst != NULL ) && (tst != elem) && + ((tst->prefix == elem->prefix) || + (xmlStrEqual(tst->prefix, elem->prefix))) && + (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + elem->name, NULL, NULL); + ret = 0; + } } - tst = xmlGetDtdElementDesc(doc->extSubset, elem->name); - if ((tst != NULL ) && (tst != elem) && - ((tst->prefix == elem->prefix) || - (xmlStrEqual(tst->prefix, elem->prefix))) && - (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { - xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, - "Redefinition of element %s\n", - elem->name, NULL, NULL); - ret = 0; + if (doc->extSubset != NULL) { + tst = xmlHashLookup2(doc->extSubset->elements, localName, prefix); + + if ((tst != NULL ) && (tst != elem) && + ((tst->prefix == elem->prefix) || + (xmlStrEqual(tst->prefix, elem->prefix))) && + (tst->etype != XML_ELEMENT_TYPE_UNDEFINED)) { + xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_ELEM_REDEFINED, + "Redefinition of element %s\n", + elem->name, NULL, NULL); + ret = 0; + } } + /* One ID per Element Type * already done when registering the attribute if (xmlScanIDAttributeDecl(ctxt, elem) > 1) { ret = 0; } */ + + xmlFree(prefix); return(ret); } @@ -4266,6 +4225,8 @@ xmlValidateElementDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @attr: an attribute instance * @value: the attribute value (without entities processing) * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single attribute for an element * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -4288,6 +4249,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value) { xmlAttributePtr attrDecl = NULL; + const xmlChar *aprefix; int val; int ret = 1; @@ -4295,42 +4257,31 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc, if ((elem == NULL) || (elem->name == NULL)) return(0); if ((attr == NULL) || (attr->name == NULL)) return(0); + aprefix = (attr->ns != NULL) ? attr->ns->prefix : NULL; + if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) { xmlChar fn[50]; xmlChar *fullname; fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50); - if (fullname == NULL) + if (fullname == NULL) { + xmlVErrMemory(ctxt); return(0); - if (attr->ns != NULL) { - attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname, - attr->name, attr->ns->prefix); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, - attr->name, attr->ns->prefix); - } else { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, - fullname, attr->name); - } + } + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname, + attr->name, aprefix); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, + attr->name, aprefix); if ((fullname != fn) && (fullname != elem->name)) xmlFree(fullname); } if (attrDecl == NULL) { - if (attr->ns != NULL) { - attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, - attr->name, attr->ns->prefix); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, - attr->name, attr->ns->prefix); - } else { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, - elem->name, attr->name); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, - elem->name, attr->name); - } + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, + attr->name, aprefix); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, + attr->name, aprefix); } @@ -4341,6 +4292,8 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc, attr->name, elem->name, NULL); return(0); } + if (attr->atype == XML_ATTRIBUTE_ID) + xmlRemoveID(doc, attr); attr->atype = attrDecl->atype; val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value); @@ -4443,6 +4396,8 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @ns: an namespace declaration instance * @value: the attribute value (without entities processing) * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single namespace declaration for an element * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -4478,7 +4433,7 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) { fullname = xmlBuildQName(elem->name, prefix, fn, 50); if (fullname == NULL) { - xmlVErrMemory(ctxt, "Validating namespace"); + xmlVErrMemory(ctxt); return(0); } if (ns->prefix != NULL) { @@ -4488,11 +4443,11 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) { attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, ns->prefix, BAD_CAST "xmlns"); } else { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, - BAD_CAST "xmlns"); + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname, + BAD_CAST "xmlns", NULL); if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, - BAD_CAST "xmlns"); + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname, + BAD_CAST "xmlns", NULL); } if ((fullname != fn) && (fullname != elem->name)) xmlFree(fullname); @@ -4505,11 +4460,11 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) { attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, ns->prefix, BAD_CAST "xmlns"); } else { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, - elem->name, BAD_CAST "xmlns"); + attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name, + BAD_CAST "xmlns", NULL); if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, - elem->name, BAD_CAST "xmlns"); + attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name, + BAD_CAST "xmlns", NULL); } } @@ -5072,7 +5027,8 @@ xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) { strcat(buf, " ..."); return; } - strcat(buf, (char *) cur->name); + if (cur->name != NULL) + strcat(buf, (char *) cur->name); if (cur->next != NULL) strcat(buf, " "); break; @@ -5158,67 +5114,74 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child, ctxt->nodeNr = 0; ctxt->nodeTab = NULL; exec = xmlRegNewExecCtxt(elemDecl->contModel, NULL, NULL); - if (exec != NULL) { - cur = child; - while (cur != NULL) { - switch (cur->type) { - case XML_ENTITY_REF_NODE: - /* - * Push the current node to be able to roll back - * and process within the entity - */ - if ((cur->children != NULL) && - (cur->children->children != NULL)) { - nodeVPush(ctxt, cur); - cur = cur->children->children; - continue; - } - break; - case XML_TEXT_NODE: - if (xmlIsBlankNode(cur)) - break; - ret = 0; - goto fail; - case XML_CDATA_SECTION_NODE: - /* TODO */ - ret = 0; - goto fail; - case XML_ELEMENT_NODE: - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlChar fn[50]; - xmlChar *fullname; - - fullname = xmlBuildQName(cur->name, - cur->ns->prefix, fn, 50); - if (fullname == NULL) { - ret = -1; - goto fail; - } - ret = xmlRegExecPushString(exec, fullname, NULL); - if ((fullname != fn) && (fullname != cur->name)) - xmlFree(fullname); - } else { - ret = xmlRegExecPushString(exec, cur->name, NULL); - } - break; - default: - break; - } - /* - * Switch to next element - */ - cur = cur->next; - while (cur == NULL) { - cur = nodeVPop(ctxt); - if (cur == NULL) - break; - cur = cur->next; - } - } - ret = xmlRegExecPushString(exec, NULL, NULL); + if (exec == NULL) { + xmlVErrMemory(ctxt); + return(-1); + } + cur = child; + while (cur != NULL) { + switch (cur->type) { + case XML_ENTITY_REF_NODE: + /* + * Push the current node to be able to roll back + * and process within the entity + */ + if ((cur->children != NULL) && + (cur->children->children != NULL)) { + nodeVPush(ctxt, cur); + cur = cur->children->children; + continue; + } + break; + case XML_TEXT_NODE: + if (xmlIsBlankNode(cur)) + break; + ret = 0; + goto fail; + case XML_CDATA_SECTION_NODE: + /* TODO */ + ret = 0; + goto fail; + case XML_ELEMENT_NODE: + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlChar fn[50]; + xmlChar *fullname; + + fullname = xmlBuildQName(cur->name, + cur->ns->prefix, fn, 50); + if (fullname == NULL) { + xmlVErrMemory(ctxt); + ret = -1; + goto fail; + } + ret = xmlRegExecPushString(exec, fullname, NULL); + if ((fullname != fn) && (fullname != cur->name)) + xmlFree(fullname); + } else { + ret = xmlRegExecPushString(exec, cur->name, NULL); + } + break; + default: + break; + } + if (ret == XML_REGEXP_OUT_OF_MEMORY) + xmlVErrMemory(ctxt); + /* + * Switch to next element + */ + cur = cur->next; + while (cur == NULL) { + cur = nodeVPop(ctxt); + if (cur == NULL) + break; + cur = cur->next; + } + } + ret = xmlRegExecPushString(exec, NULL, NULL); + if (ret == XML_REGEXP_OUT_OF_MEMORY) + xmlVErrMemory(ctxt); fail: - xmlRegFreeExecCtxt(exec); - } + xmlRegFreeExecCtxt(exec); } #else /* LIBXML_REGEXP_ENABLED */ /* @@ -5228,7 +5191,7 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child, ctxt->vstateTab = (xmlValidState *) xmlMalloc( ctxt->vstateMax * sizeof(ctxt->vstateTab[0])); if (ctxt->vstateTab == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); return(-1); } /* @@ -5287,7 +5250,7 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child, */ tmp = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); if (tmp == NULL) { - xmlVErrMemory(ctxt, "malloc failed"); + xmlVErrMemory(ctxt); xmlFreeNodeList(repl); ret = -1; goto done; @@ -5587,9 +5550,9 @@ xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * full QName but in that case being flexible makes sense. */ if (elemDecl == NULL) { - elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name); + elemDecl = xmlGetDtdQElementDesc(doc->intSubset, elem->name, NULL); if ((elemDecl == NULL) && (doc->extSubset != NULL)) { - elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name); + elemDecl = xmlGetDtdQElementDesc(doc->extSubset, elem->name, NULL); if ((elemDecl != NULL) && (extsubset != NULL)) *extsubset = 1; } @@ -5611,6 +5574,8 @@ xmlValidGetElemDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @elem: an element instance * @qname: the qualified name as appearing in the serialization * + * DEPRECATED: Internal function, don't use. + * * Push a new element start on the validation stack. * * returns 1 if no validation problem was found or 0 otherwise @@ -5679,6 +5644,10 @@ xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, */ if (state->exec != NULL) { ret = xmlRegExecPushString(state->exec, qname, NULL); + if (ret == XML_REGEXP_OUT_OF_MEMORY) { + xmlVErrMemory(ctxt); + return(0); + } if (ret < 0) { xmlErrValidNode(ctxt, state->node, XML_DTD_CONTENT_MODEL, @@ -5704,6 +5673,8 @@ xmlValidatePushElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @data: some character data read * @len: the length of the data * + * DEPRECATED: Internal function, don't use. + * * check the CData parsed for validation in the current stack * * returns 1 if no validation problem was found or 0 otherwise @@ -5777,6 +5748,8 @@ xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) { * @elem: an element instance * @qname: the qualified name as appearing in the serialization * + * DEPRECATED: Internal function, don't use. + * * Pop the element end from the validation stack. * * returns 1 if no validation problem was found or 0 otherwise @@ -5804,8 +5777,11 @@ xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED, if (state->exec != NULL) { ret = xmlRegExecPushString(state->exec, NULL, NULL); if (ret <= 0) { - xmlErrValidNode(ctxt, state->node, - XML_DTD_CONTENT_MODEL, + if (ret == XML_REGEXP_OUT_OF_MEMORY) + xmlVErrMemory(ctxt); + else + xmlErrValidNode(ctxt, state->node, + XML_DTD_CONTENT_MODEL, "Element %s content does not follow the DTD, Expecting more children\n", state->node->name, NULL,NULL); ret = 0; @@ -5831,6 +5807,8 @@ xmlValidatePopElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc ATTRIBUTE_UNUSED, * @doc: a document instance * @elem: an element instance * + * DEPRECATED: Internal function, don't use. + * * Try to validate a single element and it's attributes, * basically it does the following checks as described by the * XML-1.0 recommendation: @@ -5858,61 +5836,19 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, if (elem == NULL) return(0); switch (elem->type) { - case XML_ATTRIBUTE_NODE: - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Attribute element not expected\n", NULL, NULL ,NULL); - return(0); case XML_TEXT_NODE: - if (elem->children != NULL) { - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Text element has children !\n", - NULL,NULL,NULL); - return(0); - } - if (elem->ns != NULL) { - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Text element has namespace !\n", - NULL,NULL,NULL); - return(0); - } - if (elem->content == NULL) { - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Text element has no content !\n", - NULL,NULL,NULL); - return(0); - } - return(1); - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return(1); case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: + case XML_XINCLUDE_START: + case XML_XINCLUDE_END: return(1); - case XML_ENTITY_NODE: - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Entity element not expected\n", NULL, NULL ,NULL); - return(0); - case XML_NOTATION_NODE: - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Notation element not expected\n", NULL, NULL ,NULL); - return(0); - case XML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "Document element not expected\n", NULL, NULL ,NULL); - return(0); - case XML_HTML_DOCUMENT_NODE: - xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "HTML Document not expected\n", NULL, NULL ,NULL); - return(0); case XML_ELEMENT_NODE: break; default: xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR, - "unknown element type\n", NULL, NULL ,NULL); + "unexpected element type\n", NULL, NULL ,NULL); return(0); } @@ -5970,8 +5906,10 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, fullname = xmlBuildQName(child->name, child->ns->prefix, fn, 50); - if (fullname == NULL) + if (fullname == NULL) { + xmlVErrMemory(ctxt); return(0); + } cont = elemDecl->content; while (cont != NULL) { if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) { @@ -6035,7 +5973,8 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, */ child = elem->children; while (child != NULL) { - if (child->type == XML_TEXT_NODE) { + if ((child->type == XML_TEXT_NODE) && + (child->content != NULL)) { const xmlChar *content = child->content; while (IS_BLANK_CH(*content)) @@ -6056,7 +5995,7 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, cont = elemDecl->content; tmp = xmlValidateElementContent(ctxt, child, elemDecl, 1, elem); if (tmp <= 0) - ret = tmp; + ret = 0; break; } } /* not continuous */ @@ -6198,6 +6137,8 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, * @ctxt: the validation context * @doc: a document instance * + * DEPRECATED: Internal function, don't use. + * * Try to validate a the root element * basically it does the following check as described by the * XML-1.0 recommendation: @@ -6237,7 +6178,7 @@ xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50); if (fullname == NULL) { - xmlVErrMemory(ctxt, NULL); + xmlVErrMemory(ctxt); return(0); } ret = xmlStrEqual(doc->intSubset->name, fullname); @@ -6291,9 +6232,13 @@ xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) { attr = elem->properties; while (attr != NULL) { value = xmlNodeListGetString(doc, attr->children, 0); - ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value); - if (value != NULL) + if (value == NULL) { + xmlVErrMemory(ctxt); + ret = 0; + } else { + ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value); xmlFree((char *)value); + } attr= attr->next; } @@ -6352,7 +6297,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt, dup = xmlStrdup(name); if (dup == NULL) { - ctxt->valid = 0; + xmlVErrMemory(ctxt); return; } cur = dup; @@ -6387,7 +6332,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt, dup = xmlStrdup(name); if (dup == NULL) { - xmlVErrMemory(ctxt, "IDREFS split"); + xmlVErrMemory(ctxt); ctxt->valid = 0; return; } @@ -6455,6 +6400,8 @@ xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) { * @ctxt: the validation context * @doc: a document instance * + * DEPRECATED: Internal function, don't use. + * * Does the final step for the document validation once all the * incremental validation steps have been completed * @@ -6468,7 +6415,8 @@ xmlValidateCheckRefCallback(void *payload, void *data, const xmlChar *name) { int xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { xmlRefTablePtr table; - unsigned int save; + xmlParserCtxtPtr pctxt = NULL; + xmlParserInputPtr oldInput = NULL; if (ctxt == NULL) return(0); @@ -6478,10 +6426,6 @@ xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { return(0); } - /* trick to get correct line id report */ - save = ctxt->flags; - ctxt->flags &= ~XML_VCTXT_USE_PCTXT; - /* * Check all the NOTATION/NOTATIONS attributes */ @@ -6491,12 +6435,24 @@ xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc) { /* * Check all the IDREF/IDREFS attributes definition for validity */ + + /* + * Don't print line numbers. + */ + if (ctxt->flags & XML_VCTXT_USE_PCTXT) { + pctxt = ctxt->userData; + oldInput = pctxt->input; + pctxt->input = NULL; + } + table = (xmlRefTablePtr) doc->refs; ctxt->doc = doc; ctxt->valid = 1; xmlHashScan(table, xmlValidateCheckRefCallback, ctxt); - ctxt->flags = save; + if (ctxt->flags & XML_VCTXT_USE_PCTXT) + pctxt->input = oldInput; + return(ctxt->valid); } @@ -6522,31 +6478,42 @@ xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd) { xmlDtdPtr oldExt, oldInt; xmlNodePtr root; - if (dtd == NULL) return(0); - if (doc == NULL) return(0); + if (dtd == NULL) + return(0); + if (doc == NULL) + return(0); + oldExt = doc->extSubset; oldInt = doc->intSubset; doc->extSubset = dtd; doc->intSubset = NULL; - ret = xmlValidateRoot(ctxt, doc); - if (ret == 0) { - doc->extSubset = oldExt; - doc->intSubset = oldInt; - return(ret); - } if (doc->ids != NULL) { - xmlFreeIDTable(doc->ids); - doc->ids = NULL; + xmlFreeIDTable(doc->ids); + doc->ids = NULL; } if (doc->refs != NULL) { - xmlFreeRefTable(doc->refs); - doc->refs = NULL; + xmlFreeRefTable(doc->refs); + doc->refs = NULL; } - root = xmlDocGetRootElement(doc); - ret = xmlValidateElement(ctxt, doc, root); - ret &= xmlValidateDocumentFinal(ctxt, doc); + + ret = xmlValidateRoot(ctxt, doc); + if (ret != 0) { + root = xmlDocGetRootElement(doc); + ret = xmlValidateElement(ctxt, doc, root); + ret &= xmlValidateDocumentFinal(ctxt, doc); + } + doc->extSubset = oldExt; doc->intSubset = oldInt; + if (doc->ids != NULL) { + xmlFreeIDTable(doc->ids); + doc->ids = NULL; + } + if (doc->refs != NULL) { + xmlFreeRefTable(doc->refs); + doc->refs = NULL; + } + return(ret); } @@ -6613,6 +6580,9 @@ xmlValidateAttributeCallback(void *payload, void *data, } } if (cur->atype == XML_ATTRIBUTE_NOTATION) { + const xmlChar *elemLocalName; + xmlChar *elemPrefix; + doc = cur->doc; if (cur->elem == NULL) { xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR, @@ -6621,13 +6591,25 @@ xmlValidateAttributeCallback(void *payload, void *data, return; } - if (doc != NULL) - elem = xmlGetDtdElementDesc(doc->intSubset, cur->elem); - if ((elem == NULL) && (doc != NULL)) - elem = xmlGetDtdElementDesc(doc->extSubset, cur->elem); + elemLocalName = xmlSplitQName4(cur->elem, &elemPrefix); + if (elemLocalName == NULL) { + xmlVErrMemory(ctxt); + return; + } + + if ((doc != NULL) && (doc->intSubset != NULL)) + elem = xmlHashLookup2(doc->intSubset->elements, + elemLocalName, elemPrefix); + if ((elem == NULL) && (doc != NULL) && (doc->extSubset != NULL)) + elem = xmlHashLookup2(doc->extSubset->elements, + elemLocalName, elemPrefix); if ((elem == NULL) && (cur->parent != NULL) && (cur->parent->type == XML_DTD_NODE)) - elem = xmlGetDtdElementDesc((xmlDtdPtr) cur->parent, cur->elem); + elem = xmlHashLookup2(((xmlDtdPtr) cur->parent)->elements, + elemLocalName, elemPrefix); + + xmlFree(elemPrefix); + if (elem == NULL) { xmlErrValidNode(ctxt, NULL, XML_DTD_UNKNOWN_ELEM, "attribute %s: could not find decl for element %s\n", @@ -6648,6 +6630,8 @@ xmlValidateAttributeCallback(void *payload, void *data, * @ctxt: the validation context * @doc: a document instance * + * DEPRECATED: Internal function, don't use. + * * Does the final step for the dtds validation once all the * subsets have been parsed * diff --git a/win32/rcVersion.h b/win32/rcVersion.h index abd2d71..47f1a9c 100644 --- a/win32/rcVersion.h +++ b/win32/rcVersion.h @@ -1,4 +1,4 @@ #define LIBXML_MAJOR_VERSION 2 -#define LIBXML_MINOR_VERSION 12 -#define LIBXML_MICRO_VERSION 8 -#define LIBXML_DOTTED_VERSION "2.12.8" +#define LIBXML_MINOR_VERSION 13 +#define LIBXML_MICRO_VERSION 0 +#define LIBXML_DOTTED_VERSION "2.13.0" diff --git a/xinclude.c b/xinclude.c index b658155..7949a1c 100644 --- a/xinclude.c +++ b/xinclude.c @@ -49,11 +49,11 @@ typedef xmlXIncludeRef *xmlXIncludeRefPtr; struct _xmlXIncludeRef { xmlChar *URI; /* the fully resolved resource URL */ xmlChar *fragment; /* the fragment in the URI */ + xmlChar *base; /* base URI of xi:include element */ xmlNodePtr elem; /* the xi:include element */ xmlNodePtr inc; /* the included copy */ int xml; /* xml or txt */ int fallback; /* fallback was loaded */ - int emptyFb; /* flag to show fallback empty */ int expanding; /* flag to detect inclusion loops */ int replace; /* should the node be replaced? */ }; @@ -89,9 +89,9 @@ struct _xmlXIncludeCtxt { int nbErrors; /* the number of errors detected */ int fatalErr; /* abort processing */ + int errNo; /* error code */ int legacy; /* using XINCLUDE_OLD_NS */ int parseFlags; /* the flags used for parsing XML documents */ - xmlChar * base; /* the current xml:base */ void *_private; /* application data */ @@ -100,6 +100,11 @@ struct _xmlXIncludeCtxt { #endif int depth; /* recursion depth */ int isStream; /* streaming mode */ + + xmlXPathContextPtr xpctxt; + + xmlStructuredErrorFunc errorHandler; + void *errorCtxt; }; static xmlXIncludeRefPtr @@ -125,15 +130,14 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree); * Handle an out of memory condition */ static void -xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, - const char *extra) +xmlXIncludeErrMemory(xmlXIncludeCtxtPtr ctxt) { - if (ctxt != NULL) - ctxt->nbErrors++; - __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, - XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, - extra, NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->fatalErr = 1; + ctxt->nbErrors++; + + xmlRaiseMemoryError(ctxt->errorHandler, NULL, ctxt->errorCtxt, + XML_FROM_XINCLUDE, NULL); } /** @@ -149,34 +153,34 @@ static void LIBXML_ATTR_FORMAT(4,0) xmlXIncludeErr(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, const char *msg, const xmlChar *extra) { - if (ctxt != NULL) - ctxt->nbErrors++; - __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, - error, XML_ERR_ERROR, NULL, 0, - (const char *) extra, NULL, NULL, 0, 0, - msg, (const char *) extra); -} + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + int res; -#if 0 -/** - * xmlXIncludeWarn: - * @ctxt: the XInclude context - * @node: the context node - * @msg: the error message - * @extra: extra information - * - * Emit an XInclude warning. - */ -static void LIBXML_ATTR_FORMAT(4,0) -xmlXIncludeWarn(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node, int error, - const char *msg, const xmlChar *extra) -{ - __xmlRaiseError(NULL, NULL, NULL, ctxt, node, XML_FROM_XINCLUDE, - error, XML_ERR_WARNING, NULL, 0, - (const char *) extra, NULL, NULL, 0, 0, - msg, (const char *) extra); + if (ctxt->fatalErr != 0) + return; + ctxt->nbErrors++; + + schannel = ctxt->errorHandler; + data = ctxt->errorCtxt; + + if (schannel == NULL) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + res = __xmlRaiseError(schannel, channel, data, ctxt, node, + XML_FROM_XINCLUDE, error, XML_ERR_ERROR, + NULL, 0, (const char *) extra, NULL, NULL, 0, 0, + msg, (const char *) extra); + if (res < 0) { + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->fatalErr = 1; + } else { + ctxt->errNo = error; + } } -#endif /** * xmlXIncludeGetProp: @@ -193,15 +197,20 @@ xmlXIncludeGetProp(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur, const xmlChar *name) { xmlChar *ret; - ret = xmlGetNsProp(cur, XINCLUDE_NS, name); + if (xmlNodeGetAttrValue(cur, name, XINCLUDE_NS, &ret) < 0) + xmlXIncludeErrMemory(ctxt); if (ret != NULL) return(ret); + if (ctxt->legacy != 0) { - ret = xmlGetNsProp(cur, XINCLUDE_OLD_NS, name); - if (ret != NULL) - return(ret); + if (xmlNodeGetAttrValue(cur, name, XINCLUDE_OLD_NS, &ret) < 0) + xmlXIncludeErrMemory(ctxt); + if (ret != NULL) + return(ret); } - ret = xmlGetProp(cur, name); + + if (xmlNodeGetAttrValue(cur, name, NULL, &ret) < 0) + xmlXIncludeErrMemory(ctxt); return(ret); } /** @@ -218,60 +227,11 @@ xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) { xmlFree(ref->URI); if (ref->fragment != NULL) xmlFree(ref->fragment); + if (ref->base != NULL) + xmlFree(ref->base); xmlFree(ref); } -/** - * xmlXIncludeNewRef: - * @ctxt: the XInclude context - * @URI: the resource URI - * @elem: the xi:include element - * - * Creates a new reference within an XInclude context - * - * Returns the new set - */ -static xmlXIncludeRefPtr -xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, - xmlNodePtr elem) { - xmlXIncludeRefPtr ret; - - ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef)); - if (ret == NULL) { - xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context"); - return(NULL); - } - memset(ret, 0, sizeof(xmlXIncludeRef)); - if (URI == NULL) - ret->URI = NULL; - else - ret->URI = xmlStrdup(URI); - ret->fragment = NULL; - ret->elem = elem; - ret->xml = 0; - ret->inc = NULL; - if (ctxt->incNr >= ctxt->incMax) { - xmlXIncludeRefPtr *tmp; -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 1; -#else - size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 4; -#endif - - tmp = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab, - newSize * sizeof(ctxt->incTab[0])); - if (tmp == NULL) { - xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context"); - xmlXIncludeFreeRef(ret); - return(NULL); - } - ctxt->incTab = tmp; - ctxt->incMax = newSize; - } - ctxt->incTab[ctxt->incNr++] = ret; - return(ret); -} - /** * xmlXIncludeNewContext: * @doc: an XML Document @@ -287,11 +247,8 @@ xmlXIncludeNewContext(xmlDocPtr doc) { if (doc == NULL) return(NULL); ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt)); - if (ret == NULL) { - xmlXIncludeErrMemory(NULL, (xmlNodePtr) doc, - "creating XInclude context"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlXIncludeCtxt)); ret->doc = doc; ret->incNr = 0; @@ -333,9 +290,8 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { } xmlFree(ctxt->txtTab); } - if (ctxt->base != NULL) { - xmlFree(ctxt->base); - } + if (ctxt->xpctxt != NULL) + xmlXPathFreeContext(ctxt->xpctxt); xmlFree(ctxt); } @@ -348,7 +304,7 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { */ static xmlDocPtr xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { - xmlDocPtr ret; + xmlDocPtr ret = NULL; xmlParserCtxtPtr pctxt; xmlParserInputPtr inputStream; @@ -356,9 +312,11 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { pctxt = xmlNewParserCtxt(); if (pctxt == NULL) { - xmlXIncludeErrMemory(ctxt, NULL, "cannot allocate parser context"); + xmlXIncludeErrMemory(ctxt); return(NULL); } + if (ctxt->errorHandler != NULL) + xmlCtxtSetErrorHandler(pctxt, ctxt->errorHandler, ctxt->errorCtxt); /* * pass in the application data to the parser context. @@ -376,25 +334,14 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { xmlDictReference(pctxt->dict); } - xmlCtxtUseOptions(pctxt, ctxt->parseFlags | XML_PARSE_DTDLOAD); - - /* Don't read from stdin. */ - if ((URL != NULL) && (strcmp(URL, "-") == 0)) - URL = "./-"; + xmlCtxtUseOptions(pctxt, ctxt->parseFlags); inputStream = xmlLoadExternalEntity(URL, NULL, pctxt); - if (inputStream == NULL) { - xmlFreeParserCtxt(pctxt); - return(NULL); - } + if (inputStream == NULL) + goto error; inputPush(pctxt, inputStream); - if (pctxt->directory == NULL) - pctxt->directory = xmlParserGetDirectory(URL); - - pctxt->loadsubset |= XML_DETECT_IDS; - xmlParseDocument(pctxt); if (pctxt->wellFormed) { @@ -406,6 +353,10 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { xmlFreeDoc(pctxt->myDoc); pctxt->myDoc = NULL; } + +error: + if (pctxt->errNo == XML_ERR_NO_MEMORY) + xmlXIncludeErrMemory(ctxt); xmlFreeParserCtxt(pctxt); return(ret); @@ -420,17 +371,17 @@ xmlXIncludeParseFile(xmlXIncludeCtxtPtr ctxt, const char *URL) { */ static xmlXIncludeRefPtr xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { - xmlXIncludeRefPtr ref; - xmlURIPtr uri; - xmlChar *URL; + xmlXIncludeRefPtr ref = NULL; + xmlXIncludeRefPtr ret = NULL; + xmlURIPtr uri = NULL; + xmlChar *href = NULL; + xmlChar *parse = NULL; xmlChar *fragment = NULL; - xmlChar *href; - xmlChar *parse; - xmlChar *base; - xmlChar *URI; + xmlChar *base = NULL; + xmlChar *tmp; int xml = 1; int local = 0; - + int res; if (ctxt == NULL) return(NULL); @@ -440,12 +391,24 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { /* * read the attributes */ + + fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER); + href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF); if (href == NULL) { + if (fragment == NULL) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_NO_HREF, + "href or xpointer must be present\n", parse); + goto error; + } + href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */ - if (href == NULL) - return(NULL); + if (href == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } } + parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE); if (parse != NULL) { if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) @@ -455,61 +418,21 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { else { xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE, "invalid value %s for 'parse'\n", parse); - if (href != NULL) - xmlFree(href); - if (parse != NULL) - xmlFree(parse); - return(NULL); + goto error; } } - /* - * compute the URI - */ - base = xmlNodeGetBase(ctxt->doc, cur); - if (base == NULL) { - URI = xmlBuildURI(href, ctxt->doc->URL); - } else { - URI = xmlBuildURI(href, base); - } - if (URI == NULL) { - xmlChar *escbase; - xmlChar *eschref; - /* - * Some escaping may be needed - */ - escbase = xmlURIEscape(base); - eschref = xmlURIEscape(href); - URI = xmlBuildURI(eschref, escbase); - if (escbase != NULL) - xmlFree(escbase); - if (eschref != NULL) - xmlFree(eschref); - } - if (parse != NULL) - xmlFree(parse); - if (href != NULL) - xmlFree(href); - if (base != NULL) - xmlFree(base); - if (URI == NULL) { - xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, - "failed build URL\n", NULL); - return(NULL); - } - fragment = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE_XPOINTER); - /* * Check the URL and remove any fragment identifier */ - uri = xmlParseURI((const char *)URI); + res = xmlParseURISafe((const char *)href, &uri); if (uri == NULL) { - xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", URI); - if (fragment != NULL) - xmlFree(fragment); - xmlFree(URI); - return(NULL); + if (res < 0) + xmlXIncludeErrMemory(ctxt); + else + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, + "invalid value href %s\n", href); + goto error; } if (uri->fragment != NULL) { @@ -522,29 +445,46 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { } else { xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_FRAGMENT_ID, "Invalid fragment identifier in URI %s use the xpointer attribute\n", - URI); - if (fragment != NULL) - xmlFree(fragment); - xmlFreeURI(uri); - xmlFree(URI); - return(NULL); + href); + goto error; } uri->fragment = NULL; } - URL = xmlSaveUri(uri); - xmlFreeURI(uri); - if (URL == NULL) { - xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", URI); - if (fragment != NULL) - xmlFree(fragment); - xmlFree(URI); - return(NULL); + tmp = xmlSaveUri(uri); + if (tmp == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + xmlFree(href); + href = tmp; + + /* + * Resolve URI + */ + + if (xmlNodeGetBaseSafe(ctxt->doc, cur, &base) < 0) { + xmlXIncludeErrMemory(ctxt); + goto error; } - xmlFree(URI); - if (xmlStrEqual(URL, ctxt->doc->URL)) - local = 1; + if (href[0] != 0) { + if (xmlBuildURISafe(href, base, &tmp) < 0) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + if (tmp == NULL) { + xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, + "failed build URL\n", NULL); + goto error; + } + xmlFree(href); + href = tmp; + + if (xmlStrEqual(href, ctxt->doc->URL)) + local = 1; + } else { + local = 1; + } /* * If local and xml then we need a fragment @@ -553,21 +493,72 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { ((fragment == NULL) || (fragment[0] == 0))) { xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION, "detected a local recursion with no xpointer in %s\n", - URL); - xmlFree(URL); - xmlFree(fragment); - return(NULL); + href); + goto error; } - ref = xmlXIncludeNewRef(ctxt, URL, cur); - xmlFree(URL); + ref = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef)); if (ref == NULL) { - xmlFree(fragment); - return(NULL); + xmlXIncludeErrMemory(ctxt); + goto error; } - ref->fragment = fragment; + memset(ref, 0, sizeof(xmlXIncludeRef)); + + ref->elem = cur; ref->xml = xml; - return(ref); + ref->URI = href; + href = NULL; + ref->fragment = fragment; + fragment = NULL; + + /* + * xml:base fixup + */ + if (((ctxt->parseFlags & XML_PARSE_NOBASEFIX) == 0) && + (cur->doc != NULL) && + ((cur->doc->parseFlags & XML_PARSE_NOBASEFIX) == 0)) { + if (base != NULL) { + ref->base = base; + base = NULL; + } else { + ref->base = xmlStrdup(BAD_CAST ""); + if (ref->base == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + } + } + + if (ctxt->incNr >= ctxt->incMax) { + xmlXIncludeRefPtr *table; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 1; +#else + size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 4; +#endif + + table = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab, + newSize * sizeof(ctxt->incTab[0])); + if (table == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + ctxt->incTab = table; + ctxt->incMax = newSize; + } + ctxt->incTab[ctxt->incNr++] = ref; + + ret = ref; + ref = NULL; + +error: + xmlXIncludeFreeRef(ref); + xmlFreeURI(uri); + xmlFree(href); + xmlFree(parse); + xmlFree(fragment); + xmlFree(base); + return(ret); } /** @@ -579,8 +570,7 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { * The XInclude recursive nature is handled at this point. */ static void -xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, - const xmlURL url ATTRIBUTE_UNUSED) { +xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc) { xmlDocPtr oldDoc; xmlXIncludeRefPtr *oldIncTab; int oldIncMax, oldIncNr, oldIsStream; @@ -618,6 +608,56 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, * * ************************************************************************/ +static void +xmlXIncludeBaseFixup(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur, xmlNodePtr copy, + const xmlChar *targetBase) { + xmlChar *base = NULL; + xmlChar *relBase = NULL; + xmlNs ns; + int res; + + if (cur->type != XML_ELEMENT_NODE) + return; + + if (xmlNodeGetBaseSafe(cur->doc, cur, &base) < 0) + xmlXIncludeErrMemory(ctxt); + + if ((base != NULL) && !xmlStrEqual(base, targetBase)) { + if (xmlBuildRelativeURISafe(base, targetBase, &relBase) < 0) { + xmlXIncludeErrMemory(ctxt); + goto done; + } + if (relBase == NULL) { + xmlXIncludeErr(ctxt, cur, + XML_XINCLUDE_HREF_URI, + "Building relative URI failed: %s\n", + base); + goto done; + } + + /* + * If the new base doesn't contain a slash, it can be omitted. + */ + if (xmlStrchr(relBase, '/') != NULL) { + res = xmlNodeSetBase(copy, relBase); + if (res < 0) + xmlXIncludeErrMemory(ctxt); + goto done; + } + } + + /* + * Delete existing xml:base if bases are equal + */ + memset(&ns, 0, sizeof(ns)); + ns.href = XML_XML_NAMESPACE; + xmlUnsetNsProp(copy, &ns, BAD_CAST "base"); + +done: + xmlFree(base); + xmlFree(relBase); +} + /** * xmlXIncludeCopyNode: * @ctxt: the XInclude context @@ -630,11 +670,13 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, */ static xmlNodePtr xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem, - int copyChildren) { + int copyChildren, const xmlChar *targetBase) { xmlNodePtr result = NULL; xmlNodePtr insertParent = NULL; xmlNodePtr insertLast = NULL; xmlNodePtr cur; + xmlNodePtr item; + int depth = 0; if (copyChildren) { cur = elem->children; @@ -663,22 +705,33 @@ xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem, /* * TODO: Insert XML_XINCLUDE_START and XML_XINCLUDE_END nodes */ - if (ref->inc != NULL) { - copy = xmlStaticCopyNodeList(ref->inc, ctxt->doc, - insertParent); - if (copy == NULL) + for (item = ref->inc; item != NULL; item = item->next) { + copy = xmlStaticCopyNode(item, ctxt->doc, insertParent, 1); + if (copy == NULL) { + xmlXIncludeErrMemory(ctxt); goto error; + } + + if (result == NULL) + result = copy; + if (insertLast != NULL) { + insertLast->next = copy; + copy->prev = insertLast; + } else if (insertParent != NULL) { + insertParent->children = copy; + } + insertLast = copy; + + if ((depth == 0) && (targetBase != NULL)) + xmlXIncludeBaseFixup(ctxt, item, copy, targetBase); } } else { copy = xmlStaticCopyNode(cur, ctxt->doc, insertParent, 2); - if (copy == NULL) + if (copy == NULL) { + xmlXIncludeErrMemory(ctxt); goto error; + } - recurse = (cur->type != XML_ENTITY_REF_NODE) && - (cur->children != NULL); - } - - if (copy != NULL) { if (result == NULL) result = copy; if (insertLast != NULL) { @@ -688,15 +741,19 @@ xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem, insertParent->children = copy; } insertLast = copy; - while (insertLast->next != NULL) { - insertLast = insertLast->next; - } + + if ((depth == 0) && (targetBase != NULL)) + xmlXIncludeBaseFixup(ctxt, cur, copy, targetBase); + + recurse = (cur->type != XML_ENTITY_REF_NODE) && + (cur->children != NULL); } if (recurse) { cur = cur->children; insertParent = insertLast; insertLast = NULL; + depth += 1; continue; } @@ -711,6 +768,7 @@ xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr elem, return(result); insertLast = insertParent; insertParent = insertParent->parent; + depth -= 1; } cur = cur->next; @@ -959,6 +1017,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr range) { } #endif /* LIBXML_XPTR_LOCS_ENABLED */ +#ifdef LIBXML_XPTR_ENABLED /** * xmlXIncludeCopyXPointer: * @ctxt: the XInclude context @@ -971,7 +1030,8 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr range) { * the caller has to free the node tree. */ static xmlNodePtr -xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { +xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj, + const xmlChar *targetBase) { xmlNodePtr list = NULL, last = NULL, copy; int i; @@ -981,7 +1041,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { case XPATH_NODESET: { xmlNodeSetPtr set = obj->nodesetval; if (set == NULL) - return(NULL); + break; for (i = 0;i < set->nodeNr;i++) { xmlNodePtr node; @@ -995,11 +1055,11 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { if (node == NULL) { xmlXIncludeErr(ctxt, set->nodeTab[i], XML_ERR_INTERNAL_ERROR, - "document without root\n", NULL); + "document without root\n", NULL); continue; } break; - case XML_TEXT_NODE: + case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_ELEMENT_NODE: case XML_PI_NODE: @@ -1019,7 +1079,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { * xmlXIncludeCopyNode is only required for the initial * document. */ - copy = xmlXIncludeCopyNode(ctxt, node, 0); + copy = xmlXIncludeCopyNode(ctxt, node, 0, targetBase); if (copy == NULL) { xmlFreeNodeList(list); return(NULL); @@ -1044,10 +1104,12 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { for (i = 0;i < set->locNr;i++) { if (last == NULL) list = last = xmlXIncludeCopyXPointer(ctxt, - set->locTab[i]); + set->locTab[i], + targetBase); else xmlAddNextSibling(last, - xmlXIncludeCopyXPointer(ctxt, set->locTab[i])); + xmlXIncludeCopyXPointer(ctxt, set->locTab[i], + targetBase)); if (last != NULL) { while (last->next != NULL) last = last->next; @@ -1066,6 +1128,8 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlXPathObjectPtr obj) { } return(list); } +#endif + /************************************************************************ * * * XInclude I/O handling * @@ -1112,32 +1176,36 @@ xmlXIncludeMergeEntity(void *payload, void *vdata, case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: break; } - ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID, - ent->SystemID, ent->content); - if (ret != NULL) { - if (ent->URI != NULL) + prev = xmlGetDocEntity(doc, ent->name); + if (prev == NULL) { + ret = xmlAddDocEntity(doc, ent->name, ent->etype, ent->ExternalID, + ent->SystemID, ent->content); + if (ret == NULL) { + xmlXIncludeErrMemory(ctxt); + return; + } + if (ent->URI != NULL) { ret->URI = xmlStrdup(ent->URI); + if (ret->URI == 0) + xmlXIncludeErrMemory(ctxt); + } } else { - prev = xmlGetDocEntity(doc, ent->name); - if (prev != NULL) { - if (ent->etype != prev->etype) - goto error; - - if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) { - if (!xmlStrEqual(ent->SystemID, prev->SystemID)) - goto error; - } else if ((ent->ExternalID != NULL) && - (prev->ExternalID != NULL)) { - if (!xmlStrEqual(ent->ExternalID, prev->ExternalID)) - goto error; - } else if ((ent->content != NULL) && (prev->content != NULL)) { - if (!xmlStrEqual(ent->content, prev->content)) - goto error; - } else { - goto error; - } + if (ent->etype != prev->etype) + goto error; - } + if ((ent->SystemID != NULL) && (prev->SystemID != NULL)) { + if (!xmlStrEqual(ent->SystemID, prev->SystemID)) + goto error; + } else if ((ent->ExternalID != NULL) && + (prev->ExternalID != NULL)) { + if (!xmlStrEqual(ent->ExternalID, prev->ExternalID)) + goto error; + } else if ((ent->content != NULL) && (prev->content != NULL)) { + if (!xmlStrEqual(ent->content, prev->content)) + goto error; + } else { + goto error; + } } return; error: @@ -1184,8 +1252,10 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, if (cur == NULL) return(-1); target = xmlCreateIntSubset(doc, cur->name, NULL, NULL); - if (target == NULL) + if (target == NULL) { + xmlXIncludeErrMemory(ctxt); return(-1); + } } source = from->intSubset; @@ -1228,13 +1298,11 @@ xmlXIncludeMergeEntities(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, * Returns 0 in case of success, -1 in case of failure */ static int -xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, - xmlXIncludeRefPtr ref) { +xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { xmlXIncludeDocPtr cache; xmlDocPtr doc; - xmlURIPtr uri; - xmlChar *URL = NULL; - xmlChar *fragment = NULL; + const xmlChar *url = ref->URI; + const xmlChar *fragment = ref->fragment; int i = 0; int ret = -1; int cacheNr; @@ -1242,37 +1310,12 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int saveFlags; #endif - /* - * Check the URL and remove any fragment identifier - */ - uri = xmlParseURI((const char *)url); - if (uri == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", url); - goto error; - } - if (uri->fragment != NULL) { - fragment = (xmlChar *) uri->fragment; - uri->fragment = NULL; - } - if (ref->fragment != NULL) { - if (fragment != NULL) xmlFree(fragment); - fragment = xmlStrdup(ref->fragment); - } - URL = xmlSaveUri(uri); - xmlFreeURI(uri); - if (URL == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", url); - goto error; - } - /* * Handling of references to the local document are done * directly through ctxt->doc. */ - if ((URL[0] == 0) || (URL[0] == '#') || - ((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) { + if ((url[0] == 0) || (url[0] == '#') || + ((ctxt->doc != NULL) && (xmlStrEqual(url, ctxt->doc->URL)))) { doc = ctxt->doc; goto loaded; } @@ -1281,7 +1324,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * Prevent reloading the document twice. */ for (i = 0; i < ctxt->urlNr; i++) { - if (xmlStrEqual(URL, ctxt->urlTab[i].url)) { + if (xmlStrEqual(url, ctxt->urlTab[i].url)) { if (ctxt->urlTab[i].expanding) { xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_RECURSION, "inclusion loop detected\n", NULL); @@ -1309,7 +1352,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, } #endif - doc = xmlXIncludeParseFile(ctxt, (const char *)URL); + doc = xmlXIncludeParseFile(ctxt, (const char *)url); #ifdef LIBXML_XPTR_ENABLED ctxt->parseFlags = saveFlags; #endif @@ -1325,19 +1368,23 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, tmp = xmlRealloc(ctxt->urlTab, sizeof(xmlXIncludeDoc) * newSize); if (tmp == NULL) { - xmlXIncludeErrMemory(ctxt, ref->elem, - "growing XInclude URL table"); + xmlXIncludeErrMemory(ctxt); xmlFreeDoc(doc); goto error; } ctxt->urlMax = newSize; ctxt->urlTab = tmp; } - cacheNr = ctxt->urlNr++; - cache = &ctxt->urlTab[cacheNr]; + cache = &ctxt->urlTab[ctxt->urlNr]; cache->doc = doc; - cache->url = xmlStrdup(URL); + cache->url = xmlStrdup(url); + if (cache->url == NULL) { + xmlXIncludeErrMemory(ctxt); + xmlFreeDoc(doc); + goto error; + } cache->expanding = 0; + cacheNr = ctxt->urlNr++; if (doc == NULL) goto error; @@ -1347,10 +1394,8 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * To check for this, we compare the URL with that of the doc * and change it if they disagree (bug 146988). */ - if (!xmlStrEqual(URL, doc->URL)) { - xmlFree(URL); - URL = xmlStrdup(doc->URL); - } + if ((doc->URL != NULL) && (!xmlStrEqual(url, doc->URL))) + url = doc->URL; /* * Make sure we have all entities fixed up @@ -1371,17 +1416,30 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, } */ cache->expanding = 1; - xmlXIncludeRecurseDoc(ctxt, doc, URL); + xmlXIncludeRecurseDoc(ctxt, doc); /* urlTab might be reallocated. */ cache = &ctxt->urlTab[cacheNr]; cache->expanding = 0; loaded: if (fragment == NULL) { - /* - * Add the top children list as the replacement copy. - */ - ref->inc = xmlDocCopyNode(xmlDocGetRootElement(doc), ctxt->doc, 1); + xmlNodePtr root; + + root = xmlDocGetRootElement(doc); + if (root == NULL) { + xmlXIncludeErr(ctxt, ref->elem, XML_ERR_INTERNAL_ERROR, + "document without root\n", NULL); + goto error; + } + + ref->inc = xmlDocCopyNode(root, ctxt->doc, 1); + if (ref->inc == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + + if (ref->base != NULL) + xmlXIncludeBaseFixup(ctxt, root, ref->inc, ref->base); } #ifdef LIBXML_XPTR_ENABLED else { @@ -1390,7 +1448,6 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * as the replacement copy. */ xmlXPathObjectPtr xptr; - xmlXPathContextPtr xptrctxt; xmlNodeSetPtr set; if (ctxt->isStream && doc == ctxt->doc) { @@ -1400,18 +1457,27 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, goto error; } - xptrctxt = xmlXPtrNewContext(doc, NULL, NULL); - if (xptrctxt == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED, - "could not create XPointer context\n", NULL); - goto error; - } - xptr = xmlXPtrEval(fragment, xptrctxt); + if (ctxt->xpctxt == NULL) { + ctxt->xpctxt = xmlXPtrNewContext(doc, NULL, NULL); + if (ctxt->xpctxt == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + if (ctxt->errorHandler != NULL) + xmlXPathSetErrorHandler(ctxt->xpctxt, ctxt->errorHandler, + ctxt->errorCtxt); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + ctxt->xpctxt->opLimit = 100000; +#endif + } + xptr = xmlXPtrEval(fragment, ctxt->xpctxt); if (xptr == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED, - "XPointer evaluation failed: #%s\n", - fragment); - xmlXPathFreeContext(xptrctxt); + if (ctxt->xpctxt->lastError.code == XML_ERR_NO_MEMORY) + xmlXIncludeErrMemory(ctxt); + else + xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_XPTR_FAILED, + "XPointer evaluation failed: #%s\n", + fragment); goto error; } switch (xptr->type) { @@ -1428,15 +1494,9 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, "XPointer is not a range: #%s\n", fragment); xmlXPathFreeObject(xptr); - xmlXPathFreeContext(xptrctxt); goto error; case XPATH_NODESET: - if ((xptr->nodesetval == NULL) || - (xptr->nodesetval->nodeNr <= 0)) { - xmlXPathFreeObject(xptr); - xmlXPathFreeContext(xptrctxt); - goto error; - } + break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_RANGE: @@ -1494,106 +1554,20 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, } } } - ref->inc = xmlXIncludeCopyXPointer(ctxt, xptr); + ref->inc = xmlXIncludeCopyXPointer(ctxt, xptr, ref->base); xmlXPathFreeObject(xptr); - xmlXPathFreeContext(xptrctxt); } #endif - /* - * Do the xml:base fixup if needed - */ - if ((doc != NULL) && (URL != NULL) && - (!(ctxt->parseFlags & XML_PARSE_NOBASEFIX)) && - (!(doc->parseFlags & XML_PARSE_NOBASEFIX))) { - xmlNodePtr node; - xmlChar *base; - xmlChar *curBase; - - /* - * The base is only adjusted if "necessary", i.e. if the xinclude node - * has a base specified, or the URL is relative - */ - base = xmlGetNsProp(ref->elem, BAD_CAST "base", XML_XML_NAMESPACE); - if (base == NULL) { - /* - * No xml:base on the xinclude node, so we check whether the - * URI base is different than (relative to) the context base - */ - curBase = xmlBuildRelativeURI(URL, ctxt->base); - if (curBase == NULL) { /* Error return */ - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI, - "trying to build relative URI from %s\n", URL); - } else { - /* If the URI doesn't contain a slash, it's not relative */ - if (!xmlStrchr(curBase, '/')) - xmlFree(curBase); - else - base = curBase; - } - } - if (base != NULL) { /* Adjustment may be needed */ - node = ref->inc; - while (node != NULL) { - /* Only work on element nodes */ - if (node->type == XML_ELEMENT_NODE) { - curBase = xmlNodeGetBase(node->doc, node); - /* If no current base, set it */ - if (curBase == NULL) { - xmlNodeSetBase(node, base); - } else { - /* - * If the current base is the same as the - * URL of the document, then reset it to be - * the specified xml:base or the relative URI - */ - if (xmlStrEqual(curBase, node->doc->URL)) { - xmlNodeSetBase(node, base); - } else { - /* - * If the element already has an xml:base - * set, then relativise it if necessary - */ - xmlChar *xmlBase; - xmlBase = xmlGetNsProp(node, - BAD_CAST "base", - XML_XML_NAMESPACE); - if (xmlBase != NULL) { - xmlChar *relBase; - relBase = xmlBuildURI(xmlBase, base); - if (relBase == NULL) { /* error */ - xmlXIncludeErr(ctxt, - ref->elem, - XML_XINCLUDE_HREF_URI, - "trying to rebuild base from %s\n", - xmlBase); - } else { - xmlNodeSetBase(node, relBase); - xmlFree(relBase); - } - xmlFree(xmlBase); - } - } - xmlFree(curBase); - } - } - node = node->next; - } - xmlFree(base); - } - } ret = 0; error: - xmlFree(URL); - xmlFree(fragment); return(ret); } /** * xmlXIncludeLoadTxt: * @ctxt: the XInclude context - * @url: the associated URL * @ref: an XMLXincludeRefPtr * * Load the content, and store the result in the XInclude context @@ -1601,53 +1575,25 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * Returns 0 in case of success, -1 in case of failure */ static int -xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, - xmlXIncludeRefPtr ref) { +xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { xmlParserInputBufferPtr buf; xmlNodePtr node = NULL; - xmlURIPtr uri = NULL; - xmlChar *URL = NULL; + const xmlChar *url = ref->URI; int i; int ret = -1; xmlChar *encoding = NULL; - xmlCharEncoding enc = (xmlCharEncoding) 0; + xmlCharEncodingHandlerPtr handler = NULL; xmlParserCtxtPtr pctxt = NULL; xmlParserInputPtr inputStream = NULL; int len; + int res; const xmlChar *content; - - /* Don't read from stdin. */ - if (xmlStrcmp(url, BAD_CAST "-") == 0) - url = BAD_CAST "./-"; - - /* - * Check the URL and remove any fragment identifier - */ - uri = xmlParseURI((const char *)url); - if (uri == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", url); - goto error; - } - if (uri->fragment != NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_TEXT_FRAGMENT, - "fragment identifier forbidden for text: %s\n", - (const xmlChar *) uri->fragment); - goto error; - } - URL = xmlSaveUri(uri); - if (URL == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_HREF_URI, - "invalid value URI %s\n", url); - goto error; - } - /* * Handling of references to the local document are done * directly through ctxt->doc. */ - if (URL[0] == 0) { + if (url[0] == 0) { xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_TEXT_DOCUMENT, "text serialization of document not available\n", NULL); goto error; @@ -1657,8 +1603,10 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * Prevent reloading the document twice. */ for (i = 0; i < ctxt->txtNr; i++) { - if (xmlStrEqual(URL, ctxt->txtTab[i].url)) { + if (xmlStrEqual(url, ctxt->txtTab[i].url)) { node = xmlNewDocText(ctxt->doc, ctxt->txtTab[i].text); + if (node == NULL) + xmlXIncludeErrMemory(ctxt); goto loaded; } } @@ -1667,47 +1615,70 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, * Try to get the encoding if available */ if (ref->elem != NULL) { - encoding = xmlGetProp(ref->elem, XINCLUDE_PARSE_ENCODING); + encoding = xmlXIncludeGetProp(ctxt, ref->elem, XINCLUDE_PARSE_ENCODING); } if (encoding != NULL) { - /* - * TODO: we should not have to remap to the xmlCharEncoding - * predefined set, a better interface than - * xmlParserInputBufferCreateFilename should allow any - * encoding supported by iconv - */ - enc = xmlParseCharEncoding((const char *) encoding); - if (enc == XML_CHAR_ENCODING_ERROR) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_UNKNOWN_ENCODING, - "encoding %s not supported\n", encoding); - goto error; - } + res = xmlOpenCharEncodingHandler((const char *) encoding, + /* output */ 0, &handler); + + if (res != 0) { + if (res == XML_ERR_NO_MEMORY) { + xmlXIncludeErrMemory(ctxt); + } else if (res == XML_ERR_UNSUPPORTED_ENCODING) { + xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_UNKNOWN_ENCODING, + "encoding %s not supported\n", encoding); + goto error; + } else { + xmlXIncludeErr(ctxt, ref->elem, res, + "unexpected error from iconv or ICU\n", NULL); + goto error; + } + } } /* * Load it. */ pctxt = xmlNewParserCtxt(); - inputStream = xmlLoadExternalEntity((const char*)URL, NULL, pctxt); - if(inputStream == NULL) + if (pctxt == NULL) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + inputStream = xmlLoadExternalEntity((const char*)url, NULL, pctxt); + if (inputStream == NULL) { + if (pctxt->errNo == XML_ERR_NO_MEMORY) + xmlXIncludeErrMemory(ctxt); + else + xmlXIncludeErr(ctxt, NULL, pctxt->errNo, "load error", NULL); goto error; + } buf = inputStream->buf; if (buf == NULL) goto error; if (buf->encoder) xmlCharEncCloseFunc(buf->encoder); - buf->encoder = xmlGetCharEncodingHandler(enc); + buf->encoder = handler; + handler = NULL; + node = xmlNewDocText(ctxt->doc, NULL); if (node == NULL) { - xmlXIncludeErrMemory(ctxt, ref->elem, NULL); + xmlXIncludeErrMemory(ctxt); goto error; } /* * Scan all chars from the resource and add the to the node */ - while (xmlParserInputBufferRead(buf, 4096) > 0) - ; + do { + res = xmlParserInputBufferRead(buf, 4096); + } while (res > 0); + if (res < 0) { + if (buf->error == XML_ERR_NO_MEMORY) + xmlXIncludeErrMemory(ctxt); + else + xmlXIncludeErr(ctxt, NULL, buf->error, "read error", NULL); + goto error; + } content = xmlBufContent(buf->buffer); len = xmlBufLength(buf->buffer); @@ -1719,14 +1690,15 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, cur = xmlGetUTF8Char(&content[i], &l); if ((cur < 0) || (!IS_CHAR(cur))) { xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_INVALID_CHAR, - "%s contains invalid char\n", URL); + "%s contains invalid char\n", url); goto error; } i += l; } - xmlNodeAddContentLen(node, content, len); + if (xmlNodeAddContentLen(node, content, len) < 0) + xmlXIncludeErrMemory(ctxt); if (ctxt->txtNr >= ctxt->txtMax) { xmlXIncludeTxt *tmp; @@ -1738,15 +1710,24 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, tmp = xmlRealloc(ctxt->txtTab, sizeof(xmlXIncludeTxt) * newSize); if (tmp == NULL) { - xmlXIncludeErrMemory(ctxt, ref->elem, - "growing XInclude text table"); + xmlXIncludeErrMemory(ctxt); goto error; } ctxt->txtMax = newSize; ctxt->txtTab = tmp; } ctxt->txtTab[ctxt->txtNr].text = xmlStrdup(node->content); - ctxt->txtTab[ctxt->txtNr].url = xmlStrdup(URL); + if ((node->content != NULL) && + (ctxt->txtTab[ctxt->txtNr].text == NULL)) { + xmlXIncludeErrMemory(ctxt); + goto error; + } + ctxt->txtTab[ctxt->txtNr].url = xmlStrdup(url); + if (ctxt->txtTab[ctxt->txtNr].url == NULL) { + xmlXIncludeErrMemory(ctxt); + xmlFree(ctxt->txtTab[ctxt->txtNr].text); + goto error; + } ctxt->txtNr++; loaded: @@ -1761,9 +1742,8 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, xmlFreeNode(node); xmlFreeInputStream(inputStream); xmlFreeParserCtxt(pctxt); + xmlCharEncCloseFunc(handler); xmlFree(encoding); - xmlFreeURI(uri); - xmlFree(URL); return(ret); } @@ -1793,14 +1773,11 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, * (Bug 129969), so we re-process the fallback just in case */ oldNbErrors = ctxt->nbErrors; - ref->inc = xmlXIncludeCopyNode(ctxt, fallback, 1); + ref->inc = xmlXIncludeCopyNode(ctxt, fallback, 1, ref->base); if (ctxt->nbErrors > oldNbErrors) ret = -1; - else if (ref->inc == NULL) - ref->emptyFb = 1; } else { ref->inc = NULL; - ref->emptyFb = 1; /* flag empty callback */ } ref->fallback = 1; return(ret); @@ -1896,12 +1873,6 @@ xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { static int xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { xmlNodePtr cur; - xmlChar *href; - xmlChar *parse; - xmlChar *base; - xmlChar *oldBase; - xmlChar *URI; - int xml = 1; /* default Issue 64 */ int ret; if ((ctxt == NULL) || (ref == NULL)) @@ -1910,85 +1881,13 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { if (cur == NULL) return(-1); - /* - * read the attributes - */ - href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF); - if (href == NULL) { - href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */ - if (href == NULL) - return(-1); - } - parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE); - if (parse != NULL) { - if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) - xml = 1; - else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT)) - xml = 0; - else { - xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_PARSE_VALUE, - "invalid value %s for 'parse'\n", parse); - if (href != NULL) - xmlFree(href); - if (parse != NULL) - xmlFree(parse); - return(-1); - } - } - - /* - * compute the URI - */ - base = xmlNodeGetBase(ctxt->doc, cur); - if (base == NULL) { - URI = xmlBuildURI(href, ctxt->doc->URL); - } else { - URI = xmlBuildURI(href, base); - } - if (URI == NULL) { - xmlChar *escbase; - xmlChar *eschref; - /* - * Some escaping may be needed - */ - escbase = xmlURIEscape(base); - eschref = xmlURIEscape(href); - URI = xmlBuildURI(eschref, escbase); - if (escbase != NULL) - xmlFree(escbase); - if (eschref != NULL) - xmlFree(eschref); - } - if (URI == NULL) { - xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_HREF_URI, - "failed build URL\n", NULL); - if (parse != NULL) - xmlFree(parse); - if (href != NULL) - xmlFree(href); - if (base != NULL) - xmlFree(base); - return(-1); - } - - /* - * Save the base for this include (saving the current one) - */ - oldBase = ctxt->base; - ctxt->base = base; - - if (xml) { - ret = xmlXIncludeLoadDoc(ctxt, URI, ref); + if (ref->xml) { + ret = xmlXIncludeLoadDoc(ctxt, ref); /* xmlXIncludeGetFragment(ctxt, cur, URI); */ } else { - ret = xmlXIncludeLoadTxt(ctxt, URI, ref); + ret = xmlXIncludeLoadTxt(ctxt, ref); } - /* - * Restore the original base before checking for fallback - */ - ctxt->base = oldBase; - if (ret < 0) { xmlNodePtr children; @@ -2011,20 +1910,9 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { if (ret < 0) { xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_NO_FALLBACK, "could not load %s, and no fallback was found\n", - URI); + ref->URI); } - /* - * Cleanup - */ - if (URI != NULL) - xmlFree(URI); - if (parse != NULL) - xmlFree(parse); - if (href != NULL) - xmlFree(href); - if (base != NULL) - xmlFree(base); return(0); } @@ -2049,7 +1937,6 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { list = ref->inc; ref->inc = NULL; - ref->emptyFb = 0; /* * Check against the risk of generating a multi-rooted document @@ -2076,16 +1963,19 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) { /* * Add the list of nodes + * + * TODO: Coalesce text nodes unless we are streaming mode. */ while (list != NULL) { end = list; list = list->next; - xmlAddPrevSibling(cur, end); + if (xmlAddPrevSibling(cur, end) == NULL) { + xmlUnlinkNode(end); + xmlFreeNode(end); + goto err_memory; + } } - /* - * FIXME: xmlUnlinkNode doesn't coalesce text nodes. - */ xmlUnlinkNode(cur); xmlFreeNode(cur); } else { @@ -2105,14 +1995,13 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { xmlFreeNode(child); } end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL); - if (end == NULL) { - xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_BUILD_FAILED, - "failed to build node\n", NULL); - xmlFreeNodeList(list); - return(-1); - } + if (end == NULL) + goto err_memory; end->type = XML_XINCLUDE_END; - xmlAddNextSibling(cur, end); + if (xmlAddNextSibling(cur, end) == NULL) { + xmlFreeNode(end); + goto err_memory; + } /* * Add the list of nodes @@ -2121,12 +2010,21 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { cur = list; list = list->next; - xmlAddPrevSibling(end, cur); + if (xmlAddPrevSibling(end, cur) == NULL) { + xmlUnlinkNode(cur); + xmlFreeNode(cur); + goto err_memory; + } } } return(0); + +err_memory: + xmlXIncludeErrMemory(ctxt); + xmlFreeNodeList(list); + return(-1); } /** @@ -2222,11 +2120,6 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) { int ret = 0; int i, start; - if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL)) - return(-1); - if (ctxt == NULL) - return(-1); - /* * First phase: lookup the elements in the document */ @@ -2263,10 +2156,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) { */ for (i = start; i < ctxt->incNr; i++) { if (ctxt->incTab[i]->replace != 0) { - if ((ctxt->incTab[i]->inc != NULL) || - (ctxt->incTab[i]->emptyFb != 0)) { /* (empty fallback) */ - xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]); - } + xmlXIncludeIncludeNode(ctxt, ctxt->incTab[i]); ctxt->incTab[i]->replace = 0; } else { /* @@ -2296,6 +2186,61 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) { return(ret); } +/** + * xmlXIncludeDoProcessRoot: + * @ctxt: the XInclude processing context + * @tree: the top of the tree to process + * + * Implement the XInclude substitution on the XML document @doc + * + * Returns 0 if no substitution were done, -1 if some processing failed + * or the number of substitutions done. + */ +static int +xmlXIncludeDoProcessRoot(xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree) { + if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL)) + return(-1); + if (ctxt == NULL) + return(-1); + + return(xmlXIncludeDoProcess(ctxt, tree)); +} + +/** + * xmlXIncludeGetLastError: + * @ctxt: an XInclude processing context + * + * Available since 2.13.0. + * + * Returns the last error code. + */ +int +xmlXIncludeGetLastError(xmlXIncludeCtxtPtr ctxt) { + if (ctxt == NULL) + return(XML_ERR_ARGUMENT); + return(ctxt->errNo); +} + +/** + * xmlXIncludeSetErrorHandler: + * @ctxt: an XInclude processing context + * @handler: error handler + * @data: user data which will be passed to the handler + * + * Register a callback function that will be called on errors and + * warnings. If handler is NULL, the error handler will be deactivated. + * + * Available since 2.13.0. + */ +void +xmlXIncludeSetErrorHandler(xmlXIncludeCtxtPtr ctxt, + xmlStructuredErrorFunc handler, void *data) { + if (ctxt == NULL) + return; + ctxt->errorHandler = handler; + ctxt->errorCtxt = data; +} + /** * xmlXIncludeSetFlags: * @ctxt: an XInclude processing context @@ -2356,9 +2301,8 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) { if (ctxt == NULL) return(-1); ctxt->_private = data; - ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL); xmlXIncludeSetFlags(ctxt, flags); - ret = xmlXIncludeDoProcess(ctxt, tree); + ret = xmlXIncludeDoProcessRoot(ctxt, tree); if ((ret >= 0) && (ctxt->nbErrors > 0)) ret = -1; @@ -2440,9 +2384,8 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) { ctxt = xmlXIncludeNewContext(tree->doc); if (ctxt == NULL) return(-1); - ctxt->base = xmlNodeGetBase(tree->doc, tree); xmlXIncludeSetFlags(ctxt, flags); - ret = xmlXIncludeDoProcess(ctxt, tree); + ret = xmlXIncludeDoProcessRoot(ctxt, tree); if ((ret >= 0) && (ctxt->nbErrors > 0)) ret = -1; @@ -2482,7 +2425,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (node->doc == NULL) || (ctxt == NULL)) return(-1); - ret = xmlXIncludeDoProcess(ctxt, node); + ret = xmlXIncludeDoProcessRoot(ctxt, node); if ((ret >= 0) && (ctxt->nbErrors > 0)) ret = -1; return(ret); diff --git a/xmlIO.c b/xmlIO.c index 22acb59..1156715 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -4,8 +4,6 @@ * See Copyright for the status of this software. * * daniel@veillard.com - * - * 14 Nov 2000 ht - for VMS, truncated name of long functions to under 32 char */ #define IN_LIBXML @@ -44,22 +42,8 @@ #include #endif -#ifndef S_ISDIR -# ifdef _S_ISDIR -# define S_ISDIR(x) _S_ISDIR(x) -# elif defined(S_IFDIR) -# ifdef S_IFMT -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -# elif defined(_S_IFMT) -# define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR) -# endif -# endif -#endif - #include #include -#include -#include #include #include #include @@ -78,6 +62,22 @@ #define MINLEN 4000 +#ifndef STDOUT_FILENO + #define STDOUT_FILENO 1 +#endif + +#ifndef S_ISDIR +# ifdef _S_ISDIR +# define S_ISDIR(x) _S_ISDIR(x) +# elif defined(S_IFDIR) +# ifdef S_IFMT +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# elif defined(_S_IFMT) +# define S_ISDIR(m) (((m) & _S_IFMT) == S_IFDIR) +# endif +# endif +#endif + /* * Input I/O callback sets */ @@ -88,11 +88,14 @@ typedef struct _xmlInputCallback { xmlInputCloseCallback closecallback; } xmlInputCallback; -#define MAX_INPUT_CALLBACK 15 +/* This dummy function only marks default IO in the callback table */ +static int +xmlIODefaultMatch(const char *filename); + +#define MAX_INPUT_CALLBACK 10 static xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK]; -static int xmlInputCallbackNr = 0; -static int xmlInputCallbackInitialized = 0; +static int xmlInputCallbackNr; #ifdef LIBXML_OUTPUT_ENABLED /* @@ -105,112 +108,18 @@ typedef struct _xmlOutputCallback { xmlOutputCloseCallback closecallback; } xmlOutputCallback; -#define MAX_OUTPUT_CALLBACK 15 +#define MAX_OUTPUT_CALLBACK 10 static xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK]; -static int xmlOutputCallbackNr = 0; -static int xmlOutputCallbackInitialized = 0; +static int xmlOutputCallbackNr; #endif /* LIBXML_OUTPUT_ENABLED */ /************************************************************************ * * - * Tree memory error handler * + * Error handling * * * ************************************************************************/ -static const char* const IOerr[] = { - "Unknown IO error", /* UNKNOWN */ - "Permission denied", /* EACCES */ - "Resource temporarily unavailable",/* EAGAIN */ - "Bad file descriptor", /* EBADF */ - "Bad message", /* EBADMSG */ - "Resource busy", /* EBUSY */ - "Operation canceled", /* ECANCELED */ - "No child processes", /* ECHILD */ - "Resource deadlock avoided",/* EDEADLK */ - "Domain error", /* EDOM */ - "File exists", /* EEXIST */ - "Bad address", /* EFAULT */ - "File too large", /* EFBIG */ - "Operation in progress", /* EINPROGRESS */ - "Interrupted function call",/* EINTR */ - "Invalid argument", /* EINVAL */ - "Input/output error", /* EIO */ - "Is a directory", /* EISDIR */ - "Too many open files", /* EMFILE */ - "Too many links", /* EMLINK */ - "Inappropriate message buffer length",/* EMSGSIZE */ - "Filename too long", /* ENAMETOOLONG */ - "Too many open files in system",/* ENFILE */ - "No such device", /* ENODEV */ - "No such file or directory",/* ENOENT */ - "Exec format error", /* ENOEXEC */ - "No locks available", /* ENOLCK */ - "Not enough space", /* ENOMEM */ - "No space left on device", /* ENOSPC */ - "Function not implemented", /* ENOSYS */ - "Not a directory", /* ENOTDIR */ - "Directory not empty", /* ENOTEMPTY */ - "Not supported", /* ENOTSUP */ - "Inappropriate I/O control operation",/* ENOTTY */ - "No such device or address",/* ENXIO */ - "Operation not permitted", /* EPERM */ - "Broken pipe", /* EPIPE */ - "Result too large", /* ERANGE */ - "Read-only file system", /* EROFS */ - "Invalid seek", /* ESPIPE */ - "No such process", /* ESRCH */ - "Operation timed out", /* ETIMEDOUT */ - "Improper link", /* EXDEV */ - "Attempt to load network entity %s", /* XML_IO_NETWORK_ATTEMPT */ - "encoder error", /* XML_IO_ENCODER */ - "flush error", - "write error", - "no input", - "buffer full", - "loading error", - "not a socket", /* ENOTSOCK */ - "already connected", /* EISCONN */ - "connection refused", /* ECONNREFUSED */ - "unreachable network", /* ENETUNREACH */ - "address in use", /* EADDRINUSE */ - "already in use", /* EALREADY */ - "unknown address family", /* EAFNOSUPPORT */ -}; - -#if defined(_WIN32) -/** - * __xmlIOWin32UTF8ToWChar: - * @u8String: uft-8 string - * - * Convert a string from utf-8 to wchar (WINDOWS ONLY!) - */ -static wchar_t * -__xmlIOWin32UTF8ToWChar(const char *u8String) -{ - wchar_t *wString = NULL; - - if (u8String) { - int wLen = - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String, - -1, NULL, 0); - if (wLen) { - wString = xmlMalloc(wLen * sizeof(wchar_t)); - if (wString) { - if (MultiByteToWideChar - (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) { - xmlFree(wString); - wString = NULL; - } - } - } - } - - return wString; -} -#endif - -#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_OUTPUT_ENABLED) /** * xmlIOErrMemory: * @extra: extra information @@ -218,11 +127,10 @@ __xmlIOWin32UTF8ToWChar(const char *u8String) * Handle an out of memory condition */ static void -xmlIOErrMemory(const char *extra) +xmlIOErrMemory(void) { - __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_IO, NULL); } -#endif /** * __xmlIOErr: @@ -232,13 +140,17 @@ xmlIOErrMemory(const char *extra) * * Handle an I/O error */ -void +int __xmlIOErr(int domain, int code, const char *extra) { - unsigned int idx; + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + const char *fmt, *arg1, *arg2; + int res; if (code == 0) { - if (errno == 0) code = 0; + if (errno == 0) code = XML_IO_UNKNOWN; #ifdef EACCES else if (errno == EACCES) code = XML_IO_EACCES; #endif @@ -394,189 +306,49 @@ __xmlIOErr(int domain, int code, const char *extra) #endif else code = XML_IO_UNKNOWN; } - idx = 0; - if (code >= XML_IO_UNKNOWN) idx = code - XML_IO_UNKNOWN; - if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0; - - __xmlSimpleError(domain, code, NULL, IOerr[idx], extra); -} - -/** - * xmlIOErr: - * @code: the error number - * @extra: extra information - * - * Handle an I/O error - */ -static void -xmlIOErr(int code, const char *extra) -{ - __xmlIOErr(XML_FROM_IO, code, extra); -} -/** - * __xmlLoaderErr: - * @ctx: the parser context - * @extra: extra information - * - * Handle a resource access error - */ -void -__xmlLoaderErr(void *ctx, const char *msg, const char *filename) -{ - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - void *data = NULL; - xmlErrorLevel level = XML_ERR_ERROR; - - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if ((ctxt != NULL) && (ctxt->sax != NULL)) { - if (ctxt->validate) { - channel = ctxt->sax->error; - level = XML_ERR_ERROR; - } else { - channel = ctxt->sax->warning; - level = XML_ERR_WARNING; - } - if (ctxt->sax->initialized == XML_SAX2_MAGIC) - schannel = ctxt->sax->serror; - data = ctxt->userData; + if (xmlStructuredError) { + schannel = xmlStructuredError; + data = xmlStructuredErrorContext; + } else { + channel = xmlGenericError; + data = xmlGenericErrorContext; } - __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO, - XML_IO_LOAD_ERROR, level, NULL, 0, - filename, NULL, NULL, 0, 0, - msg, filename); - -} -/************************************************************************ - * * - * Tree memory error handler * - * * - ************************************************************************/ -/** - * xmlNormalizeWindowsPath: - * @path: the input file path - * - * This function is obsolete. Please see xmlURIFromPath in uri.c for - * a better solution. - * - * Returns a canonicalized version of the path - */ -xmlChar * -xmlNormalizeWindowsPath(const xmlChar *path) -{ - return xmlCanonicPath(path); -} - -/** - * xmlCleanupInputCallbacks: - * - * clears the entire input callback table. this includes the - * compiled-in I/O. - */ -void -xmlCleanupInputCallbacks(void) -{ - int i; - - if (!xmlInputCallbackInitialized) - return; - - for (i = xmlInputCallbackNr - 1; i >= 0; i--) { - xmlInputCallbackTable[i].matchcallback = NULL; - xmlInputCallbackTable[i].opencallback = NULL; - xmlInputCallbackTable[i].readcallback = NULL; - xmlInputCallbackTable[i].closecallback = NULL; + if (extra != NULL) { + fmt = "%s: %s"; + } else { + fmt = "%s"; } - xmlInputCallbackNr = 0; - xmlInputCallbackInitialized = 0; -} - -/** - * xmlPopInputCallbacks: - * - * Clear the top input callback from the input stack. this includes the - * compiled-in I/O. - * - * Returns the number of input callback registered or -1 in case of error. - */ -int -xmlPopInputCallbacks(void) -{ - if (!xmlInputCallbackInitialized) - return(-1); - - if (xmlInputCallbackNr <= 0) - return(-1); - - xmlInputCallbackNr--; - xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = NULL; - xmlInputCallbackTable[xmlInputCallbackNr].opencallback = NULL; - xmlInputCallbackTable[xmlInputCallbackNr].readcallback = NULL; - xmlInputCallbackTable[xmlInputCallbackNr].closecallback = NULL; - - return(xmlInputCallbackNr); -} - -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlCleanupOutputCallbacks: - * - * clears the entire output callback table. this includes the - * compiled-in I/O callbacks. - */ -void -xmlCleanupOutputCallbacks(void) -{ - int i; - - if (!xmlOutputCallbackInitialized) - return; + arg1 = xmlErrString(code); + arg2 = extra; - for (i = xmlOutputCallbackNr - 1; i >= 0; i--) { - xmlOutputCallbackTable[i].matchcallback = NULL; - xmlOutputCallbackTable[i].opencallback = NULL; - xmlOutputCallbackTable[i].writecallback = NULL; - xmlOutputCallbackTable[i].closecallback = NULL; + res = __xmlRaiseError(schannel, channel, data, NULL, NULL, + domain, code, XML_ERR_ERROR, NULL, 0, + extra, NULL, NULL, 0, 0, + fmt, arg1, arg2); + if (res < 0) { + xmlIOErrMemory(); + return(XML_ERR_NO_MEMORY); } - xmlOutputCallbackNr = 0; - xmlOutputCallbackInitialized = 0; + return(code); } /** - * xmlPopOutputCallbacks: - * - * Remove the top output callbacks from the output stack. This includes the - * compiled-in I/O. + * xmlIOErr: + * @code: the error number + * @extra: extra information * - * Returns the number of output callback registered or -1 in case of error. + * Handle an I/O error */ -int -xmlPopOutputCallbacks(void) +static int +xmlIOErr(int code, const char *extra) { - if (!xmlOutputCallbackInitialized) - return(-1); - - if (xmlOutputCallbackNr <= 0) - return(-1); - - xmlOutputCallbackNr--; - xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = NULL; - xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = NULL; - xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = NULL; - xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = NULL; - - return(xmlOutputCallbackNr); + return(__xmlIOErr(XML_FROM_IO, code, extra)); } -#endif /* LIBXML_OUTPUT_ENABLED */ - /************************************************************************ * * * Standard I/O for file accesses * @@ -594,100 +366,65 @@ typedef struct stat _stat_t; #if defined(_WIN32) /** - * xmlWrapOpenUtf8: - * @path: the path in utf-8 encoding - * @mode: type of access (0 - read, 1 - write) - * - * function opens the file specified by @path + * __xmlIOWin32UTF8ToWChar: + * @u8String: uft-8 string * + * Convert a string from utf-8 to wchar (WINDOWS ONLY!) */ -static FILE* -xmlWrapOpenUtf8(const char *path,int mode) -{ - FILE *fd = NULL; - wchar_t *wPath; - - wPath = __xmlIOWin32UTF8ToWChar(path); - if(wPath) - { - fd = _wfopen(wPath, mode ? L"wb" : L"rb"); - xmlFree(wPath); - } - /* maybe path in native encoding */ - if(fd == NULL) - fd = fopen(path, mode ? "wb" : "rb"); - - return fd; -} - -#ifdef LIBXML_ZLIB_ENABLED -static gzFile -xmlWrapGzOpenUtf8(const char *path, const char *mode) +static wchar_t * +__xmlIOWin32UTF8ToWChar(const char *u8String) { - gzFile fd; - wchar_t *wPath; + wchar_t *wString = NULL; + int i; - fd = gzopen (path, mode); - if (fd) - return fd; + if (u8String) { + int wLen = + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u8String, + -1, NULL, 0); + if (wLen) { + wString = xmlMalloc(wLen * sizeof(wchar_t)); + if (wString) { + if (MultiByteToWideChar + (CP_UTF8, 0, u8String, -1, wString, wLen) == 0) { + xmlFree(wString); + wString = NULL; + } + } - wPath = __xmlIOWin32UTF8ToWChar(path); - if(wPath) - { - int d, m = (strstr(mode, "r") ? O_RDONLY : O_RDWR); -#ifdef _O_BINARY - m |= (strstr(mode, "b") ? _O_BINARY : 0); -#endif - d = _wopen(wPath, m); - if (d >= 0) - fd = gzdopen(d, mode); - xmlFree(wPath); + /* + * Convert to backward slash + */ + for (i = 0; wString[i] != 0; i++) { + if (wString[i] == '/') + wString[i] = '\\'; + } + } } - return fd; + return wString; } + #endif /** - * xmlWrapStatUtf8: - * @path: the path in utf-8 encoding - * @info: structure that stores results + * xmlNormalizeWindowsPath: + * @path: the input file path * - * function obtains information about the file or directory + * DEPRECATED: This never really worked. * + * Returns a copy of path. */ -static int -xmlWrapStatUtf8(const char *path, _stat_t *info) { - int retval = -1; - wchar_t *wPath; - - wPath = __xmlIOWin32UTF8ToWChar(path); - if (wPath) { -#if defined(_MSC_VER) && _MSC_VER >= 1500 - retval = _wstat64(wPath, info); -#else - retval = _wstat(wPath, info); -#endif - xmlFree(wPath); - } - /* maybe path in native encoding */ - if(retval < 0) -#if defined(_MSC_VER) && _MSC_VER >= 1500 - retval = _stat64(path, info); -#else - retval = _stat(path, info); -#endif - return retval; +xmlChar * +xmlNormalizeWindowsPath(const xmlChar *path) +{ + return xmlStrdup(path); } -#endif - /** * xmlCheckFilename: * @path: the path to check * - * function checks to see if @path is a valid source - * (file, socket...) for XML. + * DEPRECATED: Internal function, don't use. * * if stat is not available on the target machine, * returns 1. if stat fails, returns 0 (if calling @@ -695,40 +432,162 @@ xmlWrapStatUtf8(const char *path, _stat_t *info) { * if stat succeeds and the file is a directory, * returns 2. otherwise returns 1. */ - int -xmlCheckFilename (const char *path) +xmlCheckFilename(const char *path) { #ifdef HAVE_STAT - _stat_t stat_buffer; +#if defined(_MSC_VER) && _MSC_VER >= 1500 + struct _stat64 stat_buffer; +#else + struct stat stat_buffer; #endif + int res; +#endif + if (path == NULL) return(0); #ifdef HAVE_STAT #if defined(_WIN32) - /* - * On Windows stat and wstat do not work with long pathname, - * which start with '\\?\' - */ - if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') && - (path[3] == '\\') ) - return 1; + { + wchar_t *wpath; - if (xmlWrapStatUtf8(path, &stat_buffer) == -1) - return 0; + /* + * On Windows stat and wstat do not work with long pathname, + * which start with '\\?\' + */ + if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') && + (path[3] == '\\') ) + return 1; + + wpath = __xmlIOWin32UTF8ToWChar(path); + if (wpath == NULL) + return(0); +#if defined(_MSC_VER) && _MSC_VER >= 1500 + res = _wstat64(wpath, &stat_buffer); #else - if (stat(path, &stat_buffer) == -1) - return 0; -#endif -#ifdef S_ISDIR - if (S_ISDIR(stat_buffer.st_mode)) - return 2; + res = _wstat(wpath, &stat_buffer); +#endif + xmlFree(wpath); + } +#else + res = stat(path, &stat_buffer); +#endif + + if (res < 0) + return 0; + +#ifdef S_ISDIR + if (S_ISDIR(stat_buffer.st_mode)) + return 2; #endif #endif /* HAVE_STAT */ + return 1; } +static int +xmlConvertUriToPath(const char *uri, char **out) { + const char *escaped; + char *unescaped; + + *out = NULL; + + if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file://localhost/", 17)) { + escaped = &uri[16]; + } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:///", 8)) { + escaped = &uri[7]; + } else if (!xmlStrncasecmp(BAD_CAST uri, BAD_CAST "file:/", 6)) { + /* lots of generators seems to lazy to read RFC 1738 */ + escaped = &uri[5]; + } else { + return(1); + } + +#ifdef _WIN32 + /* Ignore slash like in file:///C:/file.txt */ + escaped += 1; +#endif + + unescaped = xmlURIUnescapeString(escaped, 0, NULL); + if (unescaped == NULL) + return(-1); + + *out = unescaped; + return(0); +} + +/** + * xmlFdOpen: + * @filename: the URI for matching + * @out: pointer to resulting context + * + * Returns an xmlParserErrors code + */ +static int +xmlFdOpen(const char *filename, int write, int *out) { + char *fromUri = NULL; + int flags; + int fd; + int ret; + + *out = -1; + if (filename == NULL) + return(XML_ERR_ARGUMENT); + + if (xmlConvertUriToPath(filename, &fromUri) < 0) + return(XML_ERR_NO_MEMORY); + + if (fromUri != NULL) + filename = fromUri; + +#if defined(_WIN32) + { + wchar_t *wpath; + + wpath = __xmlIOWin32UTF8ToWChar(filename); + if (wpath == NULL) { + xmlFree(fromUri); + return(XML_ERR_NO_MEMORY); + } + if (write) + flags = _O_WRONLY | _O_CREAT | _O_TRUNC; + else + flags = _O_RDONLY; + fd = _wopen(wpath, flags | _O_BINARY, 0777); + xmlFree(wpath); + } +#else + if (write) + flags = O_WRONLY | O_CREAT | O_TRUNC; + else + flags = O_RDONLY; + fd = open(filename, flags, 0777); +#endif /* WIN32 */ + + if (fd < 0) { + /* + * Windows and possibly other platforms return EINVAL + * for invalid filenames. + */ + if ((errno == ENOENT) || (errno == EINVAL)) { + ret = XML_IO_ENOENT; + } else { + /* + * This error won't be forwarded to the parser context + * which will report it a second time. + */ + ret = xmlIOErr(0, filename); + } + } else { + *out = fd; + ret = XML_ERR_OK; + } + + xmlFree(fromUri); + return(ret); +} + /** * xmlFdRead: * @context: the I/O context @@ -737,14 +596,32 @@ xmlCheckFilename (const char *path) * * Read @len bytes to @buffer from the I/O channel. * - * Returns the number of bytes written + * Returns the number of bytes read */ static int -xmlFdRead (void * context, char * buffer, int len) { - int ret; +xmlFdRead(void *context, char *buffer, int len) { + int fd = (int) (ptrdiff_t) context; + int ret = 0; + int bytes; + + while (len > 0) { + bytes = read(fd, buffer, len); + if (bytes < 0) { + /* + * If we already got some bytes, return them without + * raising an error. + */ + if (ret > 0) + break; + return(-xmlIOErr(0, "read()")); + } + if (bytes == 0) + break; + ret += bytes; + buffer += bytes; + len -= bytes; + } - ret = read((int) (ptrdiff_t) context, &buffer[0], len); - if (ret < 0) xmlIOErr(0, "read()"); return(ret); } @@ -760,13 +637,20 @@ xmlFdRead (void * context, char * buffer, int len) { * Returns the number of bytes written */ static int -xmlFdWrite (void * context, const char * buffer, int len) { +xmlFdWrite(void *context, const char *buffer, int len) { + int fd = (int) (ptrdiff_t) context; int ret = 0; + int bytes; - if (len > 0) { - ret = write((int) (ptrdiff_t) context, &buffer[0], len); - if (ret < 0) xmlIOErr(0, "write()"); + while (len > 0) { + bytes = write(fd, buffer, len); + if (bytes < 0) + return(-xmlIOErr(0, "write()")); + ret += bytes; + buffer += bytes; + len -= bytes; } + return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -782,16 +666,19 @@ xmlFdWrite (void * context, const char * buffer, int len) { static int xmlFdClose (void * context) { int ret; + ret = close((int) (ptrdiff_t) context); - if (ret < 0) xmlIOErr(0, "close()"); - return(ret); + if (ret < 0) + return(xmlIOErr(0, "close()")); + + return(XML_ERR_OK); } /** * xmlFileMatch: * @filename: the URI for matching * - * input from FILE * + * DEPRECATED: Internal function, don't use. * * Returns 1 if matches, 0 otherwise */ @@ -801,139 +688,82 @@ xmlFileMatch (const char *filename ATTRIBUTE_UNUSED) { } /** - * xmlFileOpen_real: + * xmlFileOpenSafe: * @filename: the URI for matching + * @out: pointer to resulting context * - * input from FILE *, supports compressed input - * if @filename is " " then the standard input is used + * input from FILE * * * Returns an I/O context or NULL in case of error */ -static void * -xmlFileOpen_real (const char *filename) { - const char *path = filename; +static int +xmlFileOpenSafe(const char *filename, int write, void **out) { + char *fromUri = NULL; FILE *fd; + int ret = XML_ERR_OK; + *out = NULL; if (filename == NULL) - return(NULL); - - if (!strcmp(filename, "-")) { - fd = stdin; - return((void *) fd); - } + return(XML_ERR_ARGUMENT); - if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) { -#if defined (_WIN32) - path = &filename[17]; -#else - path = &filename[16]; -#endif - } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { -#if defined (_WIN32) - path = &filename[8]; -#else - path = &filename[7]; -#endif - } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) { - /* lots of generators seems to lazy to read RFC 1738 */ -#if defined (_WIN32) - path = &filename[6]; -#else - path = &filename[5]; -#endif - } + if (xmlConvertUriToPath(filename, &fromUri) < 0) + return(XML_ERR_NO_MEMORY); - /* Do not check DDNAME on zOS ! */ -#if !defined(__MVS__) - if (!xmlCheckFilename(path)) - return(NULL); -#endif + if (fromUri != NULL) + filename = fromUri; #if defined(_WIN32) - fd = xmlWrapOpenUtf8(path, 0); + { + wchar_t *wpath; + + wpath = __xmlIOWin32UTF8ToWChar(filename); + if (wpath == NULL) { + xmlFree(fromUri); + return(XML_ERR_NO_MEMORY); + } + fd = _wfopen(wpath, write ? L"wb" : L"rb"); + xmlFree(wpath); + } #else - fd = fopen(path, "rb"); + fd = fopen(filename, write ? "wb" : "rb"); #endif /* WIN32 */ - if (fd == NULL) xmlIOErr(0, path); - return((void *) fd); -} -/** - * xmlFileOpen: - * @filename: the URI for matching - * - * Wrapper around xmlFileOpen_real that try it with an unescaped - * version of @filename, if this fails fallback to @filename - * - * Returns a handler or NULL in case or failure - */ -void * -xmlFileOpen (const char *filename) { - char *unescaped; - void *retval; - - retval = xmlFileOpen_real(filename); - if (retval == NULL) { - unescaped = xmlURIUnescapeString(filename, 0, NULL); - if (unescaped != NULL) { - retval = xmlFileOpen_real(unescaped); - xmlFree(unescaped); - } + if (fd == NULL) { + /* + * Windows and possibly other platforms return EINVAL + * for invalid filenames. + */ + if ((errno == ENOENT) || (errno == EINVAL)) { + ret = XML_IO_ENOENT; + } else { + /* + * This error won't be forwarded to the parser context + * which will report it a second time. + */ + ret = xmlIOErr(0, filename); + } } - return retval; + *out = fd; + xmlFree(fromUri); + return(ret); } -#ifdef LIBXML_OUTPUT_ENABLED /** - * xmlFileOpenW: + * xmlFileOpen: * @filename: the URI for matching * - * output to from FILE *, - * if @filename is "-" then the standard output is used + * DEPRECATED: Internal function, don't use. * - * Returns an I/O context or NULL in case of error + * Returns an IO context or NULL in case or failure */ -static void * -xmlFileOpenW (const char *filename) { - const char *path = NULL; - FILE *fd; - - if (!strcmp(filename, "-")) { - fd = stdout; - return((void *) fd); - } - - if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) -#if defined (_WIN32) - path = &filename[17]; -#else - path = &filename[16]; -#endif - else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { -#if defined (_WIN32) - path = &filename[8]; -#else - path = &filename[7]; -#endif - } else - path = filename; - - if (path == NULL) - return(NULL); - -#if defined(_WIN32) - fd = xmlWrapOpenUtf8(path, 1); -#elif(__MVS__) - fd = fopen(path, "w"); -#else - fd = fopen(path, "wb"); -#endif /* WIN32 */ +void * +xmlFileOpen(const char *filename) { + void *context; - if (fd == NULL) xmlIOErr(0, path); - return((void *) fd); + xmlFileOpenSafe(filename, 0, &context); + return(context); } -#endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlFileRead: @@ -941,18 +771,30 @@ xmlFileOpenW (const char *filename) { * @buffer: where to drop data * @len: number of bytes to write * - * Read @len bytes to @buffer from the I/O channel. + * DEPRECATED: Internal function, don't use. * - * Returns the number of bytes written or < 0 in case of failure + * Returns the number of bytes read or < 0 in case of failure */ int -xmlFileRead (void * context, char * buffer, int len) { - int ret; +xmlFileRead(void * context, char * buffer, int len) { + FILE *file = context; + size_t bytes; + if ((context == NULL) || (buffer == NULL)) return(-1); - ret = fread(&buffer[0], 1, len, (FILE *) context); - if (ret < 0) xmlIOErr(0, "fread()"); - return(ret); + + /* + * The C standard doesn't mandate that fread sets errno, only + * POSIX does. The Windows documentation isn't really clear. + * Set errno to zero which will be reported as unknown error + * if fread fails without setting errno. + */ + errno = 0; + bytes = fread(buffer, 1, len, file); + if ((bytes < (size_t) len) && (ferror(file))) + return(-xmlIOErr(0, "fread()")); + + return(len); } #ifdef LIBXML_OUTPUT_ENABLED @@ -967,66 +809,65 @@ xmlFileRead (void * context, char * buffer, int len) { * Returns the number of bytes written */ static int -xmlFileWrite (void * context, const char * buffer, int len) { - int items; +xmlFileWrite(void *context, const char *buffer, int len) { + FILE *file = context; + size_t bytes; if ((context == NULL) || (buffer == NULL)) return(-1); - items = fwrite(&buffer[0], len, 1, (FILE *) context); - if ((items == 0) && (ferror((FILE *) context))) { - xmlIOErr(0, "fwrite()"); - return(-1); - } - return(items * len); + + errno = 0; + bytes = fwrite(buffer, 1, len, file); + if (bytes < (size_t) len) + return(-xmlIOErr(0, "fwrite()")); + + return(len); } #endif /* LIBXML_OUTPUT_ENABLED */ /** - * xmlFileClose: + * xmlFileFlush: * @context: the I/O context * - * Close an I/O channel - * - * Returns 0 or -1 in case of error + * Flush an I/O channel */ -int -xmlFileClose (void * context) { - FILE *fil; - int ret; +static int +xmlFileFlush (void * context) { + FILE *file = context; - if (context == NULL) + if (file == NULL) return(-1); - fil = (FILE *) context; - if ((fil == stdout) || (fil == stderr)) { - ret = fflush(fil); - if (ret < 0) - xmlIOErr(0, "fflush()"); - return(0); - } - if (fil == stdin) - return(0); - ret = ( fclose((FILE *) context) == EOF ) ? -1 : 0; - if (ret < 0) - xmlIOErr(0, "fclose()"); - return(ret); + + if (fflush(file) != 0) + return(xmlIOErr(0, "fflush()")); + + return(XML_ERR_OK); } /** - * xmlFileFlush: + * xmlFileClose: * @context: the I/O context * - * Flush an I/O channel + * DEPRECATED: Internal function, don't use. + * + * Returns 0 or -1 an error code case of error */ -static int -xmlFileFlush (void * context) { - int ret; +int +xmlFileClose (void * context) { + FILE *file = context; if (context == NULL) return(-1); - ret = ( fflush((FILE *) context) == EOF ) ? -1 : 0; - if (ret < 0) - xmlIOErr(0, "fflush()"); - return(ret); + + if (file == stdin) + return(0); + if ((file == stdout) || (file == stderr)) + return(xmlFileFlush(file)); + + if (fclose(file) != 0) + return(xmlIOErr(0, "fclose()")); + + return(0); } #ifdef LIBXML_OUTPUT_ENABLED @@ -1038,7 +879,8 @@ xmlFileFlush (void * context) { * * Write @len bytes from @buffer to the xml buffer * - * Returns the number of bytes written + * Returns the number of bytes written or a negative xmlParserErrors + * value. */ static int xmlBufferWrite (void * context, const char * buffer, int len) { @@ -1046,7 +888,7 @@ xmlBufferWrite (void * context, const char * buffer, int len) { ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len); if (ret != 0) - return(-1); + return(-XML_ERR_NO_MEMORY); return(len); } #endif @@ -1057,148 +899,6 @@ xmlBufferWrite (void * context, const char * buffer, int len) { * I/O for compressed file accesses * * * ************************************************************************/ -/** - * xmlGzfileMatch: - * @filename: the URI for matching - * - * input from compressed file test - * - * Returns 1 if matches, 0 otherwise - */ -static int -xmlGzfileMatch (const char *filename ATTRIBUTE_UNUSED) { - return(1); -} - -/** - * xmlGzfileOpen_real: - * @filename: the URI for matching - * - * input from compressed file open - * if @filename is " " then the standard input is used - * - * Returns an I/O context or NULL in case of error - */ -static void * -xmlGzfileOpen_real (const char *filename) { - const char *path = NULL; - gzFile fd; - - if (!strcmp(filename, "-")) { - int duped_fd = dup(fileno(stdin)); - fd = gzdopen(duped_fd, "rb"); - if (fd == Z_NULL && duped_fd >= 0) { - close(duped_fd); /* gzdOpen() does not close on failure */ - } - - return((void *) fd); - } - - if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) -#if defined (_WIN32) - path = &filename[17]; -#else - path = &filename[16]; -#endif - else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { -#if defined (_WIN32) - path = &filename[8]; -#else - path = &filename[7]; -#endif - } else - path = filename; - - if (path == NULL) - return(NULL); - if (!xmlCheckFilename(path)) - return(NULL); - -#if defined(_WIN32) - fd = xmlWrapGzOpenUtf8(path, "rb"); -#else - fd = gzopen(path, "rb"); -#endif - return((void *) fd); -} - -/** - * xmlGzfileOpen: - * @filename: the URI for matching - * - * Wrapper around xmlGzfileOpen_real if the open fails, it will - * try to unescape @filename - */ -static void * -xmlGzfileOpen (const char *filename) { - char *unescaped; - void *retval; - - retval = xmlGzfileOpen_real(filename); - if (retval == NULL) { - unescaped = xmlURIUnescapeString(filename, 0, NULL); - if (unescaped != NULL) { - retval = xmlGzfileOpen_real(unescaped); - } - xmlFree(unescaped); - } - return retval; -} - -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlGzfileOpenW: - * @filename: the URI for matching - * @compression: the compression factor (0 - 9 included) - * - * input from compressed file open - * if @filename is " " then the standard input is used - * - * Returns an I/O context or NULL in case of error - */ -static void * -xmlGzfileOpenW (const char *filename, int compression) { - const char *path = NULL; - char mode[15]; - gzFile fd; - - snprintf(mode, sizeof(mode), "wb%d", compression); - if (!strcmp(filename, "-")) { - int duped_fd = dup(fileno(stdout)); - fd = gzdopen(duped_fd, "rb"); - if (fd == Z_NULL && duped_fd >= 0) { - close(duped_fd); /* gzdOpen() does not close on failure */ - } - - return((void *) fd); - } - - if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) -#if defined (_WIN32) - path = &filename[17]; -#else - path = &filename[16]; -#endif - else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { -#if defined (_WIN32) - path = &filename[8]; -#else - path = &filename[7]; -#endif - } else - path = filename; - - if (path == NULL) - return(NULL); - -#if defined(_WIN32) - fd = xmlWrapGzOpenUtf8(path, mode); -#else - fd = gzopen(path, mode); -#endif - return((void *) fd); -} -#endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlGzfileRead: @@ -1256,95 +956,21 @@ xmlGzfileClose (void * context) { } #endif /* LIBXML_ZLIB_ENABLED */ -#ifdef LIBXML_LZMA_ENABLED /************************************************************************ * * * I/O for compressed file accesses * * * ************************************************************************/ + +#ifdef LIBXML_LZMA_ENABLED + #include "private/xzlib.h" + /** - * xmlXzfileMatch: - * @filename: the URI for matching - * - * input from compressed file test - * - * Returns 1 if matches, 0 otherwise - */ -static int -xmlXzfileMatch (const char *filename ATTRIBUTE_UNUSED) { - return(1); -} - -/** - * xmlXzFileOpen_real: - * @filename: the URI for matching - * - * input from compressed file open - * if @filename is " " then the standard input is used - * - * Returns an I/O context or NULL in case of error - */ -static void * -xmlXzfileOpen_real (const char *filename) { - const char *path = NULL; - xzFile fd; - - if (!strcmp(filename, "-")) { - fd = __libxml2_xzdopen(dup(fileno(stdin)), "rb"); - return((void *) fd); - } - - if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file://localhost/", 17)) { - path = &filename[16]; - } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:///", 8)) { - path = &filename[7]; - } else if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "file:/", 6)) { - /* lots of generators seems to lazy to read RFC 1738 */ - path = &filename[5]; - } else - path = filename; - - if (path == NULL) - return(NULL); - if (!xmlCheckFilename(path)) - return(NULL); - - fd = __libxml2_xzopen(path, "rb"); - return((void *) fd); -} - -/** - * xmlXzfileOpen: - * @filename: the URI for matching - * - * Wrapper around xmlXzfileOpen_real that try it with an unescaped - * version of @filename, if this fails fallback to @filename - * - * Returns a handler or NULL in case or failure - */ -static void * -xmlXzfileOpen (const char *filename) { - char *unescaped; - void *retval; - - retval = xmlXzfileOpen_real(filename); - if (retval == NULL) { - unescaped = xmlURIUnescapeString(filename, 0, NULL); - if (unescaped != NULL) { - retval = xmlXzfileOpen_real(unescaped); - } - xmlFree(unescaped); - } - - return retval; -} - -/** - * xmlXzfileRead: - * @context: the I/O context - * @buffer: where to drop data - * @len: number of bytes to write + * xmlXzfileRead: + * @context: the I/O context + * @buffer: where to drop data + * @len: number of bytes to write * * Read @len bytes to @buffer from the compressed I/O channel. * @@ -1375,371 +1001,19 @@ xmlXzfileClose (void * context) { } #endif /* LIBXML_LZMA_ENABLED */ -#ifdef LIBXML_HTTP_ENABLED /************************************************************************ * * * I/O for HTTP file accesses * * * ************************************************************************/ -#ifdef LIBXML_OUTPUT_ENABLED -typedef struct xmlIOHTTPWriteCtxt_ -{ - int compression; - - char * uri; - - void * doc_buff; - -} xmlIOHTTPWriteCtxt, *xmlIOHTTPWriteCtxtPtr; - -#ifdef LIBXML_ZLIB_ENABLED - -#define DFLT_WBITS ( -15 ) -#define DFLT_MEM_LVL ( 8 ) -#define GZ_MAGIC1 ( 0x1f ) -#define GZ_MAGIC2 ( 0x8b ) -#define LXML_ZLIB_OS_CODE ( 0x03 ) -#define INIT_HTTP_BUFF_SIZE ( 32768 ) -#define DFLT_ZLIB_RATIO ( 5 ) - -/* -** Data structure and functions to work with sending compressed data -** via HTTP. -*/ - -typedef struct xmlZMemBuff_ -{ - unsigned long size; - unsigned long crc; - - unsigned char * zbuff; - z_stream zctrl; - -} xmlZMemBuff, *xmlZMemBuffPtr; - -/** - * append_reverse_ulong - * @buff: Compressed memory buffer - * @data: Unsigned long to append - * - * Append a unsigned long in reverse byte order to the end of the - * memory buffer. - */ -static void -append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) { - - int idx; - - if ( buff == NULL ) - return; - - /* - ** This is plagiarized from putLong in gzio.c (zlib source) where - ** the number "4" is hardcoded. If zlib is ever patched to - ** support 64 bit file sizes, this code would need to be patched - ** as well. - */ - - for ( idx = 0; idx < 4; idx++ ) { - *buff->zctrl.next_out = ( data & 0xff ); - data >>= 8; - buff->zctrl.next_out++; - } - - return; -} - -/** - * - * xmlFreeZMemBuff - * @buff: The memory buffer context to clear - * - * Release all the resources associated with the compressed memory buffer. - */ -static void -xmlFreeZMemBuff( xmlZMemBuffPtr buff ) { - - if ( buff == NULL ) - return; - - xmlFree( buff->zbuff ); - deflateEnd( &buff->zctrl ); - - xmlFree( buff ); - return; -} - -/** - * xmlCreateZMemBuff - *@compression: Compression value to use - * - * Create a memory buffer to hold the compressed XML document. The - * compressed document in memory will end up being identical to what - * would be created if gzopen/gzwrite/gzclose were being used to - * write the document to disk. The code for the header/trailer data to - * the compression is plagiarized from the zlib source files. - */ -static void * -xmlCreateZMemBuff( int compression ) { - - int z_err; - int hdr_lgth; - xmlZMemBuffPtr buff = NULL; - - if ( ( compression < 1 ) || ( compression > 9 ) ) - return ( NULL ); - - /* Create the control and data areas */ - - buff = xmlMalloc( sizeof( xmlZMemBuff ) ); - if ( buff == NULL ) { - xmlIOErrMemory("creating buffer context"); - return ( NULL ); - } - - (void)memset( buff, 0, sizeof( xmlZMemBuff ) ); - buff->size = INIT_HTTP_BUFF_SIZE; - buff->zbuff = xmlMalloc( buff->size ); - if ( buff->zbuff == NULL ) { - xmlFreeZMemBuff( buff ); - xmlIOErrMemory("creating buffer"); - return ( NULL ); - } - - z_err = deflateInit2( &buff->zctrl, compression, Z_DEFLATED, - DFLT_WBITS, DFLT_MEM_LVL, Z_DEFAULT_STRATEGY ); - if ( z_err != Z_OK ) { - xmlChar msg[500]; - xmlFreeZMemBuff( buff ); - buff = NULL; - xmlStrPrintf(msg, 500, - "xmlCreateZMemBuff: %s %d\n", - "Error initializing compression context. ZLIB error:", - z_err ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - return ( NULL ); - } - - /* Set the header data. The CRC will be needed for the trailer */ - buff->crc = crc32( 0L, NULL, 0 ); - hdr_lgth = snprintf( (char *)buff->zbuff, buff->size, - "%c%c%c%c%c%c%c%c%c%c", - GZ_MAGIC1, GZ_MAGIC2, Z_DEFLATED, - 0, 0, 0, 0, 0, 0, LXML_ZLIB_OS_CODE ); - buff->zctrl.next_out = buff->zbuff + hdr_lgth; - buff->zctrl.avail_out = buff->size - hdr_lgth; - - return ( buff ); -} - -/** - * xmlZMemBuffExtend - * @buff: Buffer used to compress and consolidate data. - * @ext_amt: Number of bytes to extend the buffer. - * - * Extend the internal buffer used to store the compressed data by the - * specified amount. - * - * Returns 0 on success or -1 on failure to extend the buffer. On failure - * the original buffer still exists at the original size. - */ -static int -xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) { - - int rc = -1; - size_t new_size; - size_t cur_used; - - unsigned char * tmp_ptr = NULL; - - if ( buff == NULL ) - return ( -1 ); - - else if ( ext_amt == 0 ) - return ( 0 ); - - cur_used = buff->zctrl.next_out - buff->zbuff; - new_size = buff->size + ext_amt; - - tmp_ptr = xmlRealloc( buff->zbuff, new_size ); - if ( tmp_ptr != NULL ) { - rc = 0; - buff->size = new_size; - buff->zbuff = tmp_ptr; - buff->zctrl.next_out = tmp_ptr + cur_used; - buff->zctrl.avail_out = new_size - cur_used; - } - else { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlZMemBuffExtend: %s %lu bytes.\n", - "Allocation failure extending output buffer to", - (unsigned long) new_size ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - } - - return ( rc ); -} - -/** - * xmlZMemBuffAppend - * @buff: Buffer used to compress and consolidate data - * @src: Uncompressed source content to append to buffer - * @len: Length of source data to append to buffer - * - * Compress and append data to the internal buffer. The data buffer - * will be expanded if needed to store the additional data. - * - * Returns the number of bytes appended to the buffer or -1 on error. - */ -static int -xmlZMemBuffAppend( xmlZMemBuffPtr buff, const char * src, int len ) { - - int z_err; - size_t min_accept; - - if ( ( buff == NULL ) || ( src == NULL ) ) - return ( -1 ); - - buff->zctrl.avail_in = len; - buff->zctrl.next_in = (unsigned char *)src; - while ( buff->zctrl.avail_in > 0 ) { - /* - ** Extend the buffer prior to deflate call if a reasonable amount - ** of output buffer space is not available. - */ - min_accept = buff->zctrl.avail_in / DFLT_ZLIB_RATIO; - if ( buff->zctrl.avail_out <= min_accept ) { - if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) - return ( -1 ); - } - - z_err = deflate( &buff->zctrl, Z_NO_FLUSH ); - if ( z_err != Z_OK ) { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlZMemBuffAppend: %s %d %s - %d", - "Compression error while appending", - len, "bytes to buffer. ZLIB error", z_err ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - return ( -1 ); - } - } - - buff->crc = crc32( buff->crc, (unsigned char *)src, len ); - - return ( len ); -} - -/** - * xmlZMemBuffGetContent - * @buff: Compressed memory content buffer - * @data_ref: Pointer reference to point to compressed content - * - * Flushes the compression buffers, appends gzip file trailers and - * returns the compressed content and length of the compressed data. - * NOTE: The gzip trailer code here is plagiarized from zlib source. - * - * Returns the length of the compressed data or -1 on error. - */ -static int -xmlZMemBuffGetContent( xmlZMemBuffPtr buff, char ** data_ref ) { - - int zlgth = -1; - int z_err; - - if ( ( buff == NULL ) || ( data_ref == NULL ) ) - return ( -1 ); - - /* Need to loop until compression output buffers are flushed */ - - do - { - z_err = deflate( &buff->zctrl, Z_FINISH ); - if ( z_err == Z_OK ) { - /* In this case Z_OK means more buffer space needed */ - - if ( xmlZMemBuffExtend( buff, buff->size ) == -1 ) - return ( -1 ); - } - } - while ( z_err == Z_OK ); - - /* If the compression state is not Z_STREAM_END, some error occurred */ - - if ( z_err == Z_STREAM_END ) { - - /* Need to append the gzip data trailer */ - - if ( buff->zctrl.avail_out < ( 2 * sizeof( unsigned long ) ) ) { - if ( xmlZMemBuffExtend(buff, (2 * sizeof(unsigned long))) == -1 ) - return ( -1 ); - } - - /* - ** For whatever reason, the CRC and length data are pushed out - ** in reverse byte order. So a memcpy can't be used here. - */ - - append_reverse_ulong( buff, buff->crc ); - append_reverse_ulong( buff, buff->zctrl.total_in ); - - zlgth = buff->zctrl.next_out - buff->zbuff; - *data_ref = (char *)buff->zbuff; - } - - else { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlZMemBuffGetContent: %s - %d\n", - "Error flushing zlib buffers. Error code", z_err ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - } - - return ( zlgth ); -} -#endif /* LIBXML_OUTPUT_ENABLED */ -#endif /* LIBXML_ZLIB_ENABLED */ - -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlFreeHTTPWriteCtxt - * @ctxt: Context to cleanup - * - * Free allocated memory and reclaim system resources. - * - * No return value. - */ -static void -xmlFreeHTTPWriteCtxt( xmlIOHTTPWriteCtxtPtr ctxt ) -{ - if ( ctxt->uri != NULL ) - xmlFree( ctxt->uri ); - - if ( ctxt->doc_buff != NULL ) { - -#ifdef LIBXML_ZLIB_ENABLED - if ( ctxt->compression > 0 ) { - xmlFreeZMemBuff( ctxt->doc_buff ); - } - else -#endif - { - xmlOutputBufferClose( ctxt->doc_buff ); - } - } - - xmlFree( ctxt ); - return; -} -#endif /* LIBXML_OUTPUT_ENABLED */ - - +#ifdef LIBXML_HTTP_ENABLED /** * xmlIOHTTPMatch: * @filename: the URI for matching * + * DEPRECATED: Internal function, don't use. + * * check if the URI matches an HTTP one * * Returns 1 if matches, 0 otherwise @@ -1755,6 +1029,8 @@ xmlIOHTTPMatch (const char *filename) { * xmlIOHTTPOpen: * @filename: the URI for matching * + * DEPRECATED: Internal function, don't use. + * * open an HTTP I/O channel * * Returns an I/O context or NULL in case of error @@ -1770,78 +1046,15 @@ xmlIOHTTPOpen (const char *filename) { * @post_uri: The destination URI for the document * @compression: The compression desired for the document. * - * Open a temporary buffer to collect the document for a subsequent HTTP POST - * request. Non-static as is called from the output buffer creation routine. + * DEPRECATED: Support for HTTP POST has been removed. * - * Returns an I/O context or NULL in case of error. + * Returns NULL. */ - void * -xmlIOHTTPOpenW(const char *post_uri, int compression ATTRIBUTE_UNUSED) +xmlIOHTTPOpenW(const char *post_uri ATTRIBUTE_UNUSED, + int compression ATTRIBUTE_UNUSED) { - - xmlIOHTTPWriteCtxtPtr ctxt = NULL; - - if (post_uri == NULL) - return (NULL); - - ctxt = xmlMalloc(sizeof(xmlIOHTTPWriteCtxt)); - if (ctxt == NULL) { - xmlIOErrMemory("creating HTTP output context"); - return (NULL); - } - - (void) memset(ctxt, 0, sizeof(xmlIOHTTPWriteCtxt)); - - ctxt->uri = (char *) xmlStrdup((const xmlChar *)post_uri); - if (ctxt->uri == NULL) { - xmlIOErrMemory("copying URI"); - xmlFreeHTTPWriteCtxt(ctxt); - return (NULL); - } - - /* - * ** Since the document length is required for an HTTP post, - * ** need to put the document into a buffer. A memory buffer - * ** is being used to avoid pushing the data to disk and back. - */ - -#ifdef LIBXML_ZLIB_ENABLED - if ((compression > 0) && (compression <= 9)) { - - ctxt->compression = compression; - ctxt->doc_buff = xmlCreateZMemBuff(compression); - } else -#endif - { - /* Any character conversions should have been done before this */ - - ctxt->doc_buff = xmlAllocOutputBufferInternal(NULL); - } - - if (ctxt->doc_buff == NULL) { - xmlFreeHTTPWriteCtxt(ctxt); - ctxt = NULL; - } - - return (ctxt); -} -#endif /* LIBXML_OUTPUT_ENABLED */ - -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlIOHTTPDfltOpenW - * @post_uri: The destination URI for this document. - * - * Calls xmlIOHTTPOpenW with no compression to set up for a subsequent - * HTTP post command. This function should generally not be used as - * the open callback is short circuited in xmlOutputBufferCreateFile. - * - * Returns a pointer to the new IO context. - */ -static void * -xmlIOHTTPDfltOpenW( const char * post_uri ) { - return ( xmlIOHTTPOpenW( post_uri, 0 ) ); + return(NULL); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -1851,6 +1064,8 @@ xmlIOHTTPDfltOpenW( const char * post_uri ) { * @buffer: where to drop data * @len: number of bytes to write * + * DEPRECATED: Internal function, don't use. + * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written @@ -1861,59 +1076,12 @@ xmlIOHTTPRead(void * context, char * buffer, int len) { return(xmlNanoHTTPRead(context, &buffer[0], len)); } -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlIOHTTPWrite - * @context: previously opened writing context - * @buffer: data to output to temporary buffer - * @len: bytes to output - * - * Collect data from memory buffer into a temporary file for later - * processing. - * - * Returns number of bytes written. - */ - -static int -xmlIOHTTPWrite( void * context, const char * buffer, int len ) { - - xmlIOHTTPWriteCtxtPtr ctxt = context; - - if ( ( ctxt == NULL ) || ( ctxt->doc_buff == NULL ) || ( buffer == NULL ) ) - return ( -1 ); - - if ( len > 0 ) { - - /* Use gzwrite or fwrite as previously setup in the open call */ - -#ifdef LIBXML_ZLIB_ENABLED - if ( ctxt->compression > 0 ) - len = xmlZMemBuffAppend( ctxt->doc_buff, buffer, len ); - - else -#endif - len = xmlOutputBufferWrite( ctxt->doc_buff, len, buffer ); - - if ( len < 0 ) { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlIOHTTPWrite: %s\n%s '%s'.\n", - "Error appending to internal buffer.", - "Error sending document to URI", - ctxt->uri ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - } - } - - return ( len ); -} -#endif /* LIBXML_OUTPUT_ENABLED */ - - /** * xmlIOHTTPClose: * @context: the I/O context * + * DEPRECATED: Internal function, don't use. + * * Close an HTTP I/O channel * * Returns 0 @@ -1923,119 +1091,6 @@ xmlIOHTTPClose (void * context) { xmlNanoHTTPClose(context); return 0; } - -#ifdef LIBXML_OUTPUT_ENABLED -/** - * xmlIOHTTCloseWrite - * @context: The I/O context - * @http_mthd: The HTTP method to be used when sending the data - * - * Close the transmit HTTP I/O channel and actually send the data. - */ -static int -xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) { - - int close_rc = -1; - int http_rtn = 0; - int content_lgth = 0; - xmlIOHTTPWriteCtxtPtr ctxt = context; - - char * http_content = NULL; - char * content_encoding = NULL; - char * content_type = (char *) "text/xml"; - void * http_ctxt = NULL; - - if ( ( ctxt == NULL ) || ( http_mthd == NULL ) ) - return ( -1 ); - - /* Retrieve the content from the appropriate buffer */ - -#ifdef LIBXML_ZLIB_ENABLED - - if ( ctxt->compression > 0 ) { - content_lgth = xmlZMemBuffGetContent( ctxt->doc_buff, &http_content ); - content_encoding = (char *) "Content-Encoding: gzip"; - } - else -#endif - { - /* Pull the data out of the memory output buffer */ - - xmlOutputBufferPtr dctxt = ctxt->doc_buff; - http_content = (char *) xmlBufContent(dctxt->buffer); - content_lgth = xmlBufUse(dctxt->buffer); - } - - if ( http_content == NULL ) { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlIOHTTPCloseWrite: %s '%s' %s '%s'.\n", - "Error retrieving content.\nUnable to", - http_mthd, "data to URI", ctxt->uri ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - } - - else { - - http_ctxt = xmlNanoHTTPMethod( ctxt->uri, http_mthd, http_content, - &content_type, content_encoding, - content_lgth ); - - if ( http_ctxt != NULL ) { - - http_rtn = xmlNanoHTTPReturnCode( http_ctxt ); - if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) ) - close_rc = 0; - else { - xmlChar msg[500]; - xmlStrPrintf(msg, 500, - "xmlIOHTTPCloseWrite: HTTP '%s' of %d %s\n'%s' %s %d\n", - http_mthd, content_lgth, - "bytes to URI", ctxt->uri, - "failed. HTTP return code:", http_rtn ); - xmlIOErr(XML_IO_WRITE, (const char *) msg); - } - - xmlNanoHTTPClose( http_ctxt ); - xmlFree( content_type ); - } - } - - /* Final cleanups */ - - xmlFreeHTTPWriteCtxt( ctxt ); - - return ( close_rc ); -} - -/** - * xmlIOHTTPClosePut - * - * @context: The I/O context - * - * Close the transmit HTTP I/O channel and actually send data using a PUT - * HTTP method. - */ -static int -xmlIOHTTPClosePut( void * ctxt ) { - return ( xmlIOHTTPCloseWrite( ctxt, "PUT" ) ); -} - - -/** - * xmlIOHTTPClosePost - * - * @context: The I/O context - * - * Close the transmit HTTP I/O channel and actually send data using a POST - * HTTP method. - */ -static int -xmlIOHTTPClosePost( void * ctxt ) { - return ( xmlIOHTTPCloseWrite( ctxt, "POST" ) ); -} -#endif /* LIBXML_OUTPUT_ENABLED */ - #endif /* LIBXML_HTTP_ENABLED */ #ifdef LIBXML_FTP_ENABLED @@ -2048,6 +1103,8 @@ xmlIOHTTPClosePost( void * ctxt ) { * xmlIOFTPMatch: * @filename: the URI for matching * + * DEPRECATED: Internal function, don't use. + * * check if the URI matches an FTP one * * Returns 1 if matches, 0 otherwise @@ -2063,6 +1120,8 @@ xmlIOFTPMatch (const char *filename) { * xmlIOFTPOpen: * @filename: the URI for matching * + * DEPRECATED: Internal function, don't use. + * * open an FTP I/O channel * * Returns an I/O context or NULL in case of error @@ -2078,6 +1137,8 @@ xmlIOFTPOpen (const char *filename) { * @buffer: where to drop data * @len: number of bytes to write * + * DEPRECATED: Internal function, don't use. + * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes written @@ -2092,6 +1153,8 @@ xmlIOFTPRead(void * context, char * buffer, int len) { * xmlIOFTPClose: * @context: the I/O context * + * DEPRECATED: Internal function, don't use. + * * Close an FTP I/O channel * * Returns 0 @@ -2102,161 +1165,192 @@ xmlIOFTPClose (void * context) { } #endif /* LIBXML_FTP_ENABLED */ +/************************************************************************ + * * + * Input/output buffers * + * * + ************************************************************************/ -/** - * xmlRegisterInputCallbacks: - * @matchFunc: the xmlInputMatchCallback - * @openFunc: the xmlInputOpenCallback - * @readFunc: the xmlInputReadCallback - * @closeFunc: the xmlInputCloseCallback - * - * Register a new set of I/O callback for handling parser input. - * - * Returns the registered handler number or -1 in case of error - */ -int -xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc, - xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, - xmlInputCloseCallback closeFunc) { - if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) { - return(-1); - } - xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc; - xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc; - xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc; - xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc; - xmlInputCallbackInitialized = 1; - return(xmlInputCallbackNr++); +static int +xmlIODefaultMatch(const char *filename ATTRIBUTE_UNUSED) { + return(1); } -#ifdef LIBXML_OUTPUT_ENABLED /** - * xmlRegisterOutputCallbacks: - * @matchFunc: the xmlOutputMatchCallback - * @openFunc: the xmlOutputOpenCallback - * @writeFunc: the xmlOutputWriteCallback - * @closeFunc: the xmlOutputCloseCallback + * xmlInputDefaultOpen: + * @buf: input buffer to be filled + * @filename: filename or URI * - * Register a new set of I/O callback for handling output. - * - * Returns the registered handler number or -1 in case of error + * Returns an xmlParserErrors code. */ -int -xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc, - xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc, - xmlOutputCloseCallback closeFunc) { - if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) { - return(-1); +static int +xmlInputDefaultOpen(xmlParserInputBufferPtr buf, const char *filename) { + int ret; + int fd; + +#ifdef LIBXML_FTP_ENABLED + if (xmlIOFTPMatch(filename)) { + buf->context = xmlIOFTPOpen(filename); + + if (buf->context != NULL) { + buf->readcallback = xmlIOFTPRead; + buf->closecallback = xmlIOFTPClose; + return(XML_ERR_OK); + } } - xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc; - xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc; - xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc; - xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc; - xmlOutputCallbackInitialized = 1; - return(xmlOutputCallbackNr++); -} -#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* LIBXML_FTP_ENABLED */ -/** - * xmlRegisterDefaultInputCallbacks: - * - * Registers the default compiled-in I/O handlers. - */ -void -xmlRegisterDefaultInputCallbacks(void) { - if (xmlInputCallbackInitialized) - return; +#ifdef LIBXML_HTTP_ENABLED + if (xmlIOHTTPMatch(filename)) { + buf->context = xmlIOHTTPOpen(filename); + + if (buf->context != NULL) { + buf->readcallback = xmlIOHTTPRead; + buf->closecallback = xmlIOHTTPClose; + return(XML_ERR_OK); + } + } +#endif /* LIBXML_HTTP_ENABLED */ + + if (!xmlFileMatch(filename)) + return(XML_IO_ENOENT); - xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen, - xmlFileRead, xmlFileClose); -#ifdef LIBXML_ZLIB_ENABLED - xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen, - xmlGzfileRead, xmlGzfileClose); -#endif /* LIBXML_ZLIB_ENABLED */ #ifdef LIBXML_LZMA_ENABLED - xmlRegisterInputCallbacks(xmlXzfileMatch, xmlXzfileOpen, - xmlXzfileRead, xmlXzfileClose); + { + xzFile xzStream; + + ret = xmlFdOpen(filename, 0, &fd); + if (ret != XML_ERR_OK) + return(ret); + + xzStream = __libxml2_xzdopen(filename, fd, "rb"); + + if (xzStream == NULL) { + close(fd); + } else { + if (__libxml2_xzcompressed(xzStream) > 0) { + buf->context = xzStream; + buf->readcallback = xmlXzfileRead; + buf->closecallback = xmlXzfileClose; + buf->compressed = 1; + + return(XML_ERR_OK); + } + + xmlXzfileClose(xzStream); + } + } #endif /* LIBXML_LZMA_ENABLED */ -#ifdef LIBXML_HTTP_ENABLED - xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen, - xmlIOHTTPRead, xmlIOHTTPClose); -#endif /* LIBXML_HTTP_ENABLED */ +#ifdef LIBXML_ZLIB_ENABLED + { + gzFile gzStream; -#ifdef LIBXML_FTP_ENABLED - xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, - xmlIOFTPRead, xmlIOFTPClose); -#endif /* LIBXML_FTP_ENABLED */ - xmlInputCallbackInitialized = 1; + ret = xmlFdOpen(filename, 0, &fd); + if (ret != XML_ERR_OK) + return(ret); + + gzStream = gzdopen(fd, "rb"); + + if (gzStream == NULL) { + close(fd); + } else { + char buff4[4]; + + if ((gzread(gzStream, buff4, 4) > 0) && + (gzdirect(gzStream) == 0)) { + gzrewind(gzStream); + + buf->context = gzStream; + buf->readcallback = xmlGzfileRead; + buf->closecallback = xmlGzfileClose; + buf->compressed = 1; + + return(XML_ERR_OK); + } + + xmlGzfileClose(gzStream); + } + } +#endif /* LIBXML_ZLIB_ENABLED */ + + ret = xmlFdOpen(filename, 0, &fd); + if (ret != XML_ERR_OK) + return(ret); + + buf->context = (void *) (ptrdiff_t) fd; + buf->readcallback = xmlFdRead; + buf->closecallback = xmlFdClose; + return(XML_ERR_OK); } #ifdef LIBXML_OUTPUT_ENABLED /** - * xmlRegisterDefaultOutputCallbacks: + * xmlOutputDefaultOpen: + * @buf: input buffer to be filled + * @filename: filename or URI + * @compression: compression level or 0 + * @is_file_uri: whether filename is a file URI * - * Registers the default compiled-in I/O handlers. + * Returns an xmlParserErrors code. */ -void -xmlRegisterDefaultOutputCallbacks (void) { - if (xmlOutputCallbackInitialized) - return; +static int +xmlOutputDefaultOpen(xmlOutputBufferPtr buf, const char *filename, + int compression) { + int fd; - xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW, - xmlFileWrite, xmlFileClose); + (void) compression; -#ifdef LIBXML_HTTP_ENABLED - xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, - xmlIOHTTPWrite, xmlIOHTTPClosePut); -#endif + if (!strcmp(filename, "-")) { + fd = dup(STDOUT_FILENO); + + if (fd < 0) + return(xmlIOErr(0, "dup()")); + } else { + int ret; -/********************************* - No way a-priori to distinguish between gzipped files from - uncompressed ones except opening if existing then closing - and saving with same compression ratio ... a pain. + ret = xmlFdOpen(filename, /* write */ 1, &fd); + if (ret != XML_ERR_OK) + return(ret); + } #ifdef LIBXML_ZLIB_ENABLED - xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen, - xmlGzfileWrite, xmlGzfileClose); -#endif + if ((compression > 0) && (compression <= 9)) { + gzFile gzStream; + char mode[15]; - Nor FTP PUT .... -#ifdef LIBXML_FTP_ENABLED - xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen, - xmlIOFTPWrite, xmlIOFTPClose); -#endif - **********************************/ - xmlOutputCallbackInitialized = 1; -} + snprintf(mode, sizeof(mode), "wb%d", compression); + gzStream = gzdopen(fd, mode); -#ifdef LIBXML_HTTP_ENABLED -/** - * xmlRegisterHTTPPostCallbacks: - * - * By default, libxml submits HTTP output requests using the "PUT" method. - * Calling this method changes the HTTP output method to use the "POST" - * method instead. - * - */ -void -xmlRegisterHTTPPostCallbacks( void ) { + if (gzStream == NULL) { + close(fd); + return(xmlIOErr(XML_IO_UNKNOWN, "gzdopen()")); + } - /* Register defaults if not done previously */ + buf->context = gzStream; + buf->writecallback = xmlGzfileWrite; + buf->closecallback = xmlGzfileClose; - if ( xmlOutputCallbackInitialized == 0 ) - xmlRegisterDefaultOutputCallbacks( ); + return(XML_ERR_OK); + } +#endif /* LIBXML_ZLIB_ENABLED */ - xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPDfltOpenW, - xmlIOHTTPWrite, xmlIOHTTPClosePost); - return; + buf->context = (void *) (ptrdiff_t) fd; + buf->writecallback = xmlFdWrite; + buf->closecallback = xmlFdClose; + return(XML_ERR_OK); } #endif -#endif /* LIBXML_OUTPUT_ENABLED */ /** * xmlAllocParserInputBuffer: - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) + * + * Create a buffered parser input for progressive parsing. * - * Create a buffered parser input for progressive parsing + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. * * Returns the new parser input or NULL */ @@ -2275,7 +1369,13 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) { return(NULL); } xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT); - ret->encoder = xmlGetCharEncodingHandler(enc); + if (enc != XML_CHAR_ENCODING_NONE) { + if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != 0) { + /* We can't handle errors properly here. */ + xmlFreeParserInputBuffer(ret); + return(NULL); + } + } if (ret->encoder != NULL) ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize); else @@ -2312,7 +1412,7 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) { xmlFree(ret); return(NULL); } - xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT); + xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO); ret->encoder = encoder; if (encoder != NULL) { @@ -2427,22 +1527,36 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) { * flushes and close the output I/O channel * and free up all the associated resources * - * Returns the number of byte written or -1 in case of error. + * Returns the number of byte written or a negative xmlParserErrors + * code in case of error. */ int xmlOutputBufferClose(xmlOutputBufferPtr out) { - int written; - int err_rc = 0; + int ret; if (out == NULL) return (-1); + if (out->writecallback != NULL) xmlOutputBufferFlush(out); + if (out->closecallback != NULL) { - err_rc = out->closecallback(out->context); + int code = out->closecallback(out->context); + + if ((code != XML_ERR_OK) && (out->error == XML_ERR_OK)) { + if (code < 0) + out->error = XML_IO_UNKNOWN; + else + out->error = code; + } } - written = out->written; + + if (out->error != XML_ERR_OK) + ret = -out->error; + else + ret = out->written; + if (out->conv) { xmlBufFree(out->conv); out->conv = NULL; @@ -2455,81 +1569,77 @@ xmlOutputBufferClose(xmlOutputBufferPtr out) out->buffer = NULL; } - if (out->error) - err_rc = -1; xmlFree(out); - return ((err_rc == 0) ? written : err_rc); + + return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ -xmlParserInputBufferPtr -__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { - xmlParserInputBufferPtr ret; - int i = 0; - void *context = NULL; +/** + * xmlParserInputBufferCreateFilenameInt: + * @URI: the filename or URI + * @enc: encoding enum (deprecated) + * @out: pointer to resulting input buffer + * + * Returns an xmlParserErrors code. + */ +static int +xmlParserInputBufferCreateFilenameInt(const char *URI, xmlCharEncoding enc, + xmlParserInputBufferPtr *out) { + xmlParserInputBufferPtr buf; + int ret; + int i; - if (xmlInputCallbackInitialized == 0) - xmlRegisterDefaultInputCallbacks(); + *out = NULL; + if (URI == NULL) + return(XML_ERR_ARGUMENT); - if (URI == NULL) return(NULL); + /* + * Allocate the Input buffer front-end. + */ + buf = xmlAllocParserInputBuffer(enc); + if (buf == NULL) + return(XML_ERR_NO_MEMORY); /* * Try to find one of the input accept method accepting that scheme * Go in reverse to give precedence to user defined handlers. */ - if (context == NULL) { - for (i = xmlInputCallbackNr - 1;i >= 0;i--) { - if ((xmlInputCallbackTable[i].matchcallback != NULL) && - (xmlInputCallbackTable[i].matchcallback(URI) != 0)) { - context = xmlInputCallbackTable[i].opencallback(URI); - if (context != NULL) { - break; - } - } - } + ret = XML_IO_ENOENT; + for (i = xmlInputCallbackNr - 1; i >= 0; i--) { + xmlInputCallback *cb = &xmlInputCallbackTable[i]; + + if (cb->matchcallback == xmlIODefaultMatch) { + ret = xmlInputDefaultOpen(buf, URI); + + if ((ret == XML_ERR_OK) || (ret != XML_IO_ENOENT)) + break; + } else if ((cb->matchcallback != NULL) && + (cb->matchcallback(URI) != 0)) { + buf->context = cb->opencallback(URI); + if (buf->context != NULL) { + buf->readcallback = cb->readcallback; + buf->closecallback = cb->closecallback; + ret = XML_ERR_OK; + break; + } + } } - if (context == NULL) { - return(NULL); + if (ret != XML_ERR_OK) { + xmlFreeParserInputBuffer(buf); + *out = NULL; + return(ret); } - /* - * Allocate the Input buffer front-end. - */ - ret = xmlAllocParserInputBuffer(enc); - if (ret != NULL) { - ret->context = context; - ret->readcallback = xmlInputCallbackTable[i].readcallback; - ret->closecallback = xmlInputCallbackTable[i].closecallback; -#ifdef LIBXML_ZLIB_ENABLED - if ((xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) && - (strcmp(URI, "-") != 0)) { -#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230 - ret->compressed = !gzdirect(context); -#else - if (((z_stream *)context)->avail_in > 4) { - char *cptr, buff4[4]; - cptr = (char *) ((z_stream *)context)->next_in; - if (gzread(context, buff4, 4) == 4) { - if (strncmp(buff4, cptr, 4) == 0) - ret->compressed = 0; - else - ret->compressed = 1; - gzrewind(context); - } - } -#endif - } -#endif -#ifdef LIBXML_LZMA_ENABLED - if ((xmlInputCallbackTable[i].opencallback == xmlXzfileOpen) && - (strcmp(URI, "-") != 0)) { - ret->compressed = __libxml2_xzcompressed(context); - } -#endif - } - else - xmlInputCallbackTable[i].closecallback (context); + *out = buf; + return(ret); +} + +xmlParserInputBufferPtr +__xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + xmlParserInputBufferCreateFilenameInt(URI, enc, &ret); return(ret); } @@ -2539,7 +1649,6 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { * @enc: the charset encoding if known * * Create a buffered parser input for the progressive parsing of a file - * If filename is "-' then we use stdin as the input. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. * Do an encoding check if enc == XML_CHAR_ENCODING_NONE @@ -2548,135 +1657,104 @@ __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { */ xmlParserInputBufferPtr xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) { - if ((xmlParserInputBufferCreateFilenameValue)) { - return xmlParserInputBufferCreateFilenameValue(URI, enc); - } - return __xmlParserInputBufferCreateFilename(URI, enc); + if (xmlParserInputBufferCreateFilenameValue != NULL) + return(xmlParserInputBufferCreateFilenameValue(URI, enc)); + + return(__xmlParserInputBufferCreateFilename(URI, enc)); +} + +/** + * xmlParserInputBufferCreateFilenameSafe: + * @URI: the filename or URI + * @enc: encoding enum (deprecated) + * @out: pointer to resulting input buffer + * + * Create an input buffer for a filename or URI. + * + * Returns an xmlParserErrors code. + */ +int +xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc, + xmlParserInputBufferPtr *out) { + if (xmlParserInputBufferCreateFilenameValue != NULL) { + *out = xmlParserInputBufferCreateFilenameValue(URI, enc); + + if (*out == NULL) + return(XML_IO_ENOENT); + return(XML_ERR_OK); + } + + return(xmlParserInputBufferCreateFilenameInt(URI, enc, out)); } #ifdef LIBXML_OUTPUT_ENABLED xmlOutputBufferPtr __xmlOutputBufferCreateFilename(const char *URI, xmlCharEncodingHandlerPtr encoder, - int compression ATTRIBUTE_UNUSED) { + int compression) { xmlOutputBufferPtr ret; xmlURIPtr puri; int i = 0; - void *context = NULL; char *unescaped = NULL; -#ifdef LIBXML_ZLIB_ENABLED - int is_file_uri = 1; -#endif - - if (xmlOutputCallbackInitialized == 0) - xmlRegisterDefaultOutputCallbacks(); - if (URI == NULL) return(NULL); + if (URI == NULL) + return(NULL); puri = xmlParseURI(URI); if (puri != NULL) { -#ifdef LIBXML_ZLIB_ENABLED - if ((puri->scheme != NULL) && - (!xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))) - is_file_uri = 0; -#endif - /* - * try to limit the damages of the URI unescaping code. - */ - if ((puri->scheme == NULL) || - (xmlStrEqual(BAD_CAST puri->scheme, BAD_CAST "file"))) - unescaped = xmlURIUnescapeString(URI, 0, NULL); - xmlFreeURI(puri); + /* + * try to limit the damages of the URI unescaping code. + */ + if (puri->scheme == NULL) { + unescaped = xmlURIUnescapeString(URI, 0, NULL); + if (unescaped == NULL) { + xmlFreeURI(puri); + return(NULL); + } + URI = unescaped; + } + xmlFreeURI(puri); } /* - * Try to find one of the output accept method accepting that scheme - * Go in reverse to give precedence to user defined handlers. - * try with an unescaped version of the URI + * Allocate the Output buffer front-end. */ - if (unescaped != NULL) { -#ifdef LIBXML_ZLIB_ENABLED - if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { - context = xmlGzfileOpenW(unescaped, compression); - if (context != NULL) { - ret = xmlAllocOutputBufferInternal(encoder); - if (ret != NULL) { - ret->context = context; - ret->writecallback = xmlGzfileWrite; - ret->closecallback = xmlGzfileClose; - } - xmlFree(unescaped); - return(ret); - } - } -#endif - for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { - if ((xmlOutputCallbackTable[i].matchcallback != NULL) && - (xmlOutputCallbackTable[i].matchcallback(unescaped) != 0)) { -#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED) - /* Need to pass compression parameter into HTTP open calls */ - if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) - context = xmlIOHTTPOpenW(unescaped, compression); - else -#endif - context = xmlOutputCallbackTable[i].opencallback(unescaped); - if (context != NULL) - break; - } - } - xmlFree(unescaped); + ret = xmlAllocOutputBufferInternal(encoder); + if (ret == NULL) { + xmlFree(unescaped); + return(NULL); } /* - * If this failed try with a non-escaped URI this may be a strange - * filename + * Try to find one of the output accept method accepting that scheme + * Go in reverse to give precedence to user defined handlers. */ - if (context == NULL) { -#ifdef LIBXML_ZLIB_ENABLED - if ((compression > 0) && (compression <= 9) && (is_file_uri == 1)) { - context = xmlGzfileOpenW(URI, compression); - if (context != NULL) { - ret = xmlAllocOutputBufferInternal(encoder); - if (ret != NULL) { - ret->context = context; - ret->writecallback = xmlGzfileWrite; - ret->closecallback = xmlGzfileClose; - } - else - xmlGzfileClose(context); - return(ret); - } - } -#endif - for (i = xmlOutputCallbackNr - 1;i >= 0;i--) { - if ((xmlOutputCallbackTable[i].matchcallback != NULL) && - (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) { -#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_ZLIB_ENABLED) - /* Need to pass compression parameter into HTTP open calls */ - if (xmlOutputCallbackTable[i].matchcallback == xmlIOHTTPMatch) - context = xmlIOHTTPOpenW(URI, compression); - else -#endif - context = xmlOutputCallbackTable[i].opencallback(URI); - if (context != NULL) - break; - } - } - } + for (i = xmlOutputCallbackNr - 1; i >= 0; i--) { + xmlOutputCallback *cb = &xmlOutputCallbackTable[i]; + int code; - if (context == NULL) { - return(NULL); + if (cb->matchcallback == xmlIODefaultMatch) { + code = xmlOutputDefaultOpen(ret, URI, compression); + /* TODO: Handle other errors */ + if (code == XML_ERR_OK) + break; + } else if ((cb->matchcallback != NULL) && + (cb->matchcallback(URI) != 0)) { + ret->context = cb->opencallback(URI); + if (ret->context != NULL) { + ret->writecallback = cb->writecallback; + ret->closecallback = cb->closecallback; + break; + } + } } - /* - * Allocate the Output buffer front-end. - */ - ret = xmlAllocOutputBufferInternal(encoder); - if (ret != NULL) { - ret->context = context; - ret->writecallback = xmlOutputCallbackTable[i].writecallback; - ret->closecallback = xmlOutputCallbackTable[i].closecallback; + if (ret->context == NULL) { + xmlOutputBufferClose(ret); + ret = NULL; } + + xmlFree(unescaped); return(ret); } @@ -2709,27 +1787,28 @@ xmlOutputBufferCreateFilename(const char *URI, /** * xmlParserInputBufferCreateFile: * @file: a FILE* - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing of a FILE * * buffered C I/O * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) { xmlParserInputBufferPtr ret; - if (xmlInputCallbackInitialized == 0) - xmlRegisterDefaultInputCallbacks(); - if (file == NULL) return(NULL); ret = xmlAllocParserInputBuffer(enc); if (ret != NULL) { ret->context = file; ret->readcallback = xmlFileRead; - ret->closecallback = xmlFileFlush; + ret->closecallback = NULL; } return(ret); @@ -2750,9 +1829,6 @@ xmlOutputBufferPtr xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; - if (xmlOutputCallbackInitialized == 0) - xmlRegisterDefaultOutputCallbacks(); - if (file == NULL) return(NULL); ret = xmlAllocOutputBufferInternal(encoder); @@ -2797,7 +1873,7 @@ xmlOutputBufferCreateBuffer(xmlBufferPtr buffer, */ const xmlChar * xmlOutputBufferGetContent(xmlOutputBufferPtr out) { - if ((out == NULL) || (out->buffer == NULL)) + if ((out == NULL) || (out->buffer == NULL) || (out->error != 0)) return(NULL); return(xmlBufContent(out->buffer)); @@ -2813,7 +1889,7 @@ xmlOutputBufferGetContent(xmlOutputBufferPtr out) { */ size_t xmlOutputBufferGetSize(xmlOutputBufferPtr out) { - if ((out == NULL) || (out->buffer == NULL)) + if ((out == NULL) || (out->buffer == NULL) || (out->error != 0)) return(0); return(xmlBufUse(out->buffer)); @@ -2825,11 +1901,15 @@ xmlOutputBufferGetSize(xmlOutputBufferPtr out) { /** * xmlParserInputBufferCreateFd: * @fd: a file descriptor number - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing for the input * from a file descriptor * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -2842,7 +1922,6 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) { if (ret != NULL) { ret->context = (void *) (ptrdiff_t) fd; ret->readcallback = xmlFdRead; - ret->closecallback = xmlFdClose; } return(ret); @@ -2872,17 +1951,71 @@ static int xmlMemClose(void *vctxt) { xmlMemIOCtxt *ctxt = vctxt; - if (ctxt->mem != 0) + if (ctxt->mem != NULL) xmlFree(ctxt->mem); xmlFree(ctxt); return(0); } +/** + * xmlNewInputBufferMemory: + * @mem: memory buffer + * @size: size of buffer + * @flags: flags + * @enc: the charset encoding if known (deprecated) + * + * Create an input buffer for memory. + * + * Returns the new input buffer or NULL. + */ +xmlParserInputBufferPtr +xmlNewInputBufferMemory(const void *mem, size_t size, int flags, + xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + xmlMemIOCtxt *ctxt; + char *copy = NULL; + + if ((flags & XML_INPUT_BUF_STATIC) == 0) { + if (size + 1 == 0) + return(NULL); + copy = xmlMalloc(size + 1); + if (copy == NULL) + return(NULL); + memcpy(copy, mem, size); + copy[size] = 0; + + mem = copy; + } + + ret = xmlAllocParserInputBuffer(enc); + if (ret == NULL) { + xmlFree(copy); + return(NULL); + } + + ctxt = xmlMalloc(sizeof(*ctxt)); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(ret); + xmlFree(copy); + return(NULL); + } + + ctxt->mem = copy; + ctxt->cur = mem; + ctxt->size = size; + + ret->context = ctxt; + ret->readcallback = xmlMemRead; + ret->closecallback = xmlMemClose; + + return(ret); +} + /** * xmlParserInputBufferCreateMem: * @mem: the memory input * @size: the length of the memory block - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a parser input buffer for parsing from a memory area. * @@ -2894,32 +2027,15 @@ xmlMemClose(void *vctxt) { * The encoding argument is deprecated and should be set to * XML_CHAR_ENCODING_NONE. The encoding can be changed with * xmlSwitchEncoding or xmlSwitchEncodingName later on. - * - * Returns the new parser input or NULL in case of error. - */ -xmlParserInputBufferPtr -xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { - xmlParserInputBufferPtr buf; - xmlMemIOCtxt *ctxt; - char *copy; - - if ((size < 0) || (mem == NULL)) - return(NULL); - - copy = (char *) xmlStrndup((const xmlChar *) mem, size); - if (copy == NULL) - return(NULL); - - buf = xmlParserInputBufferCreateStatic(copy, size, enc); - if (buf == NULL) { - xmlFree(copy); + * + * Returns the new parser input or NULL in case of error. + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { + if ((mem == NULL) || (size < 0)) return(NULL); - } - - ctxt = buf->context; - ctxt->mem = copy; - return(buf); + return(xmlNewInputBufferMemory(mem, size, 0, enc)); } /** @@ -2943,40 +2059,20 @@ xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { xmlParserInputBufferPtr xmlParserInputBufferCreateStatic(const char *mem, int size, xmlCharEncoding enc) { - xmlParserInputBufferPtr ret; - xmlMemIOCtxt *ctxt; - - if ((size < 0) || (mem == NULL)) - return(NULL); - - ret = xmlAllocParserInputBuffer(enc); - if (ret == NULL) - return(NULL); - - ctxt = xmlMalloc(sizeof(*ctxt)); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(ret); + if ((mem == NULL) || (size < 0)) return(NULL); - } - ctxt->mem = NULL; - ctxt->cur = mem; - ctxt->size = size; - - ret->context = ctxt; - ret->readcallback = xmlMemRead; - ret->closecallback = xmlMemClose; - return(ret); + return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc)); } typedef struct { - const xmlChar *str; + const char *str; } xmlStringIOCtxt; static int xmlStringRead(void *vctxt, char *buf, int size) { xmlStringIOCtxt *ctxt = vctxt; - const xmlChar *zero; + const char *zero; size_t len; zero = memchr(ctxt->str, 0, size); @@ -2995,20 +2091,22 @@ xmlStringClose(void *vctxt) { } /** - * xmlParserInputBufferCreateString: - * @str: a null-terminated string + * xmlNewInputBufferString: + * @str: C string + * @flags: flags * - * Create a buffered parser input for the progressive parsing for the input - * from a null-terminated C string. + * Create an input buffer for a null-teriminated C string. * - * Returns the new parser input or NULL + * Returns the new input buffer or NULL. */ xmlParserInputBufferPtr -xmlParserInputBufferCreateString(const xmlChar *str) { +xmlNewInputBufferString(const char *str, int flags) { xmlParserInputBufferPtr ret; xmlStringIOCtxt *ctxt; - if (str == NULL) return(NULL); + if ((flags & XML_INPUT_BUF_STATIC) == 0) + return(xmlNewInputBufferMemory(str, strlen(str), flags, + XML_CHAR_ENCODING_NONE)); ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); if (ret == NULL) @@ -3019,6 +2117,7 @@ xmlParserInputBufferCreateString(const xmlChar *str) { xmlFreeParserInputBuffer(ret); return(NULL); } + ctxt->str = str; ret->context = ctxt; @@ -3061,11 +2160,15 @@ xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) { * @ioread: an I/O read function * @ioclose: an I/O close function * @ioctx: an I/O handler - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing for the input * from an I/O handler * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -3274,7 +2377,10 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { if (res <= 0) in->readcallback = endOfInput; if (res < 0) { - in->error = XML_IO_UNKNOWN; + if (res == -1) + in->error = XML_IO_UNKNOWN; + else + in->error = -res; return(-1); } @@ -3359,10 +2465,16 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { */ if (out->conv == NULL) { out->conv = xmlBufCreate(); + if (out->conv == NULL) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } } ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk); - if (ret != 0) + if (ret != 0) { + out->error = XML_ERR_NO_MEMORY; return(-1); + } if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len)) goto done; @@ -3371,19 +2483,18 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { * convert as much as possible to the parser reading buffer. */ ret = xmlCharEncOutput(out, 0); - if ((ret < 0) && (ret != -3)) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (ret < 0) return(-1); - } if (out->writecallback) nbchars = xmlBufUse(out->conv); else nbchars = ret >= 0 ? ret : 0; } else { ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk); - if (ret != 0) + if (ret != 0) { + out->error = XML_ERR_NO_MEMORY; return(-1); + } if (out->writecallback) nbchars = xmlBufUse(out->buffer); else @@ -3411,8 +2522,10 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_WRITE, NULL); - out->error = XML_IO_WRITE; + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + + xmlIOErr(errNo, NULL); + out->error = errNo; return(ret); } if (out->written > INT_MAX - ret) @@ -3535,8 +2648,10 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, * not the case force a flush, but make sure we stay in the loop */ if (chunk < 40) { - if (xmlBufGrow(out->buffer, 100) < 0) + if (xmlBufGrow(out->buffer, 100) < 0) { + out->error = XML_ERR_NO_MEMORY; return(-1); + } oldwritten = -1; continue; } @@ -3550,11 +2665,17 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, */ if (out->conv == NULL) { out->conv = xmlBufCreate(); + if (out->conv == NULL) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } } ret = escaping(xmlBufEnd(out->buffer) , &chunk, str, &cons); - if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ - return(-1); + if (ret < 0) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } xmlBufAddLen(out->buffer, chunk); if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len)) @@ -3564,19 +2685,18 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, * convert as much as possible to the output buffer. */ ret = xmlCharEncOutput(out, 0); - if ((ret < 0) && (ret != -3)) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (ret < 0) return(-1); - } if (out->writecallback) nbchars = xmlBufUse(out->conv); else nbchars = ret >= 0 ? ret : 0; } else { ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons); - if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ - return(-1); + if (ret < 0) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } xmlBufAddLen(out->buffer, chunk); if (out->writecallback) nbchars = xmlBufUse(out->buffer); @@ -3605,16 +2725,20 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_WRITE, NULL); - out->error = XML_IO_WRITE; - return(ret); + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + xmlIOErr(errNo, NULL); + out->error = errNo; + return(-1); } if (out->written > INT_MAX - ret) out->written = INT_MAX; else out->written += ret; } else if (xmlBufAvail(out->buffer) < MINLEN) { - xmlBufGrow(out->buffer, MINLEN); + if (xmlBufGrow(out->buffer, MINLEN) < 0) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } } written += nbchars; } while ((len > 0) && (oldwritten != written)); @@ -3650,6 +2774,56 @@ xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) { return(len); } +/** + * xmlOutputBufferWriteQuotedString: + * @buf: output buffer + * @string: the string to add + * + * routine which manage and grows an output buffer. This one writes + * a quoted or double quoted #xmlChar string, checking first if it holds + * quote or double-quotes internally + */ +void +xmlOutputBufferWriteQuotedString(xmlOutputBufferPtr buf, + const xmlChar *string) { + const xmlChar *cur, *base; + + if ((buf == NULL) || (buf->error)) + return; + + if (xmlStrchr(string, '\"')) { + if (xmlStrchr(string, '\'')) { + xmlOutputBufferWrite(buf, 1, "\""); + base = cur = string; + while(*cur != 0){ + if(*cur == '"'){ + if (base != cur) + xmlOutputBufferWrite(buf, cur - base, + (const char *) base); + xmlOutputBufferWrite(buf, 6, """); + cur++; + base = cur; + } + else { + cur++; + } + } + if (base != cur) + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 1, "\""); + } + else{ + xmlOutputBufferWrite(buf, 1, "'"); + xmlOutputBufferWriteString(buf, (const char *) string); + xmlOutputBufferWrite(buf, 1, "'"); + } + } else { + xmlOutputBufferWrite(buf, 1, "\""); + xmlOutputBufferWriteString(buf, (const char *) string); + xmlOutputBufferWrite(buf, 1, "\""); + } +} + /** * xmlOutputBufferFlush: * @out: a buffered output @@ -3672,11 +2846,8 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) { */ do { nbchars = xmlCharEncOutput(out, 0); - if (nbchars < 0) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (nbchars < 0) return(-1); - } } while (nbchars); } @@ -3698,8 +2869,10 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) { xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_FLUSH, NULL); - out->error = XML_IO_FLUSH; + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + + xmlIOErr(errNo, NULL); + out->error = errNo; return(ret); } if (out->written > INT_MAX - ret) @@ -3725,9 +2898,6 @@ xmlParserGetDirectory(const char *filename) { char dir[1024]; char *cur; - if (xmlInputCallbackInitialized == 0) - xmlRegisterDefaultInputCallbacks(); - if (filename == NULL) return(NULL); #if defined(_WIN32) @@ -3757,332 +2927,202 @@ xmlParserGetDirectory(const char *filename) { #undef IS_XMLPGD_SEP } -/**************************************************************** - * * - * External entities loading * - * * - ****************************************************************/ - /** - * xmlCheckHTTPInput: - * @ctxt: an XML parser context - * @ret: an XML parser input + * xmlNoNetExists: + * @filename: the path to check + * + * DEPRECATED: Internal function, don't use. * - * Check an input in case it was created from an HTTP stream, in that - * case it will handle encoding and update of the base URL in case of - * redirection. It also checks for HTTP errors in which case the input - * is cleanly freed up and an appropriate error is raised in context + * Like xmlCheckFilename but handles file URIs. * - * Returns the input or NULL in case of HTTP error. + * Returns 0, 1, or 2. */ -xmlParserInputPtr -xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { - /* Avoid unused variable warning if features are disabled. */ - (void) ctxt; +int +xmlNoNetExists(const char *filename) { + char *fromUri; + int ret; -#ifdef LIBXML_HTTP_ENABLED - if ((ret != NULL) && (ret->buf != NULL) && - (ret->buf->readcallback == xmlIOHTTPRead) && - (ret->buf->context != NULL)) { - const char *encoding; - const char *redir; - const char *mime; - int code; + if (filename == NULL) + return(0); - code = xmlNanoHTTPReturnCode(ret->buf->context); - if (code >= 400) { - /* fatal error */ - if (ret->filename != NULL) - __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n", - (const char *) ret->filename); - else - __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL); - xmlFreeInputStream(ret); - ret = NULL; - } else { + if (xmlConvertUriToPath(filename, &fromUri) < 0) + return(0); - mime = xmlNanoHTTPMimeType(ret->buf->context); - if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) || - (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) { - encoding = xmlNanoHTTPEncoding(ret->buf->context); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr handler; - - handler = xmlFindCharEncodingHandler(encoding); - if (handler != NULL) { - xmlSwitchInputEncoding(ctxt, ret, handler); - } else { - __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING, - "Unknown encoding %s", - BAD_CAST encoding, NULL); - } - } -#if 0 - } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { -#endif - } - redir = xmlNanoHTTPRedir(ret->buf->context); - if (redir != NULL) { - if (ret->filename != NULL) - xmlFree((xmlChar *) ret->filename); - if (ret->directory != NULL) { - xmlFree((xmlChar *) ret->directory); - ret->directory = NULL; - } - ret->filename = - (char *) xmlStrdup((const xmlChar *) redir); - } - } - } -#endif + if (fromUri != NULL) + filename = fromUri; + + ret = xmlCheckFilename(filename); + + xmlFree(fromUri); return(ret); } -static int xmlNoNetExists(const char *URL) { - const char *path; +/************************************************************************ + * * + * Input/output callbacks * + * * + ************************************************************************/ - if (URL == NULL) - return(0); +/** + * xmlInitIOCallbacks: + * + * Initialize callback tables. + */ +void +xmlInitIOCallbacks(void) +{ + xmlInputCallbackNr = 1; + xmlInputCallbackTable[0].matchcallback = xmlIODefaultMatch; - if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file://localhost/", 17)) -#if defined (_WIN32) - path = &URL[17]; -#else - path = &URL[16]; -#endif - else if (!xmlStrncasecmp(BAD_CAST URL, BAD_CAST "file:///", 8)) { -#if defined (_WIN32) - path = &URL[8]; -#else - path = &URL[7]; +#ifdef LIBXML_OUTPUT_ENABLED + xmlOutputCallbackNr = 1; + xmlOutputCallbackTable[0].matchcallback = xmlIODefaultMatch; #endif - } else - path = URL; - - return xmlCheckFilename(path); } -#ifdef LIBXML_CATALOG_ENABLED - /** - * xmlResolveResourceFromCatalog: - * @URL: the URL for the entity to load - * @ID: the System ID for the entity to load - * @ctxt: the context in which the entity is called or NULL + * xmlRegisterInputCallbacks: + * @matchFunc: the xmlInputMatchCallback + * @openFunc: the xmlInputOpenCallback + * @readFunc: the xmlInputReadCallback + * @closeFunc: the xmlInputCloseCallback * - * Resolves the URL and ID against the appropriate catalog. - * This function is used by xmlDefaultExternalEntityLoader and - * xmlNoNetExternalEntityLoader. + * Register a new set of I/O callback for handling parser input. * - * Returns a new allocated URL, or NULL. + * Returns the registered handler number or -1 in case of error */ -static xmlChar * -xmlResolveResourceFromCatalog(const char *URL, const char *ID, - xmlParserCtxtPtr ctxt) { - xmlChar *resource = NULL; - xmlCatalogAllow pref; - - /* - * If the resource doesn't exists as a file, - * try to load it from the resource pointed in the catalogs - */ - pref = xmlCatalogGetDefaults(); - - if ((pref != XML_CATA_ALLOW_NONE) && (!xmlNoNetExists(URL))) { - /* - * Do a local lookup - */ - if ((ctxt != NULL) && (ctxt->catalogs != NULL) && - ((pref == XML_CATA_ALLOW_ALL) || - (pref == XML_CATA_ALLOW_DOCUMENT))) { - resource = xmlCatalogLocalResolve(ctxt->catalogs, - (const xmlChar *)ID, - (const xmlChar *)URL); - } - /* - * Try a global lookup - */ - if ((resource == NULL) && - ((pref == XML_CATA_ALLOW_ALL) || - (pref == XML_CATA_ALLOW_GLOBAL))) { - resource = xmlCatalogResolve((const xmlChar *)ID, - (const xmlChar *)URL); - } - if ((resource == NULL) && (URL != NULL)) - resource = xmlStrdup((const xmlChar *) URL); - - /* - * TODO: do an URI lookup on the reference - */ - if ((resource != NULL) && (!xmlNoNetExists((const char *)resource))) { - xmlChar *tmp = NULL; - - if ((ctxt != NULL) && (ctxt->catalogs != NULL) && - ((pref == XML_CATA_ALLOW_ALL) || - (pref == XML_CATA_ALLOW_DOCUMENT))) { - tmp = xmlCatalogLocalResolveURI(ctxt->catalogs, resource); - } - if ((tmp == NULL) && - ((pref == XML_CATA_ALLOW_ALL) || - (pref == XML_CATA_ALLOW_GLOBAL))) { - tmp = xmlCatalogResolveURI(resource); - } - - if (tmp != NULL) { - xmlFree(resource); - resource = tmp; - } - } +int +xmlRegisterInputCallbacks(xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc) { + if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) { + return(-1); } - - return resource; + xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = matchFunc; + xmlInputCallbackTable[xmlInputCallbackNr].opencallback = openFunc; + xmlInputCallbackTable[xmlInputCallbackNr].readcallback = readFunc; + xmlInputCallbackTable[xmlInputCallbackNr].closecallback = closeFunc; + return(xmlInputCallbackNr++); } -#endif +/** + * xmlRegisterDefaultInputCallbacks: + * + * Registers the default compiled-in I/O handlers. + */ +void +xmlRegisterDefaultInputCallbacks(void) { + xmlRegisterInputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL); +} /** - * xmlDefaultExternalEntityLoader: - * @URL: the URL for the entity to load - * @ID: the System ID for the entity to load - * @ctxt: the context in which the entity is called or NULL + * xmlPopInputCallbacks: * - * By default we don't load external entities, yet. + * Clear the top input callback from the input stack. this includes the + * compiled-in I/O. * - * Returns a new allocated xmlParserInputPtr, or NULL. + * Returns the number of input callback registered or -1 in case of error. */ -static xmlParserInputPtr -xmlDefaultExternalEntityLoader(const char *URL, const char *ID, - xmlParserCtxtPtr ctxt) +int +xmlPopInputCallbacks(void) { - xmlParserInputPtr ret = NULL; - xmlChar *resource = NULL; - - if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) { - int options = ctxt->options; - - ctxt->options -= XML_PARSE_NONET; - ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); - ctxt->options = options; - return(ret); - } -#ifdef LIBXML_CATALOG_ENABLED - resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); -#endif + if (xmlInputCallbackNr <= 0) + return(-1); - if (resource == NULL) - resource = (xmlChar *) URL; + xmlInputCallbackNr--; - if (resource == NULL) { - if (ID == NULL) - ID = "NULL"; - __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID); - return (NULL); - } - ret = xmlNewInputFromFile(ctxt, (const char *) resource); - if ((resource != NULL) && (resource != (xmlChar *) URL)) - xmlFree(resource); - return (ret); + return(xmlInputCallbackNr); } -static xmlExternalEntityLoader xmlCurrentExternalEntityLoader = - xmlDefaultExternalEntityLoader; - /** - * xmlSetExternalEntityLoader: - * @f: the new entity resolver function + * xmlCleanupInputCallbacks: * - * Changes the defaultexternal entity resolver function for the application + * clears the entire input callback table. this includes the + * compiled-in I/O. */ void -xmlSetExternalEntityLoader(xmlExternalEntityLoader f) { - xmlCurrentExternalEntityLoader = f; +xmlCleanupInputCallbacks(void) +{ + xmlInputCallbackNr = 0; } +#ifdef LIBXML_OUTPUT_ENABLED /** - * xmlGetExternalEntityLoader: + * xmlRegisterOutputCallbacks: + * @matchFunc: the xmlOutputMatchCallback + * @openFunc: the xmlOutputOpenCallback + * @writeFunc: the xmlOutputWriteCallback + * @closeFunc: the xmlOutputCloseCallback + * + * Register a new set of I/O callback for handling output. * - * Get the default external entity resolver function for the application + * Returns the registered handler number or -1 in case of error + */ +int +xmlRegisterOutputCallbacks(xmlOutputMatchCallback matchFunc, + xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc, + xmlOutputCloseCallback closeFunc) { + if (xmlOutputCallbackNr >= MAX_OUTPUT_CALLBACK) { + return(-1); + } + xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = matchFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = openFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = writeFunc; + xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = closeFunc; + return(xmlOutputCallbackNr++); +} + +/** + * xmlRegisterDefaultOutputCallbacks: * - * Returns the xmlExternalEntityLoader function pointer + * Registers the default compiled-in I/O handlers. */ -xmlExternalEntityLoader -xmlGetExternalEntityLoader(void) { - return(xmlCurrentExternalEntityLoader); +void +xmlRegisterDefaultOutputCallbacks (void) { + xmlRegisterOutputCallbacks(xmlIODefaultMatch, NULL, NULL, NULL); } /** - * xmlLoadExternalEntity: - * @URL: the URL for the entity to load - * @ID: the Public ID for the entity to load - * @ctxt: the context in which the entity is called or NULL + * xmlPopOutputCallbacks: * - * Load an external entity, note that the use of this function for - * unparsed entities may generate problems + * Remove the top output callbacks from the output stack. This includes the + * compiled-in I/O. * - * Returns the xmlParserInputPtr or NULL + * Returns the number of output callback registered or -1 in case of error. */ -xmlParserInputPtr -xmlLoadExternalEntity(const char *URL, const char *ID, - xmlParserCtxtPtr ctxt) { - if ((URL != NULL) && (xmlNoNetExists(URL) == 0)) { - char *canonicFilename; - xmlParserInputPtr ret; +int +xmlPopOutputCallbacks(void) +{ + if (xmlOutputCallbackNr <= 0) + return(-1); - canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); - if (canonicFilename == NULL) { - xmlErrMemory(ctxt, "building canonical path\n"); - return(NULL); - } + xmlOutputCallbackNr--; - ret = xmlCurrentExternalEntityLoader(canonicFilename, ID, ctxt); - xmlFree(canonicFilename); - return(ret); - } - return(xmlCurrentExternalEntityLoader(URL, ID, ctxt)); + return(xmlOutputCallbackNr); } -/************************************************************************ - * * - * Disabling Network access * - * * - ************************************************************************/ - /** - * xmlNoNetExternalEntityLoader: - * @URL: the URL for the entity to load - * @ID: the System ID for the entity to load - * @ctxt: the context in which the entity is called or NULL - * - * A specific entity loader disabling network accesses, though still - * allowing local catalog accesses for resolution. + * xmlCleanupOutputCallbacks: * - * Returns a new allocated xmlParserInputPtr, or NULL. + * clears the entire output callback table. this includes the + * compiled-in I/O callbacks. */ -xmlParserInputPtr -xmlNoNetExternalEntityLoader(const char *URL, const char *ID, - xmlParserCtxtPtr ctxt) { - xmlParserInputPtr input = NULL; - xmlChar *resource = NULL; - -#ifdef LIBXML_CATALOG_ENABLED - resource = xmlResolveResourceFromCatalog(URL, ID, ctxt); -#endif - - if (resource == NULL) - resource = (xmlChar *) URL; +void +xmlCleanupOutputCallbacks(void) +{ + xmlOutputCallbackNr = 0; +} - if (resource != NULL) { - if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) || - (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) { - xmlIOErr(XML_IO_NETWORK_ATTEMPT, (const char *) resource); - if (resource != (xmlChar *) URL) - xmlFree(resource); - return(NULL); - } - } - input = xmlDefaultExternalEntityLoader((const char *) resource, ID, ctxt); - if (resource != (xmlChar *) URL) - xmlFree(resource); - return(input); +#ifdef LIBXML_HTTP_ENABLED +/** + * xmlRegisterHTTPPostCallbacks: + * + * DEPRECATED: Support for HTTP POST has been removed. + */ +void +xmlRegisterHTTPPostCallbacks(void) { + xmlRegisterDefaultOutputCallbacks(); } +#endif +#endif /* LIBXML_OUTPUT_ENABLED */ diff --git a/xmllint.c b/xmllint.c index 9620007..3d17c37 100644 --- a/xmllint.c +++ b/xmllint.c @@ -84,10 +84,20 @@ #include #endif +#ifdef XMLLINT_FUZZ + #define ERR_STREAM stdout +#else + #define ERR_STREAM stderr +#endif + #ifndef XML_XML_DEFAULT_CATALOG #define XML_XML_DEFAULT_CATALOG "file://" SYSCONFDIR "/xml/catalog" #endif +#ifndef STDIN_FILENO + #define STDIN_FILENO 0 +#endif + typedef enum { XMLLINT_RETURN_OK = 0, /* No error */ XMLLINT_ERR_UNCLASS = 1, /* Unclassified */ @@ -97,11 +107,12 @@ typedef enum { XMLLINT_ERR_SCHEMACOMP = 5, /* Schema compilation */ XMLLINT_ERR_OUT = 6, /* Error writing output */ XMLLINT_ERR_SCHEMAPAT = 7, /* Error in schema pattern */ - XMLLINT_ERR_RDREGIS = 8, /* Error in Reader registration */ + /*XMLLINT_ERR_RDREGIS = 8,*/ XMLLINT_ERR_MEM = 9, /* Out of memory error */ XMLLINT_ERR_XPATH = 10, /* XPath evaluation error */ XMLLINT_ERR_XPATH_EMPTY = 11 /* XPath result is empty */ } xmllintReturnCode; + #ifdef LIBXML_DEBUG_ENABLED static int shell = 0; static int debugent = 0; @@ -111,44 +122,35 @@ static int maxmem = 0; #ifdef LIBXML_TREE_ENABLED static int copy = 0; #endif /* LIBXML_TREE_ENABLED */ -static int recovery = 0; -static int noent = 0; -static int noenc = 0; -static int noblanks = 0; static int noout = 0; -static int nowrap = 0; -static int format = 0; #ifdef LIBXML_OUTPUT_ENABLED static const char *output = NULL; +static int format = 0; +static const char *encoding = NULL; static int compress = 0; -static int oldout = 0; #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_VALID_ENABLED -static int valid = 0; static int postvalid = 0; -static char * dtdvalid = NULL; -static char * dtdvalidfpi = NULL; +static const char *dtdvalid = NULL; +static const char *dtdvalidfpi = NULL; +static int insert = 0; #endif #ifdef LIBXML_SCHEMAS_ENABLED -static char * relaxng = NULL; +static const char *relaxng = NULL; static xmlRelaxNGPtr relaxngschemas = NULL; -static char * schema = NULL; +static const char *schema = NULL; static xmlSchemaPtr wxschemas = NULL; #endif #ifdef LIBXML_SCHEMATRON_ENABLED -static char * schematron = NULL; +static const char *schematron = NULL; static xmlSchematronPtr wxschematron = NULL; #endif static int repeat = 0; -static int insert = 0; -#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED) +#if defined(LIBXML_HTML_ENABLED) static int html = 0; static int xmlout = 0; #endif static int htmlout = 0; -#if defined(LIBXML_HTML_ENABLED) -static int nodefdtd = 0; -#endif #ifdef LIBXML_PUSH_ENABLED static int push = 0; static int pushsize = 4096; @@ -157,28 +159,20 @@ static int pushsize = 4096; static int memory = 0; #endif static int testIO = 0; -static char *encoding = NULL; #ifdef LIBXML_XINCLUDE_ENABLED static int xinclude = 0; #endif -static int dtdattrs = 0; -static int loaddtd = 0; static xmllintReturnCode progresult = XMLLINT_RETURN_OK; static int quiet = 0; static int timing = 0; static int generate = 0; static int dropdtd = 0; -#ifdef LIBXML_CATALOG_ENABLED -static int catalogs = 0; -static int nocatalogs = 0; -#endif #ifdef LIBXML_C14N_ENABLED static int canonical = 0; static int canonical_11 = 0; static int exc_canonical = 0; #endif #ifdef LIBXML_READER_ENABLED -static int stream = 0; static int walker = 0; #ifdef LIBXML_PATTERN_ENABLED static const char *pattern = NULL; @@ -186,17 +180,10 @@ static xmlPatternPtr patternc = NULL; static xmlStreamCtxtPtr patstream = NULL; #endif #endif /* LIBXML_READER_ENABLED */ -static int chkregister = 0; -static int nbregister = 0; -#ifdef LIBXML_SAX1_ENABLED -static int sax1 = 0; -#endif /* LIBXML_SAX1_ENABLED */ #ifdef LIBXML_XPATH_ENABLED static const char *xpathquery = NULL; #endif static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES; -static int sax = 0; -static int oldxml10 = 0; static unsigned maxAmpl = 0; /************************************************************************ @@ -222,7 +209,7 @@ void parsePath(const xmlChar *path) { return; while (*path != 0) { if (nbpaths >= MAX_PATHS) { - fprintf(stderr, "MAX_PATHS reached: too many paths\n"); + fprintf(ERR_STREAM, "MAX_PATHS reached: too many paths\n"); return; } cur = path; @@ -277,7 +264,7 @@ xmllintExternalEntityLoader(const char *URL, const char *ID, ctxt->sax->error = err; if (load_trace) { fprintf \ - (stderr, + (ERR_STREAM, "Loaded URL=\"%s\" ID=\"%s\"\n", URL ? URL : "(null)", ID ? ID : "(null)"); @@ -300,7 +287,7 @@ xmllintExternalEntityLoader(const char *URL, const char *ID, ctxt->sax->error = err; if (load_trace) { fprintf \ - (stderr, + (ERR_STREAM, "Loaded URL=\"%s\" ID=\"%s\"\n", newURL, ID ? ID : "(null)"); @@ -322,6 +309,7 @@ xmllintExternalEntityLoader(const char *URL, const char *ID, } return(NULL); } + /************************************************************************ * * * Memory allocation consumption debugging * @@ -331,7 +319,7 @@ xmllintExternalEntityLoader(const char *URL, const char *ID, static void OOM(void) { - fprintf(stderr, "Ran out of memory needs > %d bytes\n", maxmem); + fprintf(ERR_STREAM, "Ran out of memory needs > %d bytes\n", maxmem); progresult = XMLLINT_ERR_MEM; } @@ -376,7 +364,7 @@ myStrdupFunc(const char *str) if (ret != NULL) { if (xmlMemUsed() > maxmem) { OOM(); - xmlFree(ret); + xmlMemFree(ret); return (NULL); } } @@ -443,10 +431,10 @@ endTimer(const char *fmt, ...) msec += (end.tv_usec - begin.tv_usec) / 1000; va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + vfprintf(ERR_STREAM, fmt, ap); va_end(ap); - fprintf(stderr, " took %ld ms\n", msec); + fprintf(ERR_STREAM, " took %ld ms\n", msec); } #else /* @@ -474,9 +462,9 @@ endTimer(const char *fmt, ...) msec = ((end - begin) * 1000) / CLOCKS_PER_SEC; va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + vfprintf(ERR_STREAM, fmt, ap); va_end(ap); - fprintf(stderr, " took %ld ms\n", msec); + fprintf(ERR_STREAM, " took %ld ms\n", msec); } #endif /************************************************************************ @@ -498,7 +486,7 @@ xmlHTMLEncodeSend(void) { memset(&buffer[sizeof(buffer)-4], 0, 4); result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer); if (result) { - xmlGenericError(xmlGenericErrorContext, "%s", result); + fprintf(ERR_STREAM, "%s", result); xmlFree(result); } buffer[0] = 0; @@ -514,7 +502,7 @@ xmlHTMLEncodeSend(void) { static void xmlHTMLPrintFileInfo(xmlParserInputPtr input) { int len; - xmlGenericError(xmlGenericErrorContext, "

"); + fprintf(ERR_STREAM, "

"); len = strlen(buffer); if (input != NULL) { @@ -542,7 +530,7 @@ xmlHTMLPrintFileContext(xmlParserInputPtr input) { int n; if (input == NULL) return; - xmlGenericError(xmlGenericErrorContext, "

\n");
+    fprintf(ERR_STREAM, "
\n");
     cur = input->cur;
     base = input->base;
     while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
@@ -574,7 +562,7 @@ xmlHTMLPrintFileContext(xmlParserInputPtr input) {
     len = strlen(buffer);
     snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
     xmlHTMLEncodeSend();
-    xmlGenericError(xmlGenericErrorContext, "
"); + fprintf(ERR_STREAM, "
"); } /** @@ -602,13 +590,13 @@ xmlHTMLError(void *ctx, const char *msg, ...) xmlHTMLPrintFileInfo(input); - xmlGenericError(xmlGenericErrorContext, "error: "); + fprintf(ERR_STREAM, "error: "); va_start(args, msg); len = strlen(buffer); vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args); va_end(args); xmlHTMLEncodeSend(); - xmlGenericError(xmlGenericErrorContext, "

\n"); + fprintf(ERR_STREAM, "

\n"); xmlHTMLPrintFileContext(input); xmlHTMLEncodeSend(); @@ -640,13 +628,13 @@ xmlHTMLWarning(void *ctx, const char *msg, ...) xmlHTMLPrintFileInfo(input); - xmlGenericError(xmlGenericErrorContext, "warning: "); + fprintf(ERR_STREAM, "warning: "); va_start(args, msg); len = strlen(buffer); vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args); va_end(args); xmlHTMLEncodeSend(); - xmlGenericError(xmlGenericErrorContext, "

\n"); + fprintf(ERR_STREAM, "

\n"); xmlHTMLPrintFileContext(input); xmlHTMLEncodeSend(); @@ -671,20 +659,24 @@ xmlHTMLValidityError(void *ctx, const char *msg, ...) buffer[0] = 0; input = ctxt->input; - if ((input->filename == NULL) && (ctxt->inputNr > 1)) - input = ctxt->inputTab[ctxt->inputNr - 2]; - xmlHTMLPrintFileInfo(input); + if (input != NULL) { + if ((input->filename == NULL) && (ctxt->inputNr > 1)) + input = ctxt->inputTab[ctxt->inputNr - 2]; - xmlGenericError(xmlGenericErrorContext, "validity error: "); + xmlHTMLPrintFileInfo(input); + } + + fprintf(ERR_STREAM, "validity error: "); len = strlen(buffer); va_start(args, msg); vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args); va_end(args); xmlHTMLEncodeSend(); - xmlGenericError(xmlGenericErrorContext, "

\n"); + fprintf(ERR_STREAM, "

\n"); - xmlHTMLPrintFileContext(input); + if (input != NULL) + xmlHTMLPrintFileContext(input); xmlHTMLEncodeSend(); progresult = XMLLINT_ERR_VALID; } @@ -713,13 +705,13 @@ xmlHTMLValidityWarning(void *ctx, const char *msg, ...) xmlHTMLPrintFileInfo(input); - xmlGenericError(xmlGenericErrorContext, "validity warning: "); + fprintf(ERR_STREAM, "validity warning: "); va_start(args, msg); len = strlen(buffer); vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args); va_end(args); xmlHTMLEncodeSend(); - xmlGenericError(xmlGenericErrorContext, "

\n"); + fprintf(ERR_STREAM, "

\n"); xmlHTMLPrintFileContext(input); xmlHTMLEncodeSend(); @@ -1250,7 +1242,7 @@ charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) if (noout) return; for (i = 0;(i 0) { - fprintf(stderr, "%s fails to validate\n", filename); + fprintf(ERR_STREAM, "%s fails to validate\n", filename); progresult = XMLLINT_ERR_VALID; } else { - fprintf(stderr, "%s validation generated an internal error\n", + fprintf(ERR_STREAM, "%s validation generated an internal error\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -1654,10 +1649,14 @@ testSAX(const char *filename) { } if (maxAmpl > 0) xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - xmlCtxtReadFile(ctxt, filename, NULL, options); + + if (strcmp(filename, "-") == 0) + xmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL, options); + else + xmlCtxtReadFile(ctxt, filename, NULL, options); if (ctxt->myDoc != NULL) { - fprintf(stderr, "SAX generated a doc !\n"); + fprintf(ERR_STREAM, "SAX generated a doc !\n"); xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; } @@ -1725,7 +1724,7 @@ static void processNode(xmlTextReaderPtr reader) { xmlTextReaderConstLocalName(reader), xmlTextReaderConstNamespaceUri(reader)); if (ret < 0) { - fprintf(stderr, "xmlStreamPush() failure\n"); + fprintf(ERR_STREAM, "xmlStreamPush() failure\n"); xmlFreeStreamCtxt(patstream); patstream = NULL; } else if (ret != match) { @@ -1735,13 +1734,13 @@ static void processNode(xmlTextReaderPtr reader) { xmlTextReaderCurrentNode(reader)); } #endif - fprintf(stderr, + fprintf(ERR_STREAM, "xmlPatternMatch and xmlStreamPush disagree\n"); if (path != NULL) - fprintf(stderr, " pattern %s node %s\n", + fprintf(ERR_STREAM, " pattern %s node %s\n", pattern, path); else - fprintf(stderr, " pattern %s node %s\n", + fprintf(ERR_STREAM, " pattern %s node %s\n", pattern, xmlTextReaderConstName(reader)); } @@ -1750,7 +1749,7 @@ static void processNode(xmlTextReaderPtr reader) { ((type == XML_READER_TYPE_ELEMENT) && (empty))) { ret = xmlStreamPop(patstream); if (ret < 0) { - fprintf(stderr, "xmlStreamPop() failure\n"); + fprintf(ERR_STREAM, "xmlStreamPop() failure\n"); xmlFreeStreamCtxt(patstream); patstream = NULL; } @@ -1762,14 +1761,13 @@ static void processNode(xmlTextReaderPtr reader) { #endif } -static void streamFile(char *filename) { +static void streamFile(const char *filename) { xmlTextReaderPtr reader; int ret; #ifdef HAVE_MMAP int fd = -1; struct stat info; const char *base = NULL; - xmlParserInputBufferPtr input = NULL; if (memory) { if (stat(filename, &info) < 0) @@ -1779,7 +1777,7 @@ static void streamFile(char *filename) { base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ; if (base == (void *) MAP_FAILED) { close(fd); - fprintf(stderr, "mmap failure for file %s\n", filename); + fprintf(ERR_STREAM, "mmap failure for file %s\n", filename); progresult = XMLLINT_ERR_RDFILE; return; } @@ -1788,6 +1786,9 @@ static void streamFile(char *filename) { NULL, options); } else #endif + if (strcmp(filename, "-") == 0) + reader = xmlReaderForFd(STDIN_FILENO, "-", NULL, options); + else reader = xmlReaderForFile(filename, NULL, options); #ifdef LIBXML_PATTERN_ENABLED if (patternc != NULL) { @@ -1795,7 +1796,7 @@ static void streamFile(char *filename) { if (patstream != NULL) { ret = xmlStreamPush(patstream, NULL, NULL); if (ret < 0) { - fprintf(stderr, "xmlStreamPush() failure\n"); + fprintf(ERR_STREAM, "xmlStreamPush() failure\n"); xmlFreeStreamCtxt(patstream); patstream = NULL; } @@ -1807,13 +1808,6 @@ static void streamFile(char *filename) { if (reader != NULL) { if (maxAmpl > 0) xmlTextReaderSetMaxAmplification(reader, maxAmpl); -#ifdef LIBXML_VALID_ENABLED - if (valid) - xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1); - else -#endif /* LIBXML_VALID_ENABLED */ - if (loaddtd) - xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1); #ifdef LIBXML_SCHEMAS_ENABLED if (relaxng != NULL) { if ((timing) && (!repeat)) { @@ -1821,7 +1815,7 @@ static void streamFile(char *filename) { } ret = xmlTextReaderRelaxNGValidate(reader, relaxng); if (ret < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Relax-NG schema %s failed to compile\n", relaxng); progresult = XMLLINT_ERR_SCHEMACOMP; relaxng = NULL; @@ -1836,7 +1830,7 @@ static void streamFile(char *filename) { } ret = xmlTextReaderSchemaValidate(reader, schema); if (ret < 0) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "XSD schema %s failed to compile\n", schema); progresult = XMLLINT_ERR_SCHEMACOMP; schema = NULL; @@ -1870,7 +1864,7 @@ static void streamFile(char *filename) { else #endif #ifdef LIBXML_VALID_ENABLED - if (valid) + if (options & XML_PARSE_DTDVALID) endTimer("Parsing and validating"); else #endif @@ -1878,9 +1872,9 @@ static void streamFile(char *filename) { } #ifdef LIBXML_VALID_ENABLED - if (valid) { + if (options & XML_PARSE_DTDVALID) { if (xmlTextReaderIsValid(reader) != 1) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Document %s does not validate\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -1889,11 +1883,11 @@ static void streamFile(char *filename) { #ifdef LIBXML_SCHEMAS_ENABLED if ((relaxng != NULL) || (schema != NULL)) { if (xmlTextReaderIsValid(reader) != 1) { - fprintf(stderr, "%s fails to validate\n", filename); + fprintf(ERR_STREAM, "%s fails to validate\n", filename); progresult = XMLLINT_ERR_VALID; } else { if (!quiet) { - fprintf(stderr, "%s validates\n", filename); + fprintf(ERR_STREAM, "%s validates\n", filename); } } } @@ -1903,11 +1897,11 @@ static void streamFile(char *filename) { */ xmlFreeTextReader(reader); if (ret != 0) { - fprintf(stderr, "%s : failed to parse\n", filename); + fprintf(ERR_STREAM, "%s : failed to parse\n", filename); progresult = XMLLINT_ERR_UNCLASS; } } else { - fprintf(stderr, "Unable to open %s\n", filename); + fprintf(ERR_STREAM, "Unable to open %s\n", filename); progresult = XMLLINT_ERR_UNCLASS; } #ifdef LIBXML_PATTERN_ENABLED @@ -1918,7 +1912,6 @@ static void streamFile(char *filename) { #endif #ifdef HAVE_MMAP if (memory) { - xmlFreeParserInputBuffer(input); munmap((char *) base, info.st_size); close(fd); } @@ -1930,45 +1923,51 @@ static void walkDoc(xmlDocPtr doc) { int ret; #ifdef LIBXML_PATTERN_ENABLED - xmlNodePtr root; - const xmlChar *namespaces[22]; - int i; - xmlNsPtr ns; - - root = xmlDocGetRootElement(doc); - if (root == NULL ) { - xmlGenericError(xmlGenericErrorContext, - "Document does not have a root element"); - progresult = XMLLINT_ERR_UNCLASS; - return; - } - for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) { - namespaces[i++] = ns->href; - namespaces[i++] = ns->prefix; - } - namespaces[i++] = NULL; - namespaces[i] = NULL; - if (pattern != NULL) { - patternc = xmlPatterncompile((const xmlChar *) pattern, doc->dict, - 0, &namespaces[0]); + xmlNodePtr root; + const xmlChar *namespaces[22]; + int i; + xmlNsPtr ns; + + root = xmlDocGetRootElement(doc); + if (root == NULL ) { + fprintf(ERR_STREAM, + "Document does not have a root element"); + progresult = XMLLINT_ERR_UNCLASS; + return; + } + for (ns = root->nsDef, i = 0;ns != NULL && i < 20;ns=ns->next) { + namespaces[i++] = ns->href; + namespaces[i++] = ns->prefix; + } + namespaces[i++] = NULL; + namespaces[i] = NULL; + + ret = xmlPatternCompileSafe((const xmlChar *) pattern, doc->dict, + 0, &namespaces[0], &patternc); if (patternc == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Pattern %s failed to compile\n", pattern); - progresult = XMLLINT_ERR_SCHEMAPAT; - pattern = NULL; - } - } - if (patternc != NULL) { - patstream = xmlPatternGetStreamCtxt(patternc); - if (patstream != NULL) { - ret = xmlStreamPush(patstream, NULL, NULL); - if (ret < 0) { - fprintf(stderr, "xmlStreamPush() failure\n"); - xmlFreeStreamCtxt(patstream); - patstream = NULL; + if (ret < 0) { + progresult = XMLLINT_ERR_MEM; + } else { + fprintf(ERR_STREAM, + "Pattern %s failed to compile\n", pattern); + progresult = XMLLINT_ERR_SCHEMAPAT; } + goto error; } + + patstream = xmlPatternGetStreamCtxt(patternc); + if (patstream == NULL) { + progresult = XMLLINT_ERR_MEM; + goto error; + } + + ret = xmlStreamPush(patstream, NULL, NULL); + if (ret < 0) { + fprintf(ERR_STREAM, "xmlStreamPush() failure\n"); + progresult = XMLLINT_ERR_MEM; + goto error; + } } #endif /* LIBXML_PATTERN_ENABLED */ reader = xmlReaderWalker(doc); @@ -1991,14 +1990,20 @@ static void walkDoc(xmlDocPtr doc) { } xmlFreeTextReader(reader); if (ret != 0) { - fprintf(stderr, "failed to walk through the doc\n"); + fprintf(ERR_STREAM, "failed to walk through the doc\n"); progresult = XMLLINT_ERR_UNCLASS; } } else { - fprintf(stderr, "Failed to crate a reader from the document\n"); + fprintf(ERR_STREAM, "Failed to crate a reader from the document\n"); progresult = XMLLINT_ERR_UNCLASS; } + #ifdef LIBXML_PATTERN_ENABLED +error: + if (patternc != NULL) { + xmlFreePattern(patternc); + patternc = NULL; + } if (patstream != NULL) { xmlFreeStreamCtxt(patstream); patstream = NULL; @@ -2017,21 +2022,21 @@ static void walkDoc(xmlDocPtr doc) { static void doXPathDump(xmlXPathObjectPtr cur) { switch(cur->type) { case XPATH_NODESET: { - int i; - xmlNodePtr node; #ifdef LIBXML_OUTPUT_ENABLED xmlOutputBufferPtr buf; + xmlNodePtr node; + int i; if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr <= 0)) { progresult = XMLLINT_ERR_XPATH_EMPTY; if (!quiet) { - fprintf(stderr, "XPath set is empty\n"); + fprintf(ERR_STREAM, "XPath set is empty\n"); } break; } buf = xmlOutputBufferCreateFile(stdout, NULL); if (buf == NULL) { - fprintf(stderr, "Out of memory for XPath\n"); + fprintf(ERR_STREAM, "Out of memory for XPath\n"); progresult = XMLLINT_ERR_MEM; return; } @@ -2070,11 +2075,11 @@ static void doXPathDump(xmlXPathObjectPtr cur) { printf("%s\n", (const char *) cur->stringval); break; case XPATH_UNDEFINED: - fprintf(stderr, "XPath Object is uninitialized\n"); + fprintf(ERR_STREAM, "XPath Object is uninitialized\n"); progresult = XMLLINT_ERR_XPATH; break; default: - fprintf(stderr, "XPath object of unexpected type\n"); + fprintf(ERR_STREAM, "XPath object of unexpected type\n"); progresult = XMLLINT_ERR_XPATH; break; } @@ -2086,7 +2091,7 @@ static void doXPathQuery(xmlDocPtr doc, const char *query) { ctxt = xmlXPathNewContext(doc); if (ctxt == NULL) { - fprintf(stderr, "Out of memory for XPath\n"); + fprintf(ERR_STREAM, "Out of memory for XPath\n"); progresult = XMLLINT_ERR_MEM; return; } @@ -2095,7 +2100,7 @@ static void doXPathQuery(xmlDocPtr doc, const char *query) { xmlXPathFreeContext(ctxt); if (res == NULL) { - fprintf(stderr, "XPath evaluation failure\n"); + fprintf(ERR_STREAM, "XPath evaluation failure\n"); progresult = XMLLINT_ERR_XPATH; return; } @@ -2109,44 +2114,54 @@ static void doXPathQuery(xmlDocPtr doc, const char *query) { * Tree Test processing * * * ************************************************************************/ -static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { - xmlDocPtr doc = NULL; -#ifdef LIBXML_TREE_ENABLED - xmlDocPtr tmp; -#endif /* LIBXML_TREE_ENABLED */ - - if ((timing) && (!repeat)) - startTimer(); +static xmlDocPtr +parseFile(const char *filename, xmlParserCtxtPtr rectxt) { + xmlParserCtxtPtr ctxt; + xmlDocPtr doc = NULL; #ifdef LIBXML_TREE_ENABLED - if (filename == NULL) { - if (generate) { - xmlNodePtr n; + if ((generate) && (filename == NULL)) { + xmlNodePtr n; - doc = xmlNewDoc(BAD_CAST "1.0"); - n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL); - xmlNodeSetContent(n, BAD_CAST "abc"); - xmlDocSetRootElement(doc, n); - } + doc = xmlNewDoc(BAD_CAST "1.0"); + if (doc == NULL) { + progresult = XMLLINT_ERR_MEM; + return(NULL); + } + n = xmlNewDocNode(doc, NULL, BAD_CAST "info", NULL); + if (n == NULL) { + xmlFreeDoc(doc); + progresult = XMLLINT_ERR_MEM; + return(NULL); + } + if (xmlNodeSetContent(n, BAD_CAST "abc") < 0) { + xmlFreeNode(n); + xmlFreeDoc(doc); + progresult = XMLLINT_ERR_MEM; + return(NULL); + } + xmlDocSetRootElement(doc, n); + + return(doc); } #endif /* LIBXML_TREE_ENABLED */ + #ifdef LIBXML_HTML_ENABLED #ifdef LIBXML_PUSH_ENABLED - else if ((html) && (push)) { + if ((html) && (push)) { FILE *f; int res; char chars[4096]; - htmlParserCtxtPtr ctxt; if ((filename[0] == '-') && (filename[1] == 0)) { f = stdin; } else { f = fopen(filename, "rb"); if (f == NULL) { - fprintf(stderr, "Can't open %s\n", filename); - progresult = XMLLINT_ERR_UNCLASS; - return; + fprintf(ERR_STREAM, "Can't open %s\n", filename); + progresult = XMLLINT_ERR_RDFILE; + return(NULL); } } @@ -2157,7 +2172,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { progresult = XMLLINT_ERR_MEM; if (f != stdin) fclose(f); - return; + return(NULL); } htmlCtxtUseOptions(ctxt, options); while ((res = fread(chars, 1, pushsize, f)) > 0) { @@ -2168,23 +2183,26 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { htmlFreeParserCtxt(ctxt); if (f != stdin) fclose(f); + + return(doc); } #endif /* LIBXML_PUSH_ENABLED */ + #ifdef HAVE_MMAP - else if ((html) && (memory)) { + if ((html) && (memory)) { int fd; struct stat info; const char *base; if (stat(filename, &info) < 0) - return; + return(NULL); if ((fd = open(filename, O_RDONLY)) < 0) - return; + return(NULL); base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ; if (base == (void *) MAP_FAILED) { close(fd); - fprintf(stderr, "mmap failure for file %s\n", filename); + fprintf(ERR_STREAM, "mmap failure for file %s\n", filename); progresult = XMLLINT_ERR_RDFILE; - return; + return(NULL); } doc = htmlReadMemory((char *) base, info.st_size, filename, @@ -2192,191 +2210,168 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { munmap((char *) base, info.st_size); close(fd); + + return(doc); } #endif - else if (html) { - doc = htmlReadFile(filename, NULL, options); + + if (html) { + if (strcmp(filename, "-") == 0) + doc = htmlReadFd(STDIN_FILENO, "-", NULL, options); + else + doc = htmlReadFile(filename, NULL, options); + + return(doc); } #endif /* LIBXML_HTML_ENABLED */ - else { -#ifdef LIBXML_PUSH_ENABLED - /* - * build an XML tree from a string; - */ - if (push) { - FILE *f; - int ret; - int res, size = 1024; - char chars[1024]; - xmlParserCtxtPtr ctxt; - /* '-' Usually means stdin - */ - if ((filename[0] == '-') && (filename[1] == 0)) { - f = stdin; - } else { - f = fopen(filename, "rb"); - if (f == NULL) { - fprintf(stderr, "Can't open %s\n", filename); - progresult = XMLLINT_ERR_UNCLASS; - return; - } - } +#ifdef LIBXML_PUSH_ENABLED + if (push) { + FILE *f; + int res; + char chars[4096]; - res = fread(chars, 1, 4, f); - ctxt = xmlCreatePushParserCtxt(NULL, NULL, - chars, res, filename); - if (ctxt == NULL) { - progresult = XMLLINT_ERR_MEM; - if (f != stdin) - fclose(f); - return; - } - xmlCtxtUseOptions(ctxt, options); - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - while ((res = fread(chars, 1, size, f)) > 0) { - xmlParseChunk(ctxt, chars, res, 0); - } - xmlParseChunk(ctxt, chars, 0, 1); - doc = ctxt->myDoc; - ret = ctxt->wellFormed; - xmlFreeParserCtxt(ctxt); - if ((!ret) && (!recovery)) { - xmlFreeDoc(doc); - doc = NULL; + if ((filename[0] == '-') && (filename[1] == 0)) { + f = stdin; + } else { + f = fopen(filename, "rb"); + if (f == NULL) { + fprintf(ERR_STREAM, "Can't open %s\n", filename); + progresult = XMLLINT_ERR_RDFILE; + return(NULL); } + } + + res = fread(chars, 1, 4, f); + ctxt = xmlCreatePushParserCtxt(NULL, NULL, + chars, res, filename); + if (ctxt == NULL) { + progresult = XMLLINT_ERR_MEM; if (f != stdin) fclose(f); - } else -#endif /* LIBXML_PUSH_ENABLED */ - if (testIO) { - if ((filename[0] == '-') && (filename[1] == 0)) { - doc = xmlReadFd(0, NULL, NULL, options); - } else { - FILE *f; + return(NULL); + } + xmlCtxtUseOptions(ctxt, options); - f = fopen(filename, "rb"); - if (f != NULL) { - if (rectxt == NULL) - doc = xmlReadIO(myRead, myClose, f, filename, NULL, - options); - else - doc = xmlCtxtReadIO(rectxt, myRead, myClose, f, - filename, NULL, options); - } else - doc = NULL; - } - } else if (htmlout) { - xmlParserCtxtPtr ctxt; - - if (rectxt == NULL) { - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - progresult = XMLLINT_ERR_MEM; - return; - } - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - } else { - ctxt = rectxt; - } + if (maxAmpl > 0) + xmlCtxtSetMaxAmplification(ctxt, maxAmpl); + if (htmlout) { ctxt->sax->error = xmlHTMLError; ctxt->sax->warning = xmlHTMLWarning; ctxt->vctxt.error = xmlHTMLValidityError; ctxt->vctxt.warning = xmlHTMLValidityWarning; + } - doc = xmlCtxtReadFile(ctxt, filename, NULL, options); + while ((res = fread(chars, 1, pushsize, f)) > 0) { + xmlParseChunk(ctxt, chars, res, 0); + } + xmlParseChunk(ctxt, chars, 0, 1); - if (rectxt == NULL) - xmlFreeParserCtxt(ctxt); -#ifdef HAVE_MMAP - } else if (memory) { - int fd; - struct stat info; - const char *base; - if (stat(filename, &info) < 0) - return; - if ((fd = open(filename, O_RDONLY)) < 0) - return; - base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ; - if (base == (void *) MAP_FAILED) { - close(fd); - fprintf(stderr, "mmap failure for file %s\n", filename); - progresult = XMLLINT_ERR_RDFILE; - return; - } + doc = ctxt->myDoc; + if (f != stdin) + fclose(f); + } else +#endif /* LIBXML_PUSH_ENABLED */ + { + if (rectxt == NULL) { + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) { + progresult = XMLLINT_ERR_MEM; + return(NULL); + } + } else { + ctxt = rectxt; + } - if (rectxt == NULL) { - xmlParserCtxtPtr ctxt; + if (maxAmpl > 0) + xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - fprintf(stderr, "out of memory\n"); - progresult = XMLLINT_ERR_MEM; - return; - } - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - doc = xmlCtxtReadMemory(ctxt, base, info.st_size, - filename, NULL, options); - xmlFreeParserCtxt(ctxt); - } else { - doc = xmlCtxtReadMemory(rectxt, (char *) base, info.st_size, - filename, NULL, options); - } + if (htmlout) { + ctxt->sax->error = xmlHTMLError; + ctxt->sax->warning = xmlHTMLWarning; + ctxt->vctxt.error = xmlHTMLValidityError; + ctxt->vctxt.warning = xmlHTMLValidityWarning; + } - munmap((char *) base, info.st_size); - close(fd); -#endif -#ifdef LIBXML_VALID_ENABLED - } else if (valid) { - xmlParserCtxtPtr ctxt = NULL; - - if (rectxt == NULL) { - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - progresult = XMLLINT_ERR_MEM; - return; - } + if (testIO) { + FILE *f; + + if ((filename[0] == '-') && (filename[1] == 0)) { + f = stdin; } else { - ctxt = rectxt; + f = fopen(filename, "rb"); + if (f == NULL) { + fprintf(ERR_STREAM, "Can't open %s\n", filename); + progresult = XMLLINT_ERR_RDFILE; + goto error; + } } - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); - doc = xmlCtxtReadFile(ctxt, filename, NULL, options); - - if (ctxt->valid == 0) + doc = xmlCtxtReadIO(ctxt, myRead, myClose, f, filename, NULL, + options); +#ifdef HAVE_MMAP + } else if (memory) { + int fd; + struct stat info; + const char *base; + + if (stat(filename, &info) < 0) + goto error; + if ((fd = open(filename, O_RDONLY)) < 0) + goto error; + base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ; + if (base == (void *) MAP_FAILED) { + close(fd); + fprintf(ERR_STREAM, "mmap failure for file %s\n", filename); progresult = XMLLINT_ERR_RDFILE; - if (rectxt == NULL) - xmlFreeParserCtxt(ctxt); -#endif /* LIBXML_VALID_ENABLED */ - } else { - if (rectxt != NULL) { - doc = xmlCtxtReadFile(rectxt, filename, NULL, options); - } else { - xmlParserCtxtPtr ctxt; + goto error; + } - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - fprintf(stderr, "out of memory\n"); - progresult = XMLLINT_ERR_MEM; - return; - } - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); + doc = xmlCtxtReadMemory(ctxt, base, info.st_size, filename, NULL, + options); + + munmap((char *) base, info.st_size); + close(fd); +#endif + } else { + if (strcmp(filename, "-") == 0) + doc = xmlCtxtReadFd(ctxt, STDIN_FILENO, "-", NULL, options); + else doc = xmlCtxtReadFile(ctxt, filename, NULL, options); - xmlFreeParserCtxt(ctxt); - } - } + } } - /* - * If we don't have a document we might as well give up. Do we - * want an error message here? */ if (doc == NULL) { - progresult = XMLLINT_ERR_UNCLASS; + if (ctxt->errNo == XML_ERR_NO_MEMORY) + progresult = XMLLINT_ERR_MEM; + else + progresult = XMLLINT_ERR_RDFILE; + } else { +#ifdef LIBXML_VALID_ENABLED + if ((options & XML_PARSE_DTDVALID) && (ctxt->valid == 0)) + progresult = XMLLINT_ERR_VALID; +#endif /* LIBXML_VALID_ENABLED */ + } + +error: + if (ctxt != rectxt) + xmlFreeParserCtxt(ctxt); + + return(doc); +} + +static void +parseAndPrintFile(const char *filename, xmlParserCtxtPtr rectxt) { + xmlDocPtr doc; + + if ((timing) && (!repeat)) + startTimer(); + + doc = parseFile(filename, rectxt); + if (doc == NULL) { + if (progresult == XMLLINT_RETURN_OK) + progresult = XMLLINT_ERR_UNCLASS; return; } @@ -2384,17 +2379,13 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { endTimer("Parsing"); } - /* - * Remove DOCTYPE nodes - */ if (dropdtd) { xmlDtdPtr dtd; dtd = xmlGetIntSubset(doc); if (dtd != NULL) { xmlUnlinkNode((xmlNodePtr)dtd); - doc->intSubset = NULL; - xmlFreeDtd(dtd); + doc->intSubset = dtd; } } @@ -2434,6 +2425,8 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { * test intermediate copy if needed. */ if (copy) { + xmlDocPtr tmp; + tmp = doc; if (timing) { startTimer(); @@ -2458,25 +2451,32 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { #endif /* LIBXML_TREE_ENABLED */ #ifdef LIBXML_VALID_ENABLED - if ((insert) && (!html)) { + if ((insert) +#ifdef LIBXML_HTML_ENABLED + && (!html) +#endif + ) { const xmlChar* list[256]; int nb, i; xmlNodePtr node; if (doc->children != NULL) { node = doc->children; - while ((node != NULL) && (node->last == NULL)) node = node->next; + while ((node != NULL) && + ((node->type != XML_ELEMENT_NODE) || + (node->last == NULL))) + node = node->next; if (node != NULL) { nb = xmlValidGetValidElements(node->last, NULL, list, 256); if (nb < 0) { - fprintf(stderr, "could not get valid list of elements\n"); + fprintf(ERR_STREAM, "could not get valid list of elements\n"); } else if (nb == 0) { - fprintf(stderr, "No element can be inserted under root\n"); + fprintf(ERR_STREAM, "No element can be inserted under root\n"); } else { - fprintf(stderr, "%d element types can be inserted under root:\n", + fprintf(ERR_STREAM, "%d element types can be inserted under root:\n", nb); for (i = 0;i < nb;i++) { - fprintf(stderr, "%s\n", (char *) list[i]); + fprintf(ERR_STREAM, "%s\n", (char *) list[i]); } } } @@ -2490,7 +2490,8 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { #endif /* LIBXML_READER_ENABLED */ #ifdef LIBXML_OUTPUT_ENABLED if (noout == 0) { - int ret; + if (compress) + xmlSetDocCompressMode(doc, 9); /* * print it. @@ -2531,7 +2532,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { if (output != NULL) fclose(out); } else { - fprintf(stderr, "failed to open %s\n", output); + fprintf(ERR_STREAM, "failed to open %s\n", output); progresult = XMLLINT_ERR_OUT; } } @@ -2548,11 +2549,11 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result); if (size >= 0) { if (write(1, result, size) == -1) { - fprintf(stderr, "Can't write data\n"); + fprintf(ERR_STREAM, "Can't write data\n"); } xmlFree(result); } else { - fprintf(stderr, "Failed to canonicalize\n"); + fprintf(ERR_STREAM, "Failed to canonicalize\n"); progresult = XMLLINT_ERR_OUT; } } else if (canonical_11) { @@ -2562,11 +2563,11 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result); if (size >= 0) { if (write(1, result, size) == -1) { - fprintf(stderr, "Can't write data\n"); + fprintf(ERR_STREAM, "Can't write data\n"); } xmlFree(result); } else { - fprintf(stderr, "Failed to canonicalize\n"); + fprintf(ERR_STREAM, "Failed to canonicalize\n"); progresult = XMLLINT_ERR_OUT; } } else @@ -2577,11 +2578,11 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result); if (size >= 0) { if (write(1, result, size) == -1) { - fprintf(stderr, "Can't write data\n"); + fprintf(ERR_STREAM, "Can't write data\n"); } xmlFree(result); } else { - fprintf(stderr, "Failed to canonicalize\n"); + fprintf(ERR_STREAM, "Failed to canonicalize\n"); progresult = XMLLINT_ERR_OUT; } } else @@ -2604,11 +2605,11 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { xmlDocDumpMemory(doc, &result, &len); } if (result == NULL) { - fprintf(stderr, "Failed to save\n"); + fprintf(ERR_STREAM, "Failed to save\n"); progresult = XMLLINT_ERR_OUT; } else { if (write(1, result, len) == -1) { - fprintf(stderr, "Can't write data\n"); + fprintf(ERR_STREAM, "Can't write data\n"); } xmlFree(result); } @@ -2617,46 +2618,6 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { #endif /* HAVE_MMAP */ if (compress) { xmlSaveFile(output ? output : "-", doc); - } else if (oldout) { - if (encoding != NULL) { - if (format == 1) { - ret = xmlSaveFormatFileEnc(output ? output : "-", doc, - encoding, 1); - } - else { - ret = xmlSaveFileEnc(output ? output : "-", doc, - encoding); - } - if (ret < 0) { - fprintf(stderr, "failed save to %s\n", - output ? output : "-"); - progresult = XMLLINT_ERR_OUT; - } - } else if (format == 1) { - ret = xmlSaveFormatFile(output ? output : "-", doc, 1); - if (ret < 0) { - fprintf(stderr, "failed save to %s\n", - output ? output : "-"); - progresult = XMLLINT_ERR_OUT; - } - } else { - FILE *out; - if (output == NULL) - out = stdout; - else { - out = fopen(output,"wb"); - } - if (out != NULL) { - if (xmlDocDump(out, doc) < 0) - progresult = XMLLINT_ERR_OUT; - - if (output != NULL) - fclose(out); - } else { - fprintf(stderr, "failed to open %s\n", output); - progresult = XMLLINT_ERR_OUT; - } - } } else { xmlSaveCtxtPtr ctxt; int saveOpts = 0; @@ -2666,7 +2627,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { else if (format == 2) saveOpts |= XML_SAVE_WSNONSIG; -#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED) +#if defined(LIBXML_HTML_ENABLED) if (xmlout) saveOpts |= XML_SAVE_AS_XML; #endif @@ -2678,7 +2639,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { if (ctxt != NULL) { if (xmlSaveDoc(ctxt, doc) < 0) { - fprintf(stderr, "failed save to %s\n", + fprintf(ERR_STREAM, "failed save to %s\n", output ? output : "-"); progresult = XMLLINT_ERR_OUT; } @@ -2704,7 +2665,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { if (output != NULL) fclose(out); } else { - fprintf(stderr, "failed to open %s\n", output); + fprintf(ERR_STREAM, "failed to open %s\n", output); progresult = XMLLINT_ERR_OUT; } } @@ -2731,35 +2692,33 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { } if (dtd == NULL) { if (dtdvalid != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Could not parse DTD %s\n", dtdvalid); else - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Could not parse DTD %s\n", dtdvalidfpi); progresult = XMLLINT_ERR_DTD; } else { xmlValidCtxtPtr cvp; if ((cvp = xmlNewValidCtxt()) == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Couldn't allocate validation context\n"); progresult = XMLLINT_ERR_MEM; xmlFreeDtd(dtd); return; } - cvp->error = xmlGenericError; - cvp->warning = xmlGenericError; if ((timing) && (!repeat)) { startTimer(); } if (!xmlValidateDtd(cvp, doc, dtd)) { if (dtdvalid != NULL) - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Document %s does not validate against %s\n", filename, dtdvalid); else - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Document %s does not validate against %s\n", filename, dtdvalidfpi); progresult = XMLLINT_ERR_VALID; @@ -2774,7 +2733,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { xmlValidCtxtPtr cvp; if ((cvp = xmlNewValidCtxt()) == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Couldn't allocate validation context\n"); progresult = XMLLINT_ERR_MEM; xmlFreeDoc(doc); @@ -2784,10 +2743,8 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { if ((timing) && (!repeat)) { startTimer(); } - cvp->error = xmlGenericError; - cvp->warning = xmlGenericError; if (!xmlValidateDocument(cvp, doc)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Document %s does not validate\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -2819,20 +2776,16 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { xmlFreeDoc(doc); return; } -#if 0 - xmlSchematronSetValidErrors(ctxt, xmlGenericError, xmlGenericError, - NULL); -#endif ret = xmlSchematronValidateDoc(ctxt, doc); if (ret == 0) { if (!quiet) { - fprintf(stderr, "%s validates\n", filename); + fprintf(ERR_STREAM, "%s validates\n", filename); } } else if (ret > 0) { - fprintf(stderr, "%s fails to validate\n", filename); + fprintf(ERR_STREAM, "%s fails to validate\n", filename); progresult = XMLLINT_ERR_VALID; } else { - fprintf(stderr, "%s validation generated an internal error\n", + fprintf(ERR_STREAM, "%s validation generated an internal error\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -2857,17 +2810,16 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { xmlFreeDoc(doc); return; } - xmlRelaxNGSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL); ret = xmlRelaxNGValidateDoc(ctxt, doc); if (ret == 0) { if (!quiet) { - fprintf(stderr, "%s validates\n", filename); + fprintf(ERR_STREAM, "%s validates\n", filename); } } else if (ret > 0) { - fprintf(stderr, "%s fails to validate\n", filename); + fprintf(ERR_STREAM, "%s fails to validate\n", filename); progresult = XMLLINT_ERR_VALID; } else { - fprintf(stderr, "%s validation generated an internal error\n", + fprintf(ERR_STREAM, "%s validation generated an internal error\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -2889,17 +2841,16 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { xmlFreeDoc(doc); return; } - xmlSchemaSetValidErrors(ctxt, xmlGenericError, xmlGenericError, NULL); ret = xmlSchemaValidateDoc(ctxt, doc); if (ret == 0) { if (!quiet) { - fprintf(stderr, "%s validates\n", filename); + fprintf(ERR_STREAM, "%s validates\n", filename); } } else if (ret > 0) { - fprintf(stderr, "%s fails to validate\n", filename); + fprintf(ERR_STREAM, "%s fails to validate\n", filename); progresult = XMLLINT_ERR_VALID; } else { - fprintf(stderr, "%s validation generated an internal error\n", + fprintf(ERR_STREAM, "%s validation generated an internal error\n", filename); progresult = XMLLINT_ERR_VALID; } @@ -2911,10 +2862,12 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { #endif #ifdef LIBXML_DEBUG_ENABLED -#if defined(LIBXML_HTML_ENABLED) || defined(LIBXML_VALID_ENABLED) - if ((debugent) && (!html)) - xmlDebugDumpEntities(stderr, doc); + if ((debugent) +#if defined(LIBXML_HTML_ENABLED) + && (!html) #endif + ) + xmlDebugDumpEntities(ERR_STREAM, doc); #endif /* @@ -2936,42 +2889,40 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { ************************************************************************/ static void showVersion(const char *name) { - fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion); - fprintf(stderr, " compiled with: "); - if (xmlHasFeature(XML_WITH_THREAD)) fprintf(stderr, "Threads "); - if (xmlHasFeature(XML_WITH_TREE)) fprintf(stderr, "Tree "); - if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(stderr, "Output "); - if (xmlHasFeature(XML_WITH_PUSH)) fprintf(stderr, "Push "); - if (xmlHasFeature(XML_WITH_READER)) fprintf(stderr, "Reader "); - if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(stderr, "Patterns "); - if (xmlHasFeature(XML_WITH_WRITER)) fprintf(stderr, "Writer "); - if (xmlHasFeature(XML_WITH_SAX1)) fprintf(stderr, "SAXv1 "); - if (xmlHasFeature(XML_WITH_FTP)) fprintf(stderr, "FTP "); - if (xmlHasFeature(XML_WITH_HTTP)) fprintf(stderr, "HTTP "); - if (xmlHasFeature(XML_WITH_VALID)) fprintf(stderr, "DTDValid "); - if (xmlHasFeature(XML_WITH_HTML)) fprintf(stderr, "HTML "); - if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(stderr, "Legacy "); - if (xmlHasFeature(XML_WITH_C14N)) fprintf(stderr, "C14N "); - if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(stderr, "Catalog "); - if (xmlHasFeature(XML_WITH_XPATH)) fprintf(stderr, "XPath "); - if (xmlHasFeature(XML_WITH_XPTR)) fprintf(stderr, "XPointer "); - if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(stderr, "XInclude "); - if (xmlHasFeature(XML_WITH_ICONV)) fprintf(stderr, "Iconv "); - if (xmlHasFeature(XML_WITH_ICU)) fprintf(stderr, "ICU "); - if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(stderr, "ISO8859X "); - if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(stderr, "Unicode "); - if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(stderr, "Regexps "); - if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(stderr, "Automata "); - if (xmlHasFeature(XML_WITH_EXPR)) fprintf(stderr, "Expr "); - if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(stderr, "Schemas "); - if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(stderr, "Schematron "); - if (xmlHasFeature(XML_WITH_MODULES)) fprintf(stderr, "Modules "); - if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(stderr, "Debug "); - if (xmlHasFeature(XML_WITH_DEBUG_MEM)) fprintf(stderr, "MemDebug "); - if (xmlHasFeature(XML_WITH_DEBUG_RUN)) fprintf(stderr, "RunDebug "); - if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(stderr, "Zlib "); - if (xmlHasFeature(XML_WITH_LZMA)) fprintf(stderr, "Lzma "); - fprintf(stderr, "\n"); + fprintf(ERR_STREAM, "%s: using libxml version %s\n", name, xmlParserVersion); + fprintf(ERR_STREAM, " compiled with: "); + if (xmlHasFeature(XML_WITH_THREAD)) fprintf(ERR_STREAM, "Threads "); + if (xmlHasFeature(XML_WITH_TREE)) fprintf(ERR_STREAM, "Tree "); + if (xmlHasFeature(XML_WITH_OUTPUT)) fprintf(ERR_STREAM, "Output "); + if (xmlHasFeature(XML_WITH_PUSH)) fprintf(ERR_STREAM, "Push "); + if (xmlHasFeature(XML_WITH_READER)) fprintf(ERR_STREAM, "Reader "); + if (xmlHasFeature(XML_WITH_PATTERN)) fprintf(ERR_STREAM, "Patterns "); + if (xmlHasFeature(XML_WITH_WRITER)) fprintf(ERR_STREAM, "Writer "); + if (xmlHasFeature(XML_WITH_SAX1)) fprintf(ERR_STREAM, "SAXv1 "); + if (xmlHasFeature(XML_WITH_FTP)) fprintf(ERR_STREAM, "FTP "); + if (xmlHasFeature(XML_WITH_HTTP)) fprintf(ERR_STREAM, "HTTP "); + if (xmlHasFeature(XML_WITH_VALID)) fprintf(ERR_STREAM, "DTDValid "); + if (xmlHasFeature(XML_WITH_HTML)) fprintf(ERR_STREAM, "HTML "); + if (xmlHasFeature(XML_WITH_LEGACY)) fprintf(ERR_STREAM, "Legacy "); + if (xmlHasFeature(XML_WITH_C14N)) fprintf(ERR_STREAM, "C14N "); + if (xmlHasFeature(XML_WITH_CATALOG)) fprintf(ERR_STREAM, "Catalog "); + if (xmlHasFeature(XML_WITH_XPATH)) fprintf(ERR_STREAM, "XPath "); + if (xmlHasFeature(XML_WITH_XPTR)) fprintf(ERR_STREAM, "XPointer "); + if (xmlHasFeature(XML_WITH_XINCLUDE)) fprintf(ERR_STREAM, "XInclude "); + if (xmlHasFeature(XML_WITH_ICONV)) fprintf(ERR_STREAM, "Iconv "); + if (xmlHasFeature(XML_WITH_ICU)) fprintf(ERR_STREAM, "ICU "); + if (xmlHasFeature(XML_WITH_ISO8859X)) fprintf(ERR_STREAM, "ISO8859X "); + if (xmlHasFeature(XML_WITH_UNICODE)) fprintf(ERR_STREAM, "Unicode "); + if (xmlHasFeature(XML_WITH_REGEXP)) fprintf(ERR_STREAM, "Regexps "); + if (xmlHasFeature(XML_WITH_AUTOMATA)) fprintf(ERR_STREAM, "Automata "); + if (xmlHasFeature(XML_WITH_EXPR)) fprintf(ERR_STREAM, "Expr "); + if (xmlHasFeature(XML_WITH_SCHEMAS)) fprintf(ERR_STREAM, "Schemas "); + if (xmlHasFeature(XML_WITH_SCHEMATRON)) fprintf(ERR_STREAM, "Schematron "); + if (xmlHasFeature(XML_WITH_MODULES)) fprintf(ERR_STREAM, "Modules "); + if (xmlHasFeature(XML_WITH_DEBUG)) fprintf(ERR_STREAM, "Debug "); + if (xmlHasFeature(XML_WITH_ZLIB)) fprintf(ERR_STREAM, "Zlib "); + if (xmlHasFeature(XML_WITH_LZMA)) fprintf(ERR_STREAM, "Lzma "); + fprintf(ERR_STREAM, "\n"); } static void usage(FILE *f, const char *name) { @@ -3010,17 +2961,12 @@ static void usage(FILE *f, const char *name) { fprintf(f, "\t--postvalid : do a posteriori validation, i.e after parsing\n"); fprintf(f, "\t--dtdvalid URL : do a posteriori validation against a given DTD\n"); fprintf(f, "\t--dtdvalidfpi FPI : same but name the DTD with a Public Identifier\n"); + fprintf(f, "\t--insert : ad-hoc test for valid insertions\n"); #endif /* LIBXML_VALID_ENABLED */ fprintf(f, "\t--quiet : be quiet when succeeded\n"); fprintf(f, "\t--timing : print some timings\n"); - fprintf(f, "\t--output file or -o file: save to a given file\n"); fprintf(f, "\t--repeat : repeat 100 times, for timing or profiling\n"); - fprintf(f, "\t--insert : ad-hoc test for valid insertions\n"); -#ifdef LIBXML_OUTPUT_ENABLED -#ifdef LIBXML_ZLIB_ENABLED - fprintf(f, "\t--compress : turn on gzip compression of output\n"); -#endif -#endif /* LIBXML_OUTPUT_ENABLED */ + fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n"); #ifdef LIBXML_HTML_ENABLED fprintf(f, "\t--html : use the HTML parser\n"); fprintf(f, "\t--xmlout : force to use the XML serializer when using --html\n"); @@ -3038,13 +2984,16 @@ static void usage(FILE *f, const char *name) { fprintf(f, "\t--noblanks : drop (ignorable?) blanks spaces\n"); fprintf(f, "\t--nocdata : replace cdata section with text nodes\n"); #ifdef LIBXML_OUTPUT_ENABLED + fprintf(f, "\t--output file or -o file: save to a given file\n"); fprintf(f, "\t--format : reformat/reindent the output\n"); fprintf(f, "\t--encode encoding : output in the given encoding\n"); - fprintf(f, "\t--dropdtd : remove the DOCTYPE of the input docs\n"); fprintf(f, "\t--pretty STYLE : pretty-print in a particular style\n"); fprintf(f, "\t 0 Do not pretty print\n"); fprintf(f, "\t 1 Format the XML content, as --format\n"); fprintf(f, "\t 2 Add whitespace inside tags, preserving content\n"); +#ifdef LIBXML_ZLIB_ENABLED + fprintf(f, "\t--compress : turn on gzip compression of output\n"); +#endif #endif /* LIBXML_OUTPUT_ENABLED */ fprintf(f, "\t--c14n : save in W3C canonical format v1.0 (with comments)\n"); fprintf(f, "\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n"); @@ -3074,7 +3023,6 @@ static void usage(FILE *f, const char *name) { fprintf(f, "\t--pattern pattern_value : test the pattern support\n"); #endif #endif /* LIBXML_READER_ENABLED */ - fprintf(f, "\t--chkregister : verify the node registration code\n"); #ifdef LIBXML_SCHEMAS_ENABLED fprintf(f, "\t--relaxng schema : do RelaxNG validation against the schema\n"); fprintf(f, "\t--schema schema : do validation against the WXS schema\n"); @@ -3095,25 +3043,6 @@ static void usage(FILE *f, const char *name) { fprintf(f, "\nLibxml project home page: https://gitlab.gnome.org/GNOME/libxml2\n"); } -static void registerNode(xmlNodePtr node) -{ - node->_private = malloc(sizeof(long)); - if (node->_private == NULL) { - fprintf(stderr, "Out of memory in xmllint:registerNode()\n"); - exit(XMLLINT_ERR_MEM); - } - *(long*)node->_private = (long) 0x81726354; - nbregister++; -} - -static void deregisterNode(xmlNodePtr node) -{ - assert(node->_private != NULL); - assert(*(long*)node->_private == (long) 0x81726354); - free(node->_private); - nbregister--; -} - static unsigned long parseInteger(const char *ctxt, const char *str, unsigned long min, unsigned long max) { @@ -3123,43 +3052,175 @@ parseInteger(const char *ctxt, const char *str, errno = 0; val = strtoul(str, &strEnd, 10); if (errno == EINVAL || *strEnd != 0) { - fprintf(stderr, "%s: invalid integer: %s\n", ctxt, str); + fprintf(ERR_STREAM, "%s: invalid integer: %s\n", ctxt, str); exit(XMLLINT_ERR_UNCLASS); } if (errno != 0 || val < min || val > max) { - fprintf(stderr, "%s: integer out of range: %s\n", ctxt, str); + fprintf(ERR_STREAM, "%s: integer out of range: %s\n", ctxt, str); exit(XMLLINT_ERR_UNCLASS); } return(val); } -int -main(int argc, char **argv) { +static int +skipArgs(const char *arg) { + if ((!strcmp(arg, "-path")) || + (!strcmp(arg, "--path")) || + (!strcmp(arg, "-maxmem")) || + (!strcmp(arg, "--maxmem")) || +#ifdef LIBXML_OUTPUT_ENABLED + (!strcmp(arg, "-o")) || + (!strcmp(arg, "-output")) || + (!strcmp(arg, "--output")) || + (!strcmp(arg, "-encode")) || + (!strcmp(arg, "--encode")) || + (!strcmp(arg, "-pretty")) || + (!strcmp(arg, "--pretty")) || +#endif +#ifdef LIBXML_VALID_ENABLED + (!strcmp(arg, "-dtdvalid")) || + (!strcmp(arg, "--dtdvalid")) || + (!strcmp(arg, "-dtdvalidfpi")) || + (!strcmp(arg, "--dtdvalidfpi")) || +#endif +#ifdef LIBXML_SCHEMAS_ENABLED + (!strcmp(arg, "-relaxng")) || + (!strcmp(arg, "--relaxng")) || + (!strcmp(arg, "-schema")) || + (!strcmp(arg, "--schema")) || +#endif +#ifdef LIBXML_SCHEMATRON_ENABLED + (!strcmp(arg, "-schematron")) || + (!strcmp(arg, "--schematron")) || +#endif +#if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED) + (!strcmp(arg, "-pattern")) || + (!strcmp(arg, "--pattern")) || +#endif +#ifdef LIBXML_XPATH_ENABLED + (!strcmp(arg, "-xpath")) || + (!strcmp(arg, "--xpath")) || +#endif + (!strcmp(arg, "-max-ampl")) || + (!strcmp(arg, "--max-ampl")) + ) { + return(1); + } + + return(0); +} + +static int +xmllintMain(int argc, const char **argv) { int i, acount; int files = 0; int version = 0; + int nowrap = 0; + int sax = 0; +#ifdef LIBXML_READER_ENABLED + int stream = 0; +#endif +#ifdef LIBXML_CATALOG_ENABLED + int catalogs = 0; + int nocatalogs = 0; +#endif + +#ifdef XMLLINT_FUZZ +#ifdef LIBXML_DEBUG_ENABLED + shell = 0; + debugent = 0; +#endif + debug = 0; + maxmem = 0; +#ifdef LIBXML_TREE_ENABLED + copy = 0; +#endif /* LIBXML_TREE_ENABLED */ + noout = 0; +#ifdef LIBXML_OUTPUT_ENABLED + format = 0; + output = NULL; + compress = 0; +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_VALID_ENABLED + postvalid = 0; + dtdvalid = NULL; + dtdvalidfpi = NULL; + insert = 0; +#endif +#ifdef LIBXML_SCHEMAS_ENABLED + relaxng = NULL; + relaxngschemas = NULL; + schema = NULL; + wxschemas = NULL; +#endif +#ifdef LIBXML_SCHEMATRON_ENABLED + schematron = NULL; + wxschematron = NULL; +#endif + repeat = 0; +#if defined(LIBXML_HTML_ENABLED) + html = 0; + xmlout = 0; +#endif + htmlout = 0; +#ifdef LIBXML_PUSH_ENABLED + push = 0; + pushsize = 4096; +#endif /* LIBXML_PUSH_ENABLED */ +#ifdef HAVE_MMAP + memory = 0; +#endif + testIO = 0; + encoding = NULL; +#ifdef LIBXML_XINCLUDE_ENABLED + xinclude = 0; +#endif + progresult = XMLLINT_RETURN_OK; + quiet = 0; + timing = 0; + generate = 0; + dropdtd = 0; +#ifdef LIBXML_C14N_ENABLED + canonical = 0; + canonical_11 = 0; + exc_canonical = 0; +#endif +#ifdef LIBXML_READER_ENABLED + walker = 0; +#ifdef LIBXML_PATTERN_ENABLED + pattern = NULL; + patternc = NULL; + patstream = NULL; +#endif +#endif /* LIBXML_READER_ENABLED */ +#ifdef LIBXML_XPATH_ENABLED + xpathquery = NULL; +#endif + options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES; + maxAmpl = 0; + defaultEntityLoader = NULL; +#endif /* XMLLINT_FUZZ */ if (argc <= 1) { - usage(stderr, argv[0]); + usage(ERR_STREAM, argv[0]); return(XMLLINT_ERR_UNCLASS); } /* xmlMemSetup must be called before initializing the parser. */ for (i = 1; i < argc ; i++) { - if (argv[i][0] != '-') - continue; - if ((!strcmp(argv[i], "-maxmem")) || (!strcmp(argv[i], "--maxmem"))) { i++; if (i >= argc) { - fprintf(stderr, "maxmem: missing integer value\n"); + fprintf(ERR_STREAM, "maxmem: missing integer value\n"); return(XMLLINT_ERR_UNCLASS); } errno = 0; maxmem = parseInteger("maxmem", argv[i], 0, INT_MAX); - } + } else if (argv[i][0] == '-') { + i += skipArgs(argv[i]); + } } if (maxmem != 0) xmlMemSetup(myFreeFunc, myMallocFunc, myReallocFunc, myStrdupFunc); @@ -3187,17 +3248,15 @@ main(int argc, char **argv) { #endif /* LIBXML_TREE_ENABLED */ if ((!strcmp(argv[i], "-recover")) || (!strcmp(argv[i], "--recover"))) { - recovery++; options |= XML_PARSE_RECOVER; } else if ((!strcmp(argv[i], "-huge")) || (!strcmp(argv[i], "--huge"))) { options |= XML_PARSE_HUGE; } else if ((!strcmp(argv[i], "-noent")) || (!strcmp(argv[i], "--noent"))) { - noent = 1; + options |= XML_PARSE_NOENT; } else if ((!strcmp(argv[i], "-noenc")) || (!strcmp(argv[i], "--noenc"))) { - noenc++; options |= XML_PARSE_IGNORE_ENC; } else if ((!strcmp(argv[i], "-nsclean")) || (!strcmp(argv[i], "--nsclean"))) { @@ -3215,14 +3274,6 @@ main(int argc, char **argv) { } else if ((!strcmp(argv[i], "-noout")) || (!strcmp(argv[i], "--noout"))) noout++; -#ifdef LIBXML_OUTPUT_ENABLED - else if ((!strcmp(argv[i], "-o")) || - (!strcmp(argv[i], "-output")) || - (!strcmp(argv[i], "--output"))) { - i++; - output = argv[i]; - } -#endif /* LIBXML_OUTPUT_ENABLED */ else if ((!strcmp(argv[i], "-htmlout")) || (!strcmp(argv[i], "--htmlout"))) htmlout++; @@ -3239,50 +3290,42 @@ main(int argc, char **argv) { xmlout++; } else if ((!strcmp(argv[i], "-nodefdtd")) || (!strcmp(argv[i], "--nodefdtd"))) { - nodefdtd++; options |= HTML_PARSE_NODEFDTD; } #endif /* LIBXML_HTML_ENABLED */ else if ((!strcmp(argv[i], "-loaddtd")) || (!strcmp(argv[i], "--loaddtd"))) { - loaddtd++; options |= XML_PARSE_DTDLOAD; } else if ((!strcmp(argv[i], "-dtdattr")) || (!strcmp(argv[i], "--dtdattr"))) { - loaddtd++; - dtdattrs++; options |= XML_PARSE_DTDATTR; } #ifdef LIBXML_VALID_ENABLED else if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid"))) { - valid++; options |= XML_PARSE_DTDVALID; } else if ((!strcmp(argv[i], "-postvalid")) || (!strcmp(argv[i], "--postvalid"))) { postvalid++; - loaddtd++; options |= XML_PARSE_DTDLOAD; } else if ((!strcmp(argv[i], "-dtdvalid")) || (!strcmp(argv[i], "--dtdvalid"))) { i++; dtdvalid = argv[i]; - loaddtd++; options |= XML_PARSE_DTDLOAD; } else if ((!strcmp(argv[i], "-dtdvalidfpi")) || (!strcmp(argv[i], "--dtdvalidfpi"))) { i++; dtdvalidfpi = argv[i]; - loaddtd++; options |= XML_PARSE_DTDLOAD; } + else if ((!strcmp(argv[i], "-insert")) || + (!strcmp(argv[i], "--insert"))) + insert++; #endif /* LIBXML_VALID_ENABLED */ else if ((!strcmp(argv[i], "-dropdtd")) || (!strcmp(argv[i], "--dropdtd"))) dropdtd++; - else if ((!strcmp(argv[i], "-insert")) || - (!strcmp(argv[i], "--insert"))) - insert++; else if ((!strcmp(argv[i], "-quiet")) || (!strcmp(argv[i], "--quiet"))) quiet++; @@ -3336,15 +3379,6 @@ main(int argc, char **argv) { options |= XML_PARSE_NOBASEFIX; } #endif -#ifdef LIBXML_OUTPUT_ENABLED -#ifdef LIBXML_ZLIB_ENABLED - else if ((!strcmp(argv[i], "-compress")) || - (!strcmp(argv[i], "--compress"))) { - compress++; - xmlSetCompressMode(9); - } -#endif -#endif /* LIBXML_OUTPUT_ENABLED */ else if ((!strcmp(argv[i], "-nowarning")) || (!strcmp(argv[i], "--nowarning"))) { options |= XML_PARSE_NOWARNING; @@ -3387,37 +3421,48 @@ main(int argc, char **argv) { nocatalogs++; } #endif - else if ((!strcmp(argv[i], "-encode")) || - (!strcmp(argv[i], "--encode"))) { - i++; - encoding = argv[i]; - /* - * OK it's for testing purposes - */ - xmlAddEncodingAlias("UTF-8", "DVEnc"); - } else if ((!strcmp(argv[i], "-noblanks")) || (!strcmp(argv[i], "--noblanks"))) { - noblanks = 1; + options |= XML_PARSE_NOBLANKS; } else if ((!strcmp(argv[i], "-maxmem")) || (!strcmp(argv[i], "--maxmem"))) { i++; } +#ifdef LIBXML_OUTPUT_ENABLED + else if ((!strcmp(argv[i], "-o")) || + (!strcmp(argv[i], "-output")) || + (!strcmp(argv[i], "--output"))) { + i++; + output = argv[i]; + } else if ((!strcmp(argv[i], "-format")) || (!strcmp(argv[i], "--format"))) { -#ifdef LIBXML_OUTPUT_ENABLED format = 1; -#endif /* LIBXML_OUTPUT_ENABLED */ + options |= XML_PARSE_NOBLANKS; } + else if ((!strcmp(argv[i], "-encode")) || + (!strcmp(argv[i], "--encode"))) { + i++; + encoding = argv[i]; + /* + * OK it's for testing purposes + */ + xmlAddEncodingAlias("UTF-8", "DVEnc"); + } else if ((!strcmp(argv[i], "-pretty")) || (!strcmp(argv[i], "--pretty"))) { i++; -#ifdef LIBXML_OUTPUT_ENABLED if (argv[i] != NULL) format = atoi(argv[i]); -#endif /* LIBXML_OUTPUT_ENABLED */ } +#ifdef LIBXML_ZLIB_ENABLED + else if ((!strcmp(argv[i], "-compress")) || + (!strcmp(argv[i], "--compress"))) { + compress++; + } +#endif +#endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_READER_ENABLED else if ((!strcmp(argv[i], "-stream")) || (!strcmp(argv[i], "--stream"))) { @@ -3427,51 +3472,52 @@ main(int argc, char **argv) { (!strcmp(argv[i], "--walker"))) { walker++; noout++; + } #ifdef LIBXML_PATTERN_ENABLED - } else if ((!strcmp(argv[i], "-pattern")) || + else if ((!strcmp(argv[i], "-pattern")) || (!strcmp(argv[i], "--pattern"))) { i++; pattern = argv[i]; -#endif } +#endif #endif /* LIBXML_READER_ENABLED */ #ifdef LIBXML_SAX1_ENABLED else if ((!strcmp(argv[i], "-sax1")) || (!strcmp(argv[i], "--sax1"))) { - sax1++; options |= XML_PARSE_SAX1; } #endif /* LIBXML_SAX1_ENABLED */ else if ((!strcmp(argv[i], "-sax")) || (!strcmp(argv[i], "--sax"))) { sax++; - } - else if ((!strcmp(argv[i], "-chkregister")) || - (!strcmp(argv[i], "--chkregister"))) { - chkregister++; + } #ifdef LIBXML_SCHEMAS_ENABLED - } else if ((!strcmp(argv[i], "-relaxng")) || + else if ((!strcmp(argv[i], "-relaxng")) || (!strcmp(argv[i], "--relaxng"))) { i++; relaxng = argv[i]; - noent = 1; + options |= XML_PARSE_NOENT; } else if ((!strcmp(argv[i], "-schema")) || (!strcmp(argv[i], "--schema"))) { i++; schema = argv[i]; - noent = 1; + options |= XML_PARSE_NOENT; + } #endif #ifdef LIBXML_SCHEMATRON_ENABLED - } else if ((!strcmp(argv[i], "-schematron")) || + else if ((!strcmp(argv[i], "-schematron")) || (!strcmp(argv[i], "--schematron"))) { i++; schematron = argv[i]; - noent = 1; + options |= XML_PARSE_NOENT; + } #endif - } else if ((!strcmp(argv[i], "-nonet")) || + else if ((!strcmp(argv[i], "-nonet")) || (!strcmp(argv[i], "--nonet"))) { options |= XML_PARSE_NONET; +#ifndef XMLLINT_FUZZ xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader); +#endif } else if ((!strcmp(argv[i], "-nocompact")) || (!strcmp(argv[i], "--nocompact"))) { options &= ~XML_PARSE_COMPACT; @@ -3482,28 +3528,29 @@ main(int argc, char **argv) { (!strcmp(argv[i], "--path"))) { i++; parsePath(BAD_CAST argv[i]); + } #ifdef LIBXML_XPATH_ENABLED - } else if ((!strcmp(argv[i], "-xpath")) || + else if ((!strcmp(argv[i], "-xpath")) || (!strcmp(argv[i], "--xpath"))) { i++; noout++; xpathquery = argv[i]; + } #endif - } else if ((!strcmp(argv[i], "-oldxml10")) || + else if ((!strcmp(argv[i], "-oldxml10")) || (!strcmp(argv[i], "--oldxml10"))) { - oldxml10++; options |= XML_PARSE_OLD10; } else if ((!strcmp(argv[i], "-max-ampl")) || (!strcmp(argv[i], "--max-ampl"))) { i++; if (i >= argc) { - fprintf(stderr, "max-ampl: missing integer value\n"); + fprintf(ERR_STREAM, "max-ampl: missing integer value\n"); return(XMLLINT_ERR_UNCLASS); } maxAmpl = parseInteger("max-ampl", argv[i], 1, UINT_MAX); } else { - fprintf(stderr, "Unknown option %s\n", argv[i]); - usage(stderr, argv[0]); + fprintf(ERR_STREAM, "Unknown option %s\n", argv[i]); + usage(ERR_STREAM, argv[0]); return(XMLLINT_ERR_UNCLASS); } } @@ -3517,17 +3564,12 @@ main(int argc, char **argv) { if (catal != NULL) { xmlLoadCatalogs(catal); } else { - fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n"); + fprintf(ERR_STREAM, "Variable $SGML_CATALOG_FILES not set\n"); } } } #endif - if (chkregister) { - xmlRegisterNodeDefault(registerNode); - xmlDeregisterNodeDefault(deregisterNode); - } - #ifdef LIBXML_OUTPUT_ENABLED { const char *indent = getenv("XMLLINT_INDENT"); @@ -3540,19 +3582,15 @@ main(int argc, char **argv) { defaultEntityLoader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader(xmllintExternalEntityLoader); - if (noent != 0) - options |= XML_PARSE_NOENT; - if ((noblanks != 0) || (format == 1)) - options |= XML_PARSE_NOBLANKS; if ((htmlout) && (!nowrap)) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "\n"); - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "%s output\n", argv[0]); - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "

%s output

\n", argv[0]); } @@ -3575,13 +3613,9 @@ main(int argc, char **argv) { progresult = XMLLINT_ERR_MEM; goto error; } -#if 0 - xmlSchematronSetParserErrors(ctxt, xmlGenericError, xmlGenericError, - NULL); -#endif wxschematron = xmlSchematronParse(ctxt); if (wxschematron == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Schematron schema %s failed to compile\n", schematron); progresult = XMLLINT_ERR_SCHEMACOMP; schematron = NULL; @@ -3610,11 +3644,9 @@ main(int argc, char **argv) { progresult = XMLLINT_ERR_MEM; goto error; } - xmlRelaxNGSetParserErrors(ctxt, xmlGenericError, xmlGenericError, - NULL); relaxngschemas = xmlRelaxNGParse(ctxt); if (relaxngschemas == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Relax-NG schema %s failed to compile\n", relaxng); progresult = XMLLINT_ERR_SCHEMACOMP; relaxng = NULL; @@ -3638,10 +3670,9 @@ main(int argc, char **argv) { progresult = XMLLINT_ERR_MEM; goto error; } - xmlSchemaSetParserErrors(ctxt, xmlGenericError, xmlGenericError, NULL); wxschemas = xmlSchemaParse(ctxt); if (wxschemas == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "WXS schema %s failed to compile\n", schema); progresult = XMLLINT_ERR_SCHEMACOMP; schema = NULL; @@ -3656,7 +3687,7 @@ main(int argc, char **argv) { if ((pattern != NULL) && (walker == 0)) { patternc = xmlPatterncompile((const xmlChar *) pattern, NULL, 0, NULL); if (patternc == NULL) { - xmlGenericError(xmlGenericErrorContext, + fprintf(ERR_STREAM, "Pattern %s failed to compile\n", pattern); progresult = XMLLINT_ERR_SCHEMAPAT; pattern = NULL; @@ -3664,141 +3695,64 @@ main(int argc, char **argv) { } #endif /* LIBXML_READER_ENABLED && LIBXML_PATTERN_ENABLED */ for (i = 1; i < argc ; i++) { - if ((!strcmp(argv[i], "-encode")) || - (!strcmp(argv[i], "--encode"))) { - i++; - continue; - } else if ((!strcmp(argv[i], "-o")) || - (!strcmp(argv[i], "-output")) || - (!strcmp(argv[i], "--output"))) { - i++; - continue; - } -#ifdef LIBXML_VALID_ENABLED - if ((!strcmp(argv[i], "-dtdvalid")) || - (!strcmp(argv[i], "--dtdvalid"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-path")) || - (!strcmp(argv[i], "--path"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-dtdvalidfpi")) || - (!strcmp(argv[i], "--dtdvalidfpi"))) { - i++; - continue; - } -#endif /* LIBXML_VALID_ENABLED */ - if ((!strcmp(argv[i], "-relaxng")) || - (!strcmp(argv[i], "--relaxng"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-maxmem")) || - (!strcmp(argv[i], "--maxmem"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-pretty")) || - (!strcmp(argv[i], "--pretty"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-schema")) || - (!strcmp(argv[i], "--schema"))) { - i++; - continue; - } - if ((!strcmp(argv[i], "-schematron")) || - (!strcmp(argv[i], "--schematron"))) { - i++; - continue; - } -#if defined(LIBXML_READER_ENABLED) && defined(LIBXML_PATTERN_ENABLED) - if ((!strcmp(argv[i], "-pattern")) || - (!strcmp(argv[i], "--pattern"))) { - i++; - continue; - } -#endif -#ifdef LIBXML_XPATH_ENABLED - if ((!strcmp(argv[i], "-xpath")) || - (!strcmp(argv[i], "--xpath"))) { - i++; - continue; - } -#endif - if ((!strcmp(argv[i], "-max-ampl")) || - (!strcmp(argv[i], "--max-ampl"))) { - i++; - continue; + if ((argv[i][0] == '-') && (strcmp(argv[i], "-") != 0)) { + i += skipArgs(argv[i]); + continue; } if ((timing) && (repeat)) startTimer(); - /* Remember file names. "-" means stdin. */ - if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { - if (repeat) { - xmlParserCtxtPtr ctxt; - - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - progresult = XMLLINT_ERR_MEM; - goto error; - } - if (maxAmpl > 0) - xmlCtxtSetMaxAmplification(ctxt, maxAmpl); + if (repeat) { + xmlParserCtxtPtr ctxt; - for (acount = 0;acount < repeat;acount++) { + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) { + progresult = XMLLINT_ERR_MEM; + goto error; + } + if (maxAmpl > 0) + xmlCtxtSetMaxAmplification(ctxt, maxAmpl); + + for (acount = 0;acount < repeat;acount++) { #ifdef LIBXML_READER_ENABLED - if (stream != 0) { - streamFile(argv[i]); - } else { + if (stream != 0) { + streamFile(argv[i]); + } else { #endif /* LIBXML_READER_ENABLED */ - if (sax) { - testSAX(argv[i]); - } else { - parseAndPrintFile(argv[i], ctxt); - } + if (sax) { + testSAX(argv[i]); + } else { + parseAndPrintFile(argv[i], ctxt); + } #ifdef LIBXML_READER_ENABLED - } + } #endif /* LIBXML_READER_ENABLED */ - } - - xmlFreeParserCtxt(ctxt); - } else { - nbregister = 0; + } + xmlFreeParserCtxt(ctxt); + } else { #ifdef LIBXML_READER_ENABLED - if (stream != 0) - streamFile(argv[i]); - else + if (stream != 0) + streamFile(argv[i]); + else #endif /* LIBXML_READER_ENABLED */ - if (sax) { - testSAX(argv[i]); - } else { - parseAndPrintFile(argv[i], NULL); - } - - if ((chkregister) && (nbregister != 0)) { - fprintf(stderr, "Registration count off: %d\n", nbregister); - progresult = XMLLINT_ERR_RDREGIS; - } - } - files ++; - if ((timing) && (repeat)) { - endTimer("%d iterations", repeat); - } - } + if (sax) { + testSAX(argv[i]); + } else { + parseAndPrintFile(argv[i], NULL); + } + } + files ++; + if ((timing) && (repeat)) { + endTimer("%d iterations", repeat); + } } if (generate) parseAndPrintFile(NULL, NULL); if ((htmlout) && (!nowrap)) { - xmlGenericError(xmlGenericErrorContext, "\n"); + fprintf(ERR_STREAM, "\n"); } if ((files == 0) && (!generate) && (version == 0)) { - usage(stderr, argv[0]); + usage(ERR_STREAM, argv[0]); progresult = XMLLINT_ERR_UNCLASS; } #ifdef LIBXML_SCHEMATRON_ENABLED @@ -3820,8 +3774,17 @@ main(int argc, char **argv) { goto error; error: + if (defaultEntityLoader != NULL) + xmlSetExternalEntityLoader(defaultEntityLoader); xmlCleanupParser(); return(progresult); } +#ifndef XMLLINT_FUZZ +int +main(int argc, char **argv) { + return(xmllintMain(argc, (const char **) argv)); +} +#endif + diff --git a/xmlmemory.c b/xmlmemory.c index 1e999b1..f0628e2 100644 --- a/xmlmemory.c +++ b/xmlmemory.c @@ -12,18 +12,6 @@ #include #include -/** - * MEM_LIST: - * - * keep track of all allocated blocks for error reporting - * Always build the memory list ! - */ -#ifdef DEBUG_MEMORY_LOCATION -#ifndef MEM_LIST -#define MEM_LIST /* keep a list of all the allocated memory blocks */ -#endif -#endif - #include #include #include @@ -34,62 +22,31 @@ static unsigned long debugMemSize = 0; static unsigned long debugMemBlocks = 0; -static unsigned long debugMaxMemSize = 0; static xmlMutex xmlMemMutex; -void xmlMallocBreakpoint(void); - /************************************************************************ * * * Macros, variables and associated types * * * ************************************************************************/ -#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED) -#ifdef xmlMalloc -#undef xmlMalloc -#endif -#ifdef xmlRealloc -#undef xmlRealloc -#endif -#ifdef xmlMemStrdup -#undef xmlMemStrdup -#endif -#endif - /* * Each of the blocks allocated begin with a header containing information */ #define MEMTAG 0x5aa5U -#define MALLOC_TYPE 1 -#define REALLOC_TYPE 2 -#define STRDUP_TYPE 3 -#define MALLOC_ATOMIC_TYPE 4 -#define REALLOC_ATOMIC_TYPE 5 - typedef struct memnod { unsigned int mh_tag; - unsigned int mh_type; - unsigned long mh_number; size_t mh_size; -#ifdef MEM_LIST - struct memnod *mh_next; - struct memnod *mh_prev; -#endif - const char *mh_file; - unsigned int mh_line; -} MEMHDR; - +} MEMHDR; #ifdef SUN4 #define ALIGN_SIZE 16 #else #define ALIGN_SIZE sizeof(double) #endif -#define HDR_SIZE sizeof(MEMHDR) -#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \ +#define RESERVE_SIZE (((sizeof(MEMHDR) + ALIGN_SIZE - 1) \ / ALIGN_SIZE ) * ALIGN_SIZE) #define MAX_SIZE_T ((size_t)-1) @@ -97,102 +54,21 @@ typedef struct memnod { #define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE)) #define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE)) - -static unsigned int block=0; -static unsigned int xmlMemStopAtBlock = 0; -static void *xmlMemTraceBlockAt = NULL; -#ifdef MEM_LIST -static MEMHDR *memlist = NULL; -#endif - -static void debugmem_tag_error(void *addr); -#ifdef MEM_LIST -static void debugmem_list_add(MEMHDR *); -static void debugmem_list_delete(MEMHDR *); -#endif -#define Mem_Tag_Err(a) debugmem_tag_error(a); - -#ifndef TEST_POINT -#define TEST_POINT -#endif - -/** - * xmlMallocBreakpoint: - * - * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block - * number reaches the specified value this function is called. One need to add a breakpoint - * to it to get the context in which the given block is allocated. - */ - -void -xmlMallocBreakpoint(void) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock); -} - /** * xmlMallocLoc: * @size: an int specifying the size in byte to allocate. * @file: the file name or NULL * @line: the line number * - * a malloc() equivalent, with logging of the allocation info. + * DEPRECATED: don't use * * Returns a pointer to the allocated area or NULL in case of lack of memory. */ - void * -xmlMallocLoc(size_t size, const char * file, int line) +xmlMallocLoc(size_t size, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED) { - MEMHDR *p; - void *ret; - - xmlInitParser(); - - TEST_POINT - - if (size > (MAX_SIZE_T - RESERVE_SIZE)) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocLoc : Unsigned overflow\n"); - return(NULL); - } - - p = (MEMHDR *) malloc(RESERVE_SIZE+size); - - if (!p) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocLoc : Out of free space\n"); - return(NULL); - } - p->mh_tag = MEMTAG; - p->mh_size = size; - p->mh_type = MALLOC_TYPE; - p->mh_file = file; - p->mh_line = line; - xmlMutexLock(&xmlMemMutex); - p->mh_number = ++block; - debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif - xmlMutexUnlock(&xmlMemMutex); - - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - ret = HDR_2_CLIENT(p); - - if (xmlMemTraceBlockAt == ret) { - xmlGenericError(xmlGenericErrorContext, - "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, - (long unsigned)size); - xmlMallocBreakpoint(); - } - - TEST_POINT - - return(ret); + return(xmlMemMalloc(size)); } /** @@ -201,174 +77,119 @@ xmlMallocLoc(size_t size, const char * file, int line) * @file: the file name or NULL * @line: the line number * - * a malloc() equivalent, with logging of the allocation info. + * DEPRECATED: don't use * * Returns a pointer to the allocated area or NULL in case of lack of memory. */ +void * +xmlMallocAtomicLoc(size_t size, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED) +{ + return(xmlMemMalloc(size)); +} +/** + * xmlMemMalloc: + * @size: an int specifying the size in byte to allocate. + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ void * -xmlMallocAtomicLoc(size_t size, const char * file, int line) +xmlMemMalloc(size_t size) { MEMHDR *p; - void *ret; xmlInitParser(); - TEST_POINT - if (size > (MAX_SIZE_T - RESERVE_SIZE)) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocAtomicLoc : Unsigned overflow\n"); - return(NULL); + fprintf(stderr, "xmlMemMalloc: Unsigned overflow\n"); + return(NULL); } - p = (MEMHDR *) malloc(RESERVE_SIZE+size); - + p = (MEMHDR *) malloc(RESERVE_SIZE + size); if (!p) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocAtomicLoc : Out of free space\n"); - return(NULL); + fprintf(stderr, "xmlMemMalloc: Out of memory\n"); + return(NULL); } p->mh_tag = MEMTAG; p->mh_size = size; - p->mh_type = MALLOC_ATOMIC_TYPE; - p->mh_file = file; - p->mh_line = line; + xmlMutexLock(&xmlMemMutex); - p->mh_number = ++block; debugMemSize += size; debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif xmlMutexUnlock(&xmlMemMutex); - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - ret = HDR_2_CLIENT(p); - - if (xmlMemTraceBlockAt == ret) { - xmlGenericError(xmlGenericErrorContext, - "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, - (long unsigned)size); - xmlMallocBreakpoint(); - } - - TEST_POINT - - return(ret); + return(HDR_2_CLIENT(p)); } + /** - * xmlMemMalloc: + * xmlReallocLoc: + * @ptr: the initial memory block pointer * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number * - * a malloc() equivalent, with logging of the allocation info. + * DEPRECATED: don't use * * Returns a pointer to the allocated area or NULL in case of lack of memory. */ - void * -xmlMemMalloc(size_t size) +xmlReallocLoc(void *ptr, size_t size, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED) { - return(xmlMallocLoc(size, "none", 0)); + return(xmlMemRealloc(ptr, size)); } /** - * xmlReallocLoc: + * xmlMemRealloc: * @ptr: the initial memory block pointer * @size: an int specifying the size in byte to allocate. - * @file: the file name or NULL - * @line: the line number * * a realloc() equivalent, with logging of the allocation info. * * Returns a pointer to the allocated area or NULL in case of lack of memory. */ - void * -xmlReallocLoc(void *ptr,size_t size, const char * file, int line) -{ +xmlMemRealloc(void *ptr, size_t size) { MEMHDR *p, *tmp; - unsigned long number; + size_t oldSize; if (ptr == NULL) - return(xmlMallocLoc(size, file, line)); + return(xmlMemMalloc(size)); xmlInitParser(); - TEST_POINT + + if (size > (MAX_SIZE_T - RESERVE_SIZE)) { + fprintf(stderr, "xmlMemRealloc: Unsigned overflow\n"); + return(NULL); + } p = CLIENT_2_HDR(ptr); - number = p->mh_number; - if (xmlMemStopAtBlock == number) xmlMallocBreakpoint(); if (p->mh_tag != MEMTAG) { - Mem_Tag_Err(p); - goto error; + fprintf(stderr, "xmlMemRealloc: Tag error\n"); + return(NULL); } + oldSize = p->mh_size; p->mh_tag = ~MEMTAG; - xmlMutexLock(&xmlMemMutex); - debugMemSize -= p->mh_size; - debugMemBlocks--; -#ifdef MEM_LIST - debugmem_list_delete(p); -#endif - xmlMutexUnlock(&xmlMemMutex); - if (size > (MAX_SIZE_T - RESERVE_SIZE)) { - xmlGenericError(xmlGenericErrorContext, - "xmlReallocLoc : Unsigned overflow\n"); - return(NULL); - } - - tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size); + tmp = (MEMHDR *) realloc(p, RESERVE_SIZE + size); if (!tmp) { - free(p); - goto error; + p->mh_tag = MEMTAG; + fprintf(stderr, "xmlMemRealloc: Out of memory\n"); + return(NULL); } p = tmp; - if (xmlMemTraceBlockAt == ptr) { - xmlGenericError(xmlGenericErrorContext, - "%p : Realloced(%lu -> %lu) Ok\n", - xmlMemTraceBlockAt, (long unsigned)p->mh_size, - (long unsigned)size); - xmlMallocBreakpoint(); - } p->mh_tag = MEMTAG; - p->mh_number = number; - p->mh_type = REALLOC_TYPE; p->mh_size = size; - p->mh_file = file; - p->mh_line = line; + xmlMutexLock(&xmlMemMutex); + debugMemSize -= oldSize; debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif xmlMutexUnlock(&xmlMemMutex); - TEST_POINT - return(HDR_2_CLIENT(p)); - -error: - return(NULL); -} - -/** - * xmlMemRealloc: - * @ptr: the initial memory block pointer - * @size: an int specifying the size in byte to allocate. - * - * a realloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlMemRealloc(void *ptr,size_t size) { - return(xmlReallocLoc(ptr, size, "none", 0)); } /** @@ -381,53 +202,30 @@ void xmlMemFree(void *ptr) { MEMHDR *p; - char *target; if (ptr == NULL) - return; + return; if (ptr == (void *) -1) { - xmlGenericError(xmlGenericErrorContext, - "trying to free pointer from freed area\n"); - goto error; - } - - if (xmlMemTraceBlockAt == ptr) { - xmlGenericError(xmlGenericErrorContext, - "%p : Freed()\n", xmlMemTraceBlockAt); - xmlMallocBreakpoint(); + fprintf(stderr, "xmlMemFree: Pointer from freed area\n"); + return; } - TEST_POINT - - target = (char *) ptr; - p = CLIENT_2_HDR(ptr); if (p->mh_tag != MEMTAG) { - Mem_Tag_Err(p); - goto error; + fprintf(stderr, "xmlMemFree: Tag error\n"); + return; } - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); p->mh_tag = ~MEMTAG; - memset(target, -1, p->mh_size); + memset(ptr, -1, p->mh_size); + xmlMutexLock(&xmlMemMutex); debugMemSize -= p->mh_size; debugMemBlocks--; -#ifdef MEM_LIST - debugmem_list_delete(p); -#endif xmlMutexUnlock(&xmlMemMutex); free(p); - TEST_POINT - - return; - -error: - xmlGenericError(xmlGenericErrorContext, - "xmlMemFree(%p) error\n", ptr); - xmlMallocBreakpoint(); return; } @@ -437,78 +235,56 @@ xmlMemFree(void *ptr) * @file: the file name or NULL * @line: the line number * - * a strdup() equivalent, with logging of the allocation info. + * DEPRECATED: don't use * * Returns a pointer to the new string or NULL if allocation error occurred. */ - char * -xmlMemStrdupLoc(const char *str, const char *file, int line) +xmlMemStrdupLoc(const char *str, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED) { + return(xmlMemoryStrdup(str)); +} + +/** + * xmlMemoryStrdup: + * @str: the initial string pointer + * + * a strdup() equivalent, with logging of the allocation info. + * + * Returns a pointer to the new string or NULL if allocation error occurred. + */ +char * +xmlMemoryStrdup(const char *str) { char *s; size_t size = strlen(str) + 1; MEMHDR *p; xmlInitParser(); - TEST_POINT if (size > (MAX_SIZE_T - RESERVE_SIZE)) { - xmlGenericError(xmlGenericErrorContext, - "xmlMemStrdupLoc : Unsigned overflow\n"); - return(NULL); + fprintf(stderr, "xmlMemoryStrdup: Unsigned overflow\n"); + return(NULL); } - p = (MEMHDR *) malloc(RESERVE_SIZE+size); + p = (MEMHDR *) malloc(RESERVE_SIZE + size); if (!p) { - goto error; + fprintf(stderr, "xmlMemoryStrdup: Out of memory\n"); + return(NULL); } p->mh_tag = MEMTAG; p->mh_size = size; - p->mh_type = STRDUP_TYPE; - p->mh_file = file; - p->mh_line = line; + xmlMutexLock(&xmlMemMutex); - p->mh_number = ++block; debugMemSize += size; debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif xmlMutexUnlock(&xmlMemMutex); s = (char *) HDR_2_CLIENT(p); - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - strcpy(s,str); - - TEST_POINT - - if (xmlMemTraceBlockAt == s) { - xmlGenericError(xmlGenericErrorContext, - "%p : Strdup() Ok\n", xmlMemTraceBlockAt); - xmlMallocBreakpoint(); - } + memcpy(s, str, size); return(s); - -error: - return(NULL); -} - -/** - * xmlMemoryStrdup: - * @str: the initial string pointer - * - * a strdup() equivalent, with logging of the allocation info. - * - * Returns a pointer to the new string or NULL if allocation error occurred. - */ - -char * -xmlMemoryStrdup(const char *str) { - return(xmlMemStrdupLoc(str, "none", 0)); } /** @@ -565,256 +341,47 @@ xmlMemBlocks(void) { /** * xmlMemDisplayLast: - * @fp: a FILE descriptor used as the output file, if NULL, the result is - * written to the file .memorylist + * @fp: a FILE descriptor * @nbBytes: the amount of memory to dump * - * the last nbBytes of memory allocated and not freed, useful for dumping - * the memory left allocated between two places at runtime. + * DEPRECATED: This feature was removed. */ - void -xmlMemDisplayLast(FILE *fp, long nbBytes) +xmlMemDisplayLast(FILE *fp ATTRIBUTE_UNUSED, long nbBytes ATTRIBUTE_UNUSED) { -#ifdef MEM_LIST - MEMHDR *p; - unsigned idx; - int nb = 0; -#endif - FILE *old_fp = fp; - - if (nbBytes <= 0) - return; - - if (fp == NULL) { - fp = fopen(".memorylist", "w"); - if (fp == NULL) - return; - } - -#ifdef MEM_LIST - fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n", - nbBytes, debugMemSize, debugMaxMemSize); - fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); - idx = 0; - xmlMutexLock(&xmlMemMutex); - p = memlist; - while ((p) && (nbBytes > 0)) { - fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, - (unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default: - fprintf(fp,"Unknown memory block, may be corrupted"); - xmlMutexUnlock(&xmlMemMutex); - if (old_fp == NULL) - fclose(fp); - return; - } - if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - nb++; - - fprintf(fp,"\n"); - nbBytes -= (unsigned long)p->mh_size; - p = p->mh_next; - } - xmlMutexUnlock(&xmlMemMutex); -#else - fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); -#endif - if (old_fp == NULL) - fclose(fp); } /** * xmlMemDisplay: - * @fp: a FILE descriptor used as the output file, if NULL, the result is - * written to the file .memorylist + * @fp: a FILE descriptor * - * show in-extenso the memory blocks allocated + * DEPRECATED: This feature was removed. */ - void -xmlMemDisplay(FILE *fp) +xmlMemDisplay(FILE *fp ATTRIBUTE_UNUSED) { -#ifdef MEM_LIST - MEMHDR *p; - unsigned idx; - int nb = 0; - time_t currentTime; - char buf[500]; - struct tm * tstruct; -#endif - FILE *old_fp = fp; - - if (fp == NULL) { - fp = fopen(".memorylist", "w"); - if (fp == NULL) - return; - } - -#ifdef MEM_LIST - currentTime = time(NULL); - tstruct = localtime(¤tTime); - strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct); - fprintf(fp," %s\n\n", buf); - - - fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", - debugMemSize, debugMaxMemSize); - fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); - idx = 0; - xmlMutexLock(&xmlMemMutex); - p = memlist; - while (p) { - fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, - (unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default: - fprintf(fp,"Unknown memory block, may be corrupted"); - xmlMutexUnlock(&xmlMemMutex); - if (old_fp == NULL) - fclose(fp); - return; - } - if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - nb++; - - fprintf(fp,"\n"); - p = p->mh_next; - } - xmlMutexUnlock(&xmlMemMutex); -#else - fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); -#endif - if (old_fp == NULL) - fclose(fp); } -#ifdef MEM_LIST - -static void debugmem_list_add(MEMHDR *p) -{ - p->mh_next = memlist; - p->mh_prev = NULL; - if (memlist) memlist->mh_prev = p; - memlist = p; -} - -static void debugmem_list_delete(MEMHDR *p) -{ - if (p->mh_next) - p->mh_next->mh_prev = p->mh_prev; - if (p->mh_prev) - p->mh_prev->mh_next = p->mh_next; - else memlist = p->mh_next; -} - -#endif - -/* - * debugmem_tag_error: - * - * internal error function. - */ - -static void debugmem_tag_error(void *p) -{ - xmlGenericError(xmlGenericErrorContext, - "Memory tag error occurs :%p \n\t bye\n", p); -#ifdef MEM_LIST - if (stderr) - xmlMemDisplay(stderr); -#endif -} - -#ifdef MEM_LIST -static FILE *xmlMemoryDumpFile = NULL; -#endif - /** * xmlMemShow: - * @fp: a FILE descriptor used as the output file + * @fp: a FILE descriptor * @nr: number of entries to dump * - * show a show display of the memory allocated, and dump - * the @nr last allocated areas which were not freed + * DEPRECATED: This feature was removed. */ - void -xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED) +xmlMemShow(FILE *fp ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { -#ifdef MEM_LIST - MEMHDR *p; -#endif - - if (fp != NULL) - fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", - debugMemSize, debugMaxMemSize); -#ifdef MEM_LIST - xmlMutexLock(&xmlMemMutex); - if (nr > 0) { - fprintf(fp,"NUMBER SIZE TYPE WHERE\n"); - p = memlist; - while ((p) && nr > 0) { - fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default:fprintf(fp," ??? in ");break; - } - if (p->mh_file != NULL) - fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - fprintf(fp,"\n"); - nr--; - p = p->mh_next; - } - } - xmlMutexUnlock(&xmlMemMutex); -#endif /* MEM_LIST */ } /** * xmlMemoryDump: * - * Dump in-extenso the memory blocks allocated to the file .memorylist + * DEPRECATED: This feature was removed. */ - void xmlMemoryDump(void) { -#ifdef MEM_LIST - FILE *dump; - - if (debugMaxMemSize == 0) - return; - dump = fopen(".memdump", "w"); - if (dump == NULL) - xmlMemoryDumpFile = stderr; - else xmlMemoryDumpFile = dump; - - xmlMemDisplay(xmlMemoryDumpFile); - - if (dump != NULL) fclose(dump); -#endif /* MEM_LIST */ } @@ -828,6 +395,8 @@ xmlMemoryDump(void) * xmlInitMemory: * * DEPRECATED: Alias for xmlInitParser. + * + * Returns 0. */ int xmlInitMemory(void) { @@ -839,23 +408,10 @@ xmlInitMemory(void) { * xmlInitMemoryInternal: * * Initialize the memory layer. - * - * Returns 0 on success */ void xmlInitMemoryInternal(void) { - char *breakpoint; - xmlInitMutex(&xmlMemMutex); - - breakpoint = getenv("XML_MEM_BREAKPOINT"); - if (breakpoint != NULL) { - sscanf(breakpoint, "%ud", &xmlMemStopAtBlock); - } - breakpoint = getenv("XML_MEM_TRACE"); - if (breakpoint != NULL) { - sscanf(breakpoint, "%p", &xmlMemTraceBlockAt); - } - + xmlInitMutex(&xmlMemMutex); } /** diff --git a/xmlmodule.c b/xmlmodule.c index d8bce32..dd2fd7a 100644 --- a/xmlmodule.c +++ b/xmlmodule.c @@ -41,27 +41,6 @@ static int xmlModulePlatformSymbol(void *handle, const char *name, void **result * * ************************************************************************/ -/** - * xmlModuleErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -xmlModuleErrMemory(xmlModulePtr module, const char *extra) -{ - const char *name = NULL; - - if (module != NULL) { - name = (const char *) module->name; - } - - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - name, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); -} - /** * xmlModuleOpen: * @name: the module name @@ -82,10 +61,8 @@ xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) xmlModulePtr module; module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule)); - if (module == NULL) { - xmlModuleErrMemory(NULL, "creating module"); + if (module == NULL) return (NULL); - } memset(module, 0, sizeof(xmlModule)); @@ -93,9 +70,6 @@ xmlModuleOpen(const char *name, int options ATTRIBUTE_UNUSED) if (module->handle == NULL) { xmlFree(module); - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, - name, NULL, 0, 0, "failed to open %s\n", name); return(NULL); } @@ -122,23 +96,13 @@ xmlModuleSymbol(xmlModulePtr module, const char *name, void **symbol) { int rc = -1; - if ((NULL == module) || (symbol == NULL) || (name == NULL)) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, - NULL, NULL, 0, 0, "null parameter\n"); + if ((NULL == module) || (symbol == NULL) || (name == NULL)) return rc; - } rc = xmlModulePlatformSymbol(module->handle, name, symbol); - if (rc == -1) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0, - name, NULL, 0, 0, - "failed to find symbol: %s\n", - (name == NULL ? "NULL" : name)); + if (rc == -1) return rc; - } return rc; } @@ -158,22 +122,13 @@ xmlModuleClose(xmlModulePtr module) { int rc; - if (NULL == module) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, - NULL, NULL, 0, 0, "null module pointer\n"); + if (NULL == module) return -1; - } rc = xmlModulePlatformClose(module->handle); - if (rc != 0) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, 0, - (const char *) module->name, NULL, 0, 0, - "failed to close: %s\n", module->name); + if (rc != 0) return -2; - } rc = xmlModuleFree(module); return (rc); @@ -192,12 +147,8 @@ xmlModuleClose(xmlModulePtr module) int xmlModuleFree(xmlModulePtr module) { - if (NULL == module) { - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE, - XML_MODULE_CLOSE, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "null module pointer\n"); + if (NULL == module) return -1; - } xmlFree(module->name); xmlFree(module); diff --git a/xmlreader.c b/xmlreader.c index 5fdeb2b..2de91bf 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -40,14 +40,13 @@ #endif #include "private/buf.h" -#include "private/parser.h" +#include "private/error.h" #include "private/tree.h" +#include "private/parser.h" #ifdef LIBXML_XINCLUDE_ENABLED #include "private/xinclude.h" #endif -#define MAX_ERR_MSG_SIZE 64000 - #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* Keeping free objects can hide memory errors. */ #define MAX_FREE_NODES 1 @@ -55,39 +54,14 @@ #define MAX_FREE_NODES 100 #endif -/* - * The following VA_COPY was coded following an example in - * the Samba project. It may not be sufficient for some - * esoteric implementations of va_list but (hopefully) will - * be sufficient for libxml2. - */ -#ifndef VA_COPY - #ifdef HAVE_VA_COPY - #define VA_COPY(dest, src) va_copy(dest, src) +#ifndef va_copy + #ifdef __va_copy + #define va_copy(dest, src) __va_copy(dest, src) #else - #ifdef HAVE___VA_COPY - #define VA_COPY(dest,src) __va_copy(dest, src) - #else - #ifndef VA_LIST_IS_ARRAY - #define VA_COPY(dest,src) (dest) = (src) - #else - #include - #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list)) - #endif - #endif + #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) #endif #endif -/** - * TODO: - * - * macro to flag unimplemented blocks - */ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - #define CHUNK_SIZE 512 /************************************************************************ * * @@ -188,22 +162,9 @@ struct _xmlTextReader { #define NODE_IS_PRESERVED 0x2 #define NODE_IS_SPRESERVED 0x4 -/** - * CONSTSTR: - * - * Macro used to return an interned string - */ -#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1) -#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str)) - static int xmlTextReaderReadTree(xmlTextReaderPtr reader); static int xmlTextReaderNextTree(xmlTextReaderPtr reader); -/************************************************************************ - * * - * Our own version of the freeing routines as we recycle nodes * - * * - ************************************************************************/ /** * DICT_FREE: * @str: a string @@ -219,6 +180,65 @@ static int xmlTextReaderNextTree(xmlTextReaderPtr reader); static void xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur); static void xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur); +static void +xmlTextReaderErrMemory(xmlTextReaderPtr reader) { + if (reader->ctxt != NULL) + xmlCtxtErrMemory(reader->ctxt); + else + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_PARSER, NULL); + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; +} + +static xmlChar * +readerStrdup(xmlTextReaderPtr reader, const xmlChar *string) { + xmlChar *copy; + + if (string == NULL) + return(NULL); + + copy = xmlStrdup(string); + if (copy == NULL) + xmlTextReaderErrMemory(reader); + + return(copy); +} + +static const xmlChar * +constString(xmlTextReaderPtr reader, const xmlChar *string) { + const xmlChar *dictString; + + if (string == NULL) + return(NULL); + + dictString = xmlDictLookup(reader->dict, string, -1); + if (dictString == NULL) + xmlTextReaderErrMemory(reader); + + return(dictString); +} + +static const xmlChar * +constQString(xmlTextReaderPtr reader, const xmlChar *prefix, + const xmlChar *name) { + const xmlChar *dictString; + + if (name == NULL) + return(NULL); + + dictString = xmlDictQLookup(reader->dict, prefix, name); + if (dictString == NULL) + xmlTextReaderErrMemory(reader); + + return(dictString); +} + +/************************************************************************ + * * + * Our own version of the freeing routines as we recycle nodes * + * * + ************************************************************************/ + /** * xmlTextReaderFreeProp: * @reader: the xmlTextReaderPtr used @@ -242,7 +262,19 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) { if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children); - DICT_FREE(cur->name); + if (cur->id != NULL) { + /* + * Operating in streaming mode, attr is gonna disappear + */ + cur->id->attr = NULL; + if (cur->id->name != NULL) + DICT_FREE(cur->id->name); + cur->id->name = cur->name; + cur->name = NULL; + } else { + DICT_FREE(cur->name); + } + if ((reader != NULL) && (reader->ctxt != NULL) && (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) { cur->next = reader->ctxt->freeAttrs; @@ -498,6 +530,34 @@ xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) { * * ************************************************************************/ +static void +xmlTextReaderStructuredRelay(void *userData, const xmlError *error) +{ + xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; + + if (reader->sErrorFunc != NULL) { + reader->sErrorFunc(reader->errorFuncArg, error); + } else if (reader->errorFunc != NULL) { + xmlParserSeverities severity; + + if ((error->domain == XML_FROM_VALID) || + (error->domain == XML_FROM_DTD)) { + if (error->level == XML_ERR_WARNING) + severity = XML_PARSER_SEVERITY_VALIDITY_WARNING; + else + severity = XML_PARSER_SEVERITY_VALIDITY_ERROR; + } else { + if (error->level == XML_ERR_WARNING) + severity = XML_PARSER_SEVERITY_WARNING; + else + severity = XML_PARSER_SEVERITY_ERROR; + } + + reader->errorFunc(reader->errorFuncArg, error->message, severity, + reader->ctxt); + } +} + /** * xmlTextReaderEntPush: * @reader: the xmlTextReaderPtr used @@ -517,7 +577,7 @@ xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value) tmp = (xmlNodePtr *) xmlRealloc(reader->entTab, newSize * sizeof(*tmp)); if (tmp == NULL) { - xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); + xmlTextReaderErrMemory(reader); return (-1); } reader->entTab = tmp; @@ -734,11 +794,10 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { break; } } else if (val < 0) { - xmlGenericError(xmlGenericErrorContext, - "xmlParserInputBufferRead failed\n"); - reader->mode = XML_TEXTREADER_MODE_EOF; - reader->state = oldstate; - return(val); + xmlCtxtErrIO(reader->ctxt, reader->input->error, NULL); + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; + return(-1); } } else @@ -820,8 +879,8 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { * * Push the current node for validation */ -static void -xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { +static int +xmlTextReaderValidatePush(xmlTextReaderPtr reader) { xmlNodePtr node = reader->node; #ifdef LIBXML_VALID_ENABLED @@ -831,17 +890,24 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, node->name); } else { - /* TODO use the BuildQName interface */ + xmlChar buf[50]; xmlChar *qname; - qname = xmlStrdup(node->ns->prefix); - qname = xmlStrcat(qname, BAD_CAST ":"); - qname = xmlStrcat(qname, node->name); + qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50); + if (qname == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); - if (qname != NULL) - xmlFree(qname); + if (qname != buf) + xmlFree(qname); } + /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; + return(-1); + }*/ } #endif /* LIBXML_VALID_ENABLED */ #ifdef LIBXML_SCHEMAS_ENABLED @@ -849,7 +915,7 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { (reader->rngValidCtxt != NULL)) { int ret; - if (reader->rngFullNode != NULL) return; + if (reader->rngFullNode != NULL) return(0); ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt, reader->ctxt->myDoc, node); @@ -871,6 +937,8 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) { reader->rngValidErrors++; } #endif + + return(0); } /** @@ -910,7 +978,7 @@ xmlTextReaderValidateCData(xmlTextReaderPtr reader, * * Pop the current node from validation */ -static void +static int xmlTextReaderValidatePop(xmlTextReaderPtr reader) { xmlNodePtr node = reader->node; @@ -921,17 +989,24 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) { reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, node->name); } else { - /* TODO use the BuildQName interface */ + xmlChar buf[50]; xmlChar *qname; - qname = xmlStrdup(node->ns->prefix); - qname = xmlStrcat(qname, BAD_CAST ":"); - qname = xmlStrcat(qname, node->name); + qname = xmlBuildQName(node->name, node->ns->prefix, buf, 50); + if (qname == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt, reader->ctxt->myDoc, node, qname); - if (qname != NULL) - xmlFree(qname); + if (qname != buf) + xmlFree(qname); } + /*if (reader->ctxt->errNo == XML_ERR_NO_MEMORY) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; + return(-1); + }*/ } #endif /* LIBXML_VALID_ENABLED */ #ifdef LIBXML_SCHEMAS_ENABLED @@ -942,7 +1017,7 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) { if (reader->rngFullNode != NULL) { if (node == reader->rngFullNode) reader->rngFullNode = NULL; - return; + return(0); } ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt, reader->ctxt->myDoc, @@ -951,6 +1026,8 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) { reader->rngValidErrors++; } #endif + + return(0); } /** @@ -961,7 +1038,7 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) { * entity substitution is not activated. As a result the parser interface * must walk through the entity and do the validation calls */ -static void +static int xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { xmlNodePtr oldnode = reader->node; xmlNodePtr node = reader->node; @@ -989,7 +1066,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { #ifdef LIBXML_REGEXP_ENABLED } else if (node->type == XML_ELEMENT_NODE) { reader->node = node; - xmlTextReaderValidatePush(reader); + if (xmlTextReaderValidatePush(reader) < 0) + return(-1); } else if ((node->type == XML_TEXT_NODE) || (node->type == XML_CDATA_SECTION_NODE)) { xmlTextReaderValidateCData(reader, node->content, @@ -1004,7 +1082,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { node = node->children; continue; } else if (node->type == XML_ELEMENT_NODE) { - xmlTextReaderValidatePop(reader); + if (xmlTextReaderValidatePop(reader) < 0) + return(-1); } skip_children: if (node->next != NULL) { @@ -1025,7 +1104,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { } } reader->node = node; - xmlTextReaderValidatePop(reader); + if (xmlTextReaderValidatePop(reader) < 0) + return(-1); } if ((node->type == XML_ENTITY_DECL) && (reader->ent != NULL) && (reader->ent->children == node)) { @@ -1040,6 +1120,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) { } while ((node != NULL) && (node != oldnode)); } while ((node != NULL) && (node != oldnode)); reader->node = oldnode; + + return(0); } #endif /* LIBXML_REGEXP_ENABLED */ @@ -1082,7 +1164,8 @@ xmlTextReaderDoExpand(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL)) return(-1); do { - if (reader->ctxt->instate == XML_PARSER_EOF) return(1); + if (PARSER_STOPPED(reader->ctxt)) + return(1); if (xmlTextReaderGetSuccessor(reader->node) != NULL) return(1); @@ -1093,60 +1176,13 @@ xmlTextReaderDoExpand(xmlTextReaderPtr reader) { val = xmlTextReaderPushData(reader); if (val < 0){ reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; return(-1); } } while(reader->mode != XML_TEXTREADER_MODE_EOF); return(1); } -/** - * xmlTextReaderCollectSiblings: - * @node: the first child - * - * Traverse depth-first through all sibling nodes and their children - * nodes and concatenate their content. This is an auxiliary function - * to xmlTextReaderReadString. - * - * Returns a string containing the content, or NULL in case of error. - */ -static xmlChar * -xmlTextReaderCollectSiblings(xmlNodePtr node) -{ - xmlBufferPtr buffer; - xmlChar *ret; - - if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) - return(NULL); - - buffer = xmlBufferCreate(); - if (buffer == NULL) - return NULL; - xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); - - for ( ; node != NULL; node = node->next) { - switch (node->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - xmlBufferCat(buffer, node->content); - break; - case XML_ELEMENT_NODE: { - xmlChar *tmp; - - tmp = xmlTextReaderCollectSiblings(node->children); - xmlBufferCat(buffer, tmp); - xmlFree(tmp); - break; - } - default: - break; - } - } - ret = buffer->content; - buffer->content = NULL; - xmlBufferFree(buffer); - return(ret); -} - /** * xmlTextReaderRead: * @reader: the xmlTextReaderPtr used @@ -1163,9 +1199,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { xmlTextReaderState oldstate = XML_TEXTREADER_START; xmlNodePtr oldnode = NULL; - if (reader == NULL) return(-1); + if (reader->state == XML_TEXTREADER_ERROR) + return(-1); + reader->curnode = NULL; if (reader->doc != NULL) return(xmlTextReaderReadTree(reader)); @@ -1179,11 +1217,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { */ do { val = xmlTextReaderPushData(reader); - if (val < 0){ - reader->mode = XML_TEXTREADER_MODE_ERROR; - reader->state = XML_TEXTREADER_ERROR; - return(-1); - } + if (val < 0) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; + return(-1); + } } while ((reader->ctxt->node == NULL) && ((reader->mode != XML_TEXTREADER_MODE_EOF) && (reader->state != XML_TEXTREADER_DONE))); @@ -1191,11 +1229,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { if (reader->ctxt->myDoc != NULL) { reader->node = reader->ctxt->myDoc->children; } - if (reader->node == NULL){ - reader->mode = XML_TEXTREADER_MODE_ERROR; - reader->state = XML_TEXTREADER_ERROR; + if (reader->node == NULL) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; return(-1); - } + } reader->state = XML_TEXTREADER_ELEMENT; } else { if (reader->ctxt->myDoc != NULL) { @@ -1215,10 +1253,13 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { get_next_node: if (reader->node == NULL) { - if (reader->mode == XML_TEXTREADER_MODE_EOF) + if (reader->mode == XML_TEXTREADER_MODE_EOF) { return(0); - else + } else { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; return(-1); + } } /* @@ -1240,13 +1281,14 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { ((reader->ctxt->node == NULL) || (reader->ctxt->node == reader->node) || (reader->ctxt->node == reader->node->parent)) && - (reader->ctxt->instate != XML_PARSER_EOF)) { + (reader->ctxt->instate != XML_PARSER_EOF) && + (PARSER_STOPPED(reader->ctxt) == 0)) { val = xmlTextReaderPushData(reader); - if (val < 0){ - reader->mode = XML_TEXTREADER_MODE_ERROR; - reader->state = XML_TEXTREADER_ERROR; + if (val < 0) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; return(-1); - } + } if (reader->node == NULL) goto node_end; } @@ -1276,7 +1318,8 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { #ifdef LIBXML_REGEXP_ENABLED if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE)) - xmlTextReaderValidatePop(reader); + if (xmlTextReaderValidatePop(reader) < 0) + return(-1); #endif /* LIBXML_REGEXP_ENABLED */ if ((reader->preserves > 0) && (reader->node->extra & NODE_IS_SPRESERVED)) @@ -1313,8 +1356,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { goto node_found; } #ifdef LIBXML_REGEXP_ENABLED - if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && (reader->node->type == XML_ELEMENT_NODE)) - xmlTextReaderValidatePop(reader); + if ((reader->validate != XML_TEXTREADER_NOT_VALIDATE) && + (reader->node->type == XML_ELEMENT_NODE)) { + if (xmlTextReaderValidatePop(reader) < 0) + return(-1); + } #endif /* LIBXML_REGEXP_ENABLED */ if ((reader->preserves > 0) && (reader->node->extra & NODE_IS_SPRESERVED)) @@ -1326,8 +1372,11 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { if (reader->mode != XML_TEXTREADER_MODE_EOF) { val = xmlParseChunk(reader->ctxt, "", 0, 1); reader->state = XML_TEXTREADER_DONE; - if (val != 0) + if (val != 0) { + reader->mode = XML_TEXTREADER_MODE_ERROR; + reader->state = XML_TEXTREADER_ERROR; return(-1); + } } reader->node = NULL; reader->depth = -1; @@ -1387,16 +1436,29 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { (xmlStrEqual(reader->node->ns->href, XINCLUDE_OLD_NS)))) { if (reader->xincctxt == NULL) { reader->xincctxt = xmlXIncludeNewContext(reader->ctxt->myDoc); + if (reader->xincctxt == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } xmlXIncludeSetFlags(reader->xincctxt, reader->parserFlags & (~XML_PARSE_NOXINCNODE)); xmlXIncludeSetStreamingMode(reader->xincctxt, 1); + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlXIncludeSetErrorHandler(reader->xincctxt, + xmlTextReaderStructuredRelay, reader); } /* * expand that node and process it */ if (xmlTextReaderExpand(reader) == NULL) - return -1; - xmlXIncludeProcessNode(reader->xincctxt, reader->node); + return(-1); + if (xmlXIncludeProcessNode(reader->xincctxt, reader->node) < 0) { + int err = xmlXIncludeGetLastError(reader->xincctxt); + + if (err == XML_ERR_NO_MEMORY) + xmlTextReaderErrMemory(reader); + return(-1); + } } if ((reader->node != NULL) && (reader->node->type == XML_XINCLUDE_START)) { reader->in_xinclude++; @@ -1424,7 +1486,8 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { } else if ((reader->node != NULL) && (reader->node->type == XML_ENTITY_REF_NODE) && (reader->ctxt != NULL) && (reader->validate)) { - xmlTextReaderValidateEntity(reader); + if (xmlTextReaderValidateEntity(reader) < 0) + return(-1); #endif /* LIBXML_REGEXP_ENABLED */ } if ((reader->node != NULL) && @@ -1441,7 +1504,8 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { if ((node->type == XML_ELEMENT_NODE) && ((reader->state != XML_TEXTREADER_END) && (reader->state != XML_TEXTREADER_BACKTRACK))) { - xmlTextReaderValidatePush(reader); + if (xmlTextReaderValidatePush(reader) < 0) + return(-1); } else if ((node->type == XML_TEXT_NODE) || (node->type == XML_CDATA_SECTION_NODE)) { xmlTextReaderValidateCData(reader, node->content, @@ -1547,6 +1611,37 @@ xmlTextReaderNext(xmlTextReaderPtr reader) { } #ifdef LIBXML_WRITER_ENABLED +static void +xmlTextReaderDumpCopy(xmlTextReaderPtr reader, xmlOutputBufferPtr output, + xmlNodePtr node) { + if ((node->type == XML_DTD_NODE) || + (node->type == XML_ELEMENT_DECL) || + (node->type == XML_ATTRIBUTE_DECL) || + (node->type == XML_ENTITY_DECL)) + return; + + if ((node->type == XML_DOCUMENT_NODE) || + (node->type == XML_HTML_DOCUMENT_NODE)) { + xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL); + } else { + xmlNodePtr copy; + + /* + * Create a copy to make sure that namespace declarations from + * ancestors are added. + */ + copy = xmlDocCopyNode(node, node->doc, 1); + if (copy == NULL) { + xmlTextReaderErrMemory(reader); + return; + } + + xmlNodeDumpOutput(output, copy->doc, copy, 0, 0, NULL); + + xmlFreeNode(copy); + } +} + /** * xmlTextReaderReadInnerXml: * @reader: the xmlTextReaderPtr used @@ -1558,47 +1653,36 @@ xmlTextReaderNext(xmlTextReaderPtr reader) { * string must be deallocated by the caller. */ xmlChar * -xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) +xmlTextReaderReadInnerXml(xmlTextReaderPtr reader) { - xmlChar *resbuf; - xmlNodePtr node, cur_node; - xmlBufferPtr buff, buff2; - xmlDocPtr doc; + xmlOutputBufferPtr output; + xmlNodePtr cur; + xmlChar *ret; - if (xmlTextReaderExpand(reader) == NULL) { - return NULL; - } - doc = reader->node->doc; - buff = xmlBufferCreate(); - if (buff == NULL) - return NULL; - xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT); - for (cur_node = reader->node->children; cur_node != NULL; - cur_node = cur_node->next) { - /* XXX: Why is the node copied? */ - node = xmlDocCopyNode(cur_node, doc, 1); - /* XXX: Why do we need a second buffer? */ - buff2 = xmlBufferCreate(); - xmlBufferSetAllocationScheme(buff2, XML_BUFFER_ALLOC_DOUBLEIT); - if (xmlNodeDump(buff2, doc, node, 0, 0) == -1) { - xmlFreeNode(node); - xmlBufferFree(buff2); - xmlBufferFree(buff); - return NULL; - } - xmlBufferCat(buff, buff2->content); - xmlFreeNode(node); - xmlBufferFree(buff2); + if (xmlTextReaderExpand(reader) == NULL) + return(NULL); + + if (reader->node == NULL) + return(NULL); + + output = xmlAllocOutputBuffer(NULL); + if (output == NULL) { + xmlTextReaderErrMemory(reader); + return(NULL); } - resbuf = buff->content; - buff->content = NULL; - xmlBufferFree(buff); - return resbuf; + for (cur = reader->node->children; cur != NULL; cur = cur->next) + xmlTextReaderDumpCopy(reader, output, cur); + + if (output->error) + xmlCtxtErrIO(reader->ctxt, output->error, NULL); + + ret = xmlBufDetach(output->buffer); + xmlOutputBufferClose(output); + + return(ret); } -#endif -#ifdef LIBXML_WRITER_ENABLED /** * xmlTextReaderReadOuterXml: * @reader: the xmlTextReaderPtr used @@ -1610,38 +1694,33 @@ xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) * by the caller. */ xmlChar * -xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) +xmlTextReaderReadOuterXml(xmlTextReaderPtr reader) { - xmlChar *resbuf; + xmlOutputBufferPtr output; xmlNodePtr node; - xmlBufferPtr buff; - xmlDocPtr doc; + xmlChar *ret; + + if (xmlTextReaderExpand(reader) == NULL) + return(NULL); - if (xmlTextReaderExpand(reader) == NULL) { - return NULL; - } node = reader->node; - doc = node->doc; - /* XXX: Why is the node copied? */ - if (node->type == XML_DTD_NODE) { - node = (xmlNodePtr) xmlCopyDtd((xmlDtdPtr) node); - } else { - node = xmlDocCopyNode(node, doc, 1); - } - buff = xmlBufferCreate(); - xmlBufferSetAllocationScheme(buff, XML_BUFFER_ALLOC_DOUBLEIT); - if (xmlNodeDump(buff, doc, node, 0, 0) == -1) { - xmlFreeNode(node); - xmlBufferFree(buff); - return NULL; + if (node == NULL) + return(NULL); + + output = xmlAllocOutputBuffer(NULL); + if (output == NULL) { + xmlTextReaderErrMemory(reader); + return(NULL); } - resbuf = buff->content; - buff->content = NULL; + xmlTextReaderDumpCopy(reader, output, node); + if (output->error) + xmlCtxtErrIO(reader->ctxt, output->error, NULL); + + ret = xmlBufDetach(output->buffer); + xmlOutputBufferClose(output); - xmlFreeNode(node); - xmlBufferFree(buff); - return resbuf; + return(ret); } #endif @@ -1658,29 +1737,70 @@ xmlTextReaderReadOuterXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED) xmlChar * xmlTextReaderReadString(xmlTextReaderPtr reader) { - xmlNodePtr node; + xmlNodePtr node, cur; + xmlBufPtr buf; + xmlChar *ret; if ((reader == NULL) || (reader->node == NULL)) return(NULL); node = (reader->curnode != NULL) ? reader->curnode : reader->node; switch (node->type) { - case XML_TEXT_NODE: - if (node->content != NULL) - return(xmlStrdup(node->content)); - break; - case XML_ELEMENT_NODE: - if (xmlTextReaderDoExpand(reader) != -1) { - return xmlTextReaderCollectSiblings(node->children); - } - break; - case XML_ATTRIBUTE_NODE: - TODO - break; - default: - break; + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ELEMENT_NODE: + break; + case XML_ATTRIBUTE_NODE: + /* TODO */ + break; + default: + break; } - return(NULL); + + buf = xmlBufCreateSize(30); + if (buf == NULL) { + xmlTextReaderErrMemory(reader); + return(NULL); + } + xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); + + cur = node; + while (cur != NULL) { + switch (cur->type) { + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + xmlBufCat(buf, cur->content); + break; + + case XML_ELEMENT_NODE: + if (cur->children != NULL) { + cur = cur->children; + continue; + } + break; + + default: + break; + } + + if (cur == node) + goto done; + + while (cur->next == NULL) { + cur = cur->parent; + if (cur == node) + goto done; + } + cur = cur->next; + } + +done: + ret = xmlBufDetach(buf); + if (ret == NULL) + xmlTextReaderErrMemory(reader); + + xmlBufFree(buf); + return(ret); } #if 0 @@ -1710,7 +1830,6 @@ xmlTextReaderReadBase64(xmlTextReaderPtr reader, if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); - TODO return(0); } @@ -1740,7 +1859,6 @@ xmlTextReaderReadBinHex(xmlTextReaderPtr reader, if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE)) return(0); - TODO return(0); } #endif @@ -1940,11 +2058,8 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { if (input == NULL) return(NULL); ret = xmlMalloc(sizeof(xmlTextReader)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextReader : malloc failed\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlTextReader)); ret->doc = NULL; ret->entTab = NULL; @@ -1954,8 +2069,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { ret->buffer = xmlBufCreateSize(100); if (ret->buffer == NULL) { xmlFree(ret); - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextReader : malloc failed\n"); return(NULL); } /* no operation on a reader should require a huge buffer */ @@ -1965,8 +2078,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { if (ret->sax == NULL) { xmlBufFree(ret->buffer); xmlFree(ret); - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextReader : malloc failed\n"); return(NULL); } xmlSAXVersion(ret->sax, 2); @@ -2012,8 +2123,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { } if (ret->ctxt == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextReader : malloc failed\n"); xmlBufFree(ret->buffer); xmlFree(ret->sax); xmlFree(ret); @@ -2027,7 +2136,6 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { /* * use the parser dictionary to allocate all elements and attributes names */ - ret->ctxt->docdict = 1; ret->dict = ret->ctxt->dict; #ifdef LIBXML_XINCLUDE_ENABLED ret->xinclude = 0; @@ -2051,7 +2159,6 @@ xmlTextReaderPtr xmlNewTextReaderFilename(const char *URI) { xmlParserInputBufferPtr input; xmlTextReaderPtr ret; - char *directory = NULL; input = xmlParserInputBufferCreateFilename(URI, XML_CHAR_ENCODING_NONE); if (input == NULL) @@ -2062,12 +2169,6 @@ xmlNewTextReaderFilename(const char *URI) { return(NULL); } ret->allocs |= XML_TEXTREADER_INPUT; - if (ret->ctxt->directory == NULL) - directory = xmlParserGetDirectory(URI); - if ((ret->ctxt->directory == NULL) && (directory != NULL)) - ret->ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); - if (directory != NULL) - xmlFree(directory); return(ret); } @@ -2143,6 +2244,7 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { * Methods for XmlTextReader * * * ************************************************************************/ + /** * xmlTextReaderClose: * @reader: the xmlTextReaderPtr used @@ -2223,7 +2325,7 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { ns = ns->next; } if (ns != NULL) - return(xmlStrdup(ns->href)); + return(readerStrdup(reader, ns->href)); cur = reader->node->properties; if (cur == NULL) @@ -2236,7 +2338,8 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { /* TODO walk the DTD if present */ ret = xmlNodeListGetString(reader->node->doc, cur->children, 1); - if (ret == NULL) return(xmlStrdup((xmlChar *)"")); + if (ret == NULL) + xmlTextReaderErrMemory(reader); return(ret); } @@ -2253,9 +2356,10 @@ xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) { xmlChar * xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { xmlChar *prefix = NULL; - xmlChar *localname; + const xmlChar *localname; xmlNsPtr ns; xmlChar *ret = NULL; + int result; if ((reader == NULL) || (name == NULL)) return(NULL); @@ -2268,43 +2372,56 @@ xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { if (reader->node->type != XML_ELEMENT_NODE) return(NULL); - localname = xmlSplitQName2(name, &prefix); + localname = xmlSplitQName4(name, &prefix); if (localname == NULL) { - /* - * Namespace default decl - */ - if (xmlStrEqual(name, BAD_CAST "xmlns")) { - ns = reader->node->nsDef; - while (ns != NULL) { - if (ns->prefix == NULL) { - return(xmlStrdup(ns->href)); - } - ns = ns->next; - } - return NULL; - } - return(xmlGetNoNsProp(reader->node, name)); - } + xmlTextReaderErrMemory(reader); + return(NULL); + } + if (prefix == NULL) { + /* + * Namespace default decl + */ + if (xmlStrEqual(name, BAD_CAST "xmlns")) { + ns = reader->node->nsDef; + while (ns != NULL) { + if (ns->prefix == NULL) { + return(readerStrdup(reader, ns->href)); + } + ns = ns->next; + } + return NULL; + } + + result = xmlNodeGetAttrValue(reader->node, name, NULL, &ret); + if (result < 0) + xmlTextReaderErrMemory(reader); + return(ret); + } /* * Namespace default decl */ if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { - ns = reader->node->nsDef; - while (ns != NULL) { - if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { - ret = xmlStrdup(ns->href); - break; - } - ns = ns->next; - } + ns = reader->node->nsDef; + while (ns != NULL) { + if ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localname))) { + ret = readerStrdup(reader, ns->href); + break; + } + ns = ns->next; + } } else { - ns = xmlSearchNs(reader->node->doc, reader->node, prefix); - if (ns != NULL) - ret = xmlGetNsProp(reader->node, localname, ns->href); - } + result = xmlSearchNsSafe(reader->node, prefix, &ns); + if (result < 0) + xmlTextReaderErrMemory(reader); + if (ns != NULL) { + result = xmlNodeGetAttrValue(reader->node, localname, ns->href, + &ret); + if (result < 0) + xmlTextReaderErrMemory(reader); + } + } - xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(ret); @@ -2325,8 +2442,10 @@ xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) { xmlChar * xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, const xmlChar *namespaceURI) { + xmlChar *ret = NULL; xmlChar *prefix = NULL; xmlNsPtr ns; + int result; if ((reader == NULL) || (localName == NULL)) return(NULL); @@ -2340,21 +2459,25 @@ xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, return(NULL); if (xmlStrEqual(namespaceURI, BAD_CAST "http://www.w3.org/2000/xmlns/")) { - if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { - prefix = BAD_CAST localName; - } - ns = reader->node->nsDef; - while (ns != NULL) { - if ((prefix == NULL && ns->prefix == NULL) || - ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { - return xmlStrdup(ns->href); - } - ns = ns->next; - } - return NULL; + if (! xmlStrEqual(localName, BAD_CAST "xmlns")) { + prefix = BAD_CAST localName; + } + ns = reader->node->nsDef; + while (ns != NULL) { + if ((prefix == NULL && ns->prefix == NULL) || + ((ns->prefix != NULL) && (xmlStrEqual(ns->prefix, localName)))) { + return readerStrdup(reader, ns->href); + } + ns = ns->next; + } + return NULL; } - return(xmlGetNsProp(reader->node, localName, namespaceURI)); + result = xmlNodeGetAttrValue(reader->node, localName, namespaceURI, &ret); + if (result < 0) + xmlTextReaderErrMemory(reader); + + return(ret); } /** @@ -2403,7 +2526,6 @@ xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { * - by the layer which allocated it. * - by the layer to which would have been returned to. */ - TODO return(NULL); } return(ret); @@ -2423,16 +2545,21 @@ xmlTextReaderGetRemainder(xmlTextReaderPtr reader) { xmlChar * xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix) { xmlNsPtr ns; + int result; if (reader == NULL) return(NULL); if (reader->node == NULL) return(NULL); - ns = xmlSearchNs(reader->node->doc, reader->node, prefix); + result = xmlSearchNsSafe(reader->node, prefix, &ns); + if (result < 0) { + xmlTextReaderErrMemory(reader); + return(NULL); + } if (ns == NULL) return(NULL); - return(xmlStrdup(ns->href)); + return(readerStrdup(reader, ns->href)); } /** @@ -2498,7 +2625,7 @@ xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no) { int xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { xmlChar *prefix = NULL; - xmlChar *localname; + const xmlChar *localname; xmlNsPtr ns; xmlAttrPtr prop; @@ -2511,8 +2638,12 @@ xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { if (reader->node->type != XML_ELEMENT_NODE) return(0); - localname = xmlSplitQName2(name, &prefix); + localname = xmlSplitQName4(name, &prefix); if (localname == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } + if (prefix == NULL) { /* * Namespace default decl */ @@ -2574,15 +2705,11 @@ xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name) { prop = prop->next; } not_found: - if (localname != NULL) - xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(0); found: - if (localname != NULL) - xmlFree(localname); if (prefix != NULL) xmlFree(prefix); return(1); @@ -2769,12 +2896,24 @@ xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { if (reader->faketext == NULL) { reader->faketext = xmlNewDocText(reader->node->doc, ns->href); + if (reader->faketext == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } } else { if ((reader->faketext->content != NULL) && (reader->faketext->content != (xmlChar *) &(reader->faketext->properties))) xmlFree(reader->faketext->content); - reader->faketext->content = xmlStrdup(ns->href); + if (ns->href == NULL) { + reader->faketext->content = NULL; + } else { + reader->faketext->content = xmlStrdup(ns->href); + if (reader->faketext->content == NULL) { + xmlTextReaderErrMemory(reader); + return(-1); + } + } } reader->curnode = reader->faketext; } else { @@ -2806,7 +2945,7 @@ xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { else if (reader->doc != NULL) encoding = reader->doc->encoding; - return(CONSTSTR(encoding)); + return(constString(reader, encoding)); } @@ -2980,14 +3119,14 @@ xmlTextReaderLocalName(xmlTextReaderPtr reader) { if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) - return(xmlStrdup(BAD_CAST "xmlns")); + return(readerStrdup(reader, BAD_CAST "xmlns")); else - return(xmlStrdup(ns->prefix)); + return(readerStrdup(reader, ns->prefix)); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(xmlTextReaderName(reader)); - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); } /** @@ -3011,7 +3150,7 @@ xmlTextReaderConstLocalName(xmlTextReaderPtr reader) { if (node->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) - return(CONSTSTR(BAD_CAST "xmlns")); + return(constString(reader, BAD_CAST "xmlns")); else return(ns->prefix); } @@ -3046,41 +3185,41 @@ xmlTextReaderName(xmlTextReaderPtr reader) { case XML_ATTRIBUTE_NODE: if ((node->ns == NULL) || (node->ns->prefix == NULL)) - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); - ret = xmlStrdup(node->ns->prefix); - ret = xmlStrcat(ret, BAD_CAST ":"); - ret = xmlStrcat(ret, node->name); + ret = xmlBuildQName(node->name, node->ns->prefix, NULL, 0); + if (ret == NULL) + xmlTextReaderErrMemory(reader); return(ret); case XML_TEXT_NODE: - return(xmlStrdup(BAD_CAST "#text")); + return(readerStrdup(reader, BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: - return(xmlStrdup(BAD_CAST "#cdata-section")); + return(readerStrdup(reader, BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); case XML_PI_NODE: - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); case XML_COMMENT_NODE: - return(xmlStrdup(BAD_CAST "#comment")); + return(readerStrdup(reader, BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: - return(xmlStrdup(BAD_CAST "#document")); + return(readerStrdup(reader, BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: - return(xmlStrdup(BAD_CAST "#document-fragment")); + return(readerStrdup(reader, BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: - return(xmlStrdup(node->name)); + return(readerStrdup(reader, node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node; - ret = xmlStrdup(BAD_CAST "xmlns"); if (ns->prefix == NULL) - return(ret); - ret = xmlStrcat(ret, BAD_CAST ":"); - ret = xmlStrcat(ret, ns->prefix); + return(readerStrdup(reader, BAD_CAST "xmlns")); + ret = xmlBuildQName(ns->prefix, BAD_CAST "xmlns", NULL, 0); + if (ret == NULL) + xmlTextReaderErrMemory(reader); return(ret); } @@ -3119,34 +3258,34 @@ xmlTextReaderConstName(xmlTextReaderPtr reader) { if ((node->ns == NULL) || (node->ns->prefix == NULL)) return(node->name); - return(CONSTQSTR(node->ns->prefix, node->name)); + return(constQString(reader, node->ns->prefix, node->name)); case XML_TEXT_NODE: - return(CONSTSTR(BAD_CAST "#text")); + return(constString(reader, BAD_CAST "#text")); case XML_CDATA_SECTION_NODE: - return(CONSTSTR(BAD_CAST "#cdata-section")); + return(constString(reader, BAD_CAST "#cdata-section")); case XML_ENTITY_NODE: case XML_ENTITY_REF_NODE: - return(CONSTSTR(node->name)); + return(constString(reader, node->name)); case XML_PI_NODE: - return(CONSTSTR(node->name)); + return(constString(reader, node->name)); case XML_COMMENT_NODE: - return(CONSTSTR(BAD_CAST "#comment")); + return(constString(reader, BAD_CAST "#comment")); case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: - return(CONSTSTR(BAD_CAST "#document")); + return(constString(reader, BAD_CAST "#document")); case XML_DOCUMENT_FRAG_NODE: - return(CONSTSTR(BAD_CAST "#document-fragment")); + return(constString(reader, BAD_CAST "#document-fragment")); case XML_NOTATION_NODE: - return(CONSTSTR(node->name)); + return(constString(reader, node->name)); case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: - return(CONSTSTR(node->name)); + return(constString(reader, node->name)); case XML_NAMESPACE_DECL: { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) - return(CONSTSTR(BAD_CAST "xmlns")); - return(CONSTQSTR(BAD_CAST "xmlns", ns->prefix)); + return(constString(reader, BAD_CAST "xmlns")); + return(constQString(reader, BAD_CAST "xmlns", ns->prefix)); } case XML_ELEMENT_DECL: @@ -3181,13 +3320,13 @@ xmlTextReaderPrefix(xmlTextReaderPtr reader) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(NULL); - return(xmlStrdup(BAD_CAST "xmlns")); + return(readerStrdup(reader, BAD_CAST "xmlns")); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if ((node->ns != NULL) && (node->ns->prefix != NULL)) - return(xmlStrdup(node->ns->prefix)); + return(readerStrdup(reader, node->ns->prefix)); return(NULL); } @@ -3213,13 +3352,13 @@ xmlTextReaderConstPrefix(xmlTextReaderPtr reader) { xmlNsPtr ns = (xmlNsPtr) node; if (ns->prefix == NULL) return(NULL); - return(CONSTSTR(BAD_CAST "xmlns")); + return(constString(reader, BAD_CAST "xmlns")); } if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if ((node->ns != NULL) && (node->ns->prefix != NULL)) - return(CONSTSTR(node->ns->prefix)); + return(constString(reader, node->ns->prefix)); return(NULL); } @@ -3242,12 +3381,12 @@ xmlTextReaderNamespaceUri(xmlTextReaderPtr reader) { else node = reader->node; if (node->type == XML_NAMESPACE_DECL) - return(xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/")); + return(readerStrdup(reader, BAD_CAST "http://www.w3.org/2000/xmlns/")); if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if (node->ns != NULL) - return(xmlStrdup(node->ns->href)); + return(readerStrdup(reader, node->ns->href)); return(NULL); } @@ -3270,12 +3409,12 @@ xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { else node = reader->node; if (node->type == XML_NAMESPACE_DECL) - return(CONSTSTR(BAD_CAST "http://www.w3.org/2000/xmlns/")); + return(constString(reader, BAD_CAST "http://www.w3.org/2000/xmlns/")); if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_ATTRIBUTE_NODE)) return(NULL); if (node->ns != NULL) - return(CONSTSTR(node->ns->href)); + return(constString(reader, node->ns->href)); return(NULL); } @@ -3290,9 +3429,16 @@ xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader) { */ xmlChar * xmlTextReaderBaseUri(xmlTextReaderPtr reader) { + xmlChar *ret = NULL; + int result; + if ((reader == NULL) || (reader->node == NULL)) return(NULL); - return(xmlNodeGetBase(NULL, reader->node)); + result = xmlNodeGetBaseSafe(NULL, reader->node, &ret); + if (result < 0) + xmlTextReaderErrMemory(reader); + + return(ret); } /** @@ -3308,13 +3454,16 @@ const xmlChar * xmlTextReaderConstBaseUri(xmlTextReaderPtr reader) { xmlChar *tmp; const xmlChar *ret; + int result; if ((reader == NULL) || (reader->node == NULL)) return(NULL); - tmp = xmlNodeGetBase(NULL, reader->node); + result = xmlNodeGetBaseSafe(NULL, reader->node, &tmp); + if (result < 0) + xmlTextReaderErrMemory(reader); if (tmp == NULL) return(NULL); - ret = CONSTSTR(tmp); + ret = constString(reader, tmp); xmlFree(tmp); return(ret); } @@ -3427,23 +3576,24 @@ xmlTextReaderValue(xmlTextReaderPtr reader) { switch (node->type) { case XML_NAMESPACE_DECL: - return(xmlStrdup(((xmlNsPtr) node)->href)); + return(readerStrdup(reader, ((xmlNsPtr) node)->href)); case XML_ATTRIBUTE_NODE:{ xmlAttrPtr attr = (xmlAttrPtr) node; + xmlDocPtr doc = NULL; + xmlChar *ret; if (attr->parent != NULL) - return (xmlNodeListGetString - (attr->parent->doc, attr->children, 1)); - else - return (xmlNodeListGetString(NULL, attr->children, 1)); - break; + doc = attr->parent->doc; + ret = xmlNodeListGetString(doc, attr->children, 1); + if (ret == NULL) + xmlTextReaderErrMemory(reader); + return(ret); } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - if (node->content != NULL) - return (xmlStrdup(node->content)); + return(readerStrdup(reader, node->content)); default: break; } @@ -3485,11 +3635,8 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) { else { if (reader->buffer == NULL) { reader->buffer = xmlBufCreateSize(100); - if (reader->buffer == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlTextReaderSetup : malloc failed\n"); + if (reader->buffer == NULL) return (NULL); - } xmlBufSetAllocationScheme(reader->buffer, XML_BUFFER_ALLOC_DOUBLEIT); } else @@ -3497,12 +3644,12 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) { xmlBufGetNodeContent(reader->buffer, node); ret = xmlBufContent(reader->buffer); if (ret == NULL) { + xmlTextReaderErrMemory(reader); /* error on the buffer best to reallocate */ xmlBufFree(reader->buffer); reader->buffer = xmlBufCreateSize(100); xmlBufSetAllocationScheme(reader->buffer, XML_BUFFER_ALLOC_DOUBLEIT); - ret = BAD_CAST ""; } return(ret); } @@ -3589,7 +3736,7 @@ xmlTextReaderConstXmlLang(xmlTextReaderPtr reader) { tmp = xmlNodeGetLang(reader->node); if (tmp == NULL) return(NULL); - ret = CONSTSTR(tmp); + ret = constString(reader, tmp); xmlFree(tmp); return(ret); } @@ -3609,7 +3756,7 @@ const xmlChar * xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) { if (reader == NULL) return(NULL); - return(CONSTSTR(str)); + return(constString(reader, str)); } /** @@ -3664,18 +3811,21 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) { if (ctxt->loadsubset == 0) { if (reader->mode != XML_TEXTREADER_MODE_INITIAL) return(-1); - ctxt->loadsubset = XML_DETECT_IDS; + ctxt->options |= XML_PARSE_DTDLOAD; + ctxt->loadsubset |= XML_DETECT_IDS; } } else { - ctxt->loadsubset = 0; + ctxt->options &= ~XML_PARSE_DTDLOAD; + ctxt->loadsubset &= ~XML_DETECT_IDS; } return(0); case XML_PARSER_DEFAULTATTRS: if (value != 0) { + ctxt->options |= XML_PARSE_DTDATTR; ctxt->loadsubset |= XML_COMPLETE_ATTRS; } else { - if (ctxt->loadsubset & XML_COMPLETE_ATTRS) - ctxt->loadsubset -= XML_COMPLETE_ATTRS; + ctxt->options &= ~XML_PARSE_DTDATTR; + ctxt->loadsubset &= ~XML_COMPLETE_ATTRS; } return(0); case XML_PARSER_VALIDATE: @@ -3810,10 +3960,7 @@ xmlTextReaderPreserve(xmlTextReaderPtr reader) { if (reader == NULL) return(NULL); - if (reader->curnode != NULL) - cur = reader->curnode; - else - cur = reader->node; + cur = reader->node; if (cur == NULL) return(NULL); @@ -3863,7 +4010,7 @@ xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, reader->patternTab = (xmlPatternPtr *) xmlMalloc(reader->patternMax * sizeof(reader->patternTab[0])); if (reader->patternTab == NULL) { - xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n"); + xmlTextReaderErrMemory(reader); return (-1); } } @@ -3874,7 +4021,7 @@ xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, reader->patternMax * sizeof(reader->patternTab[0])); if (tmp == NULL) { - xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); + xmlTextReaderErrMemory(reader); reader->patternMax /= 2; return (-1); } @@ -3911,80 +4058,6 @@ xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { } #ifdef LIBXML_SCHEMAS_ENABLED -static char *xmlTextReaderBuildMessage(const char *msg, va_list ap) LIBXML_ATTR_FORMAT(1,0); - -static void -xmlTextReaderValidityError(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); - -static void -xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); - -static void -xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); - -static void -xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); - -static void -xmlTextReaderValidityErrorRelay(void *ctx, const char *msg, ...) -{ - xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; - - char *str; - - va_list ap; - - va_start(ap, msg); - str = xmlTextReaderBuildMessage(msg, ap); - if (!reader->errorFunc) { - xmlTextReaderValidityError(ctx, "%s", str); - } else { - reader->errorFunc(reader->errorFuncArg, str, - XML_PARSER_SEVERITY_VALIDITY_ERROR, - NULL /* locator */ ); - } - if (str != NULL) - xmlFree(str); - va_end(ap); -} - -static void -xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) -{ - xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx; - - char *str; - - va_list ap; - - va_start(ap, msg); - str = xmlTextReaderBuildMessage(msg, ap); - if (!reader->errorFunc) { - xmlTextReaderValidityWarning(ctx, "%s", str); - } else { - reader->errorFunc(reader->errorFuncArg, str, - XML_PARSER_SEVERITY_VALIDITY_WARNING, - NULL /* locator */ ); - } - if (str != NULL) - xmlFree(str); - va_end(ap); -} - -static void -xmlTextReaderStructuredError(void *ctxt, const xmlError *error); - -static void -xmlTextReaderValidityStructuredRelay(void *userData, const xmlError *error) -{ - xmlTextReaderPtr reader = (xmlTextReaderPtr) userData; - - if (reader->sErrorFunc) { - reader->sErrorFunc(reader->errorFuncArg, error); - } else { - xmlTextReaderStructuredError(reader, error); - } -} /** * xmlTextReaderRelaxNGSetSchema: * @reader: the xmlTextReaderPtr used @@ -4031,17 +4104,9 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) { reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema); if (reader->rngValidCtxt == NULL) return(-1); - if (reader->errorFunc != NULL) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } - if (reader->sErrorFunc != NULL) { - xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderStructuredRelay, reader); reader->rngValidErrors = 0; reader->rngFullNode = NULL; reader->validate = XML_TEXTREADER_VALIDATE_RNG; @@ -4173,17 +4238,9 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) { xmlTextReaderLocator, (void *) reader); - if (reader->errorFunc != NULL) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } - if (reader->sErrorFunc != NULL) { - xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderStructuredRelay, reader); reader->xsdValidErrors = 0; reader->validate = XML_TEXTREADER_VALIDATE_XSD; return(0); @@ -4243,21 +4300,14 @@ xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, /* Parse the schema and create validation environment. */ pctxt = xmlRelaxNGNewParserCtxt(rng); - if (reader->errorFunc != NULL) { - xmlRelaxNGSetParserErrors(pctxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } - if (reader->sErrorFunc != NULL) { - xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlRelaxNGSetParserStructuredErrors(pctxt, + xmlTextReaderStructuredRelay, reader); reader->rngSchemas = xmlRelaxNGParse(pctxt); xmlRelaxNGFreeParserCtxt(pctxt); if (reader->rngSchemas == NULL) return(-1); + reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas); if (reader->rngValidCtxt == NULL) { xmlRelaxNGFree(reader->rngSchemas); @@ -4275,17 +4325,9 @@ xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader, * TODO: In case the user provides the validation context we * could make this redirection optional. */ - if (reader->errorFunc != NULL) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } - if (reader->sErrorFunc != NULL) { - xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderStructuredRelay, reader); reader->rngValidErrors = 0; reader->rngFullNode = NULL; reader->validate = XML_TEXTREADER_VALIDATE_RNG; @@ -4348,12 +4390,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, xmlSchemaParserCtxtPtr pctxt; /* Parse the schema and create validation environment. */ pctxt = xmlSchemaNewParserCtxt(xsd); - if (reader->errorFunc != NULL) { - xmlSchemaSetParserErrors(pctxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlSchemaSetParserStructuredErrors(pctxt, + xmlTextReaderStructuredRelay, reader); reader->xsdSchemas = xmlSchemaParse(pctxt); xmlSchemaFreeParserCtxt(pctxt); if (reader->xsdSchemas == NULL) @@ -4396,17 +4435,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader, * TODO: In case the user provides the validation context we * could make this redirection optional. */ - if (reader->errorFunc != NULL) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - } - if (reader->sErrorFunc != NULL) { - xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); - } + if ((reader->errorFunc != NULL) || (reader->sErrorFunc != NULL)) + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderStructuredRelay, reader); reader->xsdValidErrors = 0; reader->validate = XML_TEXTREADER_VALIDATE_XSD; return(0); @@ -4545,7 +4576,7 @@ xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader) { if (doc->version == NULL) return(NULL); else - return(CONSTSTR(doc->version)); + return(constString(reader, doc->version)); } /** @@ -4579,43 +4610,6 @@ xmlTextReaderStandalone(xmlTextReaderPtr reader) { * * ************************************************************************/ -/* helper to build a xmlMalloc'ed string from a format and va_list */ -static char * -xmlTextReaderBuildMessage(const char *msg, va_list ap) { - int size = 0; - int chars; - char *larger; - char *str = NULL; - va_list aq; - - while (1) { - VA_COPY(aq, ap); - chars = vsnprintf(str, size, msg, aq); - va_end(aq); - if (chars < 0) { - xmlGenericError(xmlGenericErrorContext, "vsnprintf failed !\n"); - if (str) - xmlFree(str); - return NULL; - } - if ((chars < size) || (size == MAX_ERR_MSG_SIZE)) - break; - if (chars < MAX_ERR_MSG_SIZE) - size = chars + 1; - else - size = MAX_ERR_MSG_SIZE; - if ((larger = (char *) xmlRealloc(str, size)) == NULL) { - xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n"); - if (str) - xmlFree(str); - return NULL; - } - str = larger; - } - - return str; -} - /** * xmlTextReaderLocatorLineNumber: * @locator: the xmlTextReaderLocatorPtr used @@ -4689,105 +4683,14 @@ xmlTextReaderLocatorBaseURI(xmlTextReaderLocatorPtr locator) { return ret; } -static void -xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, - char *str) -{ - xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; - - xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; - - if (str != NULL) { - if (reader->errorFunc) - reader->errorFunc(reader->errorFuncArg, str, severity, - (xmlTextReaderLocatorPtr) ctx); - xmlFree(str); - } -} - -static void -xmlTextReaderStructuredError(void *ctxt, const xmlError *error) -{ - xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt; - - xmlTextReaderPtr reader = (xmlTextReaderPtr) ctx->_private; - - if (error && reader->sErrorFunc) { - reader->sErrorFunc(reader->errorFuncArg, (xmlErrorPtr) error); - } -} - -static void LIBXML_ATTR_FORMAT(2,3) -xmlTextReaderError(void *ctxt, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - xmlTextReaderGenericError(ctxt, - XML_PARSER_SEVERITY_ERROR, - xmlTextReaderBuildMessage(msg, ap)); - va_end(ap); - -} - -static void LIBXML_ATTR_FORMAT(2,3) -xmlTextReaderWarning(void *ctxt, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - xmlTextReaderGenericError(ctxt, - XML_PARSER_SEVERITY_WARNING, - xmlTextReaderBuildMessage(msg, ap)); - va_end(ap); -} - -static void -xmlTextReaderValidityError(void *ctxt, const char *msg, ...) -{ - va_list ap; - - int len = xmlStrlen((const xmlChar *) msg); - - if ((len > 1) && (msg[len - 2] != ':')) { - /* - * some callbacks only report locator information: - * skip them (mimicking behaviour in error.c) - */ - va_start(ap, msg); - xmlTextReaderGenericError(ctxt, - XML_PARSER_SEVERITY_VALIDITY_ERROR, - xmlTextReaderBuildMessage(msg, ap)); - va_end(ap); - } -} - -static void -xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) -{ - va_list ap; - - int len = xmlStrlen((const xmlChar *) msg); - - if ((len != 0) && (msg[len - 1] != ':')) { - /* - * some callbacks only report locator information: - * skip them (mimicking behaviour in error.c) - */ - va_start(ap, msg); - xmlTextReaderGenericError(ctxt, - XML_PARSER_SEVERITY_VALIDITY_WARNING, - xmlTextReaderBuildMessage(msg, ap)); - va_end(ap); - } -} - /** * xmlTextReaderSetErrorHandler: * @reader: the xmlTextReaderPtr used * @f: the callback function to call on error and warnings * @arg: a user argument to pass to the callback function * + * DEPRECATED: Use xmlTextReaderSetStructuredErrorHandler. + * * Register a callback function that will be called on error and warnings. * * If @f is NULL, the default error and warning handlers are restored. @@ -4797,53 +4700,35 @@ xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, xmlTextReaderErrorFunc f, void *arg) { if (f != NULL) { - reader->ctxt->sax->error = xmlTextReaderError; - reader->ctxt->sax->serror = NULL; - reader->ctxt->vctxt.error = xmlTextReaderValidityError; - reader->ctxt->sax->warning = xmlTextReaderWarning; - reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->errorFunc = f; reader->sErrorFunc = NULL; reader->errorFuncArg = arg; + xmlCtxtSetErrorHandler(reader->ctxt, + xmlTextReaderStructuredRelay, reader); #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, - reader); + xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, + xmlTextReaderStructuredRelay, reader); } if (reader->xsdValidCtxt) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, - xmlTextReaderValidityErrorRelay, - xmlTextReaderValidityWarningRelay, - reader); - xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, - reader); + xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, + xmlTextReaderStructuredRelay, reader); } #endif } else { /* restore defaults */ - reader->ctxt->sax->error = xmlParserError; - reader->ctxt->vctxt.error = xmlParserValidityError; - reader->ctxt->sax->warning = xmlParserWarning; - reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL; + xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL); #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, - reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, - reader); + NULL); } if (reader->xsdValidCtxt) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, - reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, - reader); + NULL); } #endif } @@ -4864,52 +4749,35 @@ xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, xmlStructuredErrorFunc f, void *arg) { if (f != NULL) { - reader->ctxt->sax->error = NULL; - reader->ctxt->sax->serror = xmlTextReaderStructuredError; - reader->ctxt->vctxt.error = xmlTextReaderValidityError; - reader->ctxt->sax->warning = xmlTextReaderWarning; - reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning; reader->sErrorFunc = f; reader->errorFunc = NULL; reader->errorFuncArg = arg; + xmlCtxtSetErrorHandler(reader->ctxt, + xmlTextReaderStructuredRelay, reader); #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, - reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); + xmlTextReaderStructuredRelay, reader); } if (reader->xsdValidCtxt) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, - reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, - xmlTextReaderValidityStructuredRelay, - reader); + xmlTextReaderStructuredRelay, reader); } #endif } else { /* restore defaults */ - reader->ctxt->sax->error = xmlParserError; - reader->ctxt->sax->serror = NULL; - reader->ctxt->vctxt.error = xmlParserValidityError; - reader->ctxt->sax->warning = xmlParserWarning; - reader->ctxt->vctxt.warning = xmlParserValidityWarning; reader->errorFunc = NULL; reader->sErrorFunc = NULL; reader->errorFuncArg = NULL; + xmlCtxtSetErrorHandler(reader->ctxt, NULL, NULL); #ifdef LIBXML_SCHEMAS_ENABLED if (reader->rngValidCtxt) { - xmlRelaxNGSetValidErrors(reader->rngValidCtxt, NULL, NULL, - reader); xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt, NULL, - reader); + NULL); } if (reader->xsdValidCtxt) { - xmlSchemaSetValidErrors(reader->xsdValidCtxt, NULL, NULL, - reader); xmlSchemaSetValidStructuredErrors(reader->xsdValidCtxt, NULL, - reader); + NULL); } #endif } @@ -5009,8 +4877,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, if (reader->buffer == NULL) reader->buffer = xmlBufCreateSize(100); if (reader->buffer == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlTextReaderSetup : malloc failed\n"); return (-1); } /* no operation on a reader should require a huge buffer */ @@ -5019,8 +4885,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, if (reader->sax == NULL) reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (reader->sax == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlTextReaderSetup : malloc failed\n"); return (-1); } xmlSAXVersion(reader->sax, 2); @@ -5067,13 +4931,15 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, reader->base = 0; reader->cur = 0; } + if (reader->ctxt == NULL) { + return (-1); + } } else { xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf; - xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; xmlCtxtReset(reader->ctxt); - buf = xmlAllocParserInputBuffer(enc); + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); if (buf == NULL) return(-1); inputStream = xmlNewInputStream(reader->ctxt); if (inputStream == NULL) { @@ -5092,11 +4958,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, inputPush(reader->ctxt, inputStream); reader->cur = 0; } - if (reader->ctxt == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlTextReaderSetup : malloc failed\n"); - return (-1); - } } if (reader->dict != NULL) { if (reader->ctxt->dict != NULL) { @@ -5118,7 +4979,6 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, /* * use the parser dictionary to allocate all elements and attributes names */ - reader->ctxt->docdict = 1; reader->ctxt->parseMode = XML_PARSE_READER; #ifdef LIBXML_XINCLUDE_ENABLED @@ -5129,6 +4989,8 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, if (options & XML_PARSE_XINCLUDE) { reader->xinclude = 1; reader->xinclude_name = xmlDictLookup(reader->dict, XINCLUDE_NODE, -1); + if (reader->xinclude_name == NULL) + return(-1); options -= XML_PARSE_XINCLUDE; } else reader->xinclude = 0; @@ -5152,17 +5014,15 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, reader->validate = XML_TEXTREADER_VALIDATE_DTD; xmlCtxtUseOptions(reader->ctxt, options); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; - - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) - xmlSwitchToEncoding(reader->ctxt, hdlr); - } + if (encoding != NULL) + xmlSwitchEncodingName(reader->ctxt, encoding); if ((URL != NULL) && (reader->ctxt->input != NULL) && - (reader->ctxt->input->filename == NULL)) + (reader->ctxt->input->filename == NULL)) { reader->ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + if (reader->ctxt->input->filename == NULL) + return(-1); + } reader->doc = NULL; @@ -5182,6 +5042,22 @@ xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl) xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl); } +/** + * xmlTextReaderGetLastError: + * @reader: an XML reader + * + * Available since 2.13.0. + * + * Returns the last error. + */ +const xmlError * +xmlTextReaderGetLastError(xmlTextReaderPtr reader) +{ + if (reader == NULL) + return(NULL); + return(&reader->ctxt->lastError); +} + /** * xmlTextReaderByteConsumed: * @reader: an XML reader @@ -5221,8 +5097,6 @@ xmlReaderWalker(xmlDocPtr doc) ret = xmlMalloc(sizeof(xmlTextReader)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextReader : malloc failed\n"); return(NULL); } memset(ret, 0, sizeof(xmlTextReader)); @@ -5285,7 +5159,10 @@ xmlReaderForFile(const char *filename, const char *encoding, int options) reader = xmlNewTextReaderFilename(filename); if (reader == NULL) return (NULL); - xmlTextReaderSetup(reader, NULL, NULL, encoding, options); + if (xmlTextReaderSetup(reader, NULL, NULL, encoding, options) < 0) { + xmlFreeTextReader(reader); + return (NULL); + } return (reader); } @@ -5319,7 +5196,10 @@ xmlReaderForMemory(const char *buffer, int size, const char *URL, return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; - xmlTextReaderSetup(reader, NULL, URL, encoding, options); + if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) { + xmlFreeTextReader(reader); + return (NULL); + } return (reader); } @@ -5356,7 +5236,10 @@ xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; - xmlTextReaderSetup(reader, NULL, URL, encoding, options); + if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) { + xmlFreeTextReader(reader); + return (NULL); + } return (reader); } @@ -5398,7 +5281,10 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, return (NULL); } reader->allocs |= XML_TEXTREADER_INPUT; - xmlTextReaderSetup(reader, NULL, URL, encoding, options); + if (xmlTextReaderSetup(reader, NULL, URL, encoding, options) < 0) { + xmlFreeTextReader(reader); + return (NULL); + } return (reader); } diff --git a/xmlregexp.c b/xmlregexp.c index f434a0c..31e3d1a 100644 --- a/xmlregexp.c +++ b/xmlregexp.c @@ -38,16 +38,6 @@ #define MAX_PUSH 10000000 -/* - * -2 and -3 are used by xmlValidateElementType for other things. - */ -#define XML_REGEXP_OK 0 -#define XML_REGEXP_NOT_FOUND (-1) -#define XML_REGEXP_INTERNAL_ERROR (-4) -#define XML_REGEXP_OUT_OF_MEMORY (-5) -#define XML_REGEXP_INTERNAL_LIMIT (-6) -#define XML_REGEXP_INVALID_UTF8 (-7) - #ifdef ERROR #undef ERROR #endif @@ -66,16 +56,6 @@ */ #define PREV (ctxt->cur[-1]) -/** - * TODO: - * - * macro to flag unimplemented blocks - */ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - /************************************************************************ * * * Datatypes and structures * @@ -378,17 +358,12 @@ static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, * Handle an out of memory condition */ static void -xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt, const char *extra) +xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt) { - const char *regexp = NULL; - if (ctxt != NULL) { - regexp = (const char *) ctxt->string; - ctxt->error = XML_ERR_NO_MEMORY; - } - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - regexp, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); + if (ctxt != NULL) + ctxt->error = XML_ERR_NO_MEMORY; + + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_REGEXP, NULL); } /** @@ -402,16 +377,20 @@ xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra) { const char *regexp = NULL; int idx = 0; + int res; if (ctxt != NULL) { regexp = (const char *) ctxt->string; idx = ctxt->cur - ctxt->string; ctxt->error = XML_REGEXP_COMPILE_ERROR; } - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP, - XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL, NULL, 0, extra, - regexp, NULL, idx, 0, - "failed to compile: %s\n", extra); + + res = __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP, + XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL, + NULL, 0, extra, regexp, NULL, idx, 0, + "failed to compile: %s\n", extra); + if (res < 0) + xmlRegexpErrMemory(ctxt); } /************************************************************************ @@ -462,7 +441,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp)); if (ret == NULL) { - xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlRegexpErrMemory(ctxt); return(NULL); } memset(ret, 0, sizeof(xmlRegexp)); @@ -477,7 +456,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { ret->flags = ctxt->flags; if (ret->determinist == -1) { if (xmlRegexpIsDeterminist(ret) < 0) { - xmlRegexpErrMemory(ctxt, "checking determinism"); + xmlRegexpErrMemory(ctxt); xmlFree(ret); return(NULL); } @@ -507,7 +486,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { stateRemap = xmlMalloc(ret->nbStates * sizeof(int)); if (stateRemap == NULL) { - xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlRegexpErrMemory(ctxt); xmlFree(ret); return(NULL); } @@ -521,14 +500,14 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { } stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *)); if (stringMap == NULL) { - xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlRegexpErrMemory(ctxt); xmlFree(stateRemap); xmlFree(ret); return(NULL); } stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int)); if (stringRemap == NULL) { - xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlRegexpErrMemory(ctxt); xmlFree(stringMap); xmlFree(stateRemap); xmlFree(ret); @@ -607,7 +586,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { transdata = (void **) xmlRegCalloc2(nbstates, nbatoms, sizeof(void *)); if (transdata == NULL) { - xmlRegexpErrMemory(ctxt, "compiling regexp"); + xmlRegexpErrMemory(ctxt); break; } } @@ -698,8 +677,13 @@ xmlRegNewParserCtxt(const xmlChar *string) { if (ret == NULL) return(NULL); memset(ret, 0, sizeof(xmlRegParserCtxt)); - if (string != NULL) + if (string != NULL) { ret->string = xmlStrdup(string); + if (ret->string == NULL) { + xmlFree(ret); + return(NULL); + } + } ret->cur = ret->string; ret->neg = 0; ret->negs = 0; @@ -727,7 +711,7 @@ xmlRegNewRange(xmlRegParserCtxtPtr ctxt, ret = (xmlRegRangePtr) xmlMalloc(sizeof(xmlRegRange)); if (ret == NULL) { - xmlRegexpErrMemory(ctxt, "allocating range"); + xmlRegexpErrMemory(ctxt); return(NULL); } ret->neg = neg; @@ -775,7 +759,7 @@ xmlRegCopyRange(xmlRegParserCtxtPtr ctxt, xmlRegRangePtr range) { if (range->blockName != NULL) { ret->blockName = xmlStrdup(range->blockName); if (ret->blockName == NULL) { - xmlRegexpErrMemory(ctxt, "allocating range"); + xmlRegexpErrMemory(ctxt); xmlRegFreeRange(ret); return(NULL); } @@ -798,7 +782,7 @@ xmlRegNewAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomType type) { ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom)); if (ret == NULL) { - xmlRegexpErrMemory(ctxt, "allocating atom"); + xmlRegexpErrMemory(ctxt); return(NULL); } memset(ret, 0, sizeof(xmlRegAtom)); @@ -850,7 +834,7 @@ xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom)); if (ret == NULL) { - xmlRegexpErrMemory(ctxt, "copying atom"); + xmlRegexpErrMemory(ctxt); return(NULL); } memset(ret, 0, sizeof(xmlRegAtom)); @@ -864,7 +848,7 @@ xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { ret->ranges = (xmlRegRangePtr *) xmlMalloc(sizeof(xmlRegRangePtr) * atom->nbRanges); if (ret->ranges == NULL) { - xmlRegexpErrMemory(ctxt, "copying atom"); + xmlRegexpErrMemory(ctxt); goto error; } for (i = 0;i < atom->nbRanges;i++) { @@ -887,7 +871,7 @@ xmlRegNewState(xmlRegParserCtxtPtr ctxt) { ret = (xmlRegStatePtr) xmlMalloc(sizeof(xmlRegState)); if (ret == NULL) { - xmlRegexpErrMemory(ctxt, "allocating state"); + xmlRegexpErrMemory(ctxt); return(NULL); } memset(ret, 0, sizeof(xmlRegState)); @@ -1199,7 +1183,7 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom, atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges * sizeof(xmlRegRangePtr)); if (atom->ranges == NULL) { - xmlRegexpErrMemory(ctxt, "adding ranges"); + xmlRegexpErrMemory(ctxt); atom->maxRanges = 0; return(NULL); } @@ -1209,7 +1193,7 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom, tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges * sizeof(xmlRegRangePtr)); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "adding ranges"); + xmlRegexpErrMemory(ctxt); atom->maxRanges /= 2; return(NULL); } @@ -1231,7 +1215,7 @@ xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) { ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters * sizeof(xmlRegCounter)); if (ctxt->counters == NULL) { - xmlRegexpErrMemory(ctxt, "allocating counter"); + xmlRegexpErrMemory(ctxt); ctxt->maxCounters = 0; return(-1); } @@ -1241,7 +1225,7 @@ xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) { tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters * sizeof(xmlRegCounter)); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "allocating counter"); + xmlRegexpErrMemory(ctxt); ctxt->maxCounters /= 2; return(-1); } @@ -1264,7 +1248,7 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { tmp = xmlRealloc(ctxt->atoms, newSize * sizeof(xmlRegAtomPtr)); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "allocating counter"); + xmlRegexpErrMemory(ctxt); return(-1); } ctxt->atoms = tmp; @@ -1283,7 +1267,7 @@ xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, target->transTo = (int *) xmlMalloc(target->maxTransTo * sizeof(int)); if (target->transTo == NULL) { - xmlRegexpErrMemory(ctxt, "adding transition"); + xmlRegexpErrMemory(ctxt); target->maxTransTo = 0; return; } @@ -1293,7 +1277,7 @@ xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo * sizeof(int)); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "adding transition"); + xmlRegexpErrMemory(ctxt); target->maxTransTo /= 2; return; } @@ -1339,7 +1323,7 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans * sizeof(xmlRegTrans)); if (state->trans == NULL) { - xmlRegexpErrMemory(ctxt, "adding transition"); + xmlRegexpErrMemory(ctxt); state->maxTrans = 0; return; } @@ -1349,7 +1333,7 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans * sizeof(xmlRegTrans)); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "adding transition"); + xmlRegexpErrMemory(ctxt); state->maxTrans /= 2; return; } @@ -1375,7 +1359,7 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt) { tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0])); if (tmp == NULL) { - xmlRegexpErrMemory(ctxt, "adding state"); + xmlRegexpErrMemory(ctxt); return(NULL); } ctxt->states = tmp; @@ -3060,7 +3044,6 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks * sizeof(xmlRegExecRollback)); if (exec->rollbacks == NULL) { - xmlRegexpErrMemory(NULL, "saving regexp"); exec->maxRollbacks = 0; exec->status = XML_REGEXP_OUT_OF_MEMORY; return; @@ -3075,7 +3058,6 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks, exec->maxRollbacks * sizeof(xmlRegExecRollback)); if (tmp == NULL) { - xmlRegexpErrMemory(NULL, "saving regexp"); exec->maxRollbacks /= 2; exec->status = XML_REGEXP_OUT_OF_MEMORY; return; @@ -3092,7 +3074,6 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { exec->rollbacks[exec->nbRollbacks].counts = (int *) xmlMalloc(exec->comp->nbCounters * sizeof(int)); if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { - xmlRegexpErrMemory(NULL, "saving regexp"); exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } @@ -3157,7 +3138,6 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { if (comp->nbCounters > 0) { exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)); if (exec->counts == NULL) { - xmlRegexpErrMemory(NULL, "running regexp"); return(XML_REGEXP_OUT_OF_MEMORY); } memset(exec->counts, 0, comp->nbCounters * sizeof(int)); @@ -3440,10 +3420,8 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) { if ((comp->compact == NULL) && (comp->states == NULL)) return(NULL); exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt)); - if (exec == NULL) { - xmlRegexpErrMemory(NULL, "creating execution context"); + if (exec == NULL) return(NULL); - } memset(exec, 0, sizeof(xmlRegExecCtxt)); exec->inputString = NULL; exec->index = 0; @@ -3467,7 +3445,6 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) { exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int) * 2); if (exec->counts == NULL) { - xmlRegexpErrMemory(NULL, "creating execution context"); xmlFree(exec); return(NULL); } @@ -3523,6 +3500,22 @@ xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) { xmlFree(exec); } +static int +xmlRegExecSetErrString(xmlRegExecCtxtPtr exec, const xmlChar *value) { + if (exec->errString != NULL) + xmlFree(exec->errString); + if (value == NULL) { + exec->errString = NULL; + } else { + exec->errString = xmlStrdup(value); + if (exec->errString == NULL) { + exec->status = XML_REGEXP_OUT_OF_MEMORY; + return(-1); + } + } + return(0); +} + static void xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, void *data) { @@ -3531,8 +3524,8 @@ xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, exec->inputStack = (xmlRegInputTokenPtr) xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken)); if (exec->inputStack == NULL) { - xmlRegexpErrMemory(NULL, "pushing input string"); exec->inputStackMax = 0; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } } else if (exec->inputStackNr + 1 >= exec->inputStackMax) { @@ -3542,13 +3535,21 @@ xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack, exec->inputStackMax * sizeof(xmlRegInputToken)); if (tmp == NULL) { - xmlRegexpErrMemory(NULL, "pushing input string"); exec->inputStackMax /= 2; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } exec->inputStack = tmp; } - exec->inputStack[exec->inputStackNr].value = xmlStrdup(value); + if (value == NULL) { + exec->inputStack[exec->inputStackNr].value = NULL; + } else { + exec->inputStack[exec->inputStackNr].value = xmlStrdup(value); + if (exec->inputStack[exec->inputStackNr].value == NULL) { + exec->status = XML_REGEXP_OUT_OF_MEMORY; + return; + } + } exec->inputStack[exec->inputStackNr].data = data; exec->inputStackNr++; exec->inputStack[exec->inputStackNr].value = NULL; @@ -3667,12 +3668,10 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec, * current token */ error: - if (exec->errString != NULL) - xmlFree(exec->errString); - exec->errString = xmlStrdup(value); exec->errStateNo = state; exec->status = XML_REGEXP_NOT_FOUND; - return(XML_REGEXP_NOT_FOUND); + xmlRegExecSetErrString(exec, value); + return(exec->status); } /** @@ -3921,9 +3920,8 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, * entering a sink state, save the current state as error * state. */ - if (exec->errString != NULL) - xmlFree(exec->errString); - exec->errString = xmlStrdup(value); + if (xmlRegExecSetErrString(exec, value) < 0) + break; exec->errState = exec->state; memcpy(exec->errCounts, exec->counts, exec->comp->nbCounters * sizeof(int)); @@ -3960,9 +3958,8 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, if ((progress) && (exec->state != NULL) && (exec->state->type != XML_REGEXP_SINK_STATE)) { progress = 0; - if (exec->errString != NULL) - xmlFree(exec->errString); - exec->errString = xmlStrdup(value); + if (xmlRegExecSetErrString(exec, value) < 0) + break; exec->errState = exec->state; if (exec->comp->nbCounters) memcpy(exec->errCounts, exec->counts, @@ -4160,10 +4157,8 @@ xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err, continue; if (trans->count == REGEXP_ALL_LAX_COUNTER) { /* this should not be reached but ... */ - TODO; } else if (trans->count == REGEXP_ALL_COUNTER) { /* this should not be reached but ... */ - TODO; } else if (trans->counter >= 0) { xmlRegCounterPtr counter = NULL; int count; @@ -4665,6 +4660,8 @@ xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) { } type = XML_REGEXP_BLOCK_NAME; blockName = xmlStrndup(start, ctxt->cur - start); + if (blockName == NULL) + xmlRegexpErrMemory(ctxt); } else { ERROR("Unknown char property"); return; @@ -5676,6 +5673,11 @@ xmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from, return(NULL); atom->data = data; atom->valuep = xmlStrdup(token); + if (atom->valuep == NULL) { + xmlRegFreeAtom(atom); + xmlRegexpErrMemory(am); + return(NULL); + } if (xmlFAGenerateTransitions(am, from, to, atom) < 0) { xmlRegFreeAtom(atom); @@ -6287,6 +6289,8 @@ xmlAutomataCompile(xmlAutomataPtr am) { if ((am == NULL) || (am->error != 0)) return(NULL); xmlFAEliminateEpsilonTransitions(am); + if (am->error != 0) + return(NULL); /* xmlFAComputesDeterminism(am); */ ret = xmlRegEpxFromParse(am); diff --git a/xmlsave.c b/xmlsave.c index e4cda3e..ba00155 100644 --- a/xmlsave.c +++ b/xmlsave.c @@ -9,6 +9,8 @@ #define IN_LIBXML #include "libxml.h" +#include +#include #include #include #include @@ -22,17 +24,13 @@ #include "private/buf.h" #include "private/enc.h" #include "private/error.h" +#include "private/io.h" #include "private/save.h" #ifdef LIBXML_OUTPUT_ENABLED #define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml" -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - struct _xmlSaveCtxt { void *_private; int type; @@ -63,9 +61,11 @@ struct _xmlSaveCtxt { * Handle an out of memory condition */ static void -xmlSaveErrMemory(const char *extra) +xmlSaveErrMemory(xmlOutputBufferPtr out) { - __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra); + if (out != NULL) + out->error = XML_ERR_NO_MEMORY; + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_OUTPUT, NULL); } /** @@ -77,9 +77,23 @@ xmlSaveErrMemory(const char *extra) * Handle an out of memory condition */ static void -xmlSaveErr(int code, xmlNodePtr node, const char *extra) +xmlSaveErr(xmlOutputBufferPtr out, int code, xmlNodePtr node, + const char *extra) { const char *msg = NULL; + int res; + + /* Don't overwrite memory errors */ + if ((out != NULL) && (out->error == XML_ERR_NO_MEMORY)) + return; + + if (code == XML_ERR_NO_MEMORY) { + xmlSaveErrMemory(out); + return; + } + + if (out != NULL) + out->error = code; switch(code) { case XML_SAVE_NOT_UTF8: @@ -97,7 +111,13 @@ xmlSaveErr(int code, xmlNodePtr node, const char *extra) default: msg = "unexpected error number\n"; } - __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra); + + res = __xmlRaiseError(NULL, NULL, NULL, NULL, node, + XML_FROM_OUTPUT, code, XML_ERR_ERROR, NULL, 0, + extra, NULL, NULL, 0, 0, + msg, extra); + if (res < 0) + xmlSaveErrMemory(out); } /************************************************************************ @@ -198,79 +218,52 @@ xmlEscapeEntities(unsigned char* out, int *outlen, *out++ = ';'; in++; continue; + } else if (*in == 0xD) { + if (outend - out < 5) break; + *out++ = '&'; + *out++ = '#'; + *out++ = 'x'; + *out++ = 'D'; + *out++ = ';'; + in++; } else if (((*in >= 0x20) && (*in < 0x80)) || - (*in == '\n') || (*in == '\t')) { + (*in == 0xA) || (*in == 0x9)) { /* * default case, just copy ! */ *out++ = *in++; continue; - } else if (*in >= 0x80) { - /* - * We assume we have UTF-8 input. - */ + } else if (*in < 0x80) { + /* invalid control char */ + if (outend - out < 8) break; + out = xmlSerializeHexCharRef(out, 0xFFFD); + in++; + } else { + int len; + if (outend - out < 11) break; - if (*in < 0xC0) { - xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL); - in++; - goto error; - } else if (*in < 0xE0) { - if (inend - in < 2) break; - val = (in[0]) & 0x1F; - val <<= 6; - val |= (in[1]) & 0x3F; - in += 2; - } else if (*in < 0xF0) { - if (inend - in < 3) break; - val = (in[0]) & 0x0F; - val <<= 6; - val |= (in[1]) & 0x3F; - val <<= 6; - val |= (in[2]) & 0x3F; - in += 3; - } else if (*in < 0xF8) { - if (inend - in < 4) break; - val = (in[0]) & 0x07; - val <<= 6; - val |= (in[1]) & 0x3F; - val <<= 6; - val |= (in[2]) & 0x3F; - val <<= 6; - val |= (in[3]) & 0x3F; - in += 4; - } else { - xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL); - in++; - goto error; - } - if (!IS_CHAR(val)) { - xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL); - in++; - goto error; - } + len = inend - in; + val = xmlGetUTF8Char(in, &len); + + if (val < 0) { + val = 0xFFFD; + in++; + } else { + if (!IS_CHAR(val)) + val = 0xFFFD; + in += len; + } /* * We could do multiple things here. Just save as a char ref */ out = xmlSerializeHexCharRef(out, val); - } else if (IS_BYTE_CHAR(*in)) { - if (outend - out < 6) break; - out = xmlSerializeHexCharRef(out, *in++); - } else { - xmlGenericError(xmlGenericErrorContext, - "xmlEscapeEntities : char out of range\n"); - in++; - goto error; } } *outlen = out - outstart; *inlen = in - base; return(0); -error: - *outlen = out - outstart; - *inlen = in - base; - return(-1); } /************************************************************************ @@ -340,15 +333,18 @@ xmlNewSaveCtxt(const char *encoding, int options) ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt)); if (ret == NULL) { - xmlSaveErrMemory("creating saving context"); + xmlSaveErrMemory(NULL); return ( NULL ); } memset(ret, 0, sizeof(xmlSaveCtxt)); if (encoding != NULL) { - ret->handler = xmlFindCharEncodingHandler(encoding); + int res; + + res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, + &ret->handler); if (ret->handler == NULL) { - xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding); + xmlSaveErr(NULL, res, NULL, encoding); xmlFreeSaveCtxt(ret); return(NULL); } @@ -397,14 +393,13 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr) while (children != NULL) { switch (children->type) { case XML_TEXT_NODE: - xmlBufAttrSerializeTxtContent(buf->buffer, attr->doc, - attr, children->content); + xmlBufAttrSerializeTxtContent(buf, attr->doc, + children->content); break; case XML_ENTITY_REF_NODE: - xmlBufAdd(buf->buffer, BAD_CAST "&", 1); - xmlBufAdd(buf->buffer, children->name, - xmlStrlen(children->name)); - xmlBufAdd(buf->buffer, BAD_CAST ";", 1); + xmlOutputBufferWrite(buf, 1, "&"); + xmlOutputBufferWriteString(buf, (const char *) children->name); + xmlOutputBufferWrite(buf, 1, ";"); break; default: /* should not happen unless we have a badly built tree */ @@ -414,6 +409,46 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr) } } +/** + * xmlBufDumpNotationDecl: + * @buf: the XML buffer output + * @nota: A notation declaration + * + * This will dump the content the notation declaration as an XML DTD definition + */ +static void +xmlBufDumpNotationDecl(xmlOutputBufferPtr buf, xmlNotationPtr nota) { + xmlOutputBufferWrite(buf, 11, "name); + + if (nota->PublicID != NULL) { + xmlOutputBufferWrite(buf, 8, " PUBLIC "); + xmlOutputBufferWriteQuotedString(buf, nota->PublicID); + if (nota->SystemID != NULL) { + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteQuotedString(buf, nota->SystemID); + } + } else { + xmlOutputBufferWrite(buf, 8, " SYSTEM "); + xmlOutputBufferWriteQuotedString(buf, nota->SystemID); + } + + xmlOutputBufferWrite(buf, 3, " >\n"); +} + +/** + * xmlBufDumpNotationDeclScan: + * @nota: A notation declaration + * @buf: the XML buffer output + * + * This is called with the hash scan function, and just reverses args + */ +static void +xmlBufDumpNotationDeclScan(void *nota, void *buf, + const xmlChar *name ATTRIBUTE_UNUSED) { + xmlBufDumpNotationDecl((xmlOutputBufferPtr) buf, (xmlNotationPtr) nota); +} + /** * xmlBufDumpNotationTable: * @buf: an xmlBufPtr output @@ -422,19 +457,105 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr) * This will dump the content of the notation table as an XML DTD definition */ static void -xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) { - xmlBufferPtr buffer; - - buffer = xmlBufferCreate(); - if (buffer == NULL) { - /* - * TODO set the error in buf - */ - return; +xmlBufDumpNotationTable(xmlOutputBufferPtr buf, xmlNotationTablePtr table) { + xmlHashScan(table, xmlBufDumpNotationDeclScan, buf); +} + +/** + * xmlBufDumpElementOccur: + * @buf: output buffer + * @cur: element table + * + * Dump the occurrence operator of an element. + */ +static void +xmlBufDumpElementOccur(xmlOutputBufferPtr buf, xmlElementContentPtr cur) { + switch (cur->ocur) { + case XML_ELEMENT_CONTENT_ONCE: + break; + case XML_ELEMENT_CONTENT_OPT: + xmlOutputBufferWrite(buf, 1, "?"); + break; + case XML_ELEMENT_CONTENT_MULT: + xmlOutputBufferWrite(buf, 1, "*"); + break; + case XML_ELEMENT_CONTENT_PLUS: + xmlOutputBufferWrite(buf, 1, "+"); + break; } - xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); - xmlDumpNotationTable(buffer, table); - xmlBufMergeBuffer(buf, buffer); +} + +/** + * xmlBufDumpElementContent: + * @buf: output buffer + * @content: element table + * + * This will dump the content of the element table as an XML DTD definition + */ +static void +xmlBufDumpElementContent(xmlOutputBufferPtr buf, + xmlElementContentPtr content) { + xmlElementContentPtr cur; + + if (content == NULL) return; + + xmlOutputBufferWrite(buf, 1, "("); + cur = content; + + do { + if (cur == NULL) return; + + switch (cur->type) { + case XML_ELEMENT_CONTENT_PCDATA: + xmlOutputBufferWrite(buf, 7, "#PCDATA"); + break; + case XML_ELEMENT_CONTENT_ELEMENT: + if (cur->prefix != NULL) { + xmlOutputBufferWriteString(buf, + (const char *) cur->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *) cur->name); + break; + case XML_ELEMENT_CONTENT_SEQ: + case XML_ELEMENT_CONTENT_OR: + if ((cur != content) && + (cur->parent != NULL) && + ((cur->type != cur->parent->type) || + (cur->ocur != XML_ELEMENT_CONTENT_ONCE))) + xmlOutputBufferWrite(buf, 1, "("); + cur = cur->c1; + continue; + } + + while (cur != content) { + xmlElementContentPtr parent = cur->parent; + + if (parent == NULL) return; + + if (((cur->type == XML_ELEMENT_CONTENT_OR) || + (cur->type == XML_ELEMENT_CONTENT_SEQ)) && + ((cur->type != parent->type) || + (cur->ocur != XML_ELEMENT_CONTENT_ONCE))) + xmlOutputBufferWrite(buf, 1, ")"); + xmlBufDumpElementOccur(buf, cur); + + if (cur == parent->c1) { + if (parent->type == XML_ELEMENT_CONTENT_SEQ) + xmlOutputBufferWrite(buf, 3, " , "); + else if (parent->type == XML_ELEMENT_CONTENT_OR) + xmlOutputBufferWrite(buf, 3, " | "); + + cur = parent->c2; + break; + } + + cur = parent; + } + } while (cur != content); + + xmlOutputBufferWrite(buf, 1, ")"); + xmlBufDumpElementOccur(buf, content); } /** @@ -446,43 +567,173 @@ xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) { * DTD definition */ static void -xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) { - xmlBufferPtr buffer; - - buffer = xmlBufferCreate(); - if (buffer == NULL) { - /* - * TODO set the error in buf - */ - return; +xmlBufDumpElementDecl(xmlOutputBufferPtr buf, xmlElementPtr elem) { + xmlOutputBufferWrite(buf, 10, "prefix != NULL) { + xmlOutputBufferWriteString(buf, (const char *) elem->prefix); + xmlOutputBufferWrite(buf, 1, ":"); } - xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); - xmlDumpElementDecl(buffer, elem); - xmlBufMergeBuffer(buf, buffer); + xmlOutputBufferWriteString(buf, (const char *) elem->name); + xmlOutputBufferWrite(buf, 1, " "); + + switch (elem->etype) { + case XML_ELEMENT_TYPE_EMPTY: + xmlOutputBufferWrite(buf, 5, "EMPTY"); + break; + case XML_ELEMENT_TYPE_ANY: + xmlOutputBufferWrite(buf, 3, "ANY"); + break; + case XML_ELEMENT_TYPE_MIXED: + case XML_ELEMENT_TYPE_ELEMENT: + xmlBufDumpElementContent(buf, elem->content); + break; + default: + /* assert(0); */ + break; + } + + xmlOutputBufferWrite(buf, 2, ">\n"); } +/** + * xmlBufDumpEnumeration: + * @buf: output buffer + * @enum: An enumeration + * + * This will dump the content of the enumeration + */ +static void +xmlBufDumpEnumeration(xmlOutputBufferPtr buf, xmlEnumerationPtr cur) { + while (cur != NULL) { + xmlOutputBufferWriteString(buf, (const char *) cur->name); + if (cur->next != NULL) + xmlOutputBufferWrite(buf, 3, " | "); + + cur = cur->next; + } + + xmlOutputBufferWrite(buf, 1, ")"); +} /** * xmlBufDumpAttributeDecl: - * @buf: an xmlBufPtr output + * @buf: output buffer * @attr: An attribute declaration * * This will dump the content of the attribute declaration as an XML * DTD definition */ static void -xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) { - xmlBufferPtr buffer; - - buffer = xmlBufferCreate(); - if (buffer == NULL) { - /* - * TODO set the error in buf - */ - return; +xmlBufDumpAttributeDecl(xmlOutputBufferPtr buf, xmlAttributePtr attr) { + xmlOutputBufferWrite(buf, 10, "elem); + xmlOutputBufferWrite(buf, 1, " "); + if (attr->prefix != NULL) { + xmlOutputBufferWriteString(buf, (const char *) attr->prefix); + xmlOutputBufferWrite(buf, 1, ":"); + } + xmlOutputBufferWriteString(buf, (const char *) attr->name); + + switch (attr->atype) { + case XML_ATTRIBUTE_CDATA: + xmlOutputBufferWrite(buf, 6, " CDATA"); + break; + case XML_ATTRIBUTE_ID: + xmlOutputBufferWrite(buf, 3, " ID"); + break; + case XML_ATTRIBUTE_IDREF: + xmlOutputBufferWrite(buf, 6, " IDREF"); + break; + case XML_ATTRIBUTE_IDREFS: + xmlOutputBufferWrite(buf, 7, " IDREFS"); + break; + case XML_ATTRIBUTE_ENTITY: + xmlOutputBufferWrite(buf, 7, " ENTITY"); + break; + case XML_ATTRIBUTE_ENTITIES: + xmlOutputBufferWrite(buf, 9, " ENTITIES"); + break; + case XML_ATTRIBUTE_NMTOKEN: + xmlOutputBufferWrite(buf, 8, " NMTOKEN"); + break; + case XML_ATTRIBUTE_NMTOKENS: + xmlOutputBufferWrite(buf, 9, " NMTOKENS"); + break; + case XML_ATTRIBUTE_ENUMERATION: + xmlOutputBufferWrite(buf, 2, " ("); + xmlBufDumpEnumeration(buf, attr->tree); + break; + case XML_ATTRIBUTE_NOTATION: + xmlOutputBufferWrite(buf, 11, " NOTATION ("); + xmlBufDumpEnumeration(buf, attr->tree); + break; + default: + /* assert(0); */ + break; + } + + switch (attr->def) { + case XML_ATTRIBUTE_NONE: + break; + case XML_ATTRIBUTE_REQUIRED: + xmlOutputBufferWrite(buf, 10, " #REQUIRED"); + break; + case XML_ATTRIBUTE_IMPLIED: + xmlOutputBufferWrite(buf, 9, " #IMPLIED"); + break; + case XML_ATTRIBUTE_FIXED: + xmlOutputBufferWrite(buf, 7, " #FIXED"); + break; + default: + /* assert(0); */ + break; + } + + if (attr->defaultValue != NULL) { + xmlOutputBufferWrite(buf, 1, " "); + xmlOutputBufferWriteQuotedString(buf, attr->defaultValue); + } + + xmlOutputBufferWrite(buf, 2, ">\n"); +} + +/** + * xmlBufDumpEntityContent: + * @buf: output buffer + * @content: entity content. + * + * This will dump the quoted string value, taking care of the special + * treatment required by % + */ +static void +xmlBufDumpEntityContent(xmlOutputBufferPtr buf, const xmlChar *content) { + if (xmlStrchr(content, '%')) { + const char * base, *cur; + + xmlOutputBufferWrite(buf, 1, "\""); + base = cur = (const char *) content; + while (*cur != 0) { + if (*cur == '"') { + if (base != cur) + xmlOutputBufferWrite(buf, cur - base, base); + xmlOutputBufferWrite(buf, 6, """); + cur++; + base = cur; + } else if (*cur == '%') { + if (base != cur) + xmlOutputBufferWrite(buf, cur - base, base); + xmlOutputBufferWrite(buf, 6, "%"); + cur++; + base = cur; + } else { + cur++; + } + } + if (base != cur) + xmlOutputBufferWrite(buf, cur - base, base); + xmlOutputBufferWrite(buf, 1, "\""); + } else { + xmlOutputBufferWriteQuotedString(buf, content); } - xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); - xmlDumpAttributeDecl(buffer, attr); - xmlBufMergeBuffer(buf, buffer); } /** @@ -493,19 +744,47 @@ xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) { * This will dump the content of the entity table as an XML DTD definition */ static void -xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) { - xmlBufferPtr buffer; - - buffer = xmlBufferCreate(); - if (buffer == NULL) { - /* - * TODO set the error in buf - */ - return; +xmlBufDumpEntityDecl(xmlOutputBufferPtr buf, xmlEntityPtr ent) { + if ((ent->etype == XML_INTERNAL_PARAMETER_ENTITY) || + (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY)) + xmlOutputBufferWrite(buf, 11, "name); + xmlOutputBufferWrite(buf, 1, " "); + + if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) || + (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) || + (ent->etype == XML_EXTERNAL_PARAMETER_ENTITY)) { + if (ent->ExternalID != NULL) { + xmlOutputBufferWrite(buf, 7, "PUBLIC "); + xmlOutputBufferWriteQuotedString(buf, ent->ExternalID); + xmlOutputBufferWrite(buf, 1, " "); + } else { + xmlOutputBufferWrite(buf, 7, "SYSTEM "); + } + xmlOutputBufferWriteQuotedString(buf, ent->SystemID); + } + + if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) { + if (ent->content != NULL) { /* Should be true ! */ + xmlOutputBufferWrite(buf, 7, " NDATA "); + if (ent->orig != NULL) + xmlOutputBufferWriteString(buf, (const char *) ent->orig); + else + xmlOutputBufferWriteString(buf, (const char *) ent->content); + } + } + + if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) || + (ent->etype == XML_INTERNAL_PARAMETER_ENTITY)) { + if (ent->orig != NULL) + xmlOutputBufferWriteQuotedString(buf, ent->orig); + else + xmlBufDumpEntityContent(buf, ent->content); } - xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT); - xmlDumpEntityDecl(buffer, ent); - xmlBufMergeBuffer(buf, buffer); + + xmlOutputBufferWrite(buf, 2, ">\n"); } /************************************************************************ @@ -518,18 +797,21 @@ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) { xmlOutputBufferPtr buf = ctxt->buf; if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) { - buf->encoder = xmlFindCharEncodingHandler((const char *)encoding); - if (buf->encoder == NULL) { - xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, - (const char *)encoding); - return(-1); - } + xmlCharEncodingHandler *handler; + int res; + + res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler); + if (handler == NULL) { + xmlSaveErr(buf, res, NULL, encoding); + return(-1); + } buf->conv = xmlBufCreate(); if (buf->conv == NULL) { - xmlCharEncCloseFunc(buf->encoder); - xmlSaveErrMemory("creating encoding buffer"); + xmlCharEncCloseFunc(handler); + xmlSaveErrMemory(buf); return(-1); } + buf->encoder = handler; /* * initialize the state, e.g. if outputting a BOM */ @@ -588,7 +870,8 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra) * If @ctxt is supplied, @buf should be its buffer. */ static void -xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) { +xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur, + xmlSaveCtxtPtr ctxt) { if ((cur == NULL) || (buf == NULL)) return; if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) { if (xmlStrEqual(cur->prefix, BAD_CAST "xml")) @@ -605,24 +888,12 @@ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) { xmlOutputBufferWriteString(buf, (const char *)cur->prefix); } else xmlOutputBufferWrite(buf, 5, "xmlns"); - xmlOutputBufferWrite(buf, 1, "="); - xmlBufWriteQuotedString(buf->buffer, cur->href); + xmlOutputBufferWrite(buf, 2, "=\""); + xmlBufAttrSerializeTxtContent(buf, doc, cur->href); + xmlOutputBufferWrite(buf, 1, "\""); } } -/** - * xmlNsDumpOutputCtxt - * @ctxt: the save context - * @cur: a namespace - * - * Dump a local Namespace definition to a save context. - * Should be called in the context of attribute dumps. - */ -static void -xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { - xmlNsDumpOutput(ctxt->buf, cur, ctxt); -} - /** * xmlNsListDumpOutputCtxt * @ctxt: the save context @@ -632,9 +903,9 @@ xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { * Should be called in the context of attribute dumps. */ static void -xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { +xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlDocPtr doc, xmlNsPtr cur) { while (cur != NULL) { - xmlNsDumpOutput(ctxt->buf, cur, ctxt); + xmlNsDumpOutput(ctxt->buf, doc, cur, ctxt); cur = cur->next; } } @@ -650,7 +921,7 @@ xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { while (cur != NULL) { - xmlNsDumpOutput(buf, cur, NULL); + xmlNsDumpOutput(buf, NULL, cur, NULL); cur = cur->next; } } @@ -676,12 +947,12 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) { xmlOutputBufferWriteString(buf, (const char *)dtd->name); if (dtd->ExternalID != NULL) { xmlOutputBufferWrite(buf, 8, " PUBLIC "); - xmlBufWriteQuotedString(buf->buffer, dtd->ExternalID); + xmlOutputBufferWriteQuotedString(buf, dtd->ExternalID); xmlOutputBufferWrite(buf, 1, " "); - xmlBufWriteQuotedString(buf->buffer, dtd->SystemID); + xmlOutputBufferWriteQuotedString(buf, dtd->SystemID); } else if (dtd->SystemID != NULL) { xmlOutputBufferWrite(buf, 8, " SYSTEM "); - xmlBufWriteQuotedString(buf->buffer, dtd->SystemID); + xmlOutputBufferWriteQuotedString(buf, dtd->SystemID); } if ((dtd->entities == NULL) && (dtd->elements == NULL) && (dtd->attributes == NULL) && (dtd->notations == NULL) && @@ -696,8 +967,7 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) { */ if ((dtd->notations != NULL) && ((dtd->doc == NULL) || (dtd->doc->intSubset == dtd))) { - xmlBufDumpNotationTable(buf->buffer, - (xmlNotationTablePtr) dtd->notations); + xmlBufDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations); } format = ctxt->format; level = ctxt->level; @@ -735,7 +1005,19 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { } xmlOutputBufferWriteString(buf, (const char *)cur->name); xmlOutputBufferWrite(buf, 2, "=\""); - xmlAttrSerializeContent(buf, cur); +#ifdef LIBXML_HTML_ENABLED + if ((ctxt->options & XML_SAVE_XHTML) && + (cur->ns == NULL) && + ((cur->children == NULL) || + (cur->children->content == NULL) || + (cur->children->content[0] == 0)) && + (htmlIsBooleanAttr(cur->name))) { + xmlOutputBufferWriteString(buf, (const char *) cur->name); + } else +#endif + { + xmlAttrSerializeContent(buf, cur); + } xmlOutputBufferWrite(buf, 1, "\""); } @@ -839,15 +1121,15 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_ELEMENT_DECL: - xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + xmlBufDumpElementDecl(buf, (xmlElementPtr) cur); break; case XML_ATTRIBUTE_DECL: - xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur); break; case XML_ENTITY_DECL: - xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur); break; case XML_ELEMENT_NODE: @@ -875,7 +1157,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { } xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef); for (attr = cur->properties; attr != NULL; attr = attr->next) xmlAttrDumpOutput(ctxt, attr); @@ -1015,7 +1297,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_NAMESPACE_DECL: - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt); break; default: @@ -1164,12 +1446,12 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { if ((ctxt->options & XML_SAVE_NO_DECL) == 0) { xmlOutputBufferWrite(buf, 14, "version != NULL) - xmlBufWriteQuotedString(buf->buffer, cur->version); + xmlOutputBufferWriteQuotedString(buf, cur->version); else xmlOutputBufferWrite(buf, 5, "\"1.0\""); if (encoding != NULL) { xmlOutputBufferWrite(buf, 10, " encoding="); - xmlBufWriteQuotedString(buf->buffer, (xmlChar *) encoding); + xmlOutputBufferWriteQuotedString(buf, (xmlChar *) encoding); } switch (cur->standalone) { case 0: @@ -1249,7 +1531,7 @@ xhtmlIsEmpty(xmlNodePtr node) { return(0); if (node->children != NULL) return(0); - switch (node->name[0]) { + switch (node->name ? node->name[0] : 0) { case 'a': if (xmlStrEqual(node->name, BAD_CAST "area")) return(1); @@ -1329,17 +1611,6 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) && (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml"))) xml_lang = cur; - else if ((cur->ns == NULL) && - ((cur->children == NULL) || - (cur->children->content == NULL) || - (cur->children->content[0] == 0)) && - (htmlIsBooleanAttr(cur->name))) { - if (cur->children != NULL) - xmlFreeNode(cur->children); - cur->children = xmlNewDocText(cur->doc, cur->name); - if (cur->children != NULL) - cur->children->parent = (xmlNodePtr) cur; - } xmlAttrDumpOutput(ctxt, cur); cur = cur->next; } @@ -1390,13 +1661,16 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { */ static void xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { - int format = ctxt->format, addmeta; + int format = ctxt->format, addmeta, oldoptions; xmlNodePtr tmp, root, unformattedNode = NULL, parent; xmlChar *start, *end; xmlOutputBufferPtr buf = ctxt->buf; if (cur == NULL) return; + oldoptions = ctxt->options; + ctxt->options |= XML_SAVE_XHTML; + root = cur; parent = cur->parent; while (1) { @@ -1407,7 +1681,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_NAMESPACE_DECL: - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt); break; case XML_DTD_NODE: @@ -1424,15 +1698,15 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_ELEMENT_DECL: - xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur); + xmlBufDumpElementDecl(buf, (xmlElementPtr) cur); break; case XML_ATTRIBUTE_DECL: - xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); + xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur); break; case XML_ENTITY_DECL: - xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); + xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur); break; case XML_ELEMENT_NODE: @@ -1462,7 +1736,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef); if ((xmlStrEqual(cur->name, BAD_CAST "html") && (cur->ns == NULL) && (cur->nsDef == NULL))) { /* @@ -1707,6 +1981,8 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { } } } + + ctxt->options = oldoptions; } #endif @@ -1888,6 +2164,40 @@ xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) return(ret); } +/** + * xmlSaveNotationDecl: + * @ctxt: save context + * @cur: notation + * + * Serialize a notation declaration. + * + * Return 0 on succes, -1 on error. + */ +int +xmlSaveNotationDecl(xmlSaveCtxtPtr ctxt, xmlNotationPtr cur) { + if (ctxt == NULL) + return(-1); + xmlBufDumpNotationDecl(ctxt->buf, cur); + return(0); +} + +/** + * xmlSaveNotationTable: + * @ctxt: save context + * @cur: notation table + * + * Serialize notation declarations of a document. + * + * Return 0 on succes, -1 on error. + */ +int +xmlSaveNotationTable(xmlSaveCtxtPtr ctxt, xmlNotationTablePtr cur) { + if (ctxt == NULL) + return(-1); + xmlBufDumpNotationTable(ctxt->buf, cur); + return(0); +} + /** * xmlSaveFlush: * @ctxt: a document saving context @@ -1925,6 +2235,30 @@ xmlSaveClose(xmlSaveCtxtPtr ctxt) return(ret); } +/** + * xmlSaveFinish: + * @ctxt: a document saving context + * + * Close a document saving context, i.e. make sure that all bytes have + * been output and free the associated data. + * + * Available since 2.13.0. + * + * Returns an xmlParserErrors code. + */ +int +xmlSaveFinish(xmlSaveCtxtPtr ctxt) +{ + int ret; + + if (ctxt == NULL) + return(XML_ERR_INTERNAL_ERROR); + xmlSaveFlush(ctxt); + ret = ctxt->buf->error; + xmlFreeSaveCtxt(ctxt); + return(ret); +} + /** * xmlSaveSetEscape: * @ctxt: a document saving context @@ -1967,63 +2301,62 @@ xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape) /** * xmlBufAttrSerializeTxtContent: - * @buf: and xmlBufPtr output + * @buf: output buffer * @doc: the document - * @attr: the attribute node * @string: the text content * * Serialize text attribute values to an xmlBufPtr */ void -xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc, - xmlAttrPtr attr, const xmlChar * string) +xmlBufAttrSerializeTxtContent(xmlOutputBufferPtr buf, xmlDocPtr doc, + const xmlChar *string) { - xmlChar *base, *cur; + const xmlChar *base, *cur; if (string == NULL) return; - base = cur = (xmlChar *) string; + base = cur = string; while (*cur != 0) { if (*cur == '\n') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST " ", 5); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 5, " "); cur++; base = cur; } else if (*cur == '\r') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST " ", 5); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 5, " "); cur++; base = cur; } else if (*cur == '\t') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST " ", 4); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 4, " "); cur++; base = cur; } else if (*cur == '"') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST """, 6); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 6, """); cur++; base = cur; } else if (*cur == '<') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST "<", 4); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 4, "<"); cur++; base = cur; } else if (*cur == '>') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST ">", 4); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 4, ">"); cur++; base = cur; } else if (*cur == '&') { if (base != cur) - xmlBufAdd(buf, base, cur - base); - xmlBufAdd(buf, BAD_CAST "&", 5); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + xmlOutputBufferWrite(buf, 5, "&"); cur++; base = cur; } else if ((*cur >= 0x80) && (cur[1] != 0) && @@ -2032,61 +2365,34 @@ xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc, * We assume we have UTF-8 content. */ unsigned char tmp[12]; - int val = 0, l = 1; + int val = 0, l = 4; if (base != cur) - xmlBufAdd(buf, base, cur - base); - if (*cur < 0xC0) { - xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL); - xmlSerializeHexCharRef(tmp, *cur); - xmlBufAdd(buf, (xmlChar *) tmp, -1); - cur++; - base = cur; - continue; - } else if (*cur < 0xE0) { - val = (cur[0]) & 0x1F; - val <<= 6; - val |= (cur[1]) & 0x3F; - l = 2; - } else if ((*cur < 0xF0) && (cur [2] != 0)) { - val = (cur[0]) & 0x0F; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - l = 3; - } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) { - val = (cur[0]) & 0x07; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - val <<= 6; - val |= (cur[3]) & 0x3F; - l = 4; - } - if ((l == 1) || (!IS_CHAR(val))) { - xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL); - xmlSerializeHexCharRef(tmp, *cur); - xmlBufAdd(buf, (xmlChar *) tmp, -1); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); + + val = xmlGetUTF8Char(cur, &l); + if (val < 0) { + val = 0xFFFD; cur++; - base = cur; - continue; + } else { + if (!IS_CHAR(val)) + val = 0xFFFD; + cur += l; } + /* * We could do multiple things here. Just save * as a char ref */ xmlSerializeHexCharRef(tmp, val); - xmlBufAdd(buf, (xmlChar *) tmp, -1); - cur += l; + xmlOutputBufferWriteString(buf, (const char *) tmp); base = cur; } else { cur++; } } if (base != cur) - xmlBufAdd(buf, base, cur - base); + xmlOutputBufferWrite(buf, cur - base, (const char *) base); } /** @@ -2100,17 +2406,19 @@ xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc, */ void xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc, - xmlAttrPtr attr, const xmlChar * string) + xmlAttrPtr attr ATTRIBUTE_UNUSED, + const xmlChar *string) { - xmlBufPtr buffer; + xmlOutputBufferPtr out; if ((buf == NULL) || (string == NULL)) return; - buffer = xmlBufFromBuffer(buf); - if (buffer == NULL) - return; - xmlBufAttrSerializeTxtContent(buffer, doc, attr, string); - xmlBufBackToBuffer(buffer); + out = xmlOutputBufferCreateBuffer(buf, NULL); + xmlBufAttrSerializeTxtContent(out, doc, string); + xmlOutputBufferFlush(out); + if ((out == NULL) || (out->error)) + xmlFree(xmlBufferDetach(buf)); + xmlOutputBufferClose(out); } /** @@ -2138,6 +2446,10 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, if ((buf == NULL) || (cur == NULL)) return(-1); + if (level < 0) + level = 0; + else if (level > 100) + level = 100; buffer = xmlBufFromBuffer(buf); if (buffer == NULL) return(-1); @@ -2169,22 +2481,22 @@ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format) { size_t use; - int ret; + size_t ret; xmlOutputBufferPtr outbuf; int oldalloc; xmlInitParser(); if (cur == NULL) { - return (-1); + return ((size_t) -1); } if (buf == NULL) { - return (-1); + return ((size_t) -1); } outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); if (outbuf == NULL) { - xmlSaveErrMemory("creating buffer"); - return (-1); + xmlSaveErrMemory(NULL); + return ((size_t) -1); } memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer)); outbuf->buffer = buf; @@ -2199,8 +2511,11 @@ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL); xmlBufSetAllocationScheme(buf, oldalloc); + if (outbuf->error) + ret = (size_t) -1; + else + ret = xmlBufUse(buf) - use; xmlFree(outbuf); - ret = xmlBufUse(buf) - use; return (ret); } @@ -2226,13 +2541,11 @@ xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur) outbuf = xmlOutputBufferCreateFile(f, NULL); if (outbuf == NULL) return; - if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { #ifdef LIBXML_HTML_ENABLED + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) htmlNodeDumpOutput(outbuf, doc, cur, NULL); -#else - xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n"); + else #endif /* LIBXML_HTML_ENABLED */ - } else xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL); xmlOutputBufferClose(outbuf); } @@ -2272,6 +2585,11 @@ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, if ((buf == NULL) || (cur == NULL)) return; + if (level < 0) + level = 0; + else if (level > 100) + level = 100; + if (encoding == NULL) encoding = "UTF-8"; @@ -2347,16 +2665,18 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, if (txt_encoding == NULL) txt_encoding = (const char *) out_doc->encoding; if (txt_encoding != NULL) { - conv_hdlr = xmlFindCharEncodingHandler(txt_encoding); - if ( conv_hdlr == NULL ) { - xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc, - txt_encoding); + int res; + + res = xmlOpenCharEncodingHandler(txt_encoding, /* output */ 1, + &conv_hdlr); + if (conv_hdlr == NULL) { + xmlSaveErr(NULL, res, NULL, txt_encoding); return; } } if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) { - xmlSaveErrMemory("creating buffer"); + xmlSaveErrMemory(NULL); xmlCharEncCloseFunc(conv_hdlr); return; } @@ -2370,21 +2690,18 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, ctxt.options |= XML_SAVE_AS_XML; xmlDocContentDumpOutput(&ctxt, out_doc); xmlOutputBufferFlush(out_buff); - if (out_buff->conv != NULL) { - *doc_txt_len = xmlBufUse(out_buff->conv); - *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len); - } else { - *doc_txt_len = xmlBufUse(out_buff->buffer); - *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len); - } - (void)xmlOutputBufferClose(out_buff); - if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) { - *doc_txt_len = 0; - xmlSaveErrMemory("creating output"); + if (!out_buff->error) { + if (out_buff->conv != NULL) { + *doc_txt_len = xmlBufUse(out_buff->conv); + *doc_txt_ptr = xmlBufDetach(out_buff->conv); + } else { + *doc_txt_len = xmlBufUse(out_buff->buffer); + *doc_txt_ptr = xmlBufDetach(out_buff->buffer); + } } - return; + xmlOutputBufferClose(out_buff); } /** @@ -2466,7 +2783,7 @@ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) { encoding = (const char *) cur->encoding; if (encoding != NULL) { - handler = xmlFindCharEncodingHandler(encoding); + xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler); if (handler == NULL) { xmlFree((char *) cur->encoding); cur->encoding = NULL; @@ -2603,10 +2920,9 @@ xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur, encoding = (const char *) cur->encoding; if (encoding != NULL) { - - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - return(-1); + xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler); + if (handler == NULL) + return(-1); } #ifdef LIBXML_ZLIB_ENABLED diff --git a/xmlschemas.c b/xmlschemas.c index d276faf..48b4e32 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -96,10 +96,6 @@ #endif #define UNBOUNDED (1 << 30) -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##" @@ -1898,22 +1894,6 @@ xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt, * * ************************************************************************/ -#if 0 -static void -xmlSchemaErrMemory(const char *msg) -{ - __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, - msg); -} -#endif - -static void -xmlSchemaPSimpleErr(const char *msg) -{ - __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, - msg); -} - /** * xmlSchemaPErrMemory: * @node: a context node @@ -1922,13 +1902,66 @@ xmlSchemaPSimpleErr(const char *msg) * Handle an out of memory condition */ static void -xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt, - const char *extra, xmlNodePtr node) +xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt) { - if (ctxt != NULL) + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + + if (ctxt != NULL) { ctxt->nberrors++; - __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL, - extra); + ctxt->err = XML_ERR_NO_MEMORY; + channel = ctxt->error; + schannel = ctxt->serror; + data = ctxt->errCtxt; + } + + xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASP, NULL); +} + +static void LIBXML_ATTR_FORMAT(11,12) +xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code, + xmlErrorLevel level, const char *file, int line, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int col, const char *msg, ...) { + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + int res; + va_list ap; + + if (ctxt != NULL) { + /* Don't overwrite memory errors */ + if (ctxt->err == XML_ERR_NO_MEMORY) + return; + + if (level == XML_ERR_WARNING) { + channel = ctxt->warning; + } else { + ctxt->nberrors++; + ctxt->err = code; + channel = ctxt->error; + } + data = ctxt->errCtxt; + schannel = ctxt->serror; + } + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + va_start(ap, msg); + res = xmlVRaiseError(schannel, channel, data, ctxt, node, + XML_FROM_SCHEMASP, code, level, file, line, + (const char *) str1, + (const char *) str2, + (const char *) str3, + 0, col, msg, ap); + va_end(ap); + + if (res < 0) + xmlSchemaPErrMemory(ctxt); } /** @@ -1943,24 +1976,11 @@ xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt, * Handle a parser error */ static void LIBXML_ATTR_FORMAT(4,0) -xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, +xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code, const char *msg, const xmlChar * str1, const xmlChar * str2) { - xmlGenericErrorFunc channel = NULL; - xmlStructuredErrorFunc schannel = NULL; - void *data = NULL; - - if (ctxt != NULL) { - ctxt->nberrors++; - ctxt->err = error; - channel = ctxt->error; - data = ctxt->errCtxt; - schannel = ctxt->serror; - } - __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, - error, XML_ERR_ERROR, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, str1, str2); + xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -2005,29 +2025,15 @@ xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, * Handle a parser error */ static void LIBXML_ATTR_FORMAT(7,0) -xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, +xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code, const xmlChar * strData1, const xmlChar * strData2, const xmlChar * strData3, const char *msg, const xmlChar * str1, const xmlChar * str2, const xmlChar * str3, const xmlChar * str4, const xmlChar * str5) { - - xmlGenericErrorFunc channel = NULL; - xmlStructuredErrorFunc schannel = NULL; - void *data = NULL; - - if (ctxt != NULL) { - ctxt->nberrors++; - ctxt->err = error; - channel = ctxt->error; - data = ctxt->errCtxt; - schannel = ctxt->serror; - } - __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, - error, XML_ERR_ERROR, NULL, 0, - (const char *) strData1, (const char *) strData2, - (const char *) strData3, 0, 0, msg, str1, str2, - str3, str4, str5); + xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0, + strData1, strData2, strData3, 0, + msg, str1, str2, str3, str4, str5); } /************************************************************************ @@ -2044,23 +2050,66 @@ xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, * Handle an out of memory condition */ static void -xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt, - const char *extra, xmlNodePtr node) +xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt) { + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + if (ctxt != NULL) { ctxt->nberrors++; - ctxt->err = XML_SCHEMAV_INTERNAL; + ctxt->err = XML_ERR_NO_MEMORY; + channel = ctxt->error; + schannel = ctxt->serror; + data = ctxt->errCtxt; } - __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL, - extra); + + xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASV, NULL); } -static void LIBXML_ATTR_FORMAT(2,0) -xmlSchemaPSimpleInternalErr(xmlNodePtr node, - const char *msg, const xmlChar *str) -{ - __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node, - msg, (const char *) str); +static void LIBXML_ATTR_FORMAT(11,12) +xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int code, + xmlErrorLevel level, const char *file, int line, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int col, const char *msg, ...) { + xmlGenericErrorFunc channel = NULL; + xmlStructuredErrorFunc schannel = NULL; + void *data = NULL; + int res; + va_list ap; + + if (ctxt != NULL) { + /* Don't overwrite memory errors */ + if (ctxt->err == XML_ERR_NO_MEMORY) + return; + + if (level == XML_ERR_WARNING) { + channel = ctxt->warning; + } else { + ctxt->nberrors++; + ctxt->err = code; + channel = ctxt->error; + } + data = ctxt->errCtxt; + schannel = ctxt->serror; + } + + if ((channel == NULL) && (schannel == NULL)) { + channel = xmlGenericError; + data = xmlGenericErrorContext; + } + + va_start(ap, msg); + res = xmlVRaiseError(schannel, channel, data, ctxt, node, + XML_FROM_SCHEMASV, code, level, file, line, + (const char *) str1, + (const char *) str2, + (const char *) str3, + 0, col, msg, ap); + va_end(ap); + + if (res < 0) + xmlSchemaVErrMemory(ctxt); } #define WXS_ERROR_TYPE_ERROR 1 @@ -2083,28 +2132,15 @@ xmlSchemaPSimpleInternalErr(xmlNodePtr node, static void LIBXML_ATTR_FORMAT(6,0) xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, xmlErrorLevel errorLevel, - int error, xmlNodePtr node, int line, const char *msg, + int code, xmlNodePtr node, int line, const char *msg, const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, const xmlChar *str4) { - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - void *data = NULL; - if (ctxt != NULL) { if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; const char *file = NULL; int col = 0; - if (errorLevel != XML_ERR_WARNING) { - vctxt->nberrors++; - vctxt->err = error; - channel = vctxt->error; - } else { - channel = vctxt->warning; - } - schannel = vctxt->serror; - data = vctxt->errCtxt; /* * Error node. If we specify a line number, then @@ -2161,30 +2197,15 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, if ((file == NULL) && (vctxt->filename != NULL)) file = vctxt->filename; - __xmlRaiseError(schannel, channel, data, ctxt, - node, XML_FROM_SCHEMASV, - error, errorLevel, file, line, - (const char *) str1, (const char *) str2, - (const char *) str3, 0, col, msg, str1, str2, str3, str4); - + xmlSchemaVErrFull(vctxt, node, code, errorLevel, + file, line, str1, str2, str3, col, + msg, str1, str2, str3, str4); } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) { xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt; - if (errorLevel != XML_ERR_WARNING) { - pctxt->nberrors++; - pctxt->err = error; - channel = pctxt->error; - } else { - channel = pctxt->warning; - } - schannel = pctxt->serror; - data = pctxt->errCtxt; - __xmlRaiseError(schannel, channel, data, ctxt, - node, XML_FROM_SCHEMASP, error, - errorLevel, NULL, 0, - (const char *) str1, (const char *) str2, - (const char *) str3, 0, 0, msg, str1, str2, str3, str4); - } else { - TODO + + xmlSchemaPErrFull(pctxt, node, code, errorLevel, + NULL, 0, str1, str2, str3, 0, + msg, str1, str2, str3, str4); } } } @@ -2305,7 +2326,7 @@ xmlSchemaFormatNodeForError(xmlChar ** msg, */ *msg = xmlStrdup(BAD_CAST ""); } else { - TODO + /* TODO */ return (NULL); } @@ -3322,7 +3343,7 @@ xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt) ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating schema", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchema)); @@ -3369,7 +3390,7 @@ xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating annotation", node); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaAnnot)); @@ -3384,8 +3405,7 @@ xmlSchemaItemListCreate(void) ret = xmlMalloc(sizeof(xmlSchemaItemList)); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating an item list structure", NULL); + xmlSchemaPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchemaItemList)); @@ -3412,7 +3432,7 @@ xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *)); if (tmp == NULL) { - xmlSchemaPErrMemory(NULL, "growing item list", NULL); + xmlSchemaPErrMemory(NULL); return(-1); } list->items = tmp; @@ -3433,7 +3453,7 @@ xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, list->items = (void **) xmlMalloc( initialSize * sizeof(void *)); if (list->items == NULL) { - xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + xmlSchemaPErrMemory(NULL); return(-1); } list->sizeItems = initialSize; @@ -3444,7 +3464,7 @@ xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, tmp = (void **) xmlRealloc(list->items, list->sizeItems * sizeof(void *)); if (tmp == NULL) { - xmlSchemaPErrMemory(NULL, "growing item list", NULL); + xmlSchemaPErrMemory(NULL); list->sizeItems /= 2; return(-1); } @@ -3463,7 +3483,7 @@ xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx) tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *)); if (tmp == NULL) { - xmlSchemaPErrMemory(NULL, "growing item list", NULL); + xmlSchemaPErrMemory(NULL); return(-1); } list->items = tmp; @@ -3497,7 +3517,7 @@ xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, list->items = (void **) xmlMalloc( initialSize * sizeof(void *)); if (list->items == NULL) { - xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); + xmlSchemaPErrMemory(NULL); return(-1); } list->sizeItems = initialSize; @@ -3506,7 +3526,7 @@ xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, list->items = (void **) xmlRealloc(list->items, list->sizeItems * sizeof(void *)); if (list->items == NULL) { - xmlSchemaPErrMemory(NULL, "growing item list", NULL); + xmlSchemaPErrMemory(NULL); list->sizeItems = 0; return(-1); } @@ -3531,11 +3551,8 @@ static int xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx) { int i; - if ((list->items == NULL) || (idx >= list->nbItems)) { - xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, " - "index error.\n"); + if ((list->items == NULL) || (idx >= list->nbItems)) return(-1); - } if (list->nbItems == 1) { /* TODO: Really free the list? */ @@ -3627,7 +3644,7 @@ xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt, size = sizeof(xmlSchemaImport); ret = (xmlSchemaBucketPtr) xmlMalloc(size); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL); + xmlSchemaPErrMemory(NULL); return(NULL); } memset(ret, 0, size); @@ -4155,13 +4172,8 @@ xmlSchemaComponentListFree(xmlSchemaItemListPtr list) case XML_SCHEMA_EXTRA_QNAMEREF: xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item); break; - default: { + default: /* TODO: This should never be hit. */ - xmlSchemaPSimpleInternalErr(NULL, - "Internal error: xmlSchemaComponentListFree, " - "unexpected component type '%s'\n", - (const xmlChar *) WXS_ITEM_TYPE_NAME(item)); - } break; } } @@ -4180,9 +4192,6 @@ xmlSchemaFree(xmlSchemaPtr schema) { if (schema == NULL) return; - /* @volatiles is not used anymore :-/ */ - if (schema->volatiles != NULL) - TODO /* * Note that those slots are not responsible for freeing * schema components anymore; this will now be done by @@ -4675,7 +4684,7 @@ xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) ret = xmlDictLookup(ctxt->dict, val, -1); xmlFree(val); if (ret == NULL) - xmlSchemaPErrMemory(ctxt, "getting node content", node); + xmlSchemaPErrMemory(ctxt); return(ret); } @@ -4934,7 +4943,7 @@ xmlSchemaGetNamedComponent(xmlSchemaPtr schema, return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema, name, targetNs)); default: - TODO + /* TODO */ return (NULL); } } @@ -5088,7 +5097,7 @@ xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "add annotation", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaNotation)); @@ -5125,7 +5134,7 @@ xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaAttribute)); @@ -5165,7 +5174,7 @@ xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt, ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse)); if (ret == NULL) { - xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL); + xmlSchemaPErrMemory(pctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaAttributeUse)); @@ -5194,8 +5203,7 @@ xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt, ret = (xmlSchemaRedefPtr) xmlMalloc(sizeof(xmlSchemaRedef)); if (ret == NULL) { - xmlSchemaPErrMemory(pctxt, - "allocating redefinition info", NULL); + xmlSchemaPErrMemory(pctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaRedef)); @@ -5239,7 +5247,7 @@ xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, ret = (xmlSchemaAttributeGroupPtr) xmlMalloc(sizeof(xmlSchemaAttributeGroup)); if (ret == NULL) { - xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL); + xmlSchemaPErrMemory(pctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaAttributeGroup)); @@ -5288,7 +5296,7 @@ xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating element", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaElement)); @@ -5330,7 +5338,7 @@ xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating type", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaType)); @@ -5366,8 +5374,7 @@ xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt, ret = (xmlSchemaQNameRefPtr) xmlMalloc(sizeof(xmlSchemaQNameRef)); if (ret == NULL) { - xmlSchemaPErrMemory(pctxt, - "allocating QName reference item", NULL); + xmlSchemaPErrMemory(pctxt); return (NULL); } ret->node = NULL; @@ -5391,8 +5398,7 @@ xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt) ret = (xmlSchemaAttributeUseProhibPtr) xmlMalloc(sizeof(xmlSchemaAttributeUseProhib)); if (ret == NULL) { - xmlSchemaPErrMemory(pctxt, - "allocating attribute use prohibition", NULL); + xmlSchemaPErrMemory(pctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib)); @@ -5428,8 +5434,7 @@ xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, ret = (xmlSchemaModelGroupPtr) xmlMalloc(sizeof(xmlSchemaModelGroup)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating model group component", - NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaModelGroup)); @@ -5467,8 +5472,7 @@ xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, ret = (xmlSchemaParticlePtr) xmlMalloc(sizeof(xmlSchemaParticle)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating particle component", - NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } ret->type = XML_SCHEMA_TYPE_PARTICLE; @@ -5514,7 +5518,7 @@ xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "adding group", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaModelGroupDef)); @@ -5553,7 +5557,7 @@ xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt) ret = (xmlSchemaWildcardNsPtr) xmlMalloc(sizeof(xmlSchemaWildcardNs)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } ret->value = NULL; @@ -5573,8 +5577,7 @@ xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, - "allocating an identity-constraint definition", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaIDC)); @@ -5614,7 +5617,7 @@ xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); if (ret == NULL) { - xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(ret, 0, sizeof(xmlSchemaWildcard)); @@ -5655,8 +5658,7 @@ xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt, /* Create a new substitution group. */ ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup)); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating a substitution group container", NULL); + xmlSchemaPErrMemory(NULL); return(NULL); } memset(ret, 0, sizeof(xmlSchemaSubstGroup)); @@ -5896,8 +5898,8 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) * NOTE: the IDness might have already be declared in the DTD */ if (attr->atype != XML_ATTRIBUTE_ID) { - xmlIDPtr res; xmlChar *strip; + int res; /* * TODO: Use xmlSchemaStrip here; it's not exported at this @@ -5908,8 +5910,10 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) xmlFree((xmlChar *) value); value = strip; } - res = xmlAddID(NULL, attr->doc, value, attr); - if (res == NULL) { + res = xmlAddIDSafe(attr, value); + if (res < 0) { + xmlSchemaPErrMemory(ctxt); + } else if (res == 0) { ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, @@ -5917,8 +5921,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), NULL, NULL, "Duplicate value '%s' of simple " "type 'xs:ID'", value, NULL); - } else - attr->atype = XML_ATTRIBUTE_ID; + } } } else if (ret > 0) { ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; @@ -6607,7 +6610,7 @@ xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, facet = xmlSchemaNewFacet(); if (facet == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating facet", node); + xmlSchemaPErrMemory(ctxt); return (NULL); } facet->node = node; @@ -8017,8 +8020,7 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, nsArray = (const xmlChar **) xmlMalloc( (count * 2 + 1) * sizeof(const xmlChar *)); if (nsArray == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating a namespace array", - NULL); + xmlSchemaPErrMemory(ctxt); xmlFree(nsList); return (-1); } @@ -8061,7 +8063,7 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, return (annot); \ } \ cur = item->annot; \ - if (cur->next != NULL) { \ + while (cur->next != NULL) { \ cur = cur->next; \ } \ cur->next = annot; @@ -8205,9 +8207,7 @@ xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt, */ item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect)); if (item == NULL) { - xmlSchemaPErrMemory(ctxt, - "allocating a 'selector' of an identity-constraint definition", - NULL); + xmlSchemaPErrMemory(ctxt); return (NULL); } memset(item, 0, sizeof(xmlSchemaIDCSelect)); @@ -8884,8 +8884,7 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, break; tmp = xmlStrndup(cur, end - cur); if (tmp == NULL) { - xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " - "duplicating type name", NULL); + xmlSchemaPErrMemory(ctxt); return (-1); } if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, @@ -8896,8 +8895,7 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); if (link == NULL) { - xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " - "allocating a type link", NULL); + xmlSchemaPErrMemory(ctxt); FREE_AND_NULL(tmp) return (-1); } @@ -9831,7 +9829,7 @@ xmlSchemaSchemaRelationCreate(void) ret = (xmlSchemaSchemaRelationPtr) xmlMalloc(sizeof(xmlSchemaSchemaRelation)); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL); + xmlSchemaPErrMemory(NULL); return(NULL); } memset(ret, 0, sizeof(xmlSchemaSchemaRelation)); @@ -9888,23 +9886,20 @@ xmlSchemaConstructionCtxtCreate(xmlDictPtr dict) ret = (xmlSchemaConstructionCtxtPtr) xmlMalloc(sizeof(xmlSchemaConstructionCtxt)); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating schema construction context", NULL); + xmlSchemaPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchemaConstructionCtxt)); ret->buckets = xmlSchemaItemListCreate(); if (ret->buckets == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating list of schema buckets", NULL); + xmlSchemaPErrMemory(NULL); xmlFree(ret); return (NULL); } ret->pending = xmlSchemaItemListCreate(); if (ret->pending == NULL) { - xmlSchemaPErrMemory(NULL, - "allocating list of pending global components", NULL); + xmlSchemaPErrMemory(NULL); xmlSchemaConstructionCtxtFree(ret); return (NULL); } @@ -9920,8 +9915,7 @@ xmlSchemaParserCtxtCreate(void) ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); if (ret == NULL) { - xmlSchemaPErrMemory(NULL, "allocating schema parser context", - NULL); + xmlSchemaPErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchemaParserCtxt)); @@ -10506,10 +10500,13 @@ xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt, parserCtxt = xmlNewParserCtxt(); if (parserCtxt == NULL) { - xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, " - "allocating a parser context", NULL); + xmlSchemaPErrMemory(NULL); goto exit_failure; } + + if (pctxt->serror != NULL) + xmlCtxtSetErrorHandler(parserCtxt, pctxt->serror, pctxt->errCtxt); + if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { /* * TODO: Do we have to burden the schema parser dict with all @@ -11670,7 +11667,7 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink)); if (facetLink == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL); + xmlSchemaPErrMemory(ctxt); xmlFree(facetLink); return (NULL); } @@ -13117,8 +13114,7 @@ xmlSchemaBuildContentModel(xmlSchemaTypePtr type, ctxt->am = NULL; ctxt->am = xmlNewAutomata(); if (ctxt->am == NULL) { - xmlGenericError(xmlGenericErrorContext, - "Cannot create automata for complex type %s\n", type->name); + xmlSchemaPErrMemory(ctxt); return; } ctxt->state = xmlAutomataGetInitState(ctxt->am); @@ -13300,7 +13296,7 @@ xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt, while (memberType != NULL) { link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); if (link == NULL) { - xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL); + xmlSchemaPErrMemory(ctxt); return (-1); } link->type = memberType; @@ -17741,8 +17737,7 @@ xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, link = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink)); if (link == NULL) { - xmlSchemaPErrMemory(pctxt, - "deriving facets, creating a facet link", NULL); + xmlSchemaPErrMemory(pctxt); return (-1); } link->facet = cur->facet; @@ -17795,8 +17790,7 @@ xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt, newLink = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); if (newLink == NULL) { - xmlSchemaPErrMemory(pctxt, "allocating a type link", - NULL); + xmlSchemaPErrMemory(pctxt); return (-1); } newLink->type = subLink->type; @@ -18676,7 +18670,7 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet, PERROR_INT("xmlSchemaCheckFacet", "value was not computed"); } - TODO + /* TODO */ } break; } @@ -21353,6 +21347,8 @@ xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt) * @warn: the warning callback * @ctx: contextual data for the callbacks * + * DEPRECATED: Use xmlSchemaSetParserStructuredErrors. + * * Set the callback functions used to handle errors for a validation context */ void @@ -21929,9 +21925,7 @@ xmlSchemaAugmentIDC(void *payload, void *data, aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug)); if (aidc == NULL) { - xmlSchemaVErrMemory(vctxt, - "xmlSchemaAugmentIDC: allocating an augmented IDC definition", - NULL); + xmlSchemaVErrMemory(vctxt); return; } aidc->keyrefDepth = -1; @@ -21983,8 +21977,7 @@ xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef) ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc( sizeof(xmlSchemaPSVIIDCBinding)); if (ret == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating a PSVI IDC binding item", NULL); + xmlSchemaVErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding)); @@ -22014,8 +22007,7 @@ xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr)); if (vctxt->idcNodes == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating the IDC node table item list", NULL); + xmlSchemaVErrMemory(vctxt); return (-1); } vctxt->sizeIdcNodes = 20; @@ -22025,8 +22017,7 @@ xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); if (vctxt->idcNodes == NULL) { - xmlSchemaVErrMemory(vctxt, - "re-allocating the IDC node table item list", NULL); + xmlSchemaVErrMemory(vctxt); return (-1); } } @@ -22055,8 +22046,7 @@ xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr)); if (vctxt->idcKeys == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating the IDC key storage list", NULL); + xmlSchemaVErrMemory(vctxt); return (-1); } vctxt->sizeIdcKeys = 40; @@ -22066,8 +22056,7 @@ xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys * sizeof(xmlSchemaPSVIIDCKeyPtr)); if (vctxt->idcKeys == NULL) { - xmlSchemaVErrMemory(vctxt, - "re-allocating the IDC key storage list", NULL); + xmlSchemaVErrMemory(vctxt); return (-1); } } @@ -22094,8 +22083,7 @@ xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); if (bind->nodeTable == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an array of IDC node-table items", NULL); + xmlSchemaVErrMemory(NULL); return(-1); } } else if (bind->sizeNodes <= bind->nbNodes) { @@ -22104,8 +22092,7 @@ xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, xmlRealloc(bind->nodeTable, bind->sizeNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); if (bind->nodeTable == NULL) { - xmlSchemaVErrMemory(NULL, - "re-allocating an array of IDC node-table items", NULL); + xmlSchemaVErrMemory(NULL); return(-1); } } @@ -22365,8 +22352,7 @@ xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, */ sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj)); if (sto == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an IDC state object", NULL); + xmlSchemaVErrMemory(NULL); return (-1); } memset(sto, 0, sizeof(xmlSchemaIDCStateObj)); @@ -22454,8 +22440,7 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, if (sto->history == NULL) { sto->history = (int *) xmlMalloc(5 * sizeof(int)); if (sto->history == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating the state object history", NULL); + xmlSchemaVErrMemory(NULL); return(-1); } sto->sizeHistory = 5; @@ -22464,8 +22449,7 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, sto->history = (int *) xmlRealloc(sto->history, sto->sizeHistory * sizeof(int)); if (sto->history == NULL) { - xmlSchemaVErrMemory(NULL, - "re-allocating the state object history", NULL); + xmlSchemaVErrMemory(NULL); return(-1); } } @@ -22733,9 +22717,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, xmlMalloc(matcher->sizeKeySeqs * sizeof(xmlSchemaPSVIIDCKeyPtr *)); if (matcher->keySeqs == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an array of key-sequences", - NULL); + xmlSchemaVErrMemory(NULL); return(-1); } memset(matcher->keySeqs, 0, @@ -22750,9 +22732,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, matcher->sizeKeySeqs * sizeof(xmlSchemaPSVIIDCKeyPtr *)); if (matcher->keySeqs == NULL) { - xmlSchemaVErrMemory(NULL, - "reallocating an array of key-sequences", - NULL); + xmlSchemaVErrMemory(NULL); return (-1); } /* @@ -22802,8 +22782,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, matcher->aidc->def->nbFields * sizeof(xmlSchemaPSVIIDCKeyPtr)); if (keySeq == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an IDC key-sequence", NULL); + xmlSchemaVErrMemory(NULL); return(-1); } memset(keySeq, 0, matcher->aidc->def->nbFields * @@ -22817,8 +22796,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc( sizeof(xmlSchemaPSVIIDCKey)); if (key == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating a IDC key", NULL); + xmlSchemaVErrMemory(NULL); xmlFree(keySeq); matcher->keySeqs[pos] = NULL; return(-1); @@ -22980,8 +22958,7 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc( sizeof(xmlSchemaPSVIIDCNode)); if (ntItem == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an IDC node-table item", NULL); + xmlSchemaVErrMemory(NULL); xmlFree(*keySeq); *keySeq = NULL; return(-1); @@ -23200,8 +23177,7 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, matcher = (xmlSchemaIDCMatcherPtr) xmlMalloc(sizeof(xmlSchemaIDCMatcher)); if (matcher == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating an IDC matcher", NULL); + xmlSchemaVErrMemory(vctxt); return (-1); } memset(matcher, 0, sizeof(xmlSchemaIDCMatcher)); @@ -23613,8 +23589,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); if (parBind->nodeTable == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating IDC list of node-table items", NULL); + xmlSchemaVErrMemory(NULL); goto internal_error; } parBind->sizeNodes = 1; @@ -23624,8 +23599,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) xmlRealloc(parBind->nodeTable, parBind->sizeNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); if (parBind->nodeTable == NULL) { - xmlSchemaVErrMemory(NULL, - "re-allocating IDC list of node-table items", NULL); + xmlSchemaVErrMemory(NULL); goto internal_error; } } @@ -23678,9 +23652,7 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); if (parBind->nodeTable == NULL) { - xmlSchemaVErrMemory(NULL, - "allocating an array of IDC node-table " - "items", NULL); + xmlSchemaVErrMemory(NULL); xmlSchemaIDCFreeBinding(parBind); goto internal_error; } @@ -23889,8 +23861,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) xmlMalloc(sizeof(xmlSchemaAttrInfoPtr)); vctxt->sizeAttrInfos = 1; if (vctxt->attrInfos == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating attribute info list", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) { @@ -23899,8 +23870,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) xmlRealloc(vctxt->attrInfos, vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr)); if (vctxt->attrInfos == NULL) { - xmlSchemaVErrMemory(vctxt, - "re-allocating attribute info list", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } } else { @@ -23919,7 +23889,7 @@ xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) iattr = (xmlSchemaAttrInfoPtr) xmlMalloc(sizeof(xmlSchemaAttrInfo)); if (iattr == NULL) { - xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } memset(iattr, 0, sizeof(xmlSchemaAttrInfo)); @@ -24070,8 +24040,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr)); if (vctxt->elemInfos == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating the element info array", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr)); @@ -24084,8 +24053,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos * sizeof(xmlSchemaNodeInfoPtr)); if (vctxt->elemInfos == NULL) { - xmlSchemaVErrMemory(vctxt, - "re-allocating the element info array", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } /* @@ -24101,8 +24069,7 @@ xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) info = (xmlSchemaNodeInfoPtr) xmlMalloc(sizeof(xmlSchemaNodeInfo)); if (info == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating an element info", NULL); + xmlSchemaVErrMemory(vctxt); return (NULL); } vctxt->elemInfos[vctxt->depth] = info; @@ -24565,7 +24532,6 @@ xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, /* * Validation via a public API is not implemented yet. */ - TODO goto internal_error; } if (ret != 0) { @@ -25378,7 +25344,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) if (wildIDs != 0) { /* VAL TODO */ iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID; - TODO continue; } wildIDs++; @@ -25396,7 +25361,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) XML_SCHEMAS_ID)) { /* URGENT VAL TODO: implement */ iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID; - TODO break; } } @@ -25532,7 +25496,7 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) ns = xmlSearchNsByHref(defAttrOwnerElem->doc, defAttrOwnerElem, iattr->nsName); if (ns == NULL) { - xmlChar prefix[12]; + xmlChar prefix[13]; int counter = 0; /* @@ -25540,7 +25504,7 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) * root node if no namespace declaration is in scope. */ do { - snprintf((char *) prefix, 12, "p%d", counter++); + snprintf((char *) prefix, 13, "p%d", counter++); ns = xmlSearchNs(defAttrOwnerElem->doc, defAttrOwnerElem, BAD_CAST prefix); if (counter > 1000) { @@ -25650,14 +25614,12 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) */ if (iattr->val == NULL) { /* VAL TODO: A value was not precomputed. */ - TODO goto eval_idcs; } if ((iattr->use != NULL) && (iattr->use->defValue != NULL)) { if (iattr->use->defVal == NULL) { /* VAL TODO: A default value was not precomputed. */ - TODO goto eval_idcs; } iattr->vcValue = iattr->use->defValue; @@ -25672,7 +25634,6 @@ xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) } else { if (iattr->decl->defVal == NULL) { /* VAL TODO: A default value was not precomputed. */ - TODO goto eval_idcs; } iattr->vcValue = iattr->decl->defValue; @@ -27197,7 +27158,6 @@ xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED, if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) return; /* SAX VAL TODO: What to do here? */ - TODO } static void @@ -27258,9 +27218,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, (const xmlChar **) xmlMalloc(10 * sizeof(const xmlChar *)); if (ielem->nsBindings == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating namespace bindings for SAX validation", - NULL); + xmlSchemaVErrMemory(vctxt); goto internal_error; } ielem->nbNsBindings = 0; @@ -27272,9 +27230,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, (void *) ielem->nsBindings, ielem->sizeNsBindings * 2 * sizeof(const xmlChar *)); if (ielem->nsBindings == NULL) { - xmlSchemaVErrMemory(vctxt, - "re-allocating namespace bindings for SAX validation", - NULL); + xmlSchemaVErrMemory(vctxt); goto internal_error; } } @@ -27312,9 +27268,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, valueLen = attributes[j+4] - attributes[j+3]; value = xmlMallocAtomic(valueLen + 1); if (value == NULL) { - xmlSchemaVErrMemory(vctxt, - "allocating string for decoded attribute", - NULL); + xmlSchemaVErrMemory(vctxt); goto internal_error; } for (k = 0, l = 0; k < valueLen; l++) { @@ -27431,7 +27385,7 @@ xmlSchemaNewValidCtxt(xmlSchemaPtr schema) ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt)); if (ret == NULL) { - xmlSchemaVErrMemory(NULL, "allocating validation context", NULL); + xmlSchemaVErrMemory(NULL); return (NULL); } memset(ret, 0, sizeof(xmlSchemaValidCtxt)); @@ -27699,6 +27653,8 @@ xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt) * @warn: the warning function * @ctx: the functions context * + * DEPRECATED: Use xmlSchemaSetValidStructuredErrors. + * * Set the error and warning callback information */ void @@ -28379,7 +28335,7 @@ warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->warning != NULL)) { - TODO + /* TODO */ } } static void @@ -28387,7 +28343,7 @@ errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->error != NULL)) { - TODO + /* TODO */ } } static void @@ -28395,7 +28351,7 @@ fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; if ((ctxt != NULL) && (ctxt->user_sax != NULL) && (ctxt->user_sax->fatalError != NULL)) { - TODO + /* TODO */ } } diff --git a/xmlschemastypes.c b/xmlschemastypes.c index de95d94..5c6db29 100644 --- a/xmlschemastypes.c +++ b/xmlschemastypes.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -41,11 +42,6 @@ extern double xmlXPathPINF; extern double xmlXPathNINF; #endif -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - #define XML_SCHEMAS_NAMESPACE_NAME \ (const xmlChar *)"http://www.w3.org/2001/XMLSchema" @@ -82,15 +78,11 @@ struct _xmlSchemaValDuration { typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; -struct _xmlSchemaValDecimal { - /* would use long long but not portable */ - unsigned long lo; - unsigned long mi; - unsigned long hi; - unsigned int extra; - unsigned int sign:1; - unsigned int frac:7; - unsigned int total:8; +struct _xmlSchemaValDecimal +{ + xmlChar *str; + unsigned integralPlaces; + unsigned fractionalPlaces; }; typedef struct _xmlSchemaValQName xmlSchemaValQName; @@ -200,9 +192,9 @@ static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL; * Handle an out of memory condition */ static void -xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra) +xmlSchemaTypeErrMemory(void) { - __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra); + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_DATATYPE, NULL); } /************************************************************************ @@ -236,6 +228,8 @@ static xmlSchemaFacetPtr xmlSchemaNewMinLengthFacet(int value) { xmlSchemaFacetPtr ret; + size_t bufsize; + xmlSchemaValDecimal *decimal; ret = xmlSchemaNewFacet(); if (ret == NULL) { @@ -245,9 +239,19 @@ xmlSchemaNewMinLengthFacet(int value) ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER); if (ret->val == NULL) { xmlFree(ret); - return(NULL); + return(NULL); } - ret->val->value.decimal.lo = value; + bufsize = snprintf(NULL, 0, "%+d.0", value) + 1; + decimal = &ret->val->value.decimal; + decimal->str = xmlMalloc(bufsize); + if (decimal->str == NULL) + { + xmlSchemaFreeFacet(ret); + return NULL; + } + snprintf((char *)decimal->str, bufsize, "%+d.0", value); + decimal->integralPlaces = bufsize - 4; + decimal->fractionalPlaces = 1; return (ret); } @@ -265,7 +269,7 @@ xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); if (ret == NULL) { - xmlSchemaTypeErrMemory(NULL, "could not initialize basic types"); + xmlSchemaTypeErrMemory(); return(NULL); } memset(ret, 0, sizeof(xmlSchemaType)); @@ -326,6 +330,90 @@ xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, return(ret); } +static const xmlChar * +xmlSchemaValDecimalGetFractionalPart(const xmlSchemaValDecimal *decimal) +{ + /* 2 = sign+dot */ + return decimal->str+2+decimal->integralPlaces; +} + +static int +xmlSchemaValDecimalIsInteger(const xmlSchemaValDecimal *decimal) +{ + return decimal->fractionalPlaces == 1 && xmlSchemaValDecimalGetFractionalPart(decimal)[0] == '0'; +} + +static unsigned long +xmlSchemaValDecimalGetSignificantDigitCount(const xmlSchemaValDecimal *decimal) +{ + unsigned fractionalPlaces = xmlSchemaValDecimalIsInteger(decimal) ? 0 : decimal->fractionalPlaces; + unsigned integralPlaces = decimal->integralPlaces; + if(integralPlaces == 1 && decimal->str[1] == '0') + { + integralPlaces = 0; + } + if(integralPlaces+fractionalPlaces == 0) + { + /* 0, but that's still 1 significant digit */ + return 1; + } + return integralPlaces+fractionalPlaces; +} + +/** + * @brief Compares two decimals + * + * @param lhs + * @param rhs + * @return positive value if lhs > rhs, negative if lhs < rhs, or 0 if lhs == rhs + */ +static int xmlSchemaValDecimalCompare(const xmlSchemaValDecimal *lhs, const xmlSchemaValDecimal *rhs) +{ + int sign = 1; + /* may be +0 and -0 for some reason, handle */ + if(strcmp((const char*)lhs->str+1, "0.0") == 0 && + strcmp((const char*)rhs->str+1, "0.0") == 0) + { + return 0; + } + /* first take care of sign */ + if(lhs->str[0] != rhs->str[0]) + { + /* ASCII- > ASCII+ */ + return rhs->str[0]-lhs->str[0]; + } + /* signs are equal, but if negative the comparison must be reversed */ + if(lhs->str[0] == '-') + { + sign = -1; + } + /* internal representation never contains leading zeroes, longer decimal representation = larger number */ + if(lhs->integralPlaces != rhs->integralPlaces) + { + return ((int)lhs->integralPlaces-(int)rhs->integralPlaces)*sign; + } + /* same length, only digits => lexicographical sorting == numerical sorting. + If integral parts are equal it will compare compare fractional parts. Again, lexicographical is good enough, + length doesn't matter. We'll be starting from 0.1, always comparing like to like, and NULL < '0' + If one is shorter and is equal until end, it must be smaller, since there are no trailing zeroes + and the longer number must therefore have at least one non-zero digit after the other has ended. + +1 to skip the sign + */ + return strcmp((const char*)lhs->str+1, (const char*)rhs->str+1)*sign; +} + +static int xmlSchemaValDecimalCompareWithInteger(const xmlSchemaValDecimal *lhs, long rhs) +{ + /* can handle integers up to 128 bits, should be good for a while */ + char buf[43]; + xmlSchemaValDecimal tmpVal; + /* 3 = sign+dot+0+NULL */ + tmpVal.integralPlaces = snprintf(buf, sizeof(buf), "%+ld.0", rhs)-3; + tmpVal.str = (xmlChar*)buf; + tmpVal.fractionalPlaces = 1; + return xmlSchemaValDecimalCompare(lhs, &tmpVal); +} + /* * WARNING: Those type reside normally in xmlschemas.c but are * redefined here locally in oder of being able to use them for xs:anyType- @@ -373,7 +461,7 @@ xmlSchemaAddParticle(void) ret = (xmlSchemaParticlePtr) xmlMalloc(sizeof(xmlSchemaParticle)); if (ret == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating particle component"); + xmlSchemaTypeErrMemory(); return (NULL); } memset(ret, 0, sizeof(xmlSchemaParticle)); @@ -435,7 +523,7 @@ xmlSchemaInitTypes(void) return (0); xmlSchemaTypesBank = xmlHashCreate(40); if (xmlSchemaTypesBank == NULL) { - xmlSchemaTypeErrMemory(NULL, NULL); + xmlSchemaTypeErrMemory(); goto error; } @@ -466,7 +554,7 @@ xmlSchemaInitTypes(void) sequence = (xmlSchemaModelGroupPtr) xmlMalloc(sizeof(xmlSchemaModelGroup)); if (sequence == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating model group component"); + xmlSchemaTypeErrMemory(); goto error; } memset(sequence, 0, sizeof(xmlSchemaModelGroup)); @@ -482,7 +570,7 @@ xmlSchemaInitTypes(void) /* The wildcard */ wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); if (wild == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating wildcard component"); + xmlSchemaTypeErrMemory(); goto error; } memset(wild, 0, sizeof(xmlSchemaWildcard)); @@ -495,8 +583,7 @@ xmlSchemaInitTypes(void) */ wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); if (wild == NULL) { - xmlSchemaTypeErrMemory(NULL, "could not create an attribute " - "wildcard on anyType"); + xmlSchemaTypeErrMemory(); goto error; } memset(wild, 0, sizeof(xmlSchemaWildcard)); @@ -1179,6 +1266,23 @@ xmlSchemaFreeValue(xmlSchemaValPtr value) { if (value->value.base64.str != NULL) xmlFree(value->value.base64.str); break; + case XML_SCHEMAS_DECIMAL: + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_NNINTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_UBYTE: + if (value->value.decimal.str != NULL) + xmlFree(value->value.decimal.str); + break; default: break; } @@ -1273,7 +1377,7 @@ static const unsigned int daysInMonthLeap[12] = ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0) #define VALID_TIME(dt) \ - (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \ + (((VALID_HOUR((int)dt->hour) && VALID_MIN((int)dt->min) && \ VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \ VALID_TZO(dt->tzo)) @@ -2238,21 +2342,16 @@ xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value, /** * xmlSchemaParseUInt: * @str: pointer to the string R/W - * @llo: pointer to the low result - * @lmi: pointer to the mid result - * @lhi: pointer to the high result + * @val: pointer to the resulting decimal * - * Parse an unsigned long into 3 fields. + * Parse an unsigned long into a decimal. * * Returns the number of significant digits in the number or * -1 if overflow of the capacity and -2 if it's not a number. */ -static int -xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, - unsigned long *lmi, unsigned long *lhi) { - unsigned long lo = 0, mi = 0, hi = 0; - const xmlChar *tmp, *cur = *str; - int ret = 0, i = 0; +static int xmlSchemaParseUInt(const xmlChar **str, xmlSchemaValDecimalPtr val) { + const xmlChar *tmp, *cur = *str; + int ret = 0, i = 0; if (!((*cur >= '0') && (*cur <= '9'))) return(-2); @@ -2260,31 +2359,29 @@ xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, while (*cur == '0') { /* ignore leading zeroes */ cur++; } + /* back up in case there is nothing after the leading zeroes */ + if(!(*cur >= '0' && *cur <= '9')) + { + --cur; + } tmp = cur; while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) { i++;tmp++;ret++; } - if (i > 24) { - *str = tmp; - return(-1); - } - while (i > 16) { - hi = hi * 10 + (*cur++ - '0'); - i--; - } - while (i > 8) { - mi = mi * 10 + (*cur++ - '0'); - i--; - } - while (i > 0) { - lo = lo * 10 + (*cur++ - '0'); - i--; + if (val->integralPlaces + val->fractionalPlaces < (unsigned)i + 1) + { + if (val->str != NULL) + { + xmlFree(val->str); + } + /* sign, dot, fractional 0 and NULL terminator */ + val->str = xmlMalloc(i + 4); } + val->fractionalPlaces = 1; + val->integralPlaces = i; + snprintf((char *)val->str, i + 4, "+%.*s.0", i, cur); - *str = cur; - *llo = lo; - *lmi = mi; - *lhi = hi; + *str = tmp; return(ret); } @@ -2472,9 +2569,11 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, } case XML_SCHEMAS_DECIMAL:{ const xmlChar *cur = value; - unsigned int len, neg, integ, hasLeadingZeroes; - xmlChar cval[25]; - xmlChar *cptr = cval; + const xmlChar *numStart, *numEnd; + xmlSchemaValDecimal decimal; + xmlChar sign; + + memset(&decimal, 0, sizeof(decimal)); if ((cur == NULL) || (*cur == 0)) goto return1; @@ -2488,9 +2587,9 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, /* * First we handle an optional sign. */ - neg = 0; + sign = '+'; if (*cur == '-') { - neg = 1; + sign = '-'; cur++; } else if (*cur == '+') cur++; @@ -2499,47 +2598,44 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, */ if (*cur == 0) goto return1; - /* - * Next we "pre-parse" the number, in preparation for calling - * the common routine xmlSchemaParseUInt. We get rid of any - * leading zeroes (because we have reserved only 25 chars), - * and note the position of a decimal point. - */ - len = 0; - integ = ~0u; - hasLeadingZeroes = 0; + /* * Skip leading zeroes. */ while (*cur == '0') { cur++; - hasLeadingZeroes = 1; - } - if (*cur != 0) { - do { - if ((*cur >= '0') && (*cur <= '9')) { - *cptr++ = *cur++; - len++; - } else if (*cur == '.') { - cur++; - integ = len; - do { - if ((*cur >= '0') && (*cur <= '9')) { - *cptr++ = *cur++; - len++; - } else - break; - } while (len < 24); - /* - * Disallow "." but allow "00." - */ - if ((len == 0) && (!hasLeadingZeroes)) - goto return1; - break; - } else - break; - } while (len < 24); } + + numStart = cur; + + while ((*cur >= '0') && (*cur <= '9')) { + ++cur; + ++decimal.integralPlaces; + } + if (*cur == '.') { + ++cur; + } + while ((*cur >= '0') && (*cur <= '9')) { + ++cur; + ++decimal.fractionalPlaces; + } + + /* disallow "." */ + if ( + decimal.fractionalPlaces == 0 && decimal.integralPlaces == 0 + && (numStart == value || numStart[-1] != '0') + ) { + goto return1; + } + + numEnd = cur; + + /* find if there are trailing FRACTIONAL zeroes, and deal with them if necessary */ + while (numEnd > numStart && decimal.fractionalPlaces && numEnd[-1] == '0') { + --numEnd; + --decimal.fractionalPlaces; + } + if (normOnTheFly) while IS_WSP_BLANK_CH(*cur) cur++; if (*cur != 0) @@ -2547,50 +2643,36 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, if (val != NULL) { v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL); if (v != NULL) { - /* - * Now evaluate the significant digits of the number - */ - if (len != 0) { - - if (integ != ~0u) { - /* - * Get rid of trailing zeroes in the - * fractional part. - */ - while ((len != integ) && (*(cptr-1) == '0')) { - cptr--; - len--; - } - } - /* - * Terminate the (preparsed) string. - */ - if (len != 0) { - *cptr = 0; - cptr = cval; - - xmlSchemaParseUInt((const xmlChar **)&cptr, - &v->value.decimal.lo, - &v->value.decimal.mi, - &v->value.decimal.hi); - } - } - /* - * Set the total digits to 1 if a zero value. - */ - v->value.decimal.sign = neg; - if (len == 0) { - /* Speedup for zero values. */ - v->value.decimal.total = 1; - } else { - v->value.decimal.total = len; - if (integ == ~0u) - v->value.decimal.frac = 0; - else - v->value.decimal.frac = len - integ; - } + /* create a standardized representation */ + size_t bufsize; + const char *integralStart = (const char *)numStart; + const char *fractionalStart = (const char *)numEnd - decimal.fractionalPlaces; + if (decimal.integralPlaces == 0) + { + integralStart = "0"; + decimal.integralPlaces = 1; + } + if (decimal.fractionalPlaces == 0) + { + fractionalStart = "0"; + decimal.fractionalPlaces = 1; + } + /* 3 = sign, dot, NULL terminator */ + bufsize = decimal.integralPlaces + decimal.fractionalPlaces + 3; + decimal.str = xmlMalloc(bufsize); + if (!decimal.str) + { + goto error; + } + snprintf((char *)decimal.str, bufsize, "%c%.*s.%.*s", sign, decimal.integralPlaces, integralStart, + decimal.fractionalPlaces, fractionalStart); + v->value.decimal = decimal; *val = v; } + else + { + goto error; + } } goto return0; } @@ -2970,19 +3052,19 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, * NOTE: the IDness might have already be declared in the DTD */ if (attr->atype != XML_ATTRIBUTE_ID) { - xmlIDPtr res; xmlChar *strip; + int res; strip = xmlSchemaStrip(value); if (strip != NULL) { - res = xmlAddID(NULL, node->doc, strip, attr); + res = xmlAddIDSafe(attr, strip); xmlFree(strip); } else - res = xmlAddID(NULL, node->doc, value, attr); - if (res == NULL) { + res = xmlAddIDSafe(attr, value); + if (res < 0) { + goto error; + } else if (res == 0) { ret = 2; - } else { - attr->atype = XML_ATTRIBUTE_ID; } } } @@ -3046,7 +3128,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, ret = 4; } if ((ret == 0) && (val != NULL)) { - TODO; + /* TODO */ } if ((ret == 0) && (node != NULL) && (node->type == XML_ATTRIBUTE_NODE)) { @@ -3198,7 +3280,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, */ cur = xmlStrndup(start, i); if (cur == NULL) { - xmlSchemaTypeErrMemory(node, "allocating hexbin data"); + xmlSchemaTypeErrMemory(); xmlFree(v); goto return1; } @@ -3325,7 +3407,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, base = (xmlChar *) xmlMallocAtomic(i + pad + 1); if (base == NULL) { - xmlSchemaTypeErrMemory(node, "allocating base64 data"); + xmlSchemaTypeErrMemory(); xmlFree(v); goto return1; } @@ -3345,201 +3427,152 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, case XML_SCHEMAS_PINTEGER: case XML_SCHEMAS_NPINTEGER: case XML_SCHEMAS_NINTEGER: - case XML_SCHEMAS_NNINTEGER:{ - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int sign = 0; - - if (cur == NULL) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur == '-') { - sign = 1; - cur++; - } else if (*cur == '+') - cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret < 0) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_NPINTEGER) { - if ((sign == 0) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_PINTEGER) { - if (sign == 1) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_NINTEGER) { - if (sign == 0) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) { - if ((sign == 1) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->builtInType); - if (v != NULL) { - if (ret == 0) - ret++; - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; - *val = v; - } - } - goto return0; - } + case XML_SCHEMAS_NNINTEGER: case XML_SCHEMAS_LONG: case XML_SCHEMAS_BYTE: case XML_SCHEMAS_SHORT: - case XML_SCHEMAS_INT:{ + case XML_SCHEMAS_INT: + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UBYTE: { const xmlChar *cur = value; - unsigned long lo, mi, hi; - int sign = 0; + xmlSchemaValDecimal decimal; + xmlChar sign = '+'; + + memset(&decimal, 0, sizeof(decimal)); if (cur == NULL) goto return1; - if (normOnTheFly) + if (normOnTheFly) while IS_WSP_BLANK_CH(*cur) cur++; if (*cur == '-') { - sign = 1; + sign = '-'; cur++; } else if (*cur == '+') cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); + ret = xmlSchemaParseUInt(&cur, &decimal); + /* add sign */ if (ret < 0) - goto return1; + goto valIntegerReturn1; + decimal.str[0] = sign; if (normOnTheFly) while IS_WSP_BLANK_CH(*cur) cur++; if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_LONG) { - if (hi >= 922) { - if (hi > 922) - goto return1; - if (mi >= 33720368) { - if (mi > 33720368) - goto return1; - if ((sign == 0) && (lo > 54775807)) - goto return1; - if ((sign == 1) && (lo > 54775808)) - goto return1; - } - } - } else if (type->builtInType == XML_SCHEMAS_INT) { - if (hi != 0) - goto return1; - if (mi >= 21) { - if (mi > 21) - goto return1; - if ((sign == 0) && (lo > 47483647)) - goto return1; - if ((sign == 1) && (lo > 47483648)) - goto return1; - } - } else if (type->builtInType == XML_SCHEMAS_SHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 32768)) - goto return1; - if ((sign == 0) && (lo > 32767)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_BYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 128)) - goto return1; - if ((sign == 0) && (lo > 127)) - goto return1; + goto valIntegerReturn1; + if (type->builtInType == XML_SCHEMAS_NPINTEGER) + { + if(xmlSchemaValDecimalCompareWithInteger(&decimal, 0) > 0) + goto valIntegerReturn1; } - if (val != NULL) { - v = xmlSchemaNewValue(type->builtInType); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; - *val = v; - } + else if (type->builtInType == XML_SCHEMAS_PINTEGER) + { + if (sign == '-') + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) <= 0) + goto valIntegerReturn1; } - goto return0; - } - case XML_SCHEMAS_UINT: - case XML_SCHEMAS_ULONG: - case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_UBYTE:{ - const xmlChar *cur = value; - unsigned long lo, mi, hi; - - if (cur == NULL) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret < 0) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_ULONG) { - if (hi >= 1844) { - if (hi > 1844) - goto return1; - if (mi >= 67440737) { - if (mi > 67440737) - goto return1; - if (lo > 9551615) - goto return1; - } - } - } else if (type->builtInType == XML_SCHEMAS_UINT) { - if (hi != 0) - goto return1; - if (mi >= 42) { - if (mi > 42) - goto return1; - if (lo > 94967295) - goto return1; - } - } else if (type->builtInType == XML_SCHEMAS_USHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 65535) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_UBYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 255) - goto return1; + else if (type->builtInType == XML_SCHEMAS_NINTEGER) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) >= 0) + goto valIntegerReturn1; + } + else if (type->builtInType == XML_SCHEMAS_NNINTEGER) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0) + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_LONG) + { + /* (u)int64_t may not be available on 32 bit platform, just use decimal */ + xmlSchemaValDecimal tmpDecimal; + static const char maxLong[] = "+9223372036854775807.0"; + static const char minLong[] = "-9223372036854775808.0"; + tmpDecimal.fractionalPlaces = 1; + tmpDecimal.integralPlaces = 19; + tmpDecimal.str = BAD_CAST maxLong; + if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0) + goto valIntegerReturn1; + tmpDecimal.str = BAD_CAST minLong; + if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) < 0) + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_ULONG) + { + xmlSchemaValDecimal tmpDecimal; + static const char maxULong[] = "+18446744073709551615.0"; + tmpDecimal.fractionalPlaces = 1; + tmpDecimal.integralPlaces = 20; + tmpDecimal.str = (xmlChar*)maxULong; + if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0) + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0) + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_INT) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fffffff) > 0) /* INT32_MAX */ + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x7fffffff-1) < 0) /* INT32_MIN */ + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_SHORT) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7fff) > 0) /* INT16_MAX */ + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x8000) < 0) /* INT16_MIN */ + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_BYTE) + {if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0x7f) > 0) /* INT8_MAX */ + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, -0x80) < 0) /* INT8_MIN */ + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_UINT) + { + xmlSchemaValDecimal tmpDecimal; + static const char maxUInt[] = "+4294967295.0"; + tmpDecimal.fractionalPlaces = 1; + tmpDecimal.integralPlaces = 10; + tmpDecimal.str = (xmlChar*)maxUInt; + if (xmlSchemaValDecimalCompare(&decimal, &tmpDecimal) > 0) + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0) + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_USHORT) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xffff) > 0) /* UINT16_MAX */ + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0) + goto valIntegerReturn1; + } + else if(type->builtInType == XML_SCHEMAS_UBYTE) + { + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0xff) > 0) /* UINT8_MAX */ + goto valIntegerReturn1; + if (xmlSchemaValDecimalCompareWithInteger(&decimal, 0) < 0) + goto valIntegerReturn1; } if (val != NULL) { v = xmlSchemaNewValue(type->builtInType); if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = 0; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; + v->value.decimal = decimal; *val = v; } } + else if(decimal.str != NULL) + { + xmlFree(decimal.str); + } goto return0; + valIntegerReturn1: + if(decimal.str != NULL) + { + xmlFree(decimal.str); + } + goto return1; } } @@ -3636,139 +3669,16 @@ xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value, static int xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) { - xmlSchemaValPtr swp; - int order = 1, integx, integy, dlen; - unsigned long hi, mi, lo; - - /* - * First test: If x is -ve and not zero - */ - if ((x->value.decimal.sign) && - ((x->value.decimal.lo != 0) || - (x->value.decimal.mi != 0) || - (x->value.decimal.hi != 0))) { - /* - * Then if y is -ve and not zero reverse the compare - */ - if ((y->value.decimal.sign) && - ((y->value.decimal.lo != 0) || - (y->value.decimal.mi != 0) || - (y->value.decimal.hi != 0))) - order = -1; - /* - * Otherwise (y >= 0) we have the answer - */ - else - return (-1); - /* - * If x is not -ve and y is -ve we have the answer - */ - } else if ((y->value.decimal.sign) && - ((y->value.decimal.lo != 0) || - (y->value.decimal.mi != 0) || - (y->value.decimal.hi != 0))) { - return (1); - } - /* - * If it's not simply determined by a difference in sign, - * then we need to compare the actual values of the two nums. - * To do this, we start by looking at the integral parts. - * If the number of integral digits differ, then we have our - * answer. - */ - integx = x->value.decimal.total - x->value.decimal.frac; - integy = y->value.decimal.total - y->value.decimal.frac; - /* - * NOTE: We changed the "total" for values like "0.1" - * (or "-0.1" or ".1") to be 1, which was 2 previously. - * Therefore the special case, when such values are - * compared with 0, needs to be handled separately; - * otherwise a zero would be recognized incorrectly as - * greater than those values. This has the nice side effect - * that we gain an overall optimized comparison with zeroes. - * Note that a "0" has a "total" of 1 already. - */ - if (integx == 1) { - if (x->value.decimal.lo == 0) { - if (integy != 1) - return -order; - else if (y->value.decimal.lo != 0) - return -order; - else - return(0); - } - } - if (integy == 1) { - if (y->value.decimal.lo == 0) { - if (integx != 1) - return order; - else if (x->value.decimal.lo != 0) - return order; - else - return(0); - } - } - - if (integx > integy) - return order; - else if (integy > integx) - return -order; - - /* - * If the number of integral digits is the same for both numbers, - * then things get a little more complicated. We need to "normalize" - * the numbers in order to properly compare them. To do this, we - * look at the total length of each number (length => number of - * significant digits), and divide the "shorter" by 10 (decreasing - * the length) until they are of equal length. - */ - dlen = x->value.decimal.total - y->value.decimal.total; - if (dlen < 0) { /* y has more digits than x */ - swp = x; - hi = y->value.decimal.hi; - mi = y->value.decimal.mi; - lo = y->value.decimal.lo; - dlen = -dlen; - order = -order; - } else { /* x has more digits than y */ - swp = y; - hi = x->value.decimal.hi; - mi = x->value.decimal.mi; - lo = x->value.decimal.lo; - } - while (dlen > 8) { /* in effect, right shift by 10**8 */ - lo = mi; - mi = hi; - hi = 0; - dlen -= 8; - } - while (dlen > 0) { - unsigned long rem1, rem2; - rem1 = (hi % 10) * 100000000L; - hi = hi / 10; - rem2 = (mi % 10) * 100000000L; - mi = (mi + rem1) / 10; - lo = (lo + rem2) / 10; - dlen--; + int res = xmlSchemaValDecimalCompare(&x->value.decimal, &y->value.decimal); + if(res > 0) + { + return 1; } - if (hi > swp->value.decimal.hi) { - return order; - } else if (hi == swp->value.decimal.hi) { - if (mi > swp->value.decimal.mi) { - return order; - } else if (mi == swp->value.decimal.mi) { - if (lo > swp->value.decimal.lo) { - return order; - } else if (lo == swp->value.decimal.lo) { - if (x->value.decimal.total == y->value.decimal.total) { - return 0; - } else { - return order; - } - } - } + if(res < 0) + { + return -1; } - return -order; + return 0; } /** @@ -3955,6 +3865,24 @@ xmlSchemaCopyValue(xmlSchemaValPtr val) cur->value.base64.str = xmlStrdup(BAD_CAST val->value.base64.str); break; + case XML_SCHEMAS_DECIMAL: + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UBYTE: + cur = xmlSchemaDupVal(val); + if (val->value.decimal.str != NULL) + cur->value.decimal.str = xmlStrdup(BAD_CAST val->value.decimal.str); + break; default: cur = xmlSchemaDupVal(val); break; @@ -5045,7 +4973,7 @@ xmlSchemaCompareValuesInternal(xmlSchemaValType xtype, * TODO: Compare those against QName. */ if (ytype == XML_SCHEMAS_QNAME) { - TODO + /* TODO */ if (y == NULL) return(-2); return (-2); @@ -5170,7 +5098,7 @@ xmlSchemaCompareValuesInternal(xmlSchemaValType xtype, case XML_SCHEMAS_IDREFS: case XML_SCHEMAS_ENTITIES: case XML_SCHEMAS_NMTOKENS: - TODO + /* TODO */ break; } return -2; @@ -5320,9 +5248,10 @@ xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet) /* * TODO: Check if this is a decimal. */ + char *discard; if (facet == NULL || facet->val == NULL) return 0; - return ((unsigned long) facet->val->value.decimal.lo); + return strtoul((const char*)facet->val->value.decimal.str+1, &discard, 10); } /** @@ -5350,21 +5279,21 @@ xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet, * (compare value.decimal.mi and value.decimal.hi as well?). */ if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (actualLen != facet->val->value.decimal.lo) { + if (actualLen != xmlSchemaGetFacetValueAsULong(facet)) { if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; + *expectedLen = xmlSchemaGetFacetValueAsULong(facet); return (XML_SCHEMAV_CVC_LENGTH_VALID); } } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (actualLen < facet->val->value.decimal.lo) { + if (actualLen < xmlSchemaGetFacetValueAsULong(facet)) { if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; + *expectedLen = xmlSchemaGetFacetValueAsULong(facet); return (XML_SCHEMAV_CVC_MINLENGTH_VALID); } } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) { - if (actualLen > facet->val->value.decimal.lo) { + if (actualLen > xmlSchemaGetFacetValueAsULong(facet)) { if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; + *expectedLen = xmlSchemaGetFacetValueAsULong(facet); return (XML_SCHEMAV_CVC_MAXLENGTH_VALID); } } else @@ -5417,7 +5346,8 @@ xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet, if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { + !(xmlSchemaValDecimalIsInteger(&facet->val->value.decimal))) + { return(-1); } if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) @@ -5471,21 +5401,22 @@ xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet, */ return (0); default: - TODO + /* TODO */ + break; } } *length = (unsigned long) len; /* - * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi". + * TODO: Return the whole expected value. (This may be possible now with xmlSchemaValDecimalCompareWithInteger) */ if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (len != facet->val->value.decimal.lo) + if (len != xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_LENGTH_VALID); } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (len < facet->val->value.decimal.lo) + if (len < xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_MINLENGTH_VALID); } else { - if (len > facet->val->value.decimal.lo) + if (len > xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); } @@ -5681,7 +5612,7 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { + !xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) { return(-1); } if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) @@ -5725,18 +5656,18 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, len = xmlSchemaNormLen(value); break; default: - TODO + /* TODO */ + break; } } if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (len != facet->val->value.decimal.lo) + if (len != xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_LENGTH_VALID); } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (len < facet->val->value.decimal.lo) + if (len < xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_MINLENGTH_VALID); - } else { - if (len > facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); + } else if (len > xmlSchemaGetFacetValueAsULong(facet)) { + return (XML_SCHEMAV_CVC_MAXLENGTH_VALID); } break; } @@ -5746,7 +5677,7 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_PINTEGER) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { + !xmlSchemaValDecimalIsInteger(&facet->val->value.decimal)) { return(-1); } if ((val == NULL) || @@ -5767,16 +5698,17 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, return(-1); } if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { - if (val->value.decimal.total > facet->val->value.decimal.lo) + if (xmlSchemaValDecimalGetSignificantDigitCount(&val->value.decimal) > xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID); } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { - if (val->value.decimal.frac > facet->val->value.decimal.lo) + if ((xmlSchemaValDecimalIsInteger(&val->value.decimal) ? 0 : val->value.decimal.fractionalPlaces) > xmlSchemaGetFacetValueAsULong(facet)) return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID); } break; default: - TODO + /* TODO */ + break; } return(0); @@ -6002,75 +5934,13 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue) BAD_CAST val->value.qname.uri); } break; - case XML_SCHEMAS_DECIMAL: - /* - * TODO: Lookout for a more simple implementation. - */ - if ((val->value.decimal.total == 1) && - (val->value.decimal.lo == 0)) { - *retValue = xmlStrdup(BAD_CAST "0.0"); - } else { - xmlSchemaValDecimal dec = val->value.decimal; - int bufsize; - char *buf = NULL, *offs; - - /* Add room for the decimal point as well. */ - bufsize = dec.total + 2; - if (dec.sign) - bufsize++; - /* Add room for leading/trailing zero. */ - if ((dec.frac == 0) || (dec.frac == dec.total)) - bufsize++; - buf = xmlMalloc(bufsize); - if (buf == NULL) - return(-1); - offs = buf; - if (dec.sign) - *offs++ = '-'; - if (dec.frac == dec.total) { - *offs++ = '0'; - *offs++ = '.'; - } - if (dec.hi != 0) - snprintf(offs, bufsize - (offs - buf), - "%lu%lu%lu", dec.hi, dec.mi, dec.lo); - else if (dec.mi != 0) - snprintf(offs, bufsize - (offs - buf), - "%lu%lu", dec.mi, dec.lo); - else - snprintf(offs, bufsize - (offs - buf), - "%lu", dec.lo); - - if (dec.frac != 0) { - if (dec.frac != dec.total) { - int diff = dec.total - dec.frac; - /* - * Insert the decimal point. - */ - memmove(offs + diff + 1, offs + diff, dec.frac +1); - offs[diff] = '.'; - } else { - unsigned int i = 0; - /* - * Insert missing zeroes behind the decimal point. - */ - while (*(offs + i) != 0) - i++; - if (i < dec.total) { - memmove(offs + (dec.total - i), offs, i +1); - memset(offs, '0', dec.total - i); - } - } - } else { - /* - * Append decimal point and zero. - */ - offs = buf + bufsize - 1; - *offs-- = 0; - *offs-- = '0'; - *offs-- = '.'; - } - *retValue = BAD_CAST buf; + case XML_SCHEMAS_DECIMAL: { + xmlChar *start = val->value.decimal.str; + if(start[0] == '+') + { + start += 1; + } + *retValue = xmlStrdup(start); } break; case XML_SCHEMAS_INTEGER: @@ -6085,40 +5955,20 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue) case XML_SCHEMAS_UINT: case XML_SCHEMAS_ULONG: case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_UBYTE: - if ((val->value.decimal.total == 1) && - (val->value.decimal.lo == 0)) - *retValue = xmlStrdup(BAD_CAST "0"); - else { - xmlSchemaValDecimal dec = val->value.decimal; - int bufsize = dec.total + 1; - - /* Add room for the decimal point as well. */ - if (dec.sign) - bufsize++; - *retValue = xmlMalloc(bufsize); - if (*retValue == NULL) - return(-1); - if (dec.hi != 0) { - if (dec.sign) - snprintf((char *) *retValue, bufsize, - "-%lu%lu%lu", dec.hi, dec.mi, dec.lo); - else - snprintf((char *) *retValue, bufsize, - "%lu%lu%lu", dec.hi, dec.mi, dec.lo); - } else if (dec.mi != 0) { - if (dec.sign) - snprintf((char *) *retValue, bufsize, - "-%lu%lu", dec.mi, dec.lo); - else - snprintf((char *) *retValue, bufsize, - "%lu%lu", dec.mi, dec.lo); - } else { - if (dec.sign) - snprintf((char *) *retValue, bufsize, "-%lu", dec.lo); - else - snprintf((char *) *retValue, bufsize, "%lu", dec.lo); - } + case XML_SCHEMAS_UBYTE: { + xmlChar *start = val->value.decimal.str; + /* 2 = sign+NULL */ + size_t bufSize = val->value.decimal.integralPlaces+2; + if(start[0] == '+') + { + start += 1; + bufSize -= 1; + } + *retValue = xmlMalloc(bufSize); + if(*retValue) { + /* no need to limit string length in format, it will only print bufSize-1 chars anyways */ + snprintf((char*)*retValue, bufSize, "%s", start); + } } break; case XML_SCHEMAS_BOOLEAN: diff --git a/xmlstring.c b/xmlstring.c index d9e16d7..258ecc9 100644 --- a/xmlstring.c +++ b/xmlstring.c @@ -26,6 +26,14 @@ #include "private/parser.h" #include "private/string.h" +#ifndef va_copy + #ifdef __va_copy + #define va_copy(dest, src) __va_copy(dest, src) + #else + #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) + #endif +#endif + /************************************************************************ * * * Commodity functions to handle xmlChars * @@ -461,7 +469,8 @@ xmlStrncat(xmlChar *cur, const xmlChar *add, int len) { return(NULL); ret = (xmlChar *) xmlRealloc(cur, (size_t) size + len + 1); if (ret == NULL) { - return(cur); + xmlFree(cur); + return(NULL); } memcpy(&ret[size], add, len); ret[size + len] = 0; @@ -490,18 +499,17 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { if (len < 0) return(NULL); } - if ((str2 == NULL) || (len == 0)) - return(xmlStrdup(str1)); if (str1 == NULL) return(xmlStrndup(str2, len)); + if ((str2 == NULL) || (len == 0)) + return(xmlStrdup(str1)); size = xmlStrlen(str1); if ((size < 0) || (size > INT_MAX - len)) return(NULL); ret = (xmlChar *) xmlMalloc((size_t) size + len + 1); - if (ret == NULL) { - return(xmlStrndup(str1, size)); - } + if (ret == NULL) + return(NULL); memcpy(ret, str1, size); memcpy(&ret[size], str2, len); ret[size + len] = 0; @@ -585,6 +593,148 @@ xmlStrVPrintf(xmlChar *buf, int len, const char *msg, va_list ap) { return(ret); } +/** + * xmlStrVASPrintf: + * @out: pointer to the resulting string + * @maxSize: maximum size of the output buffer + * @msg: printf format string + * @ap: arguments for format string + * + * Creates a newly allocated string according to format. + * + * Returns 0 on success, 1 if the result was truncated or on other + * errors, -1 if a memory allocation failed. + */ +int +xmlStrVASPrintf(xmlChar **out, int maxSize, const char *msg, va_list ap) { + char empty[1]; + va_list copy; + xmlChar *buf; + int res, size; + int truncated = 0; + + if (out == NULL) + return(1); + *out = NULL; + if (msg == NULL) + return(1); + if (maxSize < 32) + maxSize = 32; + + va_copy(copy, ap); + res = vsnprintf(empty, 1, msg, copy); + va_end(copy); + + if (res > 0) { + /* snprintf seems to work according to C99. */ + + if (res < maxSize) { + size = res + 1; + } else { + size = maxSize; + truncated = 1; + } + buf = xmlMalloc(size); + if (buf == NULL) + return(-1); + if (vsnprintf((char *) buf, size, msg, ap) < 0) { + xmlFree(buf); + return(1); + } + } else { + /* + * Unfortunately, older snprintf implementations don't follow the + * C99 spec. If the output exceeds the size of the buffer, they can + * return -1, 0 or the number of characters written instead of the + * needed size. Older MSCVRT also won't write a terminating null + * byte if the buffer is too small. + * + * If the value returned is non-negative and strictly less than + * the buffer size (without terminating null), the result should + * have been written completely, so we double the buffer size + * until this condition is true. This assumes that snprintf will + * eventually return a non-negative value. Otherwise, we will + * allocate more and more memory until we run out. + * + * Note that this code path is also executed on conforming + * platforms if the output is the empty string. + */ + + buf = NULL; + size = 32; + while (1) { + buf = xmlMalloc(size); + if (buf == NULL) + return(-1); + + va_copy(copy, ap); + res = vsnprintf((char *) buf, size, msg, copy); + va_end(copy); + if ((res >= 0) && (res < size - 1)) + break; + + if (size >= maxSize) { + truncated = 1; + break; + } + + xmlFree(buf); + + if (size > maxSize / 2) + size = maxSize; + else + size *= 2; + } + } + + /* + * If the output was truncated, make sure that the buffer doesn't + * end with a truncated UTF-8 sequence. + */ + if (truncated != 0) { + int i = size - 1; + + while (i > 0) { + /* Break after ASCII */ + if (buf[i-1] < 0x80) + break; + i -= 1; + /* Break before non-ASCII */ + if (buf[i] >= 0xc0) + break; + } + + buf[i] = 0; + } + + *out = (xmlChar *) buf; + return(truncated); +} + +/** + * xmlStrASPrintf: + * @out: pointer to the resulting string + * @maxSize: maximum size of the output buffer + * @msg: printf format string + * @...: arguments for format string + * + * See xmlStrVASPrintf. + * + * Returns 0 on success, 1 if the result was truncated or on other + * errors, -1 if a memory allocation failed. + */ +int +xmlStrASPrintf(xmlChar **out, int maxSize, const char *msg, ...) { + va_list ap; + int ret; + + va_start(ap, msg); + ret = xmlStrVASPrintf(out, maxSize, msg, ap); + va_end(ap); + + return(ret); +} + /************************************************************************ * * * Generic UTF8 handling routines * @@ -956,8 +1106,9 @@ xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) { * Create a substring from a given UTF-8 string * Note: positions are given in units of UTF-8 chars * - * Returns a pointer to a newly created string - * or NULL if any problem + * Returns a pointer to a newly created string or NULL if the + * start index is out of bounds or a memory allocation failed. + * If len is too large, the result is truncated. */ xmlChar * @@ -972,16 +1123,18 @@ xmlUTF8Strsub(const xmlChar *utf, int start, int len) { /* * Skip over any leading chars */ - for (i = 0;i < start;i++) { - if ((ch=*utf++) == 0) return(NULL); - if ( ch & 0x80 ) { - /* if not simple ascii, verify proper format */ - if ( (ch & 0xc0) != 0xc0 ) - return(NULL); - /* then skip over remaining bytes for this char */ - while ( (ch <<= 1) & 0x80 ) - if ( (*utf++ & 0xc0) != 0x80 ) + for (i = 0; i < start; i++) { + ch = *utf++; + if (ch == 0) + return(NULL); + /* skip over remaining bytes for this char */ + if (ch & 0x80) { + ch <<= 1; + while (ch & 0x80) { + if (*utf++ == 0) return(NULL); + ch <<= 1; + } } } diff --git a/xmlwriter.c b/xmlwriter.c index ad6e00c..f648dc0 100644 --- a/xmlwriter.c +++ b/xmlwriter.c @@ -11,9 +11,11 @@ #define IN_LIBXML #include "libxml.h" #include +#include #include #include +#include #include #include #include @@ -30,26 +32,11 @@ #define B64LINELEN 72 #define B64CRLF "\r\n" -/* - * The following VA_COPY was coded following an example in - * the Samba project. It may not be sufficient for some - * esoteric implementations of va_list but (hopefully) will - * be sufficient for libxml2. - */ -#ifndef VA_COPY - #ifdef HAVE_VA_COPY - #define VA_COPY(dest, src) va_copy(dest, src) +#ifndef va_copy + #ifdef __va_copy + #define va_copy(dest, src) __va_copy(dest, src) #else - #ifdef HAVE___VA_COPY - #define VA_COPY(dest,src) __va_copy(dest, src) - #else - #ifndef VA_LIST_IS_ARRAY - #define VA_COPY(dest,src) (dest) = (src) - #else - #include - #define VA_COPY(dest,src) memcpy((char *)(dest),(char *)(src),sizeof(va_list)) - #endif - #endif + #define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) #endif #endif @@ -1509,8 +1496,8 @@ xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content) break; case XML_TEXTWRITER_ATTRIBUTE: buf = NULL; - xmlBufAttrSerializeTxtContent(writer->out->buffer, - writer->doc, NULL, content); + xmlBufAttrSerializeTxtContent(writer->out, writer->doc, + content); break; default: break; @@ -4249,6 +4236,35 @@ xmlTextWriterFlush(xmlTextWriterPtr writer) return count; } +/** + * xmlTextWriterClose: + * @writer: the xmlTextWriterPtr + * + * Flushes and closes the output buffer. + * + * Available since 2.13.0. + * + * Returns an xmlParserErrors code. + */ +int +xmlTextWriterClose(xmlTextWriterPtr writer) +{ + int result; + + if ((writer == NULL) || (writer->out == NULL)) + return XML_ERR_ARGUMENT; + + result = xmlOutputBufferClose(writer->out); + writer->out = NULL; + + if (result >= 0) + result = XML_ERR_OK; + else + result = -result; + + return result; +} + /** * misc */ @@ -4486,7 +4502,7 @@ xmlTextWriterVSprintf(const char *format, va_list argptr) return NULL; } - VA_COPY(locarg, argptr); + va_copy(locarg, argptr); while (((count = vsnprintf((char *) buf, size, format, locarg)) < 0) || (count == size - 1) || (count == size) || (count > size)) { va_end(locarg); @@ -4498,7 +4514,7 @@ xmlTextWriterVSprintf(const char *format, va_list argptr) "xmlTextWriterVSprintf : out of memory!\n"); return NULL; } - VA_COPY(locarg, argptr); + va_copy(locarg, argptr); } va_end(locarg); @@ -4517,28 +4533,17 @@ xmlTextWriterStartDocumentCallback(void *ctx) xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlDocPtr doc; - if (ctxt->html) { #ifdef LIBXML_HTML_ENABLED + if (ctxt->html) { if (ctxt->myDoc == NULL) ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); if (ctxt->myDoc == NULL) { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, - "SAX.startDocument(): out of memory\n"); - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; + xmlCtxtErrMemory(ctxt); return; } -#else - xmlWriterErrMsg(NULL, XML_ERR_INTERNAL_ERROR, - "libxml2 built without HTML support\n"); - ctxt->errNo = XML_ERR_INTERNAL_ERROR; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - return; + } else #endif - } else { + { doc = ctxt->myDoc; if (doc == NULL) doc = ctxt->myDoc = xmlNewDoc(ctxt->version); @@ -4551,12 +4556,7 @@ xmlTextWriterStartDocumentCallback(void *ctx) doc->standalone = ctxt->standalone; } } else { - if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) - ctxt->sax->error(ctxt->userData, - "SAX.startDocument(): out of memory\n"); - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; + xmlCtxtErrMemory(ctxt); return; } } diff --git a/xpath.c b/xpath.c index a5aa6ae..1c04850 100644 --- a/xpath.c +++ b/xpath.c @@ -51,14 +51,12 @@ #include "private/error.h" #include "private/xpath.h" +/* Disabled for now */ +#if 0 #ifdef LIBXML_PATTERN_ENABLED #define XPATH_STREAMING #endif - -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); +#endif /** * WITH_TIM_SORT: @@ -235,7 +233,7 @@ xmlXPathIsInf(double val) { * the test should just be name[0] = ' ' */ -static xmlNs xmlXPathXMLNamespaceStruct = { +static const xmlNs xmlXPathXMLNamespaceStruct = { NULL, XML_NAMESPACE_DECL, XML_XML_NAMESPACE, @@ -243,7 +241,7 @@ static xmlNs xmlXPathXMLNamespaceStruct = { NULL, NULL }; -static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; +static const xmlNs *const xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; #ifndef LIBXML_THREAD_ENABLED /* * Optimizer is disabled only when threaded apps are detected while @@ -635,123 +633,100 @@ static const char* const xmlXPathErrorMessages[] = { /** * xmlXPathErrMemory: * @ctxt: an XPath context - * @extra: extra information * - * Handle a redefinition of attribute error + * Handle a memory allocation failure. */ -static void -xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra) +void +xmlXPathErrMemory(xmlXPathContextPtr ctxt) { - if (ctxt != NULL) { - xmlResetError(&ctxt->lastError); - if (extra) { - xmlChar buf[200]; - - xmlStrPrintf(buf, 200, - "Memory allocation failed : %s\n", - extra); - ctxt->lastError.message = (char *) xmlStrdup(buf); - } else { - ctxt->lastError.message = (char *) - xmlStrdup(BAD_CAST "Memory allocation failed\n"); - } - ctxt->lastError.domain = XML_FROM_XPATH; - ctxt->lastError.code = XML_ERR_NO_MEMORY; - if (ctxt->error != NULL) - ctxt->error(ctxt->userData, &ctxt->lastError); - } else { - if (extra) - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_XPATH, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, - extra, NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_XPATH, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, - NULL, NULL, NULL, 0, 0, - "Memory allocation failed\n"); - } + if (ctxt == NULL) + return; + xmlRaiseMemoryError(ctxt->error, NULL, ctxt->userData, XML_FROM_XPATH, + &ctxt->lastError); } /** * xmlXPathPErrMemory: * @ctxt: an XPath parser context - * @extra: extra information * - * Handle a redefinition of attribute error + * Handle a memory allocation failure. */ -static void -xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra) +void +xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt) { if (ctxt == NULL) - xmlXPathErrMemory(NULL, extra); - else { - ctxt->error = XPATH_MEMORY_ERROR; - xmlXPathErrMemory(ctxt->context, extra); - } + return; + ctxt->error = XPATH_MEMORY_ERROR; + xmlXPathErrMemory(ctxt->context); } /** * xmlXPathErr: * @ctxt: a XPath parser context - * @error: the error code + * @code: the error code * * Handle an XPath error */ void -xmlXPathErr(xmlXPathParserContextPtr ctxt, int error) +xmlXPathErr(xmlXPathParserContextPtr ctxt, int code) { - if ((error < 0) || (error > MAXERRNO)) - error = MAXERRNO; - if (ctxt == NULL) { - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_XPATH, - error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, - XML_ERR_ERROR, NULL, 0, - NULL, NULL, NULL, 0, 0, - "%s", xmlXPathErrorMessages[error]); - return; - } + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel = NULL; + void *data = NULL; + xmlNodePtr node = NULL; + int res; + + if (ctxt == NULL) + return; + if ((code < 0) || (code > MAXERRNO)) + code = MAXERRNO; /* Only report the first error */ if (ctxt->error != 0) return; - ctxt->error = error; - if (ctxt->context == NULL) { - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_XPATH, - error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, - XML_ERR_ERROR, NULL, 0, - (const char *) ctxt->base, NULL, NULL, - ctxt->cur - ctxt->base, 0, - "%s", xmlXPathErrorMessages[error]); - return; - } - /* cleanup current last error */ - xmlResetError(&ctxt->context->lastError); + ctxt->error = code; - ctxt->context->lastError.domain = XML_FROM_XPATH; - ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK - - XPATH_EXPRESSION_OK; - ctxt->context->lastError.level = XML_ERR_ERROR; - ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); - ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; - ctxt->context->lastError.node = ctxt->context->debugNode; - if (ctxt->context->error != NULL) { - ctxt->context->error(ctxt->context->userData, - &ctxt->context->lastError); - } else { - __xmlRaiseError(NULL, NULL, NULL, - NULL, ctxt->context->debugNode, XML_FROM_XPATH, - error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, - XML_ERR_ERROR, NULL, 0, - (const char *) ctxt->base, NULL, NULL, - ctxt->cur - ctxt->base, 0, - "%s", xmlXPathErrorMessages[error]); + if (ctxt->context != NULL) { + xmlErrorPtr err = &ctxt->context->lastError; + + /* Don't overwrite memory error. */ + if (err->code == XML_ERR_NO_MEMORY) + return; + + /* cleanup current last error */ + xmlResetError(err); + + err->domain = XML_FROM_XPATH; + err->code = code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK; + err->level = XML_ERR_ERROR; + if (ctxt->base != NULL) { + err->str1 = (char *) xmlStrdup(ctxt->base); + if (err->str1 == NULL) { + xmlXPathPErrMemory(ctxt); + return; + } + } + err->int1 = ctxt->cur - ctxt->base; + err->node = ctxt->context->debugNode; + + schannel = ctxt->context->error; + data = ctxt->context->userData; + node = ctxt->context->debugNode; + } + + if (schannel == NULL) { + channel = xmlGenericError; + data = xmlGenericErrorContext; } + res = __xmlRaiseError(schannel, channel, data, NULL, node, XML_FROM_XPATH, + code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, + XML_ERR_ERROR, NULL, 0, + (const char *) ctxt->base, NULL, NULL, + ctxt->cur - ctxt->base, 0, + "%s", xmlXPathErrorMessages[code]); + if (res < 0) + xmlXPathPErrMemory(ctxt); } /** @@ -795,104 +770,6 @@ xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt, unsigned long opCount) { #define OP_LIMIT_EXCEEDED(ctxt, n) \ ((ctxt->context->opLimit != 0) && (xmlXPathCheckOpLimit(ctxt, n) < 0)) -/************************************************************************ - * * - * Utilities * - * * - ************************************************************************/ - -/** - * xsltPointerList: - * - * Pointer-list for various purposes. - */ -typedef struct _xmlPointerList xmlPointerList; -typedef xmlPointerList *xmlPointerListPtr; -struct _xmlPointerList { - void **items; - int number; - int size; -}; -/* -* TODO: Since such a list-handling is used in xmlschemas.c and libxslt -* and here, we should make the functions public. -*/ -static int -xmlPointerListAddSize(xmlPointerListPtr list, - void *item, - int initialSize) -{ - if (list->size <= list->number) { - void **tmp; - size_t newSize; - - if (list->size == 0) { - if (initialSize <= 0) - initialSize = 1; - newSize = initialSize; - } else { - if (list->size > 50000000) { - xmlXPathErrMemory(NULL, - "xmlPointerListAddSize: re-allocating item\n"); - return(-1); - } - newSize = list->size * 2; - } - tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *)); - if (tmp == NULL) { - xmlXPathErrMemory(NULL, - "xmlPointerListAddSize: re-allocating item\n"); - return(-1); - } - list->items = tmp; - list->size = newSize; - } - list->items[list->number++] = item; - return(0); -} - -/** - * xsltPointerListCreate: - * - * Creates an xsltPointerList structure. - * - * Returns a xsltPointerList structure or NULL in case of an error. - */ -static xmlPointerListPtr -xmlPointerListCreate(int initialSize) -{ - xmlPointerListPtr ret; - - ret = xmlMalloc(sizeof(xmlPointerList)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, - "xmlPointerListCreate: allocating item\n"); - return (NULL); - } - memset(ret, 0, sizeof(xmlPointerList)); - if (initialSize > 0) { - xmlPointerListAddSize(ret, NULL, initialSize); - ret->number = 0; - } - return (ret); -} - -/** - * xsltPointerListFree: - * - * Frees the xsltPointerList structure. This does not free - * the content of the list. - */ -static void -xmlPointerListFree(xmlPointerListPtr list) -{ - if (list == NULL) - return; - if (list->items != NULL) - xmlFree(list->items); - xmlFree(list); -} - /************************************************************************ * * * Parser Types * @@ -991,8 +868,7 @@ struct _xmlXPathCompExpr { * Forward declarations * * * ************************************************************************/ -static void -xmlXPathFreeValueTree(xmlNodeSetPtr obj); + static void xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj); static int @@ -1023,17 +899,14 @@ xmlXPathNewCompExpr(void) { xmlXPathCompExprPtr cur; cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr)); - if (cur == NULL) { - xmlXPathErrMemory(NULL, "allocating component\n"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlXPathCompExpr)); cur->maxStep = 10; cur->nbStep = 0; cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep * sizeof(xmlXPathStepOp)); if (cur->steps == NULL) { - xmlXPathErrMemory(NULL, "allocating steps\n"); xmlFree(cur); return(NULL); } @@ -1118,7 +991,7 @@ xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2, xmlXPathStepOp *real; if (comp->maxStep >= XPATH_MAX_STEPS) { - xmlXPathPErrMemory(ctxt, "adding step\n"); + xmlXPathPErrMemory(ctxt); return(-1); } comp->maxStep *= 2; @@ -1126,7 +999,7 @@ xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2, comp->maxStep * sizeof(xmlXPathStepOp)); if (real == NULL) { comp->maxStep /= 2; - xmlXPathPErrMemory(ctxt, "adding step\n"); + xmlXPathPErrMemory(ctxt); return(-1); } comp->steps = real; @@ -1212,20 +1085,14 @@ xmlXPathCompExprAdd(ctxt, (ch1), (ch2), (op), \ /* #define XP_DEFAULT_CACHE_ON */ -#define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL)) - typedef struct _xmlXPathContextCache xmlXPathContextCache; typedef xmlXPathContextCache *xmlXPathContextCachePtr; struct _xmlXPathContextCache { - xmlPointerListPtr nodesetObjs; /* contains xmlXPathObjectPtr */ - xmlPointerListPtr stringObjs; /* contains xmlXPathObjectPtr */ - xmlPointerListPtr booleanObjs; /* contains xmlXPathObjectPtr */ - xmlPointerListPtr numberObjs; /* contains xmlXPathObjectPtr */ - xmlPointerListPtr miscObjs; /* contains xmlXPathObjectPtr */ + xmlXPathObjectPtr nodesetObjs; /* stringval points to next */ + xmlXPathObjectPtr miscObjs; /* stringval points to next */ + int numNodeset; int maxNodeset; - int maxString; - int maxBoolean; - int maxNumber; + int numMisc; int maxMisc; }; @@ -1235,11 +1102,6 @@ struct _xmlXPathContextCache { * * ************************************************************************/ -#define STRANGE \ - xmlGenericError(xmlGenericErrorContext, \ - "Internal error at %s:%d\n", \ - __FILE__, __LINE__); - #ifdef LIBXML_DEBUG_ENABLED static void xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) { @@ -1704,42 +1566,31 @@ xmlXPathNewCache(void) xmlXPathContextCachePtr ret; ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating object cache\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathContextCache)); ret->maxNodeset = 100; - ret->maxString = 100; - ret->maxBoolean = 100; - ret->maxNumber = 100; ret->maxMisc = 100; return(ret); } static void -xmlXPathCacheFreeObjectList(xmlPointerListPtr list) +xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list) { - int i; - xmlXPathObjectPtr obj; + while (list != NULL) { + xmlXPathObjectPtr next; - if (list == NULL) - return; + next = (void *) list->stringval; - for (i = 0; i < list->number; i++) { - obj = list->items[i]; - /* - * Note that it is already assured that we don't need to - * look out for namespace nodes in the node-set. - */ - if (obj->nodesetval != NULL) { - if (obj->nodesetval->nodeTab != NULL) - xmlFree(obj->nodesetval->nodeTab); - xmlFree(obj->nodesetval); + if (list->nodesetval != NULL) { + if (list->nodesetval->nodeTab != NULL) + xmlFree(list->nodesetval->nodeTab); + xmlFree(list->nodesetval); } - xmlFree(obj); + xmlFree(list); + + list = next; } - xmlPointerListFree(list); } static void @@ -1749,12 +1600,6 @@ xmlXPathFreeCache(xmlXPathContextCachePtr cache) return; if (cache->nodesetObjs) xmlXPathCacheFreeObjectList(cache->nodesetObjs); - if (cache->stringObjs) - xmlXPathCacheFreeObjectList(cache->stringObjs); - if (cache->booleanObjs) - xmlXPathCacheFreeObjectList(cache->booleanObjs); - if (cache->numberObjs) - xmlXPathCacheFreeObjectList(cache->numberObjs); if (cache->miscObjs) xmlXPathCacheFreeObjectList(cache->miscObjs); xmlFree(cache); @@ -1776,8 +1621,8 @@ xmlXPathFreeCache(xmlXPathContextCachePtr cache) * @value: * This will set the maximum number of XPath objects * to be cached per slot - * There are 5 slots for: node-set, string, number, boolean, and - * misc objects. Use <0 for the default number (100). + * There are two slots for node-set and misc objects. + * Use <0 for the default number (100). * Other values for @options have currently no effect. * * Returns 0 if the setting succeeded, and -1 on API or internal errors. @@ -1795,17 +1640,16 @@ xmlXPathContextSetCache(xmlXPathContextPtr ctxt, if (ctxt->cache == NULL) { ctxt->cache = xmlXPathNewCache(); - if (ctxt->cache == NULL) + if (ctxt->cache == NULL) { + xmlXPathErrMemory(ctxt); return(-1); + } } cache = (xmlXPathContextCachePtr) ctxt->cache; if (options == 0) { if (value < 0) value = 100; cache->maxNodeset = value; - cache->maxString = value; - cache->maxNumber = value; - cache->maxBoolean = value; cache->maxMisc = value; } } else if (ctxt->cache != NULL) { @@ -1817,7 +1661,7 @@ xmlXPathContextSetCache(xmlXPathContextPtr ctxt, /** * xmlXPathCacheWrapNodeSet: - * @ctxt: the XPath context + * @pctxt: the XPath context * @val: the NodePtr value * * This is the cached version of xmlXPathWrapNodeSet(). @@ -1828,32 +1672,35 @@ xmlXPathContextSetCache(xmlXPathContextPtr ctxt, * In case of error the node set is destroyed and NULL is returned. */ static xmlXPathObjectPtr -xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) +xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt, xmlNodeSetPtr val) { + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; + if ((ctxt != NULL) && (ctxt->cache != NULL)) { xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; - - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; + if (cache->miscObjs != NULL) { + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; + ret->stringval = NULL; ret->type = XPATH_NODESET; ret->nodesetval = val; return(ret); } } - return(xmlXPathWrapNodeSet(val)); - + ret = xmlXPathWrapNodeSet(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheWrapString: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the xmlChar * value * * This is the cached version of xmlXPathWrapString(). @@ -1862,43 +1709,33 @@ xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) +xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt, xmlChar *val) { + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; + if ((ctxt != NULL) && (ctxt->cache != NULL)) { xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - if ((cache->stringObjs != NULL) && - (cache->stringObjs->number != 0)) - { - - xmlXPathObjectPtr ret; - - ret = (xmlXPathObjectPtr) - cache->stringObjs->items[--cache->stringObjs->number]; - ret->type = XPATH_STRING; - ret->stringval = val; - return(ret); - } else if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; - /* - * Fallback to misc-cache. - */ - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; - + if (cache->miscObjs != NULL) { + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; ret->type = XPATH_STRING; ret->stringval = val; return(ret); } } - return(xmlXPathWrapString(val)); + + ret = xmlXPathWrapString(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheNewNodeSet: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the NodePtr value * * This is the cached version of xmlXPathNewNodeSet(). @@ -1908,38 +1745,37 @@ xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) +xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt, xmlNodePtr val) { - if ((ctxt != NULL) && (ctxt->cache)) { + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; + + if ((ctxt != NULL) && (ctxt->cache != NULL)) { xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - if ((cache->nodesetObjs != NULL) && - (cache->nodesetObjs->number != 0)) - { - xmlXPathObjectPtr ret; + if (cache->nodesetObjs != NULL) { /* * Use the nodeset-cache. */ - ret = (xmlXPathObjectPtr) - cache->nodesetObjs->items[--cache->nodesetObjs->number]; + ret = cache->nodesetObjs; + cache->nodesetObjs = (void *) ret->stringval; + cache->numNodeset -= 1; + ret->stringval = NULL; ret->type = XPATH_NODESET; ret->boolval = 0; if (val) { if ((ret->nodesetval->nodeMax == 0) || (val->type == XML_NAMESPACE_DECL)) { - /* TODO: Check memory error. */ - xmlXPathNodeSetAddUnique(ret->nodesetval, val); + if (xmlXPathNodeSetAddUnique(ret->nodesetval, val) < 0) + xmlXPathPErrMemory(pctxt); } else { ret->nodesetval->nodeTab[0] = val; ret->nodesetval->nodeNr = 1; } } return(ret); - } else if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; + } else if (cache->miscObjs != NULL) { xmlNodeSetPtr set; /* * Fallback to misc-cache. @@ -1947,26 +1783,29 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) set = xmlXPathNodeSetCreate(val); if (set == NULL) { - ctxt->lastError.domain = XML_FROM_XPATH; - ctxt->lastError.code = XML_ERR_NO_MEMORY; + xmlXPathPErrMemory(pctxt); return(NULL); } - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; - + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; + ret->stringval = NULL; ret->type = XPATH_NODESET; ret->boolval = 0; ret->nodesetval = set; return(ret); } } - return(xmlXPathNewNodeSet(val)); + ret = xmlXPathNewNodeSet(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheNewString: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the xmlChar * value * * This is the cached version of xmlXPathNewString(). @@ -1975,58 +1814,43 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) +xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt, const xmlChar *val) { - if ((ctxt != NULL) && (ctxt->cache)) { - xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - - if ((cache->stringObjs != NULL) && - (cache->stringObjs->number != 0)) - { - xmlXPathObjectPtr ret; - xmlChar *copy; + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; - if (val == NULL) - val = BAD_CAST ""; - copy = xmlStrdup(val); - if (copy == NULL) { - xmlXPathErrMemory(ctxt, NULL); - return(NULL); - } + if ((ctxt != NULL) && (ctxt->cache != NULL)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - ret = (xmlXPathObjectPtr) - cache->stringObjs->items[--cache->stringObjs->number]; - ret->type = XPATH_STRING; - ret->stringval = copy; - return(ret); - } else if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; + if (cache->miscObjs != NULL) { xmlChar *copy; if (val == NULL) val = BAD_CAST ""; copy = xmlStrdup(val); if (copy == NULL) { - xmlXPathErrMemory(ctxt, NULL); + xmlXPathPErrMemory(pctxt); return(NULL); } - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; - + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; ret->type = XPATH_STRING; ret->stringval = copy; return(ret); } } - return(xmlXPathNewString(val)); + + ret = xmlXPathNewString(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheNewCString: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the char * value * * This is the cached version of xmlXPathNewCString(). @@ -2035,14 +1859,14 @@ xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) +xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt, const char *val) { - return xmlXPathCacheNewString(ctxt, BAD_CAST val); + return xmlXPathCacheNewString(pctxt, BAD_CAST val); } /** * xmlXPathCacheNewBoolean: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the boolean value * * This is the cached version of xmlXPathNewBoolean(). @@ -2051,40 +1875,34 @@ xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) +xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt, int val) { - if ((ctxt != NULL) && (ctxt->cache)) { - xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - - if ((cache->booleanObjs != NULL) && - (cache->booleanObjs->number != 0)) - { - xmlXPathObjectPtr ret; - - ret = (xmlXPathObjectPtr) - cache->booleanObjs->items[--cache->booleanObjs->number]; - ret->type = XPATH_BOOLEAN; - ret->boolval = (val != 0); - return(ret); - } else if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; + if ((ctxt != NULL) && (ctxt->cache != NULL)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + if (cache->miscObjs != NULL) { + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; + ret->stringval = NULL; ret->type = XPATH_BOOLEAN; ret->boolval = (val != 0); return(ret); } } - return(xmlXPathNewBoolean(val)); + + ret = xmlXPathNewBoolean(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheNewFloat: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the double value * * This is the cached version of xmlXPathNewFloat(). @@ -2093,89 +1911,34 @@ xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) * Returns the created or reused object. */ static xmlXPathObjectPtr -xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val) +xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt, double val) { - if ((ctxt != NULL) && (ctxt->cache)) { - xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; - - if ((cache->numberObjs != NULL) && - (cache->numberObjs->number != 0)) - { - xmlXPathObjectPtr ret; - - ret = (xmlXPathObjectPtr) - cache->numberObjs->items[--cache->numberObjs->number]; - ret->type = XPATH_NUMBER; - ret->floatval = val; - return(ret); - } else if ((cache->miscObjs != NULL) && - (cache->miscObjs->number != 0)) - { - xmlXPathObjectPtr ret; + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; - ret = (xmlXPathObjectPtr) - cache->miscObjs->items[--cache->miscObjs->number]; + if ((ctxt != NULL) && (ctxt->cache != NULL)) { + xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; + if (cache->miscObjs != NULL) { + ret = cache->miscObjs; + cache->miscObjs = (void *) ret->stringval; + cache->numMisc -= 1; + ret->stringval = NULL; ret->type = XPATH_NUMBER; ret->floatval = val; return(ret); } } - return(xmlXPathNewFloat(val)); -} - -/** - * xmlXPathCacheConvertString: - * @ctxt: the XPath context - * @val: an XPath object - * - * This is the cached version of xmlXPathConvertString(). - * Converts an existing object to its string() equivalent - * - * Returns a created or reused object, the old one is freed (cached) - * (or the operation is done directly on @val) - */ -static xmlXPathObjectPtr -xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { - xmlChar *res = NULL; - - if (val == NULL) - return(xmlXPathCacheNewCString(ctxt, "")); - - switch (val->type) { - case XPATH_UNDEFINED: - break; - case XPATH_NODESET: - case XPATH_XSLT_TREE: - res = xmlXPathCastNodeSetToString(val->nodesetval); - break; - case XPATH_STRING: - return(val); - case XPATH_BOOLEAN: - res = xmlXPathCastBooleanToString(val->boolval); - break; - case XPATH_NUMBER: - res = xmlXPathCastNumberToString(val->floatval); - break; - case XPATH_USERS: -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - case XPATH_RANGE: - case XPATH_LOCATIONSET: -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO; - break; - } - xmlXPathReleaseObject(ctxt, val); - if (res == NULL) - return(xmlXPathCacheNewCString(ctxt, "")); - return(xmlXPathCacheWrapString(ctxt, res)); + ret = xmlXPathNewFloat(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); + return(ret); } /** * xmlXPathCacheObjectCopy: - * @ctxt: the XPath context + * @pctxt the XPath context * @val: the original object * * This is the cached version of xmlXPathObjectCopy(). @@ -2184,83 +1947,104 @@ xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { * Returns a created or reused created object. */ static xmlXPathObjectPtr -xmlXPathCacheObjectCopy(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) +xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt, xmlXPathObjectPtr val) { + xmlXPathObjectPtr ret; + xmlXPathContextPtr ctxt = pctxt->context; + if (val == NULL) return(NULL); - if (XP_HAS_CACHE(ctxt)) { + if ((ctxt != NULL) && (ctxt->cache != NULL)) { switch (val->type) { - case XPATH_NODESET: - return(xmlXPathCacheWrapNodeSet(ctxt, - xmlXPathNodeSetMerge(NULL, val->nodesetval))); + case XPATH_NODESET: { + xmlNodeSetPtr set; + + set = xmlXPathNodeSetMerge(NULL, val->nodesetval); + if (set == NULL) { + xmlXPathPErrMemory(pctxt); + return(NULL); + } + return(xmlXPathCacheWrapNodeSet(pctxt, set)); + } case XPATH_STRING: - return(xmlXPathCacheNewString(ctxt, val->stringval)); + return(xmlXPathCacheNewString(pctxt, val->stringval)); case XPATH_BOOLEAN: - return(xmlXPathCacheNewBoolean(ctxt, val->boolval)); + return(xmlXPathCacheNewBoolean(pctxt, val->boolval)); case XPATH_NUMBER: - return(xmlXPathCacheNewFloat(ctxt, val->floatval)); + return(xmlXPathCacheNewFloat(pctxt, val->floatval)); default: break; } } - return(xmlXPathObjectCopy(val)); -} - -/** - * xmlXPathCacheConvertBoolean: - * @ctxt: the XPath context - * @val: an XPath object - * - * This is the cached version of xmlXPathConvertBoolean(). - * Converts an existing object to its boolean() equivalent - * - * Returns a created or reused object, the old one is freed (or the operation - * is done directly on @val) - */ -static xmlXPathObjectPtr -xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { - xmlXPathObjectPtr ret; - - if (val == NULL) - return(xmlXPathCacheNewBoolean(ctxt, 0)); - if (val->type == XPATH_BOOLEAN) - return(val); - ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val)); - xmlXPathReleaseObject(ctxt, val); + ret = xmlXPathObjectCopy(val); + if (ret == NULL) + xmlXPathPErrMemory(pctxt); return(ret); } +/************************************************************************ + * * + * Parser stacks related functions and macros * + * * + ************************************************************************/ + /** - * xmlXPathCacheConvertNumber: - * @ctxt: the XPath context + * xmlXPathCastToNumberInternal: + * @ctxt: parser context * @val: an XPath object * - * This is the cached version of xmlXPathConvertNumber(). - * Converts an existing object to its number() equivalent + * Converts an XPath object to its number value * - * Returns a created or reused object, the old one is freed (or the operation - * is done directly on @val) + * Returns the number value */ -static xmlXPathObjectPtr -xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { - xmlXPathObjectPtr ret; +static double +xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr val) { + double ret = 0.0; if (val == NULL) - return(xmlXPathCacheNewFloat(ctxt, 0.0)); - if (val->type == XPATH_NUMBER) - return(val); - ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val)); - xmlXPathReleaseObject(ctxt, val); + return(xmlXPathNAN); + switch (val->type) { + case XPATH_UNDEFINED: + ret = xmlXPathNAN; + break; + case XPATH_NODESET: + case XPATH_XSLT_TREE: { + xmlChar *str; + + str = xmlXPathCastNodeSetToString(val->nodesetval); + if (str == NULL) { + xmlXPathPErrMemory(ctxt); + ret = xmlXPathNAN; + } else { + ret = xmlXPathCastStringToNumber(str); + xmlFree(str); + } + break; + } + case XPATH_STRING: + ret = xmlXPathCastStringToNumber(val->stringval); + break; + case XPATH_NUMBER: + ret = val->floatval; + break; + case XPATH_BOOLEAN: + ret = xmlXPathCastBooleanToNumber(val->boolval); + break; + case XPATH_USERS: +#ifdef LIBXML_XPTR_LOCS_ENABLED + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: +#endif /* LIBXML_XPTR_LOCS_ENABLED */ + /* TODO */ + ret = xmlXPathNAN; + break; + } return(ret); } -/************************************************************************ - * * - * Parser stacks related functions and macros * - * * - ************************************************************************/ - /** * valuePop: * @ctxt: an XPath evaluation context @@ -2304,17 +2088,16 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) if (ctxt == NULL) return(-1); if (value == NULL) { /* - * A NULL value typically indicates that a memory allocation failed, - * so we set ctxt->error here to propagate the error. + * A NULL value typically indicates that a memory allocation failed. */ - ctxt->error = XPATH_MEMORY_ERROR; + xmlXPathPErrMemory(ctxt); return(-1); } if (ctxt->valueNr >= ctxt->valueMax) { xmlXPathObjectPtr *tmp; if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) { - xmlXPathPErrMemory(ctxt, "XPath stack depth limit reached\n"); + xmlXPathPErrMemory(ctxt); xmlXPathFreeObject(value); return (-1); } @@ -2322,7 +2105,7 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) 2 * ctxt->valueMax * sizeof(ctxt->valueTab[0])); if (tmp == NULL) { - xmlXPathPErrMemory(ctxt, "pushing value\n"); + xmlXPathPErrMemory(ctxt); xmlXPathFreeObject(value); return (-1); } @@ -2381,7 +2164,7 @@ xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) { return(0); } if (obj->type != XPATH_NUMBER) - ret = xmlXPathCastToNumber(obj); + ret = xmlXPathCastToNumberInternal(ctxt, obj); else ret = obj->floatval; xmlXPathReleaseObject(ctxt->context, obj); @@ -2407,10 +2190,9 @@ xmlXPathPopString (xmlXPathParserContextPtr ctxt) { xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); return(NULL); } - ret = xmlXPathCastToString(obj); /* this does required strdup */ - /* TODO: needs refactoring somewhere else */ - if (obj->stringval == ret) - obj->stringval = NULL; + ret = xmlXPathCastToString(obj); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); xmlXPathReleaseObject(ctxt->context, obj); return(ret); } @@ -2939,16 +2721,25 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) { * Allocate a new Namespace and fill the fields. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlXPathErrMemory(NULL, "duplicating namespace\n"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_NAMESPACE_DECL; - if (ns->href != NULL) + if (ns->href != NULL) { cur->href = xmlStrdup(ns->href); - if (ns->prefix != NULL) + if (cur->href == NULL) { + xmlFree(cur); + return(NULL); + } + } + if (ns->prefix != NULL) { cur->prefix = xmlStrdup(ns->prefix); + if (cur->prefix == NULL) { + xmlFree((xmlChar *) cur->href); + xmlFree(cur); + return(NULL); + } + } cur->next = (xmlNsPtr) node; return((xmlNodePtr) cur); } @@ -2988,16 +2779,13 @@ xmlXPathNodeSetCreate(xmlNodePtr val) { xmlNodeSetPtr ret; ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating nodeset\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlNodeSet)); if (val != NULL) { ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (ret->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "creating nodeset\n"); xmlFree(ret); return(NULL); } @@ -3094,26 +2882,20 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (cur->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (cur->nodeTab == NULL) return(-1); - } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); + if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) return(-1); - } temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (temp == NULL) return(-1); - } cur->nodeMax *= 2; cur->nodeTab = temp; } @@ -3152,26 +2934,20 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (cur->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (cur->nodeTab == NULL) return(-1); - } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); + if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) return(-1); - } temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (temp == NULL) return(-1); - } cur->nodeMax *= 2; cur->nodeTab = temp; } @@ -3208,26 +2984,20 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (cur->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (cur->nodeTab == NULL) return(-1); - } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); + if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) return(-1); - } temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "growing nodeset\n"); + if (temp == NULL) return(-1); - } cur->nodeTab = temp; cur->nodeMax *= 2; } @@ -3260,12 +3030,13 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { int i, j, initNr, skip; xmlNodePtr n1, n2; - if (val2 == NULL) return(val1); if (val1 == NULL) { val1 = xmlXPathNodeSetCreate(NULL); if (val1 == NULL) return (NULL); } + if (val2 == NULL) + return(val1); /* @@ with_ns to check whether namespace nodes should be looked at @@ */ initNr = val1->nodeNr; @@ -3301,26 +3072,20 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { if (val1->nodeMax == 0) { val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (val1->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (val1->nodeTab == NULL) goto error; - } memset(val1->nodeTab, 0 , XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); val1->nodeMax = XML_NODESET_DEFAULT; } else if (val1->nodeNr == val1->nodeMax) { xmlNodePtr *temp; - if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); + if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) goto error; - } temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (temp == NULL) goto error; - } val1->nodeTab = temp; val1->nodeMax *= 2; } @@ -3393,26 +3158,20 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2) if (set1->nodeMax == 0) { set1->nodeTab = (xmlNodePtr *) xmlMalloc( XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (set1->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (set1->nodeTab == NULL) goto error; - } memset(set1->nodeTab, 0, XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); set1->nodeMax = XML_NODESET_DEFAULT; } else if (set1->nodeNr >= set1->nodeMax) { xmlNodePtr *temp; - if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); + if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) goto error; - } temp = (xmlNodePtr *) xmlRealloc( set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (temp == NULL) goto error; - } set1->nodeTab = temp; set1->nodeMax *= 2; } @@ -3454,26 +3213,20 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2) if (set1->nodeMax == 0) { set1->nodeTab = (xmlNodePtr *) xmlMalloc( XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); - if (set1->nodeTab == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (set1->nodeTab == NULL) goto error; - } memset(set1->nodeTab, 0, XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); set1->nodeMax = XML_NODESET_DEFAULT; } else if (set1->nodeNr >= set1->nodeMax) { xmlNodePtr *temp; - if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { - xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); + if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) goto error; - } temp = (xmlNodePtr *) xmlRealloc( set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); - if (temp == NULL) { - xmlXPathErrMemory(NULL, "merging nodeset\n"); + if (temp == NULL) goto error; - } set1->nodeTab = temp; set1->nodeMax *= 2; } @@ -3632,34 +3385,6 @@ xmlXPathNodeSetKeepLast(xmlNodeSetPtr set) set->nodeNr = 1; } -/** - * xmlXPathFreeValueTree: - * @obj: the xmlNodeSetPtr to free - * - * Free the NodeSet compound and the actual tree, this is different - * from xmlXPathFreeNodeSet() - */ -static void -xmlXPathFreeValueTree(xmlNodeSetPtr obj) { - int i; - - if (obj == NULL) return; - - if (obj->nodeTab != NULL) { - for (i = 0;i < obj->nodeNr;i++) { - if (obj->nodeTab[i] != NULL) { - if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) { - xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]); - } else { - xmlFreeNodeList(obj->nodeTab[i]); - } - } - } - xmlFree(obj->nodeTab); - } - xmlFree(obj); -} - /** * xmlXPathNewNodeSet: * @val: the NodePtr value @@ -3674,15 +3399,16 @@ xmlXPathNewNodeSet(xmlNodePtr val) { xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating nodeset\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_NODESET; ret->boolval = 0; - /* TODO: Check memory error. */ ret->nodesetval = xmlXPathNodeSetCreate(val); + if (ret->nodesetval == NULL) { + xmlFree(ret); + return(NULL); + } /* @@ with_ns to check whether namespace nodes should be looked at @@ */ return(ret); } @@ -3700,16 +3426,11 @@ xmlXPathObjectPtr xmlXPathNewValueTree(xmlNodePtr val) { xmlXPathObjectPtr ret; - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating result value tree\n"); + ret = xmlXPathNewNodeSet(val); + if (ret == NULL) return(NULL); - } - memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_XSLT_TREE; - ret->boolval = 1; - ret->user = (void *) val; - ret->nodesetval = xmlXPathNodeSetCreate(val); + return(ret); } @@ -3726,7 +3447,6 @@ xmlXPathObjectPtr xmlXPathNewNodeSetList(xmlNodeSetPtr val) { xmlXPathObjectPtr ret; - int i; if (val == NULL) ret = NULL; @@ -3735,12 +3455,12 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val) else { ret = xmlXPathNewNodeSet(val->nodeTab[0]); if (ret) { - for (i = 1; i < val->nodeNr; ++i) { - /* TODO: Propagate memory error. */ - if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]) - < 0) break; - } - } + ret->nodesetval = xmlXPathNodeSetMerge(NULL, val); + if (ret->nodesetval == NULL) { + xmlFree(ret); + return(NULL); + } + } } return (ret); @@ -3762,7 +3482,6 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating node set object\n"); xmlXPathFreeNodeSet(val); return(NULL); } @@ -3805,8 +3524,9 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { if (xmlXPathNodeSetIsEmpty(nodes2)) return(nodes1); - /* TODO: Check memory error. */ ret = xmlXPathNodeSetCreate(NULL); + if (ret == NULL) + return(NULL); if (xmlXPathNodeSetIsEmpty(nodes1)) return(ret); @@ -3815,9 +3535,10 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { for (i = 0; i < l1; i++) { cur = xmlXPathNodeSetItem(nodes1, i); if (!xmlXPathNodeSetContains(nodes2, cur)) { - /* TODO: Propagate memory error. */ - if (xmlXPathNodeSetAddUnique(ret, cur) < 0) - break; + if (xmlXPathNodeSetAddUnique(ret, cur) < 0) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } } } return(ret); @@ -3852,9 +3573,10 @@ xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) { for (i = 0; i < l1; i++) { cur = xmlXPathNodeSetItem(nodes1, i); if (xmlXPathNodeSetContains(nodes2, cur)) { - /* TODO: Propagate memory error. */ - if (xmlXPathNodeSetAddUnique(ret, cur) < 0) - break; + if (xmlXPathNodeSetAddUnique(ret, cur) < 0) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } } } return(ret); @@ -3992,9 +3714,10 @@ xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) { cur = xmlXPathNodeSetItem(nodes, i); if (cur == node) break; - /* TODO: Propagate memory error. */ - if (xmlXPathNodeSetAddUnique(ret, cur) < 0) - break; + if (xmlXPathNodeSetAddUnique(ret, cur) < 0) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } } return(ret); } @@ -4098,9 +3821,10 @@ xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) { cur = xmlXPathNodeSetItem(nodes, i); if (cur == node) break; - /* TODO: Propagate memory error. */ - if (xmlXPathNodeSetAddUnique(ret, cur) < 0) - break; + if (xmlXPathNodeSetAddUnique(ret, cur) < 0) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } } xmlXPathNodeSetSort(ret); /* bug 413451 */ return(ret); @@ -4208,6 +3932,8 @@ xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name, int xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri, xmlXPathFunction f) { + int ret; + if (ctxt == NULL) return(-1); if (name == NULL) @@ -4215,13 +3941,21 @@ xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name, if (ctxt->funcHash == NULL) ctxt->funcHash = xmlHashCreate(0); - if (ctxt->funcHash == NULL) + if (ctxt->funcHash == NULL) { + xmlXPathErrMemory(ctxt); return(-1); + } if (f == NULL) return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL)); XML_IGNORE_FPTR_CAST_WARNINGS - return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f)); + ret = xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f); XML_POP_WARNINGS + if (ret < 0) { + xmlXPathErrMemory(ctxt); + return(-1); + } + + return(0); } /** @@ -4450,8 +4184,7 @@ xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, if (name == NULL) return(NULL); - return(xmlXPathCacheObjectCopy(ctxt, (xmlXPathObjectPtr) - xmlHashLookup2(ctxt->varHash, name, ns_uri))); + return(xmlXPathObjectCopy(xmlHashLookup2(ctxt->varHash, name, ns_uri))); } /** @@ -4494,17 +4227,22 @@ xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix, if (ctxt->nsHash == NULL) ctxt->nsHash = xmlHashCreate(10); - if (ctxt->nsHash == NULL) + if (ctxt->nsHash == NULL) { + xmlXPathErrMemory(ctxt); return(-1); + } if (ns_uri == NULL) return(xmlHashRemoveEntry(ctxt->nsHash, prefix, xmlHashDefaultDeallocator)); copy = xmlStrdup(ns_uri); - if (copy == NULL) + if (copy == NULL) { + xmlXPathErrMemory(ctxt); return(-1); + } if (xmlHashUpdateEntry(ctxt->nsHash, prefix, copy, xmlHashDefaultDeallocator) < 0) { + xmlXPathErrMemory(ctxt); xmlFree(copy); return(-1); } @@ -4529,10 +4267,8 @@ xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) { if (prefix == NULL) return(NULL); -#ifdef XML_XML_NAMESPACE if (xmlStrEqual(prefix, (const xmlChar *) "xml")) return(XML_XML_NAMESPACE); -#endif if (ctxt->namespaces != NULL) { int i; @@ -4583,10 +4319,8 @@ xmlXPathNewFloat(double val) { xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating float object\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_NUMBER; ret->floatval = val; @@ -4606,10 +4340,8 @@ xmlXPathNewBoolean(int val) { xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating boolean object\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_BOOLEAN; ret->boolval = (val != 0); @@ -4629,10 +4361,8 @@ xmlXPathNewString(const xmlChar *val) { xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating string object\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_STRING; if (val == NULL) @@ -4661,7 +4391,6 @@ xmlXPathWrapString (xmlChar *val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating string object\n"); xmlFree(val); return(NULL); } @@ -4710,10 +4439,8 @@ xmlXPathWrapExternal (void *val) { xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating user object\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_USERS; ret->user = val; @@ -4736,10 +4463,8 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "copying object\n"); + if (ret == NULL) return(NULL); - } memcpy(ret, val , sizeof(xmlXPathObject)); switch (val->type) { case XPATH_BOOLEAN: @@ -4790,8 +4515,11 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { break; #endif case XPATH_NODESET: - /* TODO: Check memory error. */ ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval); + if (ret->nodesetval == NULL) { + xmlFree(ret); + return(NULL); + } /* Do not deallocate the copied tree value */ ret->boolval = 0; break; @@ -4806,10 +4534,9 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { case XPATH_USERS: ret->user = val->user; break; - case XPATH_UNDEFINED: - xmlGenericError(xmlGenericErrorContext, - "xmlXPathObjectCopy: unsupported type %d\n", - val->type); + default: + xmlFree(ret); + ret = NULL; break; } return(ret); @@ -4825,20 +4552,8 @@ void xmlXPathFreeObject(xmlXPathObjectPtr obj) { if (obj == NULL) return; if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) { - if (obj->boolval) { -#if 0 - if (obj->user != NULL) { - xmlXPathFreeNodeSet(obj->nodesetval); - xmlFreeNodeList((xmlNodePtr) obj->user); - } else -#endif - obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */ - if (obj->nodesetval != NULL) - xmlXPathFreeValueTree(obj->nodesetval); - } else { - if (obj->nodesetval != NULL) - xmlXPathFreeNodeSet(obj->nodesetval); - } + if (obj->nodesetval != NULL) + xmlXPathFreeNodeSet(obj->nodesetval); #ifdef LIBXML_XPTR_LOCS_ENABLED } else if (obj->type == XPATH_LOCATIONSET) { if (obj->user != NULL) @@ -4866,12 +4581,6 @@ xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) { static void xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) { -#define XP_CACHE_ADD(sl, o) if (sl == NULL) { \ - sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \ - if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj; - -#define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n)) - if (obj == NULL) return; if ((ctxt == NULL) || (ctxt->cache == NULL)) { @@ -4884,20 +4593,11 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) case XPATH_NODESET: case XPATH_XSLT_TREE: if (obj->nodesetval != NULL) { - if (obj->boolval) { - /* - * It looks like the @boolval is used for - * evaluation if this an XSLT Result Tree Fragment. - * TODO: Check if this assumption is correct. - */ - obj->type = XPATH_XSLT_TREE; /* just for debugging */ - xmlXPathFreeValueTree(obj->nodesetval); - obj->nodesetval = NULL; - } else if ((obj->nodesetval->nodeMax <= 40) && - (XP_CACHE_WANTS(cache->nodesetObjs, - cache->maxNodeset))) - { - XP_CACHE_ADD(cache->nodesetObjs, obj); + if ((obj->nodesetval->nodeMax <= 40) && + (cache->numNodeset < cache->maxNodeset)) { + obj->stringval = (void *) cache->nodesetObjs; + cache->nodesetObjs = obj; + cache->numNodeset += 1; goto obj_cached; } else { xmlXPathFreeNodeSet(obj->nodesetval); @@ -4908,23 +4608,10 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) case XPATH_STRING: if (obj->stringval != NULL) xmlFree(obj->stringval); - - if (XP_CACHE_WANTS(cache->stringObjs, cache->maxString)) { - XP_CACHE_ADD(cache->stringObjs, obj); - goto obj_cached; - } + obj->stringval = NULL; break; case XPATH_BOOLEAN: - if (XP_CACHE_WANTS(cache->booleanObjs, cache->maxBoolean)) { - XP_CACHE_ADD(cache->booleanObjs, obj); - goto obj_cached; - } - break; case XPATH_NUMBER: - if (XP_CACHE_WANTS(cache->numberObjs, cache->maxNumber)) { - XP_CACHE_ADD(cache->numberObjs, obj); - goto obj_cached; - } break; #ifdef LIBXML_XPTR_LOCS_ENABLED case XPATH_LOCATIONSET: @@ -4940,22 +4627,22 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) /* * Fallback to adding to the misc-objects slot. */ - if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) { - XP_CACHE_ADD(cache->miscObjs, obj); - } else + if (cache->numMisc >= cache->maxMisc) goto free_obj; + obj->stringval = (void *) cache->miscObjs; + cache->miscObjs = obj; + cache->numMisc += 1; obj_cached: + obj->boolval = 0; if (obj->nodesetval != NULL) { xmlNodeSetPtr tmpset = obj->nodesetval; /* - * TODO: Due to those nasty ns-nodes, we need to traverse - * the list and free the ns-nodes. - * URGENT TODO: Check if it's actually slowing things down. - * Maybe we shouldn't try to preserve the list. + * Due to those nasty ns-nodes, we need to traverse + * the list and free the ns-nodes. */ - if (tmpset->nodeNr > 1) { + if (tmpset->nodeNr > 0) { int i; xmlNodePtr node; @@ -4967,16 +4654,9 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) xmlXPathNodeSetFreeNs((xmlNsPtr) node); } } - } else if (tmpset->nodeNr == 1) { - if ((tmpset->nodeTab[0] != NULL) && - (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL)) - xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]); } tmpset->nodeNr = 0; - memset(obj, 0, sizeof(xmlXPathObject)); - obj->nodesetval = tmpset; - } else - memset(obj, 0, sizeof(xmlXPathObject)); + } return; @@ -5061,10 +4741,7 @@ xmlXPathCastNumberToString (double val) { */ xmlChar * xmlXPathCastNodeToString (xmlNodePtr node) { -xmlChar *ret; - if ((ret = xmlNodeGetContent(node)) == NULL) - ret = xmlStrdup((const xmlChar *) ""); - return(ret); + return(xmlNodeGetContent(node)); } /** @@ -5123,7 +4800,7 @@ xmlXPathCastToString(xmlXPathObjectPtr val) { case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ ret = xmlStrdup((const xmlChar *) ""); break; } @@ -5167,7 +4844,7 @@ xmlXPathConvertString(xmlXPathObjectPtr val) { case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO; + /* TODO */ break; } xmlXPathFreeObject(val); @@ -5205,23 +4882,25 @@ xmlXPathCastStringToNumber(const xmlChar * val) { } /** - * xmlXPathCastNodeToNumber: + * xmlXPathNodeToNumberInternal: * @node: a node * * Converts a node to its number value * * Returns the number value */ -double -xmlXPathCastNodeToNumber (xmlNodePtr node) { +static double +xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt, xmlNodePtr node) { xmlChar *strval; double ret; if (node == NULL) return(xmlXPathNAN); strval = xmlXPathCastNodeToString(node); - if (strval == NULL) + if (strval == NULL) { + xmlXPathPErrMemory(ctxt); return(xmlXPathNAN); + } ret = xmlXPathCastStringToNumber(strval); xmlFree(strval); @@ -5229,70 +4908,52 @@ xmlXPathCastNodeToNumber (xmlNodePtr node) { } /** - * xmlXPathCastNodeSetToNumber: - * @ns: a node-set + * xmlXPathCastNodeToNumber: + * @node: a node * - * Converts a node-set to its number value + * Converts a node to its number value * * Returns the number value */ double -xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) { - xmlChar *str; - double ret; - - if (ns == NULL) - return(xmlXPathNAN); - str = xmlXPathCastNodeSetToString(ns); - ret = xmlXPathCastStringToNumber(str); - xmlFree(str); - return(ret); +xmlXPathCastNodeToNumber (xmlNodePtr node) { + return(xmlXPathNodeToNumberInternal(NULL, node)); } /** - * xmlXPathCastToNumber: - * @val: an XPath object - * - * Converts an XPath object to its number value + * xmlXPathCastNodeSetToNumber: + * @ns: a node-set * - * Returns the number value - */ -double -xmlXPathCastToNumber(xmlXPathObjectPtr val) { - double ret = 0.0; - - if (val == NULL) - return(xmlXPathNAN); - switch (val->type) { - case XPATH_UNDEFINED: - ret = xmlXPathNAN; - break; - case XPATH_NODESET: - case XPATH_XSLT_TREE: - ret = xmlXPathCastNodeSetToNumber(val->nodesetval); - break; - case XPATH_STRING: - ret = xmlXPathCastStringToNumber(val->stringval); - break; - case XPATH_NUMBER: - ret = val->floatval; - break; - case XPATH_BOOLEAN: - ret = xmlXPathCastBooleanToNumber(val->boolval); - break; - case XPATH_USERS: -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - case XPATH_RANGE: - case XPATH_LOCATIONSET: -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO; - ret = xmlXPathNAN; - break; - } + * Converts a node-set to its number value + * + * Returns the number value + */ +double +xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) { + xmlChar *str; + double ret; + + if (ns == NULL) + return(xmlXPathNAN); + str = xmlXPathCastNodeSetToString(ns); + ret = xmlXPathCastStringToNumber(str); + xmlFree(str); return(ret); } +/** + * xmlXPathCastToNumber: + * @val: an XPath object + * + * Converts an XPath object to its number value + * + * Returns the number value + */ +double +xmlXPathCastToNumber(xmlXPathObjectPtr val) { + return(xmlXPathCastToNumberInternal(NULL, val)); +} + /** * xmlXPathConvertNumber: * @val: an XPath object @@ -5397,7 +5058,7 @@ xmlXPathCastToBoolean (xmlXPathObjectPtr val) { case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO; + /* TODO */ ret = 0; break; } @@ -5446,10 +5107,8 @@ xmlXPathNewContext(xmlDocPtr doc) { xmlXPathContextPtr ret; ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext)); - if (ret == NULL) { - xmlXPathErrMemory(NULL, "creating context\n"); + if (ret == NULL) return(NULL); - } memset(ret, 0 , sizeof(xmlXPathContext)); ret->doc = doc; ret->node = NULL; @@ -5460,8 +5119,6 @@ xmlXPathNewContext(xmlDocPtr doc) { ret->max_types = 0; ret->types = NULL; - ret->funcHash = xmlHashCreate(0); - ret->nb_axis = 0; ret->max_axis = 0; ret->axis = NULL; @@ -5481,6 +5138,11 @@ xmlXPathNewContext(xmlDocPtr doc) { xmlXPathRegisterAllFunctions(ret); + if (ret->lastError.code != XML_ERR_OK) { + xmlXPathFreeContext(ret); + return(NULL); + } + return(ret); } @@ -5503,43 +5165,33 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) { xmlFree(ctxt); } +/** + * xmlXPathSetErrorHandler: + * @ctxt: the XPath context + * @handler: error handler + * @data: user data which will be passed to the handler + * + * Register a callback function that will be called on errors and + * warnings. If handler is NULL, the error handler will be deactivated. + * + * Available since 2.13.0. + */ +void +xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt, + xmlStructuredErrorFunc handler, void *data) { + if (ctxt == NULL) + return; + + ctxt->error = handler; + ctxt->userData = data; +} + /************************************************************************ * * * Routines to handle XPath parser contexts * * * ************************************************************************/ -#define CHECK_CTXT(ctxt) \ - if (ctxt == NULL) { \ - __xmlRaiseError(NULL, NULL, NULL, \ - NULL, NULL, XML_FROM_XPATH, \ - XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ - __FILE__, __LINE__, \ - NULL, NULL, NULL, 0, 0, \ - "NULL context pointer\n"); \ - return(NULL); \ - } \ - -#define CHECK_CTXT_NEG(ctxt) \ - if (ctxt == NULL) { \ - __xmlRaiseError(NULL, NULL, NULL, \ - NULL, NULL, XML_FROM_XPATH, \ - XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ - __FILE__, __LINE__, \ - NULL, NULL, NULL, 0, 0, \ - "NULL context pointer\n"); \ - return(-1); \ - } \ - - -#define CHECK_CONTEXT(ctxt) \ - if ((ctxt == NULL) || (ctxt->doc == NULL) || \ - (ctxt->doc->children == NULL)) { \ - xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT); \ - return(NULL); \ - } - - /** * xmlXPathNewParserContext: * @str: the XPath expression @@ -5555,7 +5207,7 @@ xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) { ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); if (ret == NULL) { - xmlXPathErrMemory(ctxt, "creating parser context\n"); + xmlXPathErrMemory(ctxt); return(NULL); } memset(ret, 0 , sizeof(xmlXPathParserContext)); @@ -5564,6 +5216,7 @@ xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) { ret->comp = xmlXPathNewCompExpr(); if (ret->comp == NULL) { + xmlXPathErrMemory(ctxt); xmlFree(ret->valueTab); xmlFree(ret); return(NULL); @@ -5591,7 +5244,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) { ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); if (ret == NULL) { - xmlXPathErrMemory(ctxt, "creating evaluation context\n"); + xmlXPathErrMemory(ctxt); return(NULL); } memset(ret, 0 , sizeof(xmlXPathParserContext)); @@ -5601,7 +5254,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) { xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ret->valueTab == NULL) { xmlFree(ret); - xmlXPathErrMemory(ctxt, "creating evaluation context\n"); + xmlXPathErrMemory(ctxt); return(NULL); } ret->valueNr = 0; @@ -5822,15 +5475,16 @@ xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict, for (i = 0;i < ns->nodeNr;i++) { str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); if (str2 != NULL) { - valuePush(ctxt, - xmlXPathCacheNewString(ctxt->context, str2)); + valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2)); xmlFree(str2); xmlXPathNumberFunction(ctxt, 1); - valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, f)); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, f)); ret = xmlXPathCompareValues(ctxt, inf, strict); if (ret) break; - } + } else { + xmlXPathPErrMemory(ctxt); + } } } xmlXPathReleaseObject(ctxt->context, arg); @@ -5878,13 +5532,15 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict, str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); if (str2 != NULL) { valuePush(ctxt, - xmlXPathCacheNewString(ctxt->context, str2)); + xmlXPathCacheNewString(ctxt, str2)); xmlFree(str2); - valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, s)); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, s)); ret = xmlXPathCompareValues(ctxt, inf, strict); if (ret) break; - } + } else { + xmlXPathPErrMemory(ctxt); + } } } xmlXPathReleaseObject(ctxt->context, arg); @@ -5921,7 +5577,7 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict, * and then the comparison must be done when possible */ static int -xmlXPathCompareNodeSets(int inf, int strict, +xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict, xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { int i, j, init = 0; double val1; @@ -5958,19 +5614,19 @@ xmlXPathCompareNodeSets(int inf, int strict, values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double)); if (values2 == NULL) { - /* TODO: Propagate memory error. */ - xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathPErrMemory(ctxt); xmlXPathFreeObject(arg1); xmlXPathFreeObject(arg2); return(0); } for (i = 0;i < ns1->nodeNr;i++) { - val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]); + val1 = xmlXPathNodeToNumberInternal(ctxt, ns1->nodeTab[i]); if (xmlXPathIsNaN(val1)) continue; for (j = 0;j < ns2->nodeNr;j++) { if (init == 0) { - values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]); + values2[j] = xmlXPathNodeToNumberInternal(ctxt, + ns2->nodeTab[j]); } if (xmlXPathIsNaN(values2[j])) continue; @@ -6028,7 +5684,7 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict, return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val)); case XPATH_NODESET: case XPATH_XSLT_TREE: - return(xmlXPathCompareNodeSets(inf, strict, arg, val)); + return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val)); case XPATH_STRING: return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val)); case XPATH_BOOLEAN: @@ -6037,10 +5693,6 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict, valuePush(ctxt, val); return(xmlXPathCompareValues(ctxt, inf, strict)); default: - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompareNodeSetValue: Can't compare node set " - "and object of type %d\n", - val->type); xmlXPathReleaseObject(ctxt->context, arg); xmlXPathReleaseObject(ctxt->context, val); XP_ERROR0(XPATH_INVALID_TYPE); @@ -6063,7 +5715,8 @@ xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict, * Returns 0 or 1 depending on the results of the test. */ static int -xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq) +xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr arg, const xmlChar * str, int neq) { int i; xmlNodeSetPtr ns; @@ -6084,22 +5737,20 @@ xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq) for (i = 0; i < ns->nodeNr; i++) { if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) { str2 = xmlNodeGetContent(ns->nodeTab[i]); - if ((str2 != NULL) && (xmlStrEqual(str, str2))) { + if (str2 == NULL) { + xmlXPathPErrMemory(ctxt); + return(0); + } + if (xmlStrEqual(str, str2)) { xmlFree(str2); if (neq) continue; return (1); - } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) { - if (neq) - continue; - return (1); } else if (neq) { - if (str2 != NULL) - xmlFree(str2); + xmlFree(str2); return (1); } - if (str2 != NULL) - xmlFree(str2); + xmlFree(str2); } else if (neq) return (1); } @@ -6139,7 +5790,7 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt, for (i=0;inodeNr;i++) { str2 = xmlXPathCastNodeToString(ns->nodeTab[i]); if (str2 != NULL) { - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, str2)); + valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2)); xmlFree(str2); xmlXPathNumberFunction(ctxt, 1); CHECK_ERROR0; @@ -6158,7 +5809,9 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt, if (neq) ret = 1; } - } + } else { + xmlXPathPErrMemory(ctxt); + } } } @@ -6184,7 +5837,8 @@ xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt, * Returns 0 or 1 depending on the results of the test. */ static int -xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) { +xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr arg1, + xmlXPathObjectPtr arg2, int neq) { int i, j; unsigned int *hashs1; unsigned int *hashs2; @@ -6220,30 +5874,26 @@ xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) { values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *)); if (values1 == NULL) { - /* TODO: Propagate memory error. */ - xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathPErrMemory(ctxt); return(0); } hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int)); if (hashs1 == NULL) { - /* TODO: Propagate memory error. */ - xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathPErrMemory(ctxt); xmlFree(values1); return(0); } memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *)); values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *)); if (values2 == NULL) { - /* TODO: Propagate memory error. */ - xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathPErrMemory(ctxt); xmlFree(hashs1); xmlFree(values1); return(0); } hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int)); if (hashs2 == NULL) { - /* TODO: Propagate memory error. */ - xmlXPathErrMemory(NULL, "comparing nodesets\n"); + xmlXPathPErrMemory(ctxt); xmlFree(hashs1); xmlFree(values1); xmlFree(values2); @@ -6262,10 +5912,16 @@ xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) { } } else { - if (values1[i] == NULL) + if (values1[i] == NULL) { values1[i] = xmlNodeGetContent(ns1->nodeTab[i]); - if (values2[j] == NULL) + if (values1[i] == NULL) + xmlXPathPErrMemory(ctxt); + } + if (values2[j] == NULL) { values2[j] = xmlNodeGetContent(ns2->nodeTab[j]); + if (values2[j] == NULL) + xmlXPathPErrMemory(ctxt); + } ret = xmlStrEqual(values1[i], values2[j]) ^ neq; if (ret) break; @@ -6322,7 +5978,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -6379,7 +6035,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -6440,7 +6096,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -6453,7 +6109,7 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -6511,7 +6167,7 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { break; case XPATH_NODESET: case XPATH_XSLT_TREE: - ret = xmlXPathEqualNodeSets(arg1, arg2, 0); + ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 0); break; case XPATH_BOOLEAN: if ((arg1->nodesetval == NULL) || @@ -6524,7 +6180,8 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0); break; case XPATH_STRING: - ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0); + ret = xmlXPathEqualNodeSetString(ctxt, arg1, + arg2->stringval, 0); break; case XPATH_USERS: #ifdef LIBXML_XPTR_LOCS_ENABLED @@ -6532,7 +6189,7 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; } xmlXPathReleaseObject(ctxt->context, arg1); @@ -6590,7 +6247,7 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { break; case XPATH_NODESET: case XPATH_XSLT_TREE: - ret = xmlXPathEqualNodeSets(arg1, arg2, 1); + ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 1); break; case XPATH_BOOLEAN: if ((arg1->nodesetval == NULL) || @@ -6603,7 +6260,8 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1); break; case XPATH_STRING: - ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1); + ret = xmlXPathEqualNodeSetString(ctxt, arg1, + arg2->stringval, 1); break; case XPATH_USERS: #ifdef LIBXML_XPTR_LOCS_ENABLED @@ -6611,7 +6269,7 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { case XPATH_RANGE: case XPATH_LOCATIONSET: #endif /* LIBXML_XPTR_LOCS_ENABLED */ - TODO + /* TODO */ break; } xmlXPathReleaseObject(ctxt->context, arg1); @@ -6671,7 +6329,7 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { */ if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) && ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){ - ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2); + ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2); } else { if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) { ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict, @@ -6783,7 +6441,7 @@ xmlXPathAddValues(xmlXPathParserContextPtr ctxt) { arg = valuePop(ctxt); if (arg == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - val = xmlXPathCastToNumber(arg); + val = xmlXPathCastToNumberInternal(ctxt, arg); xmlXPathReleaseObject(ctxt->context, arg); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); @@ -6806,7 +6464,7 @@ xmlXPathSubValues(xmlXPathParserContextPtr ctxt) { arg = valuePop(ctxt); if (arg == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - val = xmlXPathCastToNumber(arg); + val = xmlXPathCastToNumberInternal(ctxt, arg); xmlXPathReleaseObject(ctxt->context, arg); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); @@ -6829,7 +6487,7 @@ xmlXPathMultValues(xmlXPathParserContextPtr ctxt) { arg = valuePop(ctxt); if (arg == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - val = xmlXPathCastToNumber(arg); + val = xmlXPathCastToNumberInternal(ctxt, arg); xmlXPathReleaseObject(ctxt->context, arg); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); @@ -6853,7 +6511,7 @@ xmlXPathDivValues(xmlXPathParserContextPtr ctxt) { arg = valuePop(ctxt); if (arg == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - val = xmlXPathCastToNumber(arg); + val = xmlXPathCastToNumberInternal(ctxt, arg); xmlXPathReleaseObject(ctxt->context, arg); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); @@ -6876,7 +6534,7 @@ xmlXPathModValues(xmlXPathParserContextPtr ctxt) { arg = valuePop(ctxt); if (arg == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - arg2 = xmlXPathCastToNumber(arg); + arg2 = xmlXPathCastToNumberInternal(ctxt, arg); xmlXPathReleaseObject(ctxt->context, arg); CAST_TO_NUMBER; CHECK_TYPE(XPATH_NUMBER); @@ -7680,14 +7338,17 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { if (cur == NULL) { if (ctxt->context->tmpNsList != NULL) xmlFree(ctxt->context->tmpNsList); - ctxt->context->tmpNsList = - xmlGetNsList(ctxt->context->doc, ctxt->context->node); ctxt->context->tmpNsNr = 0; - if (ctxt->context->tmpNsList != NULL) { - while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) { - ctxt->context->tmpNsNr++; - } - } + if (xmlGetNsListSafe(ctxt->context->doc, ctxt->context->node, + &ctxt->context->tmpNsList) < 0) { + xmlXPathPErrMemory(ctxt); + return(NULL); + } + if (ctxt->context->tmpNsList != NULL) { + while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) { + ctxt->context->tmpNsNr++; + } + } return((xmlNodePtr) xmlXPathXMLNamespace); } if (ctxt->context->tmpNsNr > 0) { @@ -7750,8 +7411,8 @@ void xmlXPathRoot(xmlXPathParserContextPtr ctxt) { if ((ctxt == NULL) || (ctxt->context == NULL)) return; - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, - (xmlNodePtr) ctxt->context->doc)); + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, + (xmlNodePtr) ctxt->context->doc)); } /************************************************************************ @@ -7776,8 +7437,7 @@ xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(0); if (ctxt->context->contextSize >= 0) { valuePush(ctxt, - xmlXPathCacheNewFloat(ctxt->context, - (double) ctxt->context->contextSize)); + xmlXPathCacheNewFloat(ctxt, (double) ctxt->context->contextSize)); } else { XP_ERROR(XPATH_INVALID_CTXT_SIZE); } @@ -7798,9 +7458,8 @@ void xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(0); if (ctxt->context->proximityPosition >= 0) { - valuePush(ctxt, - xmlXPathCacheNewFloat(ctxt->context, - (double) ctxt->context->proximityPosition)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, + (double) ctxt->context->proximityPosition)); } else { XP_ERROR(XPATH_INVALID_CTXT_POSITION); } @@ -7826,9 +7485,9 @@ xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) { cur = valuePop(ctxt); if ((cur == NULL) || (cur->nodesetval == NULL)) - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0)); else - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, (double) cur->nodesetval->nodeNr)); xmlXPathReleaseObject(ctxt->context, cur); } @@ -7862,28 +7521,33 @@ xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) { cur++; ID = xmlStrndup(ids, cur - ids); - if (ID != NULL) { - /* - * We used to check the fact that the value passed - * was an NCName, but this generated much troubles for - * me and Aleksey Sanin, people blatantly violated that - * constraint, like Visa3D spec. - * if (xmlValidateNCName(ID, 1) == 0) - */ - attr = xmlGetID(doc, ID); - if (attr != NULL) { - if (attr->type == XML_ATTRIBUTE_NODE) - elem = attr->parent; - else if (attr->type == XML_ELEMENT_NODE) - elem = (xmlNodePtr) attr; - else - elem = NULL; - /* TODO: Check memory error. */ - if (elem != NULL) - xmlXPathNodeSetAdd(ret, elem); - } - xmlFree(ID); - } + if (ID == NULL) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } + /* + * We used to check the fact that the value passed + * was an NCName, but this generated much troubles for + * me and Aleksey Sanin, people blatantly violated that + * constraint, like Visa3D spec. + * if (xmlValidateNCName(ID, 1) == 0) + */ + attr = xmlGetID(doc, ID); + xmlFree(ID); + if (attr != NULL) { + if (attr->type == XML_ATTRIBUTE_NODE) + elem = attr->parent; + else if (attr->type == XML_ELEMENT_NODE) + elem = (xmlNodePtr) attr; + else + elem = NULL; + if (elem != NULL) { + if (xmlXPathNodeSetAdd(ret, elem) < 0) { + xmlXPathFreeNodeSet(ret); + return(NULL); + } + } + } while (IS_BLANK_CH(*cur)) cur++; ids = cur; @@ -7922,30 +7586,40 @@ xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlNodeSetPtr ns; int i; - /* TODO: Check memory error. */ ret = xmlXPathNodeSetCreate(NULL); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); if (obj->nodesetval != NULL) { for (i = 0; i < obj->nodesetval->nodeNr; i++) { tokens = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]); + if (tokens == NULL) + xmlXPathPErrMemory(ctxt); ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens); - /* TODO: Check memory error. */ + if (ns == NULL) + xmlXPathPErrMemory(ctxt); ret = xmlXPathNodeSetMerge(ret, ns); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); xmlXPathFreeNodeSet(ns); if (tokens != NULL) xmlFree(tokens); } } xmlXPathReleaseObject(ctxt->context, obj); - valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret)); return; } - obj = xmlXPathCacheConvertString(ctxt->context, obj); - if (obj == NULL) return; - ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval); - valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); + tokens = xmlXPathCastToString(obj); + if (tokens == NULL) + xmlXPathPErrMemory(ctxt); xmlXPathReleaseObject(ctxt->context, obj); + ret = xmlXPathGetElementsByIds(ctxt->context->doc, tokens); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); + xmlFree(tokens); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret)); return; } @@ -7969,8 +7643,7 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { if (ctxt == NULL) return; if (nargs == 0) { - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node)); + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node)); nargs = 1; } @@ -7982,7 +7655,7 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { cur = valuePop(ctxt); if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } else { int i = 0; /* Should be first in document order !!!!! */ switch (cur->nodesetval->nodeTab[i]->type) { @@ -7990,18 +7663,17 @@ xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { case XML_ATTRIBUTE_NODE: case XML_PI_NODE: if (cur->nodesetval->nodeTab[i]->name[0] == ' ') - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); else - valuePush(ctxt, - xmlXPathCacheNewString(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewString(ctxt, cur->nodesetval->nodeTab[i]->name)); break; case XML_NAMESPACE_DECL: - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewString(ctxt, ((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix)); break; default: - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } } xmlXPathReleaseObject(ctxt->context, cur); @@ -8028,8 +7700,7 @@ xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) { if (ctxt == NULL) return; if (nargs == 0) { - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node)); + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node)); nargs = 1; } CHECK_ARITY(1); @@ -8040,20 +7711,20 @@ xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) { cur = valuePop(ctxt); if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } else { int i = 0; /* Should be first in document order !!!!! */ switch (cur->nodesetval->nodeTab[i]->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: if (cur->nodesetval->nodeTab[i]->ns == NULL) - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); else - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewString(ctxt, cur->nodesetval->nodeTab[i]->ns->href)); break; default: - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } } xmlXPathReleaseObject(ctxt->context, cur); @@ -8087,8 +7758,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) xmlXPathObjectPtr cur; if (nargs == 0) { - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node)); + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node)); nargs = 1; } @@ -8100,7 +7770,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) cur = valuePop(ctxt); if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } else { int i = 0; /* Should be first in document order !!!!! */ @@ -8109,11 +7779,10 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) case XML_ATTRIBUTE_NODE: if (cur->nodesetval->nodeTab[i]->name[0] == ' ') valuePush(ctxt, - xmlXPathCacheNewCString(ctxt->context, "")); + xmlXPathCacheNewCString(ctxt, "")); else if ((cur->nodesetval->nodeTab[i]->ns == NULL) || (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) { - valuePush(ctxt, - xmlXPathCacheNewString(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewString(ctxt, cur->nodesetval->nodeTab[i]->name)); } else { xmlChar *fullname; @@ -8124,13 +7793,12 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) if (fullname == cur->nodesetval->nodeTab[i]->name) fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name); if (fullname == NULL) - xmlXPathPErrMemory(ctxt, NULL); - valuePush(ctxt, xmlXPathCacheWrapString( - ctxt->context, fullname)); + xmlXPathPErrMemory(ctxt); + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, fullname)); } break; default: - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, cur->nodesetval->nodeTab[i])); xmlXPathLocalNameFunction(ctxt, 1); } @@ -8178,19 +7846,28 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; + xmlChar *stringval; if (ctxt == NULL) return; if (nargs == 0) { - valuePush(ctxt, - xmlXPathCacheWrapString(ctxt->context, - xmlXPathCastNodeToString(ctxt->context->node))); + stringval = xmlXPathCastNodeToString(ctxt->context->node); + if (stringval == NULL) + xmlXPathPErrMemory(ctxt); + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, stringval)); return; } CHECK_ARITY(1); cur = valuePop(ctxt); if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - valuePush(ctxt, xmlXPathCacheConvertString(ctxt->context, cur)); + if (cur->type != XPATH_STRING) { + stringval = xmlXPathCastToString(cur); + if (stringval == NULL) + xmlXPathPErrMemory(ctxt); + xmlXPathReleaseObject(ctxt->context, cur); + cur = xmlXPathCacheWrapString(ctxt, stringval); + } + valuePush(ctxt, cur); } /** @@ -8213,12 +7890,14 @@ xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) { if ((ctxt == NULL) || (ctxt->context == NULL)) return; if (ctxt->context->node == NULL) { - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0)); } else { xmlChar *content; content = xmlXPathCastNodeToString(ctxt->context->node); - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + if (content == NULL) + xmlXPathPErrMemory(ctxt); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, xmlUTF8Strlen(content))); xmlFree(content); } @@ -8228,7 +7907,7 @@ xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) { CAST_TO_STRING; CHECK_TYPE(XPATH_STRING); cur = valuePop(ctxt); - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, xmlUTF8Strlen(cur->stringval))); xmlXPathReleaseObject(ctxt->context, cur); } @@ -8269,6 +7948,8 @@ xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) { XP_ERROR(XPATH_INVALID_TYPE); } tmp = xmlStrcat(newobj->stringval, cur->stringval); + if (tmp == NULL) + xmlXPathPErrMemory(ctxt); newobj->stringval = cur->stringval; cur->stringval = tmp; xmlXPathReleaseObject(ctxt->context, newobj); @@ -8304,9 +7985,9 @@ xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) { XP_ERROR(XPATH_INVALID_TYPE); } if (xmlStrstr(hay->stringval, needle->stringval)) - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1)); else - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0)); xmlXPathReleaseObject(ctxt->context, hay); xmlXPathReleaseObject(ctxt->context, needle); } @@ -8340,9 +8021,9 @@ xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) { } n = xmlStrlen(needle->stringval); if (xmlStrncmp(hay->stringval, needle->stringval, n)) - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0)); else - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1)); xmlXPathReleaseObject(ctxt->context, hay); xmlXPathReleaseObject(ctxt->context, needle); } @@ -8434,12 +8115,17 @@ xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) { } } - if (i < j) { - xmlChar *ret = xmlUTF8Strsub(str->stringval, i - 1, j - i); - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, ret)); + i -= 1; + j -= 1; + + if ((i < j) && (i < xmlUTF8Strlen(str->stringval))) { + xmlChar *ret = xmlUTF8Strsub(str->stringval, i, j - i); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); + valuePush(ctxt, xmlXPathCacheNewString(ctxt, ret)); xmlFree(ret); } else { - valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); + valuePush(ctxt, xmlXPathCacheNewCString(ctxt, "")); } xmlXPathReleaseObject(ctxt->context, str); @@ -8460,31 +8146,34 @@ xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) { */ void xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { - xmlXPathObjectPtr str; - xmlXPathObjectPtr find; - xmlBufPtr target; - const xmlChar *point; - int offset; - - CHECK_ARITY(2); - CAST_TO_STRING; - find = valuePop(ctxt); - CAST_TO_STRING; - str = valuePop(ctxt); - - target = xmlBufCreate(); - if (target) { + xmlXPathObjectPtr str = NULL; + xmlXPathObjectPtr find = NULL; + const xmlChar *point; + xmlChar *result; + + CHECK_ARITY(2); + CAST_TO_STRING; + find = valuePop(ctxt); + CAST_TO_STRING; + str = valuePop(ctxt); + if (ctxt->error != 0) + goto error; + point = xmlStrstr(str->stringval, find->stringval); - if (point) { - offset = point - str->stringval; - xmlBufAdd(target, str->stringval, offset); + if (point == NULL) { + result = xmlStrdup(BAD_CAST ""); + } else { + result = xmlStrndup(str->stringval, point - str->stringval); } - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, - xmlBufContent(target))); - xmlBufFree(target); - } - xmlXPathReleaseObject(ctxt->context, str); - xmlXPathReleaseObject(ctxt->context, find); + if (result == NULL) { + xmlXPathPErrMemory(ctxt); + goto error; + } + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result)); + +error: + xmlXPathReleaseObject(ctxt->context, str); + xmlXPathReleaseObject(ctxt->context, find); } /** @@ -8496,39 +8185,41 @@ xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { * string substring-after(string, string) * The substring-after function returns the substring of the first * argument string that follows the first occurrence of the second - * argument string in the first argument string, or the empty stringi + * argument string in the first argument string, or the empty string * if the first argument string does not contain the second argument * string. For example, substring-after("1999/04/01","/") returns 04/01, * and substring-after("1999/04/01","19") returns 99/04/01. */ void xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { - xmlXPathObjectPtr str; - xmlXPathObjectPtr find; - xmlBufPtr target; - const xmlChar *point; - int offset; - - CHECK_ARITY(2); - CAST_TO_STRING; - find = valuePop(ctxt); - CAST_TO_STRING; - str = valuePop(ctxt); - - target = xmlBufCreate(); - if (target) { + xmlXPathObjectPtr str = NULL; + xmlXPathObjectPtr find = NULL; + const xmlChar *point; + xmlChar *result; + + CHECK_ARITY(2); + CAST_TO_STRING; + find = valuePop(ctxt); + CAST_TO_STRING; + str = valuePop(ctxt); + if (ctxt->error != 0) + goto error; + point = xmlStrstr(str->stringval, find->stringval); - if (point) { - offset = point - str->stringval + xmlStrlen(find->stringval); - xmlBufAdd(target, &str->stringval[offset], - xmlStrlen(str->stringval) - offset); + if (point == NULL) { + result = xmlStrdup(BAD_CAST ""); + } else { + result = xmlStrdup(point + xmlStrlen(find->stringval)); } - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, - xmlBufContent(target))); - xmlBufFree(target); - } - xmlXPathReleaseObject(ctxt->context, str); - xmlXPathReleaseObject(ctxt->context, find); + if (result == NULL) { + xmlXPathPErrMemory(ctxt); + goto error; + } + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result)); + +error: + xmlXPathReleaseObject(ctxt->context, str); + xmlXPathReleaseObject(ctxt->context, find); } /** @@ -8553,9 +8244,10 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { if (ctxt == NULL) return; if (nargs == 0) { /* Use current context node */ - valuePush(ctxt, - xmlXPathCacheWrapString(ctxt->context, - xmlXPathCastNodeToString(ctxt->context->node))); + source = xmlXPathCastNodeToString(ctxt->context->node); + if (source == NULL) + xmlXPathPErrMemory(ctxt); + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, source)); nargs = 1; } @@ -8611,14 +8303,14 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { */ void xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { - xmlXPathObjectPtr str; - xmlXPathObjectPtr from; - xmlXPathObjectPtr to; + xmlXPathObjectPtr str = NULL; + xmlXPathObjectPtr from = NULL; + xmlXPathObjectPtr to = NULL; xmlBufPtr target; int offset, max; int ch; const xmlChar *point; - xmlChar *cptr; + xmlChar *cptr, *content; CHECK_ARITY(3); @@ -8628,47 +8320,71 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { from = valuePop(ctxt); CAST_TO_STRING; str = valuePop(ctxt); + if (ctxt->error != 0) + goto error; - target = xmlBufCreate(); - if (target) { - max = xmlUTF8Strlen(to->stringval); - for (cptr = str->stringval; (ch=*cptr); ) { - offset = xmlUTF8Strloc(from->stringval, cptr); - if (offset >= 0) { - if (offset < max) { - point = xmlUTF8Strpos(to->stringval, offset); - if (point) - xmlBufAdd(target, point, xmlUTF8Strsize(point, 1)); - } - } else - xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); - - /* Step to next character in input */ - cptr++; - if ( ch & 0x80 ) { - /* if not simple ascii, verify proper format */ - if ( (ch & 0xc0) != 0xc0 ) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathTranslateFunction: Invalid UTF8 string\n"); - /* not asserting an XPath error is probably better */ - break; - } - /* then skip over remaining bytes for this char */ - while ( (ch <<= 1) & 0x80 ) - if ( (*cptr++ & 0xc0) != 0x80 ) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathTranslateFunction: Invalid UTF8 string\n"); - /* not asserting an XPath error is probably better */ - break; - } - if (ch & 0x80) /* must have had error encountered */ - break; - } - } + /* + * Account for quadratic runtime + */ + if (ctxt->context->opLimit != 0) { + unsigned long f1 = xmlStrlen(from->stringval); + unsigned long f2 = xmlStrlen(str->stringval); + + if ((f1 > 0) && (f2 > 0)) { + unsigned long p; + + f1 = f1 / 10 + 1; + f2 = f2 / 10 + 1; + p = f1 > ULONG_MAX / f2 ? ULONG_MAX : f1 * f2; + if (xmlXPathCheckOpLimit(ctxt, p) < 0) + goto error; + } + } + + target = xmlBufCreateSize(64); + if (target == NULL) { + xmlXPathPErrMemory(ctxt); + goto error; } - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, - xmlBufContent(target))); + + max = xmlUTF8Strlen(to->stringval); + for (cptr = str->stringval; (ch=*cptr); ) { + offset = xmlUTF8Strloc(from->stringval, cptr); + if (offset >= 0) { + if (offset < max) { + point = xmlUTF8Strpos(to->stringval, offset); + if (point) + xmlBufAdd(target, point, xmlUTF8Strsize(point, 1)); + } + } else + xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); + + /* Step to next character in input */ + cptr++; + if ( ch & 0x80 ) { + /* if not simple ascii, verify proper format */ + if ( (ch & 0xc0) != 0xc0 ) { + xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR); + break; + } + /* then skip over remaining bytes for this char */ + while ( (ch <<= 1) & 0x80 ) + if ( (*cptr++ & 0xc0) != 0x80 ) { + xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR); + break; + } + if (ch & 0x80) /* must have had error encountered */ + break; + } + } + + content = xmlBufDetach(target); + if (content == NULL) + xmlXPathPErrMemory(ctxt); + else + valuePush(ctxt, xmlXPathCacheWrapString(ctxt, content)); xmlBufFree(target); +error: xmlXPathReleaseObject(ctxt->context, str); xmlXPathReleaseObject(ctxt->context, from); xmlXPathReleaseObject(ctxt->context, to); @@ -8694,7 +8410,12 @@ xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(1); cur = valuePop(ctxt); if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); - cur = xmlXPathCacheConvertBoolean(ctxt->context, cur); + if (cur->type != XPATH_BOOLEAN) { + int boolval = xmlXPathCastToBoolean(cur); + + xmlXPathReleaseObject(ctxt->context, cur); + cur = xmlXPathCacheNewBoolean(ctxt, boolval); + } valuePush(ctxt, cur); } @@ -8727,7 +8448,7 @@ xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) { void xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(0); - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1)); } /** @@ -8741,7 +8462,7 @@ xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) { void xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(0); - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0)); } /** @@ -8767,8 +8488,9 @@ xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) { */ void xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) { - xmlXPathObjectPtr val = NULL; - const xmlChar *theLang = NULL; + xmlXPathObjectPtr val; + xmlNodePtr cur; + xmlChar *theLang = NULL; const xmlChar *lang; int ret = 0; int i; @@ -8778,20 +8500,28 @@ xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_TYPE(XPATH_STRING); val = valuePop(ctxt); lang = val->stringval; - theLang = xmlNodeGetLang(ctxt->context->node); + cur = ctxt->context->node; + while (cur != NULL) { + if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE, + &theLang) < 0) + xmlXPathPErrMemory(ctxt); + if (theLang != NULL) + break; + cur = cur->parent; + } if ((theLang != NULL) && (lang != NULL)) { for (i = 0;lang[i] != 0;i++) - if (toupper(lang[i]) != toupper(theLang[i])) - goto not_equal; - if ((theLang[i] == 0) || (theLang[i] == '-')) - ret = 1; + if (toupper(lang[i]) != toupper(theLang[i])) + goto not_equal; + if ((theLang[i] == 0) || (theLang[i] == '-')) + ret = 1; } not_equal: if (theLang != NULL) xmlFree((void *)theLang); xmlXPathReleaseObject(ctxt->context, val); - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret)); } /** @@ -8810,12 +8540,14 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) { if (ctxt == NULL) return; if (nargs == 0) { if (ctxt->context->node == NULL) { - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0.0)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0)); } else { xmlChar* content = xmlNodeGetContent(ctxt->context->node); + if (content == NULL) + xmlXPathPErrMemory(ctxt); res = xmlXPathStringEvalNumber(content); - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res)); xmlFree(content); } return; @@ -8823,7 +8555,14 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(1); cur = valuePop(ctxt); - valuePush(ctxt, xmlXPathCacheConvertNumber(ctxt->context, cur)); + if (cur->type != XPATH_NUMBER) { + double floatval; + + floatval = xmlXPathCastToNumberInternal(ctxt, cur); + xmlXPathReleaseObject(ctxt->context, cur); + cur = xmlXPathCacheNewFloat(ctxt, floatval); + } + valuePush(ctxt, cur); } /** @@ -8851,10 +8590,11 @@ xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) { for (i = 0; i < cur->nodesetval->nodeNr; i++) { - res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]); + res += xmlXPathNodeToNumberInternal(ctxt, + cur->nodesetval->nodeTab[i]); } } - valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res)); + valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res)); xmlXPathReleaseObject(ctxt->context, cur); } @@ -9078,6 +8818,8 @@ xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) { if (count == 0) return(NULL); ret = xmlStrndup(ctxt->cur, count); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); ctxt->cur = in; return(ret); } @@ -9159,6 +8901,8 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) { XP_ERRORNULL(XPATH_EXPR_ERROR); } ret = xmlStrndup(ctxt->cur, count); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); ctxt->cur = in; return(ret); } @@ -9168,6 +8912,7 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) { static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { + xmlChar *ret; xmlChar buf[XML_MAX_NAMELEN + 5]; int len = 0, l; int c; @@ -9206,7 +8951,8 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { } buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { - XP_ERRORNULL(XPATH_MEMORY_ERROR); + xmlXPathPErrMemory(ctxt); + return(NULL); } memcpy(buffer, buf, len); while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ @@ -9224,7 +8970,8 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { xmlFree(buffer); - XP_ERRORNULL(XPATH_MEMORY_ERROR); + xmlXPathPErrMemory(ctxt); + return(NULL); } buffer = tmp; } @@ -9238,7 +8985,10 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { } if (len == 0) return(NULL); - return(xmlStrndup(buf, len)); + ret = xmlStrndup(buf, len); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); + return(ret); } #define MAX_FRAC 20 @@ -9441,7 +9191,7 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) exponent = -exponent; ret *= pow(10.0, (double) exponent); } - num = xmlXPathCacheNewFloat(ctxt->context, ret); + num = xmlXPathCacheNewFloat(ctxt, ret); if (num == NULL) { ctxt->error = XPATH_MEMORY_ERROR; } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num, @@ -9465,32 +9215,33 @@ static xmlChar * xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) { const xmlChar *q; xmlChar *ret = NULL; + int quote; if (CUR == '"') { - NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '"')) - NEXT; - if (!IS_CHAR_CH(CUR)) { - XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR); - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + quote = '"'; } else if (CUR == '\'') { - NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) - NEXT; - if (!IS_CHAR_CH(CUR)) { - XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR); - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } + quote = '\''; } else { XP_ERRORNULL(XPATH_START_LITERAL_ERROR); } + + NEXT; + q = CUR_PTR; + while (CUR != quote) { + int ch; + int len = 4; + + if (CUR == 0) + XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR); + ch = xmlGetUTF8Char(CUR_PTR, &len); + if ((ch < 0) || (IS_CHAR(ch) == 0)) + XP_ERRORNULL(XPATH_INVALID_CHAR_ERROR); + CUR_PTR += len; + } + ret = xmlStrndup(q, CUR_PTR - q); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); + NEXT; return(ret); } @@ -9507,42 +9258,15 @@ xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) { */ static void xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) { - const xmlChar *q; xmlChar *ret = NULL; xmlXPathObjectPtr lit; - if (CUR == '"') { - NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '"')) - NEXT; - if (!IS_CHAR_CH(CUR)) { - XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR); - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } - } else if (CUR == '\'') { - NEXT; - q = CUR_PTR; - while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) - NEXT; - if (!IS_CHAR_CH(CUR)) { - XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR); - } else { - ret = xmlStrndup(q, CUR_PTR - q); - NEXT; - } - } else { - XP_ERROR(XPATH_START_LITERAL_ERROR); - } - if (ret == NULL) { - xmlXPathPErrMemory(ctxt, NULL); + ret = xmlXPathParseLiteral(ctxt); + if (ret == NULL) return; - } - lit = xmlXPathCacheNewString(ctxt->context, ret); + lit = xmlXPathCacheNewString(ctxt, ret); if (lit == NULL) { - ctxt->error = XPATH_MEMORY_ERROR; + ctxt->error = XPATH_MEMORY_ERROR; } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit, NULL) == -1) { xmlXPathReleaseObject(ctxt->context, lit); @@ -9801,6 +9525,8 @@ xmlXPathScanName(xmlXPathParserContextPtr ctxt) { c = CUR_CHAR(l); } ret = xmlStrndup(cur, ctxt->cur - cur); + if (ret == NULL) + xmlXPathPErrMemory(ctxt); ctxt->cur = cur; return(ret); } @@ -10309,7 +10035,6 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test, int blanks; if ((test == NULL) || (type == NULL) || (prefix == NULL)) { - STRANGE; return(NULL); } *type = (xmlXPathTypeVal) 0; @@ -10365,9 +10090,6 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test, name = NULL; if (CUR != ')') { name = xmlXPathParseLiteral(ctxt); - if (name == NULL) { - XP_ERRORNULL(XPATH_EXPR_ERROR); - } *test = NODE_TEST_PI; SKIP_BLANKS; } @@ -10861,7 +10583,7 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt, tmp = (xmlNodePtr *) xmlRealloc(set->nodeTab, nodeMax * sizeof(xmlNodePtr)); if (tmp == NULL) { - xmlXPathPErrMemory(ctxt, "shrinking nodeset\n"); + xmlXPathPErrMemory(ctxt); } else { set->nodeTab = tmp; set->nodeMax = nodeMax; @@ -10979,7 +10701,7 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt, tmp = (xmlXPathObjectPtr *) xmlRealloc(locset->locTab, locMax * sizeof(xmlXPathObjectPtr)); if (tmp == NULL) { - xmlXPathPErrMemory(ctxt, "shrinking locset\n"); + xmlXPathPErrMemory(ctxt); } else { locset->locTab = tmp; locset->locMax = locMax; @@ -11019,8 +10741,6 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt, * Process inner predicates first. */ if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEvalPredicate: Expected a predicate\n"); XP_ERROR(XPATH_INVALID_OPERAND); } if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH) @@ -11103,11 +10823,11 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, if (hasAxisRange != 0) { \ if (++pos == maxPos) { \ if (addNode(seq, cur) < 0) \ - ctxt->error = XPATH_MEMORY_ERROR; \ + xmlXPathPErrMemory(ctxt); \ goto axis_range_end; } \ } else { \ if (addNode(seq, cur) < 0) \ - ctxt->error = XPATH_MEMORY_ERROR; \ + xmlXPathPErrMemory(ctxt); \ if (breakOnFirstHit) goto first_hit; } #define XP_TEST_HIT_NS \ @@ -11115,12 +10835,12 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, if (++pos == maxPos) { \ hasNsNodes = 1; \ if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \ - ctxt->error = XPATH_MEMORY_ERROR; \ + xmlXPathPErrMemory(ctxt); \ goto axis_range_end; } \ } else { \ hasNsNodes = 1; \ if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \ - ctxt->error = XPATH_MEMORY_ERROR; \ + xmlXPathPErrMemory(ctxt); \ if (breakOnFirstHit) goto first_hit; } xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value; @@ -11260,8 +10980,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, } contextSeq = obj->nodesetval; if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) { - xmlXPathReleaseObject(xpctxt, obj); - valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL)); + valuePush(ctxt, obj); return(0); } /* @@ -11336,7 +11055,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, if (seq == NULL) { seq = xmlXPathNodeSetCreate(NULL); if (seq == NULL) { - /* TODO: Propagate memory error. */ + xmlXPathPErrMemory(ctxt); total = 0; goto error; } @@ -11390,7 +11109,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, switch (test) { case NODE_TEST_NONE: total = 0; - STRANGE goto error; case NODE_TEST_TYPE: if (type == NODE_TYPE_NODE) { @@ -11468,7 +11186,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, } break; case NODE_TEST_NS:{ - TODO; + /* TODO */ break; } case NODE_TEST_NAME: @@ -11550,9 +11268,11 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, if (outSeq == NULL) { outSeq = seq; seq = NULL; - } else - /* TODO: Check memory error. */ + } else { outSeq = mergeAndClear(outSeq, seq); + if (outSeq == NULL) + xmlXPathPErrMemory(ctxt); + } /* * Break if only a true/false result was requested. */ @@ -11568,9 +11288,11 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, if (outSeq == NULL) { outSeq = seq; seq = NULL; - } else - /* TODO: Check memory error. */ + } else { outSeq = mergeAndClear(outSeq, seq); + if (outSeq == NULL) + xmlXPathPErrMemory(ctxt); + } break; apply_predicates: /* --------------------------------------------------- */ @@ -11630,8 +11352,9 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, outSeq = seq; seq = NULL; } else { - /* TODO: Check memory error. */ outSeq = mergeAndClear(outSeq, seq); + if (outSeq == NULL) + xmlXPathPErrMemory(ctxt); } if (toBool) @@ -11657,11 +11380,13 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, * Ensure we return at least an empty set. */ if (outSeq == NULL) { - if ((seq != NULL) && (seq->nodeNr == 0)) + if ((seq != NULL) && (seq->nodeNr == 0)) { outSeq = seq; - else - /* TODO: Check memory error. */ + } else { outSeq = xmlXPathNodeSetCreate(NULL); + if (outSeq == NULL) + xmlXPathPErrMemory(ctxt); + } } if ((seq != NULL) && (seq != outSeq)) { xmlXPathFreeNodeSet(seq); @@ -11670,7 +11395,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, * Hand over the result. Better to push the set also in * case of errors. */ - valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq)); + valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, outSeq)); /* * Reset the context node. */ @@ -11768,9 +11493,13 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, break; } - /* TODO: Check memory error. */ - arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, - arg2->nodesetval); + if ((arg2->nodesetval != NULL) && + (arg2->nodesetval->nodeNr != 0)) { + arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, + arg2->nodesetval); + if (arg1->nodesetval == NULL) + xmlXPathPErrMemory(ctxt); + } valuePush(ctxt, arg1); xmlXPathReleaseObject(ctxt->context, arg2); /* optimizer */ @@ -11788,7 +11517,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, if (op->ch2 != -1) total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); CHECK_ERROR0; - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node)); break; case XPATH_OP_COLLECT:{ @@ -11802,9 +11531,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, break; } case XPATH_OP_VALUE: - valuePush(ctxt, - xmlXPathCacheObjectCopy(ctxt->context, - (xmlXPathObjectPtr) op->value4)); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4)); break; case XPATH_OP_SORT: if (op->ch1 != -1) @@ -11908,9 +11635,13 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, break; } - /* TODO: Check memory error. */ - arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, - arg2->nodesetval); + if ((arg2->nodesetval != NULL) && + (arg2->nodesetval->nodeNr != 0)) { + arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, + arg2->nodesetval); + if (arg1->nodesetval == NULL) + xmlXPathPErrMemory(ctxt); + } valuePush(ctxt, arg1); xmlXPathReleaseObject(ctxt->context, arg2); /* optimizer */ @@ -11928,7 +11659,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, if (op->ch2 != -1) total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); CHECK_ERROR0; - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node)); break; case XPATH_OP_COLLECT:{ @@ -11942,9 +11673,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, break; } case XPATH_OP_VALUE: - valuePush(ctxt, - xmlXPathCacheObjectCopy(ctxt->context, - (xmlXPathObjectPtr) op->value4)); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4)); break; case XPATH_OP_SORT: if (op->ch1 != -1) @@ -12130,7 +11859,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) equal = xmlXPathEqualValues(ctxt); else equal = xmlXPathNotEqualValues(ctxt); - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, equal)); break; case XPATH_OP_CMP: total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); @@ -12138,7 +11867,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); CHECK_ERROR0; ret = xmlXPathCompareValues(ctxt, op->value, op->value2); - valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret)); + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret)); break; case XPATH_OP_PLUS: total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); @@ -12196,13 +11925,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) break; } - if ((arg1->nodesetval == NULL) || - ((arg2->nodesetval != NULL) && + if (((arg2->nodesetval != NULL) && (arg2->nodesetval->nodeNr != 0))) { - /* TODO: Check memory error. */ arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval, arg2->nodesetval); + if (arg1->nodesetval == NULL) + xmlXPathPErrMemory(ctxt); } valuePush(ctxt, arg1); @@ -12218,8 +11947,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) if (op->ch2 != -1) total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); CHECK_ERROR0; - valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node)); + valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, + ctxt->context->node)); break; case XPATH_OP_COLLECT:{ if (op->ch1 == -1) @@ -12232,9 +11961,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) break; } case XPATH_OP_VALUE: - valuePush(ctxt, - xmlXPathCacheObjectCopy(ctxt->context, - (xmlXPathObjectPtr) op->value4)); + valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4)); break; case XPATH_OP_VARIABLE:{ xmlXPathObjectPtr val; @@ -12252,10 +11979,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) URI = xmlXPathNsLookup(ctxt->context, op->value5); if (URI == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n", - (char *) op->value4, (char *)op->value5); - ctxt->error = XPATH_UNDEF_PREFIX_ERROR; + XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); break; } val = xmlXPathVariableLookupNS(ctxt->context, @@ -12279,19 +12003,11 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) if (ctxt->error != XPATH_EXPRESSION_OK) break; } - if (ctxt->valueNr < frame + op->value) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEval: parameter error\n"); - ctxt->error = XPATH_INVALID_OPERAND; - break; - } + if (ctxt->valueNr < frame + op->value) + XP_ERROR0(XPATH_INVALID_OPERAND); for (i = 0; i < op->value; i++) { - if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEval: parameter error\n"); - ctxt->error = XPATH_INVALID_OPERAND; - break; - } + if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) + XP_ERROR0(XPATH_INVALID_OPERAND); } if (op->cache != NULL) func = op->cache; @@ -12304,22 +12020,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) op->value4); else { URI = xmlXPathNsLookup(ctxt->context, op->value5); - if (URI == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", - (char *)op->value4, (char *)op->value5); - ctxt->error = XPATH_UNDEF_PREFIX_ERROR; - break; - } + if (URI == NULL) + XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); func = xmlXPathFunctionLookupNS(ctxt->context, op->value4, URI); } - if (func == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompOpEval: function %s not found\n", - (char *)op->value4); + if (func == NULL) XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); - } op->cache = func; op->cacheURI = (void *) URI; } @@ -12538,8 +12245,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) ctxt->context->node = oldlocset->locTab[i]->user; ctxt->context->contextSize = oldlocset->locNr; ctxt->context->proximityPosition = i + 1; - tmp = xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node); + tmp = xmlXPathCacheNewNodeSet(ctxt, + ctxt->context->node); valuePush(ctxt, tmp); if (op->ch2 != -1) @@ -12601,8 +12308,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) /* * OPTIMIZE TODO: Avoid recreation for every iteration. */ - tmp = xmlXPathCacheNewNodeSet(ctxt->context, - ctxt->context->node); + tmp = xmlXPathCacheNewNodeSet(ctxt, + ctxt->context->node); valuePush(ctxt, tmp); if (op->ch2 != -1) @@ -12649,9 +12356,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) } #endif /* LIBXML_XPTR_LOCS_ENABLED */ default: - xmlGenericError(xmlGenericErrorContext, - "XPath: unknown precompiled operation %d\n", op->op); - ctxt->error = XPATH_INVALID_OPERAND; + XP_ERROR0(XPATH_INVALID_OPERAND); break; } @@ -12753,12 +12458,12 @@ xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, #ifdef XPATH_STREAMING /** * xmlXPathRunStreamEval: - * @ctxt: the XPath parser context with the compiled expression + * @pctxt: the XPath parser context with the compiled expression * * Evaluate the Precompiled Streamable XPath expression in the given context. */ static int -xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, +xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt, xmlPatternPtr comp, xmlXPathObjectPtr *resultSeq, int toBool) { int max_depth, min_depth; @@ -12767,6 +12472,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, int eval_all_nodes; xmlNodePtr cur = NULL, limit = NULL; xmlStreamCtxtPtr patstream = NULL; + xmlXPathContextPtr ctxt = pctxt->context; if ((ctxt == NULL) || (comp == NULL)) return(-1); @@ -12788,7 +12494,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, if (! toBool) { if (resultSeq == NULL) return(-1); - *resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL); + *resultSeq = xmlXPathCacheNewNodeSet(pctxt, NULL); if (*resultSeq == NULL) return(-1); } @@ -12797,20 +12503,24 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, * handle the special cases of "/" amd "." being matched */ if (min_depth == 0) { + int res; + if (from_root) { /* Select "/" */ if (toBool) return(1); - /* TODO: Check memory error. */ - xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, - (xmlNodePtr) ctxt->doc); + res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, + (xmlNodePtr) ctxt->doc); } else { /* Select "self::node()" */ if (toBool) return(1); - /* TODO: Check memory error. */ - xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node); + res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, + ctxt->node); } + + if (res < 0) + xmlXPathPErrMemory(pctxt); } if (max_depth == 0) { return(0); @@ -12852,10 +12562,8 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, patstream = xmlPatternGetStreamCtxt(comp); if (patstream == NULL) { - /* - * QUESTION TODO: Is this an error? - */ - return(0); + xmlXPathPErrMemory(pctxt); + return(-1); } eval_all_nodes = xmlStreamWantsAnyNode(patstream); @@ -12866,8 +12574,8 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, } else if (ret == 1) { if (toBool) goto return_1; - /* TODO: Check memory error. */ - xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); + if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) < 0) + xmlXPathPErrMemory(pctxt); } } depth = 0; @@ -12876,8 +12584,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, do { if (ctxt->opLimit != 0) { if (ctxt->opCount >= ctxt->opLimit) { - xmlGenericError(xmlGenericErrorContext, - "XPath operation limit exceeded\n"); + xmlXPathErr(ctxt, XPATH_RECURSION_LIMIT_EXCEEDED); xmlFreeStreamCtxt(patstream); return(-1); } @@ -12899,15 +12606,13 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, break; if (ret < 0) { - /* NOP. */ + xmlXPathPErrMemory(pctxt); } else if (ret == 1) { if (toBool) goto return_1; - if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) - < 0) { - ctxt->lastError.domain = XML_FROM_XPATH; - ctxt->lastError.code = XML_ERR_NO_MEMORY; - } + if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, + cur) < 0) + xmlXPathPErrMemory(pctxt); } if ((cur->children == NULL) || (depth >= max_depth)) { ret = xmlStreamPop(patstream); @@ -13007,7 +12712,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) ctxt->valueTab = (xmlXPathObjectPtr *) xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ctxt->valueTab == NULL) { - xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); + xmlXPathPErrMemory(ctxt); return(-1); } ctxt->valueNr = 0; @@ -13022,8 +12727,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) /* * Evaluation to boolean result. */ - res = xmlXPathRunStreamEval(ctxt->context, - ctxt->comp->stream, NULL, 1); + res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, NULL, 1); if (res != -1) return(res); } else { @@ -13032,8 +12736,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) /* * Evaluation to a sequence. */ - res = xmlXPathRunStreamEval(ctxt->context, - ctxt->comp->stream, &resObj, 0); + res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, &resObj, 0); if ((res != -1) && (resObj != NULL)) { valuePush(ctxt, resObj); @@ -13050,8 +12753,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) #endif comp = ctxt->comp; if (comp->last < 0) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathRunEval: last is less than zero\n"); + xmlXPathErr(ctxt, XPATH_STACK_ERROR); return(-1); } oldDepth = ctxt->context->depth; @@ -13104,7 +12806,7 @@ xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) { return((res->stringval != NULL) && (xmlStrlen(res->stringval) != 0)); default: - STRANGE + break; } return(0); } @@ -13155,7 +12857,7 @@ xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt, } #endif default: - STRANGE + break; } return(0); } @@ -13186,6 +12888,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) { if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) && (!xmlStrchr(str, '@'))) { const xmlChar *tmp; + int res; /* * We don't try to handle expressions using the verbose axis @@ -13206,7 +12909,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) { if (ctxt->nsNr > 0) { namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*)); if (namespaces == NULL) { - xmlXPathErrMemory(ctxt, "allocating namespaces array\n"); + xmlXPathErrMemory(ctxt); return(NULL); } for (i = 0, j = 0; (j < ctxt->nsNr); j++) { @@ -13219,14 +12922,19 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) { } } - stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces); + res = xmlPatternCompileSafe(str, dict, XML_PATTERN_XPATH, namespaces, + &stream); if (namespaces != NULL) { xmlFree((xmlChar **)namespaces); } + if (res < 0) { + xmlXPathErrMemory(ctxt); + return(NULL); + } if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) { comp = xmlXPathNewCompExpr(); if (comp == NULL) { - xmlXPathErrMemory(ctxt, "allocating streamable expression\n"); + xmlXPathErrMemory(ctxt); xmlFreePattern(stream); return(NULL); } @@ -13419,18 +13127,18 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, int toBool) { xmlXPathParserContextPtr pctxt; - xmlXPathObjectPtr resObj; + xmlXPathObjectPtr resObj = NULL; #ifndef LIBXML_THREAD_ENABLED static int reentance = 0; #endif int res; - CHECK_CTXT_NEG(ctxt) - if (comp == NULL) return(-1); xmlInitParser(); + xmlResetError(&ctxt->lastError); + #ifndef LIBXML_THREAD_ENABLED reentance++; if (reentance > 1) @@ -13442,19 +13150,11 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, return(-1); res = xmlXPathRunEval(pctxt, toBool); - if (pctxt->error != XPATH_EXPRESSION_OK) { - resObj = NULL; - } else { - resObj = valuePop(pctxt); - if (resObj == NULL) { - if (!toBool) - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompiledEval: No result on the stack.\n"); - } else if (pctxt->valueNr > 0) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompiledEval: %d object(s) left on the stack.\n", - pctxt->valueNr); - } + if (pctxt->error == XPATH_EXPRESSION_OK) { + if (pctxt->valueNr != ((toBool) ? 0 : 1)) + xmlXPathErr(pctxt, XPATH_STACK_ERROR); + else if (!toBool) + resObj = valuePop(pctxt); } if (resObjPtr) @@ -13522,10 +13222,18 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) { #endif int oldDepth = 0; - if (ctxt == NULL) return; + if (ctxt == NULL) + return; + if (ctxt->context->lastError.code != 0) + return; #ifdef XPATH_STREAMING comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base); + if ((comp == NULL) && + (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)) { + xmlXPathPErrMemory(ctxt); + return; + } if (comp != NULL) { if (ctxt->comp != NULL) xmlXPathFreeCompExpr(ctxt->comp); @@ -13572,10 +13280,13 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) { xmlXPathParserContextPtr ctxt; xmlXPathObjectPtr res; - CHECK_CTXT(ctx) + if (ctx == NULL) + return(NULL); xmlInitParser(); + xmlResetError(&ctx->lastError); + ctxt = xmlXPathNewParserContext(str, ctx); if (ctxt == NULL) return NULL; @@ -13583,16 +13294,11 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) { if (ctxt->error != XPATH_EXPRESSION_OK) { res = NULL; + } else if (ctxt->valueNr != 1) { + xmlXPathErr(ctxt, XPATH_STACK_ERROR); + res = NULL; } else { res = valuePop(ctxt); - if (res == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompiledEval: No result on the stack.\n"); - } else if (ctxt->valueNr > 0) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompiledEval: %d object(s) left on the stack.\n", - ctxt->valueNr); - } } xmlXPathFreeParserContext(ctxt); @@ -13725,7 +13431,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { CAST_TO_STRING; str = valuePop(ctxt); - target = xmlBufCreate(); + target = xmlBufCreateSize(64); escape[0] = '%'; escape[3] = 0; @@ -13765,8 +13471,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { } } } - valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, - xmlBufContent(target))); + valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target))); xmlBufFree(target); xmlXPathReleaseObject(ctxt->context, str); } diff --git a/xpointer.c b/xpointer.c index 6e1e5f4..87ea85b 100644 --- a/xpointer.c +++ b/xpointer.c @@ -45,16 +45,7 @@ #define XPTR_XMLNS_SCHEME #include "private/error.h" - -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - -#define STRANGE \ - xmlGenericError(xmlGenericErrorContext, \ - "Internal error at %s:%d\n", \ - __FILE__, __LINE__); +#include "private/xpath.h" /************************************************************************ * * @@ -62,63 +53,59 @@ * * ************************************************************************/ -/** - * xmlXPtrErrMemory: - * @extra: extra information - * - * Handle a redefinition of attribute error - */ -static void -xmlXPtrErrMemory(const char *extra) -{ - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER, - XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); -} - /** * xmlXPtrErr: * @ctxt: an XPTR evaluation context * @extra: extra information * - * Handle a redefinition of attribute error + * Handle an XPointer error */ static void LIBXML_ATTR_FORMAT(3,0) -xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error, +xmlXPtrErr(xmlXPathParserContextPtr ctxt, int code, const char * msg, const xmlChar *extra) { - if (ctxt != NULL) - ctxt->error = error; - if ((ctxt == NULL) || (ctxt->context == NULL)) { - __xmlRaiseError(NULL, NULL, NULL, - NULL, NULL, XML_FROM_XPOINTER, error, - XML_ERR_ERROR, NULL, 0, - (const char *) extra, NULL, NULL, 0, 0, - msg, extra); - return; - } + xmlStructuredErrorFunc serror = NULL; + void *data = NULL; + xmlNodePtr node = NULL; + int res; - /* cleanup current last error */ - xmlResetError(&ctxt->context->lastError); + if (ctxt == NULL) + return; + /* Only report the first error */ + if (ctxt->error != 0) + return; - ctxt->context->lastError.domain = XML_FROM_XPOINTER; - ctxt->context->lastError.code = error; - ctxt->context->lastError.level = XML_ERR_ERROR; - ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); - ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; - ctxt->context->lastError.node = ctxt->context->debugNode; - if (ctxt->context->error != NULL) { - ctxt->context->error(ctxt->context->userData, - &ctxt->context->lastError); - } else { - __xmlRaiseError(NULL, NULL, NULL, - NULL, ctxt->context->debugNode, XML_FROM_XPOINTER, - error, XML_ERR_ERROR, NULL, 0, - (const char *) extra, (const char *) ctxt->base, NULL, - ctxt->cur - ctxt->base, 0, - msg, extra); + ctxt->error = code; + + if (ctxt->context != NULL) { + xmlErrorPtr err = &ctxt->context->lastError; + + /* cleanup current last error */ + xmlResetError(err); + + err->domain = XML_FROM_XPOINTER; + err->code = code; + err->level = XML_ERR_ERROR; + err->str1 = (char *) xmlStrdup(ctxt->base); + if (err->str1 == NULL) { + xmlXPathPErrMemory(ctxt); + return; + } + err->int1 = ctxt->cur - ctxt->base; + err->node = ctxt->context->debugNode; + + serror = ctxt->context->error; + data = ctxt->context->userData; + node = ctxt->context->debugNode; } + + res = __xmlRaiseError(serror, NULL, data, NULL, node, + XML_FROM_XPOINTER, code, XML_ERR_ERROR, NULL, 0, + (const char *) extra, (const char *) ctxt->base, + NULL, ctxt->cur - ctxt->base, 0, + msg, extra); + if (res < 0) + xmlXPathPErrMemory(ctxt); } /************************************************************************ @@ -208,6 +195,18 @@ xmlXPtrGetNthChild(xmlNodePtr cur, int no) { * * ************************************************************************/ +/** + * xmlXPtrErrMemory: + * @extra: extra information + * + * Handle a redefinition of attribute error + */ +static void +xmlXPtrErrMemory(const char *extra ATTRIBUTE_UNUSED) +{ + xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_XPOINTER, NULL); +} + /** * xmlXPtrCmpPoints: * @node1: the first node @@ -959,7 +958,7 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) { len++; buffer = (xmlChar *) xmlMallocAtomic(len); if (buffer == NULL) { - xmlXPtrErrMemory("allocating buffer"); + xmlXPathPErrMemory(ctxt); xmlFree(name); return; } @@ -1060,7 +1059,8 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) { NEXT; SKIP_BLANKS; - xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur); + if (xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur) < 0) + xmlXPathPErrMemory(ctxt); ctxt->base = oldBase; ctxt->cur = oldCur; xmlFree(prefix); @@ -1230,7 +1230,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) { ctxt->valueTab = (xmlXPathObjectPtr *) xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ctxt->valueTab == NULL) { - xmlXPtrErrMemory("allocating evaluation context"); + xmlXPathPErrMemory(ctxt); return; } ctxt->valueNr = 0; @@ -1351,10 +1351,16 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) { if ((ctx == NULL) || (str == NULL)) return(NULL); + xmlResetError(&ctx->lastError); + ctxt = xmlXPathNewParserContext(str, ctx); - if (ctxt == NULL) + if (ctxt == NULL) { + xmlXPathErrMemory(ctx); return(NULL); + } xmlXPtrEvalXPointer(ctxt); + if (ctx->lastError.code != XML_ERR_OK) + goto error; if ((ctxt->value != NULL) && #ifdef LIBXML_XPTR_LOCS_ENABLED @@ -1392,11 +1398,12 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) { "xmlXPtrEval: object(s) left on the eval stack\n", NULL); } - if (ctxt->error != XPATH_EXPRESSION_OK) { + if (ctx->lastError.code != XML_ERR_OK) { xmlXPathFreeObject(res); res = NULL; } +error: xmlXPathFreeParserContext(ctxt); return(res); } @@ -1535,7 +1542,7 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { /* Do not copy DTD information */ break; case XML_ENTITY_DECL: - TODO /* handle crossing entities -> stack needed */ + /* TODO: handle crossing entities -> stack needed */ break; case XML_XINCLUDE_START: case XML_XINCLUDE_END: @@ -1543,7 +1550,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { break; case XML_ATTRIBUTE_NODE: /* Humm, should not happen ! */ - STRANGE break; default: tmp = xmlCopyNode(cur, 1); @@ -1551,7 +1557,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { } if (tmp != NULL) { if ((list == NULL) || ((last == NULL) && (parent == NULL))) { - STRANGE return(NULL); } if (last != NULL) @@ -1565,7 +1570,6 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { * Skip to next node in document order */ if ((list == NULL) || ((last == NULL) && (parent == NULL))) { - STRANGE return(NULL); } cur = xmlXPtrAdvanceNode(cur, NULL); @@ -1994,7 +1998,8 @@ xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) { } } default: - TODO /* missed one case ??? */ + /* TODO: missed one case ??? */ + break; } return(NULL); } @@ -2141,7 +2146,8 @@ xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) { } } default: - TODO /* missed one case ??? */ + /* TODO: missed one case ??? */ + break; } return(NULL); } @@ -2276,7 +2282,6 @@ xmlXPtrAdvanceNode(xmlNodePtr cur, int *level) { (cur->type != XML_HTML_DOCUMENT_NODE) && (cur->type != XML_CDATA_SECTION_NODE)) { if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */ - TODO goto skip; } goto next; @@ -2350,7 +2355,6 @@ xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) { } if (pos > len) { /* Strange, the indx in the text node is greater than it's len */ - STRANGE pos = len; } if (pos + bytes >= len) { diff --git a/xzlib.c b/xzlib.c index b5d35da..3d607ad 100644 --- a/xzlib.c +++ b/xzlib.c @@ -195,6 +195,12 @@ xz_compressed(xzFile f) { case COPY: return(0); case GZIP: +#ifdef LIBXML_ZLIB_ENABLED + /* Don't use lzma for gzip */ + return(0); +#else + return(1); +#endif case LZMA: return(1); } @@ -207,24 +213,10 @@ __libxml2_xzopen(const char *path, const char *mode) return xz_open(path, -1, mode); } -int -__libxml2_xzcompressed(xzFile f) { - return xz_compressed(f); -} - xzFile -__libxml2_xzdopen(int fd, const char *mode) +__libxml2_xzdopen(const char *path, int fd, const char *mode) { - char *path; /* identifier for error messages */ - size_t path_size = 7 + 3 * sizeof(int); - xzFile xz; - - if (fd == -1 || (path = xmlMalloc(path_size)) == NULL) - return NULL; - snprintf(path, path_size, "", fd); /* for debugging */ - xz = xz_open(path, fd, mode); - xmlFree(path); - return xz; + return xz_open(path, fd, mode); } static int @@ -320,8 +312,12 @@ is_format_lzma(xz_statep state) * If someone complains, this will be reconsidered. */ if (dict_size != UINT32_MAX) { - uint32_t d = dict_size - 1; + uint32_t d; + + if (dict_size == 0) + return 0; + d = dict_size - 1; d |= d >> 2; d |= d >> 3; d |= d >> 4; @@ -700,6 +696,13 @@ xz_skip(xz_statep state, uint64_t len) return 0; } +int +__libxml2_xzcompressed(xzFile f) { + xz_head(f); + + return xz_compressed(f); +} + int __libxml2_xzread(xzFile file, void *buf, unsigned len) {