#ifndef HAS_ETREE_DEFS_H #define HAS_ETREE_DEFS_H /* v_arg functions */ #define va_int(ap) va_arg(ap, int) #define va_charptr(ap) va_arg(ap, char *) /* Py_ssize_t support was added in Python 2.5 */ #if PY_VERSION_HEX < 0x02050000 # ifndef PY_SSIZE_T_MAX /* patched Pyrex? */ typedef int Py_ssize_t; # define PY_SSIZE_T_MAX INT_MAX # define PY_SSIZE_T_MIN INT_MIN # define PyInt_FromSsize_t(z) PyInt_FromLong(z) # define PyInt_AsSsize_t(o) PyInt_AsLong(o) # endif #endif /* Threading can crash under Python <= 2.4.1 */ #if PY_VERSION_HEX < 0x02040200 # ifndef WITHOUT_THREADING # define WITHOUT_THREADING # endif #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 */ #include "libxml/xmlversion.h" #if LIBXML_VERSION < 20621 /* (X|HT)ML_PARSE_COMPACT were added in libxml2 2.6.21 */ # define XML_PARSE_COMPACT 0 # define HTML_PARSE_COMPACT 0 /* HTML_PARSE_RECOVER was added in libxml2 2.6.21 */ # define HTML_PARSE_RECOVER XML_PARSE_RECOVER #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 #else # define ENABLE_SCHEMATRON 0 # define XML_SCHEMATRON_OUT_QUIET 0 # define XML_SCHEMATRON_OUT_XML 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) #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 /* Redefinition of some Python builtins as C functions */ #define callable(o) PyCallable_Check(o) #define _cstr(s) PyString_AS_STRING(s) #define _fqtypename(o) (((PyTypeObject*)o)->ob_type->tp_name) #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__ */ static PyObject* __PY_NEW_GLOBAL_EMPTY_TUPLE = NULL; #define PY_NEW(T) \ (((PyTypeObject*)(T))->tp_new( \ (PyTypeObject*)(T), \ (unlikely_condition(__PY_NEW_GLOBAL_EMPTY_TUPLE == NULL) ? \ (__PY_NEW_GLOBAL_EMPTY_TUPLE = PyTuple_New(0)) : \ (__PY_NEW_GLOBAL_EMPTY_TUPLE)), \ NULL)) #define _isString(obj) PyObject_TypeCheck(obj, &PyBaseString_Type) #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)) : ((c_node)->type != XML_TEXT_NODE)) #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; \ _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 */