diff options
-rw-r--r-- | Include/methodobject.h | 8 | ||||
-rw-r--r-- | Include/rename2.h | 2 | ||||
-rw-r--r-- | Objects/methodobject.c | 73 |
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); +} |