#include "Python.h" #include "compile.h" #include "frameobject.h" #include "opcode.h" /* iexec.c helper functions imported by the python "iexec" package. */ typedef struct { PyObject_HEAD PyFrameObject *frame; PyObject *isinstance; int blockindex; } iterinstanceobject; static PyObject * iterinstance_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { iterinstanceobject *lz; PyObject* isinstance=NULL; if (!PyArg_ParseTuple(args, "|O:iterinstance", &isinstance)) return NULL; /* create iterinstanceobject structure */ lz = (iterinstanceobject *)type->tp_alloc(type, 0); if (lz == NULL) return NULL; lz->frame = PyThreadState_Get()->frame; Py_INCREF(lz->frame); lz->blockindex = lz->frame->f_iblock -1; lz->isinstance = isinstance; return (PyObject *)lz; } static void iterinstance_dealloc(iterinstanceobject *lz) { PyObject_GC_UnTrack(lz); Py_XDECREF(lz->frame); Py_XDECREF(lz->isinstance); lz->ob_type->tp_free(lz); } static int iterinstance_traverse(iterinstanceobject *lz, visitproc visit, void *arg) { int err; if (lz->frame) { err = visit((PyObject*)lz->frame, arg); if (err) return err; } if (lz->isinstance) { err = visit(lz->isinstance, arg); if (err) return err; } return 0; } static PyObject * iterinstance_next(iterinstanceobject *lz) { PyTryBlock *b; PyObject* obj; PyFrameObject * frame = lz->frame; long x; int i; if (frame == NULL) return NULL; i = lz->blockindex - 1; while (1) { for ( ; i >= 0 ; i--) { b = &lz->frame->f_blockstack[i]; if (b->b_type == SETUP_IEXEC) { obj = frame->f_valuestack[b->b_level-1]; if (lz->isinstance) { x = PyObject_IsInstance(obj, lz->isinstance); if (x < 0) return NULL; if (x == 0) continue; } lz->blockindex = i; Py_INCREF(obj); return obj; } } lz->frame = frame->f_back; Py_DECREF(frame); frame = lz->frame; if (frame == NULL) break; Py_INCREF(frame); i = frame->f_iblock - 1; } return NULL; } PyDoc_STRVAR(iterinstance_doc, "iterinstance() --> iterinstance object\n\ \n\ Return IEXEC handler starting from the current python frame."); static PyTypeObject iterinstance_type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "iexec.iterinstance", /* tp_name */ sizeof(iterinstanceobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)iterinstance_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ iterinstance_doc, /* tp_doc */ (traverseproc)iterinstance_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)iterinstance_next, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ iterinstance_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; static PyObject * getinstance(PyObject* self_, PyObject* args) { PyFrameObject* frame; PyTryBlock *b; PyObject *obj, *isinstance=NULL; int i, x; if (!PyArg_ParseTuple(args, "|O", &isinstance)) return NULL; /* "getinstance" returns the first matching handler. */ frame = PyThreadState_Get()->frame; /* traverse execution handlers up until match is found */ while (frame != NULL) { for (i = frame->f_iblock-1 ; i>=0 ; i--) { b = &frame->f_blockstack[i]; if (b->b_type == SETUP_IEXEC) { /* hack the handler object out from the block */ obj = frame->f_valuestack[b->b_level-1]; if (isinstance) { x = PyObject_IsInstance(obj, isinstance); if (x < 0) return NULL; if (x == 0) continue; } Py_INCREF(obj); return obj; } } frame = frame->f_back; } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(getinstance_doc, "getinstance(isinstance=None)-> first upwards iexec handler\ (beeing an instance according to the optionally given argument.)"); static PyMethodDef _functions[] = { {"getinstance", getinstance, METH_VARARGS, getinstance_doc}, {NULL, NULL} }; PyDoc_STRVAR(module_doc, "Support functions for the iexec protocol. "); PyMODINIT_FUNC initiexec(void) { PyObject *m; if (PyType_Ready(&iterinstance_type) < 0) return; m = Py_InitModule3("iexec", _functions, module_doc); Py_INCREF(&iterinstance_type); PyModule_AddObject(m, "iterinstance", (PyObject *)&iterinstance_type); }