diff cos/python/Objects/object.c @ 27:7f74363f4c82

Added some files for the python port
author windel
date Tue, 27 Dec 2011 18:59:02 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/python/Objects/object.c	Tue Dec 27 18:59:02 2011 +0100
@@ -0,0 +1,1737 @@
+
+/* Generic object operations; and implementation of None */
+
+#include "Python.h"
+#include "frameobject.h"
+
+/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
+   These are used by the individual routines for object creation.
+   Do not call them otherwise, they do not initialize the object! */
+
+void
+Py_IncRef(PyObject *o)
+{
+    Py_XINCREF(o);
+}
+
+void
+Py_DecRef(PyObject *o)
+{
+    Py_XDECREF(o);
+}
+
+PyObject *
+PyObject_Init(PyObject *op, PyTypeObject *tp)
+{
+    if (op == NULL)
+        return PyErr_NoMemory();
+    /* Any changes should be reflected in PyObject_INIT (objimpl.h) */
+    Py_TYPE(op) = tp;
+    _Py_NewReference(op);
+    return op;
+}
+
+PyVarObject *
+PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
+{
+    if (op == NULL)
+        return (PyVarObject *) PyErr_NoMemory();
+    /* Any changes should be reflected in PyObject_INIT_VAR */
+    op->ob_size = size;
+    Py_TYPE(op) = tp;
+    _Py_NewReference((PyObject *)op);
+    return op;
+}
+
+PyObject *
+_PyObject_New(PyTypeObject *tp)
+{
+    PyObject *op;
+    op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
+    if (op == NULL)
+        return PyErr_NoMemory();
+    return PyObject_INIT(op, tp);
+}
+
+PyVarObject *
+_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
+{
+    PyVarObject *op;
+    const size_t size = _PyObject_VAR_SIZE(tp, nitems);
+    op = (PyVarObject *) PyObject_MALLOC(size);
+    if (op == NULL)
+        return (PyVarObject *)PyErr_NoMemory();
+    return PyObject_INIT_VAR(op, tp, nitems);
+}
+
+int
+PyObject_Print(PyObject *op, FILE *fp, int flags)
+{
+    int ret = 0;
+    if (PyErr_CheckSignals())
+        return -1;
+#ifdef USE_STACKCHECK
+    if (PyOS_CheckStack()) {
+        PyErr_SetString(PyExc_MemoryError, "stack overflow");
+        return -1;
+    }
+#endif
+    clearerr(fp); /* Clear any previous error condition */
+    if (op == NULL) {
+        Py_BEGIN_ALLOW_THREADS
+        fprintf(fp, "<nil>");
+        Py_END_ALLOW_THREADS
+    }
+    else {
+        if (op->ob_refcnt <= 0)
+            /* XXX(twouters) cast refcount to long until %zd is
+               universally available */
+            Py_BEGIN_ALLOW_THREADS
+            fprintf(fp, "<refcnt %ld at %p>",
+                (long)op->ob_refcnt, op);
+            Py_END_ALLOW_THREADS
+        else {
+            PyObject *s;
+            if (flags & Py_PRINT_RAW)
+                s = PyObject_Str(op);
+            else
+                s = PyObject_Repr(op);
+            if (s == NULL)
+                ret = -1;
+            else if (PyBytes_Check(s)) {
+                fwrite(PyBytes_AS_STRING(s), 1,
+                       PyBytes_GET_SIZE(s), fp);
+            }
+            else if (PyUnicode_Check(s)) {
+                PyObject *t;
+                t = PyUnicode_AsEncodedString(s, "utf-8", "backslashreplace");
+                if (t == NULL)
+                    ret = 0;
+                else {
+                    fwrite(PyBytes_AS_STRING(t), 1,
+                           PyBytes_GET_SIZE(t), fp);
+                    Py_DECREF(t);
+                }
+            }
+            else {
+                PyErr_Format(PyExc_TypeError,
+                             "str() or repr() returned '%.100s'",
+                             s->ob_type->tp_name);
+                ret = -1;
+            }
+            Py_XDECREF(s);
+        }
+    }
+    if (ret == 0) {
+        if (ferror(fp)) {
+            PyErr_SetFromErrno(PyExc_IOError);
+            clearerr(fp);
+            ret = -1;
+        }
+    }
+    return ret;
+}
+
+/* For debugging convenience.  Set a breakpoint here and call it from your DLL */
+void
+_Py_BreakPoint(void)
+{
+}
+
+
+/* For debugging convenience.  See Misc/gdbinit for some useful gdb hooks */
+void
+_PyObject_Dump(PyObject* op)
+{
+    if (op == NULL)
+        fprintf(stderr, "NULL\n");
+    else {
+#ifdef WITH_THREAD
+        PyGILState_STATE gil;
+#endif
+        fprintf(stderr, "object  : ");
+#ifdef WITH_THREAD
+        gil = PyGILState_Ensure();
+#endif
+        (void)PyObject_Print(op, stderr, 0);
+#ifdef WITH_THREAD
+        PyGILState_Release(gil);
+#endif
+        /* XXX(twouters) cast refcount to long until %zd is
+           universally available */
+        fprintf(stderr, "\n"
+            "type    : %s\n"
+            "refcount: %ld\n"
+            "address : %p\n",
+            Py_TYPE(op)==NULL ? "NULL" : Py_TYPE(op)->tp_name,
+            (long)op->ob_refcnt,
+            op);
+    }
+}
+
+PyObject *
+PyObject_Repr(PyObject *v)
+{
+    PyObject *res;
+    if (PyErr_CheckSignals())
+        return NULL;
+#ifdef USE_STACKCHECK
+    if (PyOS_CheckStack()) {
+        PyErr_SetString(PyExc_MemoryError, "stack overflow");
+        return NULL;
+    }
+#endif
+    if (v == NULL)
+        return PyUnicode_FromString("<NULL>");
+    if (Py_TYPE(v)->tp_repr == NULL)
+        return PyUnicode_FromFormat("<%s object at %p>",
+                                    v->ob_type->tp_name, v);
+    res = (*v->ob_type->tp_repr)(v);
+    if (res == NULL)
+        return NULL;
+    if (!PyUnicode_Check(res)) {
+        PyErr_Format(PyExc_TypeError,
+                     "__repr__ returned non-string (type %.200s)",
+                     res->ob_type->tp_name);
+        Py_DECREF(res);
+        return NULL;
+    }
+#ifndef Py_DEBUG
+    if (PyUnicode_READY(res) < 0)
+        return NULL;
+#endif
+    return res;
+}
+
+PyObject *
+PyObject_Str(PyObject *v)
+{
+    PyObject *res;
+    if (PyErr_CheckSignals())
+        return NULL;
+#ifdef USE_STACKCHECK
+    if (PyOS_CheckStack()) {
+        PyErr_SetString(PyExc_MemoryError, "stack overflow");
+        return NULL;
+    }
+#endif
+    if (v == NULL)
+        return PyUnicode_FromString("<NULL>");
+    if (PyUnicode_CheckExact(v)) {
+#ifndef Py_DEBUG
+        if (PyUnicode_READY(v) < 0)
+            return NULL;
+#endif
+        Py_INCREF(v);
+        return v;
+    }
+    if (Py_TYPE(v)->tp_str == NULL)
+        return PyObject_Repr(v);
+
+    /* It is possible for a type to have a tp_str representation that loops
+       infinitely. */
+    if (Py_EnterRecursiveCall(" while getting the str of an object"))
+        return NULL;
+    res = (*Py_TYPE(v)->tp_str)(v);
+    Py_LeaveRecursiveCall();
+    if (res == NULL)
+        return NULL;
+    if (!PyUnicode_Check(res)) {
+        PyErr_Format(PyExc_TypeError,
+                     "__str__ returned non-string (type %.200s)",
+                     Py_TYPE(res)->tp_name);
+        Py_DECREF(res);
+        return NULL;
+    }
+#ifndef Py_DEBUG
+    if (PyUnicode_READY(res) < 0)
+        return NULL;
+#endif
+    assert(_PyUnicode_CheckConsistency(res, 1));
+    return res;
+}
+
+PyObject *
+PyObject_ASCII(PyObject *v)
+{
+    PyObject *repr, *ascii, *res;
+
+    repr = PyObject_Repr(v);
+    if (repr == NULL)
+        return NULL;
+
+    /* repr is guaranteed to be a PyUnicode object by PyObject_Repr */
+    ascii = _PyUnicode_AsASCIIString(repr, "backslashreplace");
+    Py_DECREF(repr);
+    if (ascii == NULL)
+        return NULL;
+
+    res = PyUnicode_DecodeASCII(
+        PyBytes_AS_STRING(ascii),
+        PyBytes_GET_SIZE(ascii),
+        NULL);
+
+    Py_DECREF(ascii);
+    return res;
+}
+
+PyObject *
+PyObject_Bytes(PyObject *v)
+{
+    PyObject *result, *func;
+    static PyObject *bytesstring = NULL;
+
+    if (v == NULL)
+        return PyBytes_FromString("<NULL>");
+
+    if (PyBytes_CheckExact(v)) {
+        Py_INCREF(v);
+        return v;
+    }
+
+    func = _PyObject_LookupSpecial(v, "__bytes__", &bytesstring);
+    if (func != NULL) {
+        result = PyObject_CallFunctionObjArgs(func, NULL);
+        Py_DECREF(func);
+        if (result == NULL)
+            return NULL;
+        if (!PyBytes_Check(result)) {
+            PyErr_Format(PyExc_TypeError,
+                         "__bytes__ returned non-bytes (type %.200s)",
+                         Py_TYPE(result)->tp_name);
+            Py_DECREF(result);
+            return NULL;
+        }
+        return result;
+    }
+    else if (PyErr_Occurred())
+        return NULL;
+    return PyBytes_FromObject(v);
+}
+
+/* For Python 3.0.1 and later, the old three-way comparison has been
+   completely removed in favour of rich comparisons.  PyObject_Compare() and
+   PyObject_Cmp() are gone, and the builtin cmp function no longer exists.
+   The old tp_compare slot has been renamed to tp_reserved, and should no
+   longer be used.  Use tp_richcompare instead.
+
+   See (*) below for practical amendments.
+
+   tp_richcompare gets called with a first argument of the appropriate type
+   and a second object of an arbitrary type.  We never do any kind of
+   coercion.
+
+   The tp_richcompare slot should return an object, as follows:
+
+    NULL if an exception occurred
+    NotImplemented if the requested comparison is not implemented
+    any other false value if the requested comparison is false
+    any other true value if the requested comparison is true
+
+  The PyObject_RichCompare[Bool]() wrappers raise TypeError when they get
+  NotImplemented.
+
+  (*) Practical amendments:
+
+  - If rich comparison returns NotImplemented, == and != are decided by
+    comparing the object pointer (i.e. falling back to the base object
+    implementation).
+
+*/
+
+/* Map rich comparison operators to their swapped version, e.g. LT <--> GT */
+int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
+
+static char *opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
+
+/* Perform a rich comparison, raising TypeError when the requested comparison
+   operator is not supported. */
+static PyObject *
+do_richcompare(PyObject *v, PyObject *w, int op)
+{
+    richcmpfunc f;
+    PyObject *res;
+    int checked_reverse_op = 0;
+
+    if (v->ob_type != w->ob_type &&
+        PyType_IsSubtype(w->ob_type, v->ob_type) &&
+        (f = w->ob_type->tp_richcompare) != NULL) {
+        checked_reverse_op = 1;
+        res = (*f)(w, v, _Py_SwappedOp[op]);
+        if (res != Py_NotImplemented)
+            return res;
+        Py_DECREF(res);
+    }
+    if ((f = v->ob_type->tp_richcompare) != NULL) {
+        res = (*f)(v, w, op);
+        if (res != Py_NotImplemented)
+            return res;
+        Py_DECREF(res);
+    }
+    if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {
+        res = (*f)(w, v, _Py_SwappedOp[op]);
+        if (res != Py_NotImplemented)
+            return res;
+        Py_DECREF(res);
+    }
+    /* If neither object implements it, provide a sensible default
+       for == and !=, but raise an exception for ordering. */
+    switch (op) {
+    case Py_EQ:
+        res = (v == w) ? Py_True : Py_False;
+        break;
+    case Py_NE:
+        res = (v != w) ? Py_True : Py_False;
+        break;
+    default:
+        /* XXX Special-case None so it doesn't show as NoneType() */
+        PyErr_Format(PyExc_TypeError,
+                     "unorderable types: %.100s() %s %.100s()",
+                     v->ob_type->tp_name,
+                     opstrings[op],
+                     w->ob_type->tp_name);
+        return NULL;
+    }
+    Py_INCREF(res);
+    return res;
+}
+
+/* Perform a rich comparison with object result.  This wraps do_richcompare()
+   with a check for NULL arguments and a recursion check. */
+
+PyObject *
+PyObject_RichCompare(PyObject *v, PyObject *w, int op)
+{
+    PyObject *res;
+
+    assert(Py_LT <= op && op <= Py_GE);
+    if (v == NULL || w == NULL) {
+        if (!PyErr_Occurred())
+            PyErr_BadInternalCall();
+        return NULL;
+    }
+    if (Py_EnterRecursiveCall(" in comparison"))
+        return NULL;
+    res = do_richcompare(v, w, op);
+    Py_LeaveRecursiveCall();
+    return res;
+}
+
+/* Perform a rich comparison with integer result.  This wraps
+   PyObject_RichCompare(), returning -1 for error, 0 for false, 1 for true. */
+int
+PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
+{
+    PyObject *res;
+    int ok;
+
+    /* Quick result when objects are the same.
+       Guarantees that identity implies equality. */
+    if (v == w) {
+        if (op == Py_EQ)
+            return 1;
+        else if (op == Py_NE)
+            return 0;
+    }
+
+    res = PyObject_RichCompare(v, w, op);
+    if (res == NULL)
+        return -1;
+    if (PyBool_Check(res))
+        ok = (res == Py_True);
+    else
+        ok = PyObject_IsTrue(res);
+    Py_DECREF(res);
+    return ok;
+}
+
+/* Set of hash utility functions to help maintaining the invariant that
+    if a==b then hash(a)==hash(b)
+
+   All the utility functions (_Py_Hash*()) return "-1" to signify an error.
+*/
+
+/* For numeric types, the hash of a number x is based on the reduction
+   of x modulo the prime P = 2**_PyHASH_BITS - 1.  It's designed so that
+   hash(x) == hash(y) whenever x and y are numerically equal, even if
+   x and y have different types.
+
+   A quick summary of the hashing strategy:
+
+   (1) First define the 'reduction of x modulo P' for any rational
+   number x; this is a standard extension of the usual notion of
+   reduction modulo P for integers.  If x == p/q (written in lowest
+   terms), the reduction is interpreted as the reduction of p times
+   the inverse of the reduction of q, all modulo P; if q is exactly
+   divisible by P then define the reduction to be infinity.  So we've
+   got a well-defined map
+
+      reduce : { rational numbers } -> { 0, 1, 2, ..., P-1, infinity }.
+
+   (2) Now for a rational number x, define hash(x) by:
+
+      reduce(x)   if x >= 0
+      -reduce(-x) if x < 0
+
+   If the result of the reduction is infinity (this is impossible for
+   integers, floats and Decimals) then use the predefined hash value
+   _PyHASH_INF for x >= 0, or -_PyHASH_INF for x < 0, instead.
+   _PyHASH_INF, -_PyHASH_INF and _PyHASH_NAN are also used for the
+   hashes of float and Decimal infinities and nans.
+
+   A selling point for the above strategy is that it makes it possible
+   to compute hashes of decimal and binary floating-point numbers
+   efficiently, even if the exponent of the binary or decimal number
+   is large.  The key point is that
+
+      reduce(x * y) == reduce(x) * reduce(y) (modulo _PyHASH_MODULUS)
+
+   provided that {reduce(x), reduce(y)} != {0, infinity}.  The reduction of a
+   binary or decimal float is never infinity, since the denominator is a power
+   of 2 (for binary) or a divisor of a power of 10 (for decimal).  So we have,
+   for nonnegative x,
+
+      reduce(x * 2**e) == reduce(x) * reduce(2**e) % _PyHASH_MODULUS
+
+      reduce(x * 10**e) == reduce(x) * reduce(10**e) % _PyHASH_MODULUS
+
+   and reduce(10**e) can be computed efficiently by the usual modular
+   exponentiation algorithm.  For reduce(2**e) it's even better: since
+   P is of the form 2**n-1, reduce(2**e) is 2**(e mod n), and multiplication
+   by 2**(e mod n) modulo 2**n-1 just amounts to a rotation of bits.
+
+   */
+
+Py_hash_t
+_Py_HashDouble(double v)
+{
+    int e, sign;
+    double m;
+    Py_uhash_t x, y;
+
+    if (!Py_IS_FINITE(v)) {
+        if (Py_IS_INFINITY(v))
+            return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
+        else
+            return _PyHASH_NAN;
+    }
+
+    m = frexp(v, &e);
+
+    sign = 1;
+    if (m < 0) {
+        sign = -1;
+        m = -m;
+    }
+
+    /* process 28 bits at a time;  this should work well both for binary
+       and hexadecimal floating point. */
+    x = 0;
+    while (m) {
+        x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28);
+        m *= 268435456.0;  /* 2**28 */
+        e -= 28;
+        y = (Py_uhash_t)m;  /* pull out integer part */
+        m -= y;
+        x += y;
+        if (x >= _PyHASH_MODULUS)
+            x -= _PyHASH_MODULUS;
+    }
+
+    /* adjust for the exponent;  first reduce it modulo _PyHASH_BITS */
+    e = e >= 0 ? e % _PyHASH_BITS : _PyHASH_BITS-1-((-1-e) % _PyHASH_BITS);
+    x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e);
+
+    x = x * sign;
+    if (x == (Py_uhash_t)-1)
+        x = (Py_uhash_t)-2;
+    return (Py_hash_t)x;
+}
+
+Py_hash_t
+_Py_HashPointer(void *p)
+{
+    Py_hash_t x;
+    size_t y = (size_t)p;
+    /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
+       excessive hash collisions for dicts and sets */
+    y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));
+    x = (Py_hash_t)y;
+    if (x == -1)
+        x = -2;
+    return x;
+}
+
+Py_hash_t
+_Py_HashBytes(unsigned char *p, Py_ssize_t len)
+{
+    Py_uhash_t x;
+    Py_ssize_t i;
+
+    x = (Py_uhash_t) *p << 7;
+    for (i = 0; i < len; i++)
+        x = (1000003U * x) ^ (Py_uhash_t) *p++;
+    x ^= (Py_uhash_t) len;
+    if (x == -1)
+        x = -2;
+    return x;
+}
+
+Py_hash_t
+PyObject_HashNotImplemented(PyObject *v)
+{
+    PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
+                 Py_TYPE(v)->tp_name);
+    return -1;
+}
+
+Py_hash_t
+PyObject_Hash(PyObject *v)
+{
+    PyTypeObject *tp = Py_TYPE(v);
+    if (tp->tp_hash != NULL)
+        return (*tp->tp_hash)(v);
+    /* To keep to the general practice that inheriting
+     * solely from object in C code should work without
+     * an explicit call to PyType_Ready, we implicitly call
+     * PyType_Ready here and then check the tp_hash slot again
+     */
+    if (tp->tp_dict == NULL) {
+        if (PyType_Ready(tp) < 0)
+            return -1;
+        if (tp->tp_hash != NULL)
+            return (*tp->tp_hash)(v);
+    }
+    /* Otherwise, the object can't be hashed */
+    return PyObject_HashNotImplemented(v);
+}
+
+PyObject *
+PyObject_GetAttrString(PyObject *v, const char *name)
+{
+    PyObject *w, *res;
+
+    if (Py_TYPE(v)->tp_getattr != NULL)
+        return (*Py_TYPE(v)->tp_getattr)(v, (char*)name);
+    w = PyUnicode_InternFromString(name);
+    if (w == NULL)
+        return NULL;
+    res = PyObject_GetAttr(v, w);
+    Py_XDECREF(w);
+    return res;
+}
+
+int
+PyObject_HasAttrString(PyObject *v, const char *name)
+{
+    PyObject *res = PyObject_GetAttrString(v, name);
+    if (res != NULL) {
+        Py_DECREF(res);
+        return 1;
+    }
+    PyErr_Clear();
+    return 0;
+}
+
+int
+PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
+{
+    PyObject *s;
+    int res;
+
+    if (Py_TYPE(v)->tp_setattr != NULL)
+        return (*Py_TYPE(v)->tp_setattr)(v, (char*)name, w);
+    s = PyUnicode_InternFromString(name);
+    if (s == NULL)
+        return -1;
+    res = PyObject_SetAttr(v, s, w);
+    Py_XDECREF(s);
+    return res;
+}
+
+int
+_PyObject_IsAbstract(PyObject *obj)
+{
+    int res;
+    PyObject* isabstract;
+    _Py_IDENTIFIER(__isabstractmethod__);
+
+    if (obj == NULL)
+        return 0;
+
+    isabstract = _PyObject_GetAttrId(obj, &PyId___isabstractmethod__);
+    if (isabstract == NULL) {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+            PyErr_Clear();
+            return 0;
+        }
+        return -1;
+    }
+    res = PyObject_IsTrue(isabstract);
+    Py_DECREF(isabstract);
+    return res;
+}
+
+PyObject *
+_PyObject_GetAttrId(PyObject *v, _Py_Identifier *name)
+{
+    PyObject *result;
+    PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
+    if (!oname)
+        return NULL;
+    result = PyObject_GetAttr(v, oname);
+    return result;
+}
+
+int
+_PyObject_HasAttrId(PyObject *v, _Py_Identifier *name)
+{
+    int result;
+    PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
+    if (!oname)
+        return -1;
+    result = PyObject_HasAttr(v, oname);
+    return result;
+}
+
+int
+_PyObject_SetAttrId(PyObject *v, _Py_Identifier *name, PyObject *w)
+{
+    int result;
+    PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
+    if (!oname)
+        return -1;
+    result = PyObject_SetAttr(v, oname, w);
+    return result;
+}
+
+PyObject *
+PyObject_GetAttr(PyObject *v, PyObject *name)
+{
+    PyTypeObject *tp = Py_TYPE(v);
+
+    if (!PyUnicode_Check(name)) {
+        PyErr_Format(PyExc_TypeError,
+                     "attribute name must be string, not '%.200s'",
+                     name->ob_type->tp_name);
+        return NULL;
+    }
+    if (tp->tp_getattro != NULL)
+        return (*tp->tp_getattro)(v, name);
+    if (tp->tp_getattr != NULL) {
+        char *name_str = _PyUnicode_AsString(name);
+        if (name_str == NULL)
+            return NULL;
+        return (*tp->tp_getattr)(v, name_str);
+    }
+    PyErr_Format(PyExc_AttributeError,
+                 "'%.50s' object has no attribute '%U'",
+                 tp->tp_name, name);
+    return NULL;
+}
+
+int
+PyObject_HasAttr(PyObject *v, PyObject *name)
+{
+    PyObject *res = PyObject_GetAttr(v, name);
+    if (res != NULL) {
+        Py_DECREF(res);
+        return 1;
+    }
+    PyErr_Clear();
+    return 0;
+}
+
+int
+PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
+{
+    PyTypeObject *tp = Py_TYPE(v);
+    int err;
+
+    if (!PyUnicode_Check(name)) {
+        PyErr_Format(PyExc_TypeError,
+                     "attribute name must be string, not '%.200s'",
+                     name->ob_type->tp_name);
+        return -1;
+    }
+    Py_INCREF(name);
+
+    PyUnicode_InternInPlace(&name);
+    if (tp->tp_setattro != NULL) {
+        err = (*tp->tp_setattro)(v, name, value);
+        Py_DECREF(name);
+        return err;
+    }
+    if (tp->tp_setattr != NULL) {
+        char *name_str = _PyUnicode_AsString(name);
+        if (name_str == NULL)
+            return -1;
+        err = (*tp->tp_setattr)(v, name_str, value);
+        Py_DECREF(name);
+        return err;
+    }
+    Py_DECREF(name);
+    assert(name->ob_refcnt >= 1);
+    if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
+        PyErr_Format(PyExc_TypeError,
+                     "'%.100s' object has no attributes "
+                     "(%s .%U)",
+                     tp->tp_name,
+                     value==NULL ? "del" : "assign to",
+                     name);
+    else
+        PyErr_Format(PyExc_TypeError,
+                     "'%.100s' object has only read-only attributes "
+                     "(%s .%U)",
+                     tp->tp_name,
+                     value==NULL ? "del" : "assign to",
+                     name);
+    return -1;
+}
+
+/* Helper to get a pointer to an object's __dict__ slot, if any */
+
+PyObject **
+_PyObject_GetDictPtr(PyObject *obj)
+{
+    Py_ssize_t dictoffset;
+    PyTypeObject *tp = Py_TYPE(obj);
+
+    dictoffset = tp->tp_dictoffset;
+    if (dictoffset == 0)
+        return NULL;
+    if (dictoffset < 0) {
+        Py_ssize_t tsize;
+        size_t size;
+
+        tsize = ((PyVarObject *)obj)->ob_size;
+        if (tsize < 0)
+            tsize = -tsize;
+        size = _PyObject_VAR_SIZE(tp, tsize);
+
+        dictoffset += (long)size;
+        assert(dictoffset > 0);
+        assert(dictoffset % SIZEOF_VOID_P == 0);
+    }
+    return (PyObject **) ((char *)obj + dictoffset);
+}
+
+PyObject *
+PyObject_SelfIter(PyObject *obj)
+{
+    Py_INCREF(obj);
+    return obj;
+}
+
+/* Helper used when the __next__ method is removed from a type:
+   tp_iternext is never NULL and can be safely called without checking
+   on every iteration.
+ */
+
+PyObject *
+_PyObject_NextNotImplemented(PyObject *self)
+{
+    PyErr_Format(PyExc_TypeError,
+                 "'%.200s' object is not iterable",
+                 Py_TYPE(self)->tp_name);
+    return NULL;
+}
+
+/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
+
+PyObject *
+_PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
+{
+    PyTypeObject *tp = Py_TYPE(obj);
+    PyObject *descr = NULL;
+    PyObject *res = NULL;
+    descrgetfunc f;
+    Py_ssize_t dictoffset;
+    PyObject **dictptr;
+
+    if (!PyUnicode_Check(name)){
+        PyErr_Format(PyExc_TypeError,
+                     "attribute name must be string, not '%.200s'",
+                     name->ob_type->tp_name);
+        return NULL;
+    }
+    else
+        Py_INCREF(name);
+
+    if (tp->tp_dict == NULL) {
+        if (PyType_Ready(tp) < 0)
+            goto done;
+    }
+
+    descr = _PyType_Lookup(tp, name);
+    Py_XINCREF(descr);
+
+    f = NULL;
+    if (descr != NULL) {
+        f = descr->ob_type->tp_descr_get;
+        if (f != NULL && PyDescr_IsData(descr)) {
+            res = f(descr, obj, (PyObject *)obj->ob_type);
+            Py_DECREF(descr);
+            goto done;
+        }
+    }
+
+    if (dict == NULL) {
+        /* Inline _PyObject_GetDictPtr */
+        dictoffset = tp->tp_dictoffset;
+        if (dictoffset != 0) {
+            if (dictoffset < 0) {
+                Py_ssize_t tsize;
+                size_t size;
+
+                tsize = ((PyVarObject *)obj)->ob_size;
+                if (tsize < 0)
+                    tsize = -tsize;
+                size = _PyObject_VAR_SIZE(tp, tsize);
+
+                dictoffset += (long)size;
+                assert(dictoffset > 0);
+                assert(dictoffset % SIZEOF_VOID_P == 0);
+            }
+            dictptr = (PyObject **) ((char *)obj + dictoffset);
+            dict = *dictptr;
+        }
+    }
+    if (dict != NULL) {
+        Py_INCREF(dict);
+        res = PyDict_GetItem(dict, name);
+        if (res != NULL) {
+            Py_INCREF(res);
+            Py_XDECREF(descr);
+            Py_DECREF(dict);
+            goto done;
+        }
+        Py_DECREF(dict);
+    }
+
+    if (f != NULL) {
+        res = f(descr, obj, (PyObject *)Py_TYPE(obj));
+        Py_DECREF(descr);
+        goto done;
+    }
+
+    if (descr != NULL) {
+        res = descr;
+        /* descr was already increfed above */
+        goto done;
+    }
+
+    PyErr_Format(PyExc_AttributeError,
+                 "'%.50s' object has no attribute '%U'",
+                 tp->tp_name, name);
+  done:
+    Py_DECREF(name);
+    return res;
+}
+
+PyObject *
+PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
+{
+    return _PyObject_GenericGetAttrWithDict(obj, name, NULL);
+}
+
+int
+_PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
+                                 PyObject *value, PyObject *dict)
+{
+    PyTypeObject *tp = Py_TYPE(obj);
+    PyObject *descr;
+    descrsetfunc f;
+    PyObject **dictptr;
+    int res = -1;
+
+    if (!PyUnicode_Check(name)){
+        PyErr_Format(PyExc_TypeError,
+                     "attribute name must be string, not '%.200s'",
+                     name->ob_type->tp_name);
+        return -1;
+    }
+    else
+        Py_INCREF(name);
+
+    if (tp->tp_dict == NULL) {
+        if (PyType_Ready(tp) < 0)
+            goto done;
+    }
+
+    descr = _PyType_Lookup(tp, name);
+    f = NULL;
+    if (descr != NULL) {
+        f = descr->ob_type->tp_descr_set;
+        if (f != NULL && PyDescr_IsData(descr)) {
+            res = f(descr, obj, value);
+            goto done;
+        }
+    }
+
+    if (dict == NULL) {
+        dictptr = _PyObject_GetDictPtr(obj);
+        if (dictptr != NULL) {
+            dict = *dictptr;
+            if (dict == NULL && value != NULL) {
+                dict = PyDict_New();
+                if (dict == NULL)
+                    goto done;
+                *dictptr = dict;
+            }
+        }
+    }
+    if (dict != NULL) {
+        Py_INCREF(dict);
+        if (value == NULL)
+            res = PyDict_DelItem(dict, name);
+        else
+            res = PyDict_SetItem(dict, name, value);
+        if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
+            PyErr_SetObject(PyExc_AttributeError, name);
+        Py_DECREF(dict);
+        goto done;
+    }
+
+    if (f != NULL) {
+        res = f(descr, obj, value);
+        goto done;
+    }
+
+    if (descr == NULL) {
+        PyErr_Format(PyExc_AttributeError,
+                     "'%.100s' object has no attribute '%U'",
+                     tp->tp_name, name);
+        goto done;
+    }
+
+    PyErr_Format(PyExc_AttributeError,
+                 "'%.50s' object attribute '%U' is read-only",
+                 tp->tp_name, name);
+  done:
+    Py_DECREF(name);
+    return res;
+}
+
+int
+PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
+{
+    return _PyObject_GenericSetAttrWithDict(obj, name, value, NULL);
+}
+
+
+/* Test a value used as condition, e.g., in a for or if statement.
+   Return -1 if an error occurred */
+
+int
+PyObject_IsTrue(PyObject *v)
+{
+    Py_ssize_t res;
+    if (v == Py_True)
+        return 1;
+    if (v == Py_False)
+        return 0;
+    if (v == Py_None)
+        return 0;
+    else if (v->ob_type->tp_as_number != NULL &&
+             v->ob_type->tp_as_number->nb_bool != NULL)
+        res = (*v->ob_type->tp_as_number->nb_bool)(v);
+    else if (v->ob_type->tp_as_mapping != NULL &&
+             v->ob_type->tp_as_mapping->mp_length != NULL)
+        res = (*v->ob_type->tp_as_mapping->mp_length)(v);
+    else if (v->ob_type->tp_as_sequence != NULL &&
+             v->ob_type->tp_as_sequence->sq_length != NULL)
+        res = (*v->ob_type->tp_as_sequence->sq_length)(v);
+    else
+        return 1;
+    /* if it is negative, it should be either -1 or -2 */
+    return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
+}
+
+/* equivalent of 'not v'
+   Return -1 if an error occurred */
+
+int
+PyObject_Not(PyObject *v)
+{
+    int res;
+    res = PyObject_IsTrue(v);
+    if (res < 0)
+        return res;
+    return res == 0;
+}
+
+/* Test whether an object can be called */
+
+int
+PyCallable_Check(PyObject *x)
+{
+    if (x == NULL)
+        return 0;
+    return x->ob_type->tp_call != NULL;
+}
+
+
+/* Helper for PyObject_Dir without arguments: returns the local scope. */
+static PyObject *
+_dir_locals(void)
+{
+    PyObject *names;
+    PyObject *locals = PyEval_GetLocals();
+
+    if (locals == NULL) {
+        PyErr_SetString(PyExc_SystemError, "frame does not exist");
+        return NULL;
+    }
+
+    names = PyMapping_Keys(locals);
+    if (!names)
+        return NULL;
+    if (!PyList_Check(names)) {
+        PyErr_Format(PyExc_TypeError,
+            "dir(): expected keys() of locals to be a list, "
+            "not '%.200s'", Py_TYPE(names)->tp_name);
+        Py_DECREF(names);
+        return NULL;
+    }
+    if (PyList_Sort(names)) {
+        Py_DECREF(names);
+        return NULL;
+    }
+    /* the locals don't need to be DECREF'd */
+    return names;
+}
+
+/* Helper for PyObject_Dir: object introspection. */
+static PyObject *
+_dir_object(PyObject *obj)
+{
+    PyObject *result, *sorted;
+    static PyObject *dir_str = NULL;
+    PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str);
+
+    assert(obj);
+    if (dirfunc == NULL) {
+        if (!PyErr_Occurred())
+            PyErr_SetString(PyExc_TypeError, "object does not provide __dir__");
+        return NULL;
+    }
+    /* use __dir__ */
+    result = PyObject_CallFunctionObjArgs(dirfunc, NULL);
+    Py_DECREF(dirfunc);
+    if (result == NULL)
+        return NULL;
+    /* return sorted(result) */
+    sorted = PySequence_List(result);
+    Py_DECREF(result);
+    if (sorted == NULL)
+        return NULL;
+    if (PyList_Sort(sorted)) {
+        Py_DECREF(sorted);
+        return NULL;
+    }
+    return sorted;
+}
+
+/* Implementation of dir() -- if obj is NULL, returns the names in the current
+   (local) scope.  Otherwise, performs introspection of the object: returns a
+   sorted list of attribute names (supposedly) accessible from the object
+*/
+PyObject *
+PyObject_Dir(PyObject *obj)
+{
+    return (obj == NULL) ? _dir_locals() : _dir_object(obj);
+}
+
+/*
+None is a non-NULL undefined value.
+There is (and should be!) no way to create other objects of this type,
+so there is exactly one (which is indestructible, by the way).
+*/
+
+/* ARGSUSED */
+static PyObject *
+none_repr(PyObject *op)
+{
+    return PyUnicode_FromString("None");
+}
+
+/* ARGUSED */
+static void
+none_dealloc(PyObject* ignore)
+{
+    /* This should never get called, but we also don't want to SEGV if
+     * we accidentally decref None out of existence.
+     */
+    Py_FatalError("deallocating None");
+}
+
+static PyObject *
+none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
+        PyErr_SetString(PyExc_TypeError, "NoneType takes no arguments");
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+static int
+none_bool(PyObject *v)
+{
+    return 0;
+}
+
+static PyNumberMethods none_as_number = {
+    0,                          /* nb_add */
+    0,                          /* nb_subtract */
+    0,                          /* nb_multiply */
+    0,                          /* nb_remainder */
+    0,                          /* nb_divmod */
+    0,                          /* nb_power */
+    0,                          /* nb_negative */
+    0,                          /* nb_positive */
+    0,                          /* nb_absolute */
+    (inquiry)none_bool,         /* nb_bool */
+    0,                          /* nb_invert */
+    0,                          /* nb_lshift */
+    0,                          /* nb_rshift */
+    0,                          /* nb_and */
+    0,                          /* nb_xor */
+    0,                          /* nb_or */
+    0,                          /* nb_int */
+    0,                          /* nb_reserved */
+    0,                          /* nb_float */
+    0,                          /* nb_inplace_add */
+    0,                          /* nb_inplace_subtract */
+    0,                          /* nb_inplace_multiply */
+    0,                          /* nb_inplace_remainder */
+    0,                          /* nb_inplace_power */
+    0,                          /* nb_inplace_lshift */
+    0,                          /* nb_inplace_rshift */
+    0,                          /* nb_inplace_and */
+    0,                          /* nb_inplace_xor */
+    0,                          /* nb_inplace_or */
+    0,                          /* nb_floor_divide */
+    0,                          /* nb_true_divide */
+    0,                          /* nb_inplace_floor_divide */
+    0,                          /* nb_inplace_true_divide */
+    0,                          /* nb_index */
+};
+
+static PyTypeObject PyNone_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "NoneType",
+    0,
+    0,
+    none_dealloc,       /*tp_dealloc*/ /*never called*/
+    0,                  /*tp_print*/
+    0,                  /*tp_getattr*/
+    0,                  /*tp_setattr*/
+    0,                  /*tp_reserved*/
+    none_repr,          /*tp_repr*/
+    &none_as_number,    /*tp_as_number*/
+    0,                  /*tp_as_sequence*/
+    0,                  /*tp_as_mapping*/
+    0,                  /*tp_hash */
+    0,                  /*tp_call */
+    0,                  /*tp_str */
+    0,                  /*tp_getattro */
+    0,                  /*tp_setattro */
+    0,                  /*tp_as_buffer */
+    Py_TPFLAGS_DEFAULT, /*tp_flags */
+    0,                  /*tp_doc */
+    0,                  /*tp_traverse */
+    0,                  /*tp_clear */
+    0,                  /*tp_richcompare */
+    0,                  /*tp_weaklistoffset */
+    0,                  /*tp_iter */
+    0,                  /*tp_iternext */
+    0,                  /*tp_methods */
+    0,                  /*tp_members */
+    0,                  /*tp_getset */
+    0,                  /*tp_base */
+    0,                  /*tp_dict */
+    0,                  /*tp_descr_get */
+    0,                  /*tp_descr_set */
+    0,                  /*tp_dictoffset */
+    0,                  /*tp_init */
+    0,                  /*tp_alloc */
+    none_new,           /*tp_new */
+};
+
+PyObject _Py_NoneStruct = {
+  _PyObject_EXTRA_INIT
+  1, &PyNone_Type
+};
+
+/* NotImplemented is an object that can be used to signal that an
+   operation is not implemented for the given type combination. */
+
+static PyObject *
+NotImplemented_repr(PyObject *op)
+{
+    return PyUnicode_FromString("NotImplemented");
+}
+
+static PyObject *
+notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
+        PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments");
+        return NULL;
+    }
+    Py_RETURN_NOTIMPLEMENTED;
+}
+
+static PyTypeObject PyNotImplemented_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "NotImplementedType",
+    0,
+    0,
+    none_dealloc,       /*tp_dealloc*/ /*never called*/
+    0,                  /*tp_print*/
+    0,                  /*tp_getattr*/
+    0,                  /*tp_setattr*/
+    0,                  /*tp_reserved*/
+    NotImplemented_repr, /*tp_repr*/
+    0,                  /*tp_as_number*/
+    0,                  /*tp_as_sequence*/
+    0,                  /*tp_as_mapping*/
+    0,                  /*tp_hash */
+    0,                  /*tp_call */
+    0,                  /*tp_str */
+    0,                  /*tp_getattro */
+    0,                  /*tp_setattro */
+    0,                  /*tp_as_buffer */
+    Py_TPFLAGS_DEFAULT, /*tp_flags */
+    0,                  /*tp_doc */
+    0,                  /*tp_traverse */
+    0,                  /*tp_clear */
+    0,                  /*tp_richcompare */
+    0,                  /*tp_weaklistoffset */
+    0,                  /*tp_iter */
+    0,                  /*tp_iternext */
+    0,                  /*tp_methods */
+    0,                  /*tp_members */
+    0,                  /*tp_getset */
+    0,                  /*tp_base */
+    0,                  /*tp_dict */
+    0,                  /*tp_descr_get */
+    0,                  /*tp_descr_set */
+    0,                  /*tp_dictoffset */
+    0,                  /*tp_init */
+    0,                  /*tp_alloc */
+    notimplemented_new, /*tp_new */
+};
+
+PyObject _Py_NotImplementedStruct = {
+    _PyObject_EXTRA_INIT
+    1, &PyNotImplemented_Type
+};
+
+void
+_Py_ReadyTypes(void)
+{
+    if (PyType_Ready(&PyType_Type) < 0)
+        Py_FatalError("Can't initialize type type");
+
+    if (PyType_Ready(&_PyWeakref_RefType) < 0)
+        Py_FatalError("Can't initialize weakref type");
+
+    if (PyType_Ready(&_PyWeakref_CallableProxyType) < 0)
+        Py_FatalError("Can't initialize callable weakref proxy type");
+
+    if (PyType_Ready(&_PyWeakref_ProxyType) < 0)
+        Py_FatalError("Can't initialize weakref proxy type");
+
+    if (PyType_Ready(&PyBool_Type) < 0)
+        Py_FatalError("Can't initialize bool type");
+
+    if (PyType_Ready(&PyByteArray_Type) < 0)
+        Py_FatalError("Can't initialize bytearray type");
+
+    if (PyType_Ready(&PyBytes_Type) < 0)
+        Py_FatalError("Can't initialize 'str'");
+
+    if (PyType_Ready(&PyList_Type) < 0)
+        Py_FatalError("Can't initialize list type");
+
+    if (PyType_Ready(&PyNone_Type) < 0)
+        Py_FatalError("Can't initialize None type");
+
+    if (PyType_Ready(&PyNotImplemented_Type) < 0)
+        Py_FatalError("Can't initialize NotImplemented type");
+
+    if (PyType_Ready(&PyTraceBack_Type) < 0)
+        Py_FatalError("Can't initialize traceback type");
+
+    if (PyType_Ready(&PySuper_Type) < 0)
+        Py_FatalError("Can't initialize super type");
+
+    if (PyType_Ready(&PyBaseObject_Type) < 0)
+        Py_FatalError("Can't initialize object type");
+
+    if (PyType_Ready(&PyRange_Type) < 0)
+        Py_FatalError("Can't initialize range type");
+
+    if (PyType_Ready(&PyDict_Type) < 0)
+        Py_FatalError("Can't initialize dict type");
+
+    if (PyType_Ready(&PySet_Type) < 0)
+        Py_FatalError("Can't initialize set type");
+
+    if (PyType_Ready(&PyUnicode_Type) < 0)
+        Py_FatalError("Can't initialize str type");
+
+    if (PyType_Ready(&PySlice_Type) < 0)
+        Py_FatalError("Can't initialize slice type");
+
+    if (PyType_Ready(&PyStaticMethod_Type) < 0)
+        Py_FatalError("Can't initialize static method type");
+
+    if (PyType_Ready(&PyComplex_Type) < 0)
+        Py_FatalError("Can't initialize complex type");
+
+    if (PyType_Ready(&PyFloat_Type) < 0)
+        Py_FatalError("Can't initialize float type");
+
+    if (PyType_Ready(&PyLong_Type) < 0)
+        Py_FatalError("Can't initialize int type");
+
+    if (PyType_Ready(&PyFrozenSet_Type) < 0)
+        Py_FatalError("Can't initialize frozenset type");
+
+    if (PyType_Ready(&PyProperty_Type) < 0)
+        Py_FatalError("Can't initialize property type");
+
+    if (PyType_Ready(&PyMemoryView_Type) < 0)
+        Py_FatalError("Can't initialize memoryview type");
+
+    if (PyType_Ready(&PyTuple_Type) < 0)
+        Py_FatalError("Can't initialize tuple type");
+
+    if (PyType_Ready(&PyEnum_Type) < 0)
+        Py_FatalError("Can't initialize enumerate type");
+
+    if (PyType_Ready(&PyReversed_Type) < 0)
+        Py_FatalError("Can't initialize reversed type");
+
+    if (PyType_Ready(&PyStdPrinter_Type) < 0)
+        Py_FatalError("Can't initialize StdPrinter");
+
+    if (PyType_Ready(&PyCode_Type) < 0)
+        Py_FatalError("Can't initialize code type");
+
+    if (PyType_Ready(&PyFrame_Type) < 0)
+        Py_FatalError("Can't initialize frame type");
+
+    if (PyType_Ready(&PyCFunction_Type) < 0)
+        Py_FatalError("Can't initialize builtin function type");
+
+    if (PyType_Ready(&PyMethod_Type) < 0)
+        Py_FatalError("Can't initialize method type");
+
+    if (PyType_Ready(&PyFunction_Type) < 0)
+        Py_FatalError("Can't initialize function type");
+
+    if (PyType_Ready(&PyDictProxy_Type) < 0)
+        Py_FatalError("Can't initialize dict proxy type");
+
+    if (PyType_Ready(&PyGen_Type) < 0)
+        Py_FatalError("Can't initialize generator type");
+
+    if (PyType_Ready(&PyGetSetDescr_Type) < 0)
+        Py_FatalError("Can't initialize get-set descriptor type");
+
+    if (PyType_Ready(&PyWrapperDescr_Type) < 0)
+        Py_FatalError("Can't initialize wrapper type");
+
+    if (PyType_Ready(&_PyMethodWrapper_Type) < 0)
+        Py_FatalError("Can't initialize method wrapper type");
+
+    if (PyType_Ready(&PyEllipsis_Type) < 0)
+        Py_FatalError("Can't initialize ellipsis type");
+
+    if (PyType_Ready(&PyMemberDescr_Type) < 0)
+        Py_FatalError("Can't initialize member descriptor type");
+
+    if (PyType_Ready(&PyFilter_Type) < 0)
+        Py_FatalError("Can't initialize filter type");
+
+    if (PyType_Ready(&PyMap_Type) < 0)
+        Py_FatalError("Can't initialize map type");
+
+    if (PyType_Ready(&PyZip_Type) < 0)
+        Py_FatalError("Can't initialize zip type");
+}
+
+
+#ifdef Py_TRACE_REFS
+
+void
+_Py_NewReference(PyObject *op)
+{
+    _Py_INC_REFTOTAL;
+    op->ob_refcnt = 1;
+    _Py_AddToAllObjects(op, 1);
+    _Py_INC_TPALLOCS(op);
+}
+
+void
+_Py_ForgetReference(register PyObject *op)
+{
+#ifdef SLOW_UNREF_CHECK
+    register PyObject *p;
+#endif
+    if (op->ob_refcnt < 0)
+        Py_FatalError("UNREF negative refcnt");
+    if (op == &refchain ||
+        op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op) {
+        fprintf(stderr, "* ob\n");
+        _PyObject_Dump(op);
+        fprintf(stderr, "* op->_ob_prev->_ob_next\n");
+        _PyObject_Dump(op->_ob_prev->_ob_next);
+        fprintf(stderr, "* op->_ob_next->_ob_prev\n");
+        _PyObject_Dump(op->_ob_next->_ob_prev);
+        Py_FatalError("UNREF invalid object");
+    }
+#ifdef SLOW_UNREF_CHECK
+    for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
+        if (p == op)
+            break;
+    }
+    if (p == &refchain) /* Not found */
+        Py_FatalError("UNREF unknown object");
+#endif
+    op->_ob_next->_ob_prev = op->_ob_prev;
+    op->_ob_prev->_ob_next = op->_ob_next;
+    op->_ob_next = op->_ob_prev = NULL;
+    _Py_INC_TPFREES(op);
+}
+
+void
+_Py_Dealloc(PyObject *op)
+{
+    destructor dealloc = Py_TYPE(op)->tp_dealloc;
+    _Py_ForgetReference(op);
+    (*dealloc)(op);
+}
+
+/* Print all live objects.  Because PyObject_Print is called, the
+ * interpreter must be in a healthy state.
+ */
+void
+_Py_PrintReferences(FILE *fp)
+{
+    PyObject *op;
+    fprintf(fp, "Remaining objects:\n");
+    for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
+        fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", op, op->ob_refcnt);
+        if (PyObject_Print(op, fp, 0) != 0)
+            PyErr_Clear();
+        putc('\n', fp);
+    }
+}
+
+/* Print the addresses of all live objects.  Unlike _Py_PrintReferences, this
+ * doesn't make any calls to the Python C API, so is always safe to call.
+ */
+void
+_Py_PrintReferenceAddresses(FILE *fp)
+{
+    PyObject *op;
+    fprintf(fp, "Remaining object addresses:\n");
+    for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)
+        fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", op,
+            op->ob_refcnt, Py_TYPE(op)->tp_name);
+}
+
+PyObject *
+_Py_GetObjects(PyObject *self, PyObject *args)
+{
+    int i, n;
+    PyObject *t = NULL;
+    PyObject *res, *op;
+
+    if (!PyArg_ParseTuple(args, "i|O", &n, &t))
+        return NULL;
+    op = refchain._ob_next;
+    res = PyList_New(0);
+    if (res == NULL)
+        return NULL;
+    for (i = 0; (n == 0 || i < n) && op != &refchain; i++) {
+        while (op == self || op == args || op == res || op == t ||
+               (t != NULL && Py_TYPE(op) != (PyTypeObject *) t)) {
+            op = op->_ob_next;
+            if (op == &refchain)
+                return res;
+        }
+        if (PyList_Append(res, op) < 0) {
+            Py_DECREF(res);
+            return NULL;
+        }
+        op = op->_ob_next;
+    }
+    return res;
+}
+
+#endif
+
+/* Hack to force loading of pycapsule.o */
+PyTypeObject *_PyCapsule_hack = &PyCapsule_Type;
+
+
+/* Hack to force loading of abstract.o */
+Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
+
+
+/* Python's malloc wrappers (see pymem.h) */
+
+void *
+PyMem_Malloc(size_t nbytes)
+{
+    return PyMem_MALLOC(nbytes);
+}
+
+void *
+PyMem_Realloc(void *p, size_t nbytes)
+{
+    return PyMem_REALLOC(p, nbytes);
+}
+
+void
+PyMem_Free(void *p)
+{
+    PyMem_FREE(p);
+}
+
+
+/* These methods are used to control infinite recursion in repr, str, print,
+   etc.  Container objects that may recursively contain themselves,
+   e.g. builtin dictionaries and lists, should used Py_ReprEnter() and
+   Py_ReprLeave() to avoid infinite recursion.
+
+   Py_ReprEnter() returns 0 the first time it is called for a particular
+   object and 1 every time thereafter.  It returns -1 if an exception
+   occurred.  Py_ReprLeave() has no return value.
+
+   See dictobject.c and listobject.c for examples of use.
+*/
+
+#define KEY "Py_Repr"
+
+int
+Py_ReprEnter(PyObject *obj)
+{
+    PyObject *dict;
+    PyObject *list;
+    Py_ssize_t i;
+
+    dict = PyThreadState_GetDict();
+    if (dict == NULL)
+        return 0;
+    list = PyDict_GetItemString(dict, KEY);
+    if (list == NULL) {
+        list = PyList_New(0);
+        if (list == NULL)
+            return -1;
+        if (PyDict_SetItemString(dict, KEY, list) < 0)
+            return -1;
+        Py_DECREF(list);
+    }
+    i = PyList_GET_SIZE(list);
+    while (--i >= 0) {
+        if (PyList_GET_ITEM(list, i) == obj)
+            return 1;
+    }
+    PyList_Append(list, obj);
+    return 0;
+}
+
+void
+Py_ReprLeave(PyObject *obj)
+{
+    PyObject *dict;
+    PyObject *list;
+    Py_ssize_t i;
+
+    dict = PyThreadState_GetDict();
+    if (dict == NULL)
+        return;
+    list = PyDict_GetItemString(dict, KEY);
+    if (list == NULL || !PyList_Check(list))
+        return;
+    i = PyList_GET_SIZE(list);
+    /* Count backwards because we always expect obj to be list[-1] */
+    while (--i >= 0) {
+        if (PyList_GET_ITEM(list, i) == obj) {
+            PyList_SetSlice(list, i, i + 1, NULL);
+            break;
+        }
+    }
+}
+
+/* Trashcan support. */
+
+/* Current call-stack depth of tp_dealloc calls. */
+int _PyTrash_delete_nesting = 0;
+
+/* List of objects that still need to be cleaned up, singly linked via their
+ * gc headers' gc_prev pointers.
+ */
+PyObject *_PyTrash_delete_later = NULL;
+
+/* Add op to the _PyTrash_delete_later list.  Called when the current
+ * call-stack depth gets large.  op must be a currently untracked gc'ed
+ * object, with refcount 0.  Py_DECREF must already have been called on it.
+ */
+void
+_PyTrash_deposit_object(PyObject *op)
+{
+    assert(PyObject_IS_GC(op));
+    assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED);
+    assert(op->ob_refcnt == 0);
+    _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later;
+    _PyTrash_delete_later = op;
+}
+
+/* Dealloccate all the objects in the _PyTrash_delete_later list.  Called when
+ * the call-stack unwinds again.
+ */
+void
+_PyTrash_destroy_chain(void)
+{
+    while (_PyTrash_delete_later) {
+        PyObject *op = _PyTrash_delete_later;
+        destructor dealloc = Py_TYPE(op)->tp_dealloc;
+
+        _PyTrash_delete_later =
+            (PyObject*) _Py_AS_GC(op)->gc.gc_prev;
+
+        /* Call the deallocator directly.  This used to try to
+         * fool Py_DECREF into calling it indirectly, but
+         * Py_DECREF was already called on this object, and in
+         * assorted non-release builds calling Py_DECREF again ends
+         * up distorting allocation statistics.
+         */
+        assert(op->ob_refcnt == 0);
+        ++_PyTrash_delete_nesting;
+        (*dealloc)(op);
+        --_PyTrash_delete_nesting;
+    }
+}
+
+#ifndef Py_TRACE_REFS
+/* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc.
+   Define this here, so we can undefine the macro. */
+#undef _Py_Dealloc
+PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
+void
+_Py_Dealloc(PyObject *op)
+{
+    _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA
+    (*Py_TYPE(op)->tp_dealloc)(op);
+}
+#endif
+