diff options
| -rw-r--r-- | Objects/object.c | 64 | 
1 files changed, 64 insertions, 0 deletions
| diff --git a/Objects/object.c b/Objects/object.c index aa73740c99..f84e64fa2c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -790,3 +790,67 @@ PyMem_Free(p)  {  	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(obj) +	PyObject *obj; +{ +	PyObject *dict; +	PyObject *list; +	int i; + +	dict = PyThreadState_GetDict(); +	if (dict == NULL) +		return -1; +	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(obj) +	PyObject *obj; +{ +	PyObject *dict; +	PyObject *list; +	int i; + +	dict = PyThreadState_GetDict(); +	list = PyDict_GetItemString(dict, KEY); +	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; +		} +	} +} | 
