added Info.plist
[TestXSLT.git] / libxml2 / 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_wrap.h"
26 #include "libxml2-py.h"
27
28 #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf)
29 #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
30 #elif defined(WITH_TRIO)
31 #include "trio.h"
32 #define vsnprintf trio_vsnprintf
33 #endif
34
35 /* #define DEBUG */
36 /* #define DEBUG_SAX */
37 /* #define DEBUG_XPATH */
38 /* #define DEBUG_ERROR */
39 /* #define DEBUG_MEMORY */
40 /* #define DEBUG_FILES */
41 /* #define DEBUG_LOADER */
42
43 void initlibxml2mod(void);
44
45 /**
46  * TODO:
47  *
48  * macro to flag unimplemented blocks
49  */
50 #define TODO                                                            \
51     xmlGenericError(xmlGenericErrorContext,                             \
52             "Unimplemented block at %s:%d\n",                           \
53             __FILE__, __LINE__);
54
55 /************************************************************************
56  *                                                                      *
57  *              Memory debug interface                                  *
58  *                                                                      *
59  ************************************************************************/
60
61 #if 0
62 extern void xmlMemFree(void *ptr);
63 extern void *xmlMemMalloc(size_t size);
64 extern void *xmlMemRealloc(void *ptr, size_t size);
65 extern char *xmlMemoryStrdup(const char *str);
66 #endif
67
68 static int libxmlMemoryDebugActivated = 0;
69 static long libxmlMemoryAllocatedBase = 0;
70
71 static int libxmlMemoryDebug = 0;
72 static xmlFreeFunc freeFunc = NULL;
73 static xmlMallocFunc mallocFunc = NULL;
74 static xmlReallocFunc reallocFunc = NULL;
75 static xmlStrdupFunc strdupFunc = NULL;
76
77 PyObject *
78 libxml_xmlDebugMemory(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
79 {
80     int activate;
81     PyObject *py_retval;
82     long ret;
83
84     if (!PyArg_ParseTuple(args, (char *) "i:xmlDebugMemory", &activate))
85         return (NULL);
86
87 #ifdef DEBUG_MEMORY
88     printf("libxml_xmlDebugMemory(%d) called\n", activate);
89 #endif
90
91     if (activate != 0) {
92         if (libxmlMemoryDebug == 0) {
93             /*
94              * First initialize the library and grab the old memory handlers
95              * and switch the library to memory debugging
96              */
97             xmlMemGet((xmlFreeFunc *) & freeFunc,
98                       (xmlMallocFunc *) & mallocFunc,
99                       (xmlReallocFunc *) & reallocFunc,
100                       (xmlStrdupFunc *) & strdupFunc);
101             if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&
102                 (reallocFunc == xmlMemRealloc) &&
103                 (strdupFunc == xmlMemoryStrdup)) {
104                 libxmlMemoryAllocatedBase = xmlMemUsed();
105             } else {
106                 ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,
107                                          xmlMemRealloc, xmlMemoryStrdup);
108                 if (ret < 0)
109                     goto error;
110                 libxmlMemoryAllocatedBase = xmlMemUsed();
111             }
112             xmlInitParser();
113             ret = 0;
114         } else if (libxmlMemoryDebugActivated == 0) {
115             libxmlMemoryAllocatedBase = xmlMemUsed();
116             ret = 0;
117         } else {
118             ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
119         }
120         libxmlMemoryDebug = 1;
121         libxmlMemoryDebugActivated = 1;
122     } else {
123         if (libxmlMemoryDebugActivated == 1)
124             ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
125         else
126             ret = 0;
127         libxmlMemoryDebugActivated = 0;
128     }
129   error:
130     py_retval = libxml_longWrap(ret);
131     return (py_retval);
132 }
133
134 PyObject *
135 libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
136                      ATTRIBUTE_UNUSED PyObject * args)
137 {
138
139     if (libxmlMemoryDebug != 0)
140         xmlMemoryDump();
141     Py_INCREF(Py_None);
142     return (Py_None);
143 }
144
145 /************************************************************************
146  *                                                                      *
147  *              Handling Python FILE I/O at the C level                 *
148  *      The raw I/O attack diectly the File objects, while the          *
149  *      other routines address the ioWrapper instance instead           *
150  *                                                                      *
151  ************************************************************************/
152
153 /**
154  * xmlPythonFileCloseUnref:
155  * @context:  the I/O context
156  *
157  * Close an I/O channel
158  */
159 static int
160 xmlPythonFileCloseRaw (void * context) {
161     PyObject *file, *ret;
162
163 #ifdef DEBUG_FILES
164     printf("xmlPythonFileCloseUnref\n");
165 #endif
166     file = (PyObject *) context;
167     if (file == NULL) return(-1);
168     ret = PyEval_CallMethod(file, (char *) "close", (char *) "()");
169     if (ret != NULL) {
170         Py_DECREF(ret);
171     }
172     Py_DECREF(file);
173     return(0);
174 }
175
176 /**
177  * xmlPythonFileReadRaw:
178  * @context:  the I/O context
179  * @buffer:  where to drop data
180  * @len:  number of bytes to write
181  *
182  * Read @len bytes to @buffer from the Python file in the I/O channel
183  *
184  * Returns the number of bytes read
185  */
186 static int
187 xmlPythonFileReadRaw (void * context, char * buffer, int len) {
188     PyObject *file;
189     PyObject *ret;
190     int lenread = -1;
191     char *data;
192
193 #ifdef DEBUG_FILES
194     printf("xmlPythonFileReadRaw: %d\n", len);
195 #endif
196     file = (PyObject *) context;
197     if (file == NULL) return(-1);
198     ret = PyEval_CallMethod(file, (char *) "read", (char *) "(i)", len);
199     if (ret == NULL) {
200         printf("xmlPythonFileReadRaw: result is NULL\n");
201         return(-1);
202     } else if (PyString_Check(ret)) {
203         lenread = PyString_Size(ret);
204         data = PyString_AsString(ret);
205         if (lenread > len)
206             memcpy(buffer, data, len);
207         else
208             memcpy(buffer, data, lenread);
209         Py_DECREF(ret);
210     } else {
211         printf("xmlPythonFileReadRaw: result is not a String\n");
212         Py_DECREF(ret);
213     }
214     return(lenread);
215 }
216
217 /**
218  * xmlPythonFileRead:
219  * @context:  the I/O context
220  * @buffer:  where to drop data
221  * @len:  number of bytes to write
222  *
223  * Read @len bytes to @buffer from the I/O channel.
224  *
225  * Returns the number of bytes read
226  */
227 static int
228 xmlPythonFileRead (void * context, char * buffer, int len) {
229     PyObject *file;
230     PyObject *ret;
231     int lenread = -1;
232     char *data;
233
234 #ifdef DEBUG_FILES
235     printf("xmlPythonFileRead: %d\n", len);
236 #endif
237     file = (PyObject *) context;
238     if (file == NULL) return(-1);
239     ret = PyEval_CallMethod(file, (char *) "io_read", (char *) "(i)", len);
240     if (ret == NULL) {
241         printf("xmlPythonFileRead: result is NULL\n");
242         return(-1);
243     } else if (PyString_Check(ret)) {
244         lenread = PyString_Size(ret);
245         data = PyString_AsString(ret);
246         if (lenread > len)
247             memcpy(buffer, data, len);
248         else
249             memcpy(buffer, data, lenread);
250         Py_DECREF(ret);
251     } else {
252         printf("xmlPythonFileRead: result is not a String\n");
253         Py_DECREF(ret);
254     }
255     return(lenread);
256 }
257
258 /**
259  * xmlFileWrite:
260  * @context:  the I/O context
261  * @buffer:  where to drop data
262  * @len:  number of bytes to write
263  *
264  * Write @len bytes from @buffer to the I/O channel.
265  *
266  * Returns the number of bytes written
267  */
268 static int
269 xmlPythonFileWrite (void * context, const char * buffer, int len) {
270     PyObject *file;
271     PyObject *string;
272     PyObject *ret;
273     int written = -1;
274
275 #ifdef DEBUG_FILES
276     printf("xmlPythonFileWrite: %d\n", len);
277 #endif
278     file = (PyObject *) context;
279     if (file == NULL) return(-1);
280     string = PyString_FromStringAndSize(buffer, len);
281     if (string == NULL) return(-1);
282     ret = PyEval_CallMethod(file, (char *) "io_write", (char *) "(O)", string);
283     Py_DECREF(string);
284     if (ret == NULL) {
285         printf("xmlPythonFileWrite: result is NULL\n");
286         return(-1);
287     } else if (PyInt_Check(ret)) {
288         written = (int) PyInt_AsLong(ret);
289         Py_DECREF(ret);
290     } else if (ret == Py_None) {
291         written = len;
292         Py_DECREF(ret);
293     } else {
294         printf("xmlPythonFileWrite: result is not an Int nor None\n");
295         Py_DECREF(ret);
296     }
297     return(written);
298 }
299
300 /**
301  * xmlPythonFileClose:
302  * @context:  the I/O context
303  *
304  * Close an I/O channel
305  */
306 static int
307 xmlPythonFileClose (void * context) {
308     PyObject *file, *ret;
309
310 #ifdef DEBUG_FILES
311     printf("xmlPythonFileClose\n");
312 #endif
313     file = (PyObject *) context;
314     if (file == NULL) return(-1);
315     ret = PyEval_CallMethod(file, (char *) "io_close", (char *) "()");
316     if (ret != NULL) {
317         Py_DECREF(ret);
318     }
319     return(0);
320 }
321
322 /**
323  * xmlOutputBufferCreatePythonFile:
324  * @file:  a PyFile_Type
325  * @encoder:  the encoding converter or NULL
326  *
327  * Create a buffered output for the progressive saving to a PyFile_Type
328  * buffered C I/O
329  *
330  * Returns the new parser output or NULL
331  */
332 static xmlOutputBufferPtr
333 xmlOutputBufferCreatePythonFile(PyObject *file, 
334                                 xmlCharEncodingHandlerPtr encoder) {
335     xmlOutputBufferPtr ret;
336
337     if (file == NULL) return(NULL);
338
339     ret = xmlAllocOutputBuffer(encoder);
340     if (ret != NULL) {
341         ret->context = file;
342         /* Py_INCREF(file); */
343         ret->writecallback = xmlPythonFileWrite;
344         ret->closecallback = xmlPythonFileClose;
345     }
346
347     return(ret);
348 }
349
350 PyObject *
351 libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
352     PyObject *py_retval;
353     PyObject *file;
354     xmlChar  *encoding;
355     xmlCharEncodingHandlerPtr handler = NULL;
356     xmlOutputBufferPtr buffer;
357
358
359     if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",
360                 &file, &encoding))
361         return(NULL);
362     if ((encoding != NULL) && (encoding[0] != 0)) {
363         handler = xmlFindCharEncodingHandler((const char *) encoding);
364     }
365     buffer = xmlOutputBufferCreatePythonFile(file, handler);
366     if (buffer == NULL)
367         printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");
368     py_retval = libxml_xmlOutputBufferPtrWrap(buffer);
369     return(py_retval);
370 }
371
372
373 /**
374  * xmlParserInputBufferCreatePythonFile:
375  * @file:  a PyFile_Type
376  * @encoder:  the encoding converter or NULL
377  *
378  * Create a buffered output for the progressive saving to a PyFile_Type
379  * buffered C I/O
380  *
381  * Returns the new parser output or NULL
382  */
383 static xmlParserInputBufferPtr
384 xmlParserInputBufferCreatePythonFile(PyObject *file, 
385                                 xmlCharEncoding encoding) {
386     xmlParserInputBufferPtr ret;
387
388     if (file == NULL) return(NULL);
389
390     ret = xmlAllocParserInputBuffer(encoding);
391     if (ret != NULL) {
392         ret->context = file;
393         /* Py_INCREF(file); */
394         ret->readcallback = xmlPythonFileRead;
395         ret->closecallback = xmlPythonFileClose;
396     }
397
398     return(ret);
399 }
400
401 PyObject *
402 libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
403     PyObject *py_retval;
404     PyObject *file;
405     xmlChar  *encoding;
406     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
407     xmlParserInputBufferPtr buffer;
408
409
410     if (!PyArg_ParseTuple(args, (char *)"Oz:xmlParserInputBufferCreate",
411                 &file, &encoding))
412         return(NULL);
413     if ((encoding != NULL) && (encoding[0] != 0)) {
414         enc = xmlParseCharEncoding((const char *) encoding);
415     }
416     buffer = xmlParserInputBufferCreatePythonFile(file, enc);
417     if (buffer == NULL)
418         printf("libxml_xmlParserInputBufferCreate: buffer == NULL\n");
419     py_retval = libxml_xmlParserInputBufferPtrWrap(buffer);
420     return(py_retval);
421 }
422
423 /************************************************************************
424  *                                                                      *
425  *              Providing the resolver at the Python level              *
426  *                                                                      *
427  ************************************************************************/
428
429 static xmlExternalEntityLoader defaultExternalEntityLoader = NULL;
430 static PyObject *pythonExternalEntityLoaderObjext;
431
432 static xmlParserInputPtr
433 pythonExternalEntityLoader(const char *URL, const char *ID,
434                            xmlParserCtxtPtr ctxt) {
435     xmlParserInputPtr result = NULL;
436     if (pythonExternalEntityLoaderObjext != NULL) {
437         PyObject *ret;
438         PyObject *ctxtobj;
439
440         ctxtobj = libxml_xmlParserCtxtPtrWrap(ctxt);
441 #ifdef DEBUG_LOADER
442         printf("pythonExternalEntityLoader: ready to call\n");
443 #endif
444
445         ret = PyObject_CallFunction(pythonExternalEntityLoaderObjext,
446                       (char *) "(ssO)", URL, ID, ctxtobj);
447         Py_XDECREF(ctxtobj);
448 #ifdef DEBUG_LOADER
449         printf("pythonExternalEntityLoader: result ");
450         PyObject_Print(ret, stdout, 0);
451         printf("\n");
452 #endif
453
454         if (ret != NULL) {
455             if (PyObject_HasAttrString(ret, (char *) "read")) {
456                 xmlParserInputBufferPtr buf;
457
458                 buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
459                 if (buf != NULL) {
460                     buf->context = ret;
461                     buf->readcallback = xmlPythonFileReadRaw;
462                     buf->closecallback = xmlPythonFileCloseRaw;
463                     result = xmlNewIOInputStream(ctxt, buf,
464                                                  XML_CHAR_ENCODING_NONE);
465                 }
466             } else {
467                 printf("pythonExternalEntityLoader: can't read\n");
468             }
469             if (result == NULL) {
470                 Py_DECREF(ret);
471             } else if (URL != NULL) {
472                 result->filename = (char *) xmlStrdup((const xmlChar *)URL);
473                 result->directory = xmlParserGetDirectory((const char *) URL);
474             }
475         }
476     }
477     if ((result == NULL) && (defaultExternalEntityLoader != NULL)) {
478         result = defaultExternalEntityLoader(URL, ID, ctxt);
479     }
480     return(result);
481 }
482
483 PyObject *
484 libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
485     PyObject *py_retval;
486     PyObject *loader;
487
488     if (!PyArg_ParseTuple(args, (char *)"O:libxml_xmlSetEntityLoader",
489                 &loader))
490         return(NULL);
491
492 #ifdef DEBUG_LOADER
493     printf("libxml_xmlSetEntityLoader\n");
494 #endif
495     if (defaultExternalEntityLoader == NULL) 
496         defaultExternalEntityLoader = xmlGetExternalEntityLoader();
497
498     pythonExternalEntityLoaderObjext = loader;
499     xmlSetExternalEntityLoader(pythonExternalEntityLoader);
500
501     py_retval = PyInt_FromLong(0);
502     return(py_retval);
503 }
504
505
506 /************************************************************************
507  *                                                                      *
508  *              Handling SAX/xmllib/sgmlop callback interfaces          *
509  *                                                                      *
510  ************************************************************************/
511
512 static void
513 pythonStartElement(void *user_data, const xmlChar * name,
514                    const xmlChar ** attrs)
515 {
516     int i;
517     PyObject *handler;
518     PyObject *dict;
519     PyObject *attrname;
520     PyObject *attrvalue;
521     PyObject *result = NULL;
522     int type = 0;
523
524 #ifdef DEBUG_SAX
525     printf("pythonStartElement(%s) called\n", name);
526 #endif
527     handler = (PyObject *) user_data;
528     if (PyObject_HasAttrString(handler, (char *) "startElement"))
529         type = 1;
530     else if (PyObject_HasAttrString(handler, (char *) "start"))
531         type = 2;
532     if (type != 0) {
533         /*
534          * the xmllib interface always generate a dictionnary,
535          * possibly empty
536          */
537         if ((attrs == NULL) && (type == 1)) {
538             Py_XINCREF(Py_None);
539             dict = Py_None;
540         } else if (attrs == NULL) {
541             dict = PyDict_New();
542         } else {
543             dict = PyDict_New();
544             for (i = 0; attrs[i] != NULL; i++) {
545                 attrname = PyString_FromString((char *) attrs[i]);
546                 i++;
547                 if (attrs[i] != NULL) {
548                     attrvalue = PyString_FromString((char *) attrs[i]);
549                 } else {
550                     Py_XINCREF(Py_None);
551                     attrvalue = Py_None;
552                 }
553                 PyDict_SetItem(dict, attrname, attrvalue);
554             }
555         }
556
557         if (type == 1)
558             result = PyObject_CallMethod(handler, (char *) "startElement",
559                                          (char *) "sO", name, dict);
560         else if (type == 2)
561             result = PyObject_CallMethod(handler, (char *) "start",
562                                          (char *) "sO", name, dict);
563         if (PyErr_Occurred())
564             PyErr_Print();
565         Py_XDECREF(dict);
566         Py_XDECREF(result);
567     }
568 }
569
570 static void
571 pythonStartDocument(void *user_data)
572 {
573     PyObject *handler;
574     PyObject *result;
575
576 #ifdef DEBUG_SAX
577     printf("pythonStartDocument() called\n");
578 #endif
579     handler = (PyObject *) user_data;
580     if (PyObject_HasAttrString(handler, (char *) "startDocument")) {
581         result =
582             PyObject_CallMethod(handler, (char *) "startDocument", NULL);
583         if (PyErr_Occurred())
584             PyErr_Print();
585         Py_XDECREF(result);
586     }
587 }
588
589 static void
590 pythonEndDocument(void *user_data)
591 {
592     PyObject *handler;
593     PyObject *result;
594
595 #ifdef DEBUG_SAX
596     printf("pythonEndDocument() called\n");
597 #endif
598     handler = (PyObject *) user_data;
599     if (PyObject_HasAttrString(handler, (char *) "endDocument")) {
600         result =
601             PyObject_CallMethod(handler, (char *) "endDocument", NULL);
602         if (PyErr_Occurred())
603             PyErr_Print();
604         Py_XDECREF(result);
605     }
606     /*
607      * The reference to the handler is released there
608      */
609     Py_XDECREF(handler);
610 }
611
612 static void
613 pythonEndElement(void *user_data, const xmlChar * name)
614 {
615     PyObject *handler;
616     PyObject *result;
617
618 #ifdef DEBUG_SAX
619     printf("pythonEndElement(%s) called\n", name);
620 #endif
621     handler = (PyObject *) user_data;
622     if (PyObject_HasAttrString(handler, (char *) "endElement")) {
623         result = PyObject_CallMethod(handler, (char *) "endElement",
624                                      (char *) "s", name);
625         if (PyErr_Occurred())
626             PyErr_Print();
627         Py_XDECREF(result);
628     } else if (PyObject_HasAttrString(handler, (char *) "end")) {
629         result = PyObject_CallMethod(handler, (char *) "end",
630                                      (char *) "s", name);
631         if (PyErr_Occurred())
632             PyErr_Print();
633         Py_XDECREF(result);
634     }
635 }
636
637 static void
638 pythonReference(void *user_data, const xmlChar * name)
639 {
640     PyObject *handler;
641     PyObject *result;
642
643 #ifdef DEBUG_SAX
644     printf("pythonReference(%s) called\n", name);
645 #endif
646     handler = (PyObject *) user_data;
647     if (PyObject_HasAttrString(handler, (char *) "reference")) {
648         result = PyObject_CallMethod(handler, (char *) "reference",
649                                      (char *) "s", name);
650         if (PyErr_Occurred())
651             PyErr_Print();
652         Py_XDECREF(result);
653     }
654 }
655
656 static void
657 pythonCharacters(void *user_data, const xmlChar * ch, int len)
658 {
659     PyObject *handler;
660     PyObject *result = NULL;
661     int type = 0;
662
663 #ifdef DEBUG_SAX
664     printf("pythonCharacters(%s, %d) called\n", ch, len);
665 #endif
666     handler = (PyObject *) user_data;
667     if (PyObject_HasAttrString(handler, (char *) "characters"))
668         type = 1;
669     else if (PyObject_HasAttrString(handler, (char *) "data"))
670         type = 2;
671     if (type != 0) {
672         if (type == 1)
673             result = PyObject_CallMethod(handler, (char *) "characters",
674                                          (char *) "s#", ch, len);
675         else if (type == 2)
676             result = PyObject_CallMethod(handler, (char *) "data",
677                                          (char *) "s#", ch, len);
678         if (PyErr_Occurred())
679             PyErr_Print();
680         Py_XDECREF(result);
681     }
682 }
683
684 static void
685 pythonIgnorableWhitespace(void *user_data, const xmlChar * ch, int len)
686 {
687     PyObject *handler;
688     PyObject *result = NULL;
689     int type = 0;
690
691 #ifdef DEBUG_SAX
692     printf("pythonIgnorableWhitespace(%s, %d) called\n", ch, len);
693 #endif
694     handler = (PyObject *) user_data;
695     if (PyObject_HasAttrString(handler, (char *) "ignorableWhitespace"))
696         type = 1;
697     else if (PyObject_HasAttrString(handler, (char *) "data"))
698         type = 2;
699     if (type != 0) {
700         if (type == 1)
701             result =
702                 PyObject_CallMethod(handler,
703                                     (char *) "ignorableWhitespace",
704                                     (char *) "s#", ch, len);
705         else if (type == 2)
706             result =
707                 PyObject_CallMethod(handler, (char *) "data",
708                                     (char *) "s#", ch, len);
709         Py_XDECREF(result);
710     }
711 }
712
713 static void
714 pythonProcessingInstruction(void *user_data,
715                             const xmlChar * target, const xmlChar * data)
716 {
717     PyObject *handler;
718     PyObject *result;
719
720 #ifdef DEBUG_SAX
721     printf("pythonProcessingInstruction(%s, %s) called\n", target, data);
722 #endif
723     handler = (PyObject *) user_data;
724     if (PyObject_HasAttrString(handler, (char *) "processingInstruction")) {
725         result = PyObject_CallMethod(handler, (char *)
726                                      "processingInstruction",
727                                      (char *) "ss", target, data);
728         Py_XDECREF(result);
729     }
730 }
731
732 static void
733 pythonComment(void *user_data, const xmlChar * value)
734 {
735     PyObject *handler;
736     PyObject *result;
737
738 #ifdef DEBUG_SAX
739     printf("pythonComment(%s) called\n", value);
740 #endif
741     handler = (PyObject *) user_data;
742     if (PyObject_HasAttrString(handler, (char *) "comment")) {
743         result =
744             PyObject_CallMethod(handler, (char *) "comment", (char *) "s",
745                                 value);
746         if (PyErr_Occurred())
747             PyErr_Print();
748         Py_XDECREF(result);
749     }
750 }
751
752 static void
753 pythonWarning(void *user_data, const char *msg, ...)
754 {
755     PyObject *handler;
756     PyObject *result;
757     va_list args;
758     char buf[1024];
759
760 #ifdef DEBUG_SAX
761     printf("pythonWarning(%s) called\n", msg);
762 #endif
763     handler = (PyObject *) user_data;
764     if (PyObject_HasAttrString(handler, (char *) "warning")) {
765         va_start(args, msg);
766         vsnprintf(buf, 1023, msg, args);
767         va_end(args);
768         buf[1023] = 0;
769         result =
770             PyObject_CallMethod(handler, (char *) "warning", (char *) "s",
771                                 buf);
772         if (PyErr_Occurred())
773             PyErr_Print();
774         Py_XDECREF(result);
775     }
776 }
777
778 static void
779 pythonError(void *user_data, const char *msg, ...)
780 {
781     PyObject *handler;
782     PyObject *result;
783     va_list args;
784     char buf[1024];
785
786 #ifdef DEBUG_SAX
787     printf("pythonError(%s) called\n", msg);
788 #endif
789     handler = (PyObject *) user_data;
790     if (PyObject_HasAttrString(handler, (char *) "error")) {
791         va_start(args, msg);
792         vsnprintf(buf, 1023, msg, args);
793         va_end(args);
794         buf[1023] = 0;
795         result =
796             PyObject_CallMethod(handler, (char *) "error", (char *) "s",
797                                 buf);
798         if (PyErr_Occurred())
799             PyErr_Print();
800         Py_XDECREF(result);
801     }
802 }
803
804 static void
805 pythonFatalError(void *user_data, const char *msg, ...)
806 {
807     PyObject *handler;
808     PyObject *result;
809     va_list args;
810     char buf[1024];
811
812 #ifdef DEBUG_SAX
813     printf("pythonFatalError(%s) called\n", msg);
814 #endif
815     handler = (PyObject *) user_data;
816     if (PyObject_HasAttrString(handler, (char *) "fatalError")) {
817         va_start(args, msg);
818         vsnprintf(buf, 1023, msg, args);
819         va_end(args);
820         buf[1023] = 0;
821         result =
822             PyObject_CallMethod(handler, (char *) "fatalError",
823                                 (char *) "s", buf);
824         if (PyErr_Occurred())
825             PyErr_Print();
826         Py_XDECREF(result);
827     }
828 }
829
830 static void
831 pythonCdataBlock(void *user_data, const xmlChar * ch, int len)
832 {
833     PyObject *handler;
834     PyObject *result = NULL;
835     int type = 0;
836
837 #ifdef DEBUG_SAX
838     printf("pythonCdataBlock(%s, %d) called\n", ch, len);
839 #endif
840     handler = (PyObject *) user_data;
841     if (PyObject_HasAttrString(handler, (char *) "cdataBlock"))
842         type = 1;
843     else if (PyObject_HasAttrString(handler, (char *) "cdata"))
844         type = 2;
845     if (type != 0) {
846         if (type == 1)
847             result =
848                 PyObject_CallMethod(handler, (char *) "cdataBlock",
849                                     (char *) "s#", ch, len);
850         else if (type == 2)
851             result =
852                 PyObject_CallMethod(handler, (char *) "cdata",
853                                     (char *) "s#", ch, len);
854         if (PyErr_Occurred())
855             PyErr_Print();
856         Py_XDECREF(result);
857     }
858 }
859
860 static void
861 pythonExternalSubset(void *user_data,
862                      const xmlChar * name,
863                      const xmlChar * externalID, const xmlChar * systemID)
864 {
865     PyObject *handler;
866     PyObject *result;
867
868 #ifdef DEBUG_SAX
869     printf("pythonExternalSubset(%s, %s, %s) called\n",
870            name, externalID, systemID);
871 #endif
872     handler = (PyObject *) user_data;
873     if (PyObject_HasAttrString(handler, (char *) "externalSubset")) {
874         result =
875             PyObject_CallMethod(handler, (char *) "externalSubset",
876                                 (char *) "sss", name, externalID,
877                                 systemID);
878         Py_XDECREF(result);
879     }
880 }
881
882 static void
883 pythonEntityDecl(void *user_data,
884                  const xmlChar * name,
885                  int type,
886                  const xmlChar * publicId,
887                  const xmlChar * systemId, xmlChar * content)
888 {
889     PyObject *handler;
890     PyObject *result;
891
892     handler = (PyObject *) user_data;
893     if (PyObject_HasAttrString(handler, (char *) "entityDecl")) {
894         result = PyObject_CallMethod(handler, (char *) "entityDecl",
895                                      (char *) "sisss", name, type,
896                                      publicId, systemId, content);
897         if (PyErr_Occurred())
898             PyErr_Print();
899         Py_XDECREF(result);
900     }
901 }
902
903
904
905 static void
906
907 pythonNotationDecl(void *user_data,
908                    const xmlChar * name,
909                    const xmlChar * publicId, const xmlChar * systemId)
910 {
911     PyObject *handler;
912     PyObject *result;
913
914     handler = (PyObject *) user_data;
915     if (PyObject_HasAttrString(handler, (char *) "notationDecl")) {
916         result = PyObject_CallMethod(handler, (char *) "notationDecl",
917                                      (char *) "sss", name, publicId,
918                                      systemId);
919         if (PyErr_Occurred())
920             PyErr_Print();
921         Py_XDECREF(result);
922     }
923 }
924
925 static void
926 pythonAttributeDecl(void *user_data,
927                     const xmlChar * elem,
928                     const xmlChar * name,
929                     int type,
930                     int def,
931                     const xmlChar * defaultValue, xmlEnumerationPtr tree)
932 {
933     PyObject *handler;
934     PyObject *nameList;
935     PyObject *newName;
936     xmlEnumerationPtr node;
937     PyObject *result;
938     int count;
939
940     handler = (PyObject *) user_data;
941     if (PyObject_HasAttrString(handler, (char *) "attributeDecl")) {
942         count = 0;
943         for (node = tree; node != NULL; node = node->next) {
944             count++;
945         }
946         nameList = PyList_New(count);
947         count = 0;
948         for (node = tree; node != NULL; node = node->next) {
949             newName = PyString_FromString((char *) node->name);
950             PyList_SetItem(nameList, count, newName);
951             count++;
952         }
953         result = PyObject_CallMethod(handler, (char *) "attributeDecl",
954                                      (char *) "ssiisO", elem, name, type,
955                                      def, defaultValue, nameList);
956         if (PyErr_Occurred())
957             PyErr_Print();
958         Py_XDECREF(nameList);
959         Py_XDECREF(result);
960     }
961 }
962
963 static void
964 pythonElementDecl(void *user_data,
965                   const xmlChar * name,
966                   int type, ATTRIBUTE_UNUSED xmlElementContentPtr content)
967 {
968     PyObject *handler;
969     PyObject *obj;
970     PyObject *result;
971
972     handler = (PyObject *) user_data;
973     if (PyObject_HasAttrString(handler, (char *) "elementDecl")) {
974         /* TODO: wrap in an elementContent object */
975         printf
976             ("pythonElementDecl: xmlElementContentPtr wrapper missing !\n");
977         obj = Py_None;
978         /* Py_XINCREF(Py_None); isn't the reference just borrowed ??? */
979         result = PyObject_CallMethod(handler, (char *) "elementDecl",
980                                      (char *) "siO", name, type, obj);
981         if (PyErr_Occurred())
982             PyErr_Print();
983         Py_XDECREF(result);
984     }
985 }
986
987 static void
988 pythonUnparsedEntityDecl(void *user_data,
989                          const xmlChar * name,
990                          const xmlChar * publicId,
991                          const xmlChar * systemId,
992                          const xmlChar * notationName)
993 {
994     PyObject *handler;
995     PyObject *result;
996
997     handler = (PyObject *) user_data;
998     if (PyObject_HasAttrString(handler, (char *) "unparsedEntityDecl")) {
999         result =
1000             PyObject_CallMethod(handler, (char *) "unparsedEntityDecl",
1001                                 (char *) "ssss", name, publicId, systemId,
1002                                 notationName);
1003         if (PyErr_Occurred())
1004             PyErr_Print();
1005         Py_XDECREF(result);
1006     }
1007 }
1008
1009 static void
1010 pythonInternalSubset(void *user_data, const xmlChar * name,
1011                      const xmlChar * ExternalID, const xmlChar * SystemID)
1012 {
1013     PyObject *handler;
1014     PyObject *result;
1015
1016 #ifdef DEBUG_SAX
1017     printf("pythonInternalSubset(%s, %s, %s) called\n",
1018            name, ExternalID, SystemID);
1019 #endif
1020     handler = (PyObject *) user_data;
1021     if (PyObject_HasAttrString(handler, (char *) "internalSubset")) {
1022         result = PyObject_CallMethod(handler, (char *) "internalSubset",
1023                                      (char *) "sss", name, ExternalID,
1024                                      SystemID);
1025         if (PyErr_Occurred())
1026             PyErr_Print();
1027         Py_XDECREF(result);
1028     }
1029 }
1030
1031 static xmlSAXHandler pythonSaxHandler = {
1032     pythonInternalSubset,
1033     NULL,                       /* TODO pythonIsStandalone, */
1034     NULL,                       /* TODO pythonHasInternalSubset, */
1035     NULL,                       /* TODO pythonHasExternalSubset, */
1036     NULL,                       /* TODO pythonResolveEntity, */
1037     NULL,                       /* TODO pythonGetEntity, */
1038     pythonEntityDecl,
1039     pythonNotationDecl,
1040     pythonAttributeDecl,
1041     pythonElementDecl,
1042     pythonUnparsedEntityDecl,
1043     NULL,                       /* OBSOLETED pythonSetDocumentLocator, */
1044     pythonStartDocument,
1045     pythonEndDocument,
1046     pythonStartElement,
1047     pythonEndElement,
1048     pythonReference,
1049     pythonCharacters,
1050     pythonIgnorableWhitespace,
1051     pythonProcessingInstruction,
1052     pythonComment,
1053     pythonWarning,
1054     pythonError,
1055     pythonFatalError,
1056     NULL,                       /* TODO pythonGetParameterEntity, */
1057     pythonCdataBlock,
1058     pythonExternalSubset,
1059     1
1060 };
1061
1062 /************************************************************************
1063  *                                                                      *
1064  *              Handling of specific parser context                     *
1065  *                                                                      *
1066  ************************************************************************/
1067
1068 PyObject *
1069 libxml_xmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1070                            PyObject * args)
1071 {
1072     const char *chunk;
1073     int size;
1074     const char *URI;
1075     PyObject *pyobj_SAX = NULL;
1076     xmlSAXHandlerPtr SAX = NULL;
1077     xmlParserCtxtPtr ret;
1078     PyObject *pyret;
1079
1080     if (!PyArg_ParseTuple
1081         (args, (char *) "Oziz:xmlCreatePushParser", &pyobj_SAX, &chunk,
1082          &size, &URI))
1083         return (NULL);
1084
1085 #ifdef DEBUG
1086     printf("libxml_xmlCreatePushParser(%p, %s, %d, %s) called\n",
1087            pyobj_SAX, chunk, size, URI);
1088 #endif
1089     if (pyobj_SAX != Py_None) {
1090         SAX = &pythonSaxHandler;
1091         Py_INCREF(pyobj_SAX);
1092         /* The reference is released in pythonEndDocument() */
1093     }
1094     ret = xmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI);
1095     pyret = libxml_xmlParserCtxtPtrWrap(ret);
1096     return (pyret);
1097 }
1098
1099 PyObject *
1100 libxml_htmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1101                             PyObject * args)
1102 {
1103     const char *chunk;
1104     int size;
1105     const char *URI;
1106     PyObject *pyobj_SAX = NULL;
1107     xmlSAXHandlerPtr SAX = NULL;
1108     xmlParserCtxtPtr ret;
1109     PyObject *pyret;
1110
1111     if (!PyArg_ParseTuple
1112         (args, (char *) "Oziz:htmlCreatePushParser", &pyobj_SAX, &chunk,
1113          &size, &URI))
1114         return (NULL);
1115
1116 #ifdef DEBUG
1117     printf("libxml_htmlCreatePushParser(%p, %s, %d, %s) called\n",
1118            pyobj_SAX, chunk, size, URI);
1119 #endif
1120     if (pyobj_SAX != Py_None) {
1121         SAX = &pythonSaxHandler;
1122         Py_INCREF(pyobj_SAX);
1123         /* The reference is released in pythonEndDocument() */
1124     }
1125     ret = htmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI,
1126                                    XML_CHAR_ENCODING_NONE);
1127     pyret = libxml_xmlParserCtxtPtrWrap(ret);
1128     return (pyret);
1129 }
1130
1131 PyObject *
1132 libxml_xmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1133 {
1134     int recover;
1135     const char *URI;
1136     PyObject *pyobj_SAX = NULL;
1137     xmlSAXHandlerPtr SAX = NULL;
1138
1139     if (!PyArg_ParseTuple(args, (char *) "Osi:xmlSAXParseFile", &pyobj_SAX,
1140                           &URI, &recover))
1141         return (NULL);
1142
1143 #ifdef DEBUG
1144     printf("libxml_xmlSAXParseFile(%p, %s, %d) called\n",
1145            pyobj_SAX, URI, recover);
1146 #endif
1147     if (pyobj_SAX == Py_None) {
1148         Py_INCREF(Py_None);
1149         return (Py_None);
1150     }
1151     SAX = &pythonSaxHandler;
1152     Py_INCREF(pyobj_SAX);
1153     /* The reference is released in pythonEndDocument() */
1154     xmlSAXParseFileWithData(SAX, URI, recover, pyobj_SAX);
1155     Py_INCREF(Py_None);
1156     return (Py_None);
1157 }
1158
1159 PyObject *
1160 libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1161 {
1162     const char *URI;
1163     const char *encoding;
1164     PyObject *pyobj_SAX = NULL;
1165     xmlSAXHandlerPtr SAX = NULL;
1166
1167     if (!PyArg_ParseTuple
1168         (args, (char *) "Osz:htmlSAXParseFile", &pyobj_SAX, &URI,
1169          &encoding))
1170         return (NULL);
1171
1172 #ifdef DEBUG
1173     printf("libxml_htmlSAXParseFile(%p, %s, %s) called\n",
1174            pyobj_SAX, URI, encoding);
1175 #endif
1176     if (pyobj_SAX == Py_None) {
1177         Py_INCREF(Py_None);
1178         return (Py_None);
1179     }
1180     SAX = &pythonSaxHandler;
1181     Py_INCREF(pyobj_SAX);
1182     /* The reference is released in pythonEndDocument() */
1183     htmlSAXParseFile(URI, encoding, SAX, pyobj_SAX);
1184     Py_INCREF(Py_None);
1185     return (Py_None);
1186 }
1187
1188 /************************************************************************
1189  *                                                                      *
1190  *                      Error message callback                          *
1191  *                                                                      *
1192  ************************************************************************/
1193
1194 static PyObject *libxml_xmlPythonErrorFuncHandler = NULL;
1195 static PyObject *libxml_xmlPythonErrorFuncCtxt = NULL;
1196
1197 /* helper to build a xmlMalloc'ed string from a format and va_list */
1198 static char *
1199 libxml_buildMessage(const char *msg, va_list ap)
1200 {
1201     int size;
1202     int chars;
1203     char *larger;
1204     char *str;
1205
1206     str = (char *) xmlMalloc(150);
1207     if (str == NULL)
1208         return NULL;
1209
1210     size = 150;
1211
1212     while (1) {
1213         chars = vsnprintf(str, size, msg, ap);
1214         if ((chars > -1) && (chars < size))
1215             break;
1216         if (chars > -1)
1217             size += chars + 1;
1218         else
1219             size += 100;
1220         if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
1221             xmlFree(str);
1222             return NULL;
1223         }
1224         str = larger;
1225     }
1226
1227     return str;
1228 }
1229
1230 static void
1231 libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
1232                            ...)
1233 {
1234     va_list ap;
1235     char *str;
1236     PyObject *list;
1237     PyObject *message;
1238     PyObject *result;
1239
1240 #ifdef DEBUG_ERROR
1241     printf("libxml_xmlErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
1242 #endif
1243
1244
1245     if (libxml_xmlPythonErrorFuncHandler == NULL) {
1246         va_start(ap, msg);
1247         vfprintf(stdout, msg, ap);
1248         va_end(ap);
1249     } else {
1250         va_start(ap, msg);
1251         str = libxml_buildMessage(msg,ap);
1252         va_end(ap);
1253
1254         list = PyTuple_New(2);
1255         PyTuple_SetItem(list, 0, libxml_xmlPythonErrorFuncCtxt);
1256         Py_XINCREF(libxml_xmlPythonErrorFuncCtxt);
1257         message = libxml_charPtrWrap(str);
1258         PyTuple_SetItem(list, 1, message);
1259         result = PyEval_CallObject(libxml_xmlPythonErrorFuncHandler, list);
1260         Py_XDECREF(list);
1261         Py_XDECREF(result);
1262     }
1263 }
1264
1265 static void
1266 libxml_xmlErrorInitialize(void)
1267 {
1268 #ifdef DEBUG_ERROR
1269     printf("libxml_xmlErrorInitialize() called\n");
1270 #endif
1271     xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1272     xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1273 }
1274
1275 static PyObject *
1276 libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
1277                                PyObject * args)
1278 {
1279     PyObject *py_retval;
1280     PyObject *pyobj_f;
1281     PyObject *pyobj_ctx;
1282
1283     if (!PyArg_ParseTuple
1284         (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f,
1285          &pyobj_ctx))
1286         return (NULL);
1287
1288 #ifdef DEBUG_ERROR
1289     printf("libxml_registerXPathFunction(%p, %p) called\n", pyobj_ctx,
1290            pyobj_f);
1291 #endif
1292
1293     if (libxml_xmlPythonErrorFuncHandler != NULL) {
1294         Py_XDECREF(libxml_xmlPythonErrorFuncHandler);
1295     }
1296     if (libxml_xmlPythonErrorFuncCtxt != NULL) {
1297         Py_XDECREF(libxml_xmlPythonErrorFuncCtxt);
1298     }
1299
1300     Py_XINCREF(pyobj_ctx);
1301     Py_XINCREF(pyobj_f);
1302
1303     /* TODO: check f is a function ! */
1304     libxml_xmlPythonErrorFuncHandler = pyobj_f;
1305     libxml_xmlPythonErrorFuncCtxt = pyobj_ctx;
1306
1307     py_retval = libxml_intWrap(1);
1308     return (py_retval);
1309 }
1310
1311
1312 /************************************************************************
1313  *                                                                      *
1314  *                      Per parserCtxt error handler                    *
1315  *                                                                      *
1316  ************************************************************************/
1317
1318 typedef struct 
1319 {
1320     PyObject *f;
1321     PyObject *arg;
1322 } xmlParserCtxtPyCtxt;
1323 typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;
1324
1325 static void
1326 libxml_xmlParserCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str) 
1327 {
1328     PyObject *list;
1329     PyObject *result;
1330     xmlParserCtxtPtr ctxt;
1331     xmlParserCtxtPyCtxtPtr pyCtxt;
1332     
1333 #ifdef DEBUG_ERROR
1334     printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
1335 #endif
1336
1337     ctxt = (xmlParserCtxtPtr)ctx;
1338     pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1339
1340     list = PyTuple_New(4);
1341     PyTuple_SetItem(list, 0, pyCtxt->arg);
1342     Py_XINCREF(pyCtxt->arg);
1343     PyTuple_SetItem(list, 1, libxml_charPtrWrap(str));
1344     PyTuple_SetItem(list, 2, libxml_intWrap(severity));
1345     PyTuple_SetItem(list, 3, Py_None);
1346     Py_INCREF(Py_None);
1347     result = PyEval_CallObject(pyCtxt->f, list);
1348     if (result == NULL) 
1349     {
1350         /* TODO: manage for the exception to be propagated... */
1351         PyErr_Print();
1352     }
1353     Py_XDECREF(list);
1354     Py_XDECREF(result);
1355 }
1356
1357 static void 
1358 libxml_xmlParserCtxtErrorFuncHandler(void *ctx, const char *msg, ...) 
1359 {
1360     va_list ap;
1361
1362     va_start(ap, msg);
1363     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_ERROR,libxml_buildMessage(msg,ap));
1364     va_end(ap);
1365 }
1366
1367 static void 
1368 libxml_xmlParserCtxtWarningFuncHandler(void *ctx, const char *msg, ...) 
1369 {
1370     va_list ap;
1371
1372     va_start(ap, msg);
1373     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_WARNING,libxml_buildMessage(msg,ap));
1374     va_end(ap);
1375 }
1376
1377 static void 
1378 libxml_xmlParserCtxtValidityErrorFuncHandler(void *ctx, const char *msg, ...) 
1379 {
1380     va_list ap;
1381
1382     va_start(ap, msg);
1383     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
1384     va_end(ap);
1385 }
1386
1387 static void 
1388 libxml_xmlParserCtxtValidityWarningFuncHandler(void *ctx, const char *msg, ...) 
1389 {
1390     va_list ap;
1391
1392     va_start(ap, msg);
1393     libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
1394     va_end(ap);
1395 }
1396
1397 static PyObject *
1398 libxml_xmlParserCtxtSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) 
1399 {
1400     PyObject *py_retval;
1401     xmlParserCtxtPtr ctxt;
1402     xmlParserCtxtPyCtxtPtr pyCtxt;
1403     PyObject *pyobj_ctxt;
1404     PyObject *pyobj_f;
1405     PyObject *pyobj_arg;
1406
1407     if (!PyArg_ParseTuple(args, (char *)"OOO:xmlParserCtxtSetErrorHandler",
1408                           &pyobj_ctxt, &pyobj_f, &pyobj_arg))
1409         return(NULL);
1410     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1411     if (ctxt->_private == NULL) {
1412         pyCtxt = xmlMalloc(sizeof(xmlParserCtxtPyCtxt));
1413         if (pyCtxt == NULL) {
1414             py_retval = libxml_intWrap(-1);
1415             return(py_retval);
1416         }
1417         memset(pyCtxt,0,sizeof(xmlParserCtxtPyCtxt));
1418         ctxt->_private = pyCtxt;
1419     }
1420     else {
1421         pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1422     }
1423     /* TODO: check f is a function ! */
1424     Py_XDECREF(pyCtxt->f);
1425     Py_XINCREF(pyobj_f);
1426     pyCtxt->f = pyobj_f;
1427     Py_XDECREF(pyCtxt->arg);
1428     Py_XINCREF(pyobj_arg);
1429     pyCtxt->arg = pyobj_arg;
1430
1431     if (pyobj_f != Py_None) {
1432         ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
1433         ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
1434         ctxt->vctxt.error = libxml_xmlParserCtxtValidityErrorFuncHandler;
1435         ctxt->vctxt.warning = libxml_xmlParserCtxtValidityWarningFuncHandler;
1436     }
1437     else {
1438         ctxt->sax->error = xmlParserError;
1439         ctxt->vctxt.error = xmlParserValidityError;
1440         ctxt->sax->warning = xmlParserWarning;
1441         ctxt->vctxt.warning = xmlParserValidityWarning;
1442     }
1443
1444     py_retval = libxml_intWrap(1);
1445     return(py_retval);
1446 }
1447
1448 static PyObject *
1449 libxml_xmlParserCtxtGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) 
1450 {
1451     PyObject *py_retval;
1452     xmlParserCtxtPtr ctxt;
1453     xmlParserCtxtPyCtxtPtr pyCtxt;
1454     PyObject *pyobj_ctxt;
1455
1456     if (!PyArg_ParseTuple(args, (char *)"O:xmlParserCtxtGetErrorHandler",
1457                           &pyobj_ctxt))
1458         return(NULL);
1459     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1460     py_retval = PyTuple_New(2);
1461     if (ctxt->_private != NULL) {
1462         pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1463
1464         PyTuple_SetItem(py_retval, 0, pyCtxt->f);
1465         Py_XINCREF(pyCtxt->f);
1466         PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
1467         Py_XINCREF(pyCtxt->arg);
1468     }
1469     else {
1470         /* no python error handler registered */
1471         PyTuple_SetItem(py_retval, 0, Py_None);
1472         Py_XINCREF(Py_None);
1473         PyTuple_SetItem(py_retval, 1, Py_None);
1474         Py_XINCREF(Py_None);
1475     }
1476     return(py_retval);
1477 }
1478
1479 static PyObject *
1480 libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
1481     xmlParserCtxtPtr ctxt;
1482     PyObject *pyobj_ctxt;
1483     xmlParserCtxtPyCtxtPtr pyCtxt;
1484
1485     if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
1486         return(NULL);
1487     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1488
1489     if (ctxt != NULL) {
1490         pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
1491         if (pyCtxt) {
1492             Py_XDECREF(pyCtxt->f);
1493             Py_XDECREF(pyCtxt->arg);
1494             xmlFree(pyCtxt);
1495         }
1496         xmlFreeParserCtxt(ctxt);
1497     }
1498
1499     Py_INCREF(Py_None);
1500     return(Py_None);
1501 }
1502
1503 /************************************************************************
1504  *                                                                      *
1505  *                      Per xmlTextReader error handler                 *
1506  *                                                                      *
1507  ************************************************************************/
1508
1509 typedef struct 
1510 {
1511     PyObject *f;
1512     PyObject *arg;
1513 } xmlTextReaderPyCtxt;
1514 typedef xmlTextReaderPyCtxt *xmlTextReaderPyCtxtPtr;
1515
1516 static void 
1517 libxml_xmlTextReaderErrorCallback(void *arg, 
1518                                   const char *msg,
1519                                   int severity,
1520                                   xmlTextReaderLocatorPtr locator)
1521 {
1522     xmlTextReaderPyCtxt *pyCtxt = (xmlTextReaderPyCtxt *)arg;
1523     PyObject *list;
1524     PyObject *result;
1525     
1526     list = PyTuple_New(4);
1527     PyTuple_SetItem(list, 0, pyCtxt->arg);
1528     Py_XINCREF(pyCtxt->arg);
1529     PyTuple_SetItem(list, 1, libxml_charPtrConstWrap(msg));
1530     PyTuple_SetItem(list, 2, libxml_intWrap(severity));
1531     PyTuple_SetItem(list, 3, libxml_xmlTextReaderLocatorPtrWrap(locator));
1532     result = PyEval_CallObject(pyCtxt->f, list);
1533     if (result == NULL)
1534     {
1535         /* TODO: manage for the exception to be propagated... */
1536         PyErr_Print();
1537     }
1538     Py_XDECREF(list);
1539     Py_XDECREF(result);
1540 }
1541
1542 static PyObject *
1543 libxml_xmlTextReaderSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
1544 {
1545     xmlTextReaderPtr reader;
1546     xmlTextReaderPyCtxtPtr pyCtxt;
1547     xmlTextReaderErrorFunc f;
1548     void *arg;
1549     PyObject *pyobj_reader;
1550     PyObject *pyobj_f;
1551     PyObject *pyobj_arg;
1552     PyObject *py_retval;
1553
1554     if (!PyArg_ParseTuple(args, (char *)"OOO:xmlTextReaderSetErrorHandler", &pyobj_reader, &pyobj_f, &pyobj_arg))
1555         return(NULL);
1556     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
1557     /* clear previous error handler */
1558     xmlTextReaderGetErrorHandler(reader,&f,&arg);
1559     if (arg != NULL) {
1560         if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
1561             /* ok, it's our error handler! */
1562             pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
1563             Py_XDECREF(pyCtxt->f);
1564             Py_XDECREF(pyCtxt->arg);
1565             xmlFree(pyCtxt);
1566         }
1567         else {
1568             /* 
1569              * there already an arg, and it's not ours,
1570              * there is definitely something wrong going on here...
1571              * we don't know how to free it, so we bail out... 
1572              */
1573             py_retval = libxml_intWrap(-1);
1574             return(py_retval);
1575         }
1576     }
1577     xmlTextReaderSetErrorHandler(reader,NULL,NULL);
1578     /* set new error handler */
1579     if (pyobj_f != Py_None)
1580     {
1581         pyCtxt = (xmlTextReaderPyCtxtPtr)xmlMalloc(sizeof(xmlTextReaderPyCtxt));
1582         if (pyCtxt == NULL) {
1583             py_retval = libxml_intWrap(-1);
1584             return(py_retval);
1585         }
1586         Py_XINCREF(pyobj_f);
1587         pyCtxt->f = pyobj_f;
1588         Py_XINCREF(pyobj_arg);
1589         pyCtxt->arg = pyobj_arg;
1590         xmlTextReaderSetErrorHandler(reader,
1591             (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback,
1592                                      pyCtxt);
1593     }
1594
1595     py_retval = libxml_intWrap(1);
1596     return(py_retval);
1597 }
1598
1599 static PyObject *
1600 libxml_xmlTextReaderGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
1601 {
1602     xmlTextReaderPtr reader;
1603     xmlTextReaderPyCtxtPtr pyCtxt;
1604     xmlTextReaderErrorFunc f;
1605     void *arg;
1606     PyObject *pyobj_reader;
1607     PyObject *py_retval;
1608
1609     if (!PyArg_ParseTuple(args, (char *)"O:xmlTextReaderSetErrorHandler", &pyobj_reader))
1610         return(NULL);
1611     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
1612     xmlTextReaderGetErrorHandler(reader,&f,&arg);
1613     py_retval = PyTuple_New(2);
1614     if (f == (xmlTextReaderErrorFunc)libxml_xmlTextReaderErrorCallback) {
1615         /* ok, it's our error handler! */
1616         pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
1617         PyTuple_SetItem(py_retval, 0, pyCtxt->f);
1618         Py_XINCREF(pyCtxt->f);
1619         PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
1620         Py_XINCREF(pyCtxt->arg);
1621     }
1622     else
1623     {
1624         /* f is null or it's not our error handler */
1625         PyTuple_SetItem(py_retval, 0, Py_None);
1626         Py_XINCREF(Py_None);
1627         PyTuple_SetItem(py_retval, 1, Py_None);
1628         Py_XINCREF(Py_None);
1629     }
1630     return(py_retval);
1631 }
1632
1633 static PyObject *
1634 libxml_xmlFreeTextReader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
1635     xmlTextReaderPtr reader;
1636     PyObject *pyobj_reader;
1637     xmlTextReaderPyCtxtPtr pyCtxt;
1638     xmlTextReaderErrorFunc f;
1639     void *arg;
1640
1641     if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeTextReader", &pyobj_reader))
1642         return(NULL);
1643     reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
1644
1645     xmlTextReaderGetErrorHandler(reader,&f,&arg);
1646     if (arg != NULL) {
1647         if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
1648             /* ok, it's our error handler! */
1649             pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
1650             Py_XDECREF(pyCtxt->f);
1651             Py_XDECREF(pyCtxt->arg);
1652             xmlFree(pyCtxt);
1653         }
1654         /* 
1655          * else, something wrong happened, because the error handler is
1656          * not owned by the python bindings...
1657          */
1658     }
1659
1660     xmlFreeTextReader(reader);
1661     Py_INCREF(Py_None);
1662     return(Py_None);
1663 }
1664
1665 /************************************************************************
1666  *                                                                      *
1667  *                      XPath extensions                                *
1668  *                                                                      *
1669  ************************************************************************/
1670
1671 static int libxml_xpathCallbacksInitialized = 0;
1672
1673 typedef struct libxml_xpathCallback {
1674     xmlXPathContextPtr ctx;
1675     xmlChar *name;
1676     xmlChar *ns_uri;
1677     PyObject *function;
1678 } libxml_xpathCallback, *libxml_xpathCallbackPtr;
1679 static libxml_xpathCallback libxml_xpathCallbacks[10];
1680 static int libxml_xpathCallbacksNb = 0;
1681 static int libxml_xpathCallbacksMax = 10;
1682
1683 static void
1684 libxml_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs)
1685 {
1686     PyObject *list, *cur, *result;
1687     xmlXPathObjectPtr obj;
1688     xmlXPathContextPtr rctxt;
1689     PyObject *current_function = NULL;
1690     const xmlChar *name;
1691     const xmlChar *ns_uri;
1692     int i;
1693
1694     if (ctxt == NULL)
1695         return;
1696     rctxt = ctxt->context;
1697     if (rctxt == NULL)
1698         return;
1699     name = rctxt->function;
1700     ns_uri = rctxt->functionURI;
1701 #ifdef DEBUG_XPATH
1702     printf("libxml_xmlXPathFuncCallback called name %s URI %s\n", name,
1703            ns_uri);
1704 #endif
1705
1706     /*
1707      * Find the function, it should be there it was there at lookup
1708      */
1709     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
1710         if (                    /* TODO (ctxt == libxml_xpathCallbacks[i].ctx) && */
1711                (xmlStrEqual(name, libxml_xpathCallbacks[i].name)) &&
1712                (xmlStrEqual(ns_uri, libxml_xpathCallbacks[i].ns_uri))) {
1713             current_function = libxml_xpathCallbacks[i].function;
1714         }
1715     }
1716     if (current_function == NULL) {
1717         printf
1718             ("libxml_xmlXPathFuncCallback: internal error %s not found !\n",
1719              name);
1720         return;
1721     }
1722
1723     list = PyTuple_New(nargs + 1);
1724     PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt));
1725     for (i = 0; i < nargs; i++) {
1726         obj = valuePop(ctxt);
1727         cur = libxml_xmlXPathObjectPtrWrap(obj);
1728         PyTuple_SetItem(list, i + 1, cur);
1729     }
1730     result = PyEval_CallObject(current_function, list);
1731     Py_DECREF(list);
1732
1733     obj = libxml_xmlXPathObjectPtrConvert(result);
1734     valuePush(ctxt, obj);
1735 }
1736
1737 static xmlXPathFunction
1738 libxml_xmlXPathFuncLookupFunc(void *ctxt, const xmlChar * name,
1739                               const xmlChar * ns_uri)
1740 {
1741     int i;
1742
1743 #ifdef DEBUG_XPATH
1744     printf("libxml_xmlXPathFuncLookupFunc(%p, %s, %s) called\n",
1745            ctxt, name, ns_uri);
1746 #endif
1747     /*
1748      * This is called once only. The address is then stored in the
1749      * XPath expression evaluation, the proper object to call can
1750      * then still be found using the execution context function
1751      * and functionURI fields.
1752      */
1753     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
1754         if ((ctxt == libxml_xpathCallbacks[i].ctx) &&
1755             (xmlStrEqual(name, libxml_xpathCallbacks[i].name)) &&
1756             (xmlStrEqual(ns_uri, libxml_xpathCallbacks[i].ns_uri))) {
1757             return (libxml_xmlXPathFuncCallback);
1758         }
1759     }
1760     return (NULL);
1761 }
1762
1763 static void
1764 libxml_xpathCallbacksInitialize(void)
1765 {
1766     int i;
1767
1768     if (libxml_xpathCallbacksInitialized != 0)
1769         return;
1770
1771 #ifdef DEBUG_XPATH
1772     printf("libxml_xpathCallbacksInitialized called\n");
1773 #endif
1774
1775     for (i = 0; i < libxml_xpathCallbacksMax; i++) {
1776         libxml_xpathCallbacks[i].ctx = NULL;
1777         libxml_xpathCallbacks[i].name = NULL;
1778         libxml_xpathCallbacks[i].ns_uri = NULL;
1779         libxml_xpathCallbacks[i].function = NULL;
1780     }
1781     libxml_xpathCallbacksInitialized = 1;
1782 }
1783
1784 PyObject *
1785 libxml_xmlRegisterXPathFunction(ATTRIBUTE_UNUSED PyObject * self,
1786                                 PyObject * args)
1787 {
1788     PyObject *py_retval;
1789     int c_retval = 0;
1790     xmlChar *name;
1791     xmlChar *ns_uri;
1792     xmlXPathContextPtr ctx;
1793     PyObject *pyobj_ctx;
1794     PyObject *pyobj_f;
1795     int i;
1796
1797     if (!PyArg_ParseTuple
1798         (args, (char *) "OszO:registerXPathFunction", &pyobj_ctx, &name,
1799          &ns_uri, &pyobj_f))
1800         return (NULL);
1801
1802     ctx = (xmlXPathContextPtr) PyxmlXPathContext_Get(pyobj_ctx);
1803     if (libxml_xpathCallbacksInitialized == 0)
1804         libxml_xpathCallbacksInitialize();
1805     xmlXPathRegisterFuncLookup(ctx, libxml_xmlXPathFuncLookupFunc, ctx);
1806
1807     if ((pyobj_ctx == NULL) || (name == NULL) || (pyobj_f == NULL)) {
1808         py_retval = libxml_intWrap(-1);
1809         return (py_retval);
1810     }
1811 #ifdef DEBUG_XPATH
1812     printf("libxml_registerXPathFunction(%p, %s, %s) called\n",
1813            ctx, name, ns_uri);
1814 #endif
1815     for (i = 0; i < libxml_xpathCallbacksNb; i++) {
1816         if ((ctx == libxml_xpathCallbacks[i].ctx) &&
1817             (xmlStrEqual(name, libxml_xpathCallbacks[i].name)) &&
1818             (xmlStrEqual(ns_uri, libxml_xpathCallbacks[i].ns_uri))) {
1819             Py_XINCREF(pyobj_f);
1820             Py_XDECREF(libxml_xpathCallbacks[i].function);
1821             libxml_xpathCallbacks[i].function = pyobj_f;
1822             c_retval = 1;
1823             goto done;
1824         }
1825     }
1826     if (libxml_xpathCallbacksNb >= libxml_xpathCallbacksMax) {
1827         printf("libxml_registerXPathFunction() table full\n");
1828     } else {
1829         i = libxml_xpathCallbacksNb++;
1830         Py_XINCREF(pyobj_f);
1831         libxml_xpathCallbacks[i].ctx = ctx;
1832         libxml_xpathCallbacks[i].name = xmlStrdup(name);
1833         libxml_xpathCallbacks[i].ns_uri = xmlStrdup(ns_uri);
1834         libxml_xpathCallbacks[i].function = pyobj_f;
1835         c_retval = 1;
1836     }
1837   done:
1838     py_retval = libxml_intWrap((int) c_retval);
1839     return (py_retval);
1840 }
1841
1842 /************************************************************************
1843  *                                                                      *
1844  *                      Global properties access                        *
1845  *                                                                      *
1846  ************************************************************************/
1847 static PyObject *
1848 libxml_name(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1849 {
1850     PyObject *resultobj, *obj;
1851     xmlNodePtr cur;
1852     const xmlChar *res;
1853
1854     if (!PyArg_ParseTuple(args, (char *) "O:name", &obj))
1855         return NULL;
1856     cur = PyxmlNode_Get(obj);
1857
1858 #ifdef DEBUG
1859     printf("libxml_name: cur = %p type %d\n", cur, cur->type);
1860 #endif
1861
1862     switch (cur->type) {
1863         case XML_DOCUMENT_NODE:
1864 #ifdef LIBXML_DOCB_ENABLED
1865         case XML_DOCB_DOCUMENT_NODE:
1866 #endif
1867         case XML_HTML_DOCUMENT_NODE:{
1868                 xmlDocPtr doc = (xmlDocPtr) cur;
1869
1870                 res = doc->URL;
1871                 break;
1872             }
1873         case XML_ATTRIBUTE_NODE:{
1874                 xmlAttrPtr attr = (xmlAttrPtr) cur;
1875
1876                 res = attr->name;
1877                 break;
1878             }
1879         case XML_NAMESPACE_DECL:{
1880                 xmlNsPtr ns = (xmlNsPtr) cur;
1881
1882                 res = ns->prefix;
1883                 break;
1884             }
1885         default:
1886             res = cur->name;
1887             break;
1888     }
1889     resultobj = libxml_constxmlCharPtrWrap(res);
1890
1891     return resultobj;
1892 }
1893
1894 static PyObject *
1895 libxml_doc(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1896 {
1897     PyObject *resultobj, *obj;
1898     xmlNodePtr cur;
1899     xmlDocPtr res;
1900
1901     if (!PyArg_ParseTuple(args, (char *) "O:doc", &obj))
1902         return NULL;
1903     cur = PyxmlNode_Get(obj);
1904
1905 #ifdef DEBUG
1906     printf("libxml_doc: cur = %p\n", cur);
1907 #endif
1908
1909     switch (cur->type) {
1910         case XML_DOCUMENT_NODE:
1911 #ifdef LIBXML_DOCB_ENABLED
1912         case XML_DOCB_DOCUMENT_NODE:
1913 #endif
1914         case XML_HTML_DOCUMENT_NODE:
1915             res = NULL;
1916             break;
1917         case XML_ATTRIBUTE_NODE:{
1918                 xmlAttrPtr attr = (xmlAttrPtr) cur;
1919
1920                 res = attr->doc;
1921                 break;
1922             }
1923         case XML_NAMESPACE_DECL:
1924             res = NULL;
1925             break;
1926         default:
1927             res = cur->doc;
1928             break;
1929     }
1930     resultobj = libxml_xmlDocPtrWrap(res);
1931     return resultobj;
1932 }
1933
1934 static PyObject *
1935 libxml_properties(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1936 {
1937     PyObject *resultobj, *obj;
1938     xmlNodePtr cur = NULL;
1939     xmlAttrPtr res;
1940
1941     if (!PyArg_ParseTuple(args, (char *) "O:properties", &obj))
1942         return NULL;
1943     cur = PyxmlNode_Get(obj);
1944     if (cur->type == XML_ELEMENT_NODE)
1945         res = cur->properties;
1946     else
1947         res = NULL;
1948     resultobj = libxml_xmlAttrPtrWrap(res);
1949     return resultobj;
1950 }
1951
1952 static PyObject *
1953 libxml_next(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1954 {
1955     PyObject *resultobj, *obj;
1956     xmlNodePtr cur;
1957     xmlNodePtr res;
1958
1959     if (!PyArg_ParseTuple(args, (char *) "O:next", &obj))
1960         return NULL;
1961     cur = PyxmlNode_Get(obj);
1962
1963 #ifdef DEBUG
1964     printf("libxml_next: cur = %p\n", cur);
1965 #endif
1966
1967     switch (cur->type) {
1968         case XML_DOCUMENT_NODE:
1969 #ifdef LIBXML_DOCB_ENABLED
1970         case XML_DOCB_DOCUMENT_NODE:
1971 #endif
1972         case XML_HTML_DOCUMENT_NODE:
1973             res = NULL;
1974             break;
1975         case XML_ATTRIBUTE_NODE:{
1976                 xmlAttrPtr attr = (xmlAttrPtr) cur;
1977
1978                 res = (xmlNodePtr) attr->next;
1979                 break;
1980             }
1981         case XML_NAMESPACE_DECL:{
1982                 xmlNsPtr ns = (xmlNsPtr) cur;
1983
1984                 res = (xmlNodePtr) ns->next;
1985                 break;
1986             }
1987         default:
1988             res = cur->next;
1989             break;
1990
1991     }
1992     resultobj = libxml_xmlNodePtrWrap(res);
1993     return resultobj;
1994 }
1995
1996 static PyObject *
1997 libxml_prev(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1998 {
1999     PyObject *resultobj, *obj;
2000     xmlNodePtr cur;
2001     xmlNodePtr res;
2002
2003     if (!PyArg_ParseTuple(args, (char *) "O:prev", &obj))
2004         return NULL;
2005     cur = PyxmlNode_Get(obj);
2006
2007 #ifdef DEBUG
2008     printf("libxml_prev: cur = %p\n", cur);
2009 #endif
2010
2011     switch (cur->type) {
2012         case XML_DOCUMENT_NODE:
2013 #ifdef LIBXML_DOCB_ENABLED
2014         case XML_DOCB_DOCUMENT_NODE:
2015 #endif
2016         case XML_HTML_DOCUMENT_NODE:
2017             res = NULL;
2018             break;
2019         case XML_ATTRIBUTE_NODE:{
2020                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2021
2022                 res = (xmlNodePtr) attr->prev;
2023             }
2024         case XML_NAMESPACE_DECL:
2025             res = NULL;
2026             break;
2027         default:
2028             res = cur->prev;
2029             break;
2030     }
2031     resultobj = libxml_xmlNodePtrWrap(res);
2032     return resultobj;
2033 }
2034
2035 static PyObject *
2036 libxml_children(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2037 {
2038     PyObject *resultobj, *obj;
2039     xmlNodePtr cur;
2040     xmlNodePtr res;
2041
2042     if (!PyArg_ParseTuple(args, (char *) "O:children", &obj))
2043         return NULL;
2044     cur = PyxmlNode_Get(obj);
2045
2046 #ifdef DEBUG
2047     printf("libxml_children: cur = %p\n", cur);
2048 #endif
2049
2050     switch (cur->type) {
2051         case XML_ELEMENT_NODE:
2052         case XML_ENTITY_REF_NODE:
2053         case XML_ENTITY_NODE:
2054         case XML_PI_NODE:
2055         case XML_COMMENT_NODE:
2056         case XML_DOCUMENT_NODE:
2057 #ifdef LIBXML_DOCB_ENABLED
2058         case XML_DOCB_DOCUMENT_NODE:
2059 #endif
2060         case XML_HTML_DOCUMENT_NODE:
2061         case XML_DTD_NODE:
2062             res = cur->children;
2063             break;
2064         case XML_ATTRIBUTE_NODE:{
2065                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2066
2067                 res = attr->children;
2068                 break;
2069             }
2070         default:
2071             res = NULL;
2072             break;
2073     }
2074     resultobj = libxml_xmlNodePtrWrap(res);
2075     return resultobj;
2076 }
2077
2078 static PyObject *
2079 libxml_last(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2080 {
2081     PyObject *resultobj, *obj;
2082     xmlNodePtr cur;
2083     xmlNodePtr res;
2084
2085     if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2086         return NULL;
2087     cur = PyxmlNode_Get(obj);
2088
2089 #ifdef DEBUG
2090     printf("libxml_last: cur = %p\n", cur);
2091 #endif
2092
2093     switch (cur->type) {
2094         case XML_ELEMENT_NODE:
2095         case XML_ENTITY_REF_NODE:
2096         case XML_ENTITY_NODE:
2097         case XML_PI_NODE:
2098         case XML_COMMENT_NODE:
2099         case XML_DOCUMENT_NODE:
2100 #ifdef LIBXML_DOCB_ENABLED
2101         case XML_DOCB_DOCUMENT_NODE:
2102 #endif
2103         case XML_HTML_DOCUMENT_NODE:
2104         case XML_DTD_NODE:
2105             res = cur->last;
2106             break;
2107         case XML_ATTRIBUTE_NODE:{
2108                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2109
2110                 res = attr->last;
2111             }
2112         default:
2113             res = NULL;
2114             break;
2115     }
2116     resultobj = libxml_xmlNodePtrWrap(res);
2117     return resultobj;
2118 }
2119
2120 static PyObject *
2121 libxml_parent(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2122 {
2123     PyObject *resultobj, *obj;
2124     xmlNodePtr cur;
2125     xmlNodePtr res;
2126
2127     if (!PyArg_ParseTuple(args, (char *) "O:parent", &obj))
2128         return NULL;
2129     cur = PyxmlNode_Get(obj);
2130
2131 #ifdef DEBUG
2132     printf("libxml_parent: cur = %p\n", cur);
2133 #endif
2134
2135     switch (cur->type) {
2136         case XML_DOCUMENT_NODE:
2137         case XML_HTML_DOCUMENT_NODE:
2138 #ifdef LIBXML_DOCB_ENABLED
2139         case XML_DOCB_DOCUMENT_NODE:
2140 #endif
2141             res = NULL;
2142             break;
2143         case XML_ATTRIBUTE_NODE:{
2144                 xmlAttrPtr attr = (xmlAttrPtr) cur;
2145
2146                 res = attr->parent;
2147             }
2148         case XML_ENTITY_DECL:
2149         case XML_NAMESPACE_DECL:
2150         case XML_XINCLUDE_START:
2151         case XML_XINCLUDE_END:
2152             res = NULL;
2153             break;
2154         default:
2155             res = cur->parent;
2156             break;
2157     }
2158     resultobj = libxml_xmlNodePtrWrap(res);
2159     return resultobj;
2160 }
2161
2162 static PyObject *
2163 libxml_type(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2164 {
2165     PyObject *resultobj, *obj;
2166     xmlNodePtr cur;
2167     const xmlChar *res = NULL;
2168
2169     if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2170         return NULL;
2171     cur = PyxmlNode_Get(obj);
2172
2173 #ifdef DEBUG
2174     printf("libxml_type: cur = %p\n", cur);
2175 #endif
2176
2177     switch (cur->type) {
2178         case XML_ELEMENT_NODE:
2179             res = (const xmlChar *) "element";
2180             break;
2181         case XML_ATTRIBUTE_NODE:
2182             res = (const xmlChar *) "attribute";
2183             break;
2184         case XML_TEXT_NODE:
2185             res = (const xmlChar *) "text";
2186             break;
2187         case XML_CDATA_SECTION_NODE:
2188             res = (const xmlChar *) "cdata";
2189             break;
2190         case XML_ENTITY_REF_NODE:
2191             res = (const xmlChar *) "entity_ref";
2192             break;
2193         case XML_ENTITY_NODE:
2194             res = (const xmlChar *) "entity";
2195             break;
2196         case XML_PI_NODE:
2197             res = (const xmlChar *) "pi";
2198             break;
2199         case XML_COMMENT_NODE:
2200             res = (const xmlChar *) "comment";
2201             break;
2202         case XML_DOCUMENT_NODE:
2203             res = (const xmlChar *) "document_xml";
2204             break;
2205         case XML_DOCUMENT_TYPE_NODE:
2206             res = (const xmlChar *) "doctype";
2207             break;
2208         case XML_DOCUMENT_FRAG_NODE:
2209             res = (const xmlChar *) "fragment";
2210             break;
2211         case XML_NOTATION_NODE:
2212             res = (const xmlChar *) "notation";
2213             break;
2214         case XML_HTML_DOCUMENT_NODE:
2215             res = (const xmlChar *) "document_html";
2216             break;
2217         case XML_DTD_NODE:
2218             res = (const xmlChar *) "dtd";
2219             break;
2220         case XML_ELEMENT_DECL:
2221             res = (const xmlChar *) "elem_decl";
2222             break;
2223         case XML_ATTRIBUTE_DECL:
2224             res = (const xmlChar *) "attribute_decl";
2225             break;
2226         case XML_ENTITY_DECL:
2227             res = (const xmlChar *) "entity_decl";
2228             break;
2229         case XML_NAMESPACE_DECL:
2230             res = (const xmlChar *) "namespace";
2231             break;
2232         case XML_XINCLUDE_START:
2233             res = (const xmlChar *) "xinclude_start";
2234             break;
2235         case XML_XINCLUDE_END:
2236             res = (const xmlChar *) "xinclude_end";
2237             break;
2238 #ifdef LIBXML_DOCB_ENABLED
2239         case XML_DOCB_DOCUMENT_NODE:
2240             res = (const xmlChar *) "document_docbook";
2241             break;
2242 #endif
2243     }
2244 #ifdef DEBUG
2245     printf("libxml_type: cur = %p: %s\n", cur, res);
2246 #endif
2247
2248     resultobj = libxml_constxmlCharPtrWrap(res);
2249     return resultobj;
2250 }
2251
2252 /************************************************************************
2253  *                                                                      *
2254  *                      Specific accessor functions                     *
2255  *                                                                      *
2256  ************************************************************************/
2257 PyObject *
2258 libxml_xmlNodeGetNsDefs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2259 {
2260     PyObject *py_retval;
2261     xmlNsPtr c_retval;
2262     xmlNodePtr node;
2263     PyObject *pyobj_node;
2264
2265     if (!PyArg_ParseTuple
2266         (args, (char *) "O:xmlNodeGetNsDefs", &pyobj_node))
2267         return (NULL);
2268     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2269
2270     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2271         Py_INCREF(Py_None);
2272         return (Py_None);
2273     }
2274     c_retval = node->nsDef;
2275     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2276     return (py_retval);
2277 }
2278
2279 PyObject *
2280 libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2281 {
2282     PyObject *py_retval;
2283     xmlNsPtr c_retval;
2284     xmlNodePtr node;
2285     PyObject *pyobj_node;
2286
2287     if (!PyArg_ParseTuple(args, (char *) "O:xmlNodeGetNs", &pyobj_node))
2288         return (NULL);
2289     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2290
2291     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2292         Py_INCREF(Py_None);
2293         return (Py_None);
2294     }
2295     c_retval = node->ns;
2296     py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2297     return (py_retval);
2298 }
2299
2300 /************************************************************************
2301  *                                                                      *
2302  *                      Serialization front-end                         *
2303  *                                                                      *
2304  ************************************************************************/
2305
2306 static PyObject *
2307 libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2308 {
2309     PyObject *py_retval = NULL;
2310     xmlChar *c_retval;
2311     PyObject *pyobj_node;
2312     xmlNodePtr node;
2313     xmlDocPtr doc;
2314     const char *encoding;
2315     int format;
2316     int len;
2317
2318     if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
2319                           &encoding, &format))
2320         return (NULL);
2321     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2322
2323     if (node == NULL) {
2324         Py_INCREF(Py_None);
2325         return (Py_None);
2326     }
2327     if (node->type == XML_DOCUMENT_NODE) {
2328         doc = (xmlDocPtr) node;
2329         xmlDocDumpFormatMemoryEnc(doc, &c_retval, &len,
2330                                   (const char *) encoding, format);
2331         py_retval = libxml_charPtrWrap((char *) c_retval);
2332     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2333         xmlOutputBufferPtr buf;
2334         xmlCharEncodingHandlerPtr handler = NULL;
2335
2336         doc = (xmlDocPtr) node;
2337         if (encoding != NULL)
2338             htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
2339         encoding = (const char *) htmlGetMetaEncoding(doc);
2340
2341         if (encoding != NULL) {
2342             handler = xmlFindCharEncodingHandler(encoding);
2343             if (handler == NULL) {
2344                 Py_INCREF(Py_None);
2345                 return (Py_None);
2346             }
2347         }
2348
2349         /*
2350          * Fallback to HTML or ASCII when the encoding is unspecified
2351          */
2352         if (handler == NULL)
2353             handler = xmlFindCharEncodingHandler("HTML");
2354         if (handler == NULL)
2355             handler = xmlFindCharEncodingHandler("ascii");
2356
2357         buf = xmlAllocOutputBuffer(handler);
2358         if (buf == NULL) {
2359             Py_INCREF(Py_None);
2360             return (Py_None);
2361         }
2362         htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
2363         xmlOutputBufferFlush(buf);
2364         if (buf->conv != NULL) {
2365             len = buf->conv->use;
2366             c_retval = buf->conv->content;
2367             buf->conv->content = NULL;
2368         } else {
2369             len = buf->buffer->use;
2370             c_retval = buf->buffer->content;
2371             buf->buffer->content = NULL;
2372         }
2373         (void) xmlOutputBufferClose(buf);
2374         py_retval = libxml_charPtrWrap((char *) c_retval);
2375     } else {
2376         doc = node->doc;
2377         if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
2378             xmlOutputBufferPtr buf;
2379             xmlCharEncodingHandlerPtr handler = NULL;
2380
2381             if (encoding != NULL) {
2382                 handler = xmlFindCharEncodingHandler(encoding);
2383                 if (handler == NULL) {
2384                     Py_INCREF(Py_None);
2385                     return (Py_None);
2386                 }
2387             }
2388
2389             buf = xmlAllocOutputBuffer(handler);
2390             if (buf == NULL) {
2391                 Py_INCREF(Py_None);
2392                 return (Py_None);
2393             }
2394             xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
2395             xmlOutputBufferFlush(buf);
2396             if (buf->conv != NULL) {
2397                 len = buf->conv->use;
2398                 c_retval = buf->conv->content;
2399                 buf->conv->content = NULL;
2400             } else {
2401                 len = buf->buffer->use;
2402                 c_retval = buf->buffer->content;
2403                 buf->buffer->content = NULL;
2404             }
2405             (void) xmlOutputBufferClose(buf);
2406             py_retval = libxml_charPtrWrap((char *) c_retval);
2407         } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2408             xmlOutputBufferPtr buf;
2409             xmlCharEncodingHandlerPtr handler = NULL;
2410
2411             if (encoding != NULL)
2412                 htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
2413             encoding = (const char *) htmlGetMetaEncoding(doc);
2414             if (encoding != NULL) {
2415                 handler = xmlFindCharEncodingHandler(encoding);
2416                 if (handler == NULL) {
2417                     Py_INCREF(Py_None);
2418                     return (Py_None);
2419                 }
2420             }
2421
2422             /*
2423              * Fallback to HTML or ASCII when the encoding is unspecified
2424              */
2425             if (handler == NULL)
2426                 handler = xmlFindCharEncodingHandler("HTML");
2427             if (handler == NULL)
2428                 handler = xmlFindCharEncodingHandler("ascii");
2429
2430             buf = xmlAllocOutputBuffer(handler);
2431             if (buf == NULL) {
2432                 Py_INCREF(Py_None);
2433                 return (Py_None);
2434             }
2435             htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
2436             xmlOutputBufferFlush(buf);
2437             if (buf->conv != NULL) {
2438                 len = buf->conv->use;
2439                 c_retval = buf->conv->content;
2440                 buf->conv->content = NULL;
2441             } else {
2442                 len = buf->buffer->use;
2443                 c_retval = buf->buffer->content;
2444                 buf->buffer->content = NULL;
2445             }
2446             (void) xmlOutputBufferClose(buf);
2447             py_retval = libxml_charPtrWrap((char *) c_retval);
2448         } else {
2449             Py_INCREF(Py_None);
2450             return (Py_None);
2451         }
2452     }
2453     return (py_retval);
2454 }
2455
2456 static PyObject *
2457 libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2458 {
2459     PyObject *py_file = NULL;
2460     FILE *output;
2461     PyObject *pyobj_node;
2462     xmlNodePtr node;
2463     xmlDocPtr doc;
2464     const char *encoding;
2465     int format;
2466     int len;
2467     xmlOutputBufferPtr buf;
2468     xmlCharEncodingHandlerPtr handler = NULL;
2469
2470     if (!PyArg_ParseTuple(args, (char *) "OOzi:serializeNode", &pyobj_node,
2471                           &py_file, &encoding, &format))
2472         return (NULL);
2473     node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2474
2475     if (node == NULL) {
2476         return (PyInt_FromLong((long) -1));
2477     }
2478     if ((py_file == NULL) || (!(PyFile_Check(py_file)))) {
2479         return (PyInt_FromLong((long) -1));
2480     }
2481     output = PyFile_AsFile(py_file);
2482     if (output == NULL) {
2483         return (PyInt_FromLong((long) -1));
2484     }
2485
2486     if (node->type == XML_DOCUMENT_NODE) {
2487         doc = (xmlDocPtr) node;
2488     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2489         doc = (xmlDocPtr) node;
2490     } else {
2491         doc = node->doc;
2492     }
2493     if (doc->type == XML_HTML_DOCUMENT_NODE) {
2494         if (encoding == NULL)
2495             encoding = (const char *) htmlGetMetaEncoding(doc);
2496     }
2497     if (encoding != NULL) {
2498         handler = xmlFindCharEncodingHandler(encoding);
2499         if (handler == NULL) {
2500             return (PyInt_FromLong((long) -1));
2501         }
2502     }
2503     if (doc->type == XML_HTML_DOCUMENT_NODE) {
2504         if (handler == NULL)
2505             handler = xmlFindCharEncodingHandler("HTML");
2506         if (handler == NULL)
2507             handler = xmlFindCharEncodingHandler("ascii");
2508     }
2509
2510     buf = xmlOutputBufferCreateFile(output, handler);
2511     if (node->type == XML_DOCUMENT_NODE) {
2512         len = xmlSaveFormatFileTo(buf, doc, encoding, format);
2513     } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2514         htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
2515         len = xmlOutputBufferClose(buf);
2516     } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2517         htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
2518         len = xmlOutputBufferClose(buf);
2519     } else {
2520         xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
2521         len = xmlOutputBufferClose(buf);
2522     }
2523     return (PyInt_FromLong((long) len));
2524 }
2525
2526 /************************************************************************
2527  *                                                                      *
2528  *                      Extra stuff                                     *
2529  *                                                                      *
2530  ************************************************************************/
2531 PyObject *
2532 libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2533 {
2534     PyObject *py_retval;
2535     xmlChar *name;
2536     xmlNodePtr node;
2537
2538     if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
2539         return (NULL);
2540     node = (xmlNodePtr) xmlNewNode(NULL, name);
2541 #ifdef DEBUG
2542     printf("NewNode: %s : %p\n", name, (void *) node);
2543 #endif
2544
2545     if (node == NULL) {
2546         Py_INCREF(Py_None);
2547         return (Py_None);
2548     }
2549     py_retval = libxml_xmlNodePtrWrap(node);
2550     return (py_retval);
2551 }
2552
2553
2554 /************************************************************************
2555  *                                                                      *
2556  *                      Local Catalog stuff                             *
2557  *                                                                      *
2558  ************************************************************************/
2559 static PyObject *
2560 libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2561 {
2562     xmlChar *URL;
2563     xmlParserCtxtPtr ctxt;
2564     PyObject *pyobj_ctxt;
2565
2566     if (!PyArg_ParseTuple(args, (char *)"Os:addLocalCatalog", &pyobj_ctxt, &URL))
2567         return(NULL);
2568
2569     ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
2570
2571     if (URL != NULL) {
2572         ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
2573     }
2574
2575 #ifdef DEBUG
2576     printf("LocalCatalog: %s\n", URL);
2577 #endif
2578
2579     Py_INCREF(Py_None);
2580     return (Py_None);
2581 }
2582
2583 #ifdef LIBXML_SCHEMAS_ENABLED
2584
2585 /************************************************************************
2586  *                                                                      *
2587  * RelaxNG error handler registration                                   *
2588  *                                                                      *
2589  ************************************************************************/
2590
2591 typedef struct 
2592 {
2593     PyObject *warn;
2594     PyObject *error;
2595     PyObject *arg;
2596 } xmlRelaxNGValidCtxtPyCtxt;
2597 typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;
2598
2599 static void
2600 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str) 
2601 {
2602     PyObject *list;
2603     PyObject *result;
2604     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
2605     
2606 #ifdef DEBUG_ERROR
2607     printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
2608 #endif
2609
2610     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
2611
2612     list = PyTuple_New(2);
2613     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
2614     PyTuple_SetItem(list, 1, pyCtxt->arg);
2615     Py_XINCREF(pyCtxt->arg);
2616     result = PyEval_CallObject(pyCtxt->error, list);
2617     if (result == NULL) 
2618     {
2619         /* TODO: manage for the exception to be propagated... */
2620         PyErr_Print();
2621     }
2622     Py_XDECREF(list);
2623     Py_XDECREF(result);
2624 }
2625
2626 static void
2627 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str) 
2628 {
2629     PyObject *list;
2630     PyObject *result;
2631     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
2632     
2633 #ifdef DEBUG_ERROR
2634     printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
2635 #endif
2636
2637     pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
2638
2639     list = PyTuple_New(2);
2640     PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
2641     PyTuple_SetItem(list, 1, pyCtxt->arg);
2642     Py_XINCREF(pyCtxt->arg);
2643     result = PyEval_CallObject(pyCtxt->warn, list);
2644     if (result == NULL) 
2645     {
2646         /* TODO: manage for the exception to be propagated... */
2647         PyErr_Print();
2648     }
2649     Py_XDECREF(list);
2650     Py_XDECREF(result);
2651 }
2652
2653 static void
2654 libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
2655 {
2656     va_list ap;
2657
2658     va_start(ap, msg);
2659     libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
2660     va_end(ap);
2661 }
2662
2663 static void
2664 libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
2665 {
2666     va_list ap;
2667
2668     va_start(ap, msg);
2669     libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
2670     va_end(ap);
2671 }
2672
2673 static PyObject *
2674 libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2675 {
2676     PyObject *py_retval;
2677     PyObject *pyobj_error;
2678     PyObject *pyobj_warn;
2679     PyObject *pyobj_ctx;
2680     PyObject *pyobj_arg = Py_None;
2681     xmlRelaxNGValidCtxtPtr ctxt;
2682     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
2683
2684     if (!PyArg_ParseTuple
2685         (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
2686         return (NULL);
2687
2688 #ifdef DEBUG_ERROR
2689     printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
2690 #endif
2691
2692     ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
2693     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
2694     {
2695         py_retval = libxml_intWrap(-1);
2696         return(py_retval);
2697     }
2698     
2699     if (pyCtxt == NULL)
2700     {
2701         /* first time to set the error handlers */
2702         pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
2703         if (pyCtxt == NULL) {
2704             py_retval = libxml_intWrap(-1);
2705             return(py_retval);
2706         }
2707         memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
2708     }
2709     
2710     /* TODO: check warn and error is a function ! */
2711     Py_XDECREF(pyCtxt->error);
2712     Py_XINCREF(pyobj_error);
2713     pyCtxt->error = pyobj_error;
2714     
2715     Py_XDECREF(pyCtxt->warn);
2716     Py_XINCREF(pyobj_warn);
2717     pyCtxt->warn = pyobj_warn;
2718     
2719     Py_XDECREF(pyCtxt->arg);
2720     Py_XINCREF(pyobj_arg);
2721     pyCtxt->arg = pyobj_arg;
2722
2723     xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, &libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);
2724
2725     py_retval = libxml_intWrap(1);
2726     return (py_retval);
2727 }
2728
2729 static PyObject *
2730 libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
2731     xmlRelaxNGValidCtxtPtr ctxt;
2732     xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
2733     PyObject *pyobj_ctxt;
2734
2735     if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
2736         return(NULL);
2737     ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);
2738
2739     if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
2740     {
2741         if (pyCtxt != NULL)
2742         {
2743             Py_XDECREF(pyCtxt->error);
2744             Py_XDECREF(pyCtxt->warn);
2745             Py_XDECREF(pyCtxt->arg);
2746             xmlFree(pyCtxt);
2747         }
2748     }
2749     
2750     xmlRelaxNGFreeValidCtxt(ctxt);
2751     Py_INCREF(Py_None);
2752     return(Py_None);
2753 }
2754
2755 #endif
2756
2757 /************************************************************************
2758  *                                                                      *
2759  *                      The registration stuff                          *
2760  *                                                                      *
2761  ************************************************************************/
2762 static PyMethodDef libxmlMethods[] = {
2763 #include "libxml2-export.c"
2764     {(char *) "name", libxml_name, METH_VARARGS, NULL},
2765     {(char *) "children", libxml_children, METH_VARARGS, NULL},
2766     {(char *) "properties", libxml_properties, METH_VARARGS, NULL},
2767     {(char *) "last", libxml_last, METH_VARARGS, NULL},
2768     {(char *) "prev", libxml_prev, METH_VARARGS, NULL},
2769     {(char *) "next", libxml_next, METH_VARARGS, NULL},
2770     {(char *) "parent", libxml_parent, METH_VARARGS, NULL},
2771     {(char *) "type", libxml_type, METH_VARARGS, NULL},
2772     {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
2773     {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
2774     {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
2775     {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
2776     {(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
2777     {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
2778     {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
2779     {(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
2780     {(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
2781     {(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
2782     {(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
2783     {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
2784     {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
2785     {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
2786     {(char *)"addLocalCatalog", libxml_addLocalCatalog, METH_VARARGS, NULL },
2787 #ifdef LIBXML_SCHEMAS_ENABLED
2788     {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
2789     {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
2790 #endif
2791     {NULL, NULL, 0, NULL}
2792 };
2793
2794 #ifdef MERGED_MODULES
2795 extern void initlibxsltmod(void);
2796 #endif
2797
2798 void
2799 initlibxml2mod(void)
2800 {
2801     static int initialized = 0;
2802     PyObject *m;
2803
2804     if (initialized != 0)
2805         return;
2806     /* XXX xmlInitParser does much more than this */
2807     xmlInitGlobals();
2808     xmlRegisterDefaultOutputCallbacks();
2809     xmlRegisterDefaultInputCallbacks();
2810     m = Py_InitModule((char *) "libxml2mod", libxmlMethods);
2811     initialized = 1;
2812     libxml_xmlErrorInitialize();
2813
2814 #ifdef MERGED_MODULES
2815     initlibxsltmod();
2816 #endif
2817 }