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