#ifndef HAS_ETREE_DEFS_H #define HAS_ETREE_DEFS_H /* quick check for Python/libxml2/libxslt devel setup */ #include "Python.h" #ifndef PY_VERSION_HEX # error the development package of Python (header files etc.) is not installed correctly #endif #include "libxml/xmlversion.h" #ifndef LIBXML_VERSION # error the development package of libxml2 (header files etc.) is not installed correctly #endif #include "libxslt/xsltconfig.h" #ifndef LIBXSLT_VERSION # error the development package of libxslt (header files etc.) is not installed correctly #endif /* v_arg functions */ #define va_int(ap) va_arg(ap, int) #define va_charptr(ap) va_arg(ap, char *) #ifdef PYPY_VERSION # define IS_PYPY 1 #else # define IS_PYPY 0 #endif #if PY_VERSION_HEX >= 0x03000000 # define IS_PYTHON3 1 #else # define IS_PYTHON3 0 #endif #if IS_PYTHON3 #undef LXML_UNICODE_STRINGS #define LXML_UNICODE_STRINGS 1 #else #ifndef LXML_UNICODE_STRINGS #define LXML_UNICODE_STRINGS 0 #endif #endif #if !IS_PYPY # define PyWeakref_LockObject(obj) (NULL) #endif /* Threading can crash under Python <= 2.4.1 and is not currently supported by PyPy */ #if PY_VERSION_HEX < 0x02040200 || IS_PYPY # ifndef WITHOUT_THREADING # define WITHOUT_THREADING # endif #endif /* Python 3 doesn't have PyFile_*() anymore */ #if PY_VERSION_HEX >= 0x03000000 # define PyFile_AsFile(o) (NULL) #else #if IS_PYPY # undef PyFile_AsFile # define PyFile_AsFile(o) (NULL) # undef PyUnicode_FromFormat # define PyUnicode_FromFormat(s, a, b) (NULL) #else #if PY_VERSION_HEX < 0x02060000 /* Cython defines these already, but we may not be compiling in Cython code */ #ifndef PyBytes_CheckExact # define PyBytes_CheckExact(o) PyString_CheckExact(o) # define PyBytes_Check(o) PyString_Check(o) # define PyBytes_FromStringAndSize(s, len) PyString_FromStringAndSize(s, len) # define PyBytes_FromFormat PyString_FromFormat # define PyBytes_GET_SIZE(s) PyString_GET_SIZE(s) # define PyBytes_AS_STRING(s) PyString_AS_STRING(s) #endif /* we currently only use three parameters - MSVC can't compile (s, ...) */ # define PyUnicode_FromFormat(s, a, b) (NULL) #endif #endif #endif /* PySlice_GetIndicesEx() has wrong signature in Py<=3.1 */ #if PY_VERSION_HEX >= 0x03020000 # define _lx_PySlice_GetIndicesEx(o, l, b, e, s, sl) PySlice_GetIndicesEx(o, l, b, e, s, sl) #else # define _lx_PySlice_GetIndicesEx(o, l, b, e, s, sl) PySlice_GetIndicesEx(((PySliceObject*)o), l, b, e, s, sl) #endif #ifdef WITHOUT_THREADING # define PyEval_SaveThread() (NULL) # define PyEval_RestoreThread(state) # define PyGILState_Ensure() (PyGILState_UNLOCKED) # define PyGILState_Release(state) # undef Py_UNBLOCK_THREADS # define Py_UNBLOCK_THREADS # undef Py_BLOCK_THREADS # define Py_BLOCK_THREADS #endif #ifdef WITHOUT_THREADING # define ENABLE_THREADING 0 #else # define ENABLE_THREADING 1 #endif /* libxml2 version specific setup */ #if LIBXML_VERSION < 20621 /* (X|HT)ML_PARSE_COMPACT were added in libxml2 2.6.21 */ # define XML_PARSE_COMPACT 1 << 16 # define HTML_PARSE_COMPACT XML_PARSE_COMPACT /* HTML_PARSE_RECOVER was added in libxml2 2.6.21 */ # define HTML_PARSE_RECOVER XML_PARSE_RECOVER #endif #if LIBXML_VERSION < 20700 /* These were added in libxml2 2.7.0 */ # define XML_PARSE_OLD10 1 << 17 # define XML_PARSE_NOBASEFIX 1 << 18 # define XML_PARSE_HUGE 1 << 19 # define xmlMemDisplayLast(f,d) #endif #if LIBXML_VERSION < 20704 /* FIXME: hack to make new error reporting compile in old libxml2 versions */ # define xmlStructuredErrorContext NULL #endif /* added to xmlsave API in libxml2 2.6.23 */ #if LIBXML_VERSION < 20623 # define xmlSaveToBuffer(buffer, encoding, options) #endif /* added to xmlsave API in libxml2 2.6.22 */ #if LIBXML_VERSION < 20622 # define XML_SAVE_NO_EMPTY 1<<2 /* no empty tags */ # define XML_SAVE_NO_XHTML 1<<3 /* disable XHTML1 specific rules */ #endif /* added to xmlsave API in libxml2 2.6.21 */ #if LIBXML_VERSION < 20621 # define XML_SAVE_NO_DECL 1<<1 /* drop the xml declaration */ #endif /* schematron was added in libxml2 2.6.21 */ #ifdef LIBXML_SCHEMATRON_ENABLED # define ENABLE_SCHEMATRON 1 # if LIBXML_VERSION < 20632 /* schematron error reporting was added in libxml2 2.6.32 */ # define xmlSchematronSetValidStructuredErrors(ctxt, errorfunc, data) # define XML_SCHEMATRON_OUT_ERROR 0 # endif #else # define ENABLE_SCHEMATRON 0 # define XML_SCHEMATRON_OUT_QUIET 0 # define XML_SCHEMATRON_OUT_XML 0 # define XML_SCHEMATRON_OUT_ERROR 0 typedef void xmlSchematron; typedef void xmlSchematronParserCtxt; typedef void xmlSchematronValidCtxt; # define xmlSchematronNewDocParserCtxt(doc) NULL # define xmlSchematronNewParserCtxt(file) NULL # define xmlSchematronParse(ctxt) NULL # define xmlSchematronFreeParserCtxt(ctxt) # define xmlSchematronFree(schema) # define xmlSchematronNewValidCtxt(schema, options) NULL # define xmlSchematronValidateDoc(ctxt, doc) 0 # define xmlSchematronFreeValidCtxt(ctxt) # define xmlSchematronSetValidStructuredErrors(ctxt, errorfunc, data) #endif #include "libxml/tree.h" #ifndef LIBXML2_NEW_BUFFER typedef xmlBuffer xmlBuf; # define xmlBufContent(buf) xmlBufferContent(buf) # define xmlBufUse(buf) xmlBufferLength(buf) #endif /* libexslt 1.1.25+ support EXSLT functions in XPath */ #if LIBXSLT_VERSION < 10125 #define exsltDateXpathCtxtRegister(ctxt, prefix) #define exsltSetsXpathCtxtRegister(ctxt, prefix) #define exsltMathXpathCtxtRegister(ctxt, prefix) #define exsltStrXpathCtxtRegister(ctxt, prefix) #endif /* work around MSDEV 6.0 */ #if (_MSC_VER == 1200) && (WINVER < 0x0500) long _ftol( double ); //defined by VC6 C libs long _ftol2( double dblSource ) { return _ftol( dblSource ); } #endif #ifdef __GNUC__ /* Test for GCC > 2.95 */ #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) #define unlikely_condition(x) __builtin_expect((x), 0) #else /* __GNUC__ > 2 ... */ #define unlikely_condition(x) (x) #endif /* __GNUC__ > 2 ... */ #else /* __GNUC__ */ #define unlikely_condition(x) (x) #endif /* __GNUC__ */ #ifndef Py_TYPE #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif #define PY_NEW(T) \ (((PyTypeObject*)(T))->tp_new( \ (PyTypeObject*)(T), __pyx_empty_tuple, NULL)) #define _fqtypename(o) ((Py_TYPE(o))->tp_name) #if PY_MAJOR_VERSION < 3 #define _isString(obj) (PyString_CheckExact(obj) || \ PyUnicode_CheckExact(obj) || \ PyObject_TypeCheck(obj, &PyBaseString_Type)) #else #define _isString(obj) (PyUnicode_Check(obj) || PyBytes_Check(obj)) #endif #define _isElement(c_node) \ (((c_node)->type == XML_ELEMENT_NODE) || \ ((c_node)->type == XML_COMMENT_NODE) || \ ((c_node)->type == XML_ENTITY_REF_NODE) || \ ((c_node)->type == XML_PI_NODE)) #define _isElementOrXInclude(c_node) \ (_isElement(c_node) || \ ((c_node)->type == XML_XINCLUDE_START) || \ ((c_node)->type == XML_XINCLUDE_END)) #define _getNs(c_node) \ (((c_node)->ns == 0) ? 0 : ((c_node)->ns->href)) /* Macro pair implementation of a depth first tree walker * * Calls the code block between the BEGIN and END macros for all elements * below c_tree_top (exclusively), starting at c_node (inclusively iff * 'inclusive' is 1). The _ELEMENT_ variants will only stop on nodes * that match _isElement(), the normal variant will stop on every node * except text nodes. * * To traverse the node and all of its children and siblings in Pyrex, call * cdef xmlNode* some_node * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 1) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * To traverse only the children and siblings of a node, call * cdef xmlNode* some_node * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 0) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * To traverse only the children, do: * cdef xmlNode* some_node * some_node = parent_node.children * BEGIN_FOR_EACH_ELEMENT_FROM(parent_node, some_node, 1) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * NOTE: 'some_node' MUST be a plain 'xmlNode*' ! * * NOTE: parent modification during the walk can divert the iterator, but * should not segfault ! */ #define _LX__ELEMENT_MATCH(c_node, only_elements) \ ((only_elements) ? (_isElement(c_node)) : 1) #define _LX__ADVANCE_TO_NEXT(c_node, only_elements) \ while ((c_node != 0) && (!_LX__ELEMENT_MATCH(c_node, only_elements))) \ c_node = c_node->next; #define _LX__TRAVERSE_TO_NEXT(c_stop_node, c_node, only_elements) \ { \ /* walk through children first */ \ xmlNode* _lx__next = c_node->children; \ if (_lx__next != 0) { \ if (c_node->type == XML_ENTITY_REF_NODE || c_node->type == XML_DTD_NODE) { \ _lx__next = 0; \ } else { \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ } \ } \ if ((_lx__next == 0) && (c_node != c_stop_node)) { \ /* try siblings */ \ _lx__next = c_node->next; \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ /* back off through parents */ \ while (_lx__next == 0) { \ c_node = c_node->parent; \ if (c_node == 0) \ break; \ if (c_node == c_stop_node) \ break; \ if ((only_elements) && !_isElement(c_node)) \ break; \ /* we already traversed the parents -> siblings */ \ _lx__next = c_node->next; \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ } \ } \ c_node = _lx__next; \ } #define _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, only_elements) \ { \ if (c_node != 0) { \ const xmlNode* _lx__tree_top = (c_tree_top); \ const int _lx__only_elements = (only_elements); \ /* make sure we start at an element */ \ if (!_LX__ELEMENT_MATCH(c_node, _lx__only_elements)) { \ /* we skip the node, so 'inclusive' is irrelevant */ \ if (c_node == _lx__tree_top) \ c_node = 0; /* nothing to traverse */ \ else { \ c_node = c_node->next; \ _LX__ADVANCE_TO_NEXT(c_node, _lx__only_elements) \ } \ } else if (! (inclusive)) { \ /* skip the first node */ \ _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \ } \ \ /* now run the user code on the elements we find */ \ while (c_node != 0) { \ /* here goes the code to be run for each element */ #define _LX__END_FOR_EACH_FROM(c_node) \ _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \ } \ } \ } #define BEGIN_FOR_EACH_ELEMENT_FROM(c_tree_top, c_node, inclusive) \ _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 1) #define END_FOR_EACH_ELEMENT_FROM(c_node) \ _LX__END_FOR_EACH_FROM(c_node) #define BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive) \ _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 0) #define END_FOR_EACH_FROM(c_node) \ _LX__END_FOR_EACH_FROM(c_node) #endif /* HAS_ETREE_DEFS_H */