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