+++ /dev/null
-\r
-/* Method object implementation */\r
-\r
-#include "Python.h"\r
-#include "structmember.h"\r
-\r
-/* Free list for method objects to safe malloc/free overhead\r
- * The m_self element is used to chain the objects.\r
- */\r
-static PyCFunctionObject *free_list = NULL;\r
-static int numfree = 0;\r
-#ifndef PyCFunction_MAXFREELIST\r
-#define PyCFunction_MAXFREELIST 256\r
-#endif\r
-\r
-PyObject *\r
-PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)\r
-{\r
- PyCFunctionObject *op;\r
- op = free_list;\r
- if (op != NULL) {\r
- free_list = (PyCFunctionObject *)(op->m_self);\r
- PyObject_INIT(op, &PyCFunction_Type);\r
- numfree--;\r
- }\r
- else {\r
- op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);\r
- if (op == NULL)\r
- return NULL;\r
- }\r
- op->m_ml = ml;\r
- Py_XINCREF(self);\r
- op->m_self = self;\r
- Py_XINCREF(module);\r
- op->m_module = module;\r
- _PyObject_GC_TRACK(op);\r
- return (PyObject *)op;\r
-}\r
-\r
-PyCFunction\r
-PyCFunction_GetFunction(PyObject *op)\r
-{\r
- if (!PyCFunction_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;\r
-}\r
-\r
-PyObject *\r
-PyCFunction_GetSelf(PyObject *op)\r
-{\r
- if (!PyCFunction_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- return ((PyCFunctionObject *)op) -> m_self;\r
-}\r
-\r
-int\r
-PyCFunction_GetFlags(PyObject *op)\r
-{\r
- if (!PyCFunction_Check(op)) {\r
- PyErr_BadInternalCall();\r
- return -1;\r
- }\r
- return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;\r
-}\r
-\r
-PyObject *\r
-PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)\r
-{\r
- PyCFunctionObject* f = (PyCFunctionObject*)func;\r
- PyCFunction meth = PyCFunction_GET_FUNCTION(func);\r
- PyObject *self = PyCFunction_GET_SELF(func);\r
- Py_ssize_t size;\r
-\r
- switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {\r
- case METH_VARARGS:\r
- if (kw == NULL || PyDict_Size(kw) == 0)\r
- return (*meth)(self, arg);\r
- break;\r
- case METH_VARARGS | METH_KEYWORDS:\r
- case METH_OLDARGS | METH_KEYWORDS:\r
- return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);\r
- case METH_NOARGS:\r
- if (kw == NULL || PyDict_Size(kw) == 0) {\r
- size = PyTuple_GET_SIZE(arg);\r
- if (size == 0)\r
- return (*meth)(self, NULL);\r
- PyErr_Format(PyExc_TypeError,\r
- "%.200s() takes no arguments (%zd given)",\r
- f->m_ml->ml_name, size);\r
- return NULL;\r
- }\r
- break;\r
- case METH_O:\r
- if (kw == NULL || PyDict_Size(kw) == 0) {\r
- size = PyTuple_GET_SIZE(arg);\r
- if (size == 1)\r
- return (*meth)(self, PyTuple_GET_ITEM(arg, 0));\r
- PyErr_Format(PyExc_TypeError,\r
- "%.200s() takes exactly one argument (%zd given)",\r
- f->m_ml->ml_name, size);\r
- return NULL;\r
- }\r
- break;\r
- case METH_OLDARGS:\r
- /* the really old style */\r
- if (kw == NULL || PyDict_Size(kw) == 0) {\r
- size = PyTuple_GET_SIZE(arg);\r
- if (size == 1)\r
- arg = PyTuple_GET_ITEM(arg, 0);\r
- else if (size == 0)\r
- arg = NULL;\r
- return (*meth)(self, arg);\r
- }\r
- break;\r
- default:\r
- PyErr_BadInternalCall();\r
- return NULL;\r
- }\r
- PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",\r
- f->m_ml->ml_name);\r
- return NULL;\r
-}\r
-\r
-/* Methods (the standard built-in methods, that is) */\r
-\r
-static void\r
-meth_dealloc(PyCFunctionObject *m)\r
-{\r
- _PyObject_GC_UNTRACK(m);\r
- Py_XDECREF(m->m_self);\r
- Py_XDECREF(m->m_module);\r
- if (numfree < PyCFunction_MAXFREELIST) {\r
- m->m_self = (PyObject *)free_list;\r
- free_list = m;\r
- numfree++;\r
- }\r
- else {\r
- PyObject_GC_Del(m);\r
- }\r
-}\r
-\r
-static PyObject *\r
-meth_get__doc__(PyCFunctionObject *m, void *closure)\r
-{\r
- const char *doc = m->m_ml->ml_doc;\r
-\r
- if (doc != NULL)\r
- return PyString_FromString(doc);\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-\r
-static PyObject *\r
-meth_get__name__(PyCFunctionObject *m, void *closure)\r
-{\r
- return PyString_FromString(m->m_ml->ml_name);\r
-}\r
-\r
-static int\r
-meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(m->m_self);\r
- Py_VISIT(m->m_module);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-meth_get__self__(PyCFunctionObject *m, void *closure)\r
-{\r
- PyObject *self;\r
- if (PyEval_GetRestricted()) {\r
- PyErr_SetString(PyExc_RuntimeError,\r
- "method.__self__ not accessible in restricted mode");\r
- return NULL;\r
- }\r
- self = m->m_self;\r
- if (self == NULL)\r
- self = Py_None;\r
- Py_INCREF(self);\r
- return self;\r
-}\r
-\r
-static PyGetSetDef meth_getsets [] = {\r
- {"__doc__", (getter)meth_get__doc__, NULL, NULL},\r
- {"__name__", (getter)meth_get__name__, NULL, NULL},\r
- {"__self__", (getter)meth_get__self__, NULL, NULL},\r
- {0}\r
-};\r
-\r
-#define OFF(x) offsetof(PyCFunctionObject, x)\r
-\r
-static PyMemberDef meth_members[] = {\r
- {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},\r
- {NULL}\r
-};\r
-\r
-static PyObject *\r
-meth_repr(PyCFunctionObject *m)\r
-{\r
- if (m->m_self == NULL)\r
- return PyString_FromFormat("<built-in function %s>",\r
- m->m_ml->ml_name);\r
- return PyString_FromFormat("<built-in method %s of %s object at %p>",\r
- m->m_ml->ml_name,\r
- m->m_self->ob_type->tp_name,\r
- m->m_self);\r
-}\r
-\r
-static int\r
-meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)\r
-{\r
- if (a->m_self != b->m_self)\r
- return (a->m_self < b->m_self) ? -1 : 1;\r
- if (a->m_ml->ml_meth == b->m_ml->ml_meth)\r
- return 0;\r
- if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)\r
- return -1;\r
- else\r
- return 1;\r
-}\r
-\r
-static PyObject *\r
-meth_richcompare(PyObject *self, PyObject *other, int op)\r
-{\r
- PyCFunctionObject *a, *b;\r
- PyObject *res;\r
- int eq;\r
-\r
- if (op != Py_EQ && op != Py_NE) {\r
- /* Py3K warning if comparison isn't == or !=. */\r
- if (PyErr_WarnPy3k("builtin_function_or_method order "\r
- "comparisons not supported in 3.x", 1) < 0) {\r
- return NULL;\r
- }\r
-\r
- Py_INCREF(Py_NotImplemented);\r
- return Py_NotImplemented;\r
- }\r
- else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {\r
- Py_INCREF(Py_NotImplemented);\r
- return Py_NotImplemented;\r
- }\r
- a = (PyCFunctionObject *)self;\r
- b = (PyCFunctionObject *)other;\r
- eq = a->m_self == b->m_self;\r
- if (eq)\r
- eq = a->m_ml->ml_meth == b->m_ml->ml_meth;\r
- if (op == Py_EQ)\r
- res = eq ? Py_True : Py_False;\r
- else\r
- res = eq ? Py_False : Py_True;\r
- Py_INCREF(res);\r
- return res;\r
-}\r
-\r
-static long\r
-meth_hash(PyCFunctionObject *a)\r
-{\r
- long x,y;\r
- if (a->m_self == NULL)\r
- x = 0;\r
- else {\r
- x = PyObject_Hash(a->m_self);\r
- if (x == -1)\r
- return -1;\r
- }\r
- y = _Py_HashPointer((void*)(a->m_ml->ml_meth));\r
- if (y == -1)\r
- return -1;\r
- x ^= y;\r
- if (x == -1)\r
- x = -2;\r
- return x;\r
-}\r
-\r
-\r
-PyTypeObject PyCFunction_Type = {\r
- PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
- "builtin_function_or_method",\r
- sizeof(PyCFunctionObject),\r
- 0,\r
- (destructor)meth_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- (cmpfunc)meth_compare, /* tp_compare */\r
- (reprfunc)meth_repr, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- (hashfunc)meth_hash, /* tp_hash */\r
- PyCFunction_Call, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
- 0, /* tp_doc */\r
- (traverseproc)meth_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- meth_richcompare, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- 0, /* tp_iter */\r
- 0, /* tp_iternext */\r
- 0, /* tp_methods */\r
- meth_members, /* tp_members */\r
- meth_getsets, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
-};\r
-\r
-/* List all methods in a chain -- helper for findmethodinchain */\r
-\r
-static PyObject *\r
-listmethodchain(PyMethodChain *chain)\r
-{\r
- PyMethodChain *c;\r
- PyMethodDef *ml;\r
- int i, n;\r
- PyObject *v;\r
-\r
- n = 0;\r
- for (c = chain; c != NULL; c = c->link) {\r
- for (ml = c->methods; ml->ml_name != NULL; ml++)\r
- n++;\r
- }\r
- v = PyList_New(n);\r
- if (v == NULL)\r
- return NULL;\r
- i = 0;\r
- for (c = chain; c != NULL; c = c->link) {\r
- for (ml = c->methods; ml->ml_name != NULL; ml++) {\r
- PyList_SetItem(v, i, PyString_FromString(ml->ml_name));\r
- i++;\r
- }\r
- }\r
- if (PyErr_Occurred()) {\r
- Py_DECREF(v);\r
- return NULL;\r
- }\r
- PyList_Sort(v);\r
- return v;\r
-}\r
-\r
-/* Find a method in a method chain */\r
-\r
-PyObject *\r
-Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)\r
-{\r
- if (name[0] == '_' && name[1] == '_') {\r
- if (strcmp(name, "__methods__") == 0) {\r
- if (PyErr_WarnPy3k("__methods__ not supported in 3.x",\r
- 1) < 0)\r
- return NULL;\r
- return listmethodchain(chain);\r
- }\r
- if (strcmp(name, "__doc__") == 0) {\r
- const char *doc = self->ob_type->tp_doc;\r
- if (doc != NULL)\r
- return PyString_FromString(doc);\r
- }\r
- }\r
- while (chain != NULL) {\r
- PyMethodDef *ml = chain->methods;\r
- for (; ml->ml_name != NULL; ml++) {\r
- if (name[0] == ml->ml_name[0] &&\r
- strcmp(name+1, ml->ml_name+1) == 0)\r
- /* XXX */\r
- return PyCFunction_New(ml, self);\r
- }\r
- chain = chain->link;\r
- }\r
- PyErr_SetString(PyExc_AttributeError, name);\r
- return NULL;\r
-}\r
-\r
-/* Find a method in a single method list */\r
-\r
-PyObject *\r
-Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)\r
-{\r
- PyMethodChain chain;\r
- chain.methods = methods;\r
- chain.link = NULL;\r
- return Py_FindMethodInChain(&chain, self, name);\r
-}\r
-\r
-/* Clear out the free list */\r
-\r
-int\r
-PyCFunction_ClearFreeList(void)\r
-{\r
- int freelist_size = numfree;\r
-\r
- while (free_list) {\r
- PyCFunctionObject *v = free_list;\r
- free_list = (PyCFunctionObject *)(v->m_self);\r
- PyObject_GC_Del(v);\r
- numfree--;\r
- }\r
- assert(numfree == 0);\r
- return freelist_size;\r
-}\r
-\r
-void\r
-PyCFunction_Fini(void)\r
-{\r
- (void)PyCFunction_ClearFreeList();\r
-}\r
-\r
-/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),\r
- but it's part of the API so we need to keep a function around that\r
- existing C extensions can call.\r
-*/\r
-\r
-#undef PyCFunction_New\r
-PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);\r
-\r
-PyObject *\r
-PyCFunction_New(PyMethodDef *ml, PyObject *self)\r
-{\r
- return PyCFunction_NewEx(ml, self, NULL);\r
-}\r