#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)
#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

/* 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 isinstance(o,c) PyObject_IsInstance(o,c)
#define issubclass(c,csuper) PyObject_IsSubclass(c,csuper)
#define hasattr(o,a)    PyObject_HasAttr(o,a)
#define getattr(o,a)    PyObject_GetAttr(o,a)
#define callable(o)     PyCallable_Check(o)
#define str(o)          PyObject_Str(o)
#define repr(o)         PyObject_Repr(o)
#define iter(o)         PyObject_GetIter(o)
#define _cstr(s)        PyString_AS_STRING(s)

#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_PI_NODE))

#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).
 * 
 * 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 _ADVANCE_TO_NEXT_ELEMENT(c_node)             \
    while ((c_node != 0) && (!_isElement(c_node)))   \
        c_node = c_node->next;

#define _TRAVERSE_TO_NEXT_ELEMENT(c_stop_node, c_node)         \
{                                                              \
    /* walk through children first */                          \
    xmlNode* ___next = c_node->children;                       \
    _ADVANCE_TO_NEXT_ELEMENT(___next)                          \
    if ((___next == 0) && (c_node != c_stop_node)) {           \
        /* try siblings */                                     \
        ___next = c_node->next;                                \
        _ADVANCE_TO_NEXT_ELEMENT(___next)                      \
        /* back off through parents */                         \
        while (___next == 0) {                                 \
            c_node = c_node->parent;                           \
            if (c_node == 0)                                   \
                break;                                         \
            if (c_node == c_stop_node)                         \
                break;                                         \
            if (!_isElement(c_node))                           \
                break;                                         \
            /* we already traversed the parents -> siblings */ \
            ___next = c_node->next;                            \
            _ADVANCE_TO_NEXT_ELEMENT(___next)                  \
        }                                                      \
    }                                                          \
    c_node = ___next;                                          \
}

#define BEGIN_FOR_EACH_ELEMENT_FROM(c_tree_top, c_node, inclusive)    \
{                                                                     \
    if (c_node != 0) {                                                \
        const xmlNode* ___tree_top = (c_tree_top);                    \
        /* make sure we start at an element */                        \
        if (!_isElement(c_node)) {                                    \
            /* we skip the node, so 'inclusive' is irrelevant */      \
            if (c_node == ___tree_top)                                \
                c_node = 0; /* nothing to traverse */                 \
            else {                                                    \
                c_node = c_node->next;                                \
                _ADVANCE_TO_NEXT_ELEMENT(c_node)                      \
            }                                                         \
        } else if (! (inclusive)) {                                   \
            /* skip the first node */                                 \
            _TRAVERSE_TO_NEXT_ELEMENT(___tree_top, c_node)            \
        }                                                             \
                                                                      \
        /* 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 END_FOR_EACH_ELEMENT_FROM(c_node)                             \
            _TRAVERSE_TO_NEXT_ELEMENT(___tree_top, c_node)            \
        }                                                             \
    }                                                                 \
}


#endif /* HAS_ETREE_DEFS_H */


syntax highlighted by Code2HTML, v. 0.9.1