History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Objects/methodobject.c (1 of 3706 files). Show all

Unified · Split

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