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&apos;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()