patch from Stéphane Bidoul for setting up threads global defaults. this
* build_glob.py global.data globals.c parser.c
include/libxml/globals.h: patch from Stéphane Bidoul for setting
up threads global defaults.
* doc/libxml2-api.xml: this extends the API with new functions
* python/tests/Makefile.am python/tests/reader2.py
python/tests/thread2.py: integrated the associated testcase and
fixed the error string used in reader2
Daniel
diff --git a/ChangeLog b/ChangeLog
index 85f869a..b706354 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu May 15 18:06:18 EDT 2003 Daniel Veillard <daniel@veillard.com>
+
+ * build_glob.py global.data globals.c parser.c
+ include/libxml/globals.h: patch from Stéphane Bidoul for setting
+ up threads global defaults.
+ * doc/libxml2-api.xml: this extends the API with new functions
+ * python/tests/Makefile.am python/tests/reader2.py
+ python/tests/thread2.py: integrated the associated testcase and
+ fixed the error string used in reader2
+
Wed May 14 14:56:46 EDT 2003 Daniel Veillard <daniel@veillard.com>
* configure.in libxml.spec.in python/Makefile.am: trying
diff --git a/build_glob.py b/build_glob.py
index dc42c24..8855ec7 100755
--- a/build_glob.py
+++ b/build_glob.py
@@ -16,10 +16,15 @@
self.type=type
self.name=name
+def striplinesep(line):
+ while line and line[-1] in ('\r','\n'):
+ line = line[:-1]
+ return line
+
def writeline(file, line=None):
if line:
file.write(line)
- file.write(os.linesep)
+ file.write("\n")
if __name__ == "__main__":
globals={}
@@ -34,8 +39,7 @@
# Automatically generated string
#
for line in global_hdr:
- if line[-len(os.linesep):] == os.linesep:
- line = line[:-len(os.linesep)]
+ line = striplinesep(line)
if line == " * Automatically generated by build_glob.py.":
break
writeline(global_functions_hdr, line)
@@ -46,8 +50,7 @@
writeline(global_functions_hdr)
for line in global_code:
- if line[-len(os.linesep):] == os.linesep:
- line = line[:-len(os.linesep)]
+ line = striplinesep(line)
if line == " * Automatically generated by build_glob.py.":
break
writeline(global_functions_impl, line)
@@ -61,36 +64,38 @@
for line in global_data:
if line[0]=='#':
continue
- if line[-len(os.linesep):] == os.linesep:
- line = line[:-len(os.linesep)]
+ line = striplinesep(line)
fields = string.split(line, ",")
# Update the header file
writeline(global_functions_hdr)
global_functions_hdr.write("extern "+fields[0]+" *")
- if len(fields) == 3:
+ if fields[2]:
global_functions_hdr.write("(*")
global_functions_hdr.write("__"+fields[1]+"(void)")
- if len(fields) == 3:
+ if fields[2]:
global_functions_hdr.write(")"+fields[2])
writeline(global_functions_hdr,";")
writeline(global_functions_hdr, "#ifdef LIBXML_THREAD_ENABLED")
writeline(global_functions_hdr,"#define "+fields[1]+" \\")
writeline(global_functions_hdr,"(*(__"+fields[1]+"()))")
writeline(global_functions_hdr,"#else")
- if len(fields) == 3:
+ if fields[2]:
writeline(global_functions_hdr,"LIBXML_DLL_IMPORT extern "+fields[0]+" "+fields[1]+fields[2]+";")
else:
writeline(global_functions_hdr,"LIBXML_DLL_IMPORT extern "+fields[0]+" "+fields[1]+";")
writeline(global_functions_hdr,"#endif")
+ # set/get for per-thread global defaults
+ if fields[3]:
+ writeline(global_functions_hdr,fields[0]+" "+fields[1][:3]+"ThrDef"+fields[1][3:]+"("+fields[0]+" v);")
# Update the implementation file
writeline(global_functions_impl)
# writeline(global_functions_impl, "extern "+fields[0]+" "+fields[1]+";")
writeline(global_functions_impl, "#undef\t"+fields[1])
writeline(global_functions_impl, fields[0]+" *")
- if len(fields) == 3:
+ if fields[2]:
global_functions_impl.write("(*")
global_functions_impl.write("__"+fields[1]+"(void)")
- if len(fields) == 3:
+ if fields[2]:
writeline(global_functions_impl, ")[]")
writeline(global_functions_impl, " {")
writeline(global_functions_impl, " if (IS_MAIN_THREAD)")
@@ -98,6 +103,16 @@
writeline(global_functions_impl, " else")
writeline(global_functions_impl, "\treturn (&xmlGetGlobalState()->"+fields[1]+");")
writeline(global_functions_impl, "}")
+ # set/get for per-thread global defaults
+ if fields[3]:
+ writeline(global_functions_impl,fields[0]+" "+fields[1][:3]+"ThrDef"+fields[1][3:]+"("+fields[0]+" v) {")
+ writeline(global_functions_impl," "+fields[0]+" ret;");
+ writeline(global_functions_impl," xmlMutexLock(xmlThrDefMutex);")
+ writeline(global_functions_impl," ret = "+fields[1][:3]+fields[1][3:]+"ThrDef;")
+ writeline(global_functions_impl," "+fields[1][:3]+fields[1][3:]+"ThrDef = v;")
+ writeline(global_functions_impl," xmlMutexUnlock(xmlThrDefMutex);")
+ writeline(global_functions_impl," return ret;")
+ writeline(global_functions_impl,"}")
# Terminate the header file with appropriate boilerplate
writeline(global_functions_hdr)
writeline(global_functions_hdr, "#ifdef __cplusplus")
diff --git a/doc/libxml2-api.xml b/doc/libxml2-api.xml
index a36a6e5..16ac150 100644
--- a/doc/libxml2-api.xml
+++ b/doc/libxml2-api.xml
@@ -1514,6 +1514,7 @@
<exports symbol='oldXMLWDcompatibility'/>
<exports symbol='xmlBufferAllocScheme'/>
<exports symbol='xmlBufferAllocScheme'/>
+ <exports symbol='xmlCleanupGlobals'/>
<exports symbol='xmlDefaultBufferSize'/>
<exports symbol='xmlDefaultBufferSize'/>
<exports symbol='xmlDefaultSAXHandler'/>
@@ -1538,6 +1539,7 @@
<exports symbol='xmlGlobalStatePtr'/>
<exports symbol='xmlIndentTreeOutput'/>
<exports symbol='xmlIndentTreeOutput'/>
+ <exports symbol='xmlInitGlobals'/>
<exports symbol='xmlInitializeGlobalState'/>
<exports symbol='xmlKeepBlanksDefaultValue'/>
<exports symbol='xmlKeepBlanksDefaultValue'/>
@@ -1567,6 +1569,22 @@
<exports symbol='xmlSaveNoEmptyTags'/>
<exports symbol='xmlSubstituteEntitiesDefaultValue'/>
<exports symbol='xmlSubstituteEntitiesDefaultValue'/>
+ <exports symbol='xmlThrDefBufferAllocScheme'/>
+ <exports symbol='xmlThrDefDefaultBufferSize'/>
+ <exports symbol='xmlThrDefDeregisterNodeDefault'/>
+ <exports symbol='xmlThrDefDoValidityCheckingDefaultValue'/>
+ <exports symbol='xmlThrDefGetWarningsDefaultValue'/>
+ <exports symbol='xmlThrDefIndentTreeOutput'/>
+ <exports symbol='xmlThrDefKeepBlanksDefaultValue'/>
+ <exports symbol='xmlThrDefLineNumbersDefaultValue'/>
+ <exports symbol='xmlThrDefLoadExtDtdDefaultValue'/>
+ <exports symbol='xmlThrDefParserDebugEntities'/>
+ <exports symbol='xmlThrDefPedanticParserDefaultValue'/>
+ <exports symbol='xmlThrDefRegisterNodeDefault'/>
+ <exports symbol='xmlThrDefSaveNoEmptyTags'/>
+ <exports symbol='xmlThrDefSetGenericErrorFunc'/>
+ <exports symbol='xmlThrDefSubstituteEntitiesDefaultValue'/>
+ <exports symbol='xmlThrDefTreeIndentString'/>
<exports symbol='xmlTreeIndentString'/>
<exports symbol='xmlTreeIndentString'/>
</file>
@@ -5383,6 +5401,10 @@
<info>Unregisters all aliases</info>
<return type='void'/>
</function>
+ <function name='xmlCleanupGlobals' file='globals'>
+ <info></info>
+ <return type='void'/>
+ </function>
<function name='xmlCleanupInputCallbacks' file='xmlIO'>
<info>clears the entire input callback table. this includes the compiled-in I/O.</info>
<return type='void'/>
@@ -6439,6 +6461,10 @@
<info>Initialize the char encoding support, it registers the default encoding supported. NOTE: while public, this function usually doesn't need to be called in normal processing.</info>
<return type='void'/>
</function>
+ <function name='xmlInitGlobals' file='globals'>
+ <info></info>
+ <return type='void'/>
+ </function>
<function name='xmlInitMemory' file='xmlmemory'>
<info>Initialize the memory layer.</info>
<return type='int' info='0 on success'/>
@@ -9300,6 +9326,87 @@
<return type='xmlChar *' info='the xml:lang value or NULL if none exists.'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
</function>
+ <function name='xmlThrDefBufferAllocScheme' file='globals'>
+ <info></info>
+ <return type='xmlBufferAllocationScheme' info=''/>
+ <arg name='v' type='xmlBufferAllocationScheme' info=''/>
+ </function>
+ <function name='xmlThrDefDefaultBufferSize' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefDeregisterNodeDefault' file='globals'>
+ <info></info>
+ <return type='xmlDeregisterNodeFunc' info=''/>
+ <arg name='func' type='xmlDeregisterNodeFunc' info=''/>
+ </function>
+ <function name='xmlThrDefDoValidityCheckingDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefGetWarningsDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefIndentTreeOutput' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefKeepBlanksDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefLineNumbersDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefLoadExtDtdDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefParserDebugEntities' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefPedanticParserDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefRegisterNodeDefault' file='globals'>
+ <info></info>
+ <return type='xmlRegisterNodeFunc' info=''/>
+ <arg name='func' type='xmlRegisterNodeFunc' info=''/>
+ </function>
+ <function name='xmlThrDefSaveNoEmptyTags' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefSetGenericErrorFunc' file='globals'>
+ <info></info>
+ <return type='void'/>
+ <arg name='ctx' type='void *' info=''/>
+ <arg name='handler' type='xmlGenericErrorFunc' info=''/>
+ </function>
+ <function name='xmlThrDefSubstituteEntitiesDefaultValue' file='globals'>
+ <info></info>
+ <return type='int' info=''/>
+ <arg name='v' type='int' info=''/>
+ </function>
+ <function name='xmlThrDefTreeIndentString' file='globals'>
+ <info></info>
+ <return type='const char *' info=''/>
+ <arg name='v' type='const char *' info=''/>
+ </function>
<function name='xmlUCSIsAlphabeticPresentationForms' file='xmlunicode'>
<info>Check whether the character is part of AlphabeticPresentationForms UCS Block</info>
<return type='int' info='1 if true 0 otherwise'/>
diff --git a/global.data b/global.data
index 6b170dd..1a8c8a7 100644
--- a/global.data
+++ b/global.data
@@ -1,24 +1,25 @@
-int,oldXMLWDcompatibility
-xmlBufferAllocationScheme,xmlBufferAllocScheme
-int,xmlDefaultBufferSize
-xmlSAXHandler,xmlDefaultSAXHandler
-xmlSAXLocator,xmlDefaultSAXLocator
-int,xmlDoValidityCheckingDefaultValue
-xmlGenericErrorFunc,xmlGenericError
-void *,xmlGenericErrorContext
-int,xmlGetWarningsDefaultValue
-int,xmlIndentTreeOutput
-const char *,xmlTreeIndentString
-int,xmlKeepBlanksDefaultValue
-int,xmlLineNumbersDefaultValue
-int,xmlLoadExtDtdDefaultValue
-int,xmlParserDebugEntities
-const char *,xmlParserVersion
-int,xmlPedanticParserDefaultValue
-int,xmlSaveNoEmptyTags
-#const xmlChar,xmlStringComment,[]
-#const xmlChar,xmlStringText,[]
-#const xmlChar,xmlStringTextNoenc,[]
-int,xmlSubstituteEntitiesDefaultValue
-xmlRegisterNodeFunc,xmlRegisterNodeDefaultValue
-xmlDeregisterNodeFunc,xmlDeregisterNodeDefaultValue
+#type,name,array?,threadGlobalDefault accessor?
+int,oldXMLWDcompatibility,,
+xmlBufferAllocationScheme,xmlBufferAllocScheme,,1
+int,xmlDefaultBufferSize,,1
+xmlSAXHandler,xmlDefaultSAXHandler,,
+xmlSAXLocator,xmlDefaultSAXLocator,,
+int,xmlDoValidityCheckingDefaultValue,,1
+xmlGenericErrorFunc,xmlGenericError,,
+void *,xmlGenericErrorContext,,
+int,xmlGetWarningsDefaultValue,,1
+int,xmlIndentTreeOutput,,1
+const char *,xmlTreeIndentString,,1
+int,xmlKeepBlanksDefaultValue,,1
+int,xmlLineNumbersDefaultValue,,1
+int,xmlLoadExtDtdDefaultValue,,1
+int,xmlParserDebugEntities,,1
+const char *,xmlParserVersion,,
+int,xmlPedanticParserDefaultValue,,1
+int,xmlSaveNoEmptyTags,,1
+#const xmlChar,xmlStringComment,[],1
+#const xmlChar,xmlStringText,[],1
+#const xmlChar,xmlStringTextNoenc,[],1
+int,xmlSubstituteEntitiesDefaultValue,,1
+xmlRegisterNodeFunc,xmlRegisterNodeDefaultValue,,
+xmlDeregisterNodeFunc,xmlDeregisterNodeDefaultValue,,
diff --git a/globals.c b/globals.c
index 0fc54e2..ee6417b 100644
--- a/globals.c
+++ b/globals.c
@@ -21,6 +21,7 @@
#include <libxml/globals.h>
#include <libxml/xmlmemory.h>
+#include <libxml/threads.h>
/* #define DEBUG_GLOBALS */
@@ -33,6 +34,21 @@
#define IS_MAIN_THREAD 1
#endif
+/*
+ * Mutex to protect "ForNewThreads" variables
+ */
+static xmlMutexPtr xmlThrDefMutex = NULL;
+
+void xmlInitGlobals()
+{
+ xmlThrDefMutex = xmlNewMutex();
+}
+
+void xmlCleanupGlobals()
+{
+ xmlFreeMutex(xmlThrDefMutex);
+}
+
/************************************************************************
* *
* All the user accessible global variables of the library *
@@ -150,12 +166,14 @@
* XML_BUFFER_ALLOC_EXACT
*/
xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
+static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
/**
* xmlDefaultBufferSize:
*
* Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
*/
int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
+static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
/*
* Parser defaults
@@ -175,6 +193,7 @@
* Disabled by default
*/
int xmlParserDebugEntities = 0;
+static int xmlParserDebugEntitiesThrDef = 0;
/**
* xmlDoValidityCheckingDefaultValue:
*
@@ -182,6 +201,7 @@
* Disabled by default.
*/
int xmlDoValidityCheckingDefaultValue = 0;
+static int xmlDoValidityCheckingDefaultValueThrDef = 0;
/**
* xmlGetWarningsDefaultValue:
*
@@ -189,6 +209,7 @@
* Activated by default.
*/
int xmlGetWarningsDefaultValue = 1;
+static int xmlGetWarningsDefaultValueThrDef = 1;
/**
* xmlLoadExtDtdDefaultValue:
*
@@ -197,6 +218,7 @@
* Disabled by default.
*/
int xmlLoadExtDtdDefaultValue = 0;
+static int xmlLoadExtDtdDefaultValueThrDef = 0;
/**
* xmlPedanticParserDefaultValue:
*
@@ -204,6 +226,7 @@
* Disabled by default.
*/
int xmlPedanticParserDefaultValue = 0;
+static int xmlPedanticParserDefaultValueThrDef = 0;
/**
* xmlLineNumbersDefaultValue:
*
@@ -213,6 +236,7 @@
* applicaton.
*/
int xmlLineNumbersDefaultValue = 0;
+static int xmlLineNumbersDefaultValueThrDef = 0;
/**
* xmlKeepBlanksDefaultValue:
*
@@ -223,6 +247,7 @@
* for some applications since this was libxml1 default behaviour.
*/
int xmlKeepBlanksDefaultValue = 1;
+static int xmlKeepBlanksDefaultValueThrDef = 1;
/**
* xmlSubstituteEntitiesDefaultValue:
*
@@ -233,9 +258,12 @@
* engine does not handle entities references transparently.
*/
int xmlSubstituteEntitiesDefaultValue = 0;
+static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
+static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
+static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
/*
* Error handling
@@ -252,12 +280,14 @@
* Global setting: function used for generic error callbacks
*/
xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
+static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
/**
* xmlGenericErrorContext:
*
* Global setting passed to generic error callbacks
*/
void *xmlGenericErrorContext = NULL;
+static void *xmlGenericErrorContextThrDef = NULL;
/*
* output defaults
@@ -269,6 +299,7 @@
* Enabled by default
*/
int xmlIndentTreeOutput = 1;
+static int xmlIndentTreeOutputThrDef = 1;
/**
* xmlTreeIndentString:
@@ -276,6 +307,7 @@
* The string used to do one-level indent. By default is equal to " " (two spaces)
*/
const char *xmlTreeIndentString = " ";
+static const char *xmlTreeIndentStringThrDef = " ";
/**
* xmlSaveNoEmptyTags:
@@ -286,6 +318,7 @@
* Disabled by default
*/
int xmlSaveNoEmptyTags = 0;
+int xmlSaveNoEmptyTagsThrDef = 0;
/**
* xmlDefaultSAXHandler:
@@ -427,6 +460,7 @@
/*
* Perform initialization as required by libxml
*/
+ xmlMutexLock(xmlThrDefMutex);
#ifdef LIBXML_DOCB_ENABLED
initdocbDefaultSAXHandler(&gs->docbDefaultSAXHandler);
@@ -434,17 +468,17 @@
#ifdef LIBXML_HTML_ENABLED
inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
#endif
- initGenericErrorDefaultFunc(&gs->xmlGenericError);
gs->oldXMLWDcompatibility = 0;
- gs->xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
- gs->xmlDefaultBufferSize = BASE_BUFFER_SIZE;
+ gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
+ gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
gs->xmlDefaultSAXLocator.getPublicId = getPublicId;
gs->xmlDefaultSAXLocator.getSystemId = getSystemId;
gs->xmlDefaultSAXLocator.getLineNumber = getLineNumber;
gs->xmlDefaultSAXLocator.getColumnNumber = getColumnNumber;
- gs->xmlDoValidityCheckingDefaultValue = 0;
+ gs->xmlDoValidityCheckingDefaultValue =
+ xmlDoValidityCheckingDefaultValueThrDef;
#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
gs->xmlFree = (xmlFreeFunc) xmlMemFree;
gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
@@ -458,21 +492,36 @@
gs->xmlRealloc = (xmlReallocFunc) realloc;
gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
#endif
- gs->xmlGenericErrorContext = NULL;
- gs->xmlGetWarningsDefaultValue = 1;
- gs->xmlIndentTreeOutput = 1;
- gs->xmlTreeIndentString = " ";
- gs->xmlKeepBlanksDefaultValue = 1;
- gs->xmlLineNumbersDefaultValue = 0;
- gs->xmlLoadExtDtdDefaultValue = 0;
- gs->xmlParserDebugEntities = 0;
+ gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
+ gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
+ gs->xmlTreeIndentString = xmlTreeIndentStringThrDef;
+ gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
+ gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
+ gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
+ gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
gs->xmlParserVersion = LIBXML_VERSION_STRING;
- gs->xmlPedanticParserDefaultValue = 0;
- gs->xmlSaveNoEmptyTags = 0;
- gs->xmlSubstituteEntitiesDefaultValue = 0;
+ gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
+ gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
+ gs->xmlSubstituteEntitiesDefaultValue =
+ xmlSubstituteEntitiesDefaultValueThrDef;
- gs->xmlRegisterNodeDefaultValue = NULL;
- gs->xmlDeregisterNodeDefaultValue = NULL;
+ gs->xmlGenericError = xmlGenericErrorThrDef;
+ gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef;
+ gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
+ gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
+
+ xmlMutexUnlock(xmlThrDefMutex);
+}
+
+void
+xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
+ xmlMutexLock(xmlThrDefMutex);
+ xmlGenericErrorContextThrDef = ctx;
+ if (handler != NULL)
+ xmlGenericErrorThrDef = handler;
+ else
+ xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
+ xmlMutexUnlock(xmlThrDefMutex);
}
/**
@@ -493,6 +542,21 @@
return(old);
}
+xmlRegisterNodeFunc
+xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
+{
+ xmlRegisterNodeFunc old;
+
+ xmlMutexLock(xmlThrDefMutex);
+ old = xmlRegisterNodeDefaultValueThrDef;
+
+ __xmlRegisterCallbacks = 1;
+ xmlRegisterNodeDefaultValueThrDef = func;
+ xmlMutexUnlock(xmlThrDefMutex);
+
+ return(old);
+}
+
/**
* xmlDeregisterNodeDefault:
* @func: function pointer to the new DeregisterNodeFunc
@@ -511,6 +575,21 @@
return(old);
}
+xmlDeregisterNodeFunc
+xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+{
+ xmlDeregisterNodeFunc old;
+
+ xmlMutexLock(xmlThrDefMutex);
+ old = xmlDeregisterNodeDefaultValueThrDef;
+
+ __xmlRegisterCallbacks = 1;
+ xmlDeregisterNodeDefaultValueThrDef = func;
+ xmlMutexUnlock(xmlThrDefMutex);
+
+ return(old);
+}
+
#ifdef LIBXML_DOCB_ENABLED
#undef docbDefaultSAXHandler
@@ -558,6 +637,14 @@
else
return (&xmlGetGlobalState()->xmlBufferAllocScheme);
}
+xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
+ xmlBufferAllocationScheme ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlBufferAllocSchemeThrDef;
+ xmlBufferAllocSchemeThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlDefaultBufferSize
int *
@@ -567,6 +654,14 @@
else
return (&xmlGetGlobalState()->xmlDefaultBufferSize);
}
+int xmlThrDefDefaultBufferSize(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlDefaultBufferSizeThrDef;
+ xmlDefaultBufferSizeThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlDefaultSAXHandler
xmlSAXHandler *
@@ -594,6 +689,14 @@
else
return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue);
}
+int xmlThrDefDoValidityCheckingDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlDoValidityCheckingDefaultValueThrDef;
+ xmlDoValidityCheckingDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlGenericError
xmlGenericErrorFunc *
@@ -621,6 +724,14 @@
else
return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue);
}
+int xmlThrDefGetWarningsDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlGetWarningsDefaultValueThrDef;
+ xmlGetWarningsDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlIndentTreeOutput
int *
@@ -630,6 +741,14 @@
else
return (&xmlGetGlobalState()->xmlIndentTreeOutput);
}
+int xmlThrDefIndentTreeOutput(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlIndentTreeOutputThrDef;
+ xmlIndentTreeOutputThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlTreeIndentString
const char * *
@@ -639,6 +758,14 @@
else
return (&xmlGetGlobalState()->xmlTreeIndentString);
}
+const char * xmlThrDefTreeIndentString(const char * v) {
+ const char * ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlTreeIndentStringThrDef;
+ xmlTreeIndentStringThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlKeepBlanksDefaultValue
int *
@@ -648,6 +775,14 @@
else
return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue);
}
+int xmlThrDefKeepBlanksDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlKeepBlanksDefaultValueThrDef;
+ xmlKeepBlanksDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlLineNumbersDefaultValue
int *
@@ -657,6 +792,14 @@
else
return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue);
}
+int xmlThrDefLineNumbersDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlLineNumbersDefaultValueThrDef;
+ xmlLineNumbersDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlLoadExtDtdDefaultValue
int *
@@ -666,6 +809,14 @@
else
return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue);
}
+int xmlThrDefLoadExtDtdDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlLoadExtDtdDefaultValueThrDef;
+ xmlLoadExtDtdDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlParserDebugEntities
int *
@@ -675,6 +826,14 @@
else
return (&xmlGetGlobalState()->xmlParserDebugEntities);
}
+int xmlThrDefParserDebugEntities(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlParserDebugEntitiesThrDef;
+ xmlParserDebugEntitiesThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlParserVersion
const char * *
@@ -693,6 +852,14 @@
else
return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue);
}
+int xmlThrDefPedanticParserDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlPedanticParserDefaultValueThrDef;
+ xmlPedanticParserDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlSaveNoEmptyTags
int *
@@ -702,6 +869,14 @@
else
return (&xmlGetGlobalState()->xmlSaveNoEmptyTags);
}
+int xmlThrDefSaveNoEmptyTags(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlSaveNoEmptyTagsThrDef;
+ xmlSaveNoEmptyTagsThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlSubstituteEntitiesDefaultValue
int *
@@ -711,6 +886,14 @@
else
return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue);
}
+int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
+ int ret;
+ xmlMutexLock(xmlThrDefMutex);
+ ret = xmlSubstituteEntitiesDefaultValueThrDef;
+ xmlSubstituteEntitiesDefaultValueThrDef = v;
+ xmlMutexUnlock(xmlThrDefMutex);
+ return ret;
+}
#undef xmlRegisterNodeDefaultValue
xmlRegisterNodeFunc *
diff --git a/include/libxml/globals.h b/include/libxml/globals.h
index 9a7e3d1..3a832f6 100644
--- a/include/libxml/globals.h
+++ b/include/libxml/globals.h
@@ -22,6 +22,9 @@
extern "C" {
#endif
+void xmlInitGlobals(void);
+void xmlCleanupGlobals(void);
+
/*
* Externally global symbols which need to be protected for backwards
* compatibility support.
@@ -112,8 +115,12 @@
void xmlInitializeGlobalState(xmlGlobalStatePtr gs);
+void xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler);
+
xmlRegisterNodeFunc xmlRegisterNodeDefault(xmlRegisterNodeFunc func);
+xmlRegisterNodeFunc xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func);
xmlDeregisterNodeFunc xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func);
+xmlDeregisterNodeFunc xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func);
/*
* In general the memory allocation entry points are not kept
@@ -217,6 +224,7 @@
#else
LIBXML_DLL_IMPORT extern xmlBufferAllocationScheme xmlBufferAllocScheme;
#endif
+xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v);
extern int *__xmlDefaultBufferSize(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -225,6 +233,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlDefaultBufferSize;
#endif
+int xmlThrDefDefaultBufferSize(int v);
extern xmlSAXHandler *__xmlDefaultSAXHandler(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -249,6 +258,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlDoValidityCheckingDefaultValue;
#endif
+int xmlThrDefDoValidityCheckingDefaultValue(int v);
extern xmlGenericErrorFunc *__xmlGenericError(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -273,6 +283,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlGetWarningsDefaultValue;
#endif
+int xmlThrDefGetWarningsDefaultValue(int v);
extern int *__xmlIndentTreeOutput(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -281,6 +292,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlIndentTreeOutput;
#endif
+int xmlThrDefIndentTreeOutput(int v);
extern const char * *__xmlTreeIndentString(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -289,6 +301,7 @@
#else
LIBXML_DLL_IMPORT extern const char * xmlTreeIndentString;
#endif
+const char * xmlThrDefTreeIndentString(const char * v);
extern int *__xmlKeepBlanksDefaultValue(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -297,6 +310,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlKeepBlanksDefaultValue;
#endif
+int xmlThrDefKeepBlanksDefaultValue(int v);
extern int *__xmlLineNumbersDefaultValue(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -305,6 +319,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlLineNumbersDefaultValue;
#endif
+int xmlThrDefLineNumbersDefaultValue(int v);
extern int *__xmlLoadExtDtdDefaultValue(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -313,6 +328,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlLoadExtDtdDefaultValue;
#endif
+int xmlThrDefLoadExtDtdDefaultValue(int v);
extern int *__xmlParserDebugEntities(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -321,6 +337,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlParserDebugEntities;
#endif
+int xmlThrDefParserDebugEntities(int v);
extern const char * *__xmlParserVersion(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -337,6 +354,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlPedanticParserDefaultValue;
#endif
+int xmlThrDefPedanticParserDefaultValue(int v);
extern int *__xmlSaveNoEmptyTags(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -345,6 +363,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlSaveNoEmptyTags;
#endif
+int xmlThrDefSaveNoEmptyTags(int v);
extern int *__xmlSubstituteEntitiesDefaultValue(void);
#ifdef LIBXML_THREAD_ENABLED
@@ -353,6 +372,7 @@
#else
LIBXML_DLL_IMPORT extern int xmlSubstituteEntitiesDefaultValue;
#endif
+int xmlThrDefSubstituteEntitiesDefaultValue(int v);
extern xmlRegisterNodeFunc *__xmlRegisterNodeDefaultValue(void);
#ifdef LIBXML_THREAD_ENABLED
diff --git a/parser.c b/parser.c
index faeda8d..40ffd20 100644
--- a/parser.c
+++ b/parser.c
@@ -11140,6 +11140,7 @@
if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
(xmlGenericError == NULL))
initGenericErrorDefaultFunc(NULL);
+ xmlInitGlobals();
xmlInitThreads();
xmlInitMemory();
xmlInitCharEncodingHandlers();
@@ -11176,5 +11177,6 @@
xmlCatalogCleanup();
#endif
xmlCleanupThreads();
+ xmlCleanupGlobals();
xmlParserInitialized = 0;
}
diff --git a/python/libxml.c b/python/libxml.c
index a943530..e372835 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -1267,6 +1267,7 @@
printf("libxml_xmlErrorInitialize() called\n");
#endif
xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
+ xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
}
PyObject *
@@ -1767,7 +1768,7 @@
printf("libxml_xpathCallbacksInitialized called\n");
#endif
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < libxml_xpathCallbacksMax; i++) {
libxml_xpathCallbacks[i].ctx = NULL;
libxml_xpathCallbacks[i].name = NULL;
libxml_xpathCallbacks[i].ns_uri = NULL;
@@ -2620,6 +2621,8 @@
if (initialized != 0)
return;
+ /* XXX xmlInitParser does much more than this */
+ xmlInitGlobals();
xmlRegisterDefaultOutputCallbacks();
xmlRegisterDefaultInputCallbacks();
m = Py_InitModule((char *) "libxml2mod", libxmlMethods);
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index e4587f8..b33c873 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -63,6 +63,22 @@
initializePredefinedEntities()
predefinedEntity()
+# functions from module globals
+cleanupGlobals()
+initGlobals()
+thrDefDefaultBufferSize()
+thrDefDoValidityCheckingDefaultValue()
+thrDefGetWarningsDefaultValue()
+thrDefIndentTreeOutput()
+thrDefKeepBlanksDefaultValue()
+thrDefLineNumbersDefaultValue()
+thrDefLoadExtDtdDefaultValue()
+thrDefParserDebugEntities()
+thrDefPedanticParserDefaultValue()
+thrDefSaveNoEmptyTags()
+thrDefSubstituteEntitiesDefaultValue()
+thrDefTreeIndentString()
+
# functions from module nanoftp
nanoFTPCleanup()
nanoFTPInit()
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index 0c16acf..d4e91dd 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -28,7 +28,8 @@
reader6.py \
ctxterror.py\
readererr.py\
- relaxng.py
+ relaxng.py \
+ thread2.py
XMLS= \
tst.xml \
diff --git a/python/tests/reader2.py b/python/tests/reader2.py
index f8ca254..afc3586 100755
--- a/python/tests/reader2.py
+++ b/python/tests/reader2.py
@@ -14,10 +14,10 @@
err=""
expect="""../../test/valid/rss.xml:172: validity error: Element rss does not carry attribute version
</rss>
- ^
+ ^
../../test/valid/xlink.xml:450: validity error: ID dt-arc already defined
<p><termdef id="dt-arc" term="Arc">An <ter
- ^
+ ^
../../test/valid/xlink.xml:530: validity error: attribute def line 199 references an unknown ID "dt-xlg"
^
diff --git a/python/tests/thread2.py b/python/tests/thread2.py
new file mode 100755
index 0000000..c8ac5ed
--- /dev/null
+++ b/python/tests/thread2.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python -u
+import string, sys, time
+import thread
+from threading import Thread, Lock
+
+import libxml2
+
+THREADS_COUNT = 15
+
+failed = 0
+
+class ErrorHandler:
+
+ def __init__(self):
+ self.errors = []
+ self.lock = Lock()
+
+ def handler(self,ctx,str):
+ self.lock.acquire()
+ self.errors.append(str)
+ self.lock.release()
+
+def getLineNumbersDefault():
+ old = libxml2.lineNumbersDefault(0)
+ libxml2.lineNumbersDefault(old)
+ return old
+
+def test(expectedLineNumbersDefault):
+ time.sleep(1)
+ global failed
+ # check a per thread-global
+ if expectedLineNumbersDefault != getLineNumbersDefault():
+ failed = 1
+ print "FAILED to obtain correct value for " \
+ "lineNumbersDefault in thread %d" % thread.get_ident()
+ # check ther global error handler
+ # (which is NOT per-thread in the python bindings)
+ try:
+ doc = libxml2.parseFile("bad.xml")
+ except:
+ pass
+ else:
+ assert "failed"
+
+# global error handler
+eh = ErrorHandler()
+libxml2.registerErrorHandler(eh.handler,"")
+
+# set on the main thread only
+libxml2.lineNumbersDefault(1)
+test(1)
+ec = len(eh.errors)
+if ec == 0:
+ print "FAILED: should have obtained errors"
+ sys.exit(1)
+
+ts = []
+for i in range(THREADS_COUNT):
+ # expect 0 for lineNumbersDefault because
+ # the new value has been set on the main thread only
+ ts.append(Thread(target=test,args=(0,)))
+for t in ts:
+ t.start()
+for t in ts:
+ t.join()
+
+if len(eh.errors) != ec+THREADS_COUNT*ec:
+ print "FAILED: did not obtain the correct number of errors"
+ sys.exit(1)
+
+# set lineNumbersDefault for future new threads
+libxml2.thrDefLineNumbersDefaultValue(1)
+ts = []
+for i in range(THREADS_COUNT):
+ # expect 1 for lineNumbersDefault
+ ts.append(Thread(target=test,args=(1,)))
+for t in ts:
+ t.start()
+for t in ts:
+ t.join()
+
+if len(eh.errors) != ec+THREADS_COUNT*ec*2:
+ print "FAILED: did not obtain the correct number of errors"
+ sys.exit(1)
+
+if failed:
+ print "FAILED"
+ sys.exit(1)
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+ print "OK"
+else:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()