9dabf8985ea7a9fd8806a619b06d8a26307551db
[platform/upstream/libxml2.git] / python / libxml.c
1 /*
2  * libxml.c: this modules implements the main part of the glue of the
3  *           libxml2 library and the Python interpreter. It provides the
4  *           entry points where an automatically generated stub is either
5  *           unpractical or would not match cleanly the Python model.
6  *
7  * If compiled with MERGED_MODULES, the entry point will be used to
8  * initialize both the libxml2 and the libxslt wrappers
9  *
10  * See Copyright for the status of this software.
11  *
12  * daniel@veillard.com
13  */
14 #include <Python.h>
15 #include <fileobject.h>
16 /* #include "config.h" */
17 #include <libxml/xmlmemory.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
20 #include <libxml/xpath.h>
21 #include <libxml/xmlerror.h>
22 #include <libxml/xpathInternals.h>
23 #include <libxml/xmlmemory.h>
24 #include <libxml/xmlIO.h>
25 #include <libxml/c14n.h>
26 #include <libxml/xmlreader.h>
27 #include <libxml/xmlsave.h>
28 #include "libxml_wrap.h"
29 #include "libxml2-py.h"
30
31 #if defined(_MSC_VER) && !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, ATTRIBUTE_UNUSED 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, ATTRIBUTE_UNUSED 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     xmlSaveCtxtPtr ctxt;
2766     xmlBufferPtr buf;
2767     int options = 0;
2768
2769     if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
2770                           &encoding, &format))
2771         return (NULL);
2772     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2773
2774     if (node == NULL) {
2775         Py_INCREF(Py_None);
2776         return (Py_None);
2777     }
2778     if (node->type == XML_DOCUMENT_NODE) {
2779         doc = (xmlDocPtr) node;
2780         node = NULL;
2781 #ifdef LIBXML_HTML_ENABLED
2782     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2783         doc = (xmlDocPtr) node;
2784         node = NULL;
2785 #endif
2786     } else {
2787         if (node->type == XML_NAMESPACE_DECL)
2788             doc = NULL;
2789         else
2790             doc = node->doc;
2791         if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
2792 #ifdef LIBXML_HTML_ENABLED
2793         } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2794 #endif /* LIBXML_HTML_ENABLED */
2795         } else {
2796             Py_INCREF(Py_None);
2797             return (Py_None);
2798         }
2799     }
2800
2801
2802     buf = xmlBufferCreate();
2803     if (buf == NULL) {
2804         Py_INCREF(Py_None);
2805         return (Py_None);
2806     }
2807     if (format) options |= XML_SAVE_FORMAT;
2808     ctxt = xmlSaveToBuffer(buf, encoding, options);
2809     if (ctxt == NULL) {
2810         xmlBufferFree(buf);
2811         Py_INCREF(Py_None);
2812         return (Py_None);
2813     }
2814     if (node == NULL)
2815         xmlSaveDoc(ctxt, doc);
2816     else
2817         xmlSaveTree(ctxt, node);
2818     xmlSaveClose(ctxt);
2819
2820     c_retval = buf->content;
2821     buf->content = NULL;
2822
2823     xmlBufferFree(buf);
2824     py_retval = libxml_charPtrWrap((char *) c_retval);
2825
2826     return (py_retval);
2827 }
2828
2829 static PyObject *
2830 libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2831 {
2832     PyObject *py_file = NULL;
2833     FILE *output;
2834     PyObject *pyobj_node;
2835     xmlNodePtr node;
2836     xmlDocPtr doc;
2837     const char *encoding;
2838     int format;
2839     int len;
2840     xmlOutputBufferPtr buf;
2841     xmlCharEncodingHandlerPtr handler = NULL;
2842
2843     if (!PyArg_ParseTuple(args, (char *) "OOzi:serializeNode", &pyobj_node,
2844                           &py_file, &encoding, &format))
2845         return (NULL);
2846     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2847
2848     if (node == NULL) {
2849         return (PyInt_FromLong((long) -1));
2850     }
2851     if ((py_file == NULL) || (!(PyFile_Check(py_file)))) {
2852         return (PyInt_FromLong((long) -1));
2853     }
2854     output = PyFile_AsFile(py_file);
2855     if (output == NULL) {
2856         return (PyInt_FromLong((long) -1));
2857     }
2858
2859     if (node->type == XML_DOCUMENT_NODE) {
2860         doc = (xmlDocPtr) node;
2861     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2862         doc = (xmlDocPtr) node;
2863     } else {
2864         doc = node->doc;
2865     }
2866 #ifdef LIBXML_HTML_ENABLED
2867     if (doc->type == XML_HTML_DOCUMENT_NODE) {
2868         if (encoding == NULL)
2869             encoding = (const char *) htmlGetMetaEncoding(doc);
2870     }
2871 #endif /* LIBXML_HTML_ENABLED */
2872     if (encoding != NULL) {
2873         handler = xmlFindCharEncodingHandler(encoding);
2874         if (handler == NULL) {
2875             return (PyInt_FromLong((long) -1));
2876         }
2877     }
2878     if (doc->type == XML_HTML_DOCUMENT_NODE) {
2879         if (handler == NULL)
2880             handler = xmlFindCharEncodingHandler("HTML");
2881         if (handler == NULL)
2882             handler = xmlFindCharEncodingHandler("ascii");
2883     }
2884
2885     buf = xmlOutputBufferCreateFile(output, handler);
2886     if (node->type == XML_DOCUMENT_NODE) {
2887         len = xmlSaveFormatFileTo(buf, doc, encoding, format);
2888 #ifdef LIBXML_HTML_ENABLED
2889     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2890         htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
2891         len = xmlOutputBufferClose(buf);
2892     } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2893         htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
2894         len = xmlOutputBufferClose(buf);
2895 #endif /* LIBXML_HTML_ENABLED */
2896     } else {
2897         xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
2898         len = xmlOutputBufferClose(buf);
2899     }
2900     return (PyInt_FromLong((long) len));
2901 }
2902 #endif /* LIBXML_OUTPUT_ENABLED */
2903
2904 /************************************************************************
2905  *                                                                      *
2906  *                      Extra stuff                                     *
2907  *                                                                      *
2908  ************************************************************************/
2909 PyObject *
2910 libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2911 {
2912     PyObject *py_retval;
2913     xmlChar *name;
2914     xmlNodePtr node;
2915
2916     if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
2917         return (NULL);
2918     node = (xmlNodePtr) xmlNewNode(NULL, name);
2919 #ifdef DEBUG
2920     printf("NewNode: %s : %p\n", name, (void *) node);
2921 #endif
2922
2923     if (node == NULL) {
2924         Py_INCREF(Py_None);
2925         return (Py_None);
2926     }
2927     py_retval = libxml_xmlNodePtrWrap(node);
2928     return (py_retval);
2929 }
2930
2931
2932 /************************************************************************
2933  *                                                                      *
2934  *                      Local Catalog stuff                             *
2935  *                                                                      *
2936  ************************************************************************/
2937 static PyObject *
2938 libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2939 {
2940     xmlChar *URL;
2941     xmlParserCtxtPtr ctxt;
2942     PyObject *pyobj_ctxt;
2943
2944     if (!PyArg_ParseTuple(args, (char *)"Os:addLocalCatalog", &pyobj_ctxt, &URL))
2945         return(NULL);
2946
2947     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
2948
2949     if (URL != NULL) {
2950         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
2951     }
2952
2953 #ifdef DEBUG
2954     printf("LocalCatalog: %s\n", URL);
2955 #endif
2956
2957     Py_INCREF(Py_None);
2958     return (Py_None);
2959 }
2960
2961 #ifdef LIBXML_SCHEMAS_ENABLED
2962
2963 /************************************************************************
2964  *                                                                      *
2965  * RelaxNG error handler registration                                   *
2966  *                                                                      *
2967  ************************************************************************/
2968
2969 typedef struct 
2970 {
2971     PyObject *warn;
2972     PyObject *error;
2973     PyObject *arg;
2974 } xmlRelaxNGValidCtxtPyCtxt;
2975 typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;
2976
2977 static void
2978 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str) 
2979 {
2980     PyObject *list;
2981     PyObject *result;
2982     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
2983     
2984 #ifdef DEBUG_ERROR
2985     printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
2986 #endif
2987
2988     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
2989
2990     list = PyTuple_New(2);
2991     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
2992     PyTuple_SetItem(list, 1, pyCtxt->arg);
2993     Py_XINCREF(pyCtxt->arg);
2994     result = PyEval_CallObject(pyCtxt->error, list);
2995     if (result == NULL) 
2996     {
2997         /* TODO: manage for the exception to be propagated... */
2998         PyErr_Print();
2999     }
3000     Py_XDECREF(list);
3001     Py_XDECREF(result);
3002 }
3003
3004 static void
3005 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str) 
3006 {
3007     PyObject *list;
3008     PyObject *result;
3009     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3010     
3011 #ifdef DEBUG_ERROR
3012     printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3013 #endif
3014
3015     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3016
3017     list = PyTuple_New(2);
3018     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3019     PyTuple_SetItem(list, 1, pyCtxt->arg);
3020     Py_XINCREF(pyCtxt->arg);
3021     result = PyEval_CallObject(pyCtxt->warn, list);
3022     if (result == NULL) 
3023     {
3024         /* TODO: manage for the exception to be propagated... */
3025         PyErr_Print();
3026     }
3027     Py_XDECREF(list);
3028     Py_XDECREF(result);
3029 }
3030
3031 static void
3032 libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
3033 {
3034     va_list ap;
3035
3036     va_start(ap, msg);
3037     libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3038     va_end(ap);
3039 }
3040
3041 static void
3042 libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
3043 {
3044     va_list ap;
3045
3046     va_start(ap, msg);
3047     libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3048     va_end(ap);
3049 }
3050
3051 static PyObject *
3052 libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3053 {
3054     PyObject *py_retval;
3055     PyObject *pyobj_error;
3056     PyObject *pyobj_warn;
3057     PyObject *pyobj_ctx;
3058     PyObject *pyobj_arg = Py_None;
3059     xmlRelaxNGValidCtxtPtr ctxt;
3060     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3061
3062     if (!PyArg_ParseTuple
3063         (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3064         return (NULL);
3065
3066 #ifdef DEBUG_ERROR
3067     printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3068 #endif
3069
3070     ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
3071     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3072     {
3073         py_retval = libxml_intWrap(-1);
3074         return(py_retval);
3075     }
3076     
3077     if (pyCtxt == NULL)
3078     {
3079         /* first time to set the error handlers */
3080         pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
3081         if (pyCtxt == NULL) {
3082             py_retval = libxml_intWrap(-1);
3083             return(py_retval);
3084         }
3085         memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
3086     }
3087     
3088     /* TODO: check warn and error is a function ! */
3089     Py_XDECREF(pyCtxt->error);
3090     Py_XINCREF(pyobj_error);
3091     pyCtxt->error = pyobj_error;
3092     
3093     Py_XDECREF(pyCtxt->warn);
3094     Py_XINCREF(pyobj_warn);
3095     pyCtxt->warn = pyobj_warn;
3096     
3097     Py_XDECREF(pyCtxt->arg);
3098     Py_XINCREF(pyobj_arg);
3099     pyCtxt->arg = pyobj_arg;
3100
3101     xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, &libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);
3102
3103     py_retval = libxml_intWrap(1);
3104     return (py_retval);
3105 }
3106
3107 static PyObject *
3108 libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
3109     xmlRelaxNGValidCtxtPtr ctxt;
3110     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3111     PyObject *pyobj_ctxt;
3112
3113     if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
3114         return(NULL);
3115     ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);
3116
3117     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3118     {
3119         if (pyCtxt != NULL)
3120         {
3121             Py_XDECREF(pyCtxt->error);
3122             Py_XDECREF(pyCtxt->warn);
3123             Py_XDECREF(pyCtxt->arg);
3124             xmlFree(pyCtxt);
3125         }
3126     }
3127     
3128     xmlRelaxNGFreeValidCtxt(ctxt);
3129     Py_INCREF(Py_None);
3130     return(Py_None);
3131 }
3132
3133 typedef struct
3134 {
3135         PyObject *warn;
3136         PyObject *error;
3137         PyObject *arg;
3138 } xmlSchemaValidCtxtPyCtxt;
3139 typedef xmlSchemaValidCtxtPyCtxt *xmlSchemaValidCtxtPyCtxtPtr;
3140
3141 static void
3142 libxml_xmlSchemaValidityGenericErrorFuncHandler(void *ctx, char *str)
3143 {
3144         PyObject *list;
3145         PyObject *result;
3146         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3147
3148 #ifdef DEBUG_ERROR
3149         printf("libxml_xmlSchemaValiditiyGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3150 #endif
3151
3152         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3153
3154         list = PyTuple_New(2);
3155         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3156         PyTuple_SetItem(list, 1, pyCtxt->arg);
3157         Py_XINCREF(pyCtxt->arg);
3158         result = PyEval_CallObject(pyCtxt->error, list);
3159         if (result == NULL) 
3160         {
3161                 /* TODO: manage for the exception to be propagated... */
3162                 PyErr_Print();
3163         }
3164         Py_XDECREF(list);
3165         Py_XDECREF(result);
3166 }
3167
3168 static void
3169 libxml_xmlSchemaValidityGenericWarningFuncHandler(void *ctx, char *str)
3170 {
3171         PyObject *list;
3172         PyObject *result;
3173         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3174
3175 #ifdef DEBUG_ERROR
3176         printf("libxml_xmlSchemaValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3177 #endif
3178         
3179         pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3180
3181         list = PyTuple_New(2);
3182         PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3183         PyTuple_SetItem(list, 1, pyCtxt->arg);
3184         Py_XINCREF(pyCtxt->arg);
3185         result = PyEval_CallObject(pyCtxt->warn, list);
3186         if (result == NULL)
3187         {
3188                 /* TODO: manage for the exception to be propagated... */
3189                 PyErr_Print();
3190         }
3191         Py_XDECREF(list);
3192         Py_XDECREF(result);
3193 }
3194
3195 static void
3196 libxml_xmlSchemaValidityErrorFunc(void *ctx, const char *msg, ...)
3197 {
3198         va_list ap;
3199         
3200         va_start(ap, msg);
3201         libxml_xmlSchemaValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3202         va_end(ap);
3203 }
3204
3205 static void
3206 libxml_xmlSchemaValidityWarningFunc(void *ctx, const char *msg, ...)
3207 {
3208         va_list ap;
3209
3210         va_start(ap, msg);
3211         libxml_xmlSchemaValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3212         va_end(ap);
3213 }
3214
3215 PyObject *
3216 libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3217 {
3218         PyObject *py_retval;
3219         PyObject *pyobj_error;
3220         PyObject *pyobj_warn;
3221         PyObject *pyobj_ctx;
3222         PyObject *pyobj_arg = Py_None;
3223         xmlSchemaValidCtxtPtr ctxt;
3224         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3225
3226         if (!PyArg_ParseTuple
3227                 (args, (char *) "OOO|O:xmlSchemaSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3228                 return (NULL);
3229
3230 #ifdef DEBUG_ERROR
3231         printf("libxml_xmlSchemaSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3232 #endif
3233
3234         ctxt = PySchemaValidCtxt_Get(pyobj_ctx);
3235         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3236         {
3237                 py_retval = libxml_intWrap(-1);
3238                 return(py_retval);
3239         }
3240
3241         if (pyCtxt == NULL)
3242         {
3243                 /* first time to set the error handlers */
3244                 pyCtxt = xmlMalloc(sizeof(xmlSchemaValidCtxtPyCtxt));
3245                 if (pyCtxt == NULL) {
3246                         py_retval = libxml_intWrap(-1);
3247                         return(py_retval);
3248                 }
3249                 memset(pyCtxt, 0, sizeof(xmlSchemaValidCtxtPyCtxt));
3250         }
3251
3252         /* TODO: check warn and error is a function ! */
3253         Py_XDECREF(pyCtxt->error);
3254         Py_XINCREF(pyobj_error);
3255         pyCtxt->error = pyobj_error;
3256
3257         Py_XDECREF(pyCtxt->warn);
3258         Py_XINCREF(pyobj_warn);
3259         pyCtxt->warn = pyobj_warn;
3260
3261         Py_XDECREF(pyCtxt->arg);
3262         Py_XINCREF(pyobj_arg);
3263         pyCtxt->arg = pyobj_arg;
3264
3265         xmlSchemaSetValidErrors(ctxt, &libxml_xmlSchemaValidityErrorFunc, &libxml_xmlSchemaValidityWarningFunc, pyCtxt);
3266
3267         py_retval = libxml_intWrap(1);
3268         return(py_retval);
3269 }
3270
3271 static PyObject *
3272 libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3273 {
3274         xmlSchemaValidCtxtPtr ctxt;
3275         xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3276         PyObject *pyobj_ctxt;
3277
3278         if (!PyArg_ParseTuple(args, (char *)"O:xmlSchemaFreeValidCtxt", &pyobj_ctxt))
3279                 return(NULL);
3280         ctxt = (xmlSchemaValidCtxtPtr) PySchemaValidCtxt_Get(pyobj_ctxt);
3281
3282         if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3283         {
3284                 if (pyCtxt != NULL)
3285                 {
3286                         Py_XDECREF(pyCtxt->error);
3287                         Py_XDECREF(pyCtxt->warn);
3288                         Py_XDECREF(pyCtxt->arg);
3289                         xmlFree(pyCtxt);
3290                 }
3291         }
3292
3293         xmlSchemaFreeValidCtxt(ctxt);
3294         Py_INCREF(Py_None);
3295         return(Py_None);
3296 }
3297
3298 #endif
3299
3300 #ifdef LIBXML_C14N_ENABLED
3301 #ifdef LIBXML_OUTPUT_ENABLED
3302
3303 /************************************************************************
3304  *                                                                      *
3305  * XML Canonicalization c14n                                            *
3306  *                                                                      *
3307  ************************************************************************/
3308
3309 static int
3310 PyxmlNodeSet_Convert(PyObject *py_nodeset, xmlNodeSetPtr *result)
3311 {
3312     xmlNodeSetPtr nodeSet;
3313     int is_tuple = 0;
3314
3315     if (PyTuple_Check(py_nodeset))
3316         is_tuple = 1;
3317     else if (PyList_Check(py_nodeset))
3318         is_tuple = 0;
3319     else if (py_nodeset == Py_None) {
3320         *result = NULL;
3321         return 0;
3322     }
3323     else {
3324         PyErr_SetString(PyExc_TypeError,
3325                         "must be a tuple or list of nodes.");
3326         return -1;
3327     }
3328
3329     nodeSet = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
3330     if (nodeSet == NULL) {
3331         PyErr_SetString(PyExc_MemoryError, "");
3332         return -1;
3333     }
3334
3335     nodeSet->nodeNr = 0;
3336     nodeSet->nodeMax = (is_tuple
3337                         ? PyTuple_GET_SIZE(py_nodeset)
3338                         : PyList_GET_SIZE(py_nodeset));
3339     nodeSet->nodeTab
3340         = (xmlNodePtr *) xmlMalloc (nodeSet->nodeMax
3341                                     * sizeof(xmlNodePtr));
3342     if (nodeSet->nodeTab == NULL) {
3343         xmlFree(nodeSet);
3344         PyErr_SetString(PyExc_MemoryError, "");
3345         return -1;
3346     }
3347     memset(nodeSet->nodeTab, 0 ,
3348            nodeSet->nodeMax * sizeof(xmlNodePtr));
3349
3350     {
3351         int idx;
3352         for (idx=0; idx < nodeSet->nodeMax; ++idx) {
3353             xmlNodePtr pynode =
3354                 PyxmlNode_Get (is_tuple
3355                                ? PyTuple_GET_ITEM(py_nodeset, idx)
3356                                : PyList_GET_ITEM(py_nodeset, idx));
3357             if (pynode)
3358                 nodeSet->nodeTab[nodeSet->nodeNr++] = pynode;
3359         }
3360     }
3361     *result = nodeSet;
3362     return 0;
3363 }
3364
3365 static int
3366 PystringSet_Convert(PyObject *py_strings, xmlChar *** result)
3367 {
3368     /* NOTE: the array should be freed, but the strings are shared
3369        with the python strings and so must not be freed. */
3370
3371     xmlChar ** strings;
3372     int is_tuple = 0;
3373     int count;
3374     int init_index = 0;
3375
3376     if (PyTuple_Check(py_strings))
3377         is_tuple = 1;
3378     else if (PyList_Check(py_strings))
3379         is_tuple = 0;
3380     else if (py_strings == Py_None) {
3381         *result = NULL;
3382         return 0;
3383     }
3384     else {
3385         PyErr_SetString(PyExc_TypeError,
3386                         "must be a tuple or list of strings.");
3387         return -1;
3388     }
3389
3390     count = (is_tuple
3391              ? PyTuple_GET_SIZE(py_strings)
3392              : PyList_GET_SIZE(py_strings));
3393
3394     strings = (xmlChar **) xmlMalloc(sizeof(xmlChar *) * count);
3395
3396     if (strings == NULL) {
3397         PyErr_SetString(PyExc_MemoryError, "");
3398         return -1;
3399     }
3400
3401     memset(strings, 0 , sizeof(xmlChar *) * count);
3402
3403     {
3404         int idx;
3405         for (idx=0; idx < count; ++idx) {
3406             char* s = PyString_AsString
3407                 (is_tuple
3408                  ? PyTuple_GET_ITEM(py_strings, idx)
3409                  : PyList_GET_ITEM(py_strings, idx));
3410             if (s)
3411                 strings[init_index++] = (xmlChar *)s;
3412             else {
3413                 xmlFree(strings);
3414                 PyErr_SetString(PyExc_TypeError,
3415                                 "must be a tuple or list of strings.");
3416                 return -1;
3417             }
3418         }
3419     }
3420
3421     *result = strings;
3422     return 0;
3423 }
3424
3425 static PyObject *
3426 libxml_C14NDocDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
3427                          PyObject * args)
3428 {
3429     PyObject *py_retval = NULL;
3430
3431     PyObject *pyobj_doc;
3432     PyObject *pyobj_nodes;
3433     int exclusive;
3434     PyObject *pyobj_prefixes;
3435     int with_comments;
3436
3437     xmlDocPtr doc;
3438     xmlNodeSetPtr nodes;
3439     xmlChar **prefixes = NULL;
3440     xmlChar *doc_txt;
3441
3442     int result;
3443
3444     if (!PyArg_ParseTuple(args, (char *) "OOiOi:C14NDocDumpMemory",
3445                           &pyobj_doc,
3446                           &pyobj_nodes,
3447                           &exclusive,
3448                           &pyobj_prefixes,
3449                           &with_comments))
3450         return (NULL);
3451
3452     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3453     if (!doc) {
3454         PyErr_SetString(PyExc_TypeError, "bad document.");
3455         return NULL;
3456     }
3457
3458     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3459     if (result < 0) return NULL;
3460
3461     if (exclusive) {
3462         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3463         if (result < 0) {
3464             if (nodes) {
3465                 xmlFree(nodes->nodeTab);
3466                 xmlFree(nodes);
3467             }
3468             return NULL;
3469         }
3470     }
3471
3472     result = xmlC14NDocDumpMemory(doc,
3473                                   nodes,
3474                                   exclusive,
3475                                   prefixes,
3476                                   with_comments,
3477                                   &doc_txt);
3478
3479     if (nodes) {
3480         xmlFree(nodes->nodeTab);
3481         xmlFree(nodes);
3482     }
3483     if (prefixes) {
3484         xmlChar ** idx = prefixes;
3485         while (*idx) xmlFree(*(idx++));
3486         xmlFree(prefixes);
3487     }
3488
3489     if (result < 0) {
3490         PyErr_SetString(PyExc_Exception,
3491                         "libxml2 xmlC14NDocDumpMemory failure.");
3492         return NULL;
3493     }
3494     else {
3495         py_retval = PyString_FromStringAndSize((const char *) doc_txt,
3496                                                result);
3497         xmlFree(doc_txt);
3498         return py_retval;
3499     }
3500 }
3501
3502 static PyObject *
3503 libxml_C14NDocSaveTo(ATTRIBUTE_UNUSED PyObject * self,
3504                      PyObject * args)
3505 {
3506     PyObject *pyobj_doc;
3507     PyObject *py_file;
3508     PyObject *pyobj_nodes;
3509     int exclusive;
3510     PyObject *pyobj_prefixes;
3511     int with_comments;
3512
3513     xmlDocPtr doc;
3514     xmlNodeSetPtr nodes;
3515     xmlChar **prefixes = NULL;
3516     FILE * output;
3517     xmlOutputBufferPtr buf;
3518
3519     int result;
3520     int len;
3521
3522     if (!PyArg_ParseTuple(args, (char *) "OOiOiO:C14NDocSaveTo",
3523                           &pyobj_doc,
3524                           &pyobj_nodes,
3525                           &exclusive,
3526                           &pyobj_prefixes,
3527                           &with_comments,
3528                           &py_file))
3529         return (NULL);
3530
3531     doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3532     if (!doc) {
3533         PyErr_SetString(PyExc_TypeError, "bad document.");
3534         return NULL;
3535     }
3536
3537     if ((py_file == NULL) || (!(PyFile_Check(py_file)))) {
3538         PyErr_SetString(PyExc_TypeError, "bad file.");
3539         return NULL;
3540     }
3541     output = PyFile_AsFile(py_file);
3542     if (output == NULL) {
3543         PyErr_SetString(PyExc_TypeError, "bad file.");
3544         return NULL;
3545     }
3546     buf = xmlOutputBufferCreateFile(output, NULL);
3547
3548     result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3549     if (result < 0) return NULL;
3550
3551     if (exclusive) {
3552         result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3553         if (result < 0) {
3554             if (nodes) {
3555                 xmlFree(nodes->nodeTab);
3556                 xmlFree(nodes);
3557             }
3558             return NULL;
3559         }
3560     }
3561
3562     result = xmlC14NDocSaveTo(doc,
3563                               nodes,
3564                               exclusive,
3565                               prefixes,
3566                               with_comments,
3567                               buf);
3568
3569     if (nodes) {
3570         xmlFree(nodes->nodeTab);
3571         xmlFree(nodes);
3572     }
3573     if (prefixes) {
3574         xmlChar ** idx = prefixes;
3575         while (*idx) xmlFree(*(idx++));
3576         xmlFree(prefixes);
3577     }
3578
3579     len = xmlOutputBufferClose(buf);
3580
3581     if (result < 0) {
3582         PyErr_SetString(PyExc_Exception,
3583                         "libxml2 xmlC14NDocSaveTo failure.");
3584         return NULL;
3585     }
3586     else
3587         return PyInt_FromLong((long) len);
3588 }
3589
3590 #endif
3591 #endif
3592
3593 static PyObject *
3594 libxml_getObjDesc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3595
3596     PyObject *obj;
3597     char *str;
3598
3599     if (!PyArg_ParseTuple(args, (char *)"O:getObjDesc", &obj))
3600         return NULL;
3601     str = PyCObject_GetDesc(obj);
3602     return Py_BuildValue((char *)"s", str);
3603 }
3604
3605 static PyObject *
3606 libxml_compareNodesEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3607     
3608     PyObject *py_node1, *py_node2;
3609     xmlNodePtr node1, node2;
3610
3611     if (!PyArg_ParseTuple(args, (char *)"OO:compareNodesEqual",
3612                 &py_node1, &py_node2))
3613         return NULL;
3614     /* To compare two node objects, we compare their pointer addresses */
3615     node1 = PyxmlNode_Get(py_node1);
3616     node2 = PyxmlNode_Get(py_node2);
3617     if ( node1 == node2 )
3618         return Py_BuildValue((char *)"i", 1);
3619     else
3620         return Py_BuildValue((char *)"i", 0);
3621     
3622 }
3623
3624 static PyObject *
3625 libxml_nodeHash(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3626
3627     PyObject *py_node1;
3628     xmlNodePtr node1;
3629
3630     if (!PyArg_ParseTuple(args, (char *)"O:nodeHash", &py_node1))
3631             return NULL;
3632     /* For simplicity, we use the node pointer address as a hash value */
3633     node1 = PyxmlNode_Get(py_node1);
3634
3635     return PyLong_FromVoidPtr(node1);
3636
3637 }
3638
3639 /************************************************************************
3640  *                                                                      *
3641  *                      The registration stuff                          *
3642  *                                                                      *
3643  ************************************************************************/
3644 static PyMethodDef libxmlMethods[] = {
3645 #include "libxml2-export.c"
3646     {(char *) "name", libxml_name, METH_VARARGS, NULL},
3647     {(char *) "children", libxml_children, METH_VARARGS, NULL},
3648     {(char *) "properties", libxml_properties, METH_VARARGS, NULL},
3649     {(char *) "last", libxml_last, METH_VARARGS, NULL},
3650     {(char *) "prev", libxml_prev, METH_VARARGS, NULL},
3651     {(char *) "next", libxml_next, METH_VARARGS, NULL},
3652     {(char *) "parent", libxml_parent, METH_VARARGS, NULL},
3653     {(char *) "type", libxml_type, METH_VARARGS, NULL},
3654     {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
3655     {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
3656     {(char *) "xmlNodeRemoveNsDef", libxml_xmlNodeRemoveNsDef, METH_VARARGS, NULL},
3657     {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL},
3658     {(char *)"xmlFreeValidCtxt", libxml_xmlFreeValidCtxt, METH_VARARGS, NULL},
3659 #ifdef LIBXML_OUTPUT_ENABLED
3660     {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
3661     {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
3662     {(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
3663     {(char *) "outputBufferGetPythonFile", libxml_outputBufferGetPythonFile, METH_VARARGS, NULL},
3664     {(char *) "xmlOutputBufferClose", libxml_xmlOutputBufferClose, METH_VARARGS, NULL},
3665     { (char *)"xmlOutputBufferFlush", libxml_xmlOutputBufferFlush, METH_VARARGS, NULL },
3666     { (char *)"xmlSaveFileTo", libxml_xmlSaveFileTo, METH_VARARGS, NULL },
3667     { (char *)"xmlSaveFormatFileTo", libxml_xmlSaveFormatFileTo, METH_VARARGS, NULL },
3668 #endif /* LIBXML_OUTPUT_ENABLED */
3669     {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
3670     {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
3671     {(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
3672     {(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
3673     {(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
3674     {(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
3675 #ifdef LIBXML_READER_ENABLED
3676     {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
3677     {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
3678     {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
3679 #endif
3680     {(char *)"addLocalCatalog", libxml_addLocalCatalog, METH_VARARGS, NULL },
3681 #ifdef LIBXML_SCHEMAS_ENABLED
3682     {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
3683     {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
3684     {(char *)"xmlSchemaSetValidErrors", libxml_xmlSchemaSetValidErrors, METH_VARARGS, NULL},
3685     {(char *)"xmlSchemaFreeValidCtxt", libxml_xmlSchemaFreeValidCtxt, METH_VARARGS, NULL},
3686 #endif
3687 #ifdef LIBXML_C14N_ENABLED
3688 #ifdef LIBXML_OUTPUT_ENABLED
3689     {(char *)"xmlC14NDocDumpMemory", libxml_C14NDocDumpMemory, METH_VARARGS, NULL},
3690     {(char *)"xmlC14NDocSaveTo", libxml_C14NDocSaveTo, METH_VARARGS, NULL},
3691 #endif
3692 #endif
3693     {(char *) "getObjDesc", libxml_getObjDesc, METH_VARARGS, NULL},
3694     {(char *) "compareNodesEqual", libxml_compareNodesEqual, METH_VARARGS, NULL},
3695     {(char *) "nodeHash", libxml_nodeHash, METH_VARARGS, NULL},
3696     {NULL, NULL, 0, NULL}
3697 };
3698
3699 #ifdef MERGED_MODULES
3700 extern void initlibxsltmod(void);
3701 #endif
3702
3703 void
3704 initlibxml2mod(void)
3705 {
3706     static int initialized = 0;
3707
3708     if (initialized != 0)
3709         return;
3710
3711     /* intialize the python extension module */
3712     Py_InitModule((char *) "libxml2mod", libxmlMethods);
3713
3714     /* initialize libxml2 */
3715     xmlInitParser();
3716     libxml_xmlErrorInitialize();
3717
3718     initialized = 1;
3719
3720 #ifdef MERGED_MODULES
3721     initlibxsltmod();
3722 #endif
3723 }