blob: bff79ed042df4076b90eac10855039f4b19ad005 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00002/* Method object implementation */
3
Guido van Rossumc0b618a1997-05-02 03:12:38 +00004#include "Python.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00005
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00006#include "token.h"
7
Guido van Rossum1f39c5c1997-08-05 02:11:41 +00008static PyCFunctionObject *free_list = NULL;
9
Guido van Rossumc0b618a1997-05-02 03:12:38 +000010PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +000011PyCFunction_New(PyMethodDef *ml, PyObject *self)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000012{
Guido van Rossum1f39c5c1997-08-05 02:11:41 +000013 PyCFunctionObject *op;
14 op = free_list;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000015 if (op != NULL) {
Guido van Rossum1f39c5c1997-08-05 02:11:41 +000016 free_list = (PyCFunctionObject *)(op->m_self);
Guido van Rossumb18618d2000-05-03 23:44:39 +000017 PyObject_INIT(op, &PyCFunction_Type);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000018 }
Guido van Rossum1f39c5c1997-08-05 02:11:41 +000019 else {
20 op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
21 if (op == NULL)
22 return NULL;
23 }
24 op->m_ml = ml;
25 Py_XINCREF(self);
26 op->m_self = self;
Neil Schemenauer10c66922001-07-12 13:27:35 +000027 PyObject_GC_Init(op);
Guido van Rossumc0b618a1997-05-02 03:12:38 +000028 return (PyObject *)op;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000029}
30
Guido van Rossumc0b618a1997-05-02 03:12:38 +000031PyCFunction
Fred Drakeee238b92000-07-09 06:03:25 +000032PyCFunction_GetFunction(PyObject *op)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000033{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000034 if (!PyCFunction_Check(op)) {
35 PyErr_BadInternalCall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036 return NULL;
37 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +000038 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039}
40
Guido van Rossumc0b618a1997-05-02 03:12:38 +000041PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +000042PyCFunction_GetSelf(PyObject *op)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000044 if (!PyCFunction_Check(op)) {
45 PyErr_BadInternalCall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000046 return NULL;
47 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +000048 return ((PyCFunctionObject *)op) -> m_self;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000049}
50
Guido van Rossumc0602291991-12-16 13:07:24 +000051int
Fred Drakeee238b92000-07-09 06:03:25 +000052PyCFunction_GetFlags(PyObject *op)
Guido van Rossumc0602291991-12-16 13:07:24 +000053{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000054 if (!PyCFunction_Check(op)) {
55 PyErr_BadInternalCall();
Guido van Rossumc0602291991-12-16 13:07:24 +000056 return -1;
57 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +000058 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
Guido van Rossumc0602291991-12-16 13:07:24 +000059}
60
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000061/* Methods (the standard built-in methods, that is) */
62
63static void
Fred Drakeee238b92000-07-09 06:03:25 +000064meth_dealloc(PyCFunctionObject *m)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000065{
Neil Schemenauer10c66922001-07-12 13:27:35 +000066 PyObject_GC_Fini(m);
Guido van Rossumc0b618a1997-05-02 03:12:38 +000067 Py_XDECREF(m->m_self);
Guido van Rossum1f39c5c1997-08-05 02:11:41 +000068 m->m_self = (PyObject *)free_list;
69 free_list = m;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000070}
71
Neil Schemenauer10c66922001-07-12 13:27:35 +000072static int
73meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
74{
75 if (m->m_self != NULL)
76 return visit(m->m_self, arg);
77 else
78 return 0;
79}
80
Guido van Rossumc0b618a1997-05-02 03:12:38 +000081static PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +000082meth_getattr(PyCFunctionObject *m, char *name)
Guido van Rossumcab650d1995-01-07 12:34:58 +000083{
84 if (strcmp(name, "__name__") == 0) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000085 return PyString_FromString(m->m_ml->ml_name);
Guido van Rossumcab650d1995-01-07 12:34:58 +000086 }
87 if (strcmp(name, "__doc__") == 0) {
88 char *doc = m->m_ml->ml_doc;
89 if (doc != NULL)
Guido van Rossumc0b618a1997-05-02 03:12:38 +000090 return PyString_FromString(doc);
91 Py_INCREF(Py_None);
92 return Py_None;
Guido van Rossumcab650d1995-01-07 12:34:58 +000093 }
94 if (strcmp(name, "__self__") == 0) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000095 PyObject *self;
96 if (PyEval_GetRestricted()) {
97 PyErr_SetString(PyExc_RuntimeError,
Guido van Rossum10393b11995-01-10 10:39:49 +000098 "method.__self__ not accessible in restricted mode");
99 return NULL;
100 }
101 self = m->m_self;
Guido van Rossumcab650d1995-01-07 12:34:58 +0000102 if (self == NULL)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000103 self = Py_None;
104 Py_INCREF(self);
Guido van Rossumcab650d1995-01-07 12:34:58 +0000105 return self;
106 }
107 if (strcmp(name, "__members__") == 0) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000108 return Py_BuildValue("[sss]",
109 "__doc__", "__name__", "__self__");
Guido van Rossumcab650d1995-01-07 12:34:58 +0000110 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000111 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossumcab650d1995-01-07 12:34:58 +0000112 return NULL;
113}
114
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000115static PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +0000116meth_repr(PyCFunctionObject *m)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000117{
118 char buf[200];
119 if (m->m_self == NULL)
Guido van Rossumcab650d1995-01-07 12:34:58 +0000120 sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000121 else
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122 sprintf(buf,
Fred Drakea44d3532000-06-30 15:01:00 +0000123 "<built-in method %.80s of %.80s object at %p>",
Guido van Rossumcab650d1995-01-07 12:34:58 +0000124 m->m_ml->ml_name, m->m_self->ob_type->tp_name,
Fred Drakea44d3532000-06-30 15:01:00 +0000125 m->m_self);
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000126 return PyString_FromString(buf);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000127}
128
Guido van Rossum9bfef441993-03-29 10:43:31 +0000129static int
Fred Drakeee238b92000-07-09 06:03:25 +0000130meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
Guido van Rossum9bfef441993-03-29 10:43:31 +0000131{
132 if (a->m_self != b->m_self)
Guido van Rossum13fdf5e1998-12-04 18:52:55 +0000133 return (a->m_self < b->m_self) ? -1 : 1;
Guido van Rossumcab650d1995-01-07 12:34:58 +0000134 if (a->m_ml->ml_meth == b->m_ml->ml_meth)
Guido van Rossum9bfef441993-03-29 10:43:31 +0000135 return 0;
Guido van Rossumcab650d1995-01-07 12:34:58 +0000136 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
Guido van Rossum9bfef441993-03-29 10:43:31 +0000137 return -1;
138 else
139 return 1;
140}
141
142static long
Fred Drakeee238b92000-07-09 06:03:25 +0000143meth_hash(PyCFunctionObject *a)
Guido van Rossum9bfef441993-03-29 10:43:31 +0000144{
Fred Drake13634cf2000-06-29 19:17:04 +0000145 long x,y;
Guido van Rossum9bfef441993-03-29 10:43:31 +0000146 if (a->m_self == NULL)
147 x = 0;
148 else {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000149 x = PyObject_Hash(a->m_self);
Guido van Rossum9bfef441993-03-29 10:43:31 +0000150 if (x == -1)
151 return -1;
152 }
Guido van Rossum9a15c212000-06-30 22:46:04 +0000153 y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
Fred Drake13634cf2000-06-29 19:17:04 +0000154 if (y == -1)
155 return -1;
156 x ^= y;
157 if (x == -1)
158 x = -2;
159 return x;
Guido van Rossum9bfef441993-03-29 10:43:31 +0000160}
161
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000162PyTypeObject PyCFunction_Type = {
163 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000164 0,
Guido van Rossum7066dd71992-09-17 17:54:56 +0000165 "builtin_function_or_method",
Neil Schemenauer10c66922001-07-12 13:27:35 +0000166 sizeof(PyCFunctionObject) + PyGC_HEAD_SIZE,
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 0,
Neil Schemenauer10c66922001-07-12 13:27:35 +0000168 (destructor)meth_dealloc, /* tp_dealloc */
169 0, /* tp_print */
170 (getattrfunc)meth_getattr, /* tp_getattr */
171 0, /* tp_setattr */
172 (cmpfunc)meth_compare, /* tp_compare */
173 (reprfunc)meth_repr, /* tp_repr */
174 0, /* tp_as_number */
175 0, /* tp_as_sequence */
176 0, /* tp_as_mapping */
177 (hashfunc)meth_hash, /* tp_hash */
178 0, /* tp_call */
179 0, /* tp_str */
180 0, /* tp_getattro */
181 0, /* tp_setattro */
182 0, /* tp_as_buffer */
183 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
184 0, /* tp_doc */
185 (traverseproc)meth_traverse, /* tp_traverse */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186};
Guido van Rossum3f5da241990-12-20 15:06:42 +0000187
Guido van Rossum69785031995-01-26 22:58:48 +0000188/* List all methods in a chain -- helper for findmethodinchain */
Guido van Rossume9c430f1991-10-20 20:21:15 +0000189
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000190static PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +0000191listmethodchain(PyMethodChain *chain)
Guido van Rossume9c430f1991-10-20 20:21:15 +0000192{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000193 PyMethodChain *c;
194 PyMethodDef *ml;
Guido van Rossume9c430f1991-10-20 20:21:15 +0000195 int i, n;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000196 PyObject *v;
Guido van Rossum69785031995-01-26 22:58:48 +0000197
198 n = 0;
199 for (c = chain; c != NULL; c = c->link) {
200 for (ml = c->methods; ml->ml_name != NULL; ml++)
201 n++;
202 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000203 v = PyList_New(n);
Guido van Rossum69785031995-01-26 22:58:48 +0000204 if (v == NULL)
205 return NULL;
206 i = 0;
207 for (c = chain; c != NULL; c = c->link) {
208 for (ml = c->methods; ml->ml_name != NULL; ml++) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000209 PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
Guido van Rossum69785031995-01-26 22:58:48 +0000210 i++;
Guido van Rossume9c430f1991-10-20 20:21:15 +0000211 }
212 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000213 if (PyErr_Occurred()) {
214 Py_DECREF(v);
Guido van Rossum69785031995-01-26 22:58:48 +0000215 return NULL;
216 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000217 PyList_Sort(v);
Guido van Rossume9c430f1991-10-20 20:21:15 +0000218 return v;
219}
220
Guido van Rossum69785031995-01-26 22:58:48 +0000221/* Find a method in a method chain */
Guido van Rossum3f5da241990-12-20 15:06:42 +0000222
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000223PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +0000224Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000225{
Guido van Rossum8a92c621998-06-27 18:28:59 +0000226 if (name[0] == '_' && name[1] == '_') {
227 if (strcmp(name, "__methods__") == 0)
228 return listmethodchain(chain);
229 if (strcmp(name, "__doc__") == 0) {
230 char *doc = self->ob_type->tp_doc;
231 if (doc != NULL)
232 return PyString_FromString(doc);
233 }
234 }
Guido van Rossum69785031995-01-26 22:58:48 +0000235 while (chain != NULL) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000236 PyMethodDef *ml = chain->methods;
Guido van Rossum69785031995-01-26 22:58:48 +0000237 for (; ml->ml_name != NULL; ml++) {
238 if (name[0] == ml->ml_name[0] &&
239 strcmp(name+1, ml->ml_name+1) == 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000240 return PyCFunction_New(ml, self);
Guido van Rossum69785031995-01-26 22:58:48 +0000241 }
242 chain = chain->link;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000243 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000244 PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000245 return NULL;
246}
Guido van Rossum69785031995-01-26 22:58:48 +0000247
248/* Find a method in a single method list */
249
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000250PyObject *
Fred Drakeee238b92000-07-09 06:03:25 +0000251Py_FindMethod(PyMethodDef *methods, PyObject *self, char *name)
Guido van Rossum69785031995-01-26 22:58:48 +0000252{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000253 PyMethodChain chain;
Guido van Rossum69785031995-01-26 22:58:48 +0000254 chain.methods = methods;
255 chain.link = NULL;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000256 return Py_FindMethodInChain(&chain, self, name);
Guido van Rossum69785031995-01-26 22:58:48 +0000257}
Guido van Rossum1f39c5c1997-08-05 02:11:41 +0000258
259/* Clear out the free list */
260
261void
Fred Drakeee238b92000-07-09 06:03:25 +0000262PyCFunction_Fini(void)
Guido van Rossum1f39c5c1997-08-05 02:11:41 +0000263{
264 while (free_list) {
265 PyCFunctionObject *v = free_list;
266 free_list = (PyCFunctionObject *)(v->m_self);
Neil Schemenauer10c66922001-07-12 13:27:35 +0000267 v = (PyCFunctionObject *) PyObject_AS_GC(v);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000268 PyObject_DEL(v);
Guido van Rossum1f39c5c1997-08-05 02:11:41 +0000269 }
270}