| /*********************************************************** | 
 | 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(name) | 
 |   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(o1, o2, result) | 
 |   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(x) | 
 |   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) { | 
 | 			PyErr_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(o) | 
 | 	PyObject *o; | 
 | { | 
 | 	PyObject *v; | 
 |  | 
 | 	if(! o) return Py_ReturnNullError(); | 
 | 	v = (PyObject *)o->ob_type; | 
 | 	Py_INCREF(v); | 
 | 	return v; | 
 | } | 
 |  | 
 | int | 
 | PyObject_Length(o) | 
 |   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(o, key) | 
 |   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(o, key, value) | 
 |   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(o) | 
 |   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(o) | 
 |   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(o) | 
 |   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(o) | 
 |   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(o) | 
 |   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(o) | 
 |   PyObject *o; | 
 | { | 
 |   return o && o->ob_type->tp_as_sequence; | 
 | } | 
 |  | 
 | int  | 
 | PySequence_Length(s) | 
 |   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(s, o) | 
 |   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(o, count) | 
 |   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(s, i) | 
 |   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(s, i1, i2) | 
 |   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(s, i, o) | 
 |   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(s, i1, i2, o) | 
 |   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(s) | 
 |   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(s, o) | 
 |   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(s, o) | 
 |   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(s, o) | 
 |   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(o) | 
 |   PyObject *o; | 
 | { | 
 |   return o && o->ob_type->tp_as_mapping; | 
 | } | 
 |  | 
 | int  | 
 | PyMapping_Length(s) | 
 |   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(o, key) | 
 |   PyObject *o; | 
 |   char *key; | 
 | { | 
 |   PyObject *v; | 
 |  | 
 |   v=PyMapping_GetItemString(o,key); | 
 |   if(v) return 1; | 
 |   PyErr_Clear(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int  | 
 | PyMapping_HasKey(o, key) | 
 |   PyObject *o; | 
 |   PyObject *key; | 
 | { | 
 |   PyObject *v; | 
 |  | 
 |   v=PyObject_GetItem(o,key); | 
 |   if(v) return 1; | 
 |   PyErr_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 *name; | 
 |   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(o, key) | 
 |   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(o, key, value) | 
 |  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; | 
 | } |