VirtualBox

source: vbox/trunk/src/libs/libxml2-2.9.14/python/libxml.c@ 104197

Last change on this file since 104197 was 95312, checked in by vboxsync, 3 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette