New \grammartoken markup, similar to \token but allowed everywhere.
[python/dscho.git] / Objects / methodobject.c
blobcdba3505f9b0426e4accf85ca7c083b537595e7e
2 /* Method object implementation */
4 #include "Python.h"
6 static PyCFunctionObject *free_list = NULL;
8 PyObject *
9 PyCFunction_New(PyMethodDef *ml, PyObject *self)
11 PyCFunctionObject *op;
12 op = free_list;
13 if (op != NULL) {
14 free_list = (PyCFunctionObject *)(op->m_self);
15 PyObject_INIT(op, &PyCFunction_Type);
17 else {
18 op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
19 if (op == NULL)
20 return NULL;
22 op->m_ml = ml;
23 Py_XINCREF(self);
24 op->m_self = self;
25 PyObject_GC_Init(op);
26 return (PyObject *)op;
29 PyCFunction
30 PyCFunction_GetFunction(PyObject *op)
32 if (!PyCFunction_Check(op)) {
33 PyErr_BadInternalCall();
34 return NULL;
36 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
39 PyObject *
40 PyCFunction_GetSelf(PyObject *op)
42 if (!PyCFunction_Check(op)) {
43 PyErr_BadInternalCall();
44 return NULL;
46 return ((PyCFunctionObject *)op) -> m_self;
49 int
50 PyCFunction_GetFlags(PyObject *op)
52 if (!PyCFunction_Check(op)) {
53 PyErr_BadInternalCall();
54 return -1;
56 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
59 PyObject *
60 PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
62 PyCFunctionObject* f = (PyCFunctionObject*)func;
63 PyCFunction meth = PyCFunction_GET_FUNCTION(func);
64 PyObject *self = PyCFunction_GET_SELF(func);
65 int flags = PyCFunction_GET_FLAGS(func);
66 int size = PyTuple_GET_SIZE(arg);
68 if (flags & METH_KEYWORDS) {
69 return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
71 if (kw != NULL && PyDict_Size(kw) != 0) {
72 PyErr_Format(PyExc_TypeError,
73 "%.200s() takes no keyword arguments",
74 f->m_ml->ml_name);
75 return NULL;
78 switch (flags) {
79 case METH_VARARGS:
80 return (*meth)(self, arg);
81 break;
82 case METH_NOARGS:
83 if (size == 0)
84 return (*meth)(self, NULL);
85 PyErr_Format(PyExc_TypeError,
86 "%.200s() takes no arguments (%d given)",
87 f->m_ml->ml_name, size);
88 return NULL;
89 break;
90 case METH_O:
91 if (size == 1)
92 return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
93 PyErr_Format(PyExc_TypeError,
94 "%.200s() takes exactly one argument (%d given)",
95 f->m_ml->ml_name, size);
96 return NULL;
97 break;
98 case METH_OLDARGS:
99 /* the really old style */
100 if (size == 1)
101 arg = PyTuple_GET_ITEM(arg, 0);
102 else if (size == 0)
103 arg = NULL;
104 return (*meth)(self, arg);
105 default:
106 /* should never get here ??? */
107 PyErr_BadInternalCall();
108 return NULL;
112 /* Methods (the standard built-in methods, that is) */
114 static void
115 meth_dealloc(PyCFunctionObject *m)
117 PyObject_GC_Fini(m);
118 Py_XDECREF(m->m_self);
119 m->m_self = (PyObject *)free_list;
120 free_list = m;
123 static PyObject *
124 meth_get__doc__(PyCFunctionObject *m, void *closure)
126 char *doc = m->m_ml->ml_doc;
128 if (doc != NULL)
129 return PyString_FromString(doc);
130 Py_INCREF(Py_None);
131 return Py_None;
134 static PyObject *
135 meth_get__name__(PyCFunctionObject *m, void *closure)
137 return PyString_FromString(m->m_ml->ml_name);
140 static int
141 meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
143 if (m->m_self != NULL)
144 return visit(m->m_self, arg);
145 else
146 return 0;
149 static PyObject *
150 meth_get__self__(PyCFunctionObject *m, void *closure)
152 PyObject *self;
153 if (PyEval_GetRestricted()) {
154 PyErr_SetString(PyExc_RuntimeError,
155 "method.__self__ not accessible in restricted mode");
156 return NULL;
158 self = m->m_self;
159 if (self == NULL)
160 self = Py_None;
161 Py_INCREF(self);
162 return self;
165 static struct getsetlist meth_getsets [] = {
166 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
167 {"__name__", (getter)meth_get__name__, NULL, NULL},
168 {"__self__", (getter)meth_get__self__, NULL, NULL},
172 static PyObject *
173 meth_repr(PyCFunctionObject *m)
175 char buf[200];
176 if (m->m_self == NULL)
177 sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
178 else
179 sprintf(buf,
180 "<built-in method %.80s of %.80s object at %p>",
181 m->m_ml->ml_name, m->m_self->ob_type->tp_name,
182 m->m_self);
183 return PyString_FromString(buf);
186 static int
187 meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
189 if (a->m_self != b->m_self)
190 return (a->m_self < b->m_self) ? -1 : 1;
191 if (a->m_ml->ml_meth == b->m_ml->ml_meth)
192 return 0;
193 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
194 return -1;
195 else
196 return 1;
199 static long
200 meth_hash(PyCFunctionObject *a)
202 long x,y;
203 if (a->m_self == NULL)
204 x = 0;
205 else {
206 x = PyObject_Hash(a->m_self);
207 if (x == -1)
208 return -1;
210 y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
211 if (y == -1)
212 return -1;
213 x ^= y;
214 if (x == -1)
215 x = -2;
216 return x;
220 PyTypeObject PyCFunction_Type = {
221 PyObject_HEAD_INIT(&PyType_Type)
223 "builtin_function_or_method",
224 sizeof(PyCFunctionObject) + PyGC_HEAD_SIZE,
226 (destructor)meth_dealloc, /* tp_dealloc */
227 0, /* tp_print */
228 0, /* tp_getattr */
229 0, /* tp_setattr */
230 (cmpfunc)meth_compare, /* tp_compare */
231 (reprfunc)meth_repr, /* tp_repr */
232 0, /* tp_as_number */
233 0, /* tp_as_sequence */
234 0, /* tp_as_mapping */
235 (hashfunc)meth_hash, /* tp_hash */
236 PyCFunction_Call, /* tp_call */
237 0, /* tp_str */
238 PyObject_GenericGetAttr, /* tp_getattro */
239 0, /* tp_setattro */
240 0, /* tp_as_buffer */
241 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
242 0, /* tp_doc */
243 (traverseproc)meth_traverse, /* tp_traverse */
244 0, /* tp_clear */
245 0, /* tp_richcompare */
246 0, /* tp_weaklistoffset */
247 0, /* tp_iter */
248 0, /* tp_iternext */
249 0, /* tp_methods */
250 0, /* tp_members */
251 meth_getsets, /* tp_getset */
252 0, /* tp_base */
253 0, /* tp_dict */
256 /* List all methods in a chain -- helper for findmethodinchain */
258 static PyObject *
259 listmethodchain(PyMethodChain *chain)
261 PyMethodChain *c;
262 PyMethodDef *ml;
263 int i, n;
264 PyObject *v;
266 n = 0;
267 for (c = chain; c != NULL; c = c->link) {
268 for (ml = c->methods; ml->ml_name != NULL; ml++)
269 n++;
271 v = PyList_New(n);
272 if (v == NULL)
273 return NULL;
274 i = 0;
275 for (c = chain; c != NULL; c = c->link) {
276 for (ml = c->methods; ml->ml_name != NULL; ml++) {
277 PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
278 i++;
281 if (PyErr_Occurred()) {
282 Py_DECREF(v);
283 return NULL;
285 PyList_Sort(v);
286 return v;
289 /* Find a method in a method chain */
291 PyObject *
292 Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name)
294 if (name[0] == '_' && name[1] == '_') {
295 if (strcmp(name, "__methods__") == 0)
296 return listmethodchain(chain);
297 if (strcmp(name, "__doc__") == 0) {
298 char *doc = self->ob_type->tp_doc;
299 if (doc != NULL)
300 return PyString_FromString(doc);
303 while (chain != NULL) {
304 PyMethodDef *ml = chain->methods;
305 for (; ml->ml_name != NULL; ml++) {
306 if (name[0] == ml->ml_name[0] &&
307 strcmp(name+1, ml->ml_name+1) == 0)
308 return PyCFunction_New(ml, self);
310 chain = chain->link;
312 PyErr_SetString(PyExc_AttributeError, name);
313 return NULL;
316 /* Find a method in a single method list */
318 PyObject *
319 Py_FindMethod(PyMethodDef *methods, PyObject *self, char *name)
321 PyMethodChain chain;
322 chain.methods = methods;
323 chain.link = NULL;
324 return Py_FindMethodInChain(&chain, self, name);
327 /* Clear out the free list */
329 void
330 PyCFunction_Fini(void)
332 while (free_list) {
333 PyCFunctionObject *v = free_list;
334 free_list = (PyCFunctionObject *)(v->m_self);
335 v = (PyCFunctionObject *) PyObject_AS_GC(v);
336 PyObject_DEL(v);