/* * extensions.c: Implemetation of the extensions support * * Reference: * http://www.w3.org/TR/1999/REC-xslt-19991116 * * See Copyright for the status of this software. * * [email protected] */ #define IN_LIBXSLT #include "libxslt.h" #include <stdlib.h> #include <string.h> #include <limits.h> #include <libxml/xmlmemory.h> #include <libxml/tree.h> #include <libxml/hash.h> #include <libxml/xmlerror.h> #include <libxml/parserInternals.h> #include <libxml/xpathInternals.h> #ifdef WITH_MODULES #include <libxml/xmlmodule.h> #endif #include <libxml/list.h> #include <libxml/xmlIO.h> #include <libxml/threads.h> #include "xslt.h" #include "xsltInternals.h" #include "xsltlocale.h" #include "xsltutils.h" #include "imports.h" #include "extensions.h" #ifdef _WIN32 #include <stdlib.h> /* for _MAX_PATH */ #ifndef PATH_MAX #define PATH_MAX … #endif #endif #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_EXTENSIONS #endif /************************************************************************ * * * Private Types and Globals * * * ************************************************************************/ xsltExtDef; xsltExtDefPtr; struct _xsltExtDef { … }; xsltExtModule; xsltExtModulePtr; struct _xsltExtModule { … }; xsltExtData; xsltExtDataPtr; struct _xsltExtData { … }; xsltExtElement; xsltExtElementPtr; struct _xsltExtElement { … }; static xmlHashTablePtr xsltExtensionsHash = …; static xmlHashTablePtr xsltFunctionsHash = …; static xmlHashTablePtr xsltElementsHash = …; static xmlHashTablePtr xsltTopLevelsHash = …; static xmlHashTablePtr xsltModuleHash = …; static xmlMutexPtr xsltExtMutex = …; /************************************************************************ * * * Type functions * * * ************************************************************************/ /** * xsltNewExtDef: * @prefix: the extension prefix * @URI: the namespace URI * * Create a new XSLT ExtDef * * Returns the newly allocated xsltExtDefPtr or NULL in case of error */ static xsltExtDefPtr xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI) { … } /** * xsltFreeExtDef: * @extensiond: an XSLT extension definition * * Free up the memory allocated by @extensiond */ static void xsltFreeExtDef(xsltExtDefPtr extensiond) { … } /** * xsltFreeExtDefList: * @extensiond: an XSLT extension definition list * * Free up the memory allocated by all the elements of @extensiond */ static void xsltFreeExtDefList(xsltExtDefPtr extensiond) { … } /** * xsltNewExtModule: * @initFunc: the module initialization function * @shutdownFunc: the module shutdown function * @styleInitFunc: the stylesheet module data allocator function * @styleShutdownFunc: the stylesheet module data free function * * Create a new XSLT extension module * * Returns the newly allocated xsltExtModulePtr or NULL in case of error */ static xsltExtModulePtr xsltNewExtModule(xsltExtInitFunction initFunc, xsltExtShutdownFunction shutdownFunc, xsltStyleExtInitFunction styleInitFunc, xsltStyleExtShutdownFunction styleShutdownFunc) { … } /** * xsltFreeExtModule: * @ext: an XSLT extension module * * Free up the memory allocated by @ext */ static void xsltFreeExtModule(xsltExtModulePtr ext) { … } static void xsltFreeExtModuleEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { … } /** * xsltNewExtData: * @extModule: the module * @extData: the associated data * * Create a new XSLT extension module data wrapper * * Returns the newly allocated xsltExtDataPtr or NULL in case of error */ static xsltExtDataPtr xsltNewExtData(xsltExtModulePtr extModule, void *extData) { … } /** * xsltFreeExtData: * @ext: an XSLT extension module data wrapper * * Free up the memory allocated by @ext */ static void xsltFreeExtData(xsltExtDataPtr ext) { … } static void xsltFreeExtDataEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { … } /** * xsltNewExtElement: * @precomp: the pre-computation function * @transform: the transformation function * * Create a new XSLT extension element * * Returns the newly allocated xsltExtElementPtr or NULL in case of * error */ static xsltExtElementPtr xsltNewExtElement(xsltPreComputeFunction precomp, xsltTransformFunction transform) { … } /** * xsltFreeExtElement: * @ext: an XSLT extension element * * Frees up the memory allocated by @ext */ static void xsltFreeExtElement(xsltExtElementPtr ext) { … } static void xsltFreeExtElementEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) { … } #ifdef WITH_MODULES typedef void (*exsltRegisterFunction) (void); #ifndef PATH_MAX #define PATH_MAX … #endif /** * xsltExtModuleRegisterDynamic: * @URI: the function or element namespace URI * * Dynamically loads an extension plugin when available. * * The plugin name is derived from the URI by removing the * initial protocol designation, e.g. "http://", then converting * the characters ".", "-", "/", and "\" into "_", the removing * any trailing "/", then concatenating LIBXML_MODULE_EXTENSION. * * Plugins are loaded from the directory specified by the * environment variable LIBXSLT_PLUGINS_PATH, or if NULL, * by LIBXSLT_DEFAULT_PLUGINS_PATH() which is determined at * compile time. * * Returns 0 if successful, -1 in case of error. */ static int xsltExtModuleRegisterDynamic(const xmlChar * URI) { xmlModulePtr m; exsltRegisterFunction regfunc; xmlChar *ext_name; char module_filename[PATH_MAX]; const xmlChar *ext_directory = NULL; const xmlChar *protocol = NULL; xmlChar *i, *regfunc_name; void *vregfunc; int rc; /* check for bad inputs */ if (URI == NULL) return (-1); if (NULL == xsltModuleHash) { xsltModuleHash = xmlHashCreate(5); if (xsltModuleHash == NULL) return (-1); } xmlMutexLock(xsltExtMutex); /* have we attempted to register this module already? */ if (xmlHashLookup(xsltModuleHash, URI) != NULL) { xmlMutexUnlock(xsltExtMutex); return (-1); } xmlMutexUnlock(xsltExtMutex); /* transform extension namespace into a module name */ protocol = xmlStrstr(URI, BAD_CAST "://"); if (protocol == NULL) { ext_name = xmlStrdup(URI); } else { ext_name = xmlStrdup(protocol + 3); } if (ext_name == NULL) { return (-1); } i = ext_name; while ('\0' != *i) { if (('/' == *i) || ('\\' == *i) || ('.' == *i) || ('-' == *i)) *i = '_'; i++; } /* Strip underscores from end of string. */ while (i > ext_name && *(i - 1) == '_') { i--; *i = '\0'; } /* determine module directory */ ext_directory = (xmlChar *) getenv("LIBXSLT_PLUGINS_PATH"); if (NULL == ext_directory) { ext_directory = BAD_CAST LIBXSLT_DEFAULT_PLUGINS_PATH(); if (NULL == ext_directory) return (-1); } #ifdef WITH_XSLT_DEBUG_EXTENSIONS else xsltGenericDebug(xsltGenericDebugContext, "LIBXSLT_PLUGINS_PATH is %s\n", ext_directory); #endif /* build the module filename, and confirm the module exists */ xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename), "%s/%s%s", ext_directory, ext_name, LIBXML_MODULE_EXTENSION); #ifdef WITH_XSLT_DEBUG_EXTENSIONS xsltGenericDebug(xsltGenericDebugContext, "Attempting to load plugin: %s for URI: %s\n", module_filename, URI); #endif #if LIBXML_VERSION < 21300 if (1 != xmlCheckFilename(module_filename)) { #ifdef WITH_XSLT_DEBUG_EXTENSIONS xsltGenericDebug(xsltGenericDebugContext, "xmlCheckFilename failed for plugin: %s\n", module_filename); #endif xmlFree(ext_name); return (-1); } #endif /* attempt to open the module */ m = xmlModuleOpen(module_filename, 0); if (NULL == m) { #ifdef WITH_XSLT_DEBUG_EXTENSIONS xsltGenericDebug(xsltGenericDebugContext, "xmlModuleOpen failed for plugin: %s\n", module_filename); #endif xmlFree(ext_name); return (-1); } /* construct initialization func name */ regfunc_name = xmlStrdup(ext_name); regfunc_name = xmlStrcat(regfunc_name, BAD_CAST "_init"); vregfunc = NULL; rc = xmlModuleSymbol(m, (const char *) regfunc_name, &vregfunc); regfunc = vregfunc; if (0 == rc) { /* * Call the module's init function. Note that this function * calls xsltRegisterExtModuleFull which will add the module * to xsltExtensionsHash (together with it's entry points). */ (*regfunc) (); /* register this module in our hash */ xmlMutexLock(xsltExtMutex); xmlHashAddEntry(xsltModuleHash, URI, (void *) m); xmlMutexUnlock(xsltExtMutex); } else { #ifdef WITH_XSLT_DEBUG_EXTENSIONS xsltGenericDebug(xsltGenericDebugContext, "xmlModuleSymbol failed for plugin: %s, regfunc: %s\n", module_filename, regfunc_name); #endif /* if regfunc not found unload the module immediately */ xmlModuleClose(m); } xmlFree(ext_name); xmlFree(regfunc_name); return (NULL == regfunc) ? -1 : 0; } #else static int xsltExtModuleRegisterDynamic(const xmlChar * URI ATTRIBUTE_UNUSED) { … } #endif /************************************************************************ * * * The stylesheet extension prefixes handling * * * ************************************************************************/ /** * xsltFreeExts: * @style: an XSLT stylesheet * * Free up the memory used by XSLT extensions in a stylesheet */ void xsltFreeExts(xsltStylesheetPtr style) { … } /** * xsltRegisterExtPrefix: * @style: an XSLT stylesheet * @prefix: the prefix used (optional) * @URI: the URI associated to the extension * * Registers an extension namespace * This is called from xslt.c during compile-time. * The given prefix is not needed. * Called by: * xsltParseExtElemPrefixes() (new function) * xsltRegisterExtPrefix() (old function) * * Returns 0 in case of success, 1 if the @URI was already * registered as an extension namespace and * -1 in case of failure */ int xsltRegisterExtPrefix(xsltStylesheetPtr style, const xmlChar * prefix, const xmlChar * URI) { … } /************************************************************************ * * * The extensions modules interfaces * * * ************************************************************************/ /** * xsltRegisterExtFunction: * @ctxt: an XSLT transformation context * @name: the name of the element * @URI: the URI associated to the element * @function: the actual implementation which should be called * * Registers an extension function * * Returns 0 in case of success, -1 in case of failure */ int xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar * name, const xmlChar * URI, xmlXPathFunction function) { … } /** * xsltRegisterExtElement: * @ctxt: an XSLT transformation context * @name: the name of the element * @URI: the URI associated to the element * @function: the actual implementation which should be called * * Registers an extension element * * Returns 0 in case of success, -1 in case of failure */ int xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar * name, const xmlChar * URI, xsltTransformFunction function) { … } /** * xsltFreeCtxtExts: * @ctxt: an XSLT transformation context * * Free the XSLT extension data */ void xsltFreeCtxtExts(xsltTransformContextPtr ctxt) { … } /** * xsltStyleGetStylesheetExtData: * @style: an XSLT stylesheet * @URI: the URI associated to the exension module * * Fires the compile-time initialization callback * of an extension module and returns a container * holding the user-data (retrieved via the callback). * * Returns the create module-data container * or NULL if such a module was not registered. */ static xsltExtDataPtr xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style, const xmlChar * URI) { … } /** * xsltStyleGetExtData: * @style: an XSLT stylesheet * @URI: the URI associated to the exension module * * Retrieve the data associated to the extension module * in this given stylesheet. * Called by: * xsltRegisterExtPrefix(), * ( xsltExtElementPreCompTest(), xsltExtInitTest ) * * Returns the pointer or NULL if not present */ void * xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) { … } #ifdef XSLT_REFACTORED /** * xsltStyleStylesheetLevelGetExtData: * @style: an XSLT stylesheet * @URI: the URI associated to the exension module * * Retrieve the data associated to the extension module in this given * stylesheet. * * Returns the pointer or NULL if not present */ void * xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style, const xmlChar * URI) { xsltExtDataPtr dataContainer = NULL; if ((style == NULL) || (URI == NULL) || (xsltExtensionsHash == NULL)) return (NULL); if (style->extInfos != NULL) { dataContainer = (xsltExtDataPtr) xmlHashLookup(style->extInfos, URI); /* * The module was already initialized in the context * of this stylesheet; just return the user-data that * comes with it. */ if (dataContainer) return(dataContainer->extData); } dataContainer = xsltStyleInitializeStylesheetModule(style, URI); if (dataContainer != NULL) return (dataContainer->extData); return(NULL); } #endif /** * xsltGetExtData: * @ctxt: an XSLT transformation context * @URI: the URI associated to the exension module * * Retrieve the data associated to the extension module in this given * transformation. * * Returns the pointer or NULL if not present */ void * xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI) { … } xsltInitExtCtxt; struct _xsltInitExtCtxt { … }; /** * xsltInitCtxtExt: * @styleData: the registered stylesheet data for the module * @ctxt: the XSLT transformation context + the return value * @URI: the extension URI * * Initializes an extension module */ static void xsltInitCtxtExt(void *payload, void *data, const xmlChar * URI) { … } /** * xsltInitCtxtExts: * @ctxt: an XSLT transformation context * * Initialize the set of modules with registered stylesheet data * * Returns the number of modules initialized or -1 in case of error */ int xsltInitCtxtExts(xsltTransformContextPtr ctxt) { … } /** * xsltShutdownCtxtExt: * @data: the registered data for the module * @ctxt: the XSLT transformation context * @URI: the extension URI * * Shutdown an extension module loaded */ static void xsltShutdownCtxtExt(void *payload, void *vctxt, const xmlChar * URI) { … } /** * xsltShutdownCtxtExts: * @ctxt: an XSLT transformation context * * Shutdown the set of modules loaded */ void xsltShutdownCtxtExts(xsltTransformContextPtr ctxt) { … } /** * xsltShutdownExt: * @data: the registered data for the module * @ctxt: the XSLT stylesheet * @URI: the extension URI * * Shutdown an extension module loaded */ static void xsltShutdownExt(void *payload, void *vctxt, const xmlChar * URI) { … } /** * xsltShutdownExts: * @style: an XSLT stylesheet * * Shutdown the set of modules loaded */ void xsltShutdownExts(xsltStylesheetPtr style) { … } /** * xsltCheckExtPrefix: * @style: the stylesheet * @URI: the namespace prefix (possibly NULL) * * Check if the given prefix is one of the declared extensions. * This is intended to be called only at compile-time. * Called by: * xsltGetInheritedNsList() (xslt.c) * xsltParseTemplateContent (xslt.c) * * Returns 1 if this is an extension, 0 otherwise */ int xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * URI) { … } /** * xsltCheckExtURI: * @style: the stylesheet * @URI: the namespace URI (possibly NULL) * * Check if the given prefix is one of the declared extensions. * This is intended to be called only at compile-time. * Called by: * xsltPrecomputeStylesheet() (xslt.c) * xsltParseTemplateContent (xslt.c) * * Returns 1 if this is an extension, 0 otherwise */ int xsltCheckExtURI(xsltStylesheetPtr style, const xmlChar * URI) { … } /** * xsltRegisterExtModuleFull: * @URI: URI associated to this module * @initFunc: the module initialization function * @shutdownFunc: the module shutdown function * @styleInitFunc: the module initialization function * @styleShutdownFunc: the module shutdown function * * Register an XSLT extension module to the library. * * Returns 0 if sucessful, -1 in case of error */ int xsltRegisterExtModuleFull(const xmlChar * URI, xsltExtInitFunction initFunc, xsltExtShutdownFunction shutdownFunc, xsltStyleExtInitFunction styleInitFunc, xsltStyleExtShutdownFunction styleShutdownFunc) { … } /** * xsltRegisterExtModule: * @URI: URI associated to this module * @initFunc: the module initialization function * @shutdownFunc: the module shutdown function * * Register an XSLT extension module to the library. * * Returns 0 if sucessful, -1 in case of error */ int xsltRegisterExtModule(const xmlChar * URI, xsltExtInitFunction initFunc, xsltExtShutdownFunction shutdownFunc) { … } /** * xsltUnregisterExtModule: * @URI: URI associated to this module * * Unregister an XSLT extension module from the library. * * Returns 0 if sucessful, -1 in case of error */ int xsltUnregisterExtModule(const xmlChar * URI) { … } /** * xsltUnregisterAllExtModules: * * Unregister all the XSLT extension module from the library. */ static void xsltUnregisterAllExtModules(void) { … } /** * xsltXPathGetTransformContext: * @ctxt: an XPath transformation context * * Provides the XSLT transformation context from the XPath transformation * context. This is useful when an XPath function in the extension module * is called by the XPath interpreter and that the XSLT context is needed * for example to retrieve the associated data pertaining to this XSLT * transformation. * * Returns the XSLT transformation context or NULL in case of error. */ xsltTransformContextPtr xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt) { … } /** * xsltRegisterExtModuleFunction: * @name: the function name * @URI: the function namespace URI * @function: the function callback * * Registers an extension module function. * * Returns 0 if successful, -1 in case of error. */ int xsltRegisterExtModuleFunction(const xmlChar * name, const xmlChar * URI, xmlXPathFunction function) { … } /** * xsltExtModuleFunctionLookup: * @name: the function name * @URI: the function namespace URI * * Looks up an extension module function * * Returns the function if found, NULL otherwise. */ xmlXPathFunction xsltExtModuleFunctionLookup(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterExtModuleFunction: * @name: the function name * @URI: the function namespace URI * * Unregisters an extension module function * * Returns 0 if successful, -1 in case of error. */ int xsltUnregisterExtModuleFunction(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterAllExtModuleFunction: * * Unregisters all extension module function */ static void xsltUnregisterAllExtModuleFunction(void) { … } static void xsltFreeElemPreComp(xsltElemPreCompPtr comp) { … } /** * xsltNewElemPreComp: * @style: the XSLT stylesheet * @inst: the element node * @function: the transform function * * Creates and initializes an #xsltElemPreComp * * Returns the new and initialized #xsltElemPreComp */ xsltElemPreCompPtr xsltNewElemPreComp(xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function) { … } /** * xsltInitElemPreComp: * @comp: an #xsltElemPreComp (or generally a derived structure) * @style: the XSLT stylesheet * @inst: the element node * @function: the transform function * @freeFunc: the @comp deallocator * * Initializes an existing #xsltElemPreComp structure. This is usefull * when extending an #xsltElemPreComp to store precomputed data. * This function MUST be called on any extension element precomputed * data struct. */ void xsltInitElemPreComp(xsltElemPreCompPtr comp, xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function, xsltElemPreCompDeallocator freeFunc) { … } /** * xsltPreComputeExtModuleElement: * @style: the stylesheet * @inst: the element node * * Precomputes an extension module element * * Returns the precomputed data */ xsltElemPreCompPtr xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst) { … } /** * xsltRegisterExtModuleElement: * @name: the element name * @URI: the element namespace URI * @precomp: the pre-computation callback * @transform: the transformation callback * * Registers an extension module element. * * Returns 0 if successful, -1 in case of error. */ int xsltRegisterExtModuleElement(const xmlChar * name, const xmlChar * URI, xsltPreComputeFunction precomp, xsltTransformFunction transform) { … } /** * xsltExtElementLookup: * @ctxt: an XSLT process context * @name: the element name * @URI: the element namespace URI * * Looks up an extension element. @ctxt can be NULL to search only in * module elements. * * Returns the element callback or NULL if not found */ xsltTransformFunction xsltExtElementLookup(xsltTransformContextPtr ctxt, const xmlChar * name, const xmlChar * URI) { … } /** * xsltExtModuleElementLookup: * @name: the element name * @URI: the element namespace URI * * Looks up an extension module element * * Returns the callback function if found, NULL otherwise. */ xsltTransformFunction xsltExtModuleElementLookup(const xmlChar * name, const xmlChar * URI) { … } /** * xsltExtModuleElementPreComputeLookup: * @name: the element name * @URI: the element namespace URI * * Looks up an extension module element pre-computation function * * Returns the callback function if found, NULL otherwise. */ xsltPreComputeFunction xsltExtModuleElementPreComputeLookup(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterExtModuleElement: * @name: the element name * @URI: the element namespace URI * * Unregisters an extension module element * * Returns 0 if successful, -1 in case of error. */ int xsltUnregisterExtModuleElement(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterAllExtModuleElement: * * Unregisters all extension module element */ static void xsltUnregisterAllExtModuleElement(void) { … } /** * xsltRegisterExtModuleTopLevel: * @name: the top-level element name * @URI: the top-level element namespace URI * @function: the top-level element callback * * Registers an extension module top-level element. * * Returns 0 if successful, -1 in case of error. */ int xsltRegisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI, xsltTopLevelFunction function) { … } /** * xsltExtModuleTopLevelLookup: * @name: the top-level element name * @URI: the top-level element namespace URI * * Looks up an extension module top-level element * * Returns the callback function if found, NULL otherwise. */ xsltTopLevelFunction xsltExtModuleTopLevelLookup(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterExtModuleTopLevel: * @name: the top-level element name * @URI: the top-level element namespace URI * * Unregisters an extension module top-level element * * Returns 0 if successful, -1 in case of error. */ int xsltUnregisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI) { … } /** * xsltUnregisterAllExtModuleTopLevel: * * Unregisters all extension module function */ static void xsltUnregisterAllExtModuleTopLevel(void) { … } /** * xsltGetExtInfo: * @style: pointer to a stylesheet * @URI: the namespace URI desired * * looks up URI in extInfos of the stylesheet * * returns a pointer to the hash table if found, else NULL */ xmlHashTablePtr xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI) { … } /************************************************************************ * * * Test of the extension module API * * * ************************************************************************/ static xmlChar *testData = …; static xmlChar *testStyleData = …; /** * xsltExtFunctionTest: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * function libxslt:test() for testing the extensions support. */ static void xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs ATTRIBUTE_UNUSED) { … } /** * xsltExtElementPreCompTest: * @style: the stylesheet * @inst: the instruction in the stylesheet * * Process a libxslt:test node */ static xsltElemPreCompPtr xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function) { … } /** * xsltExtElementTest: * @ctxt: an XSLT processing context * @node: The current node * @inst: the instruction in the stylesheet * @comp: precomputed information * * Process a libxslt:test node */ static void xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) { … } /** * xsltExtInitTest: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension * * A function called at initialization time of an XSLT extension module * * Returns a pointer to the module specific data for this transformation */ static void * xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) { … } /** * xsltExtShutdownTest: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension * @data: the data associated to this module * * A function called at shutdown time of an XSLT extension module */ static void xsltExtShutdownTest(xsltTransformContextPtr ctxt, const xmlChar * URI, void *data) { … } /** * xsltExtStyleInitTest: * @style: an XSLT stylesheet * @URI: the namespace URI for the extension * * A function called at initialization time of an XSLT extension module * * Returns a pointer to the module specific data for this transformation */ static void * xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, const xmlChar * URI) { … } /** * xsltExtStyleShutdownTest: * @style: an XSLT stylesheet * @URI: the namespace URI for the extension * @data: the data associated to this module * * A function called at shutdown time of an XSLT extension module */ static void xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, const xmlChar * URI, void *data) { … } /** * xsltRegisterTestModule: * * Registers the test module */ void xsltRegisterTestModule(void) { … } static void xsltHashScannerModuleFree(void *payload ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED, const xmlChar *name ATTRIBUTE_UNUSED) { … } /** * xsltInitGlobals: * * Initialize the global variables for extensions */ void xsltInitGlobals(void) { … } /** * xsltCleanupGlobals: * * Unregister all global variables set up by the XSLT library */ void xsltCleanupGlobals(void) { … } static void xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED, void *data, const xmlChar * name, const xmlChar * URI, const xmlChar * not_used ATTRIBUTE_UNUSED) { … } static void xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED, void *data, const xmlChar * URI, const xmlChar * not_used ATTRIBUTE_UNUSED, const xmlChar * not_used2 ATTRIBUTE_UNUSED) { … } /** * xsltDebugDumpExtensions: * @output: the FILE * for the output, if NULL stdout is used * * Dumps a list of the registered XSLT extension functions and elements */ void xsltDebugDumpExtensions(FILE * output) { … }