153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel/* Generator object implementation */ 253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "Python.h" 453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "frameobject.h" 553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "genobject.h" 653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "ceval.h" 753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "structmember.h" 853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#include "opcode.h" 953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 1053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic int 1153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_traverse(PyGenObject *gen, visitproc visit, void *arg) 1253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 1353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_VISIT((PyObject *)gen->gi_frame); 1453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_VISIT(gen->gi_code); 1553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return 0; 1653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 1753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 1853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic void 1953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_dealloc(PyGenObject *gen) 2053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 2153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *self = (PyObject *) gen; 2253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 2353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _PyObject_GC_UNTRACK(gen); 2453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 2553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (gen->gi_weakreflist != NULL) 2653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject_ClearWeakRefs(self); 2753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 2853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _PyObject_GC_TRACK(self); 2953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 3053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) { 3153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Generator is paused, so we need to close */ 3253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_TYPE(gen)->tp_del(self); 3353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (self->ob_refcnt > 0) 3453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return; /* resurrected. :( */ 3553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 3653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 3753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _PyObject_GC_UNTRACK(self); 3853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_CLEAR(gen->gi_frame); 3953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_CLEAR(gen->gi_code); 4053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject_GC_Del(gen); 4153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 4253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 4353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 4453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 4553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_send_ex(PyGenObject *gen, PyObject *arg, int exc) 4653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 4753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyThreadState *tstate = PyThreadState_GET(); 4853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyFrameObject *f = gen->gi_frame; 4953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *result; 5053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 5153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (gen->gi_running) { 5253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetString(PyExc_ValueError, 5353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "generator already executing"); 5453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 5553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 5653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (f==NULL || f->f_stacktop == NULL) { 5753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Only set exception if called from send() */ 5853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (arg && !exc) 5953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetNone(PyExc_StopIteration); 6053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 6153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 6253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 6353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (f->f_lasti == -1) { 6453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (arg && arg != Py_None) { 6553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetString(PyExc_TypeError, 6653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "can't send non-None value to a " 6753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "just-started generator"); 6853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 6953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 7053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } else { 7153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Push arg onto the frame's value stack */ 7253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel result = arg ? arg : Py_None; 7353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(result); 7453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel *(f->f_stacktop++) = result; 7553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 7653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 7753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Generators always return to their most recent caller, not 7853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * necessarily their creator. */ 7953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel f->f_tstate = tstate; 8053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XINCREF(tstate->frame); 8153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel assert(f->f_back == NULL); 8253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel f->f_back = tstate->frame; 8353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 8453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_running = 1; 8553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel result = PyEval_EvalFrameEx(f, exc); 8653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_running = 0; 8753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 8853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Don't keep the reference to f_back any longer than necessary. It 8953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * may keep a chain of frames alive or it could create a reference 9053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * cycle. */ 9153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel assert(f->f_back == tstate->frame); 9253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_CLEAR(f->f_back); 9353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Clear the borrowed reference to the thread state */ 9453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel f->f_tstate = NULL; 9553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 9653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* If the generator just returned (as opposed to yielding), signal 9753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * that the generator is exhausted. */ 9853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (result == Py_None && f->f_stacktop == NULL) { 9953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(result); 10053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel result = NULL; 10153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Set exception if not called by gen_iternext() */ 10253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (arg) 10353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetNone(PyExc_StopIteration); 10453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 10553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 10653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (!result || f->f_stacktop == NULL) { 10753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* generator can't be rerun, so release the frame */ 10853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(f); 10953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_frame = NULL; 11053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 11153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 11253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return result; 11353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 11453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 11553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(send_doc, 11653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"send(arg) -> send 'arg' into generator,\n\ 11753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielreturn next yielded value or raise StopIteration."); 11853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 11953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 12053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_send(PyGenObject *gen, PyObject *arg) 12153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 12253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return gen_send_ex(gen, arg, 0); 12353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 12453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 12553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(close_doc, 12653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"close() -> raise GeneratorExit inside generator."); 12753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 12853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 12953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_close(PyGenObject *gen, PyObject *args) 13053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 13153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *retval; 13253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetNone(PyExc_GeneratorExit); 13353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel retval = gen_send_ex(gen, Py_None, 1); 13453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (retval) { 13553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(retval); 13653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetString(PyExc_RuntimeError, 13753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "generator ignored GeneratorExit"); 13853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 13953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 14053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (PyErr_ExceptionMatches(PyExc_StopIteration) 14153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel || PyErr_ExceptionMatches(PyExc_GeneratorExit)) 14253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel { 14353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_Clear(); /* ignore these errors */ 14453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(Py_None); 14553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return Py_None; 14653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 14753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 14853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 14953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 15053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic void 15153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_del(PyObject *self) 15253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 15353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *res; 15453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *error_type, *error_value, *error_traceback; 15553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyGenObject *gen = (PyGenObject *)self; 15653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 15753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL) 15853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Generator isn't paused, so no need to close */ 15953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return; 16053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 16153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Temporarily resurrect the object. */ 16253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel assert(self->ob_refcnt == 0); 16353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel self->ob_refcnt = 1; 16453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 16553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Save the current exception, if any. */ 16653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_Fetch(&error_type, &error_value, &error_traceback); 16753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 16853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel res = gen_close(gen, NULL); 16953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 17053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (res == NULL) 17153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_WriteUnraisable(self); 17253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel else 17353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(res); 17453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 17553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Restore the saved exception. */ 17653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_Restore(error_type, error_value, error_traceback); 17753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 17853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Undo the temporary resurrection; can't use DECREF here, it would 17953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * cause a recursive call. 18053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */ 18153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel assert(self->ob_refcnt > 0); 18253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (--self->ob_refcnt == 0) 18353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return; /* this is the normal path out */ 18453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 18553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* close() resurrected it! Make it look like the original Py_DECREF 18653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * never happened. 18753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */ 18853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel { 18953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_ssize_t refcnt = self->ob_refcnt; 19053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _Py_NewReference(self); 19153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel self->ob_refcnt = refcnt; 19253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 19353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel assert(PyType_IS_GC(self->ob_type) && 19453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); 19553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 19653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so 19753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * we need to undo that. */ 19853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _Py_DEC_REFTOTAL; 19953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object 20053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * chain, so no more to do there. 20153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * If COUNT_ALLOCS, the original decref bumped tp_frees, and 20253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * _Py_NewReference bumped tp_allocs: both of those need to be 20353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel * undone. 20453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel */ 20553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#ifdef COUNT_ALLOCS 20653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel --self->ob_type->tp_frees; 20753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel --self->ob_type->tp_allocs; 20853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel#endif 20953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 21053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 21153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 21253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 21353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(throw_doc, 21453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"throw(typ[,val[,tb]]) -> raise exception in generator,\n\ 21553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielreturn next yielded value or raise StopIteration."); 21653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 21753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 21853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_throw(PyGenObject *gen, PyObject *args) 21953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 22053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *typ; 22153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *tb = NULL; 22253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *val = NULL; 22353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 22453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) 22553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 22653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 22753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* First, check the traceback argument, replacing None with 22853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel NULL. */ 22953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (tb == Py_None) 23053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel tb = NULL; 23153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel else if (tb != NULL && !PyTraceBack_Check(tb)) { 23253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetString(PyExc_TypeError, 23353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "throw() third argument must be a traceback object"); 23453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 23553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 23653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 23753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(typ); 23853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XINCREF(val); 23953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XINCREF(tb); 24053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 24153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (PyExceptionClass_Check(typ)) { 24253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_NormalizeException(&typ, &val, &tb); 24353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 24453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 24553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel else if (PyExceptionInstance_Check(typ)) { 24653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Raising an instance. The value should be a dummy. */ 24753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (val && val != Py_None) { 24853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_SetString(PyExc_TypeError, 24953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "instance exception may not have a separate value"); 25053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel goto failed_throw; 25153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 25253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel else { 25353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Normalize to raise <class>, <instance> */ 25453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XDECREF(val); 25553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel val = typ; 25653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel typ = PyExceptionInstance_Class(typ); 25753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(typ); 25853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 25953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 26053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel else { 26153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Not something you can raise. throw() fails. */ 26253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_Format(PyExc_TypeError, 26353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "exceptions must be classes, or instances, not %s", 26453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel typ->ob_type->tp_name); 26553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel goto failed_throw; 26653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 26753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 26853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyErr_Restore(typ, val, tb); 26953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return gen_send_ex(gen, Py_None, 1); 27053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 27153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielfailed_throw: 27253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Didn't use our arguments, so restore their original refcounts */ 27353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(typ); 27453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XDECREF(val); 27553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_XDECREF(tb); 27653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 27753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 27853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 27953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 28053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 28153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_iternext(PyGenObject *gen) 28253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 28353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return gen_send_ex(gen, NULL, 0); 28453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 28553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 28653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 28753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 28853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_repr(PyGenObject *gen) 28953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 29053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel char *code_name; 29153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel code_name = PyString_AsString(((PyCodeObject *)gen->gi_code)->co_name); 29253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (code_name == NULL) 29353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 29453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return PyString_FromFormat("<generator object %.200s at %p>", 29553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel code_name, gen); 29653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 29753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 29853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 29953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyObject * 30053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielgen_get_name(PyGenObject *gen) 30153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 30253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name; 30353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(name); 30453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return name; 30553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 30653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 30753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 30853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyDoc_STRVAR(gen__name__doc__, 30953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel"Return the name of the generator's associated code object."); 31053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 31153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyGetSetDef gen_getsetlist[] = { 31253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"__name__", (getter)gen_get_name, NULL, gen__name__doc__}, 31353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {NULL} 31453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}; 31553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 31653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 31753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyMemberDef gen_memberlist[] = { 31853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO}, 31953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO}, 32053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), RO}, 32153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {NULL} /* Sentinel */ 32253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}; 32353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 32453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielstatic PyMethodDef gen_methods[] = { 32553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"send",(PyCFunction)gen_send, METH_O, send_doc}, 32653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc}, 32753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, 32853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel {NULL, NULL} /* Sentinel */ 32953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}; 33053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 33153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyTypeObject PyGen_Type = { 33253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyVarObject_HEAD_INIT(&PyType_Type, 0) 33353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel "generator", /* tp_name */ 33453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel sizeof(PyGenObject), /* tp_basicsize */ 33553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_itemsize */ 33653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* methods */ 33753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel (destructor)gen_dealloc, /* tp_dealloc */ 33853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_print */ 33953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_getattr */ 34053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_setattr */ 34153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_compare */ 34253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel (reprfunc)gen_repr, /* tp_repr */ 34353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_as_number */ 34453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_as_sequence */ 34553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_as_mapping */ 34653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_hash */ 34753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_call */ 34853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_str */ 34953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject_GenericGetAttr, /* tp_getattro */ 35053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_setattro */ 35153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_as_buffer */ 35253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 35353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_doc */ 35453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel (traverseproc)gen_traverse, /* tp_traverse */ 35553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_clear */ 35653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_richcompare */ 35753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */ 35853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyObject_SelfIter, /* tp_iter */ 35953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel (iternextfunc)gen_iternext, /* tp_iternext */ 36053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen_methods, /* tp_methods */ 36153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen_memberlist, /* tp_members */ 36253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen_getsetlist, /* tp_getset */ 36353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_base */ 36453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_dict */ 36553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 36653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_descr_get */ 36753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_descr_set */ 36853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_dictoffset */ 36953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_init */ 37053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_alloc */ 37153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_new */ 37253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_free */ 37353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_is_gc */ 37453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_bases */ 37553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_mro */ 37653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_cache */ 37753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_subclasses */ 37853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 0, /* tp_weaklist */ 37953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen_del, /* tp_del */ 38053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel}; 38153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 38253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyObject * 38353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyGen_New(PyFrameObject *f) 38453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 38553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type); 38653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (gen == NULL) { 38753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_DECREF(f); 38853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return NULL; 38953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 39053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_frame = f; 39153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel Py_INCREF(f->f_code); 39253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_code = (PyObject *)(f->f_code); 39353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_running = 0; 39453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel gen->gi_weakreflist = NULL; 39553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel _PyObject_GC_TRACK(gen); 39653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return (PyObject *)gen; 39753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 39853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 39953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielint 40053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDanielPyGen_NeedsFinalizing(PyGenObject *gen) 40153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel{ 40253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel int i; 40353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel PyFrameObject *f = gen->gi_frame; 40453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 40553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0) 40653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return 0; /* no frame or empty blockstack == no finalization */ 40753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 40853b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* Any block type besides a loop requires cleanup. */ 40953b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel i = f->f_iblock; 41053b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel while (--i >= 0) { 41153b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel if (f->f_blockstack[i].b_type != SETUP_LOOP) 41253b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return 1; 41353b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel } 41453b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel 41553b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel /* No blocks except loops, it's safe to skip finalization. */ 41653b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel return 0; 41753b2ba5790b57b3dcdfbb9fa5835a979d94908faDaryl McDaniel} 418