diff --git a/Objects/abstract.c b/Objects/abstract.c new file mode 100644 index 00000000000..a2099c7668b --- /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,¬_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,¬_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,¬_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; +}