diff --git a/ChangeLog b/ChangeLog index 795696dd..38228d85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Tue Oct 7 23:19:39 CEST 2003 Daniel Veillard + + * error.c include/libxml/xmlerror.h include/libxml/xpath.h + include/libxml/xpathInternals.h xpath.c: cleaning up XPath + error reporting that time. + * threads.c: applied the two patches for TLS threads + on Windows from Jesse Pelton + * parser.c: tiny safety patch for xmlStrPrintf() make sure the + return is always zero terminated. Should also help detecting + passing wrong buffer size easilly. + * result/VC/* result/valid/rss.xml.err result/valid/xlink.xml.err: + updated the results to follow the errors string generated by + last commit. + Tue Oct 7 14:16:45 CEST 2003 Daniel Veillard * relaxng.c include/libxml/xmlerror.h: last cleanup of error diff --git a/error.c b/error.c index f2fe3780..59c7037d 100644 --- a/error.c +++ b/error.c @@ -262,13 +262,13 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, if (input != NULL) { if (input->filename) channel(data, "%s:%d: ", input->filename, input->line); - else + 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 + else if ((line != 0) && (domain == XML_FROM_PARSER)) channel(data, "Entity: line %d: ", line); } if (name != NULL) { @@ -362,11 +362,24 @@ xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str, if (cur != NULL) { if (cur->filename) channel(data, "%s:%d: \n", cur->filename, cur->line); - else + 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); + } } /** diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h index 2d653602..7c21aec3 100644 --- a/include/libxml/xmlerror.h +++ b/include/libxml/xmlerror.h @@ -375,7 +375,29 @@ typedef enum { XML_RNGP_VALUE_EMPTY, XML_RNGP_VALUE_NO_CONTENT, XML_RNGP_XMLNS_NAME, - XML_RNGP_XML_NS + XML_RNGP_XML_NS, + XML_XPATH_EXPRESSION_OK = 1200, + XML_XPATH_NUMBER_ERROR, + XML_XPATH_UNFINISHED_LITERAL_ERROR, + XML_XPATH_START_LITERAL_ERROR, + XML_XPATH_VARIABLE_REF_ERROR, + XML_XPATH_UNDEF_VARIABLE_ERROR, + XML_XPATH_INVALID_PREDICATE_ERROR, + XML_XPATH_EXPR_ERROR, + XML_XPATH_UNCLOSED_ERROR, + XML_XPATH_UNKNOWN_FUNC_ERROR, + XML_XPATH_INVALID_OPERAND, + XML_XPATH_INVALID_TYPE, + XML_XPATH_INVALID_ARITY, + XML_XPATH_INVALID_CTXT_SIZE, + XML_XPATH_INVALID_CTXT_POSITION, + XML_XPATH_MEMORY_ERROR, + XML_XPTR_SYNTAX_ERROR, + XML_XPTR_RESOURCE_ERROR, + XML_XPTR_SUB_RESOURCE_ERROR, + XML_XPATH_UNDEF_PREFIX_ERROR, + XML_XPATH_ENCODING_ERROR, + XML_XPATH_INVALID_CHAR_ERROR } xmlParserErrors; /** @@ -389,7 +411,16 @@ typedef enum { */ typedef void (*xmlGenericErrorFunc) (void *ctx, const char *msg, - ...); + ...); +/** + * xmlStructuredErrorFunc: + * @userData: user provided data for the error callback + * @error: the error being raised. + * + * Signature of the function to use when there is an error and + * the module handles the new error reporting mechanism. + */ +typedef void (*xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); /* * Use the following function to reset the two global variables diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h index d7471dfb..dbd1b777 100644 --- a/include/libxml/xpath.h +++ b/include/libxml/xpath.h @@ -13,6 +13,7 @@ #define __XML_XPATH_H__ #include +#include #include #include @@ -253,6 +254,12 @@ struct _xmlXPathContext { /* temporary namespace lists kept for walking the namespace axis */ xmlNsPtr *tmpNsList; /* Array of namespaces */ int tmpNsNr; /* number of namespace in scope */ + + /* error reporting mechanism */ + void *userData; /* user specific data block */ + xmlStructuredErrorFunc error; /* the callback in case of errors */ + xmlError lastError; /* the last error */ + xmlNodePtr debugNode; /* the source node XSLT */ }; /* diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h index 6b9e9965..269edb8c 100644 --- a/include/libxml/xpathInternals.h +++ b/include/libxml/xpathInternals.h @@ -250,8 +250,7 @@ XMLPUBFUN void * XMLCALL * Macro to raise an XPath error and return. */ #define XP_ERROR(X) \ - { xmlXPatherror(ctxt, __FILE__, __LINE__, X); \ - ctxt->error = (X); return; } + { xmlXPathErr(ctxt, X); return; } /** * XP_ERROR0: @@ -260,8 +259,7 @@ XMLPUBFUN void * XMLCALL * Macro to raise an XPath error and return 0. */ #define XP_ERROR0(X) \ - { xmlXPatherror(ctxt, __FILE__, __LINE__, X); \ - ctxt->error = (X); return(0); } + { xmlXPathErr(ctxt, X); return(0); } /** * CHECK_TYPE: @@ -377,6 +375,10 @@ XMLPUBFUN void XMLCALL int line, int no); +XMLPUBFUN void XMLCALL + xmlXPathErr (xmlXPathParserContextPtr ctxt, + int error); + #ifdef LIBXML_DEBUG_ENABLED XMLPUBFUN void XMLCALL xmlXPathDebugDumpObject (FILE *output, diff --git a/parser.c b/parser.c index e5ce1dac..33fe5ee8 100644 --- a/parser.c +++ b/parser.c @@ -2449,6 +2449,7 @@ xmlStrPrintf(xmlChar *buf, int len, const xmlChar *msg, ...) { va_start(args, msg); ret = vsnprintf((char *) buf, len, (const char *) msg, args); va_end(args); + buf[len - 1] = 0; /* be safe ! */ return(ret); } diff --git a/result/VC/AttributeDefaultLegal b/result/VC/AttributeDefaultLegal index 739c6641..6b616866 100644 --- a/result/VC/AttributeDefaultLegal +++ b/result/VC/AttributeDefaultLegal @@ -7,6 +7,6 @@ ./test/VC/AttributeDefaultLegal:8: validity error : Attribute doc of bad2: invalid default value ^ -./test/VC/AttributeDefaultLegal:11: validity error : No declaration for attribute val of element doc +./test/VC/AttributeDefaultLegal:11: element doc: validity error : No declaration for attribute val of element doc ^ diff --git a/result/VC/ElementValid2 b/result/VC/ElementValid2 index c78caff5..db47c897 100644 --- a/result/VC/ElementValid2 +++ b/result/VC/ElementValid2 @@ -1,3 +1,3 @@ -./test/VC/ElementValid2:4: validity error : No declaration for element p +./test/VC/ElementValid2:4: element p: validity error : No declaration for element p

^ diff --git a/result/VC/ElementValid3 b/result/VC/ElementValid3 index 02ffe0d8..2fc236d5 100644 --- a/result/VC/ElementValid3 +++ b/result/VC/ElementValid3 @@ -1,3 +1,3 @@ -./test/VC/ElementValid3:4: validity error : Element doc was declared EMPTY this one has content +./test/VC/ElementValid3:4: element doc: validity error : Element doc was declared EMPTY this one has content Oops, this element was declared EMPTY ^ diff --git a/result/VC/ElementValid4 b/result/VC/ElementValid4 index 00d737da..4791db5d 100644 --- a/result/VC/ElementValid4 +++ b/result/VC/ElementValid4 @@ -1,3 +1,3 @@ -./test/VC/ElementValid4:7: validity error : Element c is not declared in doc list of possible children +./test/VC/ElementValid4:7: element doc: validity error : Element c is not declared in doc list of possible children This seems Ok but this was not declared ^ diff --git a/result/VC/ElementValid5 b/result/VC/ElementValid5 index 7dd5d7df..bd064f6b 100644 --- a/result/VC/ElementValid5 +++ b/result/VC/ElementValid5 @@ -1,3 +1,3 @@ -./test/VC/ElementValid5:7: validity error : Element doc content does not follow the DTD, expecting (a , b* , c+), got (a b c b) +./test/VC/ElementValid5:7: element doc: validity error : Element doc content does not follow the DTD, expecting (a , b* , c+), got (a b c b) but thiswas not declaredseems ^ diff --git a/result/VC/ElementValid6 b/result/VC/ElementValid6 index ff5f52f6..1cbf8fdb 100644 --- a/result/VC/ElementValid6 +++ b/result/VC/ElementValid6 @@ -1,3 +1,3 @@ -./test/VC/ElementValid6:7: validity error : Element doc content does not follow the DTD, expecting (a , b? , c+)?, got (a b) +./test/VC/ElementValid6:7: element doc: validity error : Element doc content does not follow the DTD, expecting (a , b? , c+)?, got (a b) lacks c ^ diff --git a/result/VC/ElementValid7 b/result/VC/ElementValid7 index a800f90a..4ce9dbfe 100644 --- a/result/VC/ElementValid7 +++ b/result/VC/ElementValid7 @@ -1,3 +1,3 @@ -./test/VC/ElementValid7:7: validity error : Element doc content does not follow the DTD, expecting ((a | b)* , c+ , a , b? , c , a?), got (a b a c c a) +./test/VC/ElementValid7:7: element doc: validity error : Element doc content does not follow the DTD, expecting ((a | b)* , c+ , a , b? , c , a?), got (a b a c c a) ^ diff --git a/result/VC/Enumeration b/result/VC/Enumeration index 394f576b..30896fc2 100644 --- a/result/VC/Enumeration +++ b/result/VC/Enumeration @@ -1,3 +1,3 @@ -./test/VC/Enumeration:5: validity error : Value "v4" for attribute val of doc is not among the enumerated set +./test/VC/Enumeration:5: element doc: validity error : Value "v4" for attribute val of doc is not among the enumerated set ^ diff --git a/result/VC/NS2 b/result/VC/NS2 index ac095d3c..abd1f88f 100644 --- a/result/VC/NS2 +++ b/result/VC/NS2 @@ -1,3 +1,3 @@ -./test/VC/NS2:9: validity error : No declaration for attribute attr of element doc +./test/VC/NS2:9: element doc: validity error : No declaration for attribute attr of element doc ^ diff --git a/result/VC/NS3 b/result/VC/NS3 index e7989785..72c01175 100644 --- a/result/VC/NS3 +++ b/result/VC/NS3 @@ -1,9 +1,9 @@ -./test/VC/NS3:9: validity error : Value for attribute xmlns of foo is different from default "http://example.com/fooo" +./test/VC/NS3:9: element foo: validity error : Value for attribute xmlns of foo is different from default "http://example.com/fooo" xmlns="http://example.com/foo" xmlns:foo="http://example.com/fo" foo:info="toto" ^ -./test/VC/NS3:9: validity error : Value for attribute xmlns of foo must be "http://example.com/fooo" +./test/VC/NS3:9: element foo: validity error : Value for attribute xmlns of foo must be "http://example.com/fooo" xmlns="http://example.com/foo" xmlns:foo="http://example.com/fo" foo:info="toto" ^ -./test/VC/NS3:9: validity error : Element foo namespace name for default namespace does not match the DTD +./test/VC/NS3:9: element foo: validity error : Element foo namespace name for default namespace does not match the DTD mlns="http://example.com/foo" xmlns:foo="http://example.com/fo" foo:info="toto"/ ^ diff --git a/result/VC/OneID b/result/VC/OneID index 422e87c2..4a73cbe5 100644 --- a/result/VC/OneID +++ b/result/VC/OneID @@ -1,7 +1,7 @@ ./test/VC/OneID:4: validity error : Element doc has too may ID attributes defined : id ^ -Element doc has too many ID attributes defined : id +./test/VC/OneID:0: validity error : Element doc has too many ID attributes defined : id ./test/VC/OneID:4: validity error : Element doc has 2 ID attribute defined in the internal subset : id ^ diff --git a/result/VC/OneID2 b/result/VC/OneID2 index 7dbd4bcc..b46663bd 100644 --- a/result/VC/OneID2 +++ b/result/VC/OneID2 @@ -1,7 +1,7 @@ ./test/VC/OneID2:3: validity error : Element doc has too may ID attributes defined : id ^ -Element doc has too many ID attributes defined : id +Entity: line 0: validity error : Element doc has too many ID attributes defined : id ./test/VC/OneID2:3: validity error : Element doc has 2 ID attribute defined in the internal subset : id ^ diff --git a/result/VC/OneID3 b/result/VC/OneID3 index 6c3041ed..994051a2 100644 --- a/result/VC/OneID3 +++ b/result/VC/OneID3 @@ -1,7 +1,7 @@ test/VC/dtds/doc.dtd:2: validity error : Element doc has too may ID attributes defined : val ^ -Element doc has too many ID attributes defined : val +./test/VC/OneID3:0: validity error : Element doc has too many ID attributes defined : val test/VC/dtds/doc.dtd:2: validity error : Element doc has 2 ID attribute defined in the external subset : val ^ diff --git a/result/noent/slashdot16.xml b/result/noent/slashdot16.xml new file mode 100644 index 00000000..f4b168d6 Binary files /dev/null and b/result/noent/slashdot16.xml differ diff --git a/result/slashdot16.xml b/result/slashdot16.xml new file mode 100644 index 00000000..f4b168d6 Binary files /dev/null and b/result/slashdot16.xml differ diff --git a/result/valid/rss.xml.err b/result/valid/rss.xml.err index fd7b7d11..2ec7c9e5 100644 --- a/result/valid/rss.xml.err +++ b/result/valid/rss.xml.err @@ -1,3 +1,3 @@ -./test/valid/rss.xml:177: validity error : Element rss does not carry attribute version +./test/valid/rss.xml:177: element rss: validity error : Element rss does not carry attribute version ^ diff --git a/result/valid/xlink.xml.err b/result/valid/xlink.xml.err index bf011c84..08c84bdc 100644 --- a/result/valid/xlink.xml.err +++ b/result/valid/xlink.xml.err @@ -1,6 +1,6 @@ -./test/valid/xlink.xml:450: validity error : ID dt-arc already defined +./test/valid/xlink.xml:450: element termdef: validity error : ID dt-arc already defined

An arc is contained within an e ^ -./test/valid/xlink.xml:530: validity error : IDREF attribute def references an unknown ID "dt-xlg" +./test/valid/xlink.xml:530: element termref: validity error : IDREF attribute def references an unknown ID "dt-xlg" ^ diff --git a/threads.c b/threads.c index b51caa21..63d50b0e 100644 --- a/threads.c +++ b/threads.c @@ -336,7 +336,8 @@ xmlNewGlobalState(void) #ifdef HAVE_WIN32_THREADS -#if !defined(HAVE_COMPILER_TLS) && defined(LIBXML_STATIC) +#if !defined(HAVE_COMPILER_TLS) +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) typedef struct _xmlGlobalStateCleanupHelperParams { HANDLE thread; @@ -352,7 +353,20 @@ static void xmlGlobalStateCleanupHelper (void *p) free(params); _endthread(); } -#endif /* HAVE_COMPILER_TLS && LIBXML_STATIC */ +#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */ + +typedef struct _xmlGlobalStateCleanupHelperParams +{ + void *memory; + struct _xmlGlobalStateCleanupHelperParams * prev; + struct _xmlGlobalStateCleanupHelperParams * next; +} xmlGlobalStateCleanupHelperParams; + +static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL; +static CRITICAL_SECTION cleanup_helpers_cs; + +#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */ +#endif /* HAVE_COMPILER_TLS */ #endif /* HAVE_WIN32_THREADS */ /** @@ -387,23 +401,37 @@ xmlGetGlobalState(void) return &tlstate; #else /* HAVE_COMPILER_TLS */ xmlGlobalState *globalval; + xmlGlobalStateCleanupHelperParams * p; if (run_once_init) { run_once_init = 0; xmlOnceInit(); } - if ((globalval = (xmlGlobalState *) TlsGetValue(globalkey)) == NULL) { +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) + globalval = (xmlGlobalState *)TlsGetValue(globalkey); +#else + p = (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); + globalval = (xmlGlobalState *)(p ? p->memory : NULL); +#endif + if (globalval == NULL) { xmlGlobalState *tsd = xmlNewGlobalState(); -#if defined(LIBXML_STATIC) - xmlGlobalStateCleanupHelperParams *p = - (xmlGlobalStateCleanupHelperParams *) malloc(sizeof(xmlGlobalStateCleanupHelperParams)); + p = (xmlGlobalStateCleanupHelperParams *) malloc(sizeof(xmlGlobalStateCleanupHelperParams)); p->memory = tsd; +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->thread, 0, TRUE, DUPLICATE_SAME_ACCESS); -#endif TlsSetValue(globalkey, tsd); -#if defined(LIBXML_STATIC) _beginthread(xmlGlobalStateCleanupHelper, 0, p); +#else + EnterCriticalSection(&cleanup_helpers_cs); + if (cleanup_helpers_head != NULL) { + cleanup_helpers_head->prev = p; + } + p->next = cleanup_helpers_head; + p->prev = NULL; + cleanup_helpers_head = p; + TlsSetValue(globalkey, p); + LeaveCriticalSection(&cleanup_helpers_cs); #endif return (tsd); @@ -513,6 +541,9 @@ xmlInitThreads(void) #ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlInitThreads()\n"); #endif +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) + InitializeCriticalSection(&cleanup_helpers_cs); +#endif } /** @@ -527,6 +558,24 @@ xmlCleanupThreads(void) #ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); #endif +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) + if (globalkey != TLS_OUT_OF_INDEXES) { + xmlGlobalStateCleanupHelperParams * p; + EnterCriticalSection(&cleanup_helpers_cs); + p = cleanup_helpers_head; + while (p != NULL) { + xmlGlobalStateCleanupHelperParams * temp = p; + p = p->next; + xmlFreeGlobalState(temp->memory); + free(temp); + } + cleanup_helpers_head = 0; + LeaveCriticalSection(&cleanup_helpers_cs); + TlsFree(globalkey); + globalkey = TLS_OUT_OF_INDEXES; + } + DeleteCriticalSection(&cleanup_helpers_cs); +#endif } #ifdef LIBXML_THREAD_ENABLED @@ -566,27 +615,39 @@ xmlOnceInit(void) { * * Returns TRUE always */ -#if defined(HAVE_WIN32_THREADS) && !defined(LIBXML_STATIC) +#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) +#if defined(LIBXML_STATIC_FOR_DLL) +BOOL WINAPI xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +#else BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +#endif { switch(fdwReason) { case DLL_THREAD_DETACH: if (globalkey != TLS_OUT_OF_INDEXES) { - xmlGlobalState *globalval = (xmlGlobalState *)TlsGetValue(globalkey); - if (globalval) { - xmlFreeGlobalState(globalval); - TlsSetValue(globalkey, NULL); + xmlGlobalState *globalval = NULL; + xmlGlobalStateCleanupHelperParams * p = + (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); + globalval = (xmlGlobalState *)(p ? p->memory : NULL); + if (globalval) { + xmlFreeGlobalState(globalval); + TlsSetValue(globalkey,NULL); + } + if (p) + { + EnterCriticalSection(&cleanup_helpers_cs); + if (p == cleanup_helpers_head) + cleanup_helpers_head = p->next; + else + p->prev->next = p->next; + if (p->next != NULL) + p->next->prev = p->prev; + LeaveCriticalSection(&cleanup_helpers_cs); + free(p); } } break; - case DLL_PROCESS_DETACH: - if (globalkey != TLS_OUT_OF_INDEXES) { - TlsFree(globalkey); - globalkey = TLS_OUT_OF_INDEXES; - } - break; } return TRUE; } #endif - diff --git a/xpath.c b/xpath.c index 65ca1800..605b5887 100644 --- a/xpath.c +++ b/xpath.c @@ -52,6 +52,11 @@ #include #include +#define TODO \ + xmlGenericError(xmlGenericErrorContext, \ + "Unimplemented block at %s:%d\n", \ + __FILE__, __LINE__); + #if defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XPATH_ENABLED) /************************************************************************ * * @@ -164,6 +169,161 @@ static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; static int xmlXPathDisableOptimizer = 0; #endif +/************************************************************************ + * * + * Error handling routines * + * * + ************************************************************************/ + + +static const char *xmlXPathErrorMessages[] = { + "Ok\n", + "Number encoding\n", + "Unfinished literal\n", + "Start of literal\n", + "Expected $ for variable reference\n", + "Undefined variable\n", + "Invalid predicate\n", + "Invalid expression\n", + "Missing closing curly brace\n", + "Unregistered function\n", + "Invalid operand\n", + "Invalid type\n", + "Invalid number of arguments\n", + "Invalid context size\n", + "Invalid context position\n", + "Memory allocation error\n", + "Syntax error\n", + "Resource error\n", + "Sub resource error\n", + "Undefined namespace prefix\n", + "Encoding error\n", + "Char out of XML range\n" +}; + + +/** + * xmlXPathErrMemory: + * @ctxt: an XPath context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra) +{ + if (ctxt != NULL) { + if (extra) { + xmlChar buf[200]; + + xmlStrPrintf(buf, 200, + BAD_CAST "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, 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, XML_FROM_XPATH, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, + NULL, NULL, NULL, 0, 0, + "Memory allocation failed\n"); + } +} + +/** + * xmlXPathErrMemory: + * @ctxt: an XPath parser context + * @extra: extra informations + * + * Handle a redefinition of attribute error + */ +static void +xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra) +{ + ctxt->error = XPATH_MEMORY_ERROR; + if (ctxt == NULL) + xmlXPathErrMemory(NULL, extra); + else + xmlXPathErrMemory(ctxt->context, extra); +} + +/** + * xmlXPathErr: + * @ctxt: a XPath parser context + * @node: the node raising the error + * @error: the error code + * @msg: message + * @str1: extra info + * @str2: extra info + * + * Handle a Relax NG Parsing error + */ +void +xmlXPathErr(xmlXPathParserContextPtr ctxt, int error) +{ + if (ctxt != NULL) + ctxt->error = error; + if ((ctxt == NULL) || (ctxt->context == NULL)) { + __xmlRaiseError(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, + xmlXPathErrorMessages[error]); + return; + } + 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_FATAL; + 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, 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, + xmlXPathErrorMessages[error]); + } + +} + +/** + * xmlXPatherror: + * @ctxt: the XPath Parser context + * @file: the file name + * @line: the line number + * @no: the error number + * + * Formats an error message. + */ +void +xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED, + int line ATTRIBUTE_UNUSED, int no) { + xmlXPathErr(ctxt, no); +} + + /************************************************************************ * * * Parser Types * @@ -278,8 +438,7 @@ xmlXPathNewCompExpr(void) { cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr)); if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewCompExpr : malloc failed\n"); + xmlXPathErrMemory(NULL, "allocating component\n"); return(NULL); } memset(cur, 0, sizeof(xmlXPathCompExpr)); @@ -288,8 +447,7 @@ xmlXPathNewCompExpr(void) { cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep * sizeof(xmlXPathStepOp)); if (cur->steps == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewCompExpr : malloc failed\n"); + xmlXPathErrMemory(NULL, "allocating steps\n"); xmlFree(cur); return(NULL); } @@ -369,8 +527,7 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, comp->maxStep * sizeof(xmlXPathStepOp)); if (real == NULL) { comp->maxStep /= 2; - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompExprAdd : realloc failed\n"); + xmlXPathErrMemory(NULL, "adding step\n"); return(-1); } comp->steps = real; @@ -436,11 +593,6 @@ xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), (val), (val2), 0 ,NULL ,NULL * * ************************************************************************/ -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - #define STRANGE \ xmlGenericError(xmlGenericErrorContext, \ "Internal error at %s:%d\n", \ @@ -1247,96 +1399,6 @@ xmlXPathFormatNumber(double number, char buffer[], int buffersize) } } -/************************************************************************ - * * - * Error handling routines * - * * - ************************************************************************/ - - -static const char *xmlXPathErrorMessages[] = { - "Ok", - "Number encoding", - "Unfinished literal", - "Start of literal", - "Expected $ for variable reference", - "Undefined variable", - "Invalid predicate", - "Invalid expression", - "Missing closing curly brace", - "Unregistered function", - "Invalid operand", - "Invalid type", - "Invalid number of arguments", - "Invalid context size", - "Invalid context position", - "Memory allocation error", - "Syntax error", - "Resource error", - "Sub resource error", - "Undefined namespace prefix", - "Encoding error", - "Char out of XML range" -}; - -/** - * xmlXPatherror: - * @ctxt: the XPath Parser context - * @file: the file name - * @line: the line number - * @no: the error number - * - * Formats an error message. - */ -void -xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED, - int line ATTRIBUTE_UNUSED, int no) { - int n; - const xmlChar *cur; - const xmlChar *base; - - cur = ctxt->cur; - base = ctxt->base; - if ((cur == NULL) || (base == NULL)) { - if ((ctxt->comp != NULL) && (ctxt->comp->expr != NULL)) { - xmlGenericError(xmlGenericErrorContext, - "XPath error %s in %s\n", xmlXPathErrorMessages[no], - ctxt->comp->expr); - } else { - xmlGenericError(xmlGenericErrorContext, - "XPath error %s\n", xmlXPathErrorMessages[no]); - } - - return; - } - xmlGenericError(xmlGenericErrorContext, - "XPath error %s\n", xmlXPathErrorMessages[no]); - - while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) { - cur--; - } - n = 0; - while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r')) - cur--; - if ((*cur == '\n') || (*cur == '\r')) cur++; - base = cur; - n = 0; - while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) { - xmlGenericError(xmlGenericErrorContext, "%c", (unsigned char) *cur++); - n++; - } - xmlGenericError(xmlGenericErrorContext, "\n"); - cur = ctxt->cur; - while ((*cur == '\n') || (*cur == '\r')) - cur--; - n = 0; - while ((cur != base) && (n++ < 80)) { - xmlGenericError(xmlGenericErrorContext, " "); - base++; - } - xmlGenericError(xmlGenericErrorContext,"^\n"); -} - /************************************************************************ * * @@ -1564,8 +1626,7 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) { */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetDupNs : malloc failed\n"); + xmlXPathErrMemory(NULL, "duplicating namespace\n"); return(NULL); } memset(cur, 0, sizeof(xmlNs)); @@ -1614,8 +1675,7 @@ xmlXPathNodeSetCreate(xmlNodePtr val) { ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetCreate: out of memory\n"); + xmlXPathErrMemory(NULL, "creating nodeset\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); @@ -1623,8 +1683,8 @@ xmlXPathNodeSetCreate(xmlNodePtr val) { ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (ret->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetCreate: out of memory\n"); + xmlXPathErrMemory(NULL, "creating nodeset\n"); + xmlFree(ret); return(NULL); } memset(ret->nodeTab, 0 , @@ -1712,8 +1772,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAdd: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , @@ -1726,8 +1785,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAdd: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; @@ -1767,8 +1825,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAdd: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , @@ -1781,8 +1838,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAdd: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; @@ -1821,8 +1877,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAddUnique: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , @@ -1835,8 +1890,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetAddUnique: out of memory\n"); + xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; @@ -1903,8 +1957,7 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (val1->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetMerge: out of memory\n"); + xmlXPathErrMemory(NULL, "merging nodeset\n"); return(NULL); } memset(val1->nodeTab, 0 , @@ -1917,8 +1970,7 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetMerge: out of memory\n"); + xmlXPathErrMemory(NULL, "merging nodeset\n"); return(NULL); } val1->nodeTab = temp; @@ -1964,8 +2016,7 @@ xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (val1->nodeTab == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetMerge: out of memory\n"); + xmlXPathErrMemory(NULL, "merging nodeset\n"); return(NULL); } memset(val1->nodeTab, 0 , @@ -1978,8 +2029,7 @@ xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetMerge: out of memory\n"); + xmlXPathErrMemory(NULL, "merging nodeset\n"); return(NULL); } val1->nodeTab = temp; @@ -2159,8 +2209,7 @@ xmlXPathNewNodeSet(xmlNodePtr val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewNodeSet: out of memory\n"); + xmlXPathErrMemory(NULL, "creating nodeset\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -2186,8 +2235,7 @@ xmlXPathNewValueTree(xmlNodePtr val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewNodeSet: out of memory\n"); + xmlXPathErrMemory(NULL, "creating result value tree\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -2240,8 +2288,7 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathWrapNodeSet: out of memory\n"); + xmlXPathErrMemory(NULL, "creating node set object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3007,8 +3054,7 @@ xmlXPathNewFloat(double val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewFloat: out of memory\n"); + xmlXPathErrMemory(NULL, "creating float object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3031,8 +3077,7 @@ xmlXPathNewBoolean(int val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewBoolean: out of memory\n"); + xmlXPathErrMemory(NULL, "creating boolean object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3055,8 +3100,7 @@ xmlXPathNewString(const xmlChar *val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewString: out of memory\n"); + xmlXPathErrMemory(NULL, "creating string object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3082,8 +3126,7 @@ xmlXPathWrapString (xmlChar *val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathWrapString: out of memory\n"); + xmlXPathErrMemory(NULL, "creating string object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3106,8 +3149,7 @@ xmlXPathNewCString(const char *val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewCString: out of memory\n"); + xmlXPathErrMemory(NULL, "creating string object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3143,8 +3185,7 @@ xmlXPathWrapExternal (void *val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathWrapExternal: out of memory\n"); + xmlXPathErrMemory(NULL, "creating user object\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); @@ -3170,8 +3211,7 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathObjectCopy: out of memory\n"); + xmlXPathErrMemory(NULL, "copying object\n"); return(NULL); } memcpy(ret, val , (size_t) sizeof(xmlXPathObject)); @@ -3722,8 +3762,7 @@ xmlXPathNewContext(xmlDocPtr doc) { ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewContext: out of memory\n"); + xmlXPathErrMemory(NULL, "creating context\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathContext)); @@ -3814,8 +3853,7 @@ xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) { ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNewParserContext: out of memory\n"); + xmlXPathErrMemory(ctxt, "creating parser context\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); @@ -3847,8 +3885,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) { ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompParserContext: out of memory\n"); + xmlXPathErrMemory(ctxt, "creating evaluation context\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); @@ -3858,8 +3895,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) { xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ret->valueTab == NULL) { xmlFree(ret); - xmlGenericError(xmlGenericErrorContext, - "xmlXPathCompParserContext: out of memory\n"); + xmlXPathErrMemory(ctxt, "creating evaluation context\n"); return(NULL); } ret->valueNr = 0; @@ -4210,6 +4246,7 @@ xmlXPathCompareNodeSets(int inf, int strict, values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double)); if (values2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); xmlXPathFreeObject(arg1); xmlXPathFreeObject(arg2); return(0); @@ -4460,22 +4497,27 @@ xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) { return(1); values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *)); - if (values1 == NULL) + if (values1 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); return(0); + } hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int)); if (hashs1 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); xmlFree(values1); return(0); } memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *)); values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *)); if (values2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); xmlFree(hashs1); xmlFree(values1); return(0); } hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int)); if (hashs2 == NULL) { + xmlXPathErrMemory(NULL, "comparing nodesets\n"); xmlFree(hashs1); xmlFree(values1); xmlFree(values2); @@ -10608,6 +10650,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt) { ctxt->valueTab = (xmlXPathObjectPtr *) xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ctxt->valueTab == NULL) { + xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); xmlFree(ctxt); } ctxt->valueNr = 0;