applied DSO support patch 2 from Joel Reed Daniel

* Makefile.am config.h.in configure.in error.c libxml-2.0.pc.in
  testModule.c testdso.c xml2-config.in xmllint.c xmlmodule.c
  include/libxml/Makefile.am include/libxml/xmlerror.h
  include/libxml/xmlmodule.h include/libxml/xmlversion.h.in
  include/libxml/xmlwin32version.h.in: applied DSO support
  patch 2 from Joel Reed
Daniel
diff --git a/ChangeLog b/ChangeLog
index 09d9eeb..31bffed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Jan  4 16:07:52 CET 2005 Daniel Veillard <daniel@veillard.com>
+
+	* Makefile.am config.h.in configure.in error.c libxml-2.0.pc.in
+	  testModule.c testdso.c xml2-config.in xmllint.c xmlmodule.c
+	  include/libxml/Makefile.am include/libxml/xmlerror.h
+	  include/libxml/xmlmodule.h include/libxml/xmlversion.h.in 
+	  include/libxml/xmlwin32version.h.in: applied DSO support
+	  patch 2 from Joel Reed
+
 Tue Jan  4 15:30:15 CET 2005 Daniel Veillard <daniel@veillard.com>
 
 	* configure.in: applied patch from Marcin Konicki for BeOS
diff --git a/Makefile.am b/Makefile.am
index 08a052e..c58563a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@
 
 noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \
                 testThreads testC14N testAutomata testRegexp \
-		testReader testapi
+                testReader testapi testModule
 
 bin_PROGRAMS = xmllint xmlcatalog
 
@@ -17,7 +17,7 @@
 lib_LTLIBRARIES = libxml2.la
 libxml2_la_LIBADD = @THREAD_LIBS@ @Z_LIBS@ $(ICONV_LIBS) @M_LIBS@ @WIN32_EXTRA_LIBADD@
 
-libxml2_la_LDFLAGS = @CYGWIN_EXTRA_LDFLAGS@ @WIN32_EXTRA_LDFLAGS@ -version-info @LIBXML_VERSION_INFO@
+libxml2_la_LDFLAGS = @CYGWIN_EXTRA_LDFLAGS@ @WIN32_EXTRA_LDFLAGS@ -version-info @LIBXML_VERSION_INFO@ @MODULE_PLATFORM_LIBS@
 
 if WITH_TRIO_SOURCES
 libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c  \
@@ -27,7 +27,7 @@
 		catalog.c globals.c threads.c c14n.c xmlstring.c \
 		xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \
 		triostr.c trio.c xmlreader.c relaxng.c dict.c SAX2.c \
-		xmlwriter.c legacy.c chvalid.c pattern.c xmlsave.c
+		xmlwriter.c legacy.c chvalid.c pattern.c xmlsave.c xmlmodule.c
 else
 libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c  \
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
@@ -36,7 +36,8 @@
 		catalog.c globals.c threads.c c14n.c xmlstring.c \
 		xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \
 		xmlreader.c relaxng.c dict.c SAX2.c \
-		xmlwriter.c legacy.c chvalid.c pattern.c xmlsave.c
+		xmlwriter.c legacy.c chvalid.c pattern.c xmlsave.c \
+		xmlmodule.c
 endif
 
 DEPS = $(top_builddir)/libxml2.la
@@ -113,6 +114,15 @@
 testReader_DEPENDENCIES = $(DEPS)
 testReader_LDADD= $(LDADDS)
 
+testModule_SOURCES=testModule.c
+testModule_LDFLAGS = 
+testModule_DEPENDENCIES = $(DEPS)
+testModule_LDADD= $(LDADDS)
+
+noinst_LTLIBRARIES = testdso.la
+testdso_la_SOURCES = testdso.c
+testdso_la_LDFLAGS = -module -rpath $(libdir)
+
 testapi.c: gentest.py doc/libxml2-api.xml
 	-@(if [ "$(PYTHON)" != "" ] ; then \
 	    $(PYTHON) $(srcdir)/gentest.py $(srcdir) ; fi )
@@ -131,7 +141,7 @@
 
 testall : tests SVGtests SAXtests
 
-tests: XMLtests XMLenttests NStests IDtests Errtests APItests @READER_TEST@ @TEST_SAX@ @TEST_PUSH@ @TEST_HTML@ @TEST_PHTML@  @TEST_VALID@ URItests @TEST_XPATH@ @TEST_XPTR@ @TEST_XINCLUDE@ @TEST_C14N@ @TEST_DEBUG@ @TEST_CATALOG@ @TEST_REGEXPS@ @TEST_SCHEMAS@ @TEST_THREADS@ Timingtests @TEST_VTIME@ @PYTHON_TESTS@
+tests: XMLtests XMLenttests NStests IDtests Errtests APItests @READER_TEST@ @TEST_SAX@ @TEST_PUSH@ @TEST_HTML@ @TEST_PHTML@  @TEST_VALID@ URItests @TEST_XPATH@ @TEST_XPTR@ @TEST_XINCLUDE@ @TEST_C14N@ @TEST_DEBUG@ @TEST_CATALOG@ @TEST_REGEXPS@ @TEST_SCHEMAS@ @TEST_THREADS@ Timingtests @TEST_VTIME@ @PYTHON_TESTS@ @TEST_MODULES@
 	@(if [ "@PYTHON_SUBDIR@" != "" ] ; then cd python ; \
 	    $(MAKE) MAKEFLAGS+=--silent tests ; fi)
 	@(cd doc/examples ; $(MAKE) MAKEFLAGS+=--silent tests)
@@ -985,6 +995,10 @@
 	  fi)
 	@(if [ -x $(PYTHON) -a -d xstc ] ; then cd xstc ; $(MAKE) CHECKER="$(CHECKER)" MAKEFLAGS+=--silent pytests ; fi)
 
+ModuleTests: testModule$(EXEEXT) testdso.la
+	@echo "## Module tests"
+	@(./testModule$(EXEEXT))
+
 cleanup:
 	-@(find . -name .\#\* -exec rm {} \;)
 
diff --git a/config.h.in b/config.h.in
index ad774b1..a7b6eeb 100644
--- a/config.h.in
+++ b/config.h.in
@@ -40,6 +40,9 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* Have dlopen based dso */
+#undef HAVE_DLOPEN
+
 /* Define to 1 if you have the <errno.h> header file. */
 #undef HAVE_ERRNO_H
 
@@ -94,6 +97,9 @@
 /* Define to 1 if you have the `inet' library (-linet). */
 #undef HAVE_LIBINET
 
+/* Define to 1 if you have the `net' library (-lnet). */
+#undef HAVE_LIBNET
+
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 #undef HAVE_LIBNSL
 
@@ -145,6 +151,9 @@
 /* Define to 1 if you have the <resolv.h> header file. */
 #undef HAVE_RESOLV_H
 
+/* Have shl_load based dso */
+#undef HAVE_SHLLOAD
+
 /* Define to 1 if you have the `signal' function. */
 #undef HAVE_SIGNAL
 
@@ -258,7 +267,7 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Define if compiler has function prototypes */
+/* Define to 1 if the C compiler supports function prototypes. */
 #undef PROTOTYPES
 
 /* Determine what socket length (socklen_t) data type is */
@@ -276,6 +285,9 @@
 /* Using the Win32 Socket implementation */
 #undef _WINSOCKAPI_
 
+/* Define like PROTOTYPES; this can be used by system headers. */
+#undef __PROTOTYPES
+
 /* Win32 Std C name mangling work-around */
 #undef snprintf
 
diff --git a/configure.in b/configure.in
index 9235e34..7d475aa 100644
--- a/configure.in
+++ b/configure.in
@@ -628,6 +628,32 @@
 AC_SUBST(pythondir)
 AC_SUBST(PYTHON_SUBDIR)
 
+dnl check for dso support
+WITH_MODULES=0
+MODULE_EXTENSION=".so"
+TEST_MODULES=
+
+AC_CHECK_LIB(dld, shl_load, [
+  WITH_MODULES=1
+  MODULE_PLATFORM_LIBS="-ldld"
+  AC_DEFINE([HAVE_SHLLOAD], [], [Have shl_load based dso])
+])
+
+AC_CHECK_LIB(dl, dlopen, [
+  WITH_MODULES=1
+  MODULE_PLATFORM_LIBS="-ldl"
+  AC_DEFINE([HAVE_DLOPEN], [], [Have dlopen based dso])
+])
+
+if test "${WITH_MODULES}" = "1"; then
+  TEST_MODULES="ModuleTests"
+fi  
+
+AC_SUBST(WITH_MODULES)
+AC_SUBST(MODULE_PLATFORM_LIBS)
+AC_SUBST(MODULE_EXTENSION)
+AC_SUBST(TEST_MODULES)
+
 dnl
 dnl Tester makes use of readline if present
 dnl
diff --git a/error.c b/error.c
index 9b8ddc4..b4fed92 100644
--- a/error.c
+++ b/error.c
@@ -330,6 +330,9 @@
         case XML_FROM_REGEXP:
             channel(data, "regexp ");
             break;
+        case XML_FROM_MODULE:
+            channel(data, "module ");
+            break;
         case XML_FROM_SCHEMASV:
             channel(data, "Schemas validity ");
             break;
diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am
index 70bf5f3..03f9564 100644
--- a/include/libxml/Makefile.am
+++ b/include/libxml/Makefile.am
@@ -34,6 +34,7 @@
 		c14n.h \
 		xmlautomata.h \
 		xmlregexp.h \
+		xmlmodule.h \
 		xmlschemas.h \
 		schemasInternals.h \
 		xmlschemastypes.h \
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index 29fe748..dd75f23 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -59,7 +59,8 @@
     XML_FROM_XSLT,	/* The XSLT engine from libxslt */
     XML_FROM_VALID,	/* The XML DTD validation with valid context */
     XML_FROM_CHECK,	/* The error checking module */
-    XML_FROM_WRITER	/* The xmlwriter module */
+    XML_FROM_WRITER,	/* The xmlwriter module */
+    XML_FROM_MODULE	/* The dynamically loaded module module*/
 } xmlErrorDomain;
 
 /**
@@ -746,6 +747,8 @@
     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */
     XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */
     XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */
+    XML_MODULE_OPEN = 4900, /* 4900 */
+    XML_MODULE_CLOSE, /* 4901 */
     XML_CHECK_FOUND_ELEMENT = 5000,
     XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */
     XML_CHECK_FOUND_TEXT, /* 5002 */
diff --git a/include/libxml/xmlmodule.h b/include/libxml/xmlmodule.h
new file mode 100644
index 0000000..8360ffb
--- /dev/null
+++ b/include/libxml/xmlmodule.h
@@ -0,0 +1,52 @@
+/*
+ * Summary: dynamic module loading
+ * Description: basic API for dynamic module loading, used by
+ *              libexslt
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Joel W. Reed
+ */
+
+#ifndef __XML_MODULE_H__
+#define __XML_MODULE_H__
+
+#include <libxml/xmlversion.h>
+
+#ifdef LIBXML_MODULES_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * xmlModulePtr:
+ *
+ * A handle to a dynamically loaded module
+ */
+typedef struct _xmlModule xmlModule;
+typedef xmlModule *xmlModulePtr;
+
+#ifdef __cplusplus
+}
+#endif 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XMLPUBFUN xmlModulePtr XMLCALL xmlModuleOpen	(const char *filename);
+
+XMLPUBFUN void* XMLCALL xmlModuleSymbol	(xmlModulePtr module, const char* name);
+
+XMLPUBFUN int XMLCALL xmlModuleClose	(xmlModulePtr module);
+
+XMLPUBFUN int XMLCALL xmlModuleFree	(xmlModulePtr module);
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif /* LIBXML_MODULES_ENABLED */
+
+#endif /*__XML_MODULE_H__ */
diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in
index cf06429..47a28b9 100644
--- a/include/libxml/xmlversion.h.in
+++ b/include/libxml/xmlversion.h.in
@@ -340,6 +340,16 @@
 #endif
 
 /**
+ * LIBXML_MODULES_ENABLED:
+ *
+ * Whether the module interfaces are compiled in
+ */
+#if @WITH_MODULES@
+#define LIBXML_MODULES_ENABLED
+#define LIBXML_MODULE_EXTENSION "@MODULE_EXTENSION@" 
+#endif
+
+/**
  * ATTRIBUTE_UNUSED:
  *
  * Macro used to signal to GCC unused function parameters
diff --git a/include/libxml/xmlwin32version.h.in b/include/libxml/xmlwin32version.h.in
index 8d740f5..dcbe5cb 100644
--- a/include/libxml/xmlwin32version.h.in
+++ b/include/libxml/xmlwin32version.h.in
@@ -261,6 +261,18 @@
 #endif
 #endif
 
+/*
+ * #pragma comment(lib, "kernel32.lib")
+ *
+ * pragma understood my MS compiler which enables a conditional link with
+ * kernel32.
+ */
+#ifdef _MSC_VER
+#if defined LIBXML_MODULES_ENABLED
+#pragma comment(lib, "kernel32.lib")
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/libxml-2.0.pc.in b/libxml-2.0.pc.in
index 5b54895..51a04ed 100644
--- a/libxml-2.0.pc.in
+++ b/libxml-2.0.pc.in
@@ -2,7 +2,7 @@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 includedir=@includedir@
-
+modules=@WITH_MODULES@
 
 Name: libXML
 Version: @VERSION@
diff --git a/testModule.c b/testModule.c
new file mode 100644
index 0000000..e5e9bd6
--- /dev/null
+++ b/testModule.c
@@ -0,0 +1,60 @@
+/*
+ * testModule.c : a small tester program for xmlModule
+ *
+ * See Copyright for the status of this software.
+ *
+ * joelwreed@comcast.net
+ */
+
+#include "libxml.h"
+#ifdef LIBXML_MODULES_ENABLED
+#include <libxml/xmlversion.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlmodule.h>
+
+#ifdef _WIN32
+#define MODULE_PATH "."
+#include <stdlib.h> /* for _MAX_PATH */
+#define PATH_MAX _MAX_PATH
+#else
+#define MODULE_PATH ".libs"
+#endif
+
+typedef int (*hello_world_t)();
+ 
+int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    xmlChar filename[PATH_MAX];
+    xmlModulePtr module = NULL;
+    hello_world_t hello_world = NULL;
+
+    /* build the module filename, and confirm the module exists */
+    xmlStrPrintf(filename, sizeof(filename), "%s/testdso%s", (const xmlChar*)MODULE_PATH, (const xmlChar*)LIBXML_MODULE_EXTENSION);
+
+    module = xmlModuleOpen((const char*)filename);
+    if (module)
+      {
+        hello_world = (hello_world_t)xmlModuleSymbol(module, "hello_world");
+        (*hello_world)();
+
+        xmlModuleClose(module);
+      }
+
+    xmlMemoryDump();
+
+    return(0);
+}
+
+#else
+#include <stdio.h>
+int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+    printf("%s : Module support not compiled in\n", argv[0]);
+    return(0);
+}
+#endif /* LIBXML_SCHEMAS_ENABLED */
diff --git a/testdso.c b/testdso.c
new file mode 100644
index 0000000..6c4652f
--- /dev/null
+++ b/testdso.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#define IN_LIBXML
+#include "libxml/xmlexports.h"
+
+XMLPUBFUN int hello_world()
+{
+  printf("Success!\n");
+  return 0;
+}
diff --git a/win32/Makefile.bcb b/win32/Makefile.bcb
index 9b949cc..2f32d94 100644
--- a/win32/Makefile.bcb
+++ b/win32/Makefile.bcb
@@ -95,6 +95,9 @@
 !if "$(WITH_THREADS)" == "posix"
 LIBS = $(LIBS) pthreadVC.lib
 !endif
+!if "$(WITH_MODULES)" == "1"
+LIBS = $(LIBS) kernel32.lib
+!endif
 
 # The archiver and its options.
 AR = tlib.exe
@@ -143,6 +146,7 @@
 	$(XML_INTDIR)\xmlmemory.obj\
 	$(XML_INTDIR)\xmlreader.obj\
 	$(XML_INTDIR)\xmlregexp.obj\
+	$(XML_INTDIR)\xmlmodule.obj\
 	$(XML_INTDIR)\xmlsave.obj\
 	$(XML_INTDIR)\xmlschemas.obj\
 	$(XML_INTDIR)\xmlschemastypes.obj\
@@ -186,6 +190,7 @@
 	$(XML_INTDIR_A)\xmlmemory.obj\
 	$(XML_INTDIR_A)\xmlreader.obj\
 	$(XML_INTDIR_A)\xmlregexp.obj\
+	$(XML_INTDIR_A)\xmlmodule.obj\
 	$(XML_INTDIR_A)\xmlsave.obj\
 	$(XML_INTDIR_A)\xmlschemas.obj\
 	$(XML_INTDIR_A)\xmlschemastypes.obj\
@@ -205,6 +210,7 @@
 	$(BINDIR)\testReader.exe\
 	$(BINDIR)\testRelax.exe\
 	$(BINDIR)\testRegexp.exe\
+	$(BINDIR)\testModule.exe\
 	$(BINDIR)\testSAX.exe\
 	$(BINDIR)\testSchemas.exe\
 	$(BINDIR)\testURI.exe\
diff --git a/win32/Makefile.mingw b/win32/Makefile.mingw
index 415620c..a96c228 100644
--- a/win32/Makefile.mingw
+++ b/win32/Makefile.mingw
@@ -84,6 +84,9 @@
 ifeq ($(WITH_THREADS),posix)
 LIBS += -lpthreadGC
 endif
+ifeq ($(WITH_MODULES),1)
+LIBS += -lkernel32
+endif
 
 # The archiver and its options.
 AR = ar.exe
@@ -133,6 +136,7 @@
 	$(XML_INTDIR)/xmlmemory.o\
 	$(XML_INTDIR)/xmlreader.o\
 	$(XML_INTDIR)/xmlregexp.o\
+	$(XML_INTDIR)\xmlmodule.o\
 	$(XML_INTDIR)/xmlsave.o\
 	$(XML_INTDIR)/xmlschemas.o\
 	$(XML_INTDIR)/xmlschemastypes.o\
@@ -178,6 +182,7 @@
 	$(XML_INTDIR_A)/xmlmemory.o\
 	$(XML_INTDIR_A)/xmlreader.o\
 	$(XML_INTDIR_A)/xmlregexp.o\
+	$(XML_INTDIR_A)\xmlmodule.o\
 	$(XML_INTDIR_A)/xmlsave.o\
 	$(XML_INTDIR_A)/xmlschemas.o\
 	$(XML_INTDIR_A)/xmlschemastypes.o\
@@ -198,6 +203,7 @@
 	$(BINDIR)/testHTML.exe\
 	$(BINDIR)/testReader.exe\
 	$(BINDIR)/testRegexp.exe\
+	$(BINDIR)/testModule.exe\
 	$(BINDIR)/testRelax.exe\
 	$(BINDIR)/testSAX.exe\
 	$(BINDIR)/testSchemas.exe\
diff --git a/win32/Makefile.msvc b/win32/Makefile.msvc
index 3ad0dad..be10cf9 100644
--- a/win32/Makefile.msvc
+++ b/win32/Makefile.msvc
@@ -74,6 +74,9 @@
 !if "$(WITH_THREADS)" == "posix"
 LIBS = $(LIBS) pthreadVC.lib
 !endif
+!if "$(WITH_MODULES)" == "1"
+LIBS = $(LIBS) kernel32.lib
+!endif
 
 # The archiver and its options.
 AR = lib.exe
@@ -122,6 +125,7 @@
 	$(XML_INTDIR)\xmlmemory.obj\
 	$(XML_INTDIR)\xmlreader.obj\
 	$(XML_INTDIR)\xmlregexp.obj\
+	$(XML_INTDIR)\xmlmodule.obj\
 	$(XML_INTDIR)\xmlsave.obj\
 	$(XML_INTDIR)\xmlschemas.obj\
 	$(XML_INTDIR)\xmlschemastypes.obj\
@@ -165,6 +169,7 @@
 	$(XML_INTDIR_A)\xmlmemory.obj\
 	$(XML_INTDIR_A)\xmlreader.obj\
 	$(XML_INTDIR_A)\xmlregexp.obj\
+	$(XML_INTDIR_A)\xmlmodule.obj\
 	$(XML_INTDIR_A)\xmlsave.obj\
 	$(XML_INTDIR_A)\xmlschemas.obj\
 	$(XML_INTDIR_A)\xmlschemastypes.obj\
@@ -184,6 +189,7 @@
 	$(BINDIR)\testReader.exe\
 	$(BINDIR)\testRelax.exe\
 	$(BINDIR)\testRegexp.exe\
+	$(BINDIR)\testModule.exe\
 	$(BINDIR)\testSAX.exe\
 	$(BINDIR)\testSchemas.exe\
 	$(BINDIR)\testURI.exe\
diff --git a/win32/configure.js b/win32/configure.js
index f77308d..12e5f42 100644
--- a/win32/configure.js
+++ b/win32/configure.js
@@ -46,6 +46,7 @@
 var withMemDebug = false;
 var withSchemas = true;
 var withRegExps = true;
+var withModules = true;
 var withTree = true;
 var withReader = true;
 var withWriter = true;
@@ -125,6 +126,7 @@
 	txt += "  xml_debug:  Enable XML debbugging module (" + (withDebug? "yes" : "no")  + ")\n";
 	txt += "  mem_debug:  Enable memory debugger (" + (withMemDebug? "yes" : "no")  + ")\n";
 	txt += "  regexps:    Enable regular expressions (" + (withRegExps? "yes" : "no") + ")\n";
+	txt += "  modules:    Enable module support (" + (withModules? "yes" : "no") + ")\n";
 	txt += "  tree:       Enable tree api (" + (withTree? "yes" : "no") + ")\n";
 	txt += "  reader:     Enable xmlReader api (" + (withReader? "yes" : "no") + ")\n";
 	txt += "  writer:     Enable xmlWriter api (" + (withWriter? "yes" : "no") + ")\n";
@@ -230,6 +232,7 @@
 	vf.WriteLine("WITH_MEM_DEBUG=" + (withMemDebug? "1" : "0"));
 	vf.WriteLine("WITH_SCHEMAS=" + (withSchemas? "1" : "0"));
 	vf.WriteLine("WITH_REGEXPS=" + (withRegExps? "1" : "0"));
+	vf.WriteLine("WITH_MODULES=" + (withModules? "1" : "0"));
 	vf.WriteLine("WITH_TREE=" + (withTree? "1" : "0"));
 	vf.WriteLine("WITH_READER=" + (withReader? "1" : "0"));
 	vf.WriteLine("WITH_WRITER=" + (withWriter? "1" : "0"));
@@ -318,6 +321,10 @@
 			of.WriteLine(s.replace(/\@WITH_SCHEMAS\@/, withSchemas? "1" : "0"));
 		} else if (s.search(/\@WITH_REGEXPS\@/) != -1) {
 			of.WriteLine(s.replace(/\@WITH_REGEXPS\@/, withRegExps? "1" : "0"));
+		} else if (s.search(/\@WITH_MODULES\@/) != -1) {
+			of.WriteLine(s.replace(/\@WITH_MODULES\@/, withModules? "1" : "0"));
+		} else if (s.search(/\@MODULE_EXTENSION\@/) != -1) {
+			of.WriteLine(s.replace(/\@MODULE_EXTENSION\@/, ".dll"));
 		} else if (s.search(/\@WITH_TREE\@/) != -1) {
 			of.WriteLine(s.replace(/\@WITH_TREE\@/, withTree? "1" : "0"));
 		} else if (s.search(/\@WITH_READER\@/) != -1) {
@@ -610,6 +617,7 @@
 txtOut += "  Debugging module: " + boolToStr(withDebug) + "\n";
 txtOut += "  Memory debugging: " + boolToStr(withMemDebug) + "\n";
 txtOut += "    Regexp support: " + boolToStr(withRegExps) + "\n";
+txtOut += "    Module support: " + boolToStr(withModules) + "\n";
 txtOut += "      Tree support: " + boolToStr(withTree) + "\n";
 txtOut += "    Reader support: " + boolToStr(withReader) + "\n";
 txtOut += "    Writer support: " + boolToStr(withWriter) + "\n";
diff --git a/xml2-config.in b/xml2-config.in
index cddd1a8..304df6c 100644
--- a/xml2-config.in
+++ b/xml2-config.in
@@ -17,6 +17,7 @@
   --libs		print library linking information
   --libtool-libs        print linking information for use with libtool
   --cflags		print pre-processor and compiler flags
+  --modules		module support enabled
   --help		display this help and exit
   --version		output version information
 EOF
@@ -74,6 +75,10 @@
 	echo ${libdir}/@XML_LIBTOOLLIBS@
         ;;
 
+    --modules)
+       	echo @WITH_MODULES@
+       	;;
+
     --libs)
         if [ "`uname`" = "Linux" ]
 	then
diff --git a/xmllint.c b/xmllint.c
index 906909f..2f77607 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -1663,6 +1663,9 @@
 #ifdef LIBXML_SCHEMAS_ENABLED
     fprintf(stderr, "Schemas ");
 #endif
+#ifdef LIBXML_MODULES_ENABLED
+    fprintf(stderr, "Modules ");
+#endif
     fprintf(stderr, "\n");
 }
 
diff --git a/xmlmodule.c b/xmlmodule.c
new file mode 100644
index 0000000..e21d49e
--- /dev/null
+++ b/xmlmodule.c
@@ -0,0 +1,383 @@
+/*
+ * xmlmodule.c :
+ *
+ * See Copyright for the status of this software.
+ *
+ * joelwreed@comcast.net
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlmodule.h>
+#include <libxml/globals.h>
+
+#ifdef LIBXML_MODULES_ENABLED
+
+struct _xmlModule {
+  unsigned char* name;
+  void* handle;
+};
+
+static void* xmlModulePlatformOpen(const char* name);
+static int xmlModulePlatformClose(void* handle);
+static void* xmlModulePlatformSymbol(void* handle, const char* name);
+
+/************************************************************************
+ *									*
+ * 		module memory error handler				*
+ *									*
+ ************************************************************************/
+/**
+ * xmlModuleErrMemory:
+ * @extra:  extra information
+ *
+ * Handle an out of memory condition
+ */
+static void
+xmlModuleErrMemory(xmlModulePtr module, const char *extra)
+{
+    const char *name = NULL;
+    if (module != NULL) {
+      name = (const char *) module->name;
+    }
+
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
+                    name, NULL, 0, 0,
+                    "Memory allocation failed : %s\n", extra);
+}
+
+xmlModulePtr xmlModuleOpen(const char* name)
+{
+  xmlModulePtr module;
+
+  module = (xmlModulePtr) xmlMalloc(sizeof(xmlModule));
+  if (module == NULL) {
+    xmlModuleErrMemory(NULL, "creating module");
+    return(NULL);
+  }
+
+  memset(module, 0, sizeof(xmlModule));
+
+  module->handle = xmlModulePlatformOpen(name);
+
+  if (module->handle == NULL) {
+    xmlFree(module);
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    name, NULL, 0, 0,
+                    "failed to open %s\n", name);
+    return 0;
+  }
+
+  module->name = xmlStrdup((const xmlChar*)name);
+  return (module);
+}
+
+void* xmlModuleSymbol(xmlModulePtr module, const char* name)
+{
+  void* symbol;
+
+  if (NULL == module) {
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    NULL, NULL, 0, 0,
+                    "null module pointer\n", 0);
+     return 0;
+ }
+
+  symbol = xmlModulePlatformSymbol(module->handle, name);
+
+  if (symbol == 0) {
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    symbol, NULL, 0, 0,
+                    "failed to find symbol: %s\n", 0);
+    return 0;
+  }
+
+  return (symbol);
+}
+
+int xmlModuleClose(xmlModulePtr module)
+{
+  int rc;
+
+  if (NULL == module) {
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    NULL, NULL, 0, 0,
+                    "null module pointer\n", 0);
+    return -1;
+  }
+
+  rc = xmlModulePlatformClose(module->handle);
+
+  if (rc != 0) {
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    (const char*)module->name, NULL, 0, 0,
+                    "failed to close: %s\n", 0);
+    return -2;
+  }
+
+  rc = xmlModuleFree(module);
+  return (rc);
+}
+
+int xmlModuleFree(xmlModulePtr module)
+{
+  if (NULL == module) {
+    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_MODULE,
+                    XML_MODULE_OPEN, XML_ERR_FATAL, NULL, 0, 0,
+                    NULL, NULL, 0, 0,
+                    "null module pointer\n", 0);
+    return -1;
+  }
+
+  xmlFree(module->name);
+  xmlFree(module);
+
+  return (0);
+}
+
+#ifdef HAVE_DLOPEN
+
+#include <dlfcn.h>
+
+/*
+ * xmlModulePlatformOpen:
+ * returns a handle on success, and zero on error.
+ */ 
+
+static void* xmlModulePlatformOpen(const char* name)
+{
+  void* handle;
+  handle = dlopen(name, RTLD_GLOBAL|RTLD_NOW);
+  return (handle);
+}
+
+/*
+ * xmlModulePlatformClose:
+ * returns 0 on success, and non-zero on error.
+ */ 
+
+static int xmlModulePlatformClose(void* handle)
+{
+  int rc;
+  rc = dlclose(handle);
+  return (rc);
+}
+
+/*
+ * xmlModulePlatformSymbol:
+ * returns loaded symbol on success, and zero on error.
+ */ 
+
+static void* xmlModulePlatformSymbol(void* handle, const char* name)
+{
+  void* sym;
+  sym = dlsym(handle, name);
+  return (sym);
+}
+
+#endif /* HAVE_DLOPEN */
+
+#ifdef HAVE_SHLLOAD /* HAVE_SHLLOAD */
+
+/*
+ * xmlModulePlatformOpen:
+ * returns a handle on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformOpen(const char* name)
+{
+  void* handle;
+  handle = shl_load(name, BIND_IMMEDIATE, 0L);
+  return (handle);
+}
+
+/*
+ * xmlModulePlatformClose:
+ * returns 0 on success, and non-zero on error.
+ */ 
+
+int xmlModulePlatformClose(void* handle)
+{
+  int rc;
+  rc = shl_unload(handle);
+  return (rc);
+}
+
+/*
+ * xmlModulePlatformSymbol:
+ * returns loaded symbol on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformSymbol(void* handle, const char* name)
+{
+  void* sym;
+  int rc; 
+  
+  errno = 0;
+  rc = shl_findsym(handle, name, TYPE_PROCEDURE, &sym); 
+  if (-1 == rc && 0 == errno) {
+    rc = shl_findsym(handle, sym, TYPE_DATA, &sym); 
+  }
+  return (sym);
+}
+
+#endif /* HAVE_SHLLOAD */
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+/*
+ * xmlModulePlatformOpen:
+ * returns a handle on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformOpen(const char* name)
+{
+  void* handle;
+  handle = LoadLibrary(name);
+  return (handle);
+}
+
+/*
+ * xmlModulePlatformClose:
+ * returns 0 on success, and non-zero on error.
+ */ 
+
+int xmlModulePlatformClose(void* handle)
+{
+  int rc;
+  rc = FreeLibrary(handle);
+  return (0 == rc);
+}
+
+/*
+ * xmlModulePlatformSymbol:
+ * returns loaded symbol on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformSymbol(void* handle, const char* name)
+{
+  void* sym;
+  sym = GetProcAddress(handle, name);
+  return (sym);
+}
+
+#endif /* _WIN32 */
+
+#ifdef HAVE_BEOS
+
+#include <kernel/image.h>
+
+/*
+ * xmlModulePlatformOpen:
+ * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
+ * returns a handle on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformOpen(const char* name)
+{
+  void* handle;
+  handle = (void*)load_add_on(name);
+  return (handle);
+}
+
+/*
+ * xmlModulePlatformClose:
+ * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
+ * returns 0 on success, and non-zero on error.
+ */ 
+
+int xmlModulePlatformClose(void* handle)
+{
+  status_t rc;
+  rc = unload_add_on((image_id)handle);
+
+  if (rc == B_OK) return 0;
+  else return -1;
+}
+
+/*
+ * xmlModulePlatformSymbol:
+ * beos api info: http://www.beunited.org/bebook/The%20Kernel%20Kit/Images.html
+ * returns loaded symbol on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformSymbol(void* handle, const char* name)
+{
+  void* sym;
+  status_t rc;
+
+  rc = get_image_symbol((image_id)handle, name, B_SYMBOL_TYPE_ANY, &sym);
+
+  if (rc == B_OK) return sym;
+  else return 0;
+}
+
+#endif /* HAVE_BEOS */
+
+#ifdef HAVE_OS2
+
+#include <os2.h>
+
+/*
+ * xmlModulePlatformOpen:
+ * os2 api info: http://www.edm2.com/os2api/Dos/DosLoadModule.html
+ * returns a handle on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformOpen(const char* name)
+{
+  char errbuf[255];
+  void* handle;
+  int rc;
+
+  rc = DosLoadModule(errbuf, sizeof(errbuf), name, &handle);
+
+  if (rc) return 0;
+  else return (handle);
+}
+
+/*
+ * xmlModulePlatformClose:
+ * os2 api info: http://www.edm2.com/os2api/Dos/DosFreeModule.html
+ * returns 0 on success, and non-zero on error.
+ */ 
+
+int xmlModulePlatformClose(void* handle)
+{
+  int rc;
+  rc = DosFreeModule(handle);
+  return (rc);
+}
+
+/*
+ * xmlModulePlatformSymbol:
+ * os2 api info: http://www.edm2.com/os2api/Dos/DosQueryProcAddr.html
+ * returns loaded symbol on success, and zero on error.
+ */ 
+
+void* xmlModulePlatformSymbol(void* handle, const char* name)
+{
+  void* sym;
+  int rc;
+  rc = DosQueryProcAddr(handle, 0, name, &sym);
+
+  if (rc) return 0;
+  else return (sym);
+}
+
+#endif /* HAVE_OS2 */
+
+#endif /* LIBXML_MODULES_ENABLED */
+