1 | /* |
---|
2 | * libxslt.c: this modules implements the main part of the glue of the |
---|
3 | * libxslt library and the Python interpreter. It provides the |
---|
4 | * entry points where an automatically generated stub is either |
---|
5 | * unpractical or would not match cleanly the Python model. |
---|
6 | * |
---|
7 | * If compiled with MERGED_MODULES, the entry point will be used to |
---|
8 | * initialize both the libxml2 and the libxslt wrappers |
---|
9 | * |
---|
10 | * See Copyright for the status of this software. |
---|
11 | * |
---|
12 | * daniel@veillard.com |
---|
13 | */ |
---|
14 | #include <Python.h> |
---|
15 | /* #include "config.h" */ |
---|
16 | #include <libxml/xmlmemory.h> |
---|
17 | #include <libxml/tree.h> |
---|
18 | #include <libxml/xpath.h> |
---|
19 | #include "libxslt_wrap.h" |
---|
20 | #include "libxslt-py.h" |
---|
21 | |
---|
22 | #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf) |
---|
23 | #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a) |
---|
24 | #endif |
---|
25 | |
---|
26 | /* #define DEBUG */ |
---|
27 | /* #define DEBUG_XPATH */ |
---|
28 | /* #define DEBUG_ERROR */ |
---|
29 | /* #define DEBUG_MEMORY */ |
---|
30 | /* #define DEBUG_EXTENSIONS */ |
---|
31 | |
---|
32 | void initlibxsltmod(void); |
---|
33 | |
---|
34 | /************************************************************************ |
---|
35 | * * |
---|
36 | * Per type specific glue * |
---|
37 | * * |
---|
38 | ************************************************************************/ |
---|
39 | |
---|
40 | PyObject * |
---|
41 | libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr style) { |
---|
42 | PyObject *ret; |
---|
43 | |
---|
44 | #ifdef DEBUG |
---|
45 | printf("libxslt_xsltStylesheetPtrWrap: style = %p\n", style); |
---|
46 | #endif |
---|
47 | if (style == NULL) { |
---|
48 | Py_INCREF(Py_None); |
---|
49 | return(Py_None); |
---|
50 | } |
---|
51 | ret = PyCObject_FromVoidPtrAndDesc((void *) style, |
---|
52 | (char *)"xsltStylesheetPtr", NULL); |
---|
53 | return(ret); |
---|
54 | } |
---|
55 | |
---|
56 | PyObject * |
---|
57 | libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) { |
---|
58 | PyObject *ret; |
---|
59 | |
---|
60 | #ifdef DEBUG |
---|
61 | printf("libxslt_xsltTransformContextPtrWrap: ctxt = %p\n", ctxt); |
---|
62 | #endif |
---|
63 | if (ctxt == NULL) { |
---|
64 | Py_INCREF(Py_None); |
---|
65 | return(Py_None); |
---|
66 | } |
---|
67 | ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, |
---|
68 | (char *)"xsltTransformContextPtr", NULL); |
---|
69 | return(ret); |
---|
70 | } |
---|
71 | |
---|
72 | /************************************************************************ |
---|
73 | * * |
---|
74 | * Extending the API * |
---|
75 | * * |
---|
76 | ************************************************************************/ |
---|
77 | |
---|
78 | static xmlHashTablePtr libxslt_extModuleFunctions = NULL; |
---|
79 | |
---|
80 | static void |
---|
81 | libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) { |
---|
82 | PyObject *list, *cur, *result; |
---|
83 | xmlXPathObjectPtr obj; |
---|
84 | xmlXPathContextPtr rctxt; |
---|
85 | PyObject *current_function = NULL; |
---|
86 | const xmlChar *name; |
---|
87 | const xmlChar *ns_uri; |
---|
88 | int i; |
---|
89 | |
---|
90 | if (ctxt == NULL) |
---|
91 | return; |
---|
92 | rctxt = ctxt->context; |
---|
93 | if (rctxt == NULL) |
---|
94 | return; |
---|
95 | name = rctxt->function; |
---|
96 | ns_uri = rctxt->functionURI; |
---|
97 | #ifdef DEBUG_XPATH |
---|
98 | printf("libxslt_xmlXPathFuncCallback called name %s URI %s\n", name, ns_uri); |
---|
99 | #endif |
---|
100 | |
---|
101 | /* |
---|
102 | * Find the function, it should be there it was there at lookup |
---|
103 | */ |
---|
104 | current_function = xmlHashLookup2(libxslt_extModuleFunctions, |
---|
105 | name, ns_uri); |
---|
106 | if (current_function == NULL) { |
---|
107 | printf("libxslt_xmlXPathFuncCallback: internal error %s not found !\n", |
---|
108 | name); |
---|
109 | return; |
---|
110 | } |
---|
111 | |
---|
112 | list = PyTuple_New(nargs + 1); |
---|
113 | PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt)); |
---|
114 | for (i = nargs - 1;i >= 0;i--) { |
---|
115 | obj = valuePop(ctxt); |
---|
116 | cur = libxml_xmlXPathObjectPtrWrap(obj); |
---|
117 | PyTuple_SetItem(list, i + 1, cur); |
---|
118 | } |
---|
119 | result = PyEval_CallObject(current_function, list); |
---|
120 | Py_DECREF(list); |
---|
121 | |
---|
122 | obj = libxml_xmlXPathObjectPtrConvert(result); |
---|
123 | valuePush(ctxt, obj); |
---|
124 | } |
---|
125 | |
---|
126 | PyObject * |
---|
127 | libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED, |
---|
128 | PyObject *args) { |
---|
129 | PyObject *py_retval; |
---|
130 | int ret = 0; |
---|
131 | xmlChar *name; |
---|
132 | xmlChar *ns_uri; |
---|
133 | PyObject *pyobj_f; |
---|
134 | |
---|
135 | if (!PyArg_ParseTuple(args, (char *)"szO:registerExtModuleFunction", |
---|
136 | &name, &ns_uri, &pyobj_f)) |
---|
137 | return(NULL); |
---|
138 | |
---|
139 | if ((name == NULL) || (pyobj_f == NULL)) { |
---|
140 | py_retval = libxml_intWrap(-1); |
---|
141 | return(py_retval); |
---|
142 | } |
---|
143 | |
---|
144 | #ifdef DEBUG_XPATH |
---|
145 | printf("libxslt_xsltRegisterExtModuleFunction(%s, %s) called\n", |
---|
146 | name, ns_uri); |
---|
147 | #endif |
---|
148 | |
---|
149 | if (libxslt_extModuleFunctions == NULL) |
---|
150 | libxslt_extModuleFunctions = xmlHashCreate(10); |
---|
151 | if (libxslt_extModuleFunctions == NULL) { |
---|
152 | py_retval = libxml_intWrap(-1); |
---|
153 | return(py_retval); |
---|
154 | } |
---|
155 | ret = xmlHashAddEntry2(libxslt_extModuleFunctions, name, ns_uri, pyobj_f); |
---|
156 | if (ret != 0) { |
---|
157 | py_retval = libxml_intWrap(-1); |
---|
158 | return(py_retval); |
---|
159 | } |
---|
160 | Py_XINCREF(pyobj_f); |
---|
161 | |
---|
162 | ret = xsltRegisterExtModuleFunction(name, ns_uri, |
---|
163 | libxslt_xmlXPathFuncCallback); |
---|
164 | py_retval = libxml_intWrap((int) ret); |
---|
165 | return(py_retval); |
---|
166 | } |
---|
167 | |
---|
168 | static void |
---|
169 | deallocateCallback(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { |
---|
170 | PyObject *function = (PyObject *) payload; |
---|
171 | |
---|
172 | #ifdef DEBUG_XPATH |
---|
173 | printf("deallocateCallback(%s) called\n", name); |
---|
174 | #endif |
---|
175 | |
---|
176 | Py_XDECREF(function); |
---|
177 | } |
---|
178 | |
---|
179 | /************************************************************************ |
---|
180 | * * |
---|
181 | * Some customized front-ends * |
---|
182 | * * |
---|
183 | ************************************************************************/ |
---|
184 | |
---|
185 | PyObject * |
---|
186 | libxslt_xsltApplyStylesheet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { |
---|
187 | PyObject *py_retval; |
---|
188 | xmlDocPtr c_retval; |
---|
189 | xsltStylesheetPtr style; |
---|
190 | PyObject *pyobj_style; |
---|
191 | xmlDocPtr doc; |
---|
192 | PyObject *pyobj_doc; |
---|
193 | PyObject *pyobj_params; |
---|
194 | const char **params = NULL; |
---|
195 | int len = 0, i = 0, j; |
---|
196 | PyObject *name; |
---|
197 | PyObject *value; |
---|
198 | |
---|
199 | if (!PyArg_ParseTuple(args, (char *) "OOO:xsltApplyStylesheet", |
---|
200 | &pyobj_style, &pyobj_doc, &pyobj_params)) |
---|
201 | return(NULL); |
---|
202 | |
---|
203 | if (pyobj_params != Py_None) { |
---|
204 | if (PyDict_Check(pyobj_params)) { |
---|
205 | len = PyDict_Size(pyobj_params); |
---|
206 | if (len > 0) { |
---|
207 | params = (const char **) xmlMalloc((len + 1) * 2 * |
---|
208 | sizeof(char *)); |
---|
209 | if (params == NULL) { |
---|
210 | printf("libxslt_xsltApplyStylesheet: out of memory\n"); |
---|
211 | Py_INCREF(Py_None); |
---|
212 | return(Py_None); |
---|
213 | } |
---|
214 | j = 0; |
---|
215 | while (PyDict_Next(pyobj_params, &i, &name, &value)) { |
---|
216 | const char *tmp; |
---|
217 | int size; |
---|
218 | |
---|
219 | tmp = PyString_AS_STRING(name); |
---|
220 | size = PyString_GET_SIZE(name); |
---|
221 | params[j * 2] = (char *) xmlCharStrndup(tmp, size); |
---|
222 | if (PyString_Check(value)) { |
---|
223 | tmp = PyString_AS_STRING(value); |
---|
224 | size = PyString_GET_SIZE(value); |
---|
225 | params[(j * 2) + 1] = (char *) |
---|
226 | xmlCharStrndup(tmp, size); |
---|
227 | } else { |
---|
228 | params[(j * 2) + 1] = NULL; |
---|
229 | } |
---|
230 | j = j + 1; |
---|
231 | } |
---|
232 | params[j * 2] = NULL; |
---|
233 | params[(j * 2) + 1] = NULL; |
---|
234 | } |
---|
235 | } else { |
---|
236 | printf("libxslt_xsltApplyStylesheet: parameters not a dict\n"); |
---|
237 | Py_INCREF(Py_None); |
---|
238 | return(Py_None); |
---|
239 | } |
---|
240 | } |
---|
241 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style); |
---|
242 | doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc); |
---|
243 | |
---|
244 | c_retval = xsltApplyStylesheet(style, doc, params); |
---|
245 | py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval); |
---|
246 | if (params != NULL) { |
---|
247 | if (len > 0) { |
---|
248 | for (i = 0;i < 2 * len;i++) { |
---|
249 | if (params[i] != NULL) |
---|
250 | xmlFree((char *)params[i]); |
---|
251 | } |
---|
252 | xmlFree(params); |
---|
253 | } |
---|
254 | } |
---|
255 | return(py_retval); |
---|
256 | } |
---|
257 | |
---|
258 | PyObject * |
---|
259 | libxslt_xsltSaveResultToString(PyObject *self, PyObject *args) { |
---|
260 | PyObject *py_retval; /* our final return value, a python string */ |
---|
261 | xmlChar *buffer; |
---|
262 | xmlChar *tmp; |
---|
263 | int size = 0; |
---|
264 | int emitted = 0; |
---|
265 | xmlDocPtr result; |
---|
266 | PyObject *pyobj_result; |
---|
267 | xsltStylesheetPtr style; |
---|
268 | PyObject *pyobj_style; |
---|
269 | |
---|
270 | if (!PyArg_ParseTuple(args, (char *)"OO:xsltSaveResultToString", &pyobj_style, &pyobj_result)) |
---|
271 | goto FAIL; |
---|
272 | result = (xmlDocPtr) PyxmlNode_Get(pyobj_result); |
---|
273 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style); |
---|
274 | |
---|
275 | |
---|
276 | /* FIXME: We should probably add more restrictive error checking |
---|
277 | * and raise an error instead of "just" returning NULL. |
---|
278 | * FIXME: Documentation and code for xsltSaveResultToString diff |
---|
279 | * -> emmitted will never be positive non-null. |
---|
280 | */ |
---|
281 | emitted = xsltSaveResultToString(&buffer, &size, result, style); |
---|
282 | if(!buffer || emitted < 0) |
---|
283 | goto FAIL; |
---|
284 | /* We haven't tested the aberrant case of a transformation that |
---|
285 | * renders to an empty string. For now we try to play it save. |
---|
286 | */ |
---|
287 | if(size) |
---|
288 | { |
---|
289 | buffer[size] = '\0'; |
---|
290 | py_retval = PyString_FromString((char *) buffer); |
---|
291 | xmlFree(buffer); |
---|
292 | } |
---|
293 | else |
---|
294 | py_retval = PyString_FromString(""); |
---|
295 | return(py_retval); |
---|
296 | FAIL: |
---|
297 | return(0); |
---|
298 | } |
---|
299 | |
---|
300 | |
---|
301 | /************************************************************************ |
---|
302 | * * |
---|
303 | * Error message callback * |
---|
304 | * * |
---|
305 | ************************************************************************/ |
---|
306 | |
---|
307 | static PyObject *libxslt_xsltPythonErrorFuncHandler = NULL; |
---|
308 | static PyObject *libxslt_xsltPythonErrorFuncCtxt = NULL; |
---|
309 | |
---|
310 | static void |
---|
311 | libxslt_xsltErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg, |
---|
312 | ...) |
---|
313 | { |
---|
314 | int size; |
---|
315 | int chars; |
---|
316 | char *larger; |
---|
317 | va_list ap; |
---|
318 | char *str; |
---|
319 | PyObject *list; |
---|
320 | PyObject *message; |
---|
321 | PyObject *result; |
---|
322 | |
---|
323 | #ifdef DEBUG_ERROR |
---|
324 | printf("libxslt_xsltErrorFuncHandler(%p, %s, ...) called\n", ctx, msg); |
---|
325 | #endif |
---|
326 | |
---|
327 | |
---|
328 | if (libxslt_xsltPythonErrorFuncHandler == NULL) { |
---|
329 | va_start(ap, msg); |
---|
330 | vfprintf(stdout, msg, ap); |
---|
331 | va_end(ap); |
---|
332 | } else { |
---|
333 | str = (char *) xmlMalloc(150); |
---|
334 | if (str == NULL) |
---|
335 | return; |
---|
336 | |
---|
337 | size = 150; |
---|
338 | |
---|
339 | while (1) { |
---|
340 | va_start(ap, msg); |
---|
341 | chars = vsnprintf(str, size, msg, ap); |
---|
342 | va_end(ap); |
---|
343 | if ((chars > -1) && (chars < size)) |
---|
344 | break; |
---|
345 | if (chars > -1) |
---|
346 | size += chars + 1; |
---|
347 | else |
---|
348 | size += 100; |
---|
349 | if ((larger = (char *) xmlRealloc(str, size)) == NULL) { |
---|
350 | xmlFree(str); |
---|
351 | return; |
---|
352 | } |
---|
353 | str = larger; |
---|
354 | } |
---|
355 | |
---|
356 | list = PyTuple_New(2); |
---|
357 | PyTuple_SetItem(list, 0, libxslt_xsltPythonErrorFuncCtxt); |
---|
358 | Py_XINCREF(libxslt_xsltPythonErrorFuncCtxt); |
---|
359 | message = libxml_charPtrWrap(str); |
---|
360 | PyTuple_SetItem(list, 1, message); |
---|
361 | result = PyEval_CallObject(libxslt_xsltPythonErrorFuncHandler, list); |
---|
362 | Py_XDECREF(list); |
---|
363 | Py_XDECREF(result); |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | static void |
---|
368 | libxslt_xsltErrorInitialize(void) |
---|
369 | { |
---|
370 | #ifdef DEBUG_ERROR |
---|
371 | printf("libxslt_xsltErrorInitialize() called\n"); |
---|
372 | #endif |
---|
373 | xmlSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler); |
---|
374 | xsltSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler); |
---|
375 | } |
---|
376 | |
---|
377 | PyObject * |
---|
378 | libxslt_xsltRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self, |
---|
379 | PyObject * args) |
---|
380 | { |
---|
381 | PyObject *py_retval; |
---|
382 | PyObject *pyobj_f; |
---|
383 | PyObject *pyobj_ctx; |
---|
384 | |
---|
385 | if (!PyArg_ParseTuple |
---|
386 | (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f, |
---|
387 | &pyobj_ctx)) |
---|
388 | return (NULL); |
---|
389 | |
---|
390 | #ifdef DEBUG_ERROR |
---|
391 | printf("libxml_registerXPathFunction(%p, %p) called\n", pyobj_ctx, |
---|
392 | pyobj_f); |
---|
393 | #endif |
---|
394 | |
---|
395 | if (libxslt_xsltPythonErrorFuncHandler != NULL) { |
---|
396 | Py_XDECREF(libxslt_xsltPythonErrorFuncHandler); |
---|
397 | } |
---|
398 | if (libxslt_xsltPythonErrorFuncCtxt != NULL) { |
---|
399 | Py_XDECREF(libxslt_xsltPythonErrorFuncCtxt); |
---|
400 | } |
---|
401 | |
---|
402 | Py_XINCREF(pyobj_ctx); |
---|
403 | Py_XINCREF(pyobj_f); |
---|
404 | |
---|
405 | /* TODO: check f is a function ! */ |
---|
406 | libxslt_xsltPythonErrorFuncHandler = pyobj_f; |
---|
407 | libxslt_xsltPythonErrorFuncCtxt = pyobj_ctx; |
---|
408 | |
---|
409 | py_retval = libxml_intWrap(1); |
---|
410 | return (py_retval); |
---|
411 | } |
---|
412 | |
---|
413 | /************************************************************************ |
---|
414 | * * |
---|
415 | * Extension classes * |
---|
416 | * * |
---|
417 | ************************************************************************/ |
---|
418 | |
---|
419 | static xmlHashTablePtr libxslt_extModuleClasses = NULL; |
---|
420 | |
---|
421 | static void * |
---|
422 | libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style, |
---|
423 | const xmlChar * URI) { |
---|
424 | PyObject *result; |
---|
425 | PyObject *class = NULL; |
---|
426 | |
---|
427 | #ifdef DEBUG_EXTENSIONS |
---|
428 | printf("libxslt_xsltPythonExtModuleStyleInit(%p, %s) called\n", |
---|
429 | style, URI); |
---|
430 | #endif |
---|
431 | |
---|
432 | if ((style == NULL) || (URI == NULL)) |
---|
433 | return(NULL); |
---|
434 | |
---|
435 | /* |
---|
436 | * Find the function, it should be there it was there at lookup |
---|
437 | */ |
---|
438 | class = xmlHashLookup(libxslt_extModuleClasses, URI); |
---|
439 | if (class == NULL) { |
---|
440 | fprintf(stderr, "libxslt_xsltPythonExtModuleStyleInit: internal error %s not found !\n", URI); |
---|
441 | return(NULL); |
---|
442 | } |
---|
443 | |
---|
444 | if (PyObject_HasAttrString(class, (char *) "_styleInit")) { |
---|
445 | result = PyObject_CallMethod(class, (char *) "_styleInit", |
---|
446 | (char *) "Os", libxslt_xsltStylesheetPtrWrap(style), URI); |
---|
447 | } |
---|
448 | return((void *)result); |
---|
449 | } |
---|
450 | static void |
---|
451 | libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style, |
---|
452 | const xmlChar * URI, void *data) { |
---|
453 | PyObject *class = NULL; |
---|
454 | PyObject *result; |
---|
455 | |
---|
456 | #ifdef DEBUG_EXTENSIONS |
---|
457 | printf("libxslt_xsltPythonExtModuleStyleShutdown(%p, %s, %p) called\n", |
---|
458 | style, URI, data); |
---|
459 | #endif |
---|
460 | |
---|
461 | if ((style == NULL) || (URI == NULL)) |
---|
462 | return; |
---|
463 | |
---|
464 | /* |
---|
465 | * Find the function, it should be there it was there at lookup |
---|
466 | */ |
---|
467 | class = xmlHashLookup(libxslt_extModuleClasses, URI); |
---|
468 | if (class == NULL) { |
---|
469 | fprintf(stderr, "libxslt_xsltPythonExtModuleStyleShutdown: internal error %s not found !\n", URI); |
---|
470 | return(NULL); |
---|
471 | } |
---|
472 | |
---|
473 | if (PyObject_HasAttrString(class, (char *) "_styleShutdown")) { |
---|
474 | result = PyObject_CallMethod(class, (char *) "_styleShutdown", |
---|
475 | (char *) "OsO", libxslt_xsltStylesheetPtrWrap(style), |
---|
476 | URI, (PyObject *) data); |
---|
477 | Py_XDECREF(result); |
---|
478 | Py_XDECREF((PyObject *)data); |
---|
479 | } |
---|
480 | } |
---|
481 | |
---|
482 | static void * |
---|
483 | libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt, |
---|
484 | const xmlChar * URI) { |
---|
485 | PyObject *result; |
---|
486 | PyObject *class = NULL; |
---|
487 | |
---|
488 | #ifdef DEBUG_EXTENSIONS |
---|
489 | printf("libxslt_xsltPythonExtModuleCtxtInit(%p, %s) called\n", |
---|
490 | ctxt, URI); |
---|
491 | #endif |
---|
492 | |
---|
493 | if ((ctxt == NULL) || (URI == NULL)) |
---|
494 | return(NULL); |
---|
495 | |
---|
496 | /* |
---|
497 | * Find the function, it should be there it was there at lookup |
---|
498 | */ |
---|
499 | class = xmlHashLookup(libxslt_extModuleClasses, URI); |
---|
500 | if (class == NULL) { |
---|
501 | fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtInit: internal error %s not found !\n", URI); |
---|
502 | return(NULL); |
---|
503 | } |
---|
504 | |
---|
505 | if (PyObject_HasAttrString(class, (char *) "_ctxtInit")) { |
---|
506 | result = PyObject_CallMethod(class, (char *) "_ctxtInit", |
---|
507 | (char *) "Os", libxslt_xsltTransformContextPtrWrap(ctxt), |
---|
508 | URI); |
---|
509 | } |
---|
510 | return((void *)result); |
---|
511 | } |
---|
512 | static void |
---|
513 | libxslt_xsltPythonExtModuleCtxtShutdown(xsltTransformContextPtr ctxt, |
---|
514 | const xmlChar * URI, void *data) { |
---|
515 | PyObject *class = NULL; |
---|
516 | PyObject *result; |
---|
517 | |
---|
518 | #ifdef DEBUG_EXTENSIONS |
---|
519 | printf("libxslt_xsltPythonExtModuleCtxtShutdown(%p, %s, %p) called\n", |
---|
520 | ctxt, URI, data); |
---|
521 | #endif |
---|
522 | |
---|
523 | if ((ctxt == NULL) || (URI == NULL)) |
---|
524 | return; |
---|
525 | |
---|
526 | /* |
---|
527 | * Find the function, it should be there it was there at lookup |
---|
528 | */ |
---|
529 | class = xmlHashLookup(libxslt_extModuleClasses, URI); |
---|
530 | if (class == NULL) { |
---|
531 | fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtShutdown: internal error %s not found !\n", URI); |
---|
532 | return(NULL); |
---|
533 | } |
---|
534 | |
---|
535 | if (PyObject_HasAttrString(class, (char *) "_ctxtShutdown")) { |
---|
536 | result = PyObject_CallMethod(class, (char *) "_ctxtShutdown", |
---|
537 | (char *) "OsO", libxslt_xsltTransformContextPtrWrap(ctxt), |
---|
538 | URI, (PyObject *) data); |
---|
539 | Py_XDECREF(result); |
---|
540 | Py_XDECREF((PyObject *)data); |
---|
541 | } |
---|
542 | } |
---|
543 | |
---|
544 | PyObject * |
---|
545 | libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED, |
---|
546 | PyObject *args) { |
---|
547 | PyObject *py_retval; |
---|
548 | int ret = 0; |
---|
549 | xmlChar *name; |
---|
550 | xmlChar *ns_uri; |
---|
551 | PyObject *pyobj_c; |
---|
552 | |
---|
553 | if (!PyArg_ParseTuple(args, (char *)"zO:registerExtensionClass", |
---|
554 | &ns_uri, &pyobj_c)) |
---|
555 | return(NULL); |
---|
556 | |
---|
557 | if ((ns_uri == NULL) || (pyobj_c == NULL)) { |
---|
558 | py_retval = libxml_intWrap(-1); |
---|
559 | return(py_retval); |
---|
560 | } |
---|
561 | |
---|
562 | #ifdef DEBUG_EXTENSIONS |
---|
563 | printf("libxslt_xsltRegisterExtensionClass(%s) called\n", ns_uri); |
---|
564 | #endif |
---|
565 | |
---|
566 | if (libxslt_extModuleClasses == NULL) |
---|
567 | libxslt_extModuleClasses = xmlHashCreate(10); |
---|
568 | if (libxslt_extModuleClasses == NULL) { |
---|
569 | py_retval = libxml_intWrap(-1); |
---|
570 | return(py_retval); |
---|
571 | } |
---|
572 | ret = xmlHashAddEntry(libxslt_extModuleClasses, ns_uri, pyobj_c); |
---|
573 | if (ret != 0) { |
---|
574 | py_retval = libxml_intWrap(-1); |
---|
575 | return(py_retval); |
---|
576 | } |
---|
577 | Py_XINCREF(pyobj_c); |
---|
578 | |
---|
579 | ret = xsltRegisterExtModuleFull(ns_uri, |
---|
580 | (xsltExtInitFunction) libxslt_xsltPythonExtModuleCtxtInit, |
---|
581 | (xsltExtShutdownFunction) libxslt_xsltPythonExtModuleCtxtShutdown, |
---|
582 | (xsltStyleExtInitFunction) libxslt_xsltPythonExtModuleStyleInit, |
---|
583 | (xsltStyleExtShutdownFunction) libxslt_xsltPythonExtModuleStyleShutdown); |
---|
584 | py_retval = libxml_intWrap((int) ret); |
---|
585 | if (ret < 0) { |
---|
586 | Py_XDECREF(pyobj_c); |
---|
587 | } |
---|
588 | return(py_retval); |
---|
589 | } |
---|
590 | |
---|
591 | static void |
---|
592 | deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { |
---|
593 | PyObject *class = (PyObject *) payload; |
---|
594 | |
---|
595 | #ifdef DEBUG_EXTENSIONS |
---|
596 | printf("deallocateClasse(%s) called\n", name); |
---|
597 | #endif |
---|
598 | |
---|
599 | Py_XDECREF(class); |
---|
600 | } |
---|
601 | |
---|
602 | /************************************************************************ |
---|
603 | * * |
---|
604 | * Integrated cleanup * |
---|
605 | * * |
---|
606 | ************************************************************************/ |
---|
607 | |
---|
608 | PyObject * |
---|
609 | libxslt_xsltCleanup(PyObject *self ATTRIBUTE_UNUSED, |
---|
610 | PyObject *args ATTRIBUTE_UNUSED) { |
---|
611 | |
---|
612 | if (libxslt_extModuleFunctions != NULL) { |
---|
613 | xmlHashFree(libxslt_extModuleFunctions, deallocateCallback); |
---|
614 | } |
---|
615 | if (libxslt_extModuleClasses != NULL) { |
---|
616 | xmlHashFree(libxslt_extModuleClasses, deallocateClasse); |
---|
617 | } |
---|
618 | xsltCleanupGlobals(); |
---|
619 | xmlCleanupParser(); |
---|
620 | Py_INCREF(Py_None); |
---|
621 | return(Py_None); |
---|
622 | } |
---|
623 | |
---|
624 | /************************************************************************ |
---|
625 | * * |
---|
626 | * The registration stuff * |
---|
627 | * * |
---|
628 | ************************************************************************/ |
---|
629 | static PyMethodDef libxsltMethods[] = { |
---|
630 | #include "libxslt-export.c" |
---|
631 | { NULL, NULL, 0, NULL } |
---|
632 | }; |
---|
633 | |
---|
634 | #ifdef MERGED_MODULES |
---|
635 | extern void initlibxml2mod(void); |
---|
636 | #endif |
---|
637 | |
---|
638 | void initlibxsltmod(void) { |
---|
639 | static int initialized = 0; |
---|
640 | PyObject *m; |
---|
641 | |
---|
642 | #ifdef MERGED_MODULES |
---|
643 | initlibxml2mod(); |
---|
644 | #endif |
---|
645 | |
---|
646 | if (initialized != 0) |
---|
647 | return; |
---|
648 | m = Py_InitModule((char *)"libxsltmod", libxsltMethods); |
---|
649 | initialized = 1; |
---|
650 | /* |
---|
651 | * Specific XSLT initializations |
---|
652 | */ |
---|
653 | libxslt_xsltErrorInitialize(); |
---|
654 | xmlInitMemory(); |
---|
655 | xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; |
---|
656 | xmlDefaultSAXHandler.cdataBlock = NULL; |
---|
657 | /* |
---|
658 | * Register the EXSLT extensions and the test module |
---|
659 | */ |
---|
660 | exsltRegisterAll(); |
---|
661 | } |
---|
662 | |
---|
663 | |
---|