methodobject.c 6.47 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
		free_list = (PyCFunctionObject *)(op->m_self);
49
		PyObject_INIT(op, &PyCFunction_Type);
Guido van Rossum's avatar
Guido van Rossum committed
50
	}
51 52 53 54 55 56 57 58
	else {
		op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
		if (op == NULL)
			return NULL;
	}
	op->m_ml = ml;
	Py_XINCREF(self);
	op->m_self = self;
59
	return (PyObject *)op;
Guido van Rossum's avatar
Guido van Rossum committed
60 61
}

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

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

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

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

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

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

142
static PyObject *
Guido van Rossum's avatar
Guido van Rossum committed
143
meth_repr(m)
144
	PyCFunctionObject *m;
Guido van Rossum's avatar
Guido van Rossum committed
145 146 147
{
	char buf[200];
	if (m->m_self == NULL)
148
		sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
Guido van Rossum's avatar
Guido van Rossum committed
149
	else
Guido van Rossum's avatar
Guido van Rossum committed
150
		sprintf(buf,
151
			"<built-in method %.80s of %.80s object at %lx>",
152
			m->m_ml->ml_name, m->m_self->ob_type->tp_name,
153
			(long)m->m_self);
154
	return PyString_FromString(buf);
Guido van Rossum's avatar
Guido van Rossum committed
155 156
}

157 158
static int
meth_compare(a, b)
159
	PyCFunctionObject *a, *b;
160 161
{
	if (a->m_self != b->m_self)
162
		return (a->m_self < b->m_self) ? -1 : 1;
163
	if (a->m_ml->ml_meth == b->m_ml->ml_meth)
164
		return 0;
165
	if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
166 167 168 169 170 171 172
		return -1;
	else
		return 1;
}

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

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

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

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

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

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

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

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

/* Clear out the free list */

void
PyCFunction_Fini()
{
	while (free_list) {
		PyCFunctionObject *v = free_list;
		free_list = (PyCFunctionObject *)(v->m_self);
290
		PyObject_DEL(v);
291 292
	}
}