3723 lines · 102.0 KB · C
RawDownload
/* * libxml.c: this modules implements the main part of the glue of the *           libxml2 library and the Python interpreter. It provides the *           entry points where an automatically generated stub is either *           unpractical or would not match cleanly the Python model. * * If compiled with MERGED_MODULES, the entry point will be used to * initialize both the libxml2 and the libxslt wrappers * * See Copyright for the status of this software. * * daniel@veillard.com */#include <Python.h>#include <fileobject.h>/* #include "config.h" */#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <libxml/tree.h>#include <libxml/xpath.h>#include <libxml/xmlerror.h>#include <libxml/xpathInternals.h>#include <libxml/xmlmemory.h>#include <libxml/xmlIO.h>#include <libxml/c14n.h>#include <libxml/xmlreader.h>#include <libxml/xmlsave.h>#include "libxml_wrap.h"#include "libxml2-py.h" #if defined(WITH_TRIO)#include "trio.h"#define vsnprintf trio_vsnprintf#endif /* #define DEBUG *//* #define DEBUG_SAX *//* #define DEBUG_XPATH *//* #define DEBUG_ERROR *//* #define DEBUG_MEMORY *//* #define DEBUG_FILES *//* #define DEBUG_LOADER */ void initlibxml2mod(void); /** * TODO: * * macro to flag unimplemented blocks */#define TODO 								\    xmlGenericError(xmlGenericErrorContext,				\	    "Unimplemented block at %s:%d\n",				\            __FILE__, __LINE__);/* * the following vars are used for XPath extensions, but * are also referenced within the parser cleanup routine. */static int libxml_xpathCallbacksInitialized = 0; typedef struct libxml_xpathCallback {    xmlXPathContextPtr ctx;    xmlChar *name;    xmlChar *ns_uri;    PyObject *function;} libxml_xpathCallback, *libxml_xpathCallbackPtr;typedef libxml_xpathCallback libxml_xpathCallbackArray[];static int libxml_xpathCallbacksAllocd = 10;static libxml_xpathCallbackArray *libxml_xpathCallbacks = NULL;static int libxml_xpathCallbacksNb = 0; /************************************************************************ *									* *		Memory debug interface					* *									* ************************************************************************/ #if 0extern void xmlMemFree(void *ptr);extern void *xmlMemMalloc(size_t size);extern void *xmlMemRealloc(void *ptr, size_t size);extern char *xmlMemoryStrdup(const char *str);#endif static int libxmlMemoryDebugActivated = 0;static long libxmlMemoryAllocatedBase = 0; static int libxmlMemoryDebug = 0;static xmlFreeFunc freeFunc = NULL;static xmlMallocFunc mallocFunc = NULL;static xmlReallocFunc reallocFunc = NULL;static xmlStrdupFunc strdupFunc = NULL; static voidlibxml_xmlErrorInitialize(void); /* forward declare */ PyObject *libxml_xmlMemoryUsed(PyObject * self ATTRIBUTE_UNUSED,         PyObject * args ATTRIBUTE_UNUSED){    long ret;    PyObject *py_retval;     ret = xmlMemUsed();     py_retval = libxml_longWrap(ret);    return (py_retval);} PyObject *libxml_xmlDebugMemory(PyObject * self ATTRIBUTE_UNUSED, PyObject * args){    int activate;    PyObject *py_retval;    long ret;     if (!PyArg_ParseTuple(args, (char *) "i:xmlDebugMemory", &activate))        return (NULL); #ifdef DEBUG_MEMORY    printf("libxml_xmlDebugMemory(%d) called\n", activate);#endif     if (activate != 0) {        if (libxmlMemoryDebug == 0) {            /*             * First initialize the library and grab the old memory handlers             * and switch the library to memory debugging             */            xmlMemGet((xmlFreeFunc *) & freeFunc,                      (xmlMallocFunc *) & mallocFunc,                      (xmlReallocFunc *) & reallocFunc,                      (xmlStrdupFunc *) & strdupFunc);            if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&                (reallocFunc == xmlMemRealloc) &&                (strdupFunc == xmlMemoryStrdup)) {                libxmlMemoryAllocatedBase = xmlMemUsed();            } else {                /*                  * cleanup first, because some memory has been                 * allocated with the non-debug malloc in xmlInitParser                 * when the python module was imported                 */                xmlCleanupParser();                ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,                                         xmlMemRealloc, xmlMemoryStrdup);                if (ret < 0)                    goto error;                libxmlMemoryAllocatedBase = xmlMemUsed();                /* reinitialize */                xmlInitParser();                libxml_xmlErrorInitialize();            }            ret = 0;        } else if (libxmlMemoryDebugActivated == 0) {            libxmlMemoryAllocatedBase = xmlMemUsed();            ret = 0;        } else {            ret = xmlMemUsed() - libxmlMemoryAllocatedBase;        }        libxmlMemoryDebug = 1;        libxmlMemoryDebugActivated = 1;    } else {        if (libxmlMemoryDebugActivated == 1)            ret = xmlMemUsed() - libxmlMemoryAllocatedBase;        else            ret = 0;        libxmlMemoryDebugActivated = 0;    }  error:    py_retval = libxml_longWrap(ret);    return (py_retval);} PyObject *libxml_xmlPythonCleanupParser(PyObject *self ATTRIBUTE_UNUSED,                              PyObject *args ATTRIBUTE_UNUSED) {     int ix;    long freed = -1;     if (libxmlMemoryDebug) {        freed = xmlMemUsed();    }     xmlCleanupParser();    /*     * Need to confirm whether we really want to do this (required for     * memcheck) in all cases...     */       if (libxml_xpathCallbacks != NULL) {	/* if ext funcs declared */	for (ix=0; ix<libxml_xpathCallbacksNb; ix++) {	    if ((*libxml_xpathCallbacks)[ix].name != NULL)	        xmlFree((*libxml_xpathCallbacks)[ix].name);	    if ((*libxml_xpathCallbacks)[ix].ns_uri != NULL)	        xmlFree((*libxml_xpathCallbacks)[ix].ns_uri);	}	libxml_xpathCallbacksNb = 0;        xmlFree(libxml_xpathCallbacks);	libxml_xpathCallbacks = NULL;    }     if (libxmlMemoryDebug) {        freed -= xmlMemUsed();	libxmlMemoryAllocatedBase -= freed;	if (libxmlMemoryAllocatedBase < 0)	    libxmlMemoryAllocatedBase = 0;    }     Py_INCREF(Py_None);    return(Py_None);} PyObject *libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,                     ATTRIBUTE_UNUSED PyObject * args){     if (libxmlMemoryDebug != 0)        xmlMemoryDump();    Py_INCREF(Py_None);    return (Py_None);} /************************************************************************ *									* *		Handling Python FILE I/O at the C level			* *	The raw I/O attack diectly the File objects, while the		* *	other routines address the ioWrapper instance instead		* *									* ************************************************************************/ /** * xmlPythonFileCloseUnref: * @context:  the I/O context * * Close an I/O channel */static intxmlPythonFileCloseRaw (void * context) {    PyObject *file, *ret; #ifdef DEBUG_FILES    printf("xmlPythonFileCloseUnref\n");#endif    file = (PyObject *) context;    if (file == NULL) return(-1);    ret = PyEval_CallMethod(file, (char *) "close", (char *) "()");    if (ret != NULL) {	Py_DECREF(ret);    }    Py_DECREF(file);    return(0);} /** * xmlPythonFileReadRaw: * @context:  the I/O context * @buffer:  where to drop data * @len:  number of bytes to write * * Read @len bytes to @buffer from the Python file in the I/O channel * * Returns the number of bytes read */static intxmlPythonFileReadRaw (void * context, char * buffer, int len) {    PyObject *file;    PyObject *ret;    int lenread = -1;    char *data; #ifdef DEBUG_FILES    printf("xmlPythonFileReadRaw: %d\n", len);#endif    file = (PyObject *) context;    if (file == NULL) return(-1);    ret = PyEval_CallMethod(file, (char *) "read", (char *) "(i)", len);    if (ret == NULL) {	printf("xmlPythonFileReadRaw: result is NULL\n");	return(-1);    } else if (PyString_Check(ret)) {	lenread = PyString_Size(ret);	data = PyString_AsString(ret);	if (lenread > len)	    memcpy(buffer, data, len);	else	    memcpy(buffer, data, lenread);	Py_DECREF(ret);    } else {	printf("xmlPythonFileReadRaw: result is not a String\n");	Py_DECREF(ret);    }    return(lenread);} /** * xmlPythonFileRead: * @context:  the I/O context * @buffer:  where to drop data * @len:  number of bytes to write * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes read */static intxmlPythonFileRead (void * context, char * buffer, int len) {    PyObject *file;    PyObject *ret;    int lenread = -1;    char *data; #ifdef DEBUG_FILES    printf("xmlPythonFileRead: %d\n", len);#endif    file = (PyObject *) context;    if (file == NULL) return(-1);    ret = PyEval_CallMethod(file, (char *) "io_read", (char *) "(i)", len);    if (ret == NULL) {	printf("xmlPythonFileRead: result is NULL\n");	return(-1);    } else if (PyString_Check(ret)) {	lenread = PyString_Size(ret);	data = PyString_AsString(ret);	if (lenread > len)	    memcpy(buffer, data, len);	else	    memcpy(buffer, data, lenread);	Py_DECREF(ret);    } else {	printf("xmlPythonFileRead: result is not a String\n");	Py_DECREF(ret);    }    return(lenread);} /** * xmlFileWrite: * @context:  the I/O context * @buffer:  where to drop data * @len:  number of bytes to write * * Write @len bytes from @buffer to the I/O channel. * * Returns the number of bytes written */static intxmlPythonFileWrite (void * context, const char * buffer, int len) {    PyObject *file;    PyObject *string;    PyObject *ret = NULL;    int written = -1; #ifdef DEBUG_FILES    printf("xmlPythonFileWrite: %d\n", len);#endif    file = (PyObject *) context;    if (file == NULL) return(-1);    string = PyString_FromStringAndSize(buffer, len);    if (string == NULL) return(-1);    if (PyObject_HasAttrString(file, (char *) "io_write")) {        ret = PyEval_CallMethod(file, (char *) "io_write", (char *) "(O)",	                        string);    } else if (PyObject_HasAttrString(file, (char *) "write")) {        ret = PyEval_CallMethod(file, (char *) "write", (char *) "(O)",	                        string);    }    Py_DECREF(string);    if (ret == NULL) {	printf("xmlPythonFileWrite: result is NULL\n");	return(-1);    } else if (PyInt_Check(ret)) {	written = (int) PyInt_AsLong(ret);	Py_DECREF(ret);    } else if (ret == Py_None) {	written = len;	Py_DECREF(ret);    } else {	printf("xmlPythonFileWrite: result is not an Int nor None\n");	Py_DECREF(ret);    }    return(written);} /** * xmlPythonFileClose: * @context:  the I/O context * * Close an I/O channel */static intxmlPythonFileClose (void * context) {    PyObject *file, *ret = NULL; #ifdef DEBUG_FILES    printf("xmlPythonFileClose\n");#endif    file = (PyObject *) context;    if (file == NULL) return(-1);    if (PyObject_HasAttrString(file, (char *) "io_close")) {        ret = PyEval_CallMethod(file, (char *) "io_close", (char *) "()");    } else if (PyObject_HasAttrString(file, (char *) "flush")) {        ret = PyEval_CallMethod(file, (char *) "flush", (char *) "()");    }    if (ret != NULL) {	Py_DECREF(ret);    }    return(0);} #ifdef LIBXML_OUTPUT_ENABLED/** * xmlOutputBufferCreatePythonFile: * @file:  a PyFile_Type * @encoder:  the encoding converter or NULL * * Create a buffered output for the progressive saving to a PyFile_Type * buffered C I/O * * Returns the new parser output or NULL */static xmlOutputBufferPtrxmlOutputBufferCreatePythonFile(PyObject *file, 	                        xmlCharEncodingHandlerPtr encoder) {    xmlOutputBufferPtr ret;     if (file == NULL) return(NULL);     ret = xmlAllocOutputBuffer(encoder);    if (ret != NULL) {        ret->context = file;	/* Py_INCREF(file); */	ret->writecallback = xmlPythonFileWrite;	ret->closecallback = xmlPythonFileClose;    }     return(ret);} PyObject *libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {    PyObject *py_retval;    PyObject *file;    xmlChar  *encoding;    xmlCharEncodingHandlerPtr handler = NULL;    xmlOutputBufferPtr buffer;      if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",		&file, &encoding))	return(NULL);    if ((encoding != NULL) && (encoding[0] != 0)) {	handler = xmlFindCharEncodingHandler((const char *) encoding);    }    buffer = xmlOutputBufferCreatePythonFile(file, handler);    if (buffer == NULL)	printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");    py_retval = libxml_xmlOutputBufferPtrWrap(buffer);    return(py_retval);} /** * libxml_outputBufferGetPythonFile: * @buffer:  the I/O buffer * * read the Python I/O from the CObject * * Returns the new parser output or NULL */static PyObject *libxml_outputBufferGetPythonFile(ATTRIBUTE_UNUSED PyObject *self,                                    PyObject *args) {    PyObject *buffer;    PyObject *file;    xmlOutputBufferPtr obj;     if (!PyArg_ParseTuple(args, (char *)"O:outputBufferGetPythonFile",			  &buffer))	return(NULL);     obj = PyoutputBuffer_Get(buffer);    if (obj == NULL) {	fprintf(stderr,	        "outputBufferGetPythonFile: obj == NULL\n");	Py_INCREF(Py_None);	return(Py_None);    }    if (obj->closecallback != xmlPythonFileClose) {	fprintf(stderr,	        "outputBufferGetPythonFile: not a python file wrapper\n");	Py_INCREF(Py_None);	return(Py_None);    }    file = (PyObject *) obj->context;    if (file == NULL) {	Py_INCREF(Py_None);	return(Py_None);    }

Lines 1–500 of 3723.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t