summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Objects/abstract.c972
1 files changed, 972 insertions, 0 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
new file mode 100644
index 0000000..a2099c7
--- /dev/null
+++ b/Objects/abstract.c
@@ -0,0 +1,972 @@
+/***********************************************************
+Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
+The Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Abstract Object Interface (many thanks to Jim Fulton) */
+
+#include "Python.h"
+
+#define Py_TRY(E) if(!(E)) return NULL
+#define Py_ASSERT(EXP,E,V) if(!(EXP)) return PyErr_SetString(E,V), (void*)NULL
+#define SPAM printf("line %d\n",__LINE__)
+
+static PyObject *
+Py_ReturnMethodError(char *name)
+{
+ if(! name) name = "Unknown Error";
+ PyErr_SetString(PyExc_AttributeError,name);
+ return 0;
+}
+
+PyObject *
+Py_ReturnNullError()
+{
+ if(! PyErr_Occurred())
+ PyErr_SetString(PyExc_SystemError,
+ "null argument to internal routine");
+ return 0;
+}
+
+int
+PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
+{
+ int r;
+
+ if(! o1 || ! o2) return Py_ReturnNullError(),-1;
+ r=PyObject_Compare(o1,o2);
+ if(PyErr_Occurred()) return -1;
+ *result=r;
+ return 0;
+}
+
+#if 0 /* Already in object.c */
+int
+PyCallable_Check(PyObject *x)
+{
+ if (x == NULL)
+ return 0;
+ if (x->ob_type->tp_call != NULL ||
+ PyFunction_Check(x) ||
+ PyMethod_Check(x) ||
+ PyCFunction_Check(x) ||
+ PyClass_Check(x))
+ return 1;
+ if (PyInstance_Check(x)) {
+ PyObject *call = PyObject_GetAttrString(x, "__call__");
+ if (call == NULL) {
+ err_clear();
+ return 0;
+ }
+ /* Could test recursively but don't, for fear of endless
+ recursion if some joker sets self.__call__ = self */
+ Py_DECREF(call);
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+PyObject *
+PyObject_Type(PyObject *o)
+{
+ PyObject *v;
+
+ if(! o) return Py_ReturnNullError();
+ v = (PyObject *)o->ob_type;
+ Py_INCREF(v);
+ return v;
+}
+
+int
+PyObject_Length(PyObject *o)
+{
+ PySequenceMethods *m;
+
+ if(! o) return Py_ReturnNullError(),-1;
+
+ if((m=o->ob_type->tp_as_sequence) && m->sq_length)
+ return m->sq_length(o);
+
+ return PyMapping_Length(o);
+}
+
+PyObject *
+PyObject_GetItem(PyObject *o, PyObject *key)
+{
+ PyMappingMethods *m;
+
+ if(! o || ! key) return Py_ReturnNullError();
+
+ if((m=o->ob_type->tp_as_mapping) && m->mp_subscript)
+ return m->mp_subscript(o,key);
+
+ if(PyInt_Check(key))
+ return PySequence_GetItem(o,PyInt_AsLong(key));
+
+ PyErr_SetString(PyExc_TypeError,"expected integer index");
+ return NULL;
+}
+
+int
+PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
+{
+ PyMappingMethods *m;
+
+ if(! o || ! key || ! value) return Py_ReturnNullError(),-1;
+ if((m=o->ob_type->tp_as_mapping) && m->mp_ass_subscript)
+ return m->mp_ass_subscript(o,key,value);
+
+ if(PyInt_Check(key))
+ return PySequence_SetItem(o,PyInt_AsLong(key),value);
+
+ PyErr_SetString(PyExc_TypeError,"expeced integer index");
+ return -1;
+}
+
+int
+PyNumber_Check(PyObject *o)
+{
+ return o && o->ob_type->tp_as_number;
+}
+
+
+#define BINOP(opname, ropname, thisfunc) \
+ if (!PyInstance_Check(v) && !PyInstance_Check(w)) \
+ ; \
+ else \
+ return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)
+
+PyObject *
+PyNumber_Or(v, w)
+ PyObject *v, *w;
+{
+ extern int PyNumber_Coerce();
+
+ BINOP("__or__", "__ror__", PyNumber_Or);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ PyObject * (*f) Py_FPROTO((PyObject *, PyObject *));
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ if ((f = v->ob_type->tp_as_number->nb_or) != NULL)
+ x = (*f)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (f != NULL)
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for |");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Xor(v, w)
+ PyObject *v, *w;
+{
+ extern int PyNumber_Coerce();
+
+ BINOP("__xor__", "__rxor__", PyNumber_Xor);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ PyObject * (*f) Py_FPROTO((PyObject *, PyObject *));
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ if ((f = v->ob_type->tp_as_number->nb_xor) != NULL)
+ x = (*f)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (f != NULL)
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for ^");
+ return NULL;
+}
+
+PyObject *
+PyNumber_And(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__and__", "__rand__", PyNumber_And);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ PyObject * (*f) Py_FPROTO((PyObject *, PyObject *));
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ if ((f = v->ob_type->tp_as_number->nb_and) != NULL)
+ x = (*f)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (f != NULL)
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for &");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Lshift(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__lshift__", "__rlshift__", PyNumber_Lshift);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ PyObject * (*f) Py_FPROTO((PyObject *, PyObject *));
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ if ((f = v->ob_type->tp_as_number->nb_lshift) != NULL)
+ x = (*f)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (f != NULL)
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for <<");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Rshift(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__rshift__", "__rrshift__", PyNumber_Rshift);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ PyObject * (*f) Py_FPROTO((PyObject *, PyObject *));
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ if ((f = v->ob_type->tp_as_number->nb_rshift) != NULL)
+ x = (*f)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ if (f != NULL)
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for >>");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Add(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__add__", "__radd__", PyNumber_Add);
+ if (v->ob_type->tp_as_sequence != NULL)
+ return (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
+ else if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ x = (*v->ob_type->tp_as_number->nb_add)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for +");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Subtract(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__sub__", "__rsub__", PyNumber_Subtract);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ x = (*v->ob_type->tp_as_number->nb_subtract)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for -");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Multiply(v, w)
+ PyObject *v, *w;
+{
+ PyTypeObject *tp;
+ tp = v->ob_type;
+ BINOP("__mul__", "__rmul__", PyNumber_Multiply);
+ if (tp->tp_as_number != NULL &&
+ w->ob_type->tp_as_sequence != NULL &&
+ !PyInstance_Check(v)) {
+ /* number*sequence -- swap v and w */
+ PyObject *tmp = v;
+ v = w;
+ w = tmp;
+ tp = v->ob_type;
+ }
+ if (tp->tp_as_number != NULL) {
+ PyObject *x;
+ if (PyInstance_Check(v)) {
+ /* Instances of user-defined classes get their
+ other argument uncoerced, so they may
+ implement sequence*number as well as
+ number*number. */
+ Py_INCREF(v);
+ Py_INCREF(w);
+ }
+ else if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ x = (*v->ob_type->tp_as_number->nb_multiply)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return x;
+ }
+ if (tp->tp_as_sequence != NULL) {
+ if (!PyInt_Check(w)) {
+ PyErr_SetString(PyExc_TypeError,
+ "can't multiply sequence with non-int");
+ return NULL;
+ }
+ return (*tp->tp_as_sequence->sq_repeat)
+ (v, (int)PyInt_AsLong(w));
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for *");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Divide(v, w)
+ PyObject *v, *w;
+{
+ BINOP("__div__", "__rdiv__", PyNumber_Divide);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ x = (*v->ob_type->tp_as_number->nb_divide)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for /");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Remainder(v, w)
+ PyObject *v, *w;
+{
+ if (PyString_Check(v)) {
+ return PyString_Format(v, w);
+ }
+ BINOP("__mod__", "__rmod__", PyNumber_Remainder);
+ if (v->ob_type->tp_as_number != NULL) {
+ PyObject *x;
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ x = (*v->ob_type->tp_as_number->nb_remainder)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return x;
+ }
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for %");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Divmod(v, w)
+ PyObject *v, *w;
+{
+ PyObject *res;
+
+ if (PyInstance_Check(v) || PyInstance_Check(w))
+ return PyInstance_DoBinOp(v, w, "__divmod__", "__rdivmod__",
+ PyNumber_Divmod);
+ if (v->ob_type->tp_as_number == NULL ||
+ w->ob_type->tp_as_number == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "divmod() requires numeric or class instance arguments");
+ return NULL;
+ }
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ res = (*v->ob_type->tp_as_number->nb_divmod)(v, w);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return res;
+}
+
+
+static PyObject *
+do_pow(v, w)
+ PyObject *v, *w;
+{
+ PyObject *res;
+ if (PyInstance_Check(v) || PyInstance_Check(w))
+ return PyInstance_DoBinOp(v, w, "__pow__", "__rpow__", do_pow);
+ if (v->ob_type->tp_as_number == NULL ||
+ w->ob_type->tp_as_number == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "pow() requires numeric arguments");
+ return NULL;
+ }
+ if (PyFloat_Check(w) && PyFloat_AsDouble(v) < 0.0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_ValueError,
+ "negative number to float power");
+ return NULL;
+ }
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ res = (*v->ob_type->tp_as_number->nb_power)(v, w, Py_None);
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return res;
+}
+
+PyObject *
+PyNumber_Power(v,w,z)
+ PyObject *v, *w, *z;
+{
+ PyObject *res;
+ PyObject *v1, *z1, *w2, *z2;
+
+ if (z == Py_None)
+ return do_pow(v, w);
+ /* XXX The ternary version doesn't do class instance coercions */
+ if (PyInstance_Check(v))
+ return v->ob_type->tp_as_number->nb_power(v, w, z);
+ if (v->ob_type->tp_as_number == NULL ||
+ z->ob_type->tp_as_number == NULL ||
+ w->ob_type->tp_as_number == NULL) {
+ PyErr_SetString(PyExc_TypeError, "pow() requires numeric arguments");
+ return NULL;
+ }
+ if (PyNumber_Coerce(&v, &w) != 0)
+ return NULL;
+ res = NULL;
+ v1 = v;
+ z1 = z;
+ if (PyNumber_Coerce(&v1, &z1) != 0)
+ goto error2;
+ w2 = w;
+ z2 = z1;
+ if (PyNumber_Coerce(&w2, &z2) != 0)
+ goto error1;
+ res = (*v1->ob_type->tp_as_number->nb_power)(v1, w2, z2);
+ Py_DECREF(w2);
+ Py_DECREF(z2);
+ error1:
+ Py_DECREF(v1);
+ Py_DECREF(z1);
+ error2:
+ Py_DECREF(v);
+ Py_DECREF(w);
+ return res;
+}
+
+
+PyObject *
+PyNumber_Negative(v)
+ PyObject *v;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_negative)(v);
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for unary -");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Positive(v)
+ PyObject *v;
+{
+ if (v->ob_type->tp_as_number != NULL)
+ return (*v->ob_type->tp_as_number->nb_positive)(v);
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for unary +");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Invert(v)
+ PyObject *v;
+{
+ PyObject * (*f) Py_FPROTO((PyObject *));
+ if (v->ob_type->tp_as_number != NULL &&
+ (f = v->ob_type->tp_as_number->nb_invert) != NULL)
+ return (*f)(v);
+ PyErr_SetString(PyExc_TypeError, "bad operand type(s) for unary ~");
+ return NULL;
+}
+
+PyObject *
+PyNumber_Absolute(PyObject *o)
+{
+ PyNumberMethods *m;
+
+ if(! o) return Py_ReturnNullError();
+ if((m=o->ob_type->tp_as_number) && m->nb_absolute)
+ return m->nb_absolute(o);
+
+ return Py_ReturnMethodError("__abs__");
+}
+
+PyObject *
+PyNumber_Int(PyObject *o)
+{
+ PyNumberMethods *m;
+
+ if(! o) return Py_ReturnNullError();
+ if((m=o->ob_type->tp_as_number) && m->nb_int)
+ return m->nb_int(o);
+
+ return Py_ReturnMethodError("__int__");
+}
+
+PyObject *
+PyNumber_Long(PyObject *o)
+{
+ PyNumberMethods *m;
+
+ if(! o) return Py_ReturnNullError();
+ if((m=o->ob_type->tp_as_number) && m->nb_long)
+ return m->nb_long(o);
+
+ return Py_ReturnMethodError("__long__");
+}
+
+PyObject *
+PyNumber_Float(PyObject *o)
+{
+ PyNumberMethods *m;
+
+ if(! o) return Py_ReturnNullError();
+ if((m=o->ob_type->tp_as_number) && m->nb_float)
+ return m->nb_float(o);
+
+ return Py_ReturnMethodError("__float__");
+}
+
+
+int
+PySequence_Check(PyObject *o)
+{
+ return o && o->ob_type->tp_as_sequence;
+}
+
+int
+PySequence_Length(PyObject *s)
+{
+ PySequenceMethods *m;
+
+ if(! s) return Py_ReturnNullError(),-1;
+
+ if((m=s->ob_type->tp_as_sequence) && m->sq_length)
+ return m->sq_length(s);
+
+ Py_ReturnMethodError("__len__");
+ return -1;
+}
+
+PyObject *
+PySequence_Concat(PyObject *s, PyObject *o)
+{
+ PySequenceMethods *m;
+
+ if(! s || ! o) return Py_ReturnNullError();
+
+ if((m=s->ob_type->tp_as_sequence) && m->sq_concat)
+ return m->sq_concat(s,o);
+
+ return Py_ReturnMethodError("__concat__");
+}
+
+PyObject *
+PySequence_Repeat(PyObject *o, int count)
+{
+ PySequenceMethods *m;
+
+ if(! o) return Py_ReturnNullError();
+
+ if((m=o->ob_type->tp_as_sequence) && m->sq_repeat)
+ return m->sq_repeat(o,count);
+
+ return Py_ReturnMethodError("__repeat__");
+}
+
+PyObject *
+PySequence_GetItem(PyObject *s, int i)
+{
+ PySequenceMethods *m;
+ int l;
+
+ if(! s) return Py_ReturnNullError();
+
+ if(! ((m=s->ob_type->tp_as_sequence) && m->sq_length && m->sq_item))
+ return Py_ReturnMethodError("__getitem__");
+
+ if(0 > (l=m->sq_length(s))) return NULL;
+
+ if(i < 0) i += l;
+
+ return m->sq_item(s,i);
+}
+
+PyObject *
+PySequence_GetSlice(PyObject *s, int i1, int i2)
+{
+ PySequenceMethods *m;
+ int l;
+
+ if(! s) return Py_ReturnNullError();
+
+ if(! ((m=s->ob_type->tp_as_sequence) && m->sq_length && m->sq_slice))
+ return Py_ReturnMethodError("__getslice__");
+
+ if(0 > (l=m->sq_length(s))) return NULL;
+
+ if(i1 < 0) i1 += l;
+ if(i2 < 0) i2 += l;
+
+ return m->sq_slice(s,i1,i2);
+}
+
+int
+PySequence_SetItem(PyObject *s, int i, PyObject *o)
+{
+ PySequenceMethods *m;
+ int l;
+ if(! s) return Py_ReturnNullError(),-1;
+
+ if(! ((m=s->ob_type->tp_as_sequence) && m->sq_length && m->sq_ass_item))
+ return Py_ReturnMethodError("__setitem__"),-1;
+
+ if(i < 0)
+ {
+ if(0 > (l=m->sq_length(s))) return -1;
+ i += l;
+ }
+
+ return m->sq_ass_item(s,i,o);
+}
+
+int
+PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o)
+{
+ PySequenceMethods *m;
+ int l;
+
+ if(! s) return Py_ReturnNullError(),-1;
+
+ if(! ((m=s->ob_type->tp_as_sequence) && m->sq_length && m->sq_ass_slice))
+ return Py_ReturnMethodError("__setslice__"),-1;
+
+ if(0 > (l=m->sq_length(s))) return -1;
+
+ if(i1 < 0) i1 += l;
+ if(i2 < 0) i2 += l;
+
+ return m->sq_ass_slice(s,i1,i2,o);
+}
+
+PyObject *
+PySequence_Tuple(PyObject *s)
+{
+ int l, i;
+ PyObject *t, *item;
+
+ if(! s) return Py_ReturnNullError();
+
+ Py_TRY((l=PySequence_Length(s)) != -1);
+ Py_TRY(t=PyTuple_New(l));
+
+ for(i=0; i < l; i++)
+ {
+ if(item=PySequence_GetItem(s,i))
+ {
+ if(PyTuple_SetItem(t,i,item) == -1)
+ {
+ Py_DECREF(item);
+ Py_DECREF(t);
+ return NULL;
+ }
+ }
+ else
+ {
+ Py_DECREF(t);
+ return NULL;
+ }
+ }
+ return t;
+}
+
+int
+PySequence_Count(PyObject *s, PyObject *o)
+{
+ int l, i, n=0, not_equal, err;
+ PyObject *item;
+
+ if(! s || ! o) return Py_ReturnNullError(), -1;
+ Py_TRY((l=PySequence_Length(s)) != -1),-1;
+
+ for(i=0; i < l; i++)
+ {
+ Py_TRY(item=PySequence_GetItem(s,i)),-1;
+ err=PyObject_Cmp(item,o,&not_equal) == -1;
+ Py_DECREF(item);
+ if(err) return -1;
+ n += ! not_equal;
+ }
+ return n;
+}
+
+int
+PySequence_In(PyObject *s, PyObject *o)
+{
+ int l, i, not_equal, err;
+ PyObject *item;
+
+ if(! o || ! s) return Py_ReturnNullError(), -1;
+ Py_TRY((l=PySequence_Length(s)) != -1),-1;
+
+ for(i=0; i < l; i++)
+ {
+ Py_TRY(item=PySequence_GetItem(s,i)),-1;
+ err=PyObject_Cmp(item,o,&not_equal) == -1;
+ Py_DECREF(item);
+ if(err) return -1;
+ if(! not_equal) return 1;
+ }
+ return 0;
+}
+
+int
+PySequence_Index(PyObject *s, PyObject *o)
+{
+ int l, i, n=0, not_equal, err;
+ PyObject *item;
+
+ if(! s || ! o) return Py_ReturnNullError(), -1;
+ Py_TRY((l=PySequence_Length(s)) != -1),-1;
+
+ for(i=0; i < l; i++)
+ {
+ Py_TRY(item=PySequence_GetItem(s,i)),-1;
+ err=PyObject_Cmp(item,o,&not_equal) == -1;
+ Py_DECREF(item);
+ if(err) return -1;
+ if(! not_equal) return n;
+ }
+ return -1;
+}
+
+int
+PyMapping_Check(PyObject *o)
+{
+ return o && o->ob_type->tp_as_mapping;
+}
+
+int
+PyMapping_Length(PyObject *s)
+{
+ PyMappingMethods *m;
+
+ if(! s) return Py_ReturnNullError(),-1;
+
+ if((m=s->ob_type->tp_as_mapping) && m->mp_length)
+ return m->mp_length(s);
+
+ Py_ReturnMethodError("__len__");
+ return -1;
+}
+
+int
+PyMapping_HasKeyString(PyObject *o, char *key)
+{
+ PyObject *v;
+
+ v=PyMapping_GetItemString(o,key);
+ if(v) return 1;
+ err_clear();
+ return 0;
+}
+
+int
+PyMapping_HasKey(PyObject *o, PyObject *key)
+{
+ PyObject *v;
+
+ v=PyObject_GetItem(o,key);
+ if(v) return 1;
+ err_clear();
+ return 0;
+}
+
+PyObject *
+PyObject_CallObject(o,a)
+ PyObject *o, *a;
+{
+ PyObject *r;
+
+ if(a) return PyEval_CallObject(o,a);
+
+ if(! (a=PyTuple_New(0)))
+ return NULL;
+ r=PyEval_CallObject(o,a);
+ Py_DECREF(a);
+ return r;
+}
+
+PyObject *
+#ifdef HAVE_STDARG_PROTOTYPES
+/* VARARGS 2 */
+PyObject_CallFunction(PyObject *callable, char *format, ...)
+#else
+/* VARARGS */
+PyObject_CallFunction(va_alist) va_dcl
+#endif
+{
+ va_list va;
+ PyObject *args, *retval;
+#ifdef HAVE_STDARG_PROTOTYPES
+ va_start(va, format);
+#else
+ PyObject *callable;
+ char *format;
+ va_start(va);
+ callable = va_arg(va, PyObject *);
+ format = va_arg(va, char *);
+#endif
+
+ if( ! callable)
+ {
+ va_end(va);
+ return Py_ReturnNullError();
+ }
+
+ if(format)
+ args = Py_VaBuildValue(format, va);
+ else
+ args = PyTuple_New(0);
+
+ va_end(va);
+ if(! args) return NULL;
+
+ if(! PyTuple_Check(args))
+ {
+ PyObject *a;
+
+ Py_TRY(a=PyTuple_New(1));
+ Py_TRY(PyTuple_SetItem(a,0,args) != -1);
+ args=a;
+ }
+ retval = PyObject_CallObject(callable,args);
+ Py_DECREF(args);
+ return retval;
+}
+
+PyObject *
+#ifdef HAVE_STDARG_PROTOTYPES
+/* VARARGS 2 */
+PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
+#else
+/* VARARGS */
+PyObject_CallMethod(va_alist) va_dcl
+#endif
+{
+ va_list va;
+ PyObject *args, *method=0, *retval;
+#ifdef HAVE_STDARG_PROTOTYPES
+ va_start(va, format);
+#else
+ PyObject *o;
+ char *format;
+ va_start(va);
+ o = va_arg(va, PyObject *);
+ name = va_arg(va, char *);
+ format = va_arg(va, char *);
+#endif
+
+ if( ! o || ! name)
+ {
+ va_end(va);
+ return Py_ReturnNullError();
+ }
+
+ method=PyObject_GetAttrString(o,name);
+ if(! method)
+ {
+ va_end(va);
+ PyErr_SetString(PyExc_AttributeError,name);
+ return 0;
+ }
+
+ if(! (PyCallable_Check(method)))
+ {
+ va_end(va);
+ PyErr_SetString(PyExc_TypeError,"call of non-callable attribute");
+ return 0;
+ }
+
+ if(format)
+ args = Py_VaBuildValue(format, va);
+ else
+ args = PyTuple_New(0);
+
+ va_end(va);
+
+ if(! args) return NULL;
+
+ if(! PyTuple_Check(args))
+ {
+ PyObject *a;
+
+ Py_TRY(a=PyTuple_New(1));
+ Py_TRY(PyTuple_SetItem(a,0,args) != -1);
+ args=a;
+ }
+
+ retval = PyObject_CallObject(method,args);
+ Py_DECREF(args);
+ Py_DECREF(method);
+ return retval;
+}
+
+PyObject *
+PyMapping_GetItemString(PyObject *o, char *key)
+{
+ PyObject *okey, *r;
+
+ if( ! key) return Py_ReturnNullError();
+ Py_TRY(okey=PyString_FromString(key));
+ r = PyObject_GetItem(o,okey);
+ Py_DECREF(okey);
+ return r;
+}
+
+int
+PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
+{
+ PyObject *okey;
+ int r;
+
+ if( ! key) return Py_ReturnNullError(),-1;
+ if (!(okey=PyString_FromString(key))) return -1;
+ r = PyObject_SetItem(o,okey,value);
+ Py_DECREF(okey);
+ return r;
+}