# HG changeset patch # User Daniel Veillard <veillard@src.gnome.org> # Date 1042496914 0 # Mon Jan 13 22:28:34 2003 +0000 # Node ID aff45361f72a4dffe1b94e6aaf409f92daca482b # Parent f15da7b56debabf12178452578d2ec346d55e437 fixing bug #101602 for extension modules init and shutdown callbacks, * libxslt/extensions.c libxslt/transform.c: fixing bug #101602 for extension modules init and shutdown callbacks, check that they are now called when needed. * python/libxsl.py python/libxslt-python-api.xml python/libxslt.c: started adding the extension module support at the Python level. Still a strange bug to hunt down left. Daniel diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Mon Jan 13 23:25:59 CET 2003 Daniel Veillard <daniel@veillard.com> + + * libxslt/extensions.c libxslt/transform.c: fixing bug #101602 + for extension modules init and shutdown callbacks, check that + they are now called when needed. + * python/libxsl.py python/libxslt-python-api.xml python/libxslt.c: + started adding the extension module support at the Python level. + Still a strange bug to hunt down left. + Sun Jan 12 23:56:18 CET 2003 Daniel Veillard <daniel@veillard.com> * libxslt/attributes.c libxslt/xsltInternals.h libxslt/imports.c diff --git a/libxslt/extensions.c b/libxslt/extensions.c --- a/libxslt/extensions.c +++ b/libxslt/extensions.c @@ -306,6 +306,10 @@ if ((style == NULL) || (prefix == NULL) | (URI == NULL)) return(-1); +#ifdef WITH_XSLT_DEBUG_EXTENSIONS + xsltGenericDebug(xsltGenericDebugContext, + "Registering extension prefix %s : %s\n", prefix, URI); +#endif def = (xsltExtDefPtr) style->nsDefs; while (def != NULL) { if (xmlStrEqual(prefix, def->prefix)) @@ -317,6 +321,21 @@ return(-1); ret->next = (xsltExtDefPtr) style->nsDefs; style->nsDefs = ret; + + /* + * check wether there is an extension module with a stylesheet + * initialization function. + */ + if (xsltExtensionsHash != NULL) { + xsltExtModulePtr module; + + module = xmlHashLookup(xsltExtensionsHash, URI); + if (module != NULL) { + xsltExtDataPtr data; + + data = xsltStyleGetExtData(style, URI); + } + } return(0); } @@ -438,17 +457,19 @@ #endif return(NULL); } else { - if (module->styleInitFunc == NULL) - return(NULL); - + if (module->styleInitFunc == NULL) { #ifdef WITH_XSLT_DEBUG_EXTENSIONS - xsltGenericDebug(xsltGenericDebugContext, - "Initializing module: %s\n", URI); + xsltGenericDebug(xsltGenericDebugContext, + "Registering style module: %s\n", URI); #endif - - extData = module->styleInitFunc(style, URI); - if (extData == NULL) - return(NULL); + extData = NULL; + } else { +#ifdef WITH_XSLT_DEBUG_EXTENSIONS + xsltGenericDebug(xsltGenericDebugContext, + "Initializing module: %s\n", URI); +#endif + extData = module->styleInitFunc(style, URI); + } data = xsltNewExtData(module, extData); if (data == NULL) @@ -576,7 +597,6 @@ xsltGenericDebug(xsltGenericDebugContext, "xsltInitCtxtExt: no extData\n"); #endif - return; } ctxtData = xsltNewExtData(module, extData); if (ctxtData == NULL) { diff --git a/libxslt/transform.c b/libxslt/transform.c --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -401,7 +401,6 @@ cur->extrasMax = 0; } - XSLT_REGISTER_VARIABLE_LOOKUP(cur); XSLT_REGISTER_FUNCTION_LOOKUP(cur); cur->xpathCtxt->nsHash = style->nsHash; @@ -420,6 +419,7 @@ cur->xinclude = xsltDoXIncludeDefault; cur->outputFile = NULL; cur->sec = xsltGetDefaultSecurityPrefs(); + return(cur); } @@ -433,6 +433,13 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) { if (ctxt == NULL) return; + + /* + * Shutdown the extension modules associated to the stylesheet + * used if needed. + */ + xsltShutdownCtxtExts(ctxt); + if (ctxt->xpathCtxt != NULL) { ctxt->xpathCtxt->nsHash = NULL; xmlXPathFreeContext(ctxt->xpathCtxt); diff --git a/python/libxsl.py b/python/libxsl.py --- a/python/libxsl.py +++ b/python/libxsl.py @@ -49,6 +49,37 @@ import libxsltmod import libxml2 +class extensionModule: + def _styleInit(self, style, URI): + return self.styleInit(stylesheet(_obj=style), URI) + + def _styleShutdown(self, style, URI, data): + return self.styleShutdown(stylesheet(_obj=style), URI, data) + + def _ctxtInit(self, ctxt, URI): + return self.ctxtInit(transformCtxt(_obj=ctxt), URI) + + def _ctxtShutdown(self, ctxt, URI, data): + return self.ctxtShutdown(transformCtxt(_obj=ctxt), URI, data) + + def styleInit(self, style, URI): + """Callback function when used in a newly compiled stylesheet, + the return value is passed in subsequent calls""" + pass + + def styleShutdown(self, style, URI, data): + """Callback function when a stylesheet using it is destroyed""" + pass + + def ctxtInit(self, ctxt, URI): + """Callback function when used in a new transformation process, + the return value is passed in subsequent calls""" + pass + + def ctxtShutdown(self, ctxt, URI, data): + """Callback function when a transformation using it finishes""" + pass + # # Everything below this point is automatically generated # diff --git a/python/libxslt-python-api.xml b/python/libxslt-python-api.xml --- a/python/libxslt-python-api.xml +++ b/python/libxslt-python-api.xml @@ -31,6 +31,12 @@ <arg name='URI' type='xmlChar *' info='the namespace or NULL'/> <arg name='f' type='pythonObject' info='the python function'/> </function> + <function name='xsltRegisterExtensionClass' file='python'> + <info>Register a Python written extension class to the XSLT engine</info> + <return type='int' info="0 in case of success, -1 in case of error"/> + <arg name='URI' type='xmlChar *' info='the namespace or NULL'/> + <arg name='c' type='pythonObject' info='the python class instance'/> + </function> <function name='xsltCleanup' file='python'> <info>Cleanup all libxslt and libxml2 memory allocated</info> <return type='void'/> diff --git a/python/libxslt.c b/python/libxslt.c --- a/python/libxslt.c +++ b/python/libxslt.c @@ -24,9 +24,10 @@ #endif /* #define DEBUG */ -/* #define DEBUG_XPATH */ +#define DEBUG_XPATH */ /* #define DEBUG_ERROR */ /* #define DEBUG_MEMORY */ +#define DEBUG_EXTENSIONS */ void initlibxsltmod(void); @@ -131,7 +132,7 @@ xmlChar *ns_uri; PyObject *pyobj_f; - if (!PyArg_ParseTuple(args, (char *)"szO:registerXPathFunction", + if (!PyArg_ParseTuple(args, (char *)"szO:registerExtModuleFunction", &name, &ns_uri, &pyobj_f)) return(NULL); @@ -411,6 +412,195 @@ /************************************************************************ * * + * Extension classes * + * * + ************************************************************************/ + +static xmlHashTablePtr libxslt_extModuleClasses = NULL; + +static void * +libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style, + const xmlChar * URI) { + PyObject *result; + PyObject *class = NULL; + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltPythonExtModuleStyleInit(%p, %s) called\n", + style, URI); +#endif + + if ((style == NULL) || (URI == NULL)) + return(NULL); + + /* + * Find the function, it should be there it was there at lookup + */ + class = xmlHashLookup(libxslt_extModuleClasses, URI); + if (class == NULL) { + fprintf(stderr, "libxslt_xsltPythonExtModuleStyleInit: internal error %s not found !\n", URI); + return(NULL); + } + + if (PyObject_HasAttrString(class, (char *) "_styleInit")) { + result = PyObject_CallMethod(class, (char *) "_styleInit", + (char *) "Os", libxslt_xsltStylesheetPtrWrap(style), URI); + } + return((void *)result); +} +static void +libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style, + const xmlChar * URI, void *data) { + PyObject *class = NULL; + PyObject *result; + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltPythonExtModuleStyleShutdown(%p, %s, %p) called\n", + style, URI, data); +#endif + + if ((style == NULL) || (URI == NULL)) + return; + + /* + * Find the function, it should be there it was there at lookup + */ + class = xmlHashLookup(libxslt_extModuleClasses, URI); + if (class == NULL) { + fprintf(stderr, "libxslt_xsltPythonExtModuleStyleShutdown: internal error %s not found !\n", URI); + return(NULL); + } + + if (PyObject_HasAttrString(class, (char *) "_styleShutdown")) { + result = PyObject_CallMethod(class, (char *) "_styleShutdown", + (char *) "OsO", libxslt_xsltStylesheetPtrWrap(style), + URI, (PyObject *) data); + Py_XDECREF(result); + Py_XDECREF((PyObject *)data); + } +} + +static void * +libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt, + const xmlChar * URI) { + PyObject *result; + PyObject *class = NULL; + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltPythonExtModuleCtxtInit(%p, %s) called\n", + ctxt, URI); +#endif + + if ((ctxt == NULL) || (URI == NULL)) + return(NULL); + + /* + * Find the function, it should be there it was there at lookup + */ + class = xmlHashLookup(libxslt_extModuleClasses, URI); + if (class == NULL) { + fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtInit: internal error %s not found !\n", URI); + return(NULL); + } + + if (PyObject_HasAttrString(class, (char *) "_ctxtInit")) { + result = PyObject_CallMethod(class, (char *) "_ctxtInit", + (char *) "Os", libxslt_xsltTransformContextPtrWrap(ctxt), + URI); + } + return((void *)result); +} +static void +libxslt_xsltPythonExtModuleCtxtShutdown(xsltTransformContextPtr ctxt, + const xmlChar * URI, void *data) { + PyObject *class = NULL; + PyObject *result; + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltPythonExtModuleCtxtShutdown(%p, %s, %p) called\n", + ctxt, URI, data); +#endif + + if ((ctxt == NULL) || (URI == NULL)) + return; + + /* + * Find the function, it should be there it was there at lookup + */ + class = xmlHashLookup(libxslt_extModuleClasses, URI); + if (class == NULL) { + fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtShutdown: internal error %s not found !\n", URI); + return(NULL); + } + + if (PyObject_HasAttrString(class, (char *) "_ctxtShutdown")) { + result = PyObject_CallMethod(class, (char *) "_ctxtShutdown", + (char *) "OsO", libxslt_xsltTransformContextPtrWrap(ctxt), + URI, (PyObject *) data); + Py_XDECREF(result); + Py_XDECREF((PyObject *)data); + } +} + +PyObject * +libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { + PyObject *py_retval; + int ret = 0; + xmlChar *name; + xmlChar *ns_uri; + PyObject *pyobj_c; + + if (!PyArg_ParseTuple(args, (char *)"zO:registerExtensionClass", + &ns_uri, &pyobj_c)) + return(NULL); + + if ((ns_uri == NULL) || (pyobj_c == NULL)) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltRegisterExtensionClass(%s) called\n", ns_uri); +#endif + + if (libxslt_extModuleClasses == NULL) + libxslt_extModuleClasses = xmlHashCreate(10); + if (libxslt_extModuleClasses == NULL) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + ret = xmlHashAddEntry(libxslt_extModuleClasses, ns_uri, pyobj_c); + if (ret != 0) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + Py_XINCREF(pyobj_c); + + ret = xsltRegisterExtModuleFull(ns_uri, + (xsltExtInitFunction) libxslt_xsltPythonExtModuleCtxtInit, + (xsltExtShutdownFunction) libxslt_xsltPythonExtModuleCtxtShutdown, + (xsltStyleExtInitFunction) libxslt_xsltPythonExtModuleStyleInit, + (xsltStyleExtShutdownFunction) libxslt_xsltPythonExtModuleStyleShutdown); + py_retval = libxml_intWrap((int) ret); + if (ret < 0) { + Py_XDECREF(pyobj_c); + } + return(py_retval); +} + +static void +deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { + PyObject *class = (PyObject *) payload; + +#ifdef DEBUG_EXTENSIONS + printf("deallocateClasse(%s) called\n", name); +#endif + + Py_XDECREF(class); +} + +/************************************************************************ + * * * Integrated cleanup * * * ************************************************************************/ @@ -422,6 +612,9 @@ if (libxslt_extModuleFunctions != NULL) { xmlHashFree(libxslt_extModuleFunctions, deallocateCallback); } + if (libxslt_extModuleClasses != NULL) { + xmlHashFree(libxslt_extModuleClasses, deallocateClasse); + } xsltCleanupGlobals(); xmlCleanupParser(); Py_INCREF(Py_None); diff --git a/python/libxsltclass.txt b/python/libxsltclass.txt --- a/python/libxsltclass.txt +++ b/python/libxsltclass.txt @@ -20,6 +20,7 @@ cleanup() registerErrorHandler() registerExtModuleFunction() +registerExtensionClass() # functions from module transform setXIncludeDefault()