summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/methodobject.h8
-rw-r--r--Include/rename2.h2
-rw-r--r--Objects/methodobject.c73
3 files changed, 60 insertions, 23 deletions
diff --git a/Include/methodobject.h b/Include/methodobject.h
index 1b2dd87..946d004 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -57,6 +57,14 @@ extern PyObject *PyCFunction_New
/* Flag passed to newmethodobject */
#define METH_VARARGS 0x0001
+typedef struct PyMethodChain {
+ PyMethodDef *methods; /* Methods of this type */
+ struct PyMethodChain *link; /* NULL or base type */
+} PyMethodChain;
+
+extern PyObject *Py_FindMethodInChain
+ Py_PROTO((PyMethodChain *, PyObject *, char *));
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/rename2.h b/Include/rename2.h
index e955346..e648a62 100644
--- a/Include/rename2.h
+++ b/Include/rename2.h
@@ -38,6 +38,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* typedef ANY *PyUnivPtr; */
#define methodlist PyMethodDef
+#define methodchain PyMethodChain
#define None Py_None
#define False Py_False
@@ -290,6 +291,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define newrangeobject PyRange_New
#define method PyCFunction
#define findmethod Py_FindMethod
+#define findmethodinchain Py_FindMethodInChain
#define getmethod PyCFunction_GetFunction
#define getself PyCFunction_GetSelf
#define getvarargs PyCFunction_IsVarArgs
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 61420aa..d9daf23 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -188,46 +188,73 @@ typeobject Methodtype = {
(hashfunc)meth_hash, /*tp_hash*/
};
-static object *listmethods PROTO((struct methodlist *)); /* Forward */
+/* List all methods in a chain -- helper for findmethodinchain */
static object *
-listmethods(ml)
- struct methodlist *ml;
+listmethodchain(chain)
+ struct methodchain *chain;
{
+ struct methodchain *c;
+ struct methodlist *ml;
int i, n;
object *v;
- for (n = 0; ml[n].ml_name != NULL; n++)
- ;
+
+ n = 0;
+ for (c = chain; c != NULL; c = c->link) {
+ for (ml = c->methods; ml->ml_name != NULL; ml++)
+ n++;
+ }
v = newlistobject(n);
- if (v != NULL) {
- for (i = 0; i < n; i++)
- setlistitem(v, i, newstringobject(ml[i].ml_name));
- if (err_occurred()) {
- DECREF(v);
- v = NULL;
- }
- else {
- sortlist(v);
+ if (v == NULL)
+ return NULL;
+ i = 0;
+ for (c = chain; c != NULL; c = c->link) {
+ for (ml = c->methods; ml->ml_name != NULL; ml++) {
+ setlistitem(v, i, newstringobject(ml->ml_name));
+ i++;
}
}
+ if (err_occurred()) {
+ DECREF(v);
+ return NULL;
+ }
+ sortlist(v);
return v;
}
-/* Find a method in a module's method table.
- Usually called from an object's getattr method. */
+/* Find a method in a method chain */
object *
-findmethod(ml, op, name)
- struct methodlist *ml;
- object *op;
+findmethodinchain(chain, self, name)
+ struct methodchain *chain;
+ object *self;
char *name;
{
if (strcmp(name, "__methods__") == 0)
- return listmethods(ml);
- for (; ml->ml_name != NULL; ml++) {
- if (strcmp(name, ml->ml_name) == 0)
- return newmethodobject(ml, op);
+ return listmethodchain(chain);
+ while (chain != NULL) {
+ struct methodlist *ml = chain->methods;
+ for (; ml->ml_name != NULL; ml++) {
+ if (name[0] == ml->ml_name[0] &&
+ strcmp(name+1, ml->ml_name+1) == 0)
+ return newmethodobject(ml, self);
+ }
+ chain = chain->link;
}
err_setstr(AttributeError, name);
return NULL;
}
+
+/* Find a method in a single method list */
+
+object *
+findmethod(methods, self, name)
+ struct methodlist *methods;
+ object *self;
+ char *name;
+{
+ struct methodchain chain;
+ chain.methods = methods;
+ chain.link = NULL;
+ return findmethodinchain(&chain, self, name);
+}