cleaning up XPath error reporting that time. applied the two patches for
* 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.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 795696d..38228d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Tue Oct 7 23:19:39 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+ * 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 <daniel@veillard.com>
* relaxng.c include/libxml/xmlerror.h: last cleanup of error
diff --git a/error.c b/error.c
index f2fe378..59c7037 100644
--- a/error.c
+++ b/error.c
@@ -262,13 +262,13 @@
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 @@
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 2d65360..7c21aec 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -375,7 +375,29 @@
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 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 d7471df..dbd1b77 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -13,6 +13,7 @@
#define __XML_XPATH_H__
#include <libxml/xmlversion.h>
+#include <libxml/xmlerror.h>
#include <libxml/tree.h>
#include <libxml/hash.h>
@@ -253,6 +254,12 @@
/* 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 6b9e996..269edb8 100644
--- a/include/libxml/xpathInternals.h
+++ b/include/libxml/xpathInternals.h
@@ -250,8 +250,7 @@
* 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 @@
* 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 @@
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 e5ce1da..33fe5ee 100644
--- a/parser.c
+++ b/parser.c
@@ -2449,6 +2449,7 @@
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 739c664..6b61686 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
<!ATTLIST doc bad2 IDREFS "abc:1 1abc_2">
^
-./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
<doc val="v1"/>
^
diff --git a/result/VC/ElementValid2 b/result/VC/ElementValid2
index c78caff..db47c89 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
<doc><p/></doc>
^
diff --git a/result/VC/ElementValid3 b/result/VC/ElementValid3
index 02ffe0d..2fc236d 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
<doc>Oops, this element was declared EMPTY</doc>
^
diff --git a/result/VC/ElementValid4 b/result/VC/ElementValid4
index 00d737d..4791db5 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
<doc> This <b>seems</b> Ok <a/> but this <c>was not declared</c></doc>
^
diff --git a/result/VC/ElementValid5 b/result/VC/ElementValid5
index 7dd5d7d..bd064f6 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)
<doc><a/><b> but this</b><c>was not declared</c><b>seems</b></doc>
^
diff --git a/result/VC/ElementValid6 b/result/VC/ElementValid6
index ff5f52f..1cbf8fd 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)
<doc><a/><b>lacks c</b></doc>
^
diff --git a/result/VC/ElementValid7 b/result/VC/ElementValid7
index a800f90..4ce9dbf 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)
<doc><a/><b/><a/><c/><c/><a/></doc>
^
diff --git a/result/VC/Enumeration b/result/VC/Enumeration
index 394f576..30896fc 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
<doc val="v4"></doc>
^
diff --git a/result/VC/NS2 b/result/VC/NS2
index ac095d3..abd1f88 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
<ns:doc ns:attr="val" xmlns:ns="http://www.example.org/test/">
^
diff --git a/result/VC/NS3 b/result/VC/NS3
index e798978..72c0117 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 422e87c..4a73cbe 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
<!ATTLIST doc id ID #IMPLIED>
^
-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
<!ATTLIST doc id ID #IMPLIED>
^
diff --git a/result/VC/OneID2 b/result/VC/OneID2
index 7dbd4bc..b46663b 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
<!ATTLIST doc id ID #IMPLIED>
^
-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
<!ATTLIST doc id ID #IMPLIED>
^
diff --git a/result/VC/OneID3 b/result/VC/OneID3
index 6c3041e..994051a 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
<!ATTLIST doc val ID #IMPLIED>
^
-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
<!ATTLIST doc val ID #IMPLIED>
^
diff --git a/result/noent/slashdot16.xml b/result/noent/slashdot16.xml
new file mode 100644
index 0000000..f4b168d
--- /dev/null
+++ b/result/noent/slashdot16.xml
Binary files differ
diff --git a/result/slashdot16.xml b/result/slashdot16.xml
new file mode 100644
index 0000000..f4b168d
--- /dev/null
+++ b/result/slashdot16.xml
Binary files differ
diff --git a/result/valid/rss.xml.err b/result/valid/rss.xml.err
index fd7b7d1..2ec7c9e 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
</rss>
^
diff --git a/result/valid/xlink.xml.err b/result/valid/xlink.xml.err
index bf011c8..08c84bd 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
<p><termdef id="dt-arc" term="Arc">An <term>arc</term> 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 b51caa2..63d50b0 100644
--- a/threads.c
+++ b/threads.c
@@ -336,7 +336,8 @@
#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 @@
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 @@
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 @@
#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 @@
#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 @@
*
* 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 65ca180..605b588 100644
--- a/xpath.c
+++ b/xpath.c
@@ -52,6 +52,11 @@
#include <libxml/threads.h>
#include <libxml/globals.h>
+#define TODO \
+ xmlGenericError(xmlGenericErrorContext, \
+ "Unimplemented block at %s:%d\n", \
+ __FILE__, __LINE__);
+
#if defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XPATH_ENABLED)
/************************************************************************
* *
@@ -165,6 +170,161 @@
#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 @@
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 @@
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 @@
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 @@
* *
************************************************************************/
-#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 @@
}
}
-/************************************************************************
- * *
- * 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 @@
*/
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
ctxt->valueTab = (xmlXPathObjectPtr *)
xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
if (ctxt->valueTab == NULL) {
+ xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
xmlFree(ctxt);
}
ctxt->valueNr = 0;