Imported Upstream version 2.9.2
[platform/upstream/libxml2.git] / python / libxml.c
1 /*
2  * libxml.c: this modules implements the main part of the glue of the
3  *           libxml2 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 <fileobject.h>
16 /* #include "config.h" */
17 #include <libxml/xmlmemory.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
20 #include <libxml/xpath.h>
21 #include <libxml/xmlerror.h>
22 #include <libxml/xpathInternals.h>
23 #include <libxml/xmlmemory.h>
24 #include <libxml/xmlIO.h>
25 #include <libxml/c14n.h>
26 #include <libxml/xmlreader.h>
27 #include <libxml/xmlsave.h>
28 #include "libxml_wrap.h"
29 #include "libxml2-py.h"
30
31 #if defined(WITH_TRIO)
32 #include "trio.h"
33 #define vsnprintf trio_vsnprintf
34 #endif
35
36 /* #define DEBUG */
37 /* #define DEBUG_SAX */
38 /* #define DEBUG_XPATH */
39 /* #define DEBUG_ERROR */
40 /* #define DEBUG_MEMORY */
41 /* #define DEBUG_FILES */
42 /* #define DEBUG_LOADER */
43
44 #if PY_MAJOR_VERSION >= 3
45 PyObject *PyInit_libxml2mod(void);
46
47 #define PY_IMPORT_STRING_SIZE PyUnicode_FromStringAndSize
48 #define PY_IMPORT_STRING PyUnicode_FromString
49 #else
50 void initlibxml2mod(void);
51 #define PY_IMPORT_STRING_SIZE PyString_FromStringAndSize
52 #define PY_IMPORT_STRING PyString_FromString
53 #endif
54
55
56 /**
57  * TODO:
58  *
59  * macro to flag unimplemented blocks
60  */
61 #define TODO                                                            \
62     xmlGenericError(xmlGenericErrorContext,                             \
63             "Unimplemented block at %s:%d\n",                           \
64             __FILE__, __LINE__);
65 /*
66  * the following vars are used for XPath extensions, but
67  * are also referenced within the parser cleanup routine.
68  */
69 static int libxml_xpathCallbacksInitialized = 0;
70
71 typedef struct libxml_xpathCallback {
72     xmlXPathContextPtr ctx;
73     xmlChar *name;
74     xmlChar *ns_uri;
75     PyObject *function;
76 } libxml_xpathCallback, *libxml_xpathCallbackPtr;
77 typedef libxml_xpathCallback libxml_xpathCallbackArray[];
78 static int libxml_xpathCallbacksAllocd = 10;
79 static libxml_xpathCallbackArray *libxml_xpathCallbacks = NULL;
80 static int libxml_xpathCallbacksNb = 0;
81
82 /************************************************************************
83  *                                                                      *
84  *              Memory debug interface                                  *
85  *                                                                      *
86  ************************************************************************/
87
88 #if 0
89 extern void xmlMemFree(void *ptr);
90 extern void *xmlMemMalloc(size_t size);
91 extern void *xmlMemRealloc(void *ptr, size_t size);
92 extern char *xmlMemoryStrdup(const char *str);
93 #endif
94
95 static int libxmlMemoryDebugActivated = 0;
96 static long libxmlMemoryAllocatedBase = 0;
97
98 static int libxmlMemoryDebug = 0;
99 static xmlFreeFunc freeFunc = NULL;
100 static xmlMallocFunc mallocFunc = NULL;
101 static xmlReallocFunc reallocFunc = NULL;
102 static xmlStrdupFunc strdupFunc = NULL;
103
104 static void
105 libxml_xmlErrorInitialize(void); /* forward declare */
106
107 PyObject *
108 libxml_xmlMemoryUsed(PyObject * self ATTRIBUTE_UNUSED, 
109         PyObject * args ATTRIBUTE_UNUSED)
110 {
111     long ret;
112     PyObject *py_retval;
113
114     ret = xmlMemUsed();
115
116     py_retval = libxml_longWrap(ret);
117     return (py_retval);
118 }
119
120 PyObject *
121 libxml_xmlDebugMemory(PyObject * self ATTRIBUTE_UNUSED, PyObject * args)
122 {
123     int activate;
124     PyObject *py_retval;
125     long ret;
126
127     if (!PyArg_ParseTuple(args, (char *) "i:xmlDebugMemory", &activate))
128         return (NULL);
129
130 #ifdef DEBUG_MEMORY
131     printf("libxml_xmlDebugMemory(%d) called\n", activate);
132 #endif
133
134     if (activate != 0) {
135         if (libxmlMemoryDebug == 0) {
136             /*
137              * First initialize the library and grab the old memory handlers
138              * and switch the library to memory debugging
139              */
140             xmlMemGet((xmlFreeFunc *) & freeFunc,
141                       (xmlMallocFunc *) & mallocFunc,
142                       (xmlReallocFunc *) & reallocFunc,
143                       (xmlStrdupFunc *) & strdupFunc);
144             if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&
145                 (reallocFunc == xmlMemRealloc) &&
146                 (strdupFunc == xmlMemoryStrdup)) {
147                 libxmlMemoryAllocatedBase = xmlMemUsed();
148             } else {
149                 /* 
150                  * cleanup first, because some memory has been
151                  * allocated with the non-debug malloc in xmlInitParser
152                  * when the python module was imported
153                  */
154                 xmlCleanupParser();
155                 ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,
156                                          xmlMemRealloc, xmlMemoryStrdup);
157                 if (ret < 0)
158                     goto error;
159                 libxmlMemoryAllocatedBase = xmlMemUsed();
160                 /* reinitialize */
161                 xmlInitParser();
162                 libxml_xmlErrorInitialize();
163             }
164             ret = 0;
165         } else if (libxmlMemoryDebugActivated == 0) {
166             libxmlMemoryAllocatedBase = xmlMemUsed();
167             ret = 0;
168         } else {
169             ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
170         }
171         libxmlMemoryDebug = 1;
172         libxmlMemoryDebugActivated = 1;
173     } else {
174         if (libxmlMemoryDebugActivated == 1)
175             ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
176         else
177             ret = 0;
178         libxmlMemoryDebugActivated = 0;
179     }
180   error:
181     py_retval = libxml_longWrap(ret);
182     return (py_retval);
183 }
184
185 PyObject *
186 libxml_xmlPythonCleanupParser(PyObject *self ATTRIBUTE_UNUSED,
187                               PyObject *args ATTRIBUTE_UNUSED) {
188
189     int ix;
190     long freed = -1;
191
192     if (libxmlMemoryDebug) {
193         freed = xmlMemUsed();
194     }
195
196     xmlCleanupParser();
197     /*
198      * Need to confirm whether we really want to do this (required for
199      * memcheck) in all cases...
200      */
201    
202     if (libxml_xpathCallbacks != NULL) {        /* if ext funcs declared */
203         for (ix=0; ix<libxml_xpathCallbacksNb; ix++) {
204             if ((*libxml_xpathCallbacks)[ix].name != NULL)
205                 xmlFree((*libxml_xpathCallbacks)[ix].name);
206             if ((*libxml_xpathCallbacks)[ix].ns_uri != NULL)
207                 xmlFree((*libxml_xpathCallbacks)[ix].ns_uri);
208         }
209         libxml_xpathCallbacksNb = 0;
210         xmlFree(libxml_xpathCallbacks);
211         libxml_xpathCallbacks = NULL;
212     }
213
214     if (libxmlMemoryDebug) {
215         freed -= xmlMemUsed();
216         libxmlMemoryAllocatedBase -= freed;
217         if (libxmlMemoryAllocatedBase < 0)
218             libxmlMemoryAllocatedBase = 0;
219     }
220
221     Py_INCREF(Py_None);
222     return(Py_None);
223 }
224
225 PyObject *
226 libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
227                      ATTRIBUTE_UNUSED PyObject * args)
228 {
229
230     if (libxmlMemoryDebug != 0)
231         xmlMemoryDump();
232     Py_INCREF(Py_None);
233     return (Py_None);
234 }
235
236 /************************************************************************
237  *                                                                      *
238  *              Handling Python FILE I/O at the C level                 *
239  *      The raw I/O attack diectly the File objects, while the          *
240  *      other routines address the ioWrapper instance instead           *
241  *                                                                      *
242  ************************************************************************/
243
244 /**
245  * xmlPythonFileCloseUnref:
246  * @context:  the I/O context
247  *
248  * Close an I/O channel
249  */
250 static int
251 xmlPythonFileCloseRaw (void * context) {
252     PyObject *file, *ret;
253
254 #ifdef DEBUG_FILES
255     printf("xmlPythonFileCloseUnref\n");
256 #endif
257     file = (PyObject *) context;
258     if (file == NULL) return(-1);
259     ret = PyEval_CallMethod(file, (char *) "close", (char *) "()");
260     if (ret != NULL) {
261         Py_DECREF(ret);
262     }
263     Py_DECREF(file);
264     return(0);
265 }
266
267 /**
268  * xmlPythonFileReadRaw:
269  * @context:  the I/O context
270  * @buffer:  where to drop data
271  * @len:  number of bytes to write
272  *
273  * Read @len bytes to @buffer from the Python file in the I/O channel
274  *
275  * Returns the number of bytes read
276  */
277 static int
278 xmlPythonFileReadRaw (void * context, char * buffer, int len) {
279     PyObject *file;
280     PyObject *ret;
281     int lenread = -1;
282     char *data;
283
284 #ifdef DEBUG_FILES
285     printf("xmlPythonFileReadRaw: %d\n", len);
286 #endif
287     file = (PyObject *) context;
288     if (file == NULL) return(-1);
289     ret = PyEval_CallMethod(file, (char *) "read", (char *) "(i)", len);
290     if (ret == NULL) {
291         printf("xmlPythonFileReadRaw: result is NULL\n");
292         return(-1);
293     } else if (PyBytes_Check(ret)) {
294         lenread = PyBytes_Size(ret);
295         data = PyBytes_AsString(ret);
296 #ifdef PyUnicode_Check
297     } else if PyUnicode_Check (ret) {
298 #if PY_VERSION_HEX >= 0x03030000
299         Py_ssize_t size;
300         const char *tmp;
301
302         /* tmp doesn't need to be deallocated */
303         tmp = PyUnicode_AsUTF8AndSize(ret, &size);
304
305         lenread = (int) size;
306         data = (char *) tmp;
307 #else
308         PyObject *b;
309         b = PyUnicode_AsUTF8String(ret);
310         if (b == NULL) {
311             printf("xmlPythonFileReadRaw: failed to convert to UTF-8\n");
312             return(-1);
313         }
314         lenread = PyBytes_Size(b);
315         data = PyBytes_AsString(b);
316         Py_DECREF(b);
317 #endif
318 #endif
319     } else {
320         printf("xmlPythonFileReadRaw: result is not a String\n");
321         Py_DECREF(ret);
322         return(-1);
323     }
324     if (lenread > len)
325         memcpy(buffer, data, len);
326     else
327         memcpy(buffer, data, lenread);
328     Py_DECREF(ret);
329     return(lenread);
330 }
331
332 /**
333  * xmlPythonFileRead:
334  * @context:  the I/O context
335  * @buffer:  where to drop data
336  * @len:  number of bytes to write
337  *
338  * Read @len bytes to @buffer from the I/O channel.
339  *
340  * Returns the number of bytes read
341  */
342 static int
343 xmlPythonFileRead (void * context, char * buffer, int len) {
344     PyObject *file;
345     PyObject *ret;
346     int lenread = -1;
347     char *data;
348
349 #ifdef DEBUG_FILES
350     printf("xmlPythonFileRead: %d\n", len);
351 #endif
352     file = (PyObject *) context;
353     if (file == NULL) return(-1);
354     ret = PyEval_CallMethod(file, (char *) "io_read", (char *) "(i)", len);
355     if (ret == NULL) {
356         printf("xmlPythonFileRead: result is NULL\n");
357         return(-1);
358     } else if (PyBytes_Check(ret)) {
359         lenread = PyBytes_Size(ret);
360         data = PyBytes_AsString(ret);
361 #ifdef PyUnicode_Check
362     } else if PyUnicode_Check (ret) {
363 #if PY_VERSION_HEX >= 0x03030000
364         Py_ssize_t size;
365         const char *tmp;
366
367         /* tmp doesn't need to be deallocated */
368         tmp = PyUnicode_AsUTF8AndSize(ret, &size);
369
370         lenread = (int) size;
371         data = (char *) tmp;
372 #else
373         PyObject *b;
374         b = PyUnicode_AsUTF8String(ret);
375         if (b == NULL) {
376             printf("xmlPythonFileRead: failed to convert to UTF-8\n");
377             return(-1);
378         }
379         lenread = PyBytes_Size(b);
380         data = PyBytes_AsString(b);
381         Py_DECREF(b);
382 #endif
383 #endif
384     } else {
385         printf("xmlPythonFileRead: result is not a String\n");
386         Py_DECREF(ret);
387         return(-1);
388     }
389     if (lenread > len)
390         memcpy(buffer, data, len);
391     else
392         memcpy(buffer, data, lenread);
393     Py_DECREF(ret);
394     return(lenread);
395 }
396
397 /**
398  * xmlFileWrite:
399  * @context:  the I/O context
400  * @buffer:  where to drop data
401  * @len:  number of bytes to write
402  *
403  * Write @len bytes from @buffer to the I/O channel.
404  *
405  * Returns the number of bytes written
406  */
407 static int
408 xmlPythonFileWrite (void * context, const char * buffer, int len) {
409     PyObject *file;
410     PyObject *string;
411     PyObject *ret = NULL;
412     int written = -1;
413
414 #ifdef DEBUG_FILES
415     printf("xmlPythonFileWrite: %d\n", len);
416 #endif
417     file = (PyObject *) context;
418     if (file == NULL) return(-1);
419     string = PY_IMPORT_STRING_SIZE(buffer, len);
420     if (string == NULL) return(-1);
421     if (PyObject_HasAttrString(file, (char *) "io_write")) {
422         ret = PyEval_CallMethod(file, (char *) "io_write", (char *) "(O)",
423                                 string);
424     } else if (PyObject_HasAttrString(file, (char *) "write")) {
425         ret = PyEval_CallMethod(file, (char *) "write", (char *) "(O)",
426                                 string);
427     }
428     Py_DECREF(string);
429     if (ret == NULL) {
430         printf("xmlPythonFileWrite: result is NULL\n");
431         return(-1);
432     } else if (PyLong_Check(ret)) {
433         written = (int) PyLong_AsLong(ret);
434         Py_DECREF(ret);
435     } else if (ret == Py_None) {
436         written = len;
437         Py_DECREF(ret);
438     } else {
439         printf("xmlPythonFileWrite: result is not an Int nor None\n");
440         Py_DECREF(ret);
441     }
442     return(written);
443 }
444
445 /**
446  * xmlPythonFileClose:
447  * @context:  the I/O context
448  *
449  * Close an I/O channel
450  */
451 static int
452 xmlPythonFileClose (void * context) {
453     PyObject *file, *ret = NULL;
454
455 #ifdef DEBUG_FILES
456     printf("xmlPythonFileClose\n");
457 #endif
458     file = (PyObject *) context;
459     if (file == NULL) return(-1);
460     if (PyObject_HasAttrString(file, (char *) "io_close")) {
461         ret = PyEval_CallMethod(file, (char *) "io_close", (char *) "()");
462     } else if (PyObject_HasAttrString(file, (char *) "flush")) {
463         ret = PyEval_CallMethod(file, (char *) "flush", (char *) "()");
464     }
465     if (ret != NULL) {
466         Py_DECREF(ret);
467     }
468     return(0);
469 }
470
471 #ifdef LIBXML_OUTPUT_ENABLED
472 /**
473  * xmlOutputBufferCreatePythonFile:
474  * @file:  a PyFile_Type
475  * @encoder:  the encoding converter or NULL
476  *
477  * Create a buffered output for the progressive saving to a PyFile_Type
478  * buffered C I/O
479  *
480  * Returns the new parser output or NULL
481  */
482 static xmlOutputBufferPtr
483 xmlOutputBufferCreatePythonFile(PyObject *file, 
484                                 xmlCharEncodingHandlerPtr encoder) {
485     xmlOutputBufferPtr ret;
486
487     if (file == NULL) return(NULL);
488
489     ret = xmlAllocOutputBuffer(encoder);
490     if (ret != NULL) {
491         ret->context = file;
492         /* Py_INCREF(file); */
493         ret->writecallback = xmlPythonFileWrite;
494         ret->closecallback = xmlPythonFileClose;
495     }
496
497     return(ret);
498 }
499
500 PyObject *
501 libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
502     PyObject *py_retval;
503     PyObject *file;
504     xmlChar  *encoding;
505     xmlCharEncodingHandlerPtr handler = NULL;
506     xmlOutputBufferPtr buffer;
507
508
509     if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",
510                 &file, &encoding))
511         return(NULL);
512     if ((encoding != NULL) && (encoding[0] != 0)) {
513         handler = xmlFindCharEncodingHandler((const char *) encoding);
514     }
515     buffer = xmlOutputBufferCreatePythonFile(file, handler);
516     if (buffer == NULL)
517         printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");
518     py_retval = libxml_xmlOutputBufferPtrWrap(buffer);
519     return(py_retval);
520 }
521
522 /**
523  * libxml_outputBufferGetPythonFile:
524  * @buffer:  the I/O buffer
525  *
526  * read the Python I/O from the CObject
527  *
528  * Returns the new parser output or NULL
529  */
530 static PyObject *
531 libxml_outputBufferGetPythonFile(ATTRIBUTE_UNUSED PyObject *self,
532                                     PyObject *args) {
533     PyObject *buffer;
534     PyObject *file;
535     xmlOutputBufferPtr obj;
536
537     if (!PyArg_ParseTuple(args, (char *)"O:outputBufferGetPythonFile",
538                           &buffer))
539         return(NULL);
540
541     obj = PyoutputBuffer_Get(buffer);
542     if (obj == NULL) {
543         fprintf(stderr,
544                 "outputBufferGetPythonFile: obj == NULL\n");
545         Py_INCREF(Py_None);
546         return(Py_None);
547     }
548     if (obj->closecallback != xmlPythonFileClose) {
549         fprintf(stderr,
550                 "outputBufferGetPythonFile: not a python file wrapper\n");
551         Py_INCREF(Py_None);
552         return(Py_None);
553     }
554     file = (PyObject *) obj->context;
555     if (file == NULL) {
556         Py_INCREF(Py_None);
557         return(Py_None);
558     }
559     Py_INCREF(file);
560     return(file);
561 }
562
563 static PyObject *
564 libxml_xmlOutputBufferClose(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
565     PyObject *py_retval;
566     int c_retval;
567     xmlOutputBufferPtr out;
568     PyObject *pyobj_out;
569
570     if (!PyArg_ParseTuple(args, (char *)"O:xmlOutputBufferClose", &pyobj_out))
571         return(NULL);
572     out = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_out);
573     /* Buffer may already have been destroyed elsewhere. This is harmless. */
574     if (out == NULL) {
575         Py_INCREF(Py_None);
576         return(Py_None);
577     }
578
579     c_retval = xmlOutputBufferClose(out);
580     py_retval = libxml_intWrap((int) c_retval);
581     return(py_retval);
582 }
583
584 static PyObject *
585 libxml_xmlOutputBufferFlush(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
586     PyObject *py_retval;
587     int c_retval;
588     xmlOutputBufferPtr out;
589     PyObject *pyobj_out;
590
591     if (!PyArg_ParseTuple(args, (char *)"O:xmlOutputBufferFlush", &pyobj_out))
592         return(NULL);
593     out = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_out);
594
595     c_retval = xmlOutputBufferFlush(out);
596     py_retval = libxml_intWrap((int) c_retval);
597     return(py_retval);
598 }
599
600 static PyObject *
601 libxml_xmlSaveFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
602     PyObject *py_retval;
603     int c_retval;
604     xmlOutputBufferPtr buf;
605     PyObject *pyobj_buf;
606     xmlDocPtr cur;
607     PyObject *pyobj_cur;
608     char * encoding;
609
610     if (!PyArg_ParseTuple(args, (char *)"OOz:xmlSaveFileTo", &pyobj_buf, &pyobj_cur, &encoding))
611         return(NULL);
612     buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf);
613     cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur);
614
615     c_retval = xmlSaveFileTo(buf, cur, encoding);
616         /* xmlSaveTo() freed the memory pointed to by buf, so record that in the
617          * Python object. */
618     ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL;
619     py_retval = libxml_intWrap((int) c_retval);
620     return(py_retval);
621 }
622
623 static PyObject *
624 libxml_xmlSaveFormatFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
625     PyObject *py_retval;
626     int c_retval;
627     xmlOutputBufferPtr buf;
628     PyObject *pyobj_buf;
629     xmlDocPtr cur;
630     PyObject *pyobj_cur;
631     char * encoding;
632     int format;
633
634     if (!PyArg_ParseTuple(args, (char *)"OOzi:xmlSaveFormatFileTo", &pyobj_buf, &pyobj_cur, &encoding, &format))
635         return(NULL);
636     buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf);
637     cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur);
638
639     c_retval = xmlSaveFormatFileTo(buf, cur, encoding, format);
640         /* xmlSaveFormatFileTo() freed the memory pointed to by buf, so record that
641          * in the Python object */
642         ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL;
643     py_retval = libxml_intWrap((int) c_retval);
644     return(py_retval);
645 }
646 #endif /* LIBXML_OUTPUT_ENABLED */
647
648
649 /**
650  * xmlParserInputBufferCreatePythonFile:
651  * @file:  a PyFile_Type
652  * @encoder:  the encoding converter or NULL
653  *
654  * Create a buffered output for the progressive saving to a PyFile_Type
655  * buffered C I/O
656  *
657  * Returns the new parser output or NULL
658  */
659 static xmlParserInputBufferPtr
660 xmlParserInputBufferCreatePythonFile(PyObject *file, 
661                                 xmlCharEncoding encoding) {
662     xmlParserInputBufferPtr ret;
663
664     if (file == NULL) return(NULL);
665
666     ret = xmlAllocParserInputBuffer(encoding);
667     if (ret != NULL) {
668         ret->context = file;
669         /* Py_INCREF(file); */
670         ret->readcallback = xmlPythonFileRead;
671         ret->closecallback = xmlPythonFileClose;
672     }
673
674     return(ret);
675 }
676
677 PyObject *
678 libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
679     PyObject *py_retval;
680     PyObject *file;
681     xmlChar  *encoding;
682     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
683     xmlParserInputBufferPtr buffer;
684
685
686     if (!PyArg_ParseTuple(args, (char *)"Oz:xmlParserInputBufferCreate",
687                 &file, &encoding))
688         return(NULL);
689     if ((encoding != NULL) && (encoding[0] != 0)) {
690         enc = xmlParseCharEncoding((const char *) encoding);
691     }
692     buffer = xmlParserInputBufferCreatePythonFile(file, enc);
693     if (buffer == NULL)
694         printf("libxml_xmlParserInputBufferCreate: buffer == NULL\n");
695     py_retval = libxml_xmlParserInputBufferPtrWrap(buffer);
696     return(py_retval);
697 }
698
699 /************************************************************************
700  *                                                                      *
701  *              Providing the resolver at the Python level              *
702  *                                                                      *
703  ************************************************************************/
704
705 static xmlExternalEntityLoader defaultExternalEntityLoader = NULL;
706 static PyObject *pythonExternalEntityLoaderObjext;
707
708 static xmlParserInputPtr
709 pythonExternalEntityLoader(const char *URL, const char *ID,
710                            xmlParserCtxtPtr ctxt) {
711     xmlParserInputPtr result = NULL;
712     if (pythonExternalEntityLoaderObjext != NULL) {
713         PyObject *ret;
714         PyObject *ctxtobj;
715
716         ctxtobj = libxml_xmlParserCtxtPtrWrap(ctxt);
717 #ifdef DEBUG_LOADER
718         printf("pythonExternalEntityLoader: ready to call\n");
719 #endif
720
721         ret = PyObject_CallFunction(pythonExternalEntityLoaderObjext,
722                       (char *) "(ssO)", URL, ID, ctxtobj);
723         Py_XDECREF(ctxtobj);
724 #ifdef DEBUG_LOADER
725         printf("pythonExternalEntityLoader: result ");
726         PyObject_Print(ret, stdout, 0);
727         printf("\n");
728 #endif
729
730         if (ret != NULL) {
731             if (PyObject_HasAttrString(ret, (char *) "read")) {
732                 xmlParserInputBufferPtr buf;
733
734                 buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
735                 if (buf != NULL) {
736                     buf->context = ret;
737                     buf->readcallback = xmlPythonFileReadRaw;
738                     buf->closecallback = xmlPythonFileCloseRaw;
739                     result = xmlNewIOInputStream(ctxt, buf,
740                                                  XML_CHAR_ENCODING_NONE);
741                 }
742 #if 0
743             } else {
744                 if (URL != NULL)
745                     printf("pythonExternalEntityLoader: can't read %s\n",
746                            URL);
747 #endif
748             }
749             if (result == NULL) {
750                 Py_DECREF(ret);
751             } else if (URL != NULL) {
752                 result->filename = (char *) xmlStrdup((const xmlChar *)URL);
753                 result->directory = xmlParserGetDirectory((const char *) URL);
754             }
755         }
756     }
757     if ((result == NULL) && (defaultExternalEntityLoader != NULL)) {
758         result = defaultExternalEntityLoader(URL, ID, ctxt);
759     }
760     return(result);
761 }
762
763 PyObject *
764 libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
765     PyObject *py_retval;
766     PyObject *loader;
767
768     if (!PyArg_ParseTuple(args, (char *)"O:libxml_xmlSetEntityLoader",
769                 &loader))
770         return(NULL);
771
772     if (!PyCallable_Check(loader)) {
773         PyErr_SetString(PyExc_ValueError, "entity loader is not callable");
774         return(NULL);
775     }
776
777 #ifdef DEBUG_LOADER
778     printf("libxml_xmlSetEntityLoader\n");
779 #endif
780     if (defaultExternalEntityLoader == NULL) 
781         defaultExternalEntityLoader = xmlGetExternalEntityLoader();
782
783     Py_XDECREF(pythonExternalEntityLoaderObjext);
784     pythonExternalEntityLoaderObjext = loader;
785     Py_XINCREF(pythonExternalEntityLoaderObjext);
786     xmlSetExternalEntityLoader(pythonExternalEntityLoader);
787
788     py_retval = PyLong_FromLong(0);
789     return(py_retval);
790 }
791
792 /************************************************************************
793  *                                                                      *
794  *              Input callback registration                             *
795  *                                                                      *
796  ************************************************************************/
797 static PyObject *pythonInputOpenCallbackObject;
798 static int pythonInputCallbackID = -1;
799
800 static int
801 pythonInputMatchCallback(ATTRIBUTE_UNUSED const char *URI)
802 {
803     /* Always return success, real decision whether URI is supported will be
804      * made in open callback.  */
805     return 1;
806 }
807
808 static void *
809 pythonInputOpenCallback(const char *URI)
810 {
811     PyObject *ret;
812
813     ret = PyObject_CallFunction(pythonInputOpenCallbackObject,
814             (char *)"s", URI);
815     if (ret == Py_None) {
816         Py_DECREF(Py_None);
817         return NULL;
818     }
819     return ret;
820 }
821
822 PyObject *
823 libxml_xmlRegisterInputCallback(ATTRIBUTE_UNUSED PyObject *self,
824                                 PyObject *args) {
825     PyObject *cb;
826
827     if (!PyArg_ParseTuple(args,
828                 (const char *)"O:libxml_xmlRegisterInputCallback", &cb))
829         return(NULL);
830
831     if (!PyCallable_Check(cb)) {
832         PyErr_SetString(PyExc_ValueError, "input callback is not callable");
833         return(NULL);
834     }
835
836     /* Python module registers a single callback and manages the list of
837      * all callbacks internally. This is necessitated by xmlInputMatchCallback
838      * API, which does not allow for passing of data objects to discriminate
839      * different Python methods.  */
840     if (pythonInputCallbackID == -1) {
841         pythonInputCallbackID = xmlRegisterInputCallbacks(
842                 pythonInputMatchCallback, pythonInputOpenCallback,
843                 xmlPythonFileReadRaw, xmlPythonFileCloseRaw);
844         if (pythonInputCallbackID == -1)
845             return PyErr_NoMemory();
846         pythonInputOpenCallbackObject = cb;
847         Py_INCREF(pythonInputOpenCallbackObject);
848     }
849
850     Py_INCREF(Py_None);
851     return(Py_None);
852 }
853
854 PyObject *
855 libxml_xmlUnregisterInputCallback(ATTRIBUTE_UNUSED PyObject *self,
856                                 ATTRIBUTE_UNUSED PyObject *args) {
857     int ret;
858
859     ret = xmlPopInputCallbacks();
860     if (pythonInputCallbackID != -1) {
861         /* Assert that the right input callback was popped. libxml's API does not
862          * allow removal by ID, so all that could be done is an assert.  */
863         if (pythonInputCallbackID == ret) {
864             pythonInputCallbackID = -1;
865             Py_DECREF(pythonInputOpenCallbackObject);
866             pythonInputOpenCallbackObject = NULL;
867         } else {
868             PyErr_SetString(PyExc_AssertionError, "popped non-python input callback");
869             return(NULL);
870         }
871     } else if (ret == -1) {
872         /* No more callbacks to pop */
873         PyErr_SetString(PyExc_IndexError, "no input callbacks to pop");
874         return(NULL);
875     }
876
877     Py_INCREF(Py_None);
878     return(Py_None);
879 }
880
881 /************************************************************************
882  *                                                                      *
883  *              Handling SAX/xmllib/sgmlop callback interfaces          *
884  *                                                                      *
885  ************************************************************************/
886
887 static void
888 pythonStartElement(void *user_data, const xmlChar * name,
889                    const xmlChar ** attrs)
890 {
891     int i;
892     PyObject *handler;
893     PyObject *dict;
894     PyObject *attrname;
895     PyObject *attrvalue;
896     PyObject *result = NULL;
897     int type = 0;
898
899 #ifdef DEBUG_SAX
900     printf("pythonStartElement(%s) called\n", name);
901 #endif
902     handler = (PyObject *) user_data;
903     if (PyObject_HasAttrString(handler, (char *) "startElement"))
904         type = 1;
905     else if (PyObject_HasAttrString(handler, (char *) "start"))
906         type = 2;
907     if (type != 0) {
908         /*
909          * the xmllib interface always generate a dictionnary,
910          * possibly empty
911          */
912         if ((attrs == NULL) && (type == 1)) {
913             Py_XINCREF(Py_None);
914             dict = Py_None;
915         } else if (attrs == NULL) {
916             dict = PyDict_New();
917         } else {
918             dict = PyDict_New();
919             for (i = 0; attrs[i] != NULL; i++) {
920                 attrname = PY_IMPORT_STRING((char *) attrs[i]);
921                 i++;
922                 if (attrs[i] != NULL) {
923                     attrvalue = PY_IMPORT_STRING((char *) attrs[i]);
924                 } else {
925                     Py_XINCREF(Py_None);
926                     attrvalue = Py_None;
927                 }
928                 PyDict_SetItem(dict, attrname, attrvalue);
929                 Py_DECREF(attrname);
930                 Py_DECREF(attrvalue);
931             }
932         }
933
934         if (type == 1)
935             result = PyObject_CallMethod(handler, (char *) "startElement",
936                                          (char *) "sO", name, dict);
937         else if (type == 2)
938             result = PyObject_CallMethod(handler, (char *) "start",
939                                          (char *) "sO", name, dict);
940         if (PyErr_Occurred())
941             PyErr_Print();
942         Py_XDECREF(dict);
943         Py_XDECREF(result);
944     }
945 }
946
947 static void
948 pythonStartDocument(void *user_data)
949 {
950     PyObject *handler;
951     PyObject *result;
952
953 #ifdef DEBUG_SAX
954     printf("pythonStartDocument() called\n");
955 #endif
956     handler = (PyObject *) user_data;
957     if (PyObject_HasAttrString(handler, (char *) "startDocument")) {
958         result =
959             PyObject_CallMethod(handler, (char *) "startDocument", NULL);
960         if (PyErr_Occurred())
961             PyErr_Print();
962         Py_XDECREF(result);
963     }
964 }
965
966 static void
967 pythonEndDocument(void *user_data)
968 {
969     PyObject *handler;
970     PyObject *result;
971
972 #ifdef DEBUG_SAX
973     printf("pythonEndDocument() called\n");
974 #endif
975     handler = (PyObject *) user_data;
976     if (PyObject_HasAttrString(handler, (char *) "endDocument")) {
977         result =
978             PyObject_CallMethod(handler, (char *) "endDocument", NULL);
979         if (PyErr_Occurred())
980             PyErr_Print();
981         Py_XDECREF(result);
982     }
983     /*
984      * The reference to the handler is released there
985      */
986     Py_XDECREF(handler);
987 }
988
989 static void
990 pythonEndElement(void *user_data, const xmlChar * name)
991 {
992     PyObject *handler;
993     PyObject *result;
994
995 #ifdef DEBUG_SAX
996     printf("pythonEndElement(%s) called\n", name);
997 #endif
998     handler = (PyObject *) user_data;
999     if (PyObject_HasAttrString(handler, (char *) "endElement")) {
1000         result = PyObject_CallMethod(handler, (char *) "endElement",
1001                                      (char *) "s", name);
1002         if (PyErr_Occurred())
1003             PyErr_Print();
1004         Py_XDECREF(result);
1005     } else if (PyObject_HasAttrString(handler, (char *) "end")) {
1006         result = PyObject_CallMethod(handler, (char *) "end",
1007                                      (char *) "s", name);
1008         if (PyErr_Occurred())
1009             PyErr_Print();
1010         Py_XDECREF(result);
1011     }
1012 }
1013
1014 static void
1015 pythonReference(void *user_data, const xmlChar * name)
1016 {
1017     PyObject *handler;
1018     PyObject *result;
1019
1020 #ifdef DEBUG_SAX
1021     printf("pythonReference(%s) called\n", name);
1022 #endif
1023     handler = (PyObject *) user_data;
1024     if (PyObject_HasAttrString(handler, (char *) "reference")) {
1025         result = PyObject_CallMethod(handler, (char *) "reference",
1026                                      (char *) "s", name);
1027         if (PyErr_Occurred())
1028             PyErr_Print();
1029         Py_XDECREF(result);
1030     }
1031 }
1032
1033 static void
1034 pythonCharacters(void *user_data, const xmlChar * ch, int len)
1035 {
1036     PyObject *handler;
1037     PyObject *result = NULL;
1038     int type = 0;
1039
1040 #ifdef DEBUG_SAX
1041     printf("pythonCharacters(%s, %d) called\n", ch, len);
1042 #endif
1043     handler = (PyObject *) user_data;
1044     if (PyObject_HasAttrString(handler, (char *) "characters"))
1045         type = 1;
1046     else if (PyObject_HasAttrString(handler, (char *) "data"))
1047         type = 2;
1048     if (type != 0) {
1049         if (type == 1)
1050             result = PyObject_CallMethod(handler, (char *) "characters",
1051                                          (char *) "s#", ch, len);
1052         else if (type == 2)
1053             result = PyObject_CallMethod(handler, (char *) "data",
1054                                          (char *) "s#", ch, len);
1055         if (PyErr_Occurred())
1056             PyErr_Print();
1057         Py_XDECREF(result);
1058     }
1059 }
1060
1061 static void
1062 pythonIgnorableWhitespace(void *user_data, const xmlChar * ch, int len)
1063 {
1064     PyObject *handler;
1065     PyObject *result = NULL;
1066     int type = 0;
1067
1068 #ifdef DEBUG_SAX
1069     printf("pythonIgnorableWhitespace(%s, %d) called\n", ch, len);
1070 #endif
1071     handler = (PyObject *) user_data;
1072     if (PyObject_HasAttrString(handler, (char *) "ignorableWhitespace"))
1073         type = 1;
1074     else if (PyObject_HasAttrString(handler, (char *) "data"))
1075         type = 2;
1076     if (type != 0) {
1077         if (type == 1)
1078             result =
1079                 PyObject_CallMethod(handler,
1080                                     (char *) "ignorableWhitespace",
1081                                     (char *) "s#", ch, len);
1082         else if (type == 2)
1083             result =
1084                 PyObject_CallMethod(handler, (char *) "data",
1085                                     (char *) "s#", ch, len);
1086         Py_XDECREF(result);
1087     }
1088 }
1089
1090 static void
1091 pythonProcessingInstruction(void *user_data,
1092                             const xmlChar * target, const xmlChar * data)
1093 {
1094     PyObject *handler;
1095     PyObject *result;
1096
1097 #ifdef DEBUG_SAX
1098     printf("pythonProcessingInstruction(%s, %s) called\n", target, data);
1099 #endif
1100     handler = (PyObject *) user_data;
1101     if (PyObject_HasAttrString(handler, (char *) "processingInstruction")) {
1102         result = PyObject_CallMethod(handler, (char *)
1103                                      "processingInstruction",
1104                                      (char *) "ss", target, data);
1105         Py_XDECREF(result);
1106     }
1107 }
1108
1109 static void
1110 pythonComment(void *user_data, const xmlChar * value)
1111 {
1112     PyObject *handler;
1113     PyObject *result;
1114
1115 #ifdef DEBUG_SAX
1116     printf("pythonComment(%s) called\n", value);
1117 #endif
1118     handler = (PyObject *) user_data;
1119     if (PyObject_HasAttrString(handler, (char *) "comment")) {
1120         result =
1121             PyObject_CallMethod(handler, (char *) "comment", (char *) "s",
1122                                 value);
1123         if (PyErr_Occurred())
1124             PyErr_Print();
1125         Py_XDECREF(result);
1126     }
1127 }
1128
1129 static void
1130 pythonWarning(void *user_data, const char *msg, ...)
1131 {
1132     PyObject *handler;
1133     PyObject *result;
1134     va_list args;
1135     char buf[1024];
1136
1137 #ifdef DEBUG_SAX
1138     printf("pythonWarning(%s) called\n", msg);
1139 #endif
1140     handler = (PyObject *) user_data;
1141     if (PyObject_HasAttrString(handler, (char *) "warning")) {
1142         va_start(args, msg);
1143         vsnprintf(buf, 1023, msg, args);
1144         va_end(args);
1145         buf[1023] = 0;
1146         result =
1147             PyObject_CallMethod(handler, (char *) "warning", (char *) "s",
1148                                 buf);
1149         if (PyErr_Occurred())
1150             PyErr_Print();
1151         Py_XDECREF(result);
1152     }
1153 }
1154
1155 static void
1156 pythonError(void *user_data, const char *msg, ...)
1157 {
1158     PyObject *handler;
1159     PyObject *result;
1160     va_list args;
1161     char buf[1024];
1162
1163 #ifdef DEBUG_SAX
1164     printf("pythonError(%s) called\n", msg);
1165 #endif
1166     handler = (PyObject *) user_data;
1167     if (PyObject_HasAttrString(handler, (char *) "error")) {
1168         va_start(args, msg);
1169         vsnprintf(buf, 1023, msg, args);
1170         va_end(args);
1171         buf[1023] = 0;
1172         result =
1173             PyObject_CallMethod(handler, (char *) "error", (char *) "s",
1174                                 buf);
1175         if (PyErr_Occurred())
1176             PyErr_Print();
1177         Py_XDECREF(result);
1178     }
1179 }
1180
1181 static void
1182 pythonFatalError(void *user_data, const char *msg, ...)
1183 {
1184     PyObject *handler;
1185     PyObject *result;
1186     va_list args;
1187     char buf[1024];
1188
1189 #ifdef DEBUG_SAX
1190     printf("pythonFatalError(%s) called\n", msg);
1191 #endif
1192     handler = (PyObject *) user_data;
1193     if (PyObject_HasAttrString(handler, (char *) "fatalError")) {
1194         va_start(args, msg);
1195         vsnprintf(buf, 1023, msg, args);
1196         va_end(args);
1197         buf[1023] = 0;
1198         result =
1199             PyObject_CallMethod(handler, (char *) "fatalError",
1200                                 (char *) "s", buf);
1201         if (PyErr_Occurred())
1202             PyErr_Print();
1203         Py_XDECREF(result);
1204     }
1205 }
1206
1207 static void
1208 pythonCdataBlock(void *user_data, const xmlChar * ch, int len)
1209 {
1210     PyObject *handler;
1211     PyObject *result = NULL;
1212     int type = 0;
1213
1214 #ifdef DEBUG_SAX
1215     printf("pythonCdataBlock(%s, %d) called\n", ch, len);
1216 #endif
1217     handler = (PyObject *) user_data;
1218     if (PyObject_HasAttrString(handler, (char *) "cdataBlock"))
1219         type = 1;
1220     else if (PyObject_HasAttrString(handler, (char *) "cdata"))
1221         type = 2;
1222     if (type != 0) {
1223         if (type == 1)
1224             result =
1225                 PyObject_CallMethod(handler, (char *) "cdataBlock",
1226                                     (char *) "s#", ch, len);
1227         else if (type == 2)
1228             result =
1229                 PyObject_CallMethod(handler, (char *) "cdata",
1230                                     (char *) "s#", ch, len);
1231         if (PyErr_Occurred())
1232             PyErr_Print();
1233         Py_XDECREF(result);
1234     }
1235 }
1236
1237 static void
1238 pythonExternalSubset(void *user_data,
1239                      const xmlChar * name,
1240                      const xmlChar * externalID, const xmlChar * systemID)
1241 {
1242     PyObject *handler;
1243     PyObject *result;
1244
1245 #ifdef DEBUG_SAX
1246     printf("pythonExternalSubset(%s, %s, %s) called\n",
1247            name, externalID, systemID);
1248 #endif
1249     handler = (PyObject *) user_data;
1250     if (PyObject_HasAttrString(handler, (char *) "externalSubset")) {
1251         result =
1252             PyObject_CallMethod(handler, (char *) "externalSubset",
1253                                 (char *) "sss", name, externalID,
1254                                 systemID);
1255         Py_XDECREF(result);
1256     }
1257 }
1258
1259 static void
1260 pythonEntityDecl(void *user_data,
1261                  const xmlChar * name,
1262                  int type,
1263                  const xmlChar * publicId,
1264                  const xmlChar * systemId, xmlChar * content)
1265 {
1266     PyObject *handler;
1267     PyObject *result;
1268
1269     handler = (PyObject *) user_data;
1270     if (PyObject_HasAttrString(handler, (char *) "entityDecl")) {
1271         result = PyObject_CallMethod(handler, (char *) "entityDecl",
1272                                      (char *) "sisss", name, type,
1273                                      publicId, systemId, content);
1274         if (PyErr_Occurred())
1275             PyErr_Print();
1276         Py_XDECREF(result);
1277     }
1278 }
1279
1280
1281
1282 static void
1283
1284 pythonNotationDecl(void *user_data,
1285                    const xmlChar * name,
1286                    const xmlChar * publicId, const xmlChar * systemId)
1287 {
1288     PyObject *handler;
1289     PyObject *result;
1290
1291     handler = (PyObject *) user_data;
1292     if (PyObject_HasAttrString(handler, (char *) "notationDecl")) {
1293         result = PyObject_CallMethod(handler, (char *) "notationDecl",
1294                                      (char *) "sss", name, publicId,
1295                                      systemId);
1296         if (PyErr_Occurred())
1297             PyErr_Print();
1298         Py_XDECREF(result);
1299     }
1300 }
1301
1302 static void
1303 pythonAttributeDecl(void *user_data,
1304                     const xmlChar * elem,
1305                     const xmlChar * name,
1306                     int type,
1307                     int def,
1308                     const xmlChar * defaultValue, xmlEnumerationPtr tree)
1309 {
1310     PyObject *handler;
1311     PyObject *nameList;
1312     PyObject *newName;
1313     xmlEnumerationPtr node;
1314     PyObject *result;
1315     int count;
1316
1317     handler = (PyObject *) user_data;
1318     if (PyObject_HasAttrString(handler, (char *) "attributeDecl")) {
1319         count = 0;
1320         for (node = tree; node != NULL; node = node->next) {
1321             count++;
1322         }
1323         nameList = PyList_New(count);
1324         count = 0;
1325         for (node = tree; node != NULL; node = node->next) {
1326             newName = PY_IMPORT_STRING((char *) node->name);
1327             PyList_SetItem(nameList, count, newName);
1328             Py_DECREF(newName);
1329             count++;
1330         }
1331         result = PyObject_CallMethod(handler, (char *) "attributeDecl",
1332                                      (char *) "ssiisO", elem, name, type,
1333                                      def, defaultValue, nameList);
1334         if (PyErr_Occurred())
1335             PyErr_Print();
1336         Py_XDECREF(nameList);
1337         Py_XDECREF(result);
1338     }
1339 }
1340
1341 static void
1342 pythonElementDecl(void *user_data,
1343                   const xmlChar * name,
1344                   int type, ATTRIBUTE_UNUSED xmlElementContentPtr content)
1345 {
1346     PyObject *handler;
1347     PyObject *obj;
1348     PyObject *result;
1349
1350     handler = (PyObject *) user_data;
1351     if (PyObject_HasAttrString(handler, (char *) "elementDecl")) {
1352         /* TODO: wrap in an elementContent object */
1353         printf
1354             ("pythonElementDecl: xmlElementContentPtr wrapper missing !\n");
1355         obj = Py_None;
1356         /* Py_XINCREF(Py_None); isn't the reference just borrowed ??? */
1357         result = PyObject_CallMethod(handler, (char *) "elementDecl",
1358                                      (char *) "siO", name, type, obj);
1359         if (PyErr_Occurred())
1360             PyErr_Print();
1361         Py_XDECREF(result);
1362     }
1363 }
1364
1365 static void
1366 pythonUnparsedEntityDecl(void *user_data,
1367                          const xmlChar * name,
1368                          const xmlChar * publicId,
1369                          const xmlChar * systemId,
1370                          const xmlChar * notationName)
1371 {
1372     PyObject *handler;
1373     PyObject *result;
1374
1375     handler = (PyObject *) user_data;
1376     if (PyObject_HasAttrString(handler, (char *) "unparsedEntityDecl")) {
1377         result =
1378             PyObject_CallMethod(handler, (char *) "unparsedEntityDecl",
1379                                 (char *) "ssss", name, publicId, systemId,
1380                                 notationName);
1381         if (PyErr_Occurred())
1382             PyErr_Print();
1383         Py_XDECREF(result);
1384     }
1385 }
1386
1387 static void
1388 pythonInternalSubset(void *user_data, const xmlChar * name,
1389                      const xmlChar * ExternalID, const xmlChar * SystemID)
1390 {
1391     PyObject *handler;
1392     PyObject *result;
1393
1394 #ifdef DEBUG_SAX
1395     printf("pythonInternalSubset(%s, %s, %s) called\n",
1396            name, ExternalID, SystemID);
1397 #endif
1398     handler = (PyObject *) user_data;
1399     if (PyObject_HasAttrString(handler, (char *) "internalSubset")) {
1400         result = PyObject_CallMethod(handler, (char *) "internalSubset",
1401                                      (char *) "sss", name, ExternalID,
1402                                      SystemID);
1403         if (PyErr_Occurred())
1404             PyErr_Print();
1405         Py_XDECREF(result);
1406     }
1407 }
1408
1409 static xmlSAXHandler pythonSaxHandler = {
1410     pythonInternalSubset,
1411     NULL,                       /* TODO pythonIsStandalone, */
1412     NULL,                       /* TODO pythonHasInternalSubset, */
1413     NULL,                       /* TODO pythonHasExternalSubset, */
1414     NULL,                       /* TODO pythonResolveEntity, */
1415     NULL,                       /* TODO pythonGetEntity, */
1416     pythonEntityDecl,
1417     pythonNotationDecl,
1418     pythonAttributeDecl,
1419     pythonElementDecl,
1420     pythonUnparsedEntityDecl,
1421     NULL,                       /* OBSOLETED pythonSetDocumentLocator, */
1422     pythonStartDocument,
1423     pythonEndDocument,
1424     pythonStartElement,
1425     pythonEndElement,
1426     pythonReference,
1427     pythonCharacters,
1428     pythonIgnorableWhitespace,
1429     pythonProcessingInstruction,
1430     pythonComment,
1431     pythonWarning,
1432     pythonError,
1433     pythonFatalError,
1434     NULL,                       /* TODO pythonGetParameterEntity, */
1435     pythonCdataBlock,
1436     pythonExternalSubset,
1437     1,
1438     NULL,                       /* TODO mograte to SAX2 */
1439     NULL,
1440     NULL,
1441     NULL
1442 };
1443
1444 /************************************************************************
1445  *                                                                      *
1446  *              Handling of specific parser context                     *
1447  *                                                                      *
1448  ************************************************************************/
1449
1450 PyObject *
1451 libxml_xmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1452                            PyObject * args)
1453 {
1454     const char *chunk;
1455     int size;
1456     const char *URI;
1457     PyObject *pyobj_SAX = NULL;
1458     xmlSAXHandlerPtr SAX = NULL;
1459     xmlParserCtxtPtr ret;
1460     PyObject *pyret;
1461
1462     if (!PyArg_ParseTuple
1463         (args, (char *) "Oziz:xmlCreatePushParser", &pyobj_SAX, &chunk,
1464          &size, &URI))
1465         return (NULL);
1466
1467 #ifdef DEBUG
1468     printf("libxml_xmlCreatePushParser(%p, %s, %d, %s) called\n",
1469            pyobj_SAX, chunk, size, URI);
1470 #endif
1471     if (pyobj_SAX != Py_None) {
1472         SAX = &pythonSaxHandler;
1473         Py_INCREF(pyobj_SAX);
1474         /* The reference is released in pythonEndDocument() */
1475     }
1476     ret = xmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI);
1477     pyret = libxml_xmlParserCtxtPtrWrap(ret);
1478     return (pyret);
1479 }
1480
1481 PyObject *
1482 libxml_htmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1483                             PyObject * args)
1484 {
1485 #ifdef LIBXML_HTML_ENABLED
1486     const char *chunk;
1487     int size;
1488     const char *URI;
1489     PyObject *pyobj_SAX = NULL;
1490     xmlSAXHandlerPtr SAX = NULL;
1491     xmlParserCtxtPtr ret;
1492     PyObject *pyret;
1493
1494     if (!PyArg_ParseTuple
1495         (args, (char *) "Oziz:htmlCreatePushParser", &pyobj_SAX, &chunk,
1496          &size, &URI))
1497         return (NULL);
1498
1499 #ifdef DEBUG
1500     printf("libxml_htmlCreatePushParser(%p, %s, %d, %s) called\n",
1501            pyobj_SAX, chunk, size, URI);
1502 #endif
1503     if (pyobj_SAX != Py_None) {
1504         SAX = &pythonSaxHandler;
1505         Py_INCREF(pyobj_SAX);
1506         /* The reference is released in pythonEndDocument() */
1507     }
1508     ret = htmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI,
1509                                    XML_CHAR_ENCODING_NONE);
1510     pyret = libxml_xmlParserCtxtPtrWrap(ret);
1511     return (pyret);
1512 #else
1513     Py_INCREF(Py_None);
1514     return (Py_None);
1515 #endif /* LIBXML_HTML_ENABLED */
1516 }
1517
1518 PyObject *
1519 libxml_xmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1520 {
1521 #ifdef LIBXML_SAX1_ENABLED
1522     int recover;
1523     const char *URI;
1524     PyObject *pyobj_SAX = NULL;
1525     xmlSAXHandlerPtr SAX = NULL;
1526
1527     if (!PyArg_ParseTuple(args, (char *) "Osi:xmlSAXParseFile", &pyobj_SAX,
1528                           &URI, &recover))
1529         return (NULL);
1530
1531 #ifdef DEBUG
1532     printf("libxml_xmlSAXParseFile(%p, %s, %d) called\n",
1533            pyobj_SAX, URI, recover);
1534 #endif
1535     if (pyobj_SAX == Py_None) {
1536         Py_INCREF(Py_None);
1537         return (Py_None);
1538     }
1539     SAX = &pythonSaxHandler;
1540     Py_INCREF(pyobj_SAX);
1541     /* The reference is released in pythonEndDocument() */
1542     xmlSAXUserParseFile(SAX, pyobj_SAX, URI);
1543 #endif /* LIBXML_SAX1_ENABLED */
1544     Py_INCREF(Py_None);
1545     return (Py_None);
1546 }
1547
1548 PyObject *
1549 libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1550 {
1551 #ifdef LIBXML_HTML_ENABLED
1552     const char *URI;
1553     const char *encoding;
1554     PyObject *pyobj_SAX = NULL;
1555     xmlSAXHandlerPtr SAX = NULL;
1556
1557     if (!PyArg_ParseTuple
1558         (args, (char *) "Osz:htmlSAXParseFile", &pyobj_SAX, &URI,
1559          &encoding))
1560         return (NULL);
1561
1562 #ifdef DEBUG
1563     printf("libxml_htmlSAXParseFile(%p, %s, %s) called\n",
1564            pyobj_SAX, URI, encoding);
1565 #endif
1566     if (pyobj_SAX == Py_None) {
1567         Py_INCREF(Py_None);
1568         return (Py_None);
1569     }
1570     SAX = &pythonSaxHandler;
1571     Py_INCREF(pyobj_SAX);
1572     /* The reference is released in pythonEndDocument() */
1573     htmlSAXParseFile(URI, encoding, SAX, pyobj_SAX);
1574     Py_INCREF(Py_None);
1575     return (Py_None);
1576 #else
1577     Py_INCREF(Py_None);
1578     return (Py_None);
1579 #endif /* LIBXML_HTML_ENABLED */
1580 }
1581
1582 /************************************************************************
1583  *                                                                      *
1584  *                      Error message callback                          *
1585  *                                                                      *
1586  ************************************************************************/
1587
1588 static PyObject *libxml_xmlPythonErrorFuncHandler = NULL;
1589 static PyObject *libxml_xmlPythonErrorFuncCtxt = NULL;
1590
1591 /* helper to build a xmlMalloc'ed string from a format and va_list */
1592 /* 
1593  * disabled the loop, the repeated call to vsnprintf without reset of ap
1594  * in case the initial buffer was too small segfaulted on x86_64
1595  * we now directly vsnprintf on a large buffer.
1596  */
1597 static char *
1598 libxml_buildMessage(const char *msg, va_list ap)
1599 {
1600     int chars;
1601     char *str;
1602
1603     str = (char *) xmlMalloc(1000);
1604     if (str == NULL)
1605         return NULL;
1606
1607     chars = vsnprintf(str, 999, msg, ap);
1608     if (chars >= 998)
1609         str[999] = 0;
1610
1611     return str;
1612 }
1613
1614 static void
1615 libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
1616                            ...)
1617 {
1618     va_list ap;
1619     PyObject *list;
1620     PyObject *message;
1621     PyObject *result;
1622     char str[1000];
1623
1624 #ifdef DEBUG_ERROR
1625     printf("libxml_xmlErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
1626 #endif
1627
1628
1629     if (libxml_xmlPythonErrorFuncHandler == NULL) {
1630         va_start(ap, msg);
1631         vfprintf(stderr, msg, ap);
1632         va_end(ap);
1633     } else {
1634         va_start(ap, msg);
1635         if (vsnprintf(str, 999, msg, ap) >= 998)
1636             str[999] = 0;
1637         va_end(ap);
1638
1639         list = PyTuple_New(2);
1640         PyTuple_SetItem(list, 0, libxml_xmlPythonErrorFuncCtxt);
1641         Py_XINCREF(libxml_xmlPythonErrorFuncCtxt);
1642         message = libxml_charPtrConstWrap(str);
1643         PyTuple_SetItem(list, 1, message);
1644         result = PyEval_CallObject(libxml_xmlPythonErrorFuncHandler, list);
1645         Py_XDECREF(list);
1646         Py_XDECREF(result);
1647     }
1648 }
1649
1650 static void
1651 libxml_xmlErrorInitialize(void)
1652 {
1653 #ifdef DEBUG_ERROR
1654     printf("libxml_xmlErrorInitialize() called\n");
1655 #endif
1656     xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1657     xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1658 }
1659
1660 static PyObject *
1661 libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
1662                                PyObject * args)
1663 {
1664     PyObject *py_retval;
1665     PyObject *pyobj_f;
1666     PyObject *pyobj_ctx;
1667
1668     if (!PyArg_ParseTuple
1669         (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f,
1670          &pyobj_ctx))
1671         return (NULL);
1672
1673 #ifdef DEBUG_ERROR
1674     printf("libxml_xmlRegisterErrorHandler(%p, %p) called\n", pyobj_ctx,
1675            pyobj_f);
1676 #endif
1677
1678     if (libxml_xmlPythonErrorFuncHandler != NULL) {
1679         Py_XDECREF(libxml_xmlPythonErrorFuncHandler);
1680     }
1681     if (libxml_xmlPythonErrorFuncCtxt != NULL) {
1682         Py_XDECREF(libxml_xmlPythonErrorFuncCtxt);
1683     }
1684
1685     Py_XINCREF(pyobj_ctx);
1686     Py_XINCREF(pyobj_f);
1687
1688     /* TODO: check f is a function ! */
1689     libxml_xmlPythonErrorFuncHandler = pyobj_f;
1690     libxml_xmlPythonErrorFuncCtxt = pyobj_ctx;
1691
1692     py_retval = libxml_intWrap(1);
1693     return (py_retval);
1694 }
1695
1696
1697 /************************************************************************
1698  *                                                                      *
1699  *                      Per parserCtxt error handler                    *
1700  *                                                                      *
1701  ************************************************************************/
1702
1703 typedef struct 
1704 {
1705     PyObject *f;
1706     PyObject *arg;
1707 } xmlParserCtxtPyCtxt;
1708 typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;
1709
1710 static void
1711 libxml_xmlParserCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str) 
1712 {
1713     PyObject *list;
1714     PyObject *result;
1715     xmlParserCtxtPtr ctxt;
1716     xmlParserCtxtPyCtxtPtr pyCtxt;
1717     
1718 #ifdef DEBUG_ERROR
1719     printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
1720 #endif
1721
1722     ctxt = (xmlParserCtxtPtr)ctx;
1723     pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1724
1725     list = PyTuple_New(4);
1726     PyTuple_SetItem(list, 0, pyCtxt->arg);
1727     Py_XINCREF(pyCtxt->arg);
1728     PyTuple_SetItem(list, 1, libxml_charPtrWrap(str));
1729     PyTuple_SetItem(list, 2, libxml_intWrap(severity));
1730     PyTuple_SetItem(list, 3, Py_None);
1731     Py_INCREF(Py_None);
1732     result = PyEval_CallObject(pyCtxt->f, list);
1733     if (result == NULL) 
1734     {
1735         /* TODO: manage for the exception to be propagated... */
1736         PyErr_Print();
1737     }
1738     Py_XDECREF(list);
1739     Py_XDECREF(result);
1740 }
1741
1742 static void 
1743 libxml_xmlParserCtxtErrorFuncHandler(void *ctx, const char *msg, ...) 
1744 {
1745     va_list ap;
1746
1747     va_start(ap, msg);
1748     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_ERROR,libxml_buildMessage(msg,ap));
1749     va_end(ap);
1750 }
1751
1752 static void 
1753 libxml_xmlParserCtxtWarningFuncHandler(void *ctx, const char *msg, ...) 
1754 {
1755     va_list ap;
1756
1757     va_start(ap, msg);
1758     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_WARNING,libxml_buildMessage(msg,ap));
1759     va_end(ap);
1760 }
1761
1762 static void 
1763 libxml_xmlParserCtxtValidityErrorFuncHandler(void *ctx, const char *msg, ...) 
1764 {
1765     va_list ap;
1766
1767     va_start(ap, msg);
1768     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
1769     va_end(ap);
1770 }
1771
1772 static void 
1773 libxml_xmlParserCtxtValidityWarningFuncHandler(void *ctx, const char *msg, ...) 
1774 {
1775     va_list ap;
1776
1777     va_start(ap, msg);
1778     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
1779     va_end(ap);
1780 }
1781
1782 static PyObject *
1783 libxml_xmlParserCtxtSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) 
1784 {
1785     PyObject *py_retval;
1786     xmlParserCtxtPtr ctxt;
1787     xmlParserCtxtPyCtxtPtr pyCtxt;
1788     PyObject *pyobj_ctxt;
1789     PyObject *pyobj_f;
1790     PyObject *pyobj_arg;
1791
1792     if (!PyArg_ParseTuple(args, (char *)"OOO:xmlParserCtxtSetErrorHandler",
1793                           &pyobj_ctxt, &pyobj_f, &pyobj_arg))
1794         return(NULL);
1795     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1796     if (ctxt->_private == NULL) {
1797         pyCtxt = xmlMalloc(sizeof(xmlParserCtxtPyCtxt));
1798         if (pyCtxt == NULL) {
1799             py_retval = libxml_intWrap(-1);
1800             return(py_retval);
1801         }
1802         memset(pyCtxt,0,sizeof(xmlParserCtxtPyCtxt));
1803         ctxt->_private = pyCtxt;
1804     }
1805     else {
1806         pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1807     }
1808     /* TODO: check f is a function ! */
1809     Py_XDECREF(pyCtxt->f);
1810     Py_XINCREF(pyobj_f);
1811     pyCtxt->f = pyobj_f;
1812     Py_XDECREF(pyCtxt->arg);
1813     Py_XINCREF(pyobj_arg);
1814     pyCtxt->arg = pyobj_arg;
1815
1816     if (pyobj_f != Py_None) {
1817         ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
1818         ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
1819         ctxt->vctxt.error = libxml_xmlParserCtxtValidityErrorFuncHandler;
1820         ctxt->vctxt.warning = libxml_xmlParserCtxtValidityWarningFuncHandler;
1821     }
1822     else {
1823         ctxt->sax->error = xmlParserError;
1824         ctxt->vctxt.error = xmlParserValidityError;
1825         ctxt->sax->warning = xmlParserWarning;
1826         ctxt->vctxt.warning = xmlParserValidityWarning;
1827     }
1828
1829     py_retval = libxml_intWrap(1);
1830     return(py_retval);
1831 }
1832
1833 static PyObject *
1834 libxml_xmlParserCtxtGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) 
1835 {
1836     PyObject *py_retval;
1837     xmlParserCtxtPtr ctxt;
1838     xmlParserCtxtPyCtxtPtr pyCtxt;
1839     PyObject *pyobj_ctxt;
1840
1841     if (!PyArg_ParseTuple(args, (char *)"O:xmlParserCtxtGetErrorHandler",
1842                           &pyobj_ctxt))
1843         return(NULL);
1844     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1845     py_retval = PyTuple_New(2);
1846     if (ctxt->_private != NULL) {
1847         pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1848
1849         PyTuple_SetItem(py_retval, 0, pyCtxt->f);
1850         Py_XINCREF(pyCtxt->f);
1851         PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
1852         Py_XINCREF(pyCtxt->arg);
1853     }
1854     else {
1855         /* no python error handler registered */
1856         PyTuple_SetItem(py_retval, 0, Py_None);
1857         Py_XINCREF(Py_None);
1858         PyTuple_SetItem(py_retval, 1, Py_None);
1859         Py_XINCREF(Py_None);
1860     }
1861     return(py_retval);
1862 }
1863
1864 static PyObject *
1865 libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
1866     xmlParserCtxtPtr ctxt;
1867     PyObject *pyobj_ctxt;
1868     xmlParserCtxtPyCtxtPtr pyCtxt;
1869
1870     if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
1871         return(NULL);
1872     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1873
1874     if (ctxt != NULL) {
1875         pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
1876         if (pyCtxt) {
1877             Py_XDECREF(pyCtxt->f);
1878             Py_XDECREF(pyCtxt->arg);
1879             xmlFree(pyCtxt);
1880         }
1881         xmlFreeParserCtxt(ctxt);
1882     }
1883
1884     Py_INCREF(Py_None);
1885     return(Py_None);
1886 }
1887
1888 /***
1889  * xmlValidCtxt stuff
1890  */
1891
1892 typedef struct 
1893 {
1894     PyObject *warn;
1895     PyObject *error;
1896     PyObject *arg;
1897 } xmlValidCtxtPyCtxt;
1898 typedef xmlValidCtxtPyCtxt *xmlValidCtxtPyCtxtPtr;
1899
1900 static void
1901 libxml_xmlValidCtxtGenericErrorFuncHandler(void *ctx, ATTRIBUTE_UNUSED int severity, char *str)
1902 {
1903     PyObject *list;
1904     PyObject *result;
1905     xmlValidCtxtPyCtxtPtr pyCtxt;
1906     
1907 #ifdef DEBUG_ERROR
1908     printf("libxml_xmlValidCtxtGenericErrorFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str);
1909 #endif
1910
1911     pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx;
1912     
1913     list = PyTuple_New(2);
1914     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
1915     PyTuple_SetItem(list, 1, pyCtxt->arg);
1916     Py_XINCREF(pyCtxt->arg);
1917     result = PyEval_CallObject(pyCtxt->error, list);
1918     if (result == NULL) 
1919     {
1920         /* TODO: manage for the exception to be propagated... */
1921         PyErr_Print();
1922     }
1923     Py_XDECREF(list);
1924     Py_XDECREF(result);
1925 }
1926
1927 static void
1928 libxml_xmlValidCtxtGenericWarningFuncHandler(void *ctx, ATTRIBUTE_UNUSED int severity, char *str)
1929 {
1930     PyObject *list;
1931     PyObject *result;
1932     xmlValidCtxtPyCtxtPtr pyCtxt;
1933     
1934 #ifdef DEBUG_ERROR
1935     printf("libxml_xmlValidCtxtGenericWarningFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str);
1936 #endif
1937
1938     pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx;
1939
1940     list = PyTuple_New(2);
1941     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
1942     PyTuple_SetItem(list, 1, pyCtxt->arg);
1943     Py_XINCREF(pyCtxt->arg);
1944     result = PyEval_CallObject(pyCtxt->warn, list);
1945     if (result == NULL) 
1946     {
1947         /* TODO: manage for the exception to be propagated... */
1948         PyErr_Print();
1949     }
1950     Py_XDECREF(list);
1951     Py_XDECREF(result);
1952 }
1953
1954 static void 
1955 libxml_xmlValidCtxtErrorFuncHandler(void *ctx, const char *msg, ...) 
1956 {
1957     va_list ap;
1958
1959     va_start(ap, msg);
1960     libxml_xmlValidCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
1961     va_end(ap);
1962 }
1963
1964 static void 
1965 libxml_xmlValidCtxtWarningFuncHandler(void *ctx, const char *msg, ...) 
1966 {
1967     va_list ap;
1968
1969     va_start(ap, msg);
1970     libxml_xmlValidCtxtGenericWarningFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
1971     va_end(ap);
1972 }
1973
1974 static PyObject *
1975 libxml_xmlSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1976 {
1977     PyObject *py_retval;
1978     PyObject *pyobj_error;
1979     PyObject *pyobj_warn;
1980     PyObject *pyobj_ctx;
1981     PyObject *pyobj_arg = Py_None;
1982     xmlValidCtxtPtr ctxt;
1983     xmlValidCtxtPyCtxtPtr pyCtxt;
1984
1985     if (!PyArg_ParseTuple
1986         (args, (char *) "OOO|O:xmlSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
1987         return (NULL);
1988
1989 #ifdef DEBUG_ERROR
1990     printf("libxml_xmlSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
1991 #endif
1992
1993     ctxt = PyValidCtxt_Get(pyobj_ctx);
1994     pyCtxt = xmlMalloc(sizeof(xmlValidCtxtPyCtxt));
1995     if (pyCtxt == NULL) {
1996             py_retval = libxml_intWrap(-1);
1997             return(py_retval);
1998     }
1999     memset(pyCtxt, 0, sizeof(xmlValidCtxtPyCtxt));
2000
2001     
2002     /* TODO: check warn and error is a function ! */
2003     Py_XDECREF(pyCtxt->error);
2004     Py_XINCREF(pyobj_error);
2005     pyCtxt->error = pyobj_error;
2006     
2007     Py_XDECREF(pyCtxt->warn);
2008     Py_XINCREF(pyobj_warn);
2009     pyCtxt->warn = pyobj_warn;
2010     
2011     Py_XDECREF(pyCtxt->arg);
2012     Py_XINCREF(pyobj_arg);
2013     pyCtxt->arg = pyobj_arg;
2014
2015     ctxt->error = libxml_xmlValidCtxtErrorFuncHandler;
2016     ctxt->warning = libxml_xmlValidCtxtWarningFuncHandler;
2017     ctxt->userData = pyCtxt;
2018
2019     py_retval = libxml_intWrap(1);
2020     return (py_retval);
2021 }
2022
2023
2024 static PyObject *
2025 libxml_xmlFreeValidCtxt(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
2026     xmlValidCtxtPtr cur;
2027     xmlValidCtxtPyCtxtPtr pyCtxt;
2028     PyObject *pyobj_cur;
2029
2030     if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeValidCtxt", &pyobj_cur))
2031         return(NULL);
2032     cur = (xmlValidCtxtPtr) PyValidCtxt_Get(pyobj_cur);
2033
2034     pyCtxt = (xmlValidCtxtPyCtxtPtr)(cur->userData);
2035     if (pyCtxt != NULL)
2036     {
2037             Py_XDECREF(pyCtxt->error);
2038             Py_XDECREF(pyCtxt->warn);
2039             Py_XDECREF(pyCtxt->arg);
2040             xmlFree(pyCtxt);
2041     }
2042
2043     xmlFreeValidCtxt(cur);
2044     Py_INCREF(Py_None);
2045     return(Py_None);
2046 }
2047
2048 #ifdef LIBXML_READER_ENABLED
2049 /************************************************************************
2050  *                                                                      *
2051  *                      Per xmlTextReader error handler                 *
2052  *                                                                      *
2053  ************************************************************************/
2054
2055 typedef struct 
2056 {
2057     PyObject *f;
2058     PyObject *arg;
2059 } xmlTextReaderPyCtxt;
2060 typedef xmlTextReaderPyCtxt *xmlTextReaderPyCtxtPtr;
2061
2062 static void 
2063 libxml_xmlTextReaderErrorCallback(void *arg, 
2064                                   const char *msg,
2065                                   int severity,
2066                                   xmlTextReaderLocatorPtr locator)
2067 {
2068     xmlTextReaderPyCtxt *pyCtxt = (xmlTextReaderPyCtxt *)arg;
2069     PyObject *list;
2070     PyObject *result;
2071     
2072     list = PyTuple_New(4);
2073     PyTuple_SetItem(list, 0, pyCtxt->arg);
2074     Py_XINCREF(pyCtxt->arg);
2075     PyTuple_SetItem(list, 1, libxml_charPtrConstWrap(msg));
2076     PyTuple_SetItem(list, 2, libxml_intWrap(severity));
2077     PyTuple_SetItem(list, 3, libxml_xmlTextReaderLocatorPtrWrap(locator));
2078     result = PyEval_CallObject(pyCtxt->f, list);
2079     if (result == NULL)
2080     {
2081         /* TODO: manage for the exception to be propagated... */
2082         PyErr_Print();
2083     }
2084     Py_XDECREF(list);
2085     Py_XDECREF(result);
2086 }
2087
2088 static PyObject *
2089 libxml_xmlTextReaderSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
2090 {
2091     xmlTextReaderPtr reader;
2092     xmlTextReaderPyCtxtPtr pyCtxt;
2093     xmlTextReaderErrorFunc f;
2094     void *arg;
2095     PyObject *pyobj_reader;
2096     PyObject *pyobj_f;
2097     PyObject *pyobj_arg;
2098     PyObject *py_retval;
2099
2100     if (!PyArg_ParseTuple(args, (char *)"OOO:xmlTextReaderSetErrorHandler", &pyobj_reader, &pyobj_f, &pyobj_arg))
2101         return(NULL);
2102     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2103     /* clear previous error handler */
2104     xmlTextReaderGetErrorHandler(reader,&f,&arg);
2105     if (arg != NULL) {
2106         if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
2107             /* ok, it's our error handler! */
2108             pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2109             Py_XDECREF(pyCtxt->f);
2110             Py_XDECREF(pyCtxt->arg);
2111             xmlFree(pyCtxt);
2112         }
2113         else {
2114             /* 
2115              * there already an arg, and it's not ours,
2116              * there is definitely something wrong going on here...
2117              * we don't know how to free it, so we bail out... 
2118              */
2119             py_retval = libxml_intWrap(-1);
2120             return(py_retval);
2121         }
2122     }
2123     xmlTextReaderSetErrorHandler(reader,NULL,NULL);
2124     /* set new error handler */
2125     if (pyobj_f != Py_None)
2126     {
2127         pyCtxt = (xmlTextReaderPyCtxtPtr)xmlMalloc(sizeof(xmlTextReaderPyCtxt));
2128         if (pyCtxt == NULL) {
2129             py_retval = libxml_intWrap(-1);
2130             return(py_retval);
2131         }
2132         Py_XINCREF(pyobj_f);
2133         pyCtxt->f = pyobj_f;
2134         Py_XINCREF(pyobj_arg);
2135         pyCtxt->arg = pyobj_arg;
2136         xmlTextReaderSetErrorHandler(reader,
2137             (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback,
2138                                      pyCtxt);
2139     }
2140
2141     py_retval = libxml_intWrap(1);
2142     return(py_retval);
2143 }
2144
2145 static PyObject *
2146 libxml_xmlTextReaderGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
2147 {
2148     xmlTextReaderPtr reader;
2149     xmlTextReaderPyCtxtPtr pyCtxt;
2150     xmlTextReaderErrorFunc f;
2151     void *arg;
2152     PyObject *pyobj_reader;
2153     PyObject *py_retval;
2154
2155     if (!PyArg_ParseTuple(args, (char *)"O:xmlTextReaderSetErrorHandler", &pyobj_reader))
2156         return(NULL);
2157     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2158     xmlTextReaderGetErrorHandler(reader,&f,&arg);
2159     py_retval = PyTuple_New(2);
2160     if (f == (xmlTextReaderErrorFunc)libxml_xmlTextReaderErrorCallback) {
2161         /* ok, it's our error handler! */
2162         pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2163         PyTuple_SetItem(py_retval, 0, pyCtxt->f);
2164         Py_XINCREF(pyCtxt->f);
2165         PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
2166         Py_XINCREF(pyCtxt->arg);
2167     }
2168     else
2169     {
2170         /* f is null or it's not our error handler */
2171         PyTuple_SetItem(py_retval, 0, Py_None);
2172         Py_XINCREF(Py_None);
2173         PyTuple_SetItem(py_retval, 1, Py_None);
2174         Py_XINCREF(Py_None);
2175     }
2176     return(py_retval);
2177 }
2178
2179 static PyObject *
2180 libxml_xmlFreeTextReader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
2181     xmlTextReaderPtr reader;
2182     PyObject *pyobj_reader;
2183     xmlTextReaderPyCtxtPtr pyCtxt;
2184     xmlTextReaderErrorFunc f;
2185     void *arg;
2186
2187     if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeTextReader", &pyobj_reader))
2188         return(NULL);
2189     if (!PyCapsule_CheckExact(pyobj_reader)) {
2190         Py_INCREF(Py_None);
2191         return(Py_None);
2192     }
2193     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2194     if (reader == NULL) {
2195         Py_INCREF(Py_None);
2196         return(Py_None);
2197     }
2198
2199     xmlTextReaderGetErrorHandler(reader,&f,&arg);
2200     if (arg != NULL) {
2201         if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
2202             /* ok, it's our error handler! */
2203             pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2204             Py_XDECREF(pyCtxt->f);
2205             Py_XDECREF(pyCtxt->arg);
2206             xmlFree(pyCtxt);
2207         }
2208         /* 
2209          * else, something wrong happened, because the error handler is
2210          * not owned by the python bindings...
2211          */
2212     }
2213
2214     xmlFreeTextReader(reader);
2215     Py_INCREF(Py_None);
2216     return(Py_None);
2217 }
2218 #endif
2219
2220 /************************************************************************
2221  *                                                                      *
2222  *                      XPath extensions                                *
2223  *                                                                      *
2224  ************************************************************************/
2225
2226 static void
2227 libxml_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs)
2228 {
2229     PyObject *list, *cur, *result;
2230     xmlXPathObjectPtr obj;
2231     xmlXPathContextPtr rctxt;
2232     PyObject *current_function = NULL;
2233     const xmlChar *name;
2234     const xmlChar *ns_uri;
2235     int i;
2236
2237     if (ctxt == NULL)
2238         return;
2239     rctxt = ctxt->context;
2240     if (rctxt == NULL)
2241         return;
2242     name = rctxt->function;
2243     ns_uri = rctxt->functionURI;
2244 #ifdef DEBUG_XPATH
2245     printf("libxml_xmlXPathFuncCallback called name %s URI %s\n", name,
2246            ns_uri);
2247 #endif
2248
2249     /*
2250      * Find the function, it should be there it was there at lookup
2251      */
2252     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2253         if (                    /* TODO (ctxt == libxml_xpathCallbacks[i].ctx) && */
2254                                                 (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2255                (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2256                                         current_function = (*libxml_xpathCallbacks)[i].function;
2257         }
2258     }
2259     if (current_function == NULL) {
2260         printf
2261             ("libxml_xmlXPathFuncCallback: internal error %s not found !\n",
2262              name);
2263         return;
2264     }
2265
2266     list = PyTuple_New(nargs + 1);
2267     PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt));
2268     for (i = nargs - 1; i >= 0; i--) {
2269         obj = valuePop(ctxt);
2270         cur = libxml_xmlXPathObjectPtrWrap(obj);
2271         PyTuple_SetItem(list, i + 1, cur);
2272     }
2273     result = PyEval_CallObject(current_function, list);
2274     Py_DECREF(list);
2275
2276     obj = libxml_xmlXPathObjectPtrConvert(result);
2277     valuePush(ctxt, obj);
2278 }
2279
2280 static xmlXPathFunction
2281 libxml_xmlXPathFuncLookupFunc(void *ctxt, const xmlChar * name,
2282                               const xmlChar * ns_uri)
2283 {
2284     int i;
2285
2286 #ifdef DEBUG_XPATH
2287     printf("libxml_xmlXPathFuncLookupFunc(%p, %s, %s) called\n",
2288            ctxt, name, ns_uri);
2289 #endif
2290     /*
2291      * This is called once only. The address is then stored in the
2292      * XPath expression evaluation, the proper object to call can
2293      * then still be found using the execution context function
2294      * and functionURI fields.
2295      */
2296     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2297                         if ((ctxt == (*libxml_xpathCallbacks)[i].ctx) &&
2298                                         (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2299                                         (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2300             return (libxml_xmlXPathFuncCallback);
2301         }
2302     }
2303     return (NULL);
2304 }
2305
2306 static void
2307 libxml_xpathCallbacksInitialize(void)
2308 {
2309     int i;
2310
2311     if (libxml_xpathCallbacksInitialized != 0)
2312         return;
2313
2314 #ifdef DEBUG_XPATH
2315     printf("libxml_xpathCallbacksInitialized called\n");
2316 #endif
2317     libxml_xpathCallbacks = (libxml_xpathCallbackArray*)xmlMalloc(
2318                 libxml_xpathCallbacksAllocd*sizeof(libxml_xpathCallback));
2319
2320     for (i = 0; i < libxml_xpathCallbacksAllocd; i++) {
2321                         (*libxml_xpathCallbacks)[i].ctx = NULL;
2322                         (*libxml_xpathCallbacks)[i].name = NULL;
2323                         (*libxml_xpathCallbacks)[i].ns_uri = NULL;
2324                         (*libxml_xpathCallbacks)[i].function = NULL;
2325     }
2326     libxml_xpathCallbacksInitialized = 1;
2327 }
2328
2329 PyObject *
2330 libxml_xmlRegisterXPathFunction(ATTRIBUTE_UNUSED PyObject * self,
2331                                 PyObject * args)
2332 {
2333     PyObject *py_retval;
2334     int c_retval = 0;
2335     xmlChar *name;
2336     xmlChar *ns_uri;
2337     xmlXPathContextPtr ctx;
2338     PyObject *pyobj_ctx;
2339     PyObject *pyobj_f;
2340     int i;
2341
2342     if (!PyArg_ParseTuple
2343         (args, (char *) "OszO:registerXPathFunction", &pyobj_ctx, &name,
2344          &ns_uri, &pyobj_f))
2345         return (NULL);
2346
2347     ctx = (xmlXPathContextPtr) PyxmlXPathContext_Get(pyobj_ctx);
2348     if (libxml_xpathCallbacksInitialized == 0)
2349         libxml_xpathCallbacksInitialize();
2350     xmlXPathRegisterFuncLookup(ctx, libxml_xmlXPathFuncLookupFunc, ctx);
2351
2352     if ((pyobj_ctx == NULL) || (name == NULL) || (pyobj_f == NULL)) {
2353         py_retval = libxml_intWrap(-1);
2354         return (py_retval);
2355     }
2356 #ifdef DEBUG_XPATH
2357     printf("libxml_registerXPathFunction(%p, %s, %s) called\n",
2358            ctx, name, ns_uri);
2359 #endif
2360     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2361         if ((ctx == (*libxml_xpathCallbacks)[i].ctx) &&
2362             (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2363             (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2364             Py_XINCREF(pyobj_f);
2365             Py_XDECREF((*libxml_xpathCallbacks)[i].function);
2366             (*libxml_xpathCallbacks)[i].function = pyobj_f;
2367             c_retval = 1;
2368             goto done;
2369         }
2370     }
2371     if (libxml_xpathCallbacksNb >= libxml_xpathCallbacksAllocd) {
2372                         libxml_xpathCallbacksAllocd+=10;
2373         libxml_xpathCallbacks = (libxml_xpathCallbackArray*)xmlRealloc(
2374                 libxml_xpathCallbacks,
2375                 libxml_xpathCallbacksAllocd*sizeof(libxml_xpathCallback));
2376     } 
2377     i = libxml_xpathCallbacksNb++;
2378     Py_XINCREF(pyobj_f);
2379     (*libxml_xpathCallbacks)[i].ctx = ctx;
2380     (*libxml_xpathCallbacks)[i].name = xmlStrdup(name);
2381     (*libxml_xpathCallbacks)[i].ns_uri = xmlStrdup(ns_uri);
2382     (*libxml_xpathCallbacks)[i].function = pyobj_f;
2383         c_retval = 1;
2384     
2385   done:
2386     py_retval = libxml_intWrap((int) c_retval);
2387     return (py_retval);
2388 }
2389
2390 PyObject *
2391 libxml_xmlXPathRegisterVariable(ATTRIBUTE_UNUSED PyObject * self,
2392                                 PyObject * args)
2393 {
2394     PyObject *py_retval;
2395     int c_retval = 0;
2396     xmlChar *name;
2397     xmlChar *ns_uri;
2398     xmlXPathContextPtr ctx;
2399     xmlXPathObjectPtr val;
2400     PyObject *pyobj_ctx;
2401     PyObject *pyobj_value;
2402
2403     if (!PyArg_ParseTuple
2404         (args, (char *) "OszO:xpathRegisterVariable", &pyobj_ctx, &name,
2405          &ns_uri, &pyobj_value))
2406         return (NULL);
2407
2408     ctx = (xmlXPathContextPtr) PyxmlXPathContext_Get(pyobj_ctx);
2409     val = libxml_xmlXPathObjectPtrConvert(pyobj_value);
2410
2411     c_retval = xmlXPathRegisterVariableNS(ctx, name, ns_uri, val);
2412     py_retval = libxml_intWrap(c_retval);
2413     return (py_retval);
2414 }
2415
2416 /************************************************************************
2417  *                                                                      *
2418  *                      Global properties access                        *
2419  *                                                                      *
2420  ************************************************************************/
2421 static PyObject *
2422 libxml_name(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2423 {
2424     PyObject *resultobj, *obj;
2425     xmlNodePtr cur;
2426     const xmlChar *res;
2427
2428     if (!PyArg_ParseTuple(args, (char *) "O:name", &obj))
2429         return NULL;
2430     cur = PyxmlNode_Get(obj);
2431
2432 #ifdef DEBUG
2433     printf("libxml_name: cur = %p type %d\n", cur, cur->type);
2434 #endif
2435
2436     switch (cur->type) {
2437         case XML_DOCUMENT_NODE:
2438 #ifdef LIBXML_DOCB_ENABLED
2439         case XML_DOCB_DOCUMENT_NODE:
2440 #endif
2441         case XML_HTML_DOCUMENT_NODE:{
2442                 xmlDocPtr doc = (xmlDocPtr) cur;
2443
2444                 res = doc->URL;
2445                 break;
2446             }
2447         case XML_ATTRIBUTE_NODE:{
2448                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2449
2450                 res = attr->name;
2451                 break;
2452             }
2453         case XML_NAMESPACE_DECL:{
2454                 xmlNsPtr ns = (xmlNsPtr) cur;
2455
2456                 res = ns->prefix;
2457                 break;
2458             }
2459         default:
2460             res = cur->name;
2461             break;
2462     }
2463     resultobj = libxml_constxmlCharPtrWrap(res);
2464
2465     return resultobj;
2466 }
2467
2468 static PyObject *
2469 libxml_doc(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2470 {
2471     PyObject *resultobj, *obj;
2472     xmlNodePtr cur;
2473     xmlDocPtr res;
2474
2475     if (!PyArg_ParseTuple(args, (char *) "O:doc", &obj))
2476         return NULL;
2477     cur = PyxmlNode_Get(obj);
2478
2479 #ifdef DEBUG
2480     printf("libxml_doc: cur = %p\n", cur);
2481 #endif
2482
2483     switch (cur->type) {
2484         case XML_DOCUMENT_NODE:
2485 #ifdef LIBXML_DOCB_ENABLED
2486         case XML_DOCB_DOCUMENT_NODE:
2487 #endif
2488         case XML_HTML_DOCUMENT_NODE:
2489             res = NULL;
2490             break;
2491         case XML_ATTRIBUTE_NODE:{
2492                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2493
2494                 res = attr->doc;
2495                 break;
2496             }
2497         case XML_NAMESPACE_DECL:
2498             res = NULL;
2499             break;
2500         default:
2501             res = cur->doc;
2502             break;
2503     }
2504     resultobj = libxml_xmlDocPtrWrap(res);
2505     return resultobj;
2506 }
2507
2508 static PyObject *
2509 libxml_properties(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2510 {
2511     PyObject *resultobj, *obj;
2512     xmlNodePtr cur;
2513     xmlAttrPtr res;
2514
2515     if (!PyArg_ParseTuple(args, (char *) "O:properties", &obj))
2516         return NULL;
2517     cur = PyxmlNode_Get(obj);
2518     if ((cur != NULL) && (cur->type == XML_ELEMENT_NODE))
2519         res = cur->properties;
2520     else
2521         res = NULL;
2522     resultobj = libxml_xmlAttrPtrWrap(res);
2523     return resultobj;
2524 }
2525
2526 static PyObject *
2527 libxml_next(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2528 {
2529     PyObject *resultobj, *obj;
2530     xmlNodePtr cur;
2531     xmlNodePtr res;
2532
2533     if (!PyArg_ParseTuple(args, (char *) "O:next", &obj))
2534         return NULL;
2535     cur = PyxmlNode_Get(obj);
2536
2537 #ifdef DEBUG
2538     printf("libxml_next: cur = %p\n", cur);
2539 #endif
2540
2541     switch (cur->type) {
2542         case XML_DOCUMENT_NODE:
2543 #ifdef LIBXML_DOCB_ENABLED
2544         case XML_DOCB_DOCUMENT_NODE:
2545 #endif
2546         case XML_HTML_DOCUMENT_NODE:
2547             res = NULL;
2548             break;
2549         case XML_ATTRIBUTE_NODE:{
2550                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2551
2552                 res = (xmlNodePtr) attr->next;
2553                 break;
2554             }
2555         case XML_NAMESPACE_DECL:{
2556                 xmlNsPtr ns = (xmlNsPtr) cur;
2557
2558                 res = (xmlNodePtr) ns->next;
2559                 break;
2560             }
2561         default:
2562             res = cur->next;
2563             break;
2564
2565     }
2566     resultobj = libxml_xmlNodePtrWrap(res);
2567     return resultobj;
2568 }
2569
2570 static PyObject *
2571 libxml_prev(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2572 {
2573     PyObject *resultobj, *obj;
2574     xmlNodePtr cur;
2575     xmlNodePtr res;
2576
2577     if (!PyArg_ParseTuple(args, (char *) "O:prev", &obj))
2578         return NULL;
2579     cur = PyxmlNode_Get(obj);
2580
2581 #ifdef DEBUG
2582     printf("libxml_prev: cur = %p\n", cur);
2583 #endif
2584
2585     switch (cur->type) {
2586         case XML_DOCUMENT_NODE:
2587 #ifdef LIBXML_DOCB_ENABLED
2588         case XML_DOCB_DOCUMENT_NODE:
2589 #endif
2590         case XML_HTML_DOCUMENT_NODE:
2591             res = NULL;
2592             break;
2593         case XML_ATTRIBUTE_NODE:{
2594                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2595
2596                 res = (xmlNodePtr) attr->prev;
2597             }
2598             break;
2599         case XML_NAMESPACE_DECL:
2600             res = NULL;
2601             break;
2602         default:
2603             res = cur->prev;
2604             break;
2605     }
2606     resultobj = libxml_xmlNodePtrWrap(res);
2607     return resultobj;
2608 }
2609
2610 static PyObject *
2611 libxml_children(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2612 {
2613     PyObject *resultobj, *obj;
2614     xmlNodePtr cur;
2615     xmlNodePtr res;
2616
2617     if (!PyArg_ParseTuple(args, (char *) "O:children", &obj))
2618         return NULL;
2619     cur = PyxmlNode_Get(obj);
2620
2621 #ifdef DEBUG
2622     printf("libxml_children: cur = %p\n", cur);
2623 #endif
2624
2625     switch (cur->type) {
2626         case XML_ELEMENT_NODE:
2627         case XML_ENTITY_REF_NODE:
2628         case XML_ENTITY_NODE:
2629         case XML_PI_NODE:
2630         case XML_COMMENT_NODE:
2631         case XML_DOCUMENT_NODE:
2632 #ifdef LIBXML_DOCB_ENABLED
2633         case XML_DOCB_DOCUMENT_NODE:
2634 #endif
2635         case XML_HTML_DOCUMENT_NODE:
2636         case XML_DTD_NODE:
2637             res = cur->children;
2638             break;
2639         case XML_ATTRIBUTE_NODE:{
2640                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2641
2642                 res = attr->children;
2643                 break;
2644             }
2645         default:
2646             res = NULL;
2647             break;
2648     }
2649     resultobj = libxml_xmlNodePtrWrap(res);
2650     return resultobj;
2651 }
2652
2653 static PyObject *
2654 libxml_last(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2655 {
2656     PyObject *resultobj, *obj;
2657     xmlNodePtr cur;
2658     xmlNodePtr res;
2659
2660     if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2661         return NULL;
2662     cur = PyxmlNode_Get(obj);
2663
2664 #ifdef DEBUG
2665     printf("libxml_last: cur = %p\n", cur);
2666 #endif
2667
2668     switch (cur->type) {
2669         case XML_ELEMENT_NODE:
2670         case XML_ENTITY_REF_NODE:
2671         case XML_ENTITY_NODE:
2672         case XML_PI_NODE:
2673         case XML_COMMENT_NODE:
2674         case XML_DOCUMENT_NODE:
2675 #ifdef LIBXML_DOCB_ENABLED
2676         case XML_DOCB_DOCUMENT_NODE:
2677 #endif
2678         case XML_HTML_DOCUMENT_NODE:
2679         case XML_DTD_NODE:
2680             res = cur->last;
2681             break;
2682         case XML_ATTRIBUTE_NODE:{
2683                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2684
2685                 res = attr->last;
2686                 break;
2687             }
2688         default:
2689             res = NULL;
2690             break;
2691     }
2692     resultobj = libxml_xmlNodePtrWrap(res);
2693     return resultobj;
2694 }
2695
2696 static PyObject *
2697 libxml_parent(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2698 {
2699     PyObject *resultobj, *obj;
2700     xmlNodePtr cur;
2701     xmlNodePtr res;
2702
2703     if (!PyArg_ParseTuple(args, (char *) "O:parent", &obj))
2704         return NULL;
2705     cur = PyxmlNode_Get(obj);
2706
2707 #ifdef DEBUG
2708     printf("libxml_parent: cur = %p\n", cur);
2709 #endif
2710
2711     switch (cur->type) {
2712         case XML_DOCUMENT_NODE:
2713         case XML_HTML_DOCUMENT_NODE:
2714 #ifdef LIBXML_DOCB_ENABLED
2715         case XML_DOCB_DOCUMENT_NODE:
2716 #endif
2717             res = NULL;
2718             break;
2719         case XML_ATTRIBUTE_NODE:{
2720                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2721
2722                 res = attr->parent;
2723             }
2724             break;
2725         case XML_ENTITY_DECL:
2726         case XML_NAMESPACE_DECL:
2727         case XML_XINCLUDE_START:
2728         case XML_XINCLUDE_END:
2729             res = NULL;
2730             break;
2731         default:
2732             res = cur->parent;
2733             break;
2734     }
2735     resultobj = libxml_xmlNodePtrWrap(res);
2736     return resultobj;
2737 }
2738
2739 static PyObject *
2740 libxml_type(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2741 {
2742     PyObject *resultobj, *obj;
2743     xmlNodePtr cur;
2744     const xmlChar *res = NULL;
2745
2746     if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2747         return NULL;
2748     cur = PyxmlNode_Get(obj);
2749     if (cur == NULL) {
2750         Py_INCREF(Py_None);
2751         return (Py_None);
2752     }
2753
2754 #ifdef DEBUG
2755     printf("libxml_type: cur = %p\n", cur);
2756 #endif
2757
2758     switch (cur->type) {
2759         case XML_ELEMENT_NODE:
2760             res = (const xmlChar *) "element";
2761             break;
2762         case XML_ATTRIBUTE_NODE:
2763             res = (const xmlChar *) "attribute";
2764             break;
2765         case XML_TEXT_NODE:
2766             res = (const xmlChar *) "text";
2767             break;
2768         case XML_CDATA_SECTION_NODE:
2769             res = (const xmlChar *) "cdata";
2770             break;
2771         case XML_ENTITY_REF_NODE:
2772             res = (const xmlChar *) "entity_ref";
2773             break;
2774         case XML_ENTITY_NODE:
2775             res = (const xmlChar *) "entity";
2776             break;
2777         case XML_PI_NODE:
2778             res = (const xmlChar *) "pi";
2779             break;
2780         case XML_COMMENT_NODE:
2781             res = (const xmlChar *) "comment";
2782             break;
2783         case XML_DOCUMENT_NODE:
2784             res = (const xmlChar *) "document_xml";
2785             break;
2786         case XML_DOCUMENT_TYPE_NODE:
2787             res = (const xmlChar *) "doctype";
2788             break;
2789         case XML_DOCUMENT_FRAG_NODE:
2790             res = (const xmlChar *) "fragment";
2791             break;
2792         case XML_NOTATION_NODE:
2793             res = (const xmlChar *) "notation";
2794             break;
2795         case XML_HTML_DOCUMENT_NODE:
2796             res = (const xmlChar *) "document_html";
2797             break;
2798         case XML_DTD_NODE:
2799             res = (const xmlChar *) "dtd";
2800             break;
2801         case XML_ELEMENT_DECL:
2802             res = (const xmlChar *) "elem_decl";
2803             break;
2804         case XML_ATTRIBUTE_DECL:
2805             res = (const xmlChar *) "attribute_decl";
2806             break;
2807         case XML_ENTITY_DECL:
2808             res = (const xmlChar *) "entity_decl";
2809             break;
2810         case XML_NAMESPACE_DECL:
2811             res = (const xmlChar *) "namespace";
2812             break;
2813         case XML_XINCLUDE_START:
2814             res = (const xmlChar *) "xinclude_start";
2815             break;
2816         case XML_XINCLUDE_END:
2817             res = (const xmlChar *) "xinclude_end";
2818             break;
2819 #ifdef LIBXML_DOCB_ENABLED
2820         case XML_DOCB_DOCUMENT_NODE:
2821             res = (const xmlChar *) "document_docbook";
2822             break;
2823 #endif
2824     }
2825 #ifdef DEBUG
2826     printf("libxml_type: cur = %p: %s\n", cur, res);
2827 #endif
2828
2829     resultobj = libxml_constxmlCharPtrWrap(res);
2830     return resultobj;
2831 }
2832
2833 /************************************************************************
2834  *                                                                      *
2835  *                      Specific accessor functions                     *
2836  *                                                                      *
2837  ************************************************************************/
2838 PyObject *
2839 libxml_xmlNodeGetNsDefs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2840 {
2841     PyObject *py_retval;
2842     xmlNsPtr c_retval;
2843     xmlNodePtr node;
2844     PyObject *pyobj_node;
2845
2846     if (!PyArg_ParseTuple
2847         (args, (char *) "O:xmlNodeGetNsDefs", &pyobj_node))
2848         return (NULL);
2849     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2850
2851     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2852         Py_INCREF(Py_None);
2853         return (Py_None);
2854     }
2855     c_retval = node->nsDef;
2856     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2857     return (py_retval);
2858 }
2859
2860 PyObject *
2861 libxml_xmlNodeRemoveNsDef(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2862 {
2863     PyObject *py_retval;
2864     xmlNsPtr ns, prev;
2865     xmlNodePtr node;
2866     PyObject *pyobj_node;
2867     xmlChar *href;
2868     xmlNsPtr c_retval;
2869
2870     if (!PyArg_ParseTuple
2871         (args, (char *) "Oz:xmlNodeRemoveNsDef", &pyobj_node, &href))
2872         return (NULL);
2873     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2874     ns = NULL;
2875
2876     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2877         Py_INCREF(Py_None);
2878         return (Py_None);
2879     }
2880
2881     if (href == NULL) {
2882         ns = node->nsDef;
2883         node->nsDef = NULL;
2884         c_retval = 0;
2885     }
2886     else {
2887         prev = NULL;
2888         ns = node->nsDef;
2889         while (ns != NULL) {
2890             if (xmlStrEqual(ns->href, href)) {
2891                 if (prev != NULL)
2892                     prev->next = ns->next;
2893                 else
2894                     node->nsDef = ns->next;
2895                 ns->next = NULL;
2896                 c_retval = 0;
2897                 break;
2898             }
2899             prev = ns;
2900             ns = ns->next;
2901         }
2902     }
2903
2904     c_retval = ns;
2905     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2906     return (py_retval);
2907 }
2908
2909 PyObject *
2910 libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2911 {
2912     PyObject *py_retval;
2913     xmlNsPtr c_retval;
2914     xmlNodePtr node;
2915     PyObject *pyobj_node;
2916
2917     if (!PyArg_ParseTuple(args, (char *) "O:xmlNodeGetNs", &pyobj_node))
2918         return (NULL);
2919     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2920
2921     if ((node == NULL) ||
2922         ((node->type != XML_ELEMENT_NODE) &&
2923          (node->type != XML_ATTRIBUTE_NODE))) {
2924         Py_INCREF(Py_None);
2925         return (Py_None);
2926     }
2927     c_retval = node->ns;
2928     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2929     return (py_retval);
2930 }
2931
2932 #ifdef LIBXML_OUTPUT_ENABLED
2933 /************************************************************************
2934  *                                                                      *
2935  *                      Serialization front-end                         *
2936  *                                                                      *
2937  ************************************************************************/
2938
2939 static PyObject *
2940 libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2941 {
2942     PyObject *py_retval = NULL;
2943     xmlChar *c_retval;
2944     PyObject *pyobj_node;
2945     xmlNodePtr node;
2946     xmlDocPtr doc;
2947     const char *encoding;
2948     int format;
2949     xmlSaveCtxtPtr ctxt;
2950     xmlBufferPtr buf;
2951     int options = 0;
2952
2953     if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
2954                           &encoding, &format))
2955         return (NULL);
2956     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2957
2958     if (node == NULL) {
2959         Py_INCREF(Py_None);
2960         return (Py_None);
2961     }
2962     if (node->type == XML_DOCUMENT_NODE) {
2963         doc = (xmlDocPtr) node;
2964         node = NULL;
2965 #ifdef LIBXML_HTML_ENABLED
2966     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2967         doc = (xmlDocPtr) node;
2968         node = NULL;
2969 #endif
2970     } else {
2971         if (node->type == XML_NAMESPACE_DECL)
2972             doc = NULL;
2973         else
2974             doc = node->doc;
2975         if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
2976 #ifdef LIBXML_HTML_ENABLED
2977         } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2978 #endif /* LIBXML_HTML_ENABLED */
2979         } else {
2980             Py_INCREF(Py_None);
2981             return (Py_None);
2982         }
2983     }
2984
2985
2986     buf = xmlBufferCreate();
2987     if (buf == NULL) {
2988         Py_INCREF(Py_None);
2989         return (Py_None);
2990     }
2991     if (format) options |= XML_SAVE_FORMAT;
2992     ctxt = xmlSaveToBuffer(buf, encoding, options);
2993     if (ctxt == NULL) {
2994         xmlBufferFree(buf);
2995         Py_INCREF(Py_None);
2996         return (Py_None);
2997     }
2998     if (node == NULL)
2999         xmlSaveDoc(ctxt, doc);
3000     else
3001         xmlSaveTree(ctxt, node);
3002     xmlSaveClose(ctxt);
3003
3004     c_retval = buf->content;
3005     buf->content = NULL;
3006
3007     xmlBufferFree(buf);
3008     py_retval = libxml_charPtrWrap((char *) c_retval);
3009
3010     return (py_retval);
3011 }
3012
3013 static PyObject *
3014 libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3015 {
3016     PyObject *py_file = NULL;
3017     FILE *output;
3018     PyObject *pyobj_node;
3019     xmlNodePtr node;
3020     xmlDocPtr doc;
3021     const char *encoding;
3022     int format;
3023     int len;
3024     xmlOutputBufferPtr buf;
3025     xmlCharEncodingHandlerPtr handler = NULL;
3026
3027     if (!PyArg_ParseTuple(args, (char *) "OOzi:serializeNode", &pyobj_node,
3028                           &py_file, &encoding, &format))
3029         return (NULL);
3030     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
3031     if (node == NULL) {
3032         return (PyLong_FromLong((long) -1));
3033     }
3034     output = PyFile_Get(py_file);
3035     if (output == NULL) {
3036         return (PyLong_FromLong((long) -1));
3037     }
3038
3039     if (node->type == XML_DOCUMENT_NODE) {
3040         doc = (xmlDocPtr) node;
3041     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3042         doc = (xmlDocPtr) node;
3043     } else {
3044         doc = node->doc;
3045     }
3046 #ifdef LIBXML_HTML_ENABLED
3047     if (doc->type == XML_HTML_DOCUMENT_NODE) {
3048         if (encoding == NULL)
3049             encoding = (const char *) htmlGetMetaEncoding(doc);
3050     }
3051 #endif /* LIBXML_HTML_ENABLED */
3052     if (encoding != NULL) {
3053         handler = xmlFindCharEncodingHandler(encoding);
3054         if (handler == NULL) {
3055             return (PyLong_FromLong((long) -1));
3056         }
3057     }
3058     if (doc->type == XML_HTML_DOCUMENT_NODE) {
3059         if (handler == NULL)
3060             handler = xmlFindCharEncodingHandler("HTML");
3061         if (handler == NULL)
3062             handler = xmlFindCharEncodingHandler("ascii");
3063     }
3064
3065     buf = xmlOutputBufferCreateFile(output, handler);
3066     if (node->type == XML_DOCUMENT_NODE) {
3067         len = xmlSaveFormatFileTo(buf, doc, encoding, format);
3068 #ifdef LIBXML_HTML_ENABLED
3069     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3070         htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
3071         len = xmlOutputBufferClose(buf);
3072     } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
3073         htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
3074         len = xmlOutputBufferClose(buf);
3075 #endif /* LIBXML_HTML_ENABLED */
3076     } else {
3077         xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
3078         len = xmlOutputBufferClose(buf);
3079     }
3080     PyFile_Release(output);
3081     return (PyLong_FromLong((long) len));
3082 }
3083 #endif /* LIBXML_OUTPUT_ENABLED */
3084
3085 /************************************************************************
3086  *                                                                      *
3087  *                      Extra stuff                                     *
3088  *                                                                      *
3089  ************************************************************************/
3090 PyObject *
3091 libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3092 {
3093     PyObject *py_retval;
3094     xmlChar *name;
3095     xmlNodePtr node;
3096
3097     if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
3098         return (NULL);
3099     node = (xmlNodePtr) xmlNewNode(NULL, name);
3100 #ifdef DEBUG
3101     printf("NewNode: %s : %p\n", name, (void *) node);
3102 #endif
3103
3104     if (node == NULL) {
3105         Py_INCREF(Py_None);
3106         return (Py_None);
3107     }
3108     py_retval = libxml_xmlNodePtrWrap(node);
3109     return (py_retval);
3110 }
3111
3112
3113 /************************************************************************
3114  *                                                                      *
3115  *                      Local Catalog stuff                             *
3116  *                                                                      *
3117  ************************************************************************/
3118 static PyObject *
3119 libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3120 {
3121     xmlChar *URL;
3122     xmlParserCtxtPtr ctxt;
3123     PyObject *pyobj_ctxt;
3124
3125     if (!PyArg_ParseTuple(args, (char *)"Os:addLocalCatalog", &pyobj_ctxt, &URL))
3126         return(NULL);
3127
3128     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
3129
3130     if (URL != NULL) {
3131         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
3132     }
3133
3134 #ifdef DEBUG
3135     printf("LocalCatalog: %s\n", URL);
3136 #endif
3137
3138     Py_INCREF(Py_None);
3139     return (Py_None);
3140 }
3141
3142 #ifdef LIBXML_SCHEMAS_ENABLED
3143
3144 /************************************************************************
3145  *                                                                      *
3146  * RelaxNG error handler registration                                   *
3147  *                                                                      *
3148  ************************************************************************/
3149
3150 typedef struct 
3151 {
3152     PyObject *warn;
3153     PyObject *error;
3154     PyObject *arg;
3155 } xmlRelaxNGValidCtxtPyCtxt;
3156 typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;
3157
3158 static void
3159 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str) 
3160 {
3161     PyObject *list;
3162     PyObject *result;
3163     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3164     
3165 #ifdef DEBUG_ERROR
3166     printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3167 #endif
3168
3169     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3170
3171     list = PyTuple_New(2);
3172     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3173     PyTuple_SetItem(list, 1, pyCtxt->arg);
3174     Py_XINCREF(pyCtxt->arg);
3175     result = PyEval_CallObject(pyCtxt->error, list);
3176     if (result == NULL) 
3177     {
3178         /* TODO: manage for the exception to be propagated... */
3179         PyErr_Print();
3180     }
3181     Py_XDECREF(list);
3182     Py_XDECREF(result);
3183 }
3184
3185 static void
3186 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str) 
3187 {
3188     PyObject *list;
3189     PyObject *result;
3190     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3191     
3192 #ifdef DEBUG_ERROR
3193     printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3194 #endif
3195
3196     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3197
3198     list = PyTuple_New(2);
3199     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3200     PyTuple_SetItem(list, 1, pyCtxt->arg);
3201     Py_XINCREF(pyCtxt->arg);
3202     result = PyEval_CallObject(pyCtxt->warn, list);
3203     if (result == NULL) 
3204     {
3205         /* TODO: manage for the exception to be propagated... */
3206         PyErr_Print();
3207     }
3208     Py_XDECREF(list);
3209     Py_XDECREF(result);
3210 }
3211
3212 static void
3213 libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
3214 {
3215     va_list ap;
3216
3217     va_start(ap, msg);
3218     libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3219     va_end(ap);
3220 }
3221
3222 static void
3223 libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
3224 {
3225     va_list ap;
3226
3227     va_start(ap, msg);
3228     libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3229     va_end(ap);
3230 }
3231
3232 static PyObject *
3233 libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3234 {
3235     PyObject *py_retval;
3236     PyObject *pyobj_error;
3237     PyObject *pyobj_warn;
3238     PyObject *pyobj_ctx;
3239     PyObject *pyobj_arg = Py_None;
3240     xmlRelaxNGValidCtxtPtr ctxt;
3241     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3242
3243     if (!PyArg_ParseTuple
3244         (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3245         return (NULL);
3246
3247 #ifdef DEBUG_ERROR
3248     printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3249 #endif
3250
3251     ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
3252     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3253     {
3254         py_retval = libxml_intWrap(-1);
3255         return(py_retval);
3256     }
3257     
3258     if (pyCtxt == NULL)
3259     {
3260         /* first time to set the error handlers */
3261         pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
3262         if (pyCtxt == NULL) {
3263             py_retval = libxml_intWrap(-1);
3264             return(py_retval);
3265         }
3266         memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
3267     }
3268     
3269     /* TODO: check warn and error is a function ! */
3270     Py_XDECREF(pyCtxt->error);
3271     Py_XINCREF(pyobj_error);
3272     pyCtxt->error = pyobj_error;
3273     
3274     Py_XDECREF(pyCtxt->warn);
3275     Py_XINCREF(pyobj_warn);
3276     pyCtxt->warn = pyobj_warn;
3277     
3278     Py_XDECREF(pyCtxt->arg);
3279     Py_XINCREF(pyobj_arg);
3280     pyCtxt->arg = pyobj_arg;
3281
3282     xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, &libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);
3283
3284     py_retval = libxml_intWrap(1);
3285     return (py_retval);
3286 }
3287
3288 static PyObject *
3289 libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
3290     xmlRelaxNGValidCtxtPtr ctxt;
3291     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3292     PyObject *pyobj_ctxt;
3293
3294     if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
3295         return(NULL);
3296     ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);
3297
3298     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3299     {
3300         if (pyCtxt != NULL)
3301         {
3302             Py_XDECREF(pyCtxt->error);
3303             Py_XDECREF(pyCtxt->warn);
3304             Py_XDECREF(pyCtxt->arg);
3305             xmlFree(pyCtxt);
3306         }
3307     }
3308     
3309     xmlRelaxNGFreeValidCtxt(ctxt);
3310     Py_INCREF(Py_None);
3311     return(Py_None);
3312 }
3313
3314 typedef struct
3315 {
3316         PyObject *warn;
3317         PyObject *error;
3318         PyObject *arg;
3319 } xmlSchemaValidCtxtPyCtxt;
3320 typedef xmlSchemaValidCtxtPyCtxt *xmlSchemaValidCtxtPyCtxtPtr;
3321
3322 static void
3323 libxml_xmlSchemaValidityGenericErrorFuncHandler(void *ctx, char *str)
3324 {
3325         PyObject *list;
3326         PyObject *result;
3327         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3328
3329 #ifdef DEBUG_ERROR
3330         printf("libxml_xmlSchemaValiditiyGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3331 #endif
3332
3333         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3334
3335         list = PyTuple_New(2);
3336         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3337         PyTuple_SetItem(list, 1, pyCtxt->arg);
3338         Py_XINCREF(pyCtxt->arg);
3339         result = PyEval_CallObject(pyCtxt->error, list);
3340         if (result == NULL) 
3341         {
3342                 /* TODO: manage for the exception to be propagated... */
3343                 PyErr_Print();
3344         }
3345         Py_XDECREF(list);
3346         Py_XDECREF(result);
3347 }
3348
3349 static void
3350 libxml_xmlSchemaValidityGenericWarningFuncHandler(void *ctx, char *str)
3351 {
3352         PyObject *list;
3353         PyObject *result;
3354         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3355
3356 #ifdef DEBUG_ERROR
3357         printf("libxml_xmlSchemaValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3358 #endif
3359         
3360         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3361
3362         list = PyTuple_New(2);
3363         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3364         PyTuple_SetItem(list, 1, pyCtxt->arg);
3365         Py_XINCREF(pyCtxt->arg);
3366         result = PyEval_CallObject(pyCtxt->warn, list);
3367         if (result == NULL)
3368         {
3369                 /* TODO: manage for the exception to be propagated... */
3370                 PyErr_Print();
3371         }
3372         Py_XDECREF(list);
3373         Py_XDECREF(result);
3374 }
3375
3376 static void
3377 libxml_xmlSchemaValidityErrorFunc(void *ctx, const char *msg, ...)
3378 {
3379         va_list ap;
3380         
3381         va_start(ap, msg);
3382         libxml_xmlSchemaValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3383         va_end(ap);
3384 }
3385
3386 static void
3387 libxml_xmlSchemaValidityWarningFunc(void *ctx, const char *msg, ...)
3388 {
3389         va_list ap;
3390
3391         va_start(ap, msg);
3392         libxml_xmlSchemaValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3393         va_end(ap);
3394 }
3395
3396 PyObject *
3397 libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3398 {
3399         PyObject *py_retval;
3400         PyObject *pyobj_error;
3401         PyObject *pyobj_warn;
3402         PyObject *pyobj_ctx;
3403         PyObject *pyobj_arg = Py_None;
3404         xmlSchemaValidCtxtPtr ctxt;
3405         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3406
3407         if (!PyArg_ParseTuple
3408                 (args, (char *) "OOO|O:xmlSchemaSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3409                 return (NULL);
3410
3411 #ifdef DEBUG_ERROR
3412         printf("libxml_xmlSchemaSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3413 #endif
3414
3415         ctxt = PySchemaValidCtxt_Get(pyobj_ctx);
3416         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3417         {
3418                 py_retval = libxml_intWrap(-1);
3419                 return(py_retval);
3420         }
3421
3422         if (pyCtxt == NULL)
3423         {
3424                 /* first time to set the error handlers */
3425                 pyCtxt = xmlMalloc(sizeof(xmlSchemaValidCtxtPyCtxt));
3426                 if (pyCtxt == NULL) {
3427                         py_retval = libxml_intWrap(-1);
3428                         return(py_retval);
3429                 }
3430                 memset(pyCtxt, 0, sizeof(xmlSchemaValidCtxtPyCtxt));
3431         }
3432
3433         /* TODO: check warn and error is a function ! */
3434         Py_XDECREF(pyCtxt->error);
3435         Py_XINCREF(pyobj_error);
3436         pyCtxt->error = pyobj_error;
3437
3438         Py_XDECREF(pyCtxt->warn);
3439         Py_XINCREF(pyobj_warn);
3440         pyCtxt->warn = pyobj_warn;
3441
3442         Py_XDECREF(pyCtxt->arg);
3443         Py_XINCREF(pyobj_arg);
3444         pyCtxt->arg = pyobj_arg;
3445
3446         xmlSchemaSetValidErrors(ctxt, &libxml_xmlSchemaValidityErrorFunc, &libxml_xmlSchemaValidityWarningFunc, pyCtxt);
3447
3448         py_retval = libxml_intWrap(1);
3449         return(py_retval);
3450 }
3451
3452 static PyObject *
3453 libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3454 {
3455         xmlSchemaValidCtxtPtr ctxt;
3456         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3457         PyObject *pyobj_ctxt;
3458
3459         if (!PyArg_ParseTuple(args, (char *)"O:xmlSchemaFreeValidCtxt", &pyobj_ctxt))
3460                 return(NULL);
3461         ctxt = (xmlSchemaValidCtxtPtr) PySchemaValidCtxt_Get(pyobj_ctxt);
3462
3463         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3464         {
3465                 if (pyCtxt != NULL)
3466                 {
3467                         Py_XDECREF(pyCtxt->error);
3468                         Py_XDECREF(pyCtxt->warn);
3469                         Py_XDECREF(pyCtxt->arg);
3470                         xmlFree(pyCtxt);
3471                 }
3472         }
3473
3474         xmlSchemaFreeValidCtxt(ctxt);
3475         Py_INCREF(Py_None);
3476         return(Py_None);
3477 }
3478
3479 #endif
3480
3481 #ifdef LIBXML_C14N_ENABLED
3482 #ifdef LIBXML_OUTPUT_ENABLED
3483
3484 /************************************************************************
3485  *                                                                      *
3486  * XML Canonicalization c14n                                            *
3487  *                                                                      *
3488  ************************************************************************/
3489
3490 static int
3491 PyxmlNodeSet_Convert(PyObject *py_nodeset, xmlNodeSetPtr *result)
3492 {
3493     xmlNodeSetPtr nodeSet;
3494     int is_tuple = 0;
3495
3496     if (PyTuple_Check(py_nodeset))
3497         is_tuple = 1;
3498     else if (PyList_Check(py_nodeset))
3499         is_tuple = 0;
3500     else if (py_nodeset == Py_None) {
3501         *result = NULL;
3502         return 0;
3503     }
3504     else {
3505         PyErr_SetString(PyExc_TypeError,
3506                         "must be a tuple or list of nodes.");
3507         return -1;
3508     }
3509
3510     nodeSet = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
3511     if (nodeSet == NULL) {
3512         PyErr_SetString(PyExc_MemoryError, "");
3513         return -1;
3514     }
3515
3516     nodeSet->nodeNr = 0;
3517     nodeSet->nodeMax = (is_tuple
3518                         ? PyTuple_GET_SIZE(py_nodeset)
3519                         : PyList_GET_SIZE(py_nodeset));
3520     nodeSet->nodeTab
3521         = (xmlNodePtr *) xmlMalloc (nodeSet->nodeMax
3522                                     * sizeof(xmlNodePtr));
3523     if (nodeSet->nodeTab == NULL) {
3524         xmlFree(nodeSet);
3525         PyErr_SetString(PyExc_MemoryError, "");
3526         return -1;
3527     }
3528     memset(nodeSet->nodeTab, 0 ,
3529            nodeSet->nodeMax * sizeof(xmlNodePtr));
3530
3531     {
3532         int idx;
3533         for (idx=0; idx < nodeSet->nodeMax; ++idx) {
3534             xmlNodePtr pynode =
3535                 PyxmlNode_Get (is_tuple
3536                                ? PyTuple_GET_ITEM(py_nodeset, idx)
3537                                : PyList_GET_ITEM(py_nodeset, idx));
3538             if (pynode)
3539                 nodeSet->nodeTab[nodeSet->nodeNr++] = pynode;
3540         }
3541     }
3542     *result = nodeSet;
3543     return 0;
3544 }
3545
3546 static int
3547 PystringSet_Convert(PyObject *py_strings, xmlChar *** result)
3548 {
3549     /* NOTE: the array should be freed, but the strings are shared
3550        with the python strings and so must not be freed. */
3551
3552     xmlChar ** strings;
3553     int is_tuple = 0;
3554     int count;
3555     int init_index = 0;
3556
3557     if (PyTuple_Check(py_strings))
3558         is_tuple = 1;
3559     else if (PyList_Check(py_strings))
3560         is_tuple = 0;
3561     else if (py_strings == Py_None) {
3562         *result = NULL;
3563         return 0;
3564     }
3565     else {
3566         PyErr_SetString(PyExc_TypeError,
3567                         "must be a tuple or list of strings.");
3568         return -1;
3569     }
3570
3571     count = (is_tuple
3572              ? PyTuple_GET_SIZE(py_strings)
3573              : PyList_GET_SIZE(py_strings));
3574
3575     strings = (xmlChar **) xmlMalloc(sizeof(xmlChar *) * count);
3576
3577     if (strings == NULL) {
3578         PyErr_SetString(PyExc_MemoryError, "");
3579         return -1;
3580     }
3581
3582     memset(strings, 0 , sizeof(xmlChar *) * count);
3583
3584     {
3585         int idx;
3586         for (idx=0; idx < count; ++idx) {
3587             char* s = PyBytes_AsString
3588                 (is_tuple
3589                  ? PyTuple_GET_ITEM(py_strings, idx)
3590                  : PyList_GET_ITEM(py_strings, idx));
3591             if (s)
3592                 strings[init_index++] = (xmlChar *)s;
3593             else {
3594                 xmlFree(strings);
3595                 PyErr_SetString(PyExc_TypeError,
3596                                 "must be a tuple or list of strings.");
3597                 return -1;
3598             }
3599         }
3600     }
3601
3602     *result = strings;
3603     return 0;
3604 }
3605
3606 static PyObject *
3607 libxml_C14NDocDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
3608                          PyObject * args)
3609 {
3610     PyObject *py_retval = NULL;
3611
3612     PyObject *pyobj_doc;
3613     PyObject *pyobj_nodes;
3614     int exclusive;
3615     PyObject *pyobj_prefixes;
3616     int with_comments;
3617
3618     xmlDocPtr doc;
3619     xmlNodeSetPtr nodes;
3620     xmlChar **prefixes = NULL;
3621     xmlChar *doc_txt;
3622
3623     int result;
3624
3625     if (!PyArg_ParseTuple(args, (char *) "OOiOi:C14NDocDumpMemory",
3626                           &pyobj_doc,
3627                           &pyobj_nodes,
3628                           &exclusive,
3629                           &pyobj_prefixes,
3630                           &with_comments))
3631         return (NULL);
3632
3633     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3634     if (!doc) {
3635         PyErr_SetString(PyExc_TypeError, "bad document.");
3636         return NULL;
3637     }
3638
3639     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3640     if (result < 0) return NULL;
3641
3642     if (exclusive) {
3643         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3644         if (result < 0) {
3645             if (nodes) {
3646                 xmlFree(nodes->nodeTab);
3647                 xmlFree(nodes);
3648             }
3649             return NULL;
3650         }
3651     }
3652
3653     result = xmlC14NDocDumpMemory(doc,
3654                                   nodes,
3655                                   exclusive,
3656                                   prefixes,
3657                                   with_comments,
3658                                   &doc_txt);
3659
3660     if (nodes) {
3661         xmlFree(nodes->nodeTab);
3662         xmlFree(nodes);
3663     }
3664     if (prefixes) {
3665         xmlChar ** idx = prefixes;
3666         while (*idx) xmlFree(*(idx++));
3667         xmlFree(prefixes);
3668     }
3669
3670     if (result < 0) {
3671         PyErr_SetString(PyExc_Exception,
3672                         "libxml2 xmlC14NDocDumpMemory failure.");
3673         return NULL;
3674     }
3675     else {
3676         py_retval = PY_IMPORT_STRING_SIZE((const char *) doc_txt,
3677                                                 result);
3678         xmlFree(doc_txt);
3679         return py_retval;
3680     }
3681 }
3682
3683 static PyObject *
3684 libxml_C14NDocSaveTo(ATTRIBUTE_UNUSED PyObject * self,
3685                      PyObject * args)
3686 {
3687     PyObject *pyobj_doc;
3688     PyObject *py_file;
3689     PyObject *pyobj_nodes;
3690     int exclusive;
3691     PyObject *pyobj_prefixes;
3692     int with_comments;
3693
3694     xmlDocPtr doc;
3695     xmlNodeSetPtr nodes;
3696     xmlChar **prefixes = NULL;
3697     FILE * output;
3698     xmlOutputBufferPtr buf;
3699
3700     int result;
3701     int len;
3702
3703     if (!PyArg_ParseTuple(args, (char *) "OOiOiO:C14NDocSaveTo",
3704                           &pyobj_doc,
3705                           &pyobj_nodes,
3706                           &exclusive,
3707                           &pyobj_prefixes,
3708                           &with_comments,
3709                           &py_file))
3710         return (NULL);
3711
3712     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3713     if (!doc) {
3714         PyErr_SetString(PyExc_TypeError, "bad document.");
3715         return NULL;
3716     }
3717
3718     output = PyFile_Get(py_file);
3719     if (output == NULL) {
3720         PyErr_SetString(PyExc_TypeError, "bad file.");
3721         return NULL;
3722     }
3723     buf = xmlOutputBufferCreateFile(output, NULL);
3724
3725     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3726     if (result < 0) return NULL;
3727
3728     if (exclusive) {
3729         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3730         if (result < 0) {
3731             if (nodes) {
3732                 xmlFree(nodes->nodeTab);
3733                 xmlFree(nodes);
3734             }
3735             return NULL;
3736         }
3737     }
3738
3739     result = xmlC14NDocSaveTo(doc,
3740                               nodes,
3741                               exclusive,
3742                               prefixes,
3743                               with_comments,
3744                               buf);
3745
3746     if (nodes) {
3747         xmlFree(nodes->nodeTab);
3748         xmlFree(nodes);
3749     }
3750     if (prefixes) {
3751         xmlChar ** idx = prefixes;
3752         while (*idx) xmlFree(*(idx++));
3753         xmlFree(prefixes);
3754     }
3755
3756     PyFile_Release(output);
3757     len = xmlOutputBufferClose(buf);
3758
3759     if (result < 0) {
3760         PyErr_SetString(PyExc_Exception,
3761                         "libxml2 xmlC14NDocSaveTo failure.");
3762         return NULL;
3763     }
3764     else
3765         return PyLong_FromLong((long) len);
3766 }
3767
3768 #endif
3769 #endif
3770
3771 static PyObject *
3772 libxml_getObjDesc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3773
3774     PyObject *obj;
3775     char *str;
3776
3777     if (!PyArg_ParseTuple(args, (char *)"O:getObjDesc", &obj))
3778         return NULL;
3779     str = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj));
3780     return Py_BuildValue((char *)"s", str);
3781 }
3782
3783 static PyObject *
3784 libxml_compareNodesEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3785     
3786     PyObject *py_node1, *py_node2;
3787     xmlNodePtr node1, node2;
3788
3789     if (!PyArg_ParseTuple(args, (char *)"OO:compareNodesEqual",
3790                 &py_node1, &py_node2))
3791         return NULL;
3792     /* To compare two node objects, we compare their pointer addresses */
3793     node1 = PyxmlNode_Get(py_node1);
3794     node2 = PyxmlNode_Get(py_node2);
3795     if ( node1 == node2 )
3796         return Py_BuildValue((char *)"i", 1);
3797     else
3798         return Py_BuildValue((char *)"i", 0);
3799     
3800 }
3801
3802 static PyObject *
3803 libxml_nodeHash(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3804
3805     PyObject *py_node1;
3806     xmlNodePtr node1;
3807
3808     if (!PyArg_ParseTuple(args, (char *)"O:nodeHash", &py_node1))
3809             return NULL;
3810     /* For simplicity, we use the node pointer address as a hash value */
3811     node1 = PyxmlNode_Get(py_node1);
3812
3813     return PyLong_FromVoidPtr(node1);
3814
3815 }
3816
3817 /************************************************************************
3818  *                                                                      *
3819  *                      The registration stuff                          *
3820  *                                                                      *
3821  ************************************************************************/
3822 static PyMethodDef libxmlMethods[] = {
3823 #include "libxml2-export.c"
3824     {(char *) "name", libxml_name, METH_VARARGS, NULL},
3825     {(char *) "children", libxml_children, METH_VARARGS, NULL},
3826     {(char *) "properties", libxml_properties, METH_VARARGS, NULL},
3827     {(char *) "last", libxml_last, METH_VARARGS, NULL},
3828     {(char *) "prev", libxml_prev, METH_VARARGS, NULL},
3829     {(char *) "next", libxml_next, METH_VARARGS, NULL},
3830     {(char *) "parent", libxml_parent, METH_VARARGS, NULL},
3831     {(char *) "type", libxml_type, METH_VARARGS, NULL},
3832     {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
3833     {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
3834     {(char *) "xmlNodeRemoveNsDef", libxml_xmlNodeRemoveNsDef, METH_VARARGS, NULL},
3835     {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL},
3836     {(char *)"xmlFreeValidCtxt", libxml_xmlFreeValidCtxt, METH_VARARGS, NULL},
3837 #ifdef LIBXML_OUTPUT_ENABLED
3838     {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
3839     {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
3840     {(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
3841     {(char *) "outputBufferGetPythonFile", libxml_outputBufferGetPythonFile, METH_VARARGS, NULL},
3842     {(char *) "xmlOutputBufferClose", libxml_xmlOutputBufferClose, METH_VARARGS, NULL},
3843     { (char *)"xmlOutputBufferFlush", libxml_xmlOutputBufferFlush, METH_VARARGS, NULL },
3844     { (char *)"xmlSaveFileTo", libxml_xmlSaveFileTo, METH_VARARGS, NULL },
3845     { (char *)"xmlSaveFormatFileTo", libxml_xmlSaveFormatFileTo, METH_VARARGS, NULL },
3846 #endif /* LIBXML_OUTPUT_ENABLED */
3847     {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
3848     {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
3849     {(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
3850     {(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
3851     {(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
3852     {(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
3853 #ifdef LIBXML_READER_ENABLED
3854     {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
3855     {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
3856     {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
3857 #endif
3858     {(char *)"addLocalCatalog", libxml_addLocalCatalog, METH_VARARGS, NULL },
3859 #ifdef LIBXML_SCHEMAS_ENABLED
3860     {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
3861     {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
3862     {(char *)"xmlSchemaSetValidErrors", libxml_xmlSchemaSetValidErrors, METH_VARARGS, NULL},
3863     {(char *)"xmlSchemaFreeValidCtxt", libxml_xmlSchemaFreeValidCtxt, METH_VARARGS, NULL},
3864 #endif
3865 #ifdef LIBXML_C14N_ENABLED
3866 #ifdef LIBXML_OUTPUT_ENABLED
3867     {(char *)"xmlC14NDocDumpMemory", libxml_C14NDocDumpMemory, METH_VARARGS, NULL},
3868     {(char *)"xmlC14NDocSaveTo", libxml_C14NDocSaveTo, METH_VARARGS, NULL},
3869 #endif
3870 #endif
3871     {(char *) "getObjDesc", libxml_getObjDesc, METH_VARARGS, NULL},
3872     {(char *) "compareNodesEqual", libxml_compareNodesEqual, METH_VARARGS, NULL},
3873     {(char *) "nodeHash", libxml_nodeHash, METH_VARARGS, NULL},
3874     {(char *) "xmlRegisterInputCallback", libxml_xmlRegisterInputCallback, METH_VARARGS, NULL},
3875     {(char *) "xmlUnregisterInputCallback", libxml_xmlUnregisterInputCallback, METH_VARARGS, NULL},
3876     {NULL, NULL, 0, NULL}
3877 };
3878
3879 #if PY_MAJOR_VERSION >= 3
3880 #define INITERROR return NULL
3881
3882 static struct PyModuleDef moduledef = {
3883         PyModuleDef_HEAD_INIT,
3884         "libxml2mod",
3885         NULL,
3886         -1,
3887         libxmlMethods,
3888         NULL,
3889         NULL,
3890         NULL,
3891         NULL
3892 };
3893
3894 #else
3895 #define INITERROR return
3896
3897 #ifdef MERGED_MODULES
3898 extern void initlibxsltmod(void);
3899 #endif
3900
3901 #endif
3902
3903 #if PY_MAJOR_VERSION >= 3
3904 PyObject *PyInit_libxml2mod(void)
3905 #else
3906 void initlibxml2mod(void)
3907 #endif
3908 {
3909     PyObject *module;
3910
3911 #if PY_MAJOR_VERSION >= 3
3912     module = PyModule_Create(&moduledef);
3913 #else
3914     /* intialize the python extension module */
3915     module = Py_InitModule((char *) "libxml2mod", libxmlMethods);
3916 #endif
3917     if (module == NULL)
3918         INITERROR;
3919
3920     /* initialize libxml2 */
3921     xmlInitParser();
3922     /* TODO this probably need to be revamped for Python3 */
3923     libxml_xmlErrorInitialize();
3924
3925 #if PY_MAJOR_VERSION < 3
3926 #ifdef MERGED_MODULES
3927     initlibxsltmod();
3928 #endif
3929 #endif
3930
3931 #if PY_MAJOR_VERSION >= 3
3932     return module;
3933 #endif
3934 }