[xslt] [PATCH] xslt extensions as modules, take 2
- From: Joel Reed <joelwreed comcast net>
- To: xslt gnome org
- Subject: [xslt] [PATCH] xslt extensions as modules, take 2
- Date: Sun, 2 Jan 2005 17:40:37 -0500
Patch Changes
--------------------------------------------------
1) we getenv("LIBXSLT_PLUGINS_PATH") to find out where plugins
should be loaded from.
2) libexslt is no longer a bunch of plugins to maintain binary
abi
3) the modules are actually closed on cleanup instead of being
left in the process address space
Implementation Notes
--------------------------------------------------
On a plugin enabled libxslt, when a function, top-level, or element
can't be found in the appropriate standard hashes, we attempt
to find a plugin like this:
Given an extension URI like "http://exslt.org/regular-expressions"
we take the last slash delimited string ("regular-expressions"),
and try to load it. The filename will look like:
a) sprintf("%s/%s", getenv("LIBXSLT_PLUGINS_PATH"), "regular-expressions")
or on *nix, if LIBXSLT_PLUGINS_PATH=NULL
b) sprintf("%s/%s", LIBXSLT_DEFAULT_PLUGINS_PATH(), "regular-expressions")
where LIBXSLT_DEFAULT_PLUGINS_PATH() = "/usr/local/lib/libxslt/1.1/"
for example.
Only open question i have is should plugin support default to on or off?
jr
? libxslt/cscope.out
? python/tests/foo
? tests/exslt/regexp
? tests/exslt/date/.memdump
? tests/keys/.memdump
Index: configure.in
===================================================================
RCS file: /cvs/gnome/libxslt/configure.in,v
retrieving revision 1.163
diff -w -u -r1.163 configure.in
--- configure.in 29 Oct 2004 15:07:14 -0000 1.163
+++ configure.in 2 Jan 2005 22:23:44 -0000
@@ -435,6 +435,35 @@
AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
+AC_ARG_WITH(plugins,
+[ --with-plugins Add plugin extension support (off)])
+if test "$with_plugins" = ""
+then
+ with_plugins=no
+fi
+
+if test "$with_plugins" = "yes" ; then
+ AC_MSG_CHECKING([libxml2 module support])
+ WITH_MODULES="`$XML_CONFIG --modules`"
+ if test "${WITH_MODULES}" = "1"; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+else
+ WITH_MODULES="0"
+fi
+
+AC_SUBST(WITH_MODULES)
+
+dnl
+dnl setup default module path
+dnl
+module_prefix=$prefix
+test "x$module_prefix" = xNONE && module_prefix=$ac_default_prefix
+LIBXSLT_DEFAULT_PLUGINS_PATH="\"$module_prefix/lib/libxslt/$LIBXSLT_MAJOR_VERSION.$LIBXSLT_MINOR_VERSION/\""
+AC_SUBST(LIBXSLT_DEFAULT_PLUGINS_PATH)
+
dnl
dnl In build tree I use a static version with memory debug enabled
dnl
@@ -502,7 +531,6 @@
$LN_S Copyright COPYING
)
-
AC_OUTPUT([
Makefile
libxslt.pc
Index: libxslt/extensions.c
===================================================================
RCS file: /cvs/gnome/libxslt/libxslt/extensions.c,v
retrieving revision 1.35
diff -w -u -r1.35 extensions.c
--- libxslt/extensions.c 1 Dec 2004 14:44:56 -0000 1.35
+++ libxslt/extensions.c 2 Jan 2005 22:23:45 -0000
@@ -13,6 +13,7 @@
#include "libxslt.h"
#include <string.h>
+#include <limits.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
@@ -20,12 +21,20 @@
#include <libxml/xmlerror.h>
#include <libxml/parserInternals.h>
#include <libxml/xpathInternals.h>
+#include <libxml/xmlmodule.h>
+#include <libxml/list.h>
+#include <libxml/xmlIO.h>
#include "xslt.h"
#include "xsltInternals.h"
#include "xsltutils.h"
#include "imports.h"
#include "extensions.h"
+#ifdef _WIN32
+#include <stdlib.h> /* for _MAX_PATH */
+#define PATH_MAX _MAX_PATH
+#endif
+
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_EXTENSIONS
#endif
@@ -72,6 +81,7 @@
static xmlHashTablePtr xsltFunctionsHash = NULL;
static xmlHashTablePtr xsltElementsHash = NULL;
static xmlHashTablePtr xsltTopLevelsHash = NULL;
+static xmlHashTablePtr xsltModuleHash = NULL;
/************************************************************************
* *
@@ -269,6 +279,80 @@
}
+/**
+ * xsltExtModuleRegisterDynamic:
+ * @URI: the function or element namespace URI
+ *
+ * Looks up an extension module to dynamically load
+ * based on the namespace URI
+ *
+ * Returns 0 if successful, -1 in case of error.
+ */
+
+#ifdef WITH_MODULES
+typedef void (*exsltRegisterFunction) (void);
+
+int
+static xsltExtModuleRegisterDynamic (const xmlChar *URI) {
+
+ xmlModulePtr m;
+ exsltRegisterFunction regfunc;
+ xmlChar module_filename[PATH_MAX];
+ const xmlChar *extNameBegin = NULL;
+ const xmlChar *extDirectory = NULL;
+ int i, seen_before;
+
+ /* check for bad inputs */
+ if (URI == NULL)
+ return(-1);
+
+ if (NULL == xsltModuleHash) {
+ xsltModuleHash = xmlHashCreate(5);
+ if (xsltModuleHash == NULL)
+ return(-1);
+ }
+
+ /* have we attempted to register this module already? */
+ seen_before = (int)xmlHashLookup(xsltModuleHash, URI);
+ if (0 != seen_before) {
+ return(-1);
+ }
+
+ for (i = xmlStrlen(URI); i != 0 && extNameBegin == NULL; --i)
+ {
+ if (URI[i-1] == '/') extNameBegin = URI + i;
+ }
+
+ if (extNameBegin == NULL || *extNameBegin == '\0')
+ return(-1);
+
+ /* determine module directory */
+ extDirectory = getenv("LIBXSLT_PLUGINS_PATH");
+ if (NULL == extDirectory)
+ extDirectory = LIBXSLT_DEFAULT_PLUGINS_PATH();
+ if (NULL == extDirectory)
+ return(-1);
+
+ /* build the module filename and open it*/
+ xmlStrPrintf(module_filename, sizeof(module_filename), "%s%s", extDirectory, extNameBegin);
+ m = xmlModuleOpen(module_filename);
+ if (NULL == m)
+ return(-1);
+
+ regfunc = (exsltRegisterFunction) xmlModuleSymbol(m, "exsltRegisterModule");
+ if (NULL != regfunc) {
+ (*regfunc)();
+ }
+
+ /* register this module in our hash */
+ xmlHashAddEntry(xsltModuleHash, URI, (void*)m);
+
+ return (NULL == regfunc)? -1 : 0;
+}
+#else
+#define xsltExtModuleRegisterDynamic(b) -1
+#endif
+
/************************************************************************
* *
* The stylesheet extension prefixes handling *
@@ -330,10 +414,17 @@
xsltExtModulePtr module;
module = xmlHashLookup(xsltExtensionsHash, URI);
+ if (NULL == module) {
+ if (!xsltExtModuleRegisterDynamic(URI)) {
+ module = xmlHashLookup(xsltExtensionsHash, URI);
+ }
+ }
+
if (module != NULL) {
xsltStyleGetExtData(style, URI);
}
}
+
return(0);
}
@@ -959,6 +1050,14 @@
return(NULL);
XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI);
+
+ /* if lookup fails, attempt a dynamic load on supported platforms */
+ if (NULL == ret) {
+ if (!xsltExtModuleRegisterDynamic(URI)) {
+ XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI);
+ }
+ }
+
return ret;
}
@@ -1160,6 +1259,14 @@
ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
+ /* if function lookup fails, attempt a dynamic load on supported platforms */
+ ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
+ if (NULL == ext) {
+ if (!xsltExtModuleRegisterDynamic(URI)) {
+ ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
+ }
+ }
+
if (ext == NULL)
return(NULL);
return(ext->transform);
@@ -1184,6 +1291,12 @@
ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
+ if (ext == NULL) {
+ if (!xsltExtModuleRegisterDynamic(URI)) {
+ ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
+ }
+ }
+
if (ext == NULL)
return(NULL);
return(ext->precomp);
@@ -1262,6 +1375,14 @@
return(NULL);
XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
+
+ /* if lookup fails, attempt a dynamic load on supported platforms */
+ if (NULL == ret) {
+ if (!xsltExtModuleRegisterDynamic(URI)) {
+ XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
+ }
+ }
+
return(ret);
}
@@ -1599,6 +1720,12 @@
xsltExtElementTest);
}
+static void
+xsltHashScannerModuleFree(void * payload, void * data, xmlChar * name)
+{
+ xmlModuleClose(payload);
+}
+
/**
* xsltCleanupGlobals:
*
@@ -1611,6 +1738,14 @@
xsltUnregisterAllExtModuleFunction();
xsltUnregisterAllExtModuleElement();
xsltUnregisterAllExtModuleTopLevel();
+
+ /* cleanup dynamic module hash */
+ if (NULL != xsltModuleHash)
+ {
+ xmlHashScan(xsltModuleHash, xsltHashScannerModuleFree, 0);
+ xmlHashFree(xsltModuleHash, NULL);
+ xsltModuleHash = NULL;
+ }
}
static void
Index: libxslt/xsltconfig.h.in
===================================================================
RCS file: /cvs/gnome/libxslt/libxslt/xsltconfig.h.in,v
retrieving revision 1.22
diff -w -u -r1.22 xsltconfig.h.in
--- libxslt/xsltconfig.h.in 18 Aug 2004 21:27:08 -0000 1.22
+++ libxslt/xsltconfig.h.in 2 Jan 2005 22:23:48 -0000
@@ -107,6 +107,19 @@
#endif
/**
+ * WITH_MODULES:
+ *
+ * Whether module support is configured into libxslt
+ * Note: no default module path for win32 platforms
+ */
+#if @WITH_MODULES@
+#ifndef WITH_MODULES
+#define WITH_MODULES
+#endif
+#define LIBXSLT_DEFAULT_PLUGINS_PATH() @LIBXSLT_DEFAULT_PLUGINS_PATH@
+#endif
+
+/**
* ATTRIBUTE_UNUSED:
*
* This macro is used to flag unused function parameters to GCC
Index: libxslt/xsltwin32config.h
===================================================================
RCS file: /cvs/gnome/libxslt/libxslt/xsltwin32config.h,v
retrieving revision 1.71
diff -w -u -r1.71 xsltwin32config.h
--- libxslt/xsltwin32config.h 23 Dec 2004 08:08:11 -0000 1.71
+++ libxslt/xsltwin32config.h 2 Jan 2005 22:23:48 -0000
@@ -57,6 +57,18 @@
#define WITH_XSLT_DEBUG
#endif
+/**
+ * WITH_MODULES:
+ *
+ * Whether module support is configured into libxslt
+ */
+#if 1
+#ifndef WITH_MODULES
+#define WITH_MODULES
+#endif
+#define LIBXSLT_PLUGINS_PATH() getenv("LIBXSLT_PLUGINS_PATH")
+#endif
+
#if 0
/**
* DEBUG_MEMORY:
Index: libxslt/xsltwin32config.h.in
===================================================================
RCS file: /cvs/gnome/libxslt/libxslt/xsltwin32config.h.in,v
retrieving revision 1.7
diff -w -u -r1.7 xsltwin32config.h.in
--- libxslt/xsltwin32config.h.in 18 Aug 2004 21:27:08 -0000 1.7
+++ libxslt/xsltwin32config.h.in 2 Jan 2005 22:23:48 -0000
@@ -57,6 +57,18 @@
#define WITH_XSLT_DEBUG
#endif
+/**
+ * WITH_MODULES:
+ *
+ * Whether module support is configured into libxslt
+ */
+#if @WITH_MODULES@
+#ifndef WITH_MODULES
+#define WITH_MODULES
+#endif
+#define LIBXSLT_PLUGINS_PATH() getenv("LIBXSLT_PLUGINS_PATH")
+#endif
+
#if 0
/**
* DEBUG_MEMORY:
Index: win32/configure.js
===================================================================
RCS file: /cvs/gnome/libxslt/win32/configure.js,v
retrieving revision 1.15
diff -w -u -r1.15 configure.js
--- win32/configure.js 24 Aug 2004 14:43:44 -0000 1.15
+++ win32/configure.js 2 Jan 2005 22:23:52 -0000
@@ -48,6 +48,7 @@
var withIconv = true;
var withZlib = false;
var withCrypto = true;
+var withModules = false;
/* Win32 build options. */
var dirSep = "\\";
var compiler = "msvc";
@@ -105,6 +106,7 @@
txt += " iconv: Use iconv library (" + (withIconv? "yes" : "no") + ")\n";
txt += " zlib: Use zlib library (" + (withZlib? "yes" : "no") + ")\n";
txt += " crypto: Enable Crypto support (" + (withCrypto? "yes" : "no") + ")\n";
+ txt += " modules: Enable Module support (" + (withModules? "yes" : "no") + ")\n";
txt += "\nWin32 build options, default value given in parentheses:\n\n";
txt += " compiler: Compiler to be used [msvc|mingw] (" + compiler + ")\n";
txt += " cruntime: C-runtime compiler option (only msvc) (" + cruntime + ")\n";
@@ -188,6 +190,7 @@
vf.WriteLine("WITH_ICONV=" + (withIconv? "1" : "0"));
vf.WriteLine("WITH_ZLIB=" + (withZlib? "1" : "0"));
vf.WriteLine("WITH_CRYPTO=" + (withCrypto? "1" : "0"));
+ vf.WriteLine("WITH_MODULES=" + (withModules? "1" : "0"));
vf.WriteLine("DEBUG=" + (buildDebug? "1" : "0"));
vf.WriteLine("STATIC=" + (buildStatic? "1" : "0"));
vf.WriteLine("PREFIX=" + buildPrefix);
@@ -233,6 +236,10 @@
of.WriteLine(s.replace(/\ WITH_MEM_DEBUG\@/, withMemDebug? "1" : "0"));
} else if (s.search(/\ WITH_DEBUGGER\@/) != -1) {
of.WriteLine(s.replace(/\ WITH_DEBUGGER\@/, withDebugger? "1" : "0"));
+ } else if (s.search(/\ WITH_MODULES\@/) != -1) {
+ of.WriteLine(s.replace(/\ WITH_MODULES\@/, withModules? "1" : "0"));
+ } else if (s.search(/\ LIBXSLT_DEFAULT_PLUGINS_PATH\@/) != -1) {
+ of.WriteLine(s.replace(/\ LIBXSLT_DEFAULT_PLUGINS_PATH\@/, "NULL"));
} else
of.WriteLine(ln);
}
@@ -262,6 +269,8 @@
of.WriteLine(s.replace(/\ LIBEXSLT_VERSION_EXTRA\@/, verCvs));
} else if (s.search(/\ WITH_CRYPTO\@/) != -1) {
of.WriteLine(s.replace(/\ WITH_CRYPTO\@/, withCrypto? "1" : "0"));
+ } else if (s.search(/\ WITH_MODULES\@/) != -1) {
+ of.WriteLine(s.replace(/\ WITH_MODULES\@/, withModules? "1" : "0"));
} else
of.WriteLine(ln);
}
@@ -332,6 +341,8 @@
withZlib = strToBool(arg.substring(opt.length + 1, arg.length));
else if (opt == "crypto")
withCrypto = strToBool(arg.substring(opt.length + 1, arg.length));
+ else if (opt == "modules")
+ withModules = strToBool(arg.substring(opt.length + 1, arg.length));
else if (opt == "compiler")
compiler = arg.substring(opt.length + 1, arg.length);
else if (opt == "cruntime")
@@ -446,6 +457,7 @@
txtOut += " Use iconv: " + boolToStr(withIconv) + "\n";
txtOut += " With zlib: " + boolToStr(withZlib) + "\n";
txtOut += " Crypto: " + boolToStr(withCrypto) + "\n";
+txtOut += " Modules: " + boolToStr(withModules) + "\n";
txtOut += "\n";
txtOut += "Win32 build configuration\n";
txtOut += "-------------------------\n";
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]