1 2/* Method object implementation */ 3 4#include "Python.h" 5#include "structmember.h" 6 7/* Free list for method objects to safe malloc/free overhead 8 * The m_self element is used to chain the objects. 9 */ 10static PyCFunctionObject *free_list = NULL; 11static int numfree = 0; 12#ifndef PyCFunction_MAXFREELIST 13#define PyCFunction_MAXFREELIST 256 14#endif 15 16PyObject * 17PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) 18{ 19 PyCFunctionObject *op; 20 op = free_list; 21 if (op != NULL) { 22 free_list = (PyCFunctionObject *)(op->m_self); 23 PyObject_INIT(op, &PyCFunction_Type); 24 numfree--; 25 } 26 else { 27 op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); 28 if (op == NULL) 29 return NULL; 30 } 31 op->m_ml = ml; 32 Py_XINCREF(self); 33 op->m_self = self; 34 Py_XINCREF(module); 35 op->m_module = module; 36 _PyObject_GC_TRACK(op); 37 return (PyObject *)op; 38} 39 40PyCFunction 41PyCFunction_GetFunction(PyObject *op) 42{ 43 if (!PyCFunction_Check(op)) { 44 PyErr_BadInternalCall(); 45 return NULL; 46 } 47 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth; 48} 49 50PyObject * 51PyCFunction_GetSelf(PyObject *op) 52{ 53 if (!PyCFunction_Check(op)) { 54 PyErr_BadInternalCall(); 55 return NULL; 56 } 57 return ((PyCFunctionObject *)op) -> m_self; 58} 59 60int 61PyCFunction_GetFlags(PyObject *op) 62{ 63 if (!PyCFunction_Check(op)) { 64 PyErr_BadInternalCall(); 65 return -1; 66 } 67 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags; 68} 69 70PyObject * 71PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) 72{ 73 PyCFunctionObject* f = (PyCFunctionObject*)func; 74 PyCFunction meth = PyCFunction_GET_FUNCTION(func); 75 PyObject *self = PyCFunction_GET_SELF(func); 76 Py_ssize_t size; 77 78 switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { 79 case METH_VARARGS: 80 if (kw == NULL || PyDict_Size(kw) == 0) 81 return (*meth)(self, arg); 82 break; 83 case METH_VARARGS | METH_KEYWORDS: 84 case METH_OLDARGS | METH_KEYWORDS: 85 return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); 86 case METH_NOARGS: 87 if (kw == NULL || PyDict_Size(kw) == 0) { 88 size = PyTuple_GET_SIZE(arg); 89 if (size == 0) 90 return (*meth)(self, NULL); 91 PyErr_Format(PyExc_TypeError, 92 "%.200s() takes no arguments (%zd given)", 93 f->m_ml->ml_name, size); 94 return NULL; 95 } 96 break; 97 case METH_O: 98 if (kw == NULL || PyDict_Size(kw) == 0) { 99 size = PyTuple_GET_SIZE(arg); 100 if (size == 1) 101 return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); 102 PyErr_Format(PyExc_TypeError, 103 "%.200s() takes exactly one argument (%zd given)", 104 f->m_ml->ml_name, size); 105 return NULL; 106 } 107 break; 108 case METH_OLDARGS: 109 /* the really old style */ 110 if (kw == NULL || PyDict_Size(kw) == 0) { 111 size = PyTuple_GET_SIZE(arg); 112 if (size == 1) 113 arg = PyTuple_GET_ITEM(arg, 0); 114 else if (size == 0) 115 arg = NULL; 116 return (*meth)(self, arg); 117 } 118 break; 119 default: 120 PyErr_BadInternalCall(); 121 return NULL; 122 } 123 PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", 124 f->m_ml->ml_name); 125 return NULL; 126} 127 128/* Methods (the standard built-in methods, that is) */ 129 130static void 131meth_dealloc(PyCFunctionObject *m) 132{ 133 _PyObject_GC_UNTRACK(m); 134 Py_XDECREF(m->m_self); 135 Py_XDECREF(m->m_module); 136 if (numfree < PyCFunction_MAXFREELIST) { 137 m->m_self = (PyObject *)free_list; 138 free_list = m; 139 numfree++; 140 } 141 else { 142 PyObject_GC_Del(m); 143 } 144} 145 146static PyObject * 147meth_get__doc__(PyCFunctionObject *m, void *closure) 148{ 149 const char *doc = m->m_ml->ml_doc; 150 151 if (doc != NULL) 152 return PyString_FromString(doc); 153 Py_INCREF(Py_None); 154 return Py_None; 155} 156 157static PyObject * 158meth_get__name__(PyCFunctionObject *m, void *closure) 159{ 160 return PyString_FromString(m->m_ml->ml_name); 161} 162 163static int 164meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) 165{ 166 Py_VISIT(m->m_self); 167 Py_VISIT(m->m_module); 168 return 0; 169} 170 171static PyObject * 172meth_get__self__(PyCFunctionObject *m, void *closure) 173{ 174 PyObject *self; 175 if (PyEval_GetRestricted()) { 176 PyErr_SetString(PyExc_RuntimeError, 177 "method.__self__ not accessible in restricted mode"); 178 return NULL; 179 } 180 self = m->m_self; 181 if (self == NULL) 182 self = Py_None; 183 Py_INCREF(self); 184 return self; 185} 186 187static PyGetSetDef meth_getsets [] = { 188 {"__doc__", (getter)meth_get__doc__, NULL, NULL}, 189 {"__name__", (getter)meth_get__name__, NULL, NULL}, 190 {"__self__", (getter)meth_get__self__, NULL, NULL}, 191 {0} 192}; 193 194#define OFF(x) offsetof(PyCFunctionObject, x) 195 196static PyMemberDef meth_members[] = { 197 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED}, 198 {NULL} 199}; 200 201static PyObject * 202meth_repr(PyCFunctionObject *m) 203{ 204 if (m->m_self == NULL) 205 return PyString_FromFormat("<built-in function %s>", 206 m->m_ml->ml_name); 207 return PyString_FromFormat("<built-in method %s of %s object at %p>", 208 m->m_ml->ml_name, 209 m->m_self->ob_type->tp_name, 210 m->m_self); 211} 212 213static int 214meth_compare(PyCFunctionObject *a, PyCFunctionObject *b) 215{ 216 if (a->m_self != b->m_self) 217 return (a->m_self < b->m_self) ? -1 : 1; 218 if (a->m_ml->ml_meth == b->m_ml->ml_meth) 219 return 0; 220 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0) 221 return -1; 222 else 223 return 1; 224} 225 226static PyObject * 227meth_richcompare(PyObject *self, PyObject *other, int op) 228{ 229 PyCFunctionObject *a, *b; 230 PyObject *res; 231 int eq; 232 233 if (op != Py_EQ && op != Py_NE) { 234 /* Py3K warning if comparison isn't == or !=. */ 235 if (PyErr_WarnPy3k("builtin_function_or_method order " 236 "comparisons not supported in 3.x", 1) < 0) { 237 return NULL; 238 } 239 240 Py_INCREF(Py_NotImplemented); 241 return Py_NotImplemented; 242 } 243 else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) { 244 Py_INCREF(Py_NotImplemented); 245 return Py_NotImplemented; 246 } 247 a = (PyCFunctionObject *)self; 248 b = (PyCFunctionObject *)other; 249 eq = a->m_self == b->m_self; 250 if (eq) 251 eq = a->m_ml->ml_meth == b->m_ml->ml_meth; 252 if (op == Py_EQ) 253 res = eq ? Py_True : Py_False; 254 else 255 res = eq ? Py_False : Py_True; 256 Py_INCREF(res); 257 return res; 258} 259 260static long 261meth_hash(PyCFunctionObject *a) 262{ 263 long x,y; 264 if (a->m_self == NULL) 265 x = 0; 266 else { 267 x = PyObject_Hash(a->m_self); 268 if (x == -1) 269 return -1; 270 } 271 y = _Py_HashPointer((void*)(a->m_ml->ml_meth)); 272 if (y == -1) 273 return -1; 274 x ^= y; 275 if (x == -1) 276 x = -2; 277 return x; 278} 279 280 281PyTypeObject PyCFunction_Type = { 282 PyVarObject_HEAD_INIT(&PyType_Type, 0) 283 "builtin_function_or_method", 284 sizeof(PyCFunctionObject), 285 0, 286 (destructor)meth_dealloc, /* tp_dealloc */ 287 0, /* tp_print */ 288 0, /* tp_getattr */ 289 0, /* tp_setattr */ 290 (cmpfunc)meth_compare, /* tp_compare */ 291 (reprfunc)meth_repr, /* tp_repr */ 292 0, /* tp_as_number */ 293 0, /* tp_as_sequence */ 294 0, /* tp_as_mapping */ 295 (hashfunc)meth_hash, /* tp_hash */ 296 PyCFunction_Call, /* tp_call */ 297 0, /* tp_str */ 298 PyObject_GenericGetAttr, /* tp_getattro */ 299 0, /* tp_setattro */ 300 0, /* tp_as_buffer */ 301 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 302 0, /* tp_doc */ 303 (traverseproc)meth_traverse, /* tp_traverse */ 304 0, /* tp_clear */ 305 meth_richcompare, /* tp_richcompare */ 306 0, /* tp_weaklistoffset */ 307 0, /* tp_iter */ 308 0, /* tp_iternext */ 309 0, /* tp_methods */ 310 meth_members, /* tp_members */ 311 meth_getsets, /* tp_getset */ 312 0, /* tp_base */ 313 0, /* tp_dict */ 314}; 315 316/* List all methods in a chain -- helper for findmethodinchain */ 317 318static PyObject * 319listmethodchain(PyMethodChain *chain) 320{ 321 PyMethodChain *c; 322 PyMethodDef *ml; 323 int i, n; 324 PyObject *v; 325 326 n = 0; 327 for (c = chain; c != NULL; c = c->link) { 328 for (ml = c->methods; ml->ml_name != NULL; ml++) 329 n++; 330 } 331 v = PyList_New(n); 332 if (v == NULL) 333 return NULL; 334 i = 0; 335 for (c = chain; c != NULL; c = c->link) { 336 for (ml = c->methods; ml->ml_name != NULL; ml++) { 337 PyList_SetItem(v, i, PyString_FromString(ml->ml_name)); 338 i++; 339 } 340 } 341 if (PyErr_Occurred()) { 342 Py_DECREF(v); 343 return NULL; 344 } 345 PyList_Sort(v); 346 return v; 347} 348 349/* Find a method in a method chain */ 350 351PyObject * 352Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name) 353{ 354 if (name[0] == '_' && name[1] == '_') { 355 if (strcmp(name, "__methods__") == 0) { 356 if (PyErr_WarnPy3k("__methods__ not supported in 3.x", 357 1) < 0) 358 return NULL; 359 return listmethodchain(chain); 360 } 361 if (strcmp(name, "__doc__") == 0) { 362 const char *doc = self->ob_type->tp_doc; 363 if (doc != NULL) 364 return PyString_FromString(doc); 365 } 366 } 367 while (chain != NULL) { 368 PyMethodDef *ml = chain->methods; 369 for (; ml->ml_name != NULL; ml++) { 370 if (name[0] == ml->ml_name[0] && 371 strcmp(name+1, ml->ml_name+1) == 0) 372 /* XXX */ 373 return PyCFunction_New(ml, self); 374 } 375 chain = chain->link; 376 } 377 PyErr_SetString(PyExc_AttributeError, name); 378 return NULL; 379} 380 381/* Find a method in a single method list */ 382 383PyObject * 384Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name) 385{ 386 PyMethodChain chain; 387 chain.methods = methods; 388 chain.link = NULL; 389 return Py_FindMethodInChain(&chain, self, name); 390} 391 392/* Clear out the free list */ 393 394int 395PyCFunction_ClearFreeList(void) 396{ 397 int freelist_size = numfree; 398 399 while (free_list) { 400 PyCFunctionObject *v = free_list; 401 free_list = (PyCFunctionObject *)(v->m_self); 402 PyObject_GC_Del(v); 403 numfree--; 404 } 405 assert(numfree == 0); 406 return freelist_size; 407} 408 409void 410PyCFunction_Fini(void) 411{ 412 (void)PyCFunction_ClearFreeList(); 413} 414 415/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(), 416 but it's part of the API so we need to keep a function around that 417 existing C extensions can call. 418*/ 419 420#undef PyCFunction_New 421PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); 422 423PyObject * 424PyCFunction_New(PyMethodDef *ml, PyObject *self) 425{ 426 return PyCFunction_NewEx(ml, self, NULL); 427} 428