methodobject.c 5.99 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 38

#include "token.h"

typedef struct {
39 40 41 42
	PyObject_HEAD
	PyMethodDef *m_ml;
	PyObject	*m_self;
} PyCFunctionObject;
Guido van Rossum's avatar
Guido van Rossum committed
43

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

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

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

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

Guido van Rossum's avatar
Guido van Rossum committed
92 93 94 95
/* Methods (the standard built-in methods, that is) */

static void
meth_dealloc(m)
96
	PyCFunctionObject *m;
Guido van Rossum's avatar
Guido van Rossum committed
97
{
98
	Py_XDECREF(m->m_self);
Guido van Rossum's avatar
Guido van Rossum committed
99 100 101
	free((char *)m);
}

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

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

153 154
static int
meth_compare(a, b)
155
	PyCFunctionObject *a, *b;
156 157
{
	if (a->m_self != b->m_self)
158
		return PyObject_Compare(a->m_self, b->m_self);
159
	if (a->m_ml->ml_meth == b->m_ml->ml_meth)
160
		return 0;
161
	if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
162 163 164 165 166 167 168
		return -1;
	else
		return 1;
}

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

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

200
/* List all methods in a chain -- helper for findmethodinchain */
201

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

234
/* Find a method in a method chain */
Guido van Rossum's avatar
Guido van Rossum committed
235

236 237 238 239
PyObject *
Py_FindMethodInChain(chain, self, name)
	PyMethodChain *chain;
	PyObject *self;
Guido van Rossum's avatar
Guido van Rossum committed
240 241
	char *name;
{
242
	if (strcmp(name, "__methods__") == 0)
243 244
		return listmethodchain(chain);
	while (chain != NULL) {
245
		PyMethodDef *ml = chain->methods;
246 247 248
		for (; ml->ml_name != NULL; ml++) {
			if (name[0] == ml->ml_name[0] &&
			    strcmp(name+1, ml->ml_name+1) == 0)
249
				return PyCFunction_New(ml, self);
250 251
		}
		chain = chain->link;
Guido van Rossum's avatar
Guido van Rossum committed
252
	}
253
	PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum's avatar
Guido van Rossum committed
254 255
	return NULL;
}
256 257 258

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

259 260 261 262
PyObject *
Py_FindMethod(methods, self, name)
	PyMethodDef *methods;
	PyObject *self;
263 264
	char *name;
{
265
	PyMethodChain chain;
266 267
	chain.methods = methods;
	chain.link = NULL;
268
	return Py_FindMethodInChain(&chain, self, name);
269
}