PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/src/utils/python/python26/Objects/methodobject.c

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