The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Objects / methodobject.c
blob5c69744b7bf21096008be7f70c2b08f0b82183ed
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Method object implementation */
34 #include "Python.h"
36 #include "token.h"
38 static PyCFunctionObject *free_list = NULL;
40 PyObject *
41 PyCFunction_New(ml, self)
42 PyMethodDef *ml;
43 PyObject *self;
45 PyCFunctionObject *op;
46 op = free_list;
47 if (op != NULL) {
48 free_list = (PyCFunctionObject *)(op->m_self);
49 op->ob_type = &PyCFunction_Type;
50 _Py_NewReference((PyObject *)op);
52 else {
53 op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
54 if (op == NULL)
55 return NULL;
57 op->m_ml = ml;
58 Py_XINCREF(self);
59 op->m_self = self;
60 return (PyObject *)op;
63 PyCFunction
64 PyCFunction_GetFunction(op)
65 PyObject *op;
67 if (!PyCFunction_Check(op)) {
68 PyErr_BadInternalCall();
69 return NULL;
71 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
74 PyObject *
75 PyCFunction_GetSelf(op)
76 PyObject *op;
78 if (!PyCFunction_Check(op)) {
79 PyErr_BadInternalCall();
80 return NULL;
82 return ((PyCFunctionObject *)op) -> m_self;
85 int
86 PyCFunction_GetFlags(op)
87 PyObject *op;
89 if (!PyCFunction_Check(op)) {
90 PyErr_BadInternalCall();
91 return -1;
93 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
96 /* Methods (the standard built-in methods, that is) */
98 static void
99 meth_dealloc(m)
100 PyCFunctionObject *m;
102 Py_XDECREF(m->m_self);
103 m->m_self = (PyObject *)free_list;
104 free_list = m;
107 static PyObject *
108 meth_getattr(m, name)
109 PyCFunctionObject *m;
110 char *name;
112 if (strcmp(name, "__name__") == 0) {
113 return PyString_FromString(m->m_ml->ml_name);
115 if (strcmp(name, "__doc__") == 0) {
116 char *doc = m->m_ml->ml_doc;
117 if (doc != NULL)
118 return PyString_FromString(doc);
119 Py_INCREF(Py_None);
120 return Py_None;
122 if (strcmp(name, "__self__") == 0) {
123 PyObject *self;
124 if (PyEval_GetRestricted()) {
125 PyErr_SetString(PyExc_RuntimeError,
126 "method.__self__ not accessible in restricted mode");
127 return NULL;
129 self = m->m_self;
130 if (self == NULL)
131 self = Py_None;
132 Py_INCREF(self);
133 return self;
135 if (strcmp(name, "__members__") == 0) {
136 return Py_BuildValue("[sss]",
137 "__doc__", "__name__", "__self__");
139 PyErr_SetString(PyExc_AttributeError, name);
140 return NULL;
143 static PyObject *
144 meth_repr(m)
145 PyCFunctionObject *m;
147 char buf[200];
148 if (m->m_self == NULL)
149 sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
150 else
151 sprintf(buf,
152 "<built-in method %.80s of %.80s object at %lx>",
153 m->m_ml->ml_name, m->m_self->ob_type->tp_name,
154 (long)m->m_self);
155 return PyString_FromString(buf);
158 static int
159 meth_compare(a, b)
160 PyCFunctionObject *a, *b;
162 if (a->m_self != b->m_self)
163 return (a->m_self < b->m_self) ? -1 : 1;
164 if (a->m_ml->ml_meth == b->m_ml->ml_meth)
165 return 0;
166 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
167 return -1;
168 else
169 return 1;
172 static long
173 meth_hash(a)
174 PyCFunctionObject *a;
176 long x;
177 if (a->m_self == NULL)
178 x = 0;
179 else {
180 x = PyObject_Hash(a->m_self);
181 if (x == -1)
182 return -1;
184 return x ^ (long) a->m_ml->ml_meth;
187 PyTypeObject PyCFunction_Type = {
188 PyObject_HEAD_INIT(&PyType_Type)
190 "builtin_function_or_method",
191 sizeof(PyCFunctionObject),
193 (destructor)meth_dealloc, /*tp_dealloc*/
194 0, /*tp_print*/
195 (getattrfunc)meth_getattr, /*tp_getattr*/
196 0, /*tp_setattr*/
197 (cmpfunc)meth_compare, /*tp_compare*/
198 (reprfunc)meth_repr, /*tp_repr*/
199 0, /*tp_as_number*/
200 0, /*tp_as_sequence*/
201 0, /*tp_as_mapping*/
202 (hashfunc)meth_hash, /*tp_hash*/
205 /* List all methods in a chain -- helper for findmethodinchain */
207 static PyObject *
208 listmethodchain(chain)
209 PyMethodChain *chain;
211 PyMethodChain *c;
212 PyMethodDef *ml;
213 int i, n;
214 PyObject *v;
216 n = 0;
217 for (c = chain; c != NULL; c = c->link) {
218 for (ml = c->methods; ml->ml_name != NULL; ml++)
219 n++;
221 v = PyList_New(n);
222 if (v == NULL)
223 return NULL;
224 i = 0;
225 for (c = chain; c != NULL; c = c->link) {
226 for (ml = c->methods; ml->ml_name != NULL; ml++) {
227 PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
228 i++;
231 if (PyErr_Occurred()) {
232 Py_DECREF(v);
233 return NULL;
235 PyList_Sort(v);
236 return v;
239 /* Find a method in a method chain */
241 PyObject *
242 Py_FindMethodInChain(chain, self, name)
243 PyMethodChain *chain;
244 PyObject *self;
245 char *name;
247 if (name[0] == '_' && name[1] == '_') {
248 if (strcmp(name, "__methods__") == 0)
249 return listmethodchain(chain);
250 if (strcmp(name, "__doc__") == 0) {
251 char *doc = self->ob_type->tp_doc;
252 if (doc != NULL)
253 return PyString_FromString(doc);
256 while (chain != NULL) {
257 PyMethodDef *ml = chain->methods;
258 for (; ml->ml_name != NULL; ml++) {
259 if (name[0] == ml->ml_name[0] &&
260 strcmp(name+1, ml->ml_name+1) == 0)
261 return PyCFunction_New(ml, self);
263 chain = chain->link;
265 PyErr_SetString(PyExc_AttributeError, name);
266 return NULL;
269 /* Find a method in a single method list */
271 PyObject *
272 Py_FindMethod(methods, self, name)
273 PyMethodDef *methods;
274 PyObject *self;
275 char *name;
277 PyMethodChain chain;
278 chain.methods = methods;
279 chain.link = NULL;
280 return Py_FindMethodInChain(&chain, self, name);
283 /* Clear out the free list */
285 void
286 PyCFunction_Fini()
288 while (free_list) {
289 PyCFunctionObject *v = free_list;
290 free_list = (PyCFunctionObject *)(v->m_self);
291 PyMem_DEL(v);