Imported Upstream version 2.9.1
[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         size_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         size_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             }
2687         default:
2688             res = NULL;
2689             break;
2690     }
2691     resultobj = libxml_xmlNodePtrWrap(res);
2692     return resultobj;
2693 }
2694
2695 static PyObject *
2696 libxml_parent(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2697 {
2698     PyObject *resultobj, *obj;
2699     xmlNodePtr cur;
2700     xmlNodePtr res;
2701
2702     if (!PyArg_ParseTuple(args, (char *) "O:parent", &obj))
2703         return NULL;
2704     cur = PyxmlNode_Get(obj);
2705
2706 #ifdef DEBUG
2707     printf("libxml_parent: cur = %p\n", cur);
2708 #endif
2709
2710     switch (cur->type) {
2711         case XML_DOCUMENT_NODE:
2712         case XML_HTML_DOCUMENT_NODE:
2713 #ifdef LIBXML_DOCB_ENABLED
2714         case XML_DOCB_DOCUMENT_NODE:
2715 #endif
2716             res = NULL;
2717             break;
2718         case XML_ATTRIBUTE_NODE:{
2719                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2720
2721                 res = attr->parent;
2722             }
2723             break;
2724         case XML_ENTITY_DECL:
2725         case XML_NAMESPACE_DECL:
2726         case XML_XINCLUDE_START:
2727         case XML_XINCLUDE_END:
2728             res = NULL;
2729             break;
2730         default:
2731             res = cur->parent;
2732             break;
2733     }
2734     resultobj = libxml_xmlNodePtrWrap(res);
2735     return resultobj;
2736 }
2737
2738 static PyObject *
2739 libxml_type(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2740 {
2741     PyObject *resultobj, *obj;
2742     xmlNodePtr cur;
2743     const xmlChar *res = NULL;
2744
2745     if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2746         return NULL;
2747     cur = PyxmlNode_Get(obj);
2748     if (cur == NULL) {
2749         Py_INCREF(Py_None);
2750         return (Py_None);
2751     }
2752
2753 #ifdef DEBUG
2754     printf("libxml_type: cur = %p\n", cur);
2755 #endif
2756
2757     switch (cur->type) {
2758         case XML_ELEMENT_NODE:
2759             res = (const xmlChar *) "element";
2760             break;
2761         case XML_ATTRIBUTE_NODE:
2762             res = (const xmlChar *) "attribute";
2763             break;
2764         case XML_TEXT_NODE:
2765             res = (const xmlChar *) "text";
2766             break;
2767         case XML_CDATA_SECTION_NODE:
2768             res = (const xmlChar *) "cdata";
2769             break;
2770         case XML_ENTITY_REF_NODE:
2771             res = (const xmlChar *) "entity_ref";
2772             break;
2773         case XML_ENTITY_NODE:
2774             res = (const xmlChar *) "entity";
2775             break;
2776         case XML_PI_NODE:
2777             res = (const xmlChar *) "pi";
2778             break;
2779         case XML_COMMENT_NODE:
2780             res = (const xmlChar *) "comment";
2781             break;
2782         case XML_DOCUMENT_NODE:
2783             res = (const xmlChar *) "document_xml";
2784             break;
2785         case XML_DOCUMENT_TYPE_NODE:
2786             res = (const xmlChar *) "doctype";
2787             break;
2788         case XML_DOCUMENT_FRAG_NODE:
2789             res = (const xmlChar *) "fragment";
2790             break;
2791         case XML_NOTATION_NODE:
2792             res = (const xmlChar *) "notation";
2793             break;
2794         case XML_HTML_DOCUMENT_NODE:
2795             res = (const xmlChar *) "document_html";
2796             break;
2797         case XML_DTD_NODE:
2798             res = (const xmlChar *) "dtd";
2799             break;
2800         case XML_ELEMENT_DECL:
2801             res = (const xmlChar *) "elem_decl";
2802             break;
2803         case XML_ATTRIBUTE_DECL:
2804             res = (const xmlChar *) "attribute_decl";
2805             break;
2806         case XML_ENTITY_DECL:
2807             res = (const xmlChar *) "entity_decl";
2808             break;
2809         case XML_NAMESPACE_DECL:
2810             res = (const xmlChar *) "namespace";
2811             break;
2812         case XML_XINCLUDE_START:
2813             res = (const xmlChar *) "xinclude_start";
2814             break;
2815         case XML_XINCLUDE_END:
2816             res = (const xmlChar *) "xinclude_end";
2817             break;
2818 #ifdef LIBXML_DOCB_ENABLED
2819         case XML_DOCB_DOCUMENT_NODE:
2820             res = (const xmlChar *) "document_docbook";
2821             break;
2822 #endif
2823     }
2824 #ifdef DEBUG
2825     printf("libxml_type: cur = %p: %s\n", cur, res);
2826 #endif
2827
2828     resultobj = libxml_constxmlCharPtrWrap(res);
2829     return resultobj;
2830 }
2831
2832 /************************************************************************
2833  *                                                                      *
2834  *                      Specific accessor functions                     *
2835  *                                                                      *
2836  ************************************************************************/
2837 PyObject *
2838 libxml_xmlNodeGetNsDefs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2839 {
2840     PyObject *py_retval;
2841     xmlNsPtr c_retval;
2842     xmlNodePtr node;
2843     PyObject *pyobj_node;
2844
2845     if (!PyArg_ParseTuple
2846         (args, (char *) "O:xmlNodeGetNsDefs", &pyobj_node))
2847         return (NULL);
2848     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2849
2850     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2851         Py_INCREF(Py_None);
2852         return (Py_None);
2853     }
2854     c_retval = node->nsDef;
2855     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2856     return (py_retval);
2857 }
2858
2859 PyObject *
2860 libxml_xmlNodeRemoveNsDef(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2861 {
2862     PyObject *py_retval;
2863     xmlNsPtr ns, prev;
2864     xmlNodePtr node;
2865     PyObject *pyobj_node;
2866     xmlChar *href;
2867     xmlNsPtr c_retval;
2868
2869     if (!PyArg_ParseTuple
2870         (args, (char *) "Oz:xmlNodeRemoveNsDef", &pyobj_node, &href))
2871         return (NULL);
2872     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2873     ns = NULL;
2874
2875     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2876         Py_INCREF(Py_None);
2877         return (Py_None);
2878     }
2879
2880     if (href == NULL) {
2881         ns = node->nsDef;
2882         node->nsDef = NULL;
2883         c_retval = 0;
2884     }
2885     else {
2886         prev = NULL;
2887         ns = node->nsDef;
2888         while (ns != NULL) {
2889             if (xmlStrEqual(ns->href, href)) {
2890                 if (prev != NULL)
2891                     prev->next = ns->next;
2892                 else
2893                     node->nsDef = ns->next;
2894                 ns->next = NULL;
2895                 c_retval = 0;
2896                 break;
2897             }
2898             prev = ns;
2899             ns = ns->next;
2900         }
2901     }
2902
2903     c_retval = ns;
2904     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2905     return (py_retval);
2906 }
2907
2908 PyObject *
2909 libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2910 {
2911     PyObject *py_retval;
2912     xmlNsPtr c_retval;
2913     xmlNodePtr node;
2914     PyObject *pyobj_node;
2915
2916     if (!PyArg_ParseTuple(args, (char *) "O:xmlNodeGetNs", &pyobj_node))
2917         return (NULL);
2918     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2919
2920     if ((node == NULL) ||
2921         ((node->type != XML_ELEMENT_NODE) &&
2922          (node->type != XML_ATTRIBUTE_NODE))) {
2923         Py_INCREF(Py_None);
2924         return (Py_None);
2925     }
2926     c_retval = node->ns;
2927     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2928     return (py_retval);
2929 }
2930
2931 #ifdef LIBXML_OUTPUT_ENABLED
2932 /************************************************************************
2933  *                                                                      *
2934  *                      Serialization front-end                         *
2935  *                                                                      *
2936  ************************************************************************/
2937
2938 static PyObject *
2939 libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2940 {
2941     PyObject *py_retval = NULL;
2942     xmlChar *c_retval;
2943     PyObject *pyobj_node;
2944     xmlNodePtr node;
2945     xmlDocPtr doc;
2946     const char *encoding;
2947     int format;
2948     xmlSaveCtxtPtr ctxt;
2949     xmlBufferPtr buf;
2950     int options = 0;
2951
2952     if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
2953                           &encoding, &format))
2954         return (NULL);
2955     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2956
2957     if (node == NULL) {
2958         Py_INCREF(Py_None);
2959         return (Py_None);
2960     }
2961     if (node->type == XML_DOCUMENT_NODE) {
2962         doc = (xmlDocPtr) node;
2963         node = NULL;
2964 #ifdef LIBXML_HTML_ENABLED
2965     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2966         doc = (xmlDocPtr) node;
2967         node = NULL;
2968 #endif
2969     } else {
2970         if (node->type == XML_NAMESPACE_DECL)
2971             doc = NULL;
2972         else
2973             doc = node->doc;
2974         if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
2975 #ifdef LIBXML_HTML_ENABLED
2976         } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2977 #endif /* LIBXML_HTML_ENABLED */
2978         } else {
2979             Py_INCREF(Py_None);
2980             return (Py_None);
2981         }
2982     }
2983
2984
2985     buf = xmlBufferCreate();
2986     if (buf == NULL) {
2987         Py_INCREF(Py_None);
2988         return (Py_None);
2989     }
2990     if (format) options |= XML_SAVE_FORMAT;
2991     ctxt = xmlSaveToBuffer(buf, encoding, options);
2992     if (ctxt == NULL) {
2993         xmlBufferFree(buf);
2994         Py_INCREF(Py_None);
2995         return (Py_None);
2996     }
2997     if (node == NULL)
2998         xmlSaveDoc(ctxt, doc);
2999     else
3000         xmlSaveTree(ctxt, node);
3001     xmlSaveClose(ctxt);
3002
3003     c_retval = buf->content;
3004     buf->content = NULL;
3005
3006     xmlBufferFree(buf);
3007     py_retval = libxml_charPtrWrap((char *) c_retval);
3008
3009     return (py_retval);
3010 }
3011
3012 static PyObject *
3013 libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3014 {
3015     PyObject *py_file = NULL;
3016     FILE *output;
3017     PyObject *pyobj_node;
3018     xmlNodePtr node;
3019     xmlDocPtr doc;
3020     const char *encoding;
3021     int format;
3022     int len;
3023     xmlOutputBufferPtr buf;
3024     xmlCharEncodingHandlerPtr handler = NULL;
3025
3026     if (!PyArg_ParseTuple(args, (char *) "OOzi:serializeNode", &pyobj_node,
3027                           &py_file, &encoding, &format))
3028         return (NULL);
3029     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
3030     if (node == NULL) {
3031         return (PyLong_FromLong((long) -1));
3032     }
3033     output = PyFile_Get(py_file);
3034     if (output == NULL) {
3035         return (PyLong_FromLong((long) -1));
3036     }
3037
3038     if (node->type == XML_DOCUMENT_NODE) {
3039         doc = (xmlDocPtr) node;
3040     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3041         doc = (xmlDocPtr) node;
3042     } else {
3043         doc = node->doc;
3044     }
3045 #ifdef LIBXML_HTML_ENABLED
3046     if (doc->type == XML_HTML_DOCUMENT_NODE) {
3047         if (encoding == NULL)
3048             encoding = (const char *) htmlGetMetaEncoding(doc);
3049     }
3050 #endif /* LIBXML_HTML_ENABLED */
3051     if (encoding != NULL) {
3052         handler = xmlFindCharEncodingHandler(encoding);
3053         if (handler == NULL) {
3054             return (PyLong_FromLong((long) -1));
3055         }
3056     }
3057     if (doc->type == XML_HTML_DOCUMENT_NODE) {
3058         if (handler == NULL)
3059             handler = xmlFindCharEncodingHandler("HTML");
3060         if (handler == NULL)
3061             handler = xmlFindCharEncodingHandler("ascii");
3062     }
3063
3064     buf = xmlOutputBufferCreateFile(output, handler);
3065     if (node->type == XML_DOCUMENT_NODE) {
3066         len = xmlSaveFormatFileTo(buf, doc, encoding, format);
3067 #ifdef LIBXML_HTML_ENABLED
3068     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3069         htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
3070         len = xmlOutputBufferClose(buf);
3071     } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
3072         htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
3073         len = xmlOutputBufferClose(buf);
3074 #endif /* LIBXML_HTML_ENABLED */
3075     } else {
3076         xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
3077         len = xmlOutputBufferClose(buf);
3078     }
3079     PyFile_Release(output);
3080     return (PyLong_FromLong((long) len));
3081 }
3082 #endif /* LIBXML_OUTPUT_ENABLED */
3083
3084 /************************************************************************
3085  *                                                                      *
3086  *                      Extra stuff                                     *
3087  *                                                                      *
3088  ************************************************************************/
3089 PyObject *
3090 libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3091 {
3092     PyObject *py_retval;
3093     xmlChar *name;
3094     xmlNodePtr node;
3095
3096     if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
3097         return (NULL);
3098     node = (xmlNodePtr) xmlNewNode(NULL, name);
3099 #ifdef DEBUG
3100     printf("NewNode: %s : %p\n", name, (void *) node);
3101 #endif
3102
3103     if (node == NULL) {
3104         Py_INCREF(Py_None);
3105         return (Py_None);
3106     }
3107     py_retval = libxml_xmlNodePtrWrap(node);
3108     return (py_retval);
3109 }
3110
3111
3112 /************************************************************************
3113  *                                                                      *
3114  *                      Local Catalog stuff                             *
3115  *                                                                      *
3116  ************************************************************************/
3117 static PyObject *
3118 libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3119 {
3120     xmlChar *URL;
3121     xmlParserCtxtPtr ctxt;
3122     PyObject *pyobj_ctxt;
3123
3124     if (!PyArg_ParseTuple(args, (char *)"Os:addLocalCatalog", &pyobj_ctxt, &URL))
3125         return(NULL);
3126
3127     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
3128
3129     if (URL != NULL) {
3130         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
3131     }
3132
3133 #ifdef DEBUG
3134     printf("LocalCatalog: %s\n", URL);
3135 #endif
3136
3137     Py_INCREF(Py_None);
3138     return (Py_None);
3139 }
3140
3141 #ifdef LIBXML_SCHEMAS_ENABLED
3142
3143 /************************************************************************
3144  *                                                                      *
3145  * RelaxNG error handler registration                                   *
3146  *                                                                      *
3147  ************************************************************************/
3148
3149 typedef struct 
3150 {
3151     PyObject *warn;
3152     PyObject *error;
3153     PyObject *arg;
3154 } xmlRelaxNGValidCtxtPyCtxt;
3155 typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;
3156
3157 static void
3158 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str) 
3159 {
3160     PyObject *list;
3161     PyObject *result;
3162     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3163     
3164 #ifdef DEBUG_ERROR
3165     printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3166 #endif
3167
3168     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3169
3170     list = PyTuple_New(2);
3171     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3172     PyTuple_SetItem(list, 1, pyCtxt->arg);
3173     Py_XINCREF(pyCtxt->arg);
3174     result = PyEval_CallObject(pyCtxt->error, list);
3175     if (result == NULL) 
3176     {
3177         /* TODO: manage for the exception to be propagated... */
3178         PyErr_Print();
3179     }
3180     Py_XDECREF(list);
3181     Py_XDECREF(result);
3182 }
3183
3184 static void
3185 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str) 
3186 {
3187     PyObject *list;
3188     PyObject *result;
3189     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3190     
3191 #ifdef DEBUG_ERROR
3192     printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3193 #endif
3194
3195     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3196
3197     list = PyTuple_New(2);
3198     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3199     PyTuple_SetItem(list, 1, pyCtxt->arg);
3200     Py_XINCREF(pyCtxt->arg);
3201     result = PyEval_CallObject(pyCtxt->warn, list);
3202     if (result == NULL) 
3203     {
3204         /* TODO: manage for the exception to be propagated... */
3205         PyErr_Print();
3206     }
3207     Py_XDECREF(list);
3208     Py_XDECREF(result);
3209 }
3210
3211 static void
3212 libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
3213 {
3214     va_list ap;
3215
3216     va_start(ap, msg);
3217     libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3218     va_end(ap);
3219 }
3220
3221 static void
3222 libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
3223 {
3224     va_list ap;
3225
3226     va_start(ap, msg);
3227     libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3228     va_end(ap);
3229 }
3230
3231 static PyObject *
3232 libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3233 {
3234     PyObject *py_retval;
3235     PyObject *pyobj_error;
3236     PyObject *pyobj_warn;
3237     PyObject *pyobj_ctx;
3238     PyObject *pyobj_arg = Py_None;
3239     xmlRelaxNGValidCtxtPtr ctxt;
3240     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3241
3242     if (!PyArg_ParseTuple
3243         (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3244         return (NULL);
3245
3246 #ifdef DEBUG_ERROR
3247     printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3248 #endif
3249
3250     ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
3251     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3252     {
3253         py_retval = libxml_intWrap(-1);
3254         return(py_retval);
3255     }
3256     
3257     if (pyCtxt == NULL)
3258     {
3259         /* first time to set the error handlers */
3260         pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
3261         if (pyCtxt == NULL) {
3262             py_retval = libxml_intWrap(-1);
3263             return(py_retval);
3264         }
3265         memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
3266     }
3267     
3268     /* TODO: check warn and error is a function ! */
3269     Py_XDECREF(pyCtxt->error);
3270     Py_XINCREF(pyobj_error);
3271     pyCtxt->error = pyobj_error;
3272     
3273     Py_XDECREF(pyCtxt->warn);
3274     Py_XINCREF(pyobj_warn);
3275     pyCtxt->warn = pyobj_warn;
3276     
3277     Py_XDECREF(pyCtxt->arg);
3278     Py_XINCREF(pyobj_arg);
3279     pyCtxt->arg = pyobj_arg;
3280
3281     xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, &libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);
3282
3283     py_retval = libxml_intWrap(1);
3284     return (py_retval);
3285 }
3286
3287 static PyObject *
3288 libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
3289     xmlRelaxNGValidCtxtPtr ctxt;
3290     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3291     PyObject *pyobj_ctxt;
3292
3293     if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
3294         return(NULL);
3295     ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);
3296
3297     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3298     {
3299         if (pyCtxt != NULL)
3300         {
3301             Py_XDECREF(pyCtxt->error);
3302             Py_XDECREF(pyCtxt->warn);
3303             Py_XDECREF(pyCtxt->arg);
3304             xmlFree(pyCtxt);
3305         }
3306     }
3307     
3308     xmlRelaxNGFreeValidCtxt(ctxt);
3309     Py_INCREF(Py_None);
3310     return(Py_None);
3311 }
3312
3313 typedef struct
3314 {
3315         PyObject *warn;
3316         PyObject *error;
3317         PyObject *arg;
3318 } xmlSchemaValidCtxtPyCtxt;
3319 typedef xmlSchemaValidCtxtPyCtxt *xmlSchemaValidCtxtPyCtxtPtr;
3320
3321 static void
3322 libxml_xmlSchemaValidityGenericErrorFuncHandler(void *ctx, char *str)
3323 {
3324         PyObject *list;
3325         PyObject *result;
3326         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3327
3328 #ifdef DEBUG_ERROR
3329         printf("libxml_xmlSchemaValiditiyGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3330 #endif
3331
3332         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3333
3334         list = PyTuple_New(2);
3335         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3336         PyTuple_SetItem(list, 1, pyCtxt->arg);
3337         Py_XINCREF(pyCtxt->arg);
3338         result = PyEval_CallObject(pyCtxt->error, list);
3339         if (result == NULL) 
3340         {
3341                 /* TODO: manage for the exception to be propagated... */
3342                 PyErr_Print();
3343         }
3344         Py_XDECREF(list);
3345         Py_XDECREF(result);
3346 }
3347
3348 static void
3349 libxml_xmlSchemaValidityGenericWarningFuncHandler(void *ctx, char *str)
3350 {
3351         PyObject *list;
3352         PyObject *result;
3353         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3354
3355 #ifdef DEBUG_ERROR
3356         printf("libxml_xmlSchemaValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3357 #endif
3358         
3359         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3360
3361         list = PyTuple_New(2);
3362         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3363         PyTuple_SetItem(list, 1, pyCtxt->arg);
3364         Py_XINCREF(pyCtxt->arg);
3365         result = PyEval_CallObject(pyCtxt->warn, list);
3366         if (result == NULL)
3367         {
3368                 /* TODO: manage for the exception to be propagated... */
3369                 PyErr_Print();
3370         }
3371         Py_XDECREF(list);
3372         Py_XDECREF(result);
3373 }
3374
3375 static void
3376 libxml_xmlSchemaValidityErrorFunc(void *ctx, const char *msg, ...)
3377 {
3378         va_list ap;
3379         
3380         va_start(ap, msg);
3381         libxml_xmlSchemaValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3382         va_end(ap);
3383 }
3384
3385 static void
3386 libxml_xmlSchemaValidityWarningFunc(void *ctx, const char *msg, ...)
3387 {
3388         va_list ap;
3389
3390         va_start(ap, msg);
3391         libxml_xmlSchemaValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3392         va_end(ap);
3393 }
3394
3395 PyObject *
3396 libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3397 {
3398         PyObject *py_retval;
3399         PyObject *pyobj_error;
3400         PyObject *pyobj_warn;
3401         PyObject *pyobj_ctx;
3402         PyObject *pyobj_arg = Py_None;
3403         xmlSchemaValidCtxtPtr ctxt;
3404         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3405
3406         if (!PyArg_ParseTuple
3407                 (args, (char *) "OOO|O:xmlSchemaSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3408                 return (NULL);
3409
3410 #ifdef DEBUG_ERROR
3411         printf("libxml_xmlSchemaSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3412 #endif
3413
3414         ctxt = PySchemaValidCtxt_Get(pyobj_ctx);
3415         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3416         {
3417                 py_retval = libxml_intWrap(-1);
3418                 return(py_retval);
3419         }
3420
3421         if (pyCtxt == NULL)
3422         {
3423                 /* first time to set the error handlers */
3424                 pyCtxt = xmlMalloc(sizeof(xmlSchemaValidCtxtPyCtxt));
3425                 if (pyCtxt == NULL) {
3426                         py_retval = libxml_intWrap(-1);
3427                         return(py_retval);
3428                 }
3429                 memset(pyCtxt, 0, sizeof(xmlSchemaValidCtxtPyCtxt));
3430         }
3431
3432         /* TODO: check warn and error is a function ! */
3433         Py_XDECREF(pyCtxt->error);
3434         Py_XINCREF(pyobj_error);
3435         pyCtxt->error = pyobj_error;
3436
3437         Py_XDECREF(pyCtxt->warn);
3438         Py_XINCREF(pyobj_warn);
3439         pyCtxt->warn = pyobj_warn;
3440
3441         Py_XDECREF(pyCtxt->arg);
3442         Py_XINCREF(pyobj_arg);
3443         pyCtxt->arg = pyobj_arg;
3444
3445         xmlSchemaSetValidErrors(ctxt, &libxml_xmlSchemaValidityErrorFunc, &libxml_xmlSchemaValidityWarningFunc, pyCtxt);
3446
3447         py_retval = libxml_intWrap(1);
3448         return(py_retval);
3449 }
3450
3451 static PyObject *
3452 libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3453 {
3454         xmlSchemaValidCtxtPtr ctxt;
3455         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3456         PyObject *pyobj_ctxt;
3457
3458         if (!PyArg_ParseTuple(args, (char *)"O:xmlSchemaFreeValidCtxt", &pyobj_ctxt))
3459                 return(NULL);
3460         ctxt = (xmlSchemaValidCtxtPtr) PySchemaValidCtxt_Get(pyobj_ctxt);
3461
3462         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3463         {
3464                 if (pyCtxt != NULL)
3465                 {
3466                         Py_XDECREF(pyCtxt->error);
3467                         Py_XDECREF(pyCtxt->warn);
3468                         Py_XDECREF(pyCtxt->arg);
3469                         xmlFree(pyCtxt);
3470                 }
3471         }
3472
3473         xmlSchemaFreeValidCtxt(ctxt);
3474         Py_INCREF(Py_None);
3475         return(Py_None);
3476 }
3477
3478 #endif
3479
3480 #ifdef LIBXML_C14N_ENABLED
3481 #ifdef LIBXML_OUTPUT_ENABLED
3482
3483 /************************************************************************
3484  *                                                                      *
3485  * XML Canonicalization c14n                                            *
3486  *                                                                      *
3487  ************************************************************************/
3488
3489 static int
3490 PyxmlNodeSet_Convert(PyObject *py_nodeset, xmlNodeSetPtr *result)
3491 {
3492     xmlNodeSetPtr nodeSet;
3493     int is_tuple = 0;
3494
3495     if (PyTuple_Check(py_nodeset))
3496         is_tuple = 1;
3497     else if (PyList_Check(py_nodeset))
3498         is_tuple = 0;
3499     else if (py_nodeset == Py_None) {
3500         *result = NULL;
3501         return 0;
3502     }
3503     else {
3504         PyErr_SetString(PyExc_TypeError,
3505                         "must be a tuple or list of nodes.");
3506         return -1;
3507     }
3508
3509     nodeSet = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
3510     if (nodeSet == NULL) {
3511         PyErr_SetString(PyExc_MemoryError, "");
3512         return -1;
3513     }
3514
3515     nodeSet->nodeNr = 0;
3516     nodeSet->nodeMax = (is_tuple
3517                         ? PyTuple_GET_SIZE(py_nodeset)
3518                         : PyList_GET_SIZE(py_nodeset));
3519     nodeSet->nodeTab
3520         = (xmlNodePtr *) xmlMalloc (nodeSet->nodeMax
3521                                     * sizeof(xmlNodePtr));
3522     if (nodeSet->nodeTab == NULL) {
3523         xmlFree(nodeSet);
3524         PyErr_SetString(PyExc_MemoryError, "");
3525         return -1;
3526     }
3527     memset(nodeSet->nodeTab, 0 ,
3528            nodeSet->nodeMax * sizeof(xmlNodePtr));
3529
3530     {
3531         int idx;
3532         for (idx=0; idx < nodeSet->nodeMax; ++idx) {
3533             xmlNodePtr pynode =
3534                 PyxmlNode_Get (is_tuple
3535                                ? PyTuple_GET_ITEM(py_nodeset, idx)
3536                                : PyList_GET_ITEM(py_nodeset, idx));
3537             if (pynode)
3538                 nodeSet->nodeTab[nodeSet->nodeNr++] = pynode;
3539         }
3540     }
3541     *result = nodeSet;
3542     return 0;
3543 }
3544
3545 static int
3546 PystringSet_Convert(PyObject *py_strings, xmlChar *** result)
3547 {
3548     /* NOTE: the array should be freed, but the strings are shared
3549        with the python strings and so must not be freed. */
3550
3551     xmlChar ** strings;
3552     int is_tuple = 0;
3553     int count;
3554     int init_index = 0;
3555
3556     if (PyTuple_Check(py_strings))
3557         is_tuple = 1;
3558     else if (PyList_Check(py_strings))
3559         is_tuple = 0;
3560     else if (py_strings == Py_None) {
3561         *result = NULL;
3562         return 0;
3563     }
3564     else {
3565         PyErr_SetString(PyExc_TypeError,
3566                         "must be a tuple or list of strings.");
3567         return -1;
3568     }
3569
3570     count = (is_tuple
3571              ? PyTuple_GET_SIZE(py_strings)
3572              : PyList_GET_SIZE(py_strings));
3573
3574     strings = (xmlChar **) xmlMalloc(sizeof(xmlChar *) * count);
3575
3576     if (strings == NULL) {
3577         PyErr_SetString(PyExc_MemoryError, "");
3578         return -1;
3579     }
3580
3581     memset(strings, 0 , sizeof(xmlChar *) * count);
3582
3583     {
3584         int idx;
3585         for (idx=0; idx < count; ++idx) {
3586             char* s = PyBytes_AsString
3587                 (is_tuple
3588                  ? PyTuple_GET_ITEM(py_strings, idx)
3589                  : PyList_GET_ITEM(py_strings, idx));
3590             if (s)
3591                 strings[init_index++] = (xmlChar *)s;
3592             else {
3593                 xmlFree(strings);
3594                 PyErr_SetString(PyExc_TypeError,
3595                                 "must be a tuple or list of strings.");
3596                 return -1;
3597             }
3598         }
3599     }
3600
3601     *result = strings;
3602     return 0;
3603 }
3604
3605 static PyObject *
3606 libxml_C14NDocDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
3607                          PyObject * args)
3608 {
3609     PyObject *py_retval = NULL;
3610
3611     PyObject *pyobj_doc;
3612     PyObject *pyobj_nodes;
3613     int exclusive;
3614     PyObject *pyobj_prefixes;
3615     int with_comments;
3616
3617     xmlDocPtr doc;
3618     xmlNodeSetPtr nodes;
3619     xmlChar **prefixes = NULL;
3620     xmlChar *doc_txt;
3621
3622     int result;
3623
3624     if (!PyArg_ParseTuple(args, (char *) "OOiOi:C14NDocDumpMemory",
3625                           &pyobj_doc,
3626                           &pyobj_nodes,
3627                           &exclusive,
3628                           &pyobj_prefixes,
3629                           &with_comments))
3630         return (NULL);
3631
3632     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3633     if (!doc) {
3634         PyErr_SetString(PyExc_TypeError, "bad document.");
3635         return NULL;
3636     }
3637
3638     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3639     if (result < 0) return NULL;
3640
3641     if (exclusive) {
3642         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3643         if (result < 0) {
3644             if (nodes) {
3645                 xmlFree(nodes->nodeTab);
3646                 xmlFree(nodes);
3647             }
3648             return NULL;
3649         }
3650     }
3651
3652     result = xmlC14NDocDumpMemory(doc,
3653                                   nodes,
3654                                   exclusive,
3655                                   prefixes,
3656                                   with_comments,
3657                                   &doc_txt);
3658
3659     if (nodes) {
3660         xmlFree(nodes->nodeTab);
3661         xmlFree(nodes);
3662     }
3663     if (prefixes) {
3664         xmlChar ** idx = prefixes;
3665         while (*idx) xmlFree(*(idx++));
3666         xmlFree(prefixes);
3667     }
3668
3669     if (result < 0) {
3670         PyErr_SetString(PyExc_Exception,
3671                         "libxml2 xmlC14NDocDumpMemory failure.");
3672         return NULL;
3673     }
3674     else {
3675         py_retval = PY_IMPORT_STRING_SIZE((const char *) doc_txt,
3676                                                 result);
3677         xmlFree(doc_txt);
3678         return py_retval;
3679     }
3680 }
3681
3682 static PyObject *
3683 libxml_C14NDocSaveTo(ATTRIBUTE_UNUSED PyObject * self,
3684                      PyObject * args)
3685 {
3686     PyObject *pyobj_doc;
3687     PyObject *py_file;
3688     PyObject *pyobj_nodes;
3689     int exclusive;
3690     PyObject *pyobj_prefixes;
3691     int with_comments;
3692
3693     xmlDocPtr doc;
3694     xmlNodeSetPtr nodes;
3695     xmlChar **prefixes = NULL;
3696     FILE * output;
3697     xmlOutputBufferPtr buf;
3698
3699     int result;
3700     int len;
3701
3702     if (!PyArg_ParseTuple(args, (char *) "OOiOiO:C14NDocSaveTo",
3703                           &pyobj_doc,
3704                           &pyobj_nodes,
3705                           &exclusive,
3706                           &pyobj_prefixes,
3707                           &with_comments,
3708                           &py_file))
3709         return (NULL);
3710
3711     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3712     if (!doc) {
3713         PyErr_SetString(PyExc_TypeError, "bad document.");
3714         return NULL;
3715     }
3716
3717     output = PyFile_Get(py_file);
3718     if (output == NULL) {
3719         PyErr_SetString(PyExc_TypeError, "bad file.");
3720         return NULL;
3721     }
3722     buf = xmlOutputBufferCreateFile(output, NULL);
3723
3724     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3725     if (result < 0) return NULL;
3726
3727     if (exclusive) {
3728         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3729         if (result < 0) {
3730             if (nodes) {
3731                 xmlFree(nodes->nodeTab);
3732                 xmlFree(nodes);
3733             }
3734             return NULL;
3735         }
3736     }
3737
3738     result = xmlC14NDocSaveTo(doc,
3739                               nodes,
3740                               exclusive,
3741                               prefixes,
3742                               with_comments,
3743                               buf);
3744
3745     if (nodes) {
3746         xmlFree(nodes->nodeTab);
3747         xmlFree(nodes);
3748     }
3749     if (prefixes) {
3750         xmlChar ** idx = prefixes;
3751         while (*idx) xmlFree(*(idx++));
3752         xmlFree(prefixes);
3753     }
3754
3755     PyFile_Release(output);
3756     len = xmlOutputBufferClose(buf);
3757
3758     if (result < 0) {
3759         PyErr_SetString(PyExc_Exception,
3760                         "libxml2 xmlC14NDocSaveTo failure.");
3761         return NULL;
3762     }
3763     else
3764         return PyLong_FromLong((long) len);
3765 }
3766
3767 #endif
3768 #endif
3769
3770 static PyObject *
3771 libxml_getObjDesc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3772
3773     PyObject *obj;
3774     char *str;
3775
3776     if (!PyArg_ParseTuple(args, (char *)"O:getObjDesc", &obj))
3777         return NULL;
3778     str = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj));
3779     return Py_BuildValue((char *)"s", str);
3780 }
3781
3782 static PyObject *
3783 libxml_compareNodesEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3784     
3785     PyObject *py_node1, *py_node2;
3786     xmlNodePtr node1, node2;
3787
3788     if (!PyArg_ParseTuple(args, (char *)"OO:compareNodesEqual",
3789                 &py_node1, &py_node2))
3790         return NULL;
3791     /* To compare two node objects, we compare their pointer addresses */
3792     node1 = PyxmlNode_Get(py_node1);
3793     node2 = PyxmlNode_Get(py_node2);
3794     if ( node1 == node2 )
3795         return Py_BuildValue((char *)"i", 1);
3796     else
3797         return Py_BuildValue((char *)"i", 0);
3798     
3799 }
3800
3801 static PyObject *
3802 libxml_nodeHash(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3803
3804     PyObject *py_node1;
3805     xmlNodePtr node1;
3806
3807     if (!PyArg_ParseTuple(args, (char *)"O:nodeHash", &py_node1))
3808             return NULL;
3809     /* For simplicity, we use the node pointer address as a hash value */
3810     node1 = PyxmlNode_Get(py_node1);
3811
3812     return PyLong_FromVoidPtr(node1);
3813
3814 }
3815
3816 /************************************************************************
3817  *                                                                      *
3818  *                      The registration stuff                          *
3819  *                                                                      *
3820  ************************************************************************/
3821 static PyMethodDef libxmlMethods[] = {
3822 #include "libxml2-export.c"
3823     {(char *) "name", libxml_name, METH_VARARGS, NULL},
3824     {(char *) "children", libxml_children, METH_VARARGS, NULL},
3825     {(char *) "properties", libxml_properties, METH_VARARGS, NULL},
3826     {(char *) "last", libxml_last, METH_VARARGS, NULL},
3827     {(char *) "prev", libxml_prev, METH_VARARGS, NULL},
3828     {(char *) "next", libxml_next, METH_VARARGS, NULL},
3829     {(char *) "parent", libxml_parent, METH_VARARGS, NULL},
3830     {(char *) "type", libxml_type, METH_VARARGS, NULL},
3831     {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
3832     {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
3833     {(char *) "xmlNodeRemoveNsDef", libxml_xmlNodeRemoveNsDef, METH_VARARGS, NULL},
3834     {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL},
3835     {(char *)"xmlFreeValidCtxt", libxml_xmlFreeValidCtxt, METH_VARARGS, NULL},
3836 #ifdef LIBXML_OUTPUT_ENABLED
3837     {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
3838     {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
3839     {(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
3840     {(char *) "outputBufferGetPythonFile", libxml_outputBufferGetPythonFile, METH_VARARGS, NULL},
3841     {(char *) "xmlOutputBufferClose", libxml_xmlOutputBufferClose, METH_VARARGS, NULL},
3842     { (char *)"xmlOutputBufferFlush", libxml_xmlOutputBufferFlush, METH_VARARGS, NULL },
3843     { (char *)"xmlSaveFileTo", libxml_xmlSaveFileTo, METH_VARARGS, NULL },
3844     { (char *)"xmlSaveFormatFileTo", libxml_xmlSaveFormatFileTo, METH_VARARGS, NULL },
3845 #endif /* LIBXML_OUTPUT_ENABLED */
3846     {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
3847     {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
3848     {(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
3849     {(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
3850     {(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
3851     {(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
3852 #ifdef LIBXML_READER_ENABLED
3853     {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
3854     {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
3855     {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
3856 #endif
3857     {(char *)"addLocalCatalog", libxml_addLocalCatalog, METH_VARARGS, NULL },
3858 #ifdef LIBXML_SCHEMAS_ENABLED
3859     {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
3860     {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
3861     {(char *)"xmlSchemaSetValidErrors", libxml_xmlSchemaSetValidErrors, METH_VARARGS, NULL},
3862     {(char *)"xmlSchemaFreeValidCtxt", libxml_xmlSchemaFreeValidCtxt, METH_VARARGS, NULL},
3863 #endif
3864 #ifdef LIBXML_C14N_ENABLED
3865 #ifdef LIBXML_OUTPUT_ENABLED
3866     {(char *)"xmlC14NDocDumpMemory", libxml_C14NDocDumpMemory, METH_VARARGS, NULL},
3867     {(char *)"xmlC14NDocSaveTo", libxml_C14NDocSaveTo, METH_VARARGS, NULL},
3868 #endif
3869 #endif
3870     {(char *) "getObjDesc", libxml_getObjDesc, METH_VARARGS, NULL},
3871     {(char *) "compareNodesEqual", libxml_compareNodesEqual, METH_VARARGS, NULL},
3872     {(char *) "nodeHash", libxml_nodeHash, METH_VARARGS, NULL},
3873     {(char *) "xmlRegisterInputCallback", libxml_xmlRegisterInputCallback, METH_VARARGS, NULL},
3874     {(char *) "xmlUnregisterInputCallback", libxml_xmlUnregisterInputCallback, METH_VARARGS, NULL},
3875     {NULL, NULL, 0, NULL}
3876 };
3877
3878 #if PY_MAJOR_VERSION >= 3
3879 #define INITERROR return NULL
3880
3881 static struct PyModuleDef moduledef = {
3882         PyModuleDef_HEAD_INIT,
3883         "libxml2mod",
3884         NULL,
3885         -1,
3886         libxmlMethods,
3887         NULL,
3888         NULL,
3889         NULL,
3890         NULL
3891 };
3892
3893 #else
3894 #define INITERROR return
3895
3896 #ifdef MERGED_MODULES
3897 extern void initlibxsltmod(void);
3898 #endif
3899
3900 #endif
3901
3902 #if PY_MAJOR_VERSION >= 3
3903 PyObject *PyInit_libxml2mod(void)
3904 #else
3905 void initlibxml2mod(void)
3906 #endif
3907 {
3908     PyObject *module;
3909
3910 #if PY_MAJOR_VERSION >= 3
3911     module = PyModule_Create(&moduledef);
3912 #else
3913     /* intialize the python extension module */
3914     module = Py_InitModule((char *) "libxml2mod", libxmlMethods);
3915 #endif
3916     if (module == NULL)
3917         INITERROR;
3918
3919     /* initialize libxml2 */
3920     xmlInitParser();
3921     /* TODO this probably need to be revamped for Python3 */
3922     libxml_xmlErrorInitialize();
3923
3924 #if PY_MAJOR_VERSION < 3
3925 #ifdef MERGED_MODULES
3926     initlibxsltmod();
3927 #endif
3928 #endif
3929
3930 #if PY_MAJOR_VERSION >= 3
3931     return module;
3932 #endif
3933 }