methodobject.c 6.48 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
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 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31

******************************************************************/

Guido van Rossum's avatar
Guido van Rossum committed
32 33
/* Method object implementation */

34
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
35 36 37

#include "token.h"

38 39
static PyCFunctionObject *free_list = NULL;

40 41 42 43
PyObject *
PyCFunction_New(ml, self)
	PyMethodDef *ml;
	PyObject *self;
Guido van Rossum's avatar
Guido van Rossum committed
44
{
45 46
	PyCFunctionObject *op;
	op = free_list;
Guido van Rossum's avatar
Guido van Rossum committed
47
	if (op != NULL) {
48 49 50
		free_list = (PyCFunctionObject *)(op->m_self);
		op->ob_type = &PyCFunction_Type;
		_Py_NewReference(op);
Guido van Rossum's avatar
Guido van Rossum committed
51
	}
52 53 54 55 56 57 58 59
	else {
		op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
		if (op == NULL)
			return NULL;
	}
	op->m_ml = ml;
	Py_XINCREF(self);
	op->m_self = self;
60
	return (PyObject *)op;
Guido van Rossum's avatar
Guido van Rossum committed
61 62
}

63 64 65
PyCFunction
PyCFunction_GetFunction(op)
	PyObject *op;
Guido van Rossum's avatar
Guido van Rossum committed
66
{
67 68
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
Guido van Rossum's avatar
Guido van Rossum committed
69 70
		return NULL;
	}
71
	return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
Guido van Rossum's avatar
Guido van Rossum committed
72 73
}

74 75 76
PyObject *
PyCFunction_GetSelf(op)
	PyObject *op;
Guido van Rossum's avatar
Guido van Rossum committed
77
{
78 79
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
Guido van Rossum's avatar
Guido van Rossum committed
80 81
		return NULL;
	}
82
	return ((PyCFunctionObject *)op) -> m_self;
Guido van Rossum's avatar
Guido van Rossum committed
83 84
}

85
int
86 87
PyCFunction_GetFlags(op)
	PyObject *op;
88
{
89 90
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
91 92
		return -1;
	}
93
	return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
94 95
}

Guido van Rossum's avatar
Guido van Rossum committed
96 97 98 99
/* Methods (the standard built-in methods, that is) */

static void
meth_dealloc(m)
100
	PyCFunctionObject *m;
Guido van Rossum's avatar
Guido van Rossum committed
101
{
102
	Py_XDECREF(m->m_self);
103 104
	m->m_self = (PyObject *)free_list;
	free_list = m;
Guido van Rossum's avatar
Guido van Rossum committed
105 106
}

107
static PyObject *
108
meth_getattr(m, name)
109
	PyCFunctionObject *m;
110 111 112
	char *name;
{
	if (strcmp(name, "__name__") == 0) {
113
		return PyString_FromString(m->m_ml->ml_name);
114 115 116 117
	}
	if (strcmp(name, "__doc__") == 0) {
		char *doc = m->m_ml->ml_doc;
		if (doc != NULL)
118 119 120
			return PyString_FromString(doc);
		Py_INCREF(Py_None);
		return Py_None;
121 122
	}
	if (strcmp(name, "__self__") == 0) {
123 124 125
		PyObject *self;
		if (PyEval_GetRestricted()) {
			PyErr_SetString(PyExc_RuntimeError,
126 127 128 129
			 "method.__self__ not accessible in restricted mode");
			return NULL;
		}
		self = m->m_self;
130
		if (self == NULL)
131 132
			self = Py_None;
		Py_INCREF(self);
133 134 135
		return self;
	}
	if (strcmp(name, "__members__") == 0) {
136 137
		return Py_BuildValue("[sss]",
				     "__doc__", "__name__", "__self__");
138
	}
139
	PyErr_SetString(PyExc_AttributeError, name);
140 141 142
	return NULL;
}

143
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
144
meth_repr(m)
145
	PyCFunctionObject *m;
Guido van Rossum's avatar
Guido van Rossum committed
146 147 148
{
	char buf[200];
	if (m->m_self == NULL)
149
		sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
Guido van Rossum's avatar
Guido van Rossum committed
150
	else
Guido van Rossum's avatar
Guido van Rossum committed
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);
Guido van Rossum's avatar
Guido van Rossum committed
156 157
}

158 159
static int
meth_compare(a, b)
160
	PyCFunctionObject *a, *b;
161 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 168 169 170 171 172 173
		return -1;
	else
		return 1;
}

static long
meth_hash(a)
174
	PyCFunctionObject *a;
175
{
176
	long x;
177 178 179
	if (a->m_self == NULL)
		x = 0;
	else {
180
		x = PyObject_Hash(a->m_self);
181 182 183
		if (x == -1)
			return -1;
	}
184
	return x ^ (long) a->m_ml->ml_meth;
185 186
}

187 188
PyTypeObject PyCFunction_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum's avatar
Guido van Rossum committed
189
	0,
190
	"builtin_function_or_method",
191
	sizeof(PyCFunctionObject),
Guido van Rossum's avatar
Guido van Rossum committed
192
	0,
193
	(destructor)meth_dealloc, /*tp_dealloc*/
194
	0,		/*tp_print*/
195
	(getattrfunc)meth_getattr, /*tp_getattr*/
Guido van Rossum's avatar
Guido van Rossum committed
196
	0,		/*tp_setattr*/
197 198
	(cmpfunc)meth_compare, /*tp_compare*/
	(reprfunc)meth_repr, /*tp_repr*/
Guido van Rossum's avatar
Guido van Rossum committed
199 200 201
	0,		/*tp_as_number*/
	0,		/*tp_as_sequence*/
	0,		/*tp_as_mapping*/
202
	(hashfunc)meth_hash, /*tp_hash*/
Guido van Rossum's avatar
Guido van Rossum committed
203
};
Guido van Rossum's avatar
Guido van Rossum committed
204

205
/* List all methods in a chain -- helper for findmethodinchain */
206

207
static PyObject *
208
listmethodchain(chain)
209
	PyMethodChain *chain;
210
{
211 212
	PyMethodChain *c;
	PyMethodDef *ml;
213
	int i, n;
214
	PyObject *v;
215 216 217 218 219 220
	
	n = 0;
	for (c = chain; c != NULL; c = c->link) {
		for (ml = c->methods; ml->ml_name != NULL; ml++)
			n++;
	}
221
	v = PyList_New(n);
222 223 224 225 226
	if (v == NULL)
		return NULL;
	i = 0;
	for (c = chain; c != NULL; c = c->link) {
		for (ml = c->methods; ml->ml_name != NULL; ml++) {
227
			PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
228
			i++;
229 230
		}
	}
231 232
	if (PyErr_Occurred()) {
		Py_DECREF(v);
233 234
		return NULL;
	}
235
	PyList_Sort(v);
236 237 238
	return v;
}

239
/* Find a method in a method chain */
Guido van Rossum's avatar
Guido van Rossum committed
240

241 242 243 244
PyObject *
Py_FindMethodInChain(chain, self, name)
	PyMethodChain *chain;
	PyObject *self;
Guido van Rossum's avatar
Guido van Rossum committed
245 246
	char *name;
{
247 248 249 250 251 252 253 254 255
	if (name[0] == '_' && name[1] == '_') {
		if (strcmp(name, "__methods__") == 0)
			return listmethodchain(chain);
		if (strcmp(name, "__doc__") == 0) {
			char *doc = self->ob_type->tp_doc;
			if (doc != NULL)
				return PyString_FromString(doc);
		}
	}
256
	while (chain != NULL) {
257
		PyMethodDef *ml = chain->methods;
258 259 260
		for (; ml->ml_name != NULL; ml++) {
			if (name[0] == ml->ml_name[0] &&
			    strcmp(name+1, ml->ml_name+1) == 0)
261
				return PyCFunction_New(ml, self);
262 263
		}
		chain = chain->link;
Guido van Rossum's avatar
Guido van Rossum committed
264
	}
265
	PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum's avatar
Guido van Rossum committed
266 267
	return NULL;
}
268 269 270

/* Find a method in a single method list */

271 272 273 274
PyObject *
Py_FindMethod(methods, self, name)
	PyMethodDef *methods;
	PyObject *self;
275 276
	char *name;
{
277
	PyMethodChain chain;
278 279
	chain.methods = methods;
	chain.link = NULL;
280
	return Py_FindMethodInChain(&chain, self, name);
281
}
282 283 284 285 286 287 288 289 290 291 292 293

/* Clear out the free list */

void
PyCFunction_Fini()
{
	while (free_list) {
		PyCFunctionObject *v = free_list;
		free_list = (PyCFunctionObject *)(v->m_self);
		PyMem_DEL(v);
	}
}