Added AROS port of all shell applications:
[cake.git] / rom / oop / metaclass.c
bloba5dfbf3097454ace18ee4464dc7d52ea7d908c66
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: OOP metaclass
6 Lang: english
7 */
9 #include <proto/exec.h>
10 #include <proto/utility.h>
11 #include <exec/memory.h>
13 #include <proto/oop.h>
14 #include <oop/oop.h>
16 #include "intern.h"
17 #include "hash.h"
18 #include "private.h"
20 #undef SDEBUG
21 #undef DEBUG
22 #define SDEBUG 0
23 #define DEBUG 0
24 #include <aros/debug.h>
26 #define MD(cl) ((struct metadata *)cl)
27 #define IFI(cl) ((struct ifmeta_inst *)cl)
29 # define IntCallMethod(cl, o, msg) \
30 { \
31 register struct IFBucket *b; \
32 register OOP_MethodID mid = *msg; \
33 register ULONG ifid = mid & (~METHOD_MASK); \
34 register struct IFMethod *method; \
36 mid &= METHOD_MASK; \
38 b = IFI(cl)->data.iftab_directptr[ifid & IFI(cl)->data.hashmask]; \
39 while (b) \
40 { \
41 if (b->InterfaceID == ifid) \
42 { \
43 method = &(b->MethodTable[mid]); \
44 return (method->MethodFunc(method->mClass, o, msg)); \
45 } \
46 b = b->Next; \
47 } \
48 return (0UL); \
53 #define UB(x) ((UBYTE *)x)
55 /* Allocates and initializes the interface hashtable, and the methodtables */
56 static BOOL ifmeta_allocdisptabs(OOP_Class *cl, OOP_Object *o, struct P_meta_allocdisptabs *msg);
57 static VOID ifmeta_freedisptabs(OOP_Class *cl, OOP_Object *o, OOP_Msg msg);
59 static IPTR Meta_DoMethod(OOP_Object *o, OOP_Msg msg);
60 static IPTR Meta_CoerceMethod(OOP_Class *cl, OOP_Object *o, OOP_Msg msg);
61 static IPTR Meta_DoSuperMethod(OOP_Class *cl, OOP_Object *o, OOP_Msg msg);
63 /* Hooks */
64 VOID freebucket(struct Bucket *b, struct IntOOPBase *OOPBase);
65 struct Bucket *copybucket(struct Bucket *old_b, APTR data, struct IntOOPBase *OOPBase);
67 /* Internal */
68 static struct IFBucket *createbucket(
69 STRPTR interface_id
70 ,ULONG num_methods
71 ,struct IntOOPBase *OOPBase);
73 static ULONG calc_ht_entries(struct ifmeta_inst *cl
74 ,OOP_Class *super
75 ,struct OOP_InterfaceDescr *ifDescr
76 ,struct IntOOPBase *OOPBase);
81 The metaclass is used to create class. That means,
82 classes are instances of the meta class.
83 The meta class is itself both a class (you can
84 create instances of it), and an object (you can invoke
85 methods on it.
86 */
89 #define OOPBase (GetOBase(cl->OOPBasePtr))
91 /********************
92 ** IFMeta::New() **
93 ********************/
94 static OOP_Object *ifmeta_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
96 IPTR (*domethod)(OOP_Object *, OOP_Msg) = NULL;
97 IPTR (*coercemethod)(OOP_Class *, OOP_Object *, OOP_Msg) = NULL;
98 IPTR (*dosupermethod)(OOP_Class *, OOP_Object *, OOP_Msg) = NULL;
100 EnterFunc(bug("IFMeta::New(cl=%s, msg = %p)\n",
101 cl->ClassNode.ln_Name, msg));
103 /* Let the BaseMeta class initialize some stuff for us */
104 o = (OOP_Object *)OOP_DoSuperMethod((OOP_Class *)cl, o, (OOP_Msg)msg);
105 if (o)
108 struct ifmeta_inst *inst;
110 inst = (struct ifmeta_inst *)o;
112 domethod = (IPTR (*)())GetTagData(aMeta_DoMethod, 0, msg->attrList);
113 coercemethod = (IPTR (*)())GetTagData(aMeta_CoerceMethod, 0, msg->attrList);
114 dosupermethod = (IPTR (*)())GetTagData(aMeta_DoSuperMethod, 0, msg->attrList);
117 D(bug("Instance allocated %p\n", inst));
120 if (!domethod)
121 domethod = Meta_DoMethod;
123 if (!coercemethod)
124 coercemethod = Meta_CoerceMethod;
126 if (!dosupermethod)
129 OOP_Class *superptr = inst->base.superclass;
130 if (superptr)
132 D(bug("Got superptr: %p\n", superptr));
133 /* Use superclass' DoSupermethod call if superclass isn't
134 an instance of the HIDDMetaClass
136 if (OOP_OCLASS(superptr) != (OOP_Class *)cl)
138 D(bug("superptr has different meta\n"));
140 dosupermethod = superptr->cl_DoSuperMethod;
142 else
144 D(bug("superptr has same meta\n"));
146 dosupermethod = Meta_DoSuperMethod;
150 else /* if (class has no superclass) */
152 dosupermethod = NULL;
157 inst->base.public.OOPBasePtr = (struct IntOOPBase *)OOPBase;
159 inst->base.public.cl_DoMethod = domethod;
160 inst->base.public.cl_CoerceMethod = coercemethod;
161 inst->base.public.cl_DoSuperMethod = dosupermethod;
163 D(bug("Classes' functions set\n"));
166 ReturnPtr ("IFMeta::New", OOP_Object *, o);
169 /******************************
170 ** IFMeta::allocdisptabs() **
171 ******************************/
173 /* Allocates and initializes the interface hashtable, and the methodtables */
174 static BOOL ifmeta_allocdisptabs(OOP_Class *cl, OOP_Object *o, struct P_meta_allocdisptabs *msg)
176 ULONG num_if;
178 struct ifmeta_inst *inst = (struct ifmeta_inst *)o;
180 EnterFunc(bug("IFMeta::allocdisptabs(cl=%p, o=%p,ifDescr=%p)\n",
181 cl, o, msg->ifdescr));
183 /* Get number of needed hash entries */
184 num_if = calc_ht_entries(inst, msg->superclass, msg->ifdescr, OOPBase);
186 inst->base.numinterfaces = num_if;
188 D(bug("numinterfaces set to %ld\n", num_if));
190 /* Create a new integer hashtable, with a reasonable size */
191 inst->data.iftable = NewHash(num_if, HT_INTEGER, OOPBase);
192 if (inst->data.iftable)
194 struct OOP_InterfaceDescr *ifdescr;
195 D(bug("Got iftable\n"));
196 /* Save hashmask for use in method lookup */
197 inst->data.hashmask = HashMask(inst->data.iftable);
199 if (msg->superclass) /* This test makes it work for initializing root classes */
202 /* Copy parent interfaces into the new class */
203 struct IFMethod *superif;
204 struct P_meta_iterateifs ii_msg;
205 STRPTR interface_id;
206 ULONG num_methods;
208 /* must be initialized to zero */
209 IPTR iterval = 0UL;
211 D(bug("Adding superclass' methods\n"));
213 ii_msg.mid = OOP_GetMethodID(IID_Meta, MO_meta_iterateifs);
215 ii_msg.iterval_ptr = &iterval;
216 ii_msg.interface_id_ptr = &interface_id;
217 ii_msg.num_methods_ptr = &num_methods;
220 for (;;)
222 struct IFBucket *ifb;
223 struct IFMethod *ifm = NULL;
224 ULONG mtab_size;
226 superif = (struct IFMethod *)OOP_CoerceMethod(OOP_OCLASS(msg->superclass)
227 ,(OOP_Object *)msg->superclass
228 ,(OOP_Msg)&ii_msg);
229 if (!superif)
230 break;
232 /* Allocate and insert the interface into the new class */
233 ifb = createbucket(interface_id, num_methods, OOPBase);
234 D(bug("Created bucket: %p\n", ifb));
235 if (!ifb)
236 goto failure;
238 /* Copy the interface */
239 mtab_size = UB (&ifm[num_methods]) - UB( &ifm[0]);
240 D(bug("Copying from superclass methods for if %s, mtab_size=%d,basmetaroot %p, superif %p\n",
241 ifb->GlobalInterfaceID, mtab_size, OOPBase->ob_BaseMetaObject.inst.rootif, superif));
243 CopyMem(superif, ifb->MethodTable, mtab_size);
244 InsertBucket(inst->data.iftable, (struct Bucket *)ifb, OOPBase);
246 } /* for (;;) */
248 } /* if (we inherit interfaces from some superclass) */
250 /* Insert our own interfaces */
251 D(bug("Inserting own methods\n"));
252 for ( ifdescr = msg->ifdescr; ifdescr->MethodTable; ifdescr ++)
254 struct IFBucket *ifb;
255 ULONG i;
257 ULONG iid;
258 /* Get variable interface ID */
260 D(bug("Getting Local ifID for global ID %s\n", ifdescr->InterfaceID));
261 if (!init_mi_methodbase(ifdescr->InterfaceID, &iid, OOPBase))
262 goto failure;
264 D(bug("Got local ifID %ld\n", iid));
266 /* Lookup hashtable to see if interface has been copied from superclass */
267 ifb = (struct IFBucket *)inst->data.iftable->Lookup(
268 inst->data.iftable
269 , (IPTR)iid
270 , OOPBase);
272 D(bug("tried to find bucket in hashtable: %p\n", ifb));
273 if (!ifb)
275 D(bug("Bucket doesn't exist, creating..\n"));
276 /* Bucket doesn't exist, allocate it */
277 ifb = createbucket(ifdescr->InterfaceID, ifdescr->NumMethods, OOPBase);
278 if (!ifb)
279 goto failure;
280 else
282 D(bug("Inserting bucket for IF %s\n", ifdescr->InterfaceID));
283 InsertBucket(inst->data.iftable, (struct Bucket *)ifb, OOPBase);
288 D(bug("overriding methods\n"));
290 /* Ovveride the superclass methods with our new ones */
291 for (i = 0; ifdescr->MethodTable[i].MethodFunc; i ++)
293 if (ifdescr->MethodTable[i].MethodFunc)
295 ifb->MethodTable[ ifdescr->MethodTable[i].MethodIdx ].MethodFunc = ifdescr->MethodTable[i].MethodFunc;
296 ifb->MethodTable[ ifdescr->MethodTable[i].MethodIdx ].mClass = (OOP_Class *)o;
298 } /* for (each method in the interface) */
300 } /* for (each interface to add to class) */
302 /* For speedup in method lookup */
303 inst->data.iftab_directptr = (struct IFBucket **)inst->data.iftable->Table;
305 ReturnBool ("IFMeta::allocdisptabs", TRUE);
307 } /* if (interface hash table allocated) */
309 failure:
310 D(bug("FAILURE\n"));
311 if (inst->data.iftable)
312 FreeHash(inst->data.iftable, freebucket, OOPBase);
313 ReturnBool ("IFMeta::allocdisptabs", FALSE);
316 /*****************************
317 ** IFMeta::freedisptabs() **
318 *****************************/
319 static VOID ifmeta_freedisptabs(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
322 struct ifmeta_inst *inst = (struct ifmeta_inst *)o;
323 /* This frees the hashtable + all buckets */
325 FreeHash(inst->data.iftable, freebucket, OOPBase);
327 return;
330 /**************************
331 ** IFMeta::getifinfo() **
332 **************************/
333 static struct IFMethod *ifmeta_getifinfo(OOP_Class *cl, OOP_Object *o, struct P_meta_getifinfo *msg)
335 ULONG iid;
336 struct ifmeta_inst *inst = (struct ifmeta_inst *)o;
337 struct IFMethod *mtab = NULL;
338 struct IFBucket *b;
340 /* Get the ULONG variable interface id */
341 iid = OOP_GetMethodID(msg->interface_id, 0);
343 /* Try looking it up in the class' table */
344 b = (struct IFBucket *)inst->data.iftable->Lookup(inst->data.iftable, (IPTR)iid, OOPBase);
346 *(msg->num_methods_ptr) = b->NumMethods;
348 mtab = b->MethodTable;
351 return mtab;
354 /***************************
355 ** IFMeta::iterateifs() **
356 ***************************/
357 static struct IFMethod *ifmeta_iterateifs(OOP_Class *cl, OOP_Object *o, struct P_meta_iterateifs *msg)
359 struct HashTable *ht = ((struct ifmeta_inst *)o)->data.iftable;
360 struct IFBucket *found_bucket = NULL; /* MUST default to NULL */
362 struct IFBucket *ifb = NULL; /* keep compiler happy */
365 struct IFMethod *current_if = NULL; /* MUST default to NULL */
367 UWORD last_idx = (*(msg->iterval_ptr)) >> 16;
368 UWORD last_bucket_no = (*(msg->iterval_ptr)) & 0x0000FFFF;
370 UWORD idx;
372 UWORD bucket_no = 0; /* keep compiler happy */
373 EnterFunc(bug("IFMeta::iterateifs(cl=%s, o=%s)\n",
374 cl->ClassNode.ln_Name, ((OOP_Class *)o)->ClassNode.ln_Name ));
376 D(bug("last_idx: %ld, last_bucket_no=%ld\n", last_idx, last_bucket_no));
379 for (idx = last_idx ;idx < HashSize(ht); idx ++)
381 D(bug("idx=%ld\n", idx));
383 bucket_no = 0;
385 for (ifb = (struct IFBucket *)ht->Table[idx]; ifb; )
387 D(bug("ifb=%s, netx=%p, bucket_no=%ld\n",
388 ifb->GlobalInterfaceID, ifb->Next, bucket_no));
389 /* Is this a new bucket in the iteration ? */
391 if ((idx > last_idx) || (bucket_no >= last_bucket_no))
393 found_bucket = ifb;
395 /* Yes, it's a goto, but it really simplifies things here */
396 goto after_loop;
398 else
400 ifb = ifb->Next;
401 bucket_no ++;
404 } /* for (all buckets at each idx) */
406 } /* for (each entry at east index from last idx) */
408 after_loop:
410 /* OK, found a bucket ? */
411 if (found_bucket)
413 D(bug("bucket found: %s at idx %ld, b_no %ld\n",
414 found_bucket->GlobalInterfaceID, idx, bucket_no));
415 *(msg->iterval_ptr) = (idx << 16) + bucket_no + 1;
416 *(msg->interface_id_ptr) = ifb->GlobalInterfaceID;
417 *(msg->num_methods_ptr) = ifb->NumMethods;
419 current_if = ifb->MethodTable;
422 ReturnPtr ("IFMeta::iterateifs", struct IFMethod *, current_if);
425 /***************************
426 ** IFMeta::findmethod() **
427 ***************************/
429 /* Used for finding a method for method objects */
430 static struct IFMethod *ifmeta_findmethod(OOP_Class *cl, OOP_Object *o, struct P_meta_findmethod *msg)
432 register struct IFBucket *b;
433 register ULONG method_offset;
434 struct ifmeta_inst *inst = (struct ifmeta_inst *)o;
436 /* Get interfaceID part of methodID */
437 register ULONG ifid = msg->method_to_find & (~METHOD_MASK);
439 EnterFunc(bug("IFMeta::findmethod(o=%p, mid=%ld)\n", o, msg->method_to_find));
442 /* Get method offset part of methdoID */
443 method_offset = msg->method_to_find & METHOD_MASK;
445 /* Look up ID in hashtable and get linked list of buckets,
446 storing interfaces
448 b = inst->data.iftab_directptr[ifid & inst->data.hashmask];
449 loop:
450 if (b)
452 /* Found correct interface ? */
453 if (b->InterfaceID == ifid)
455 /* Yep. Return method at supplied method offset */
456 ReturnPtr ("IFMeta::findmethod", struct IFMethod *, &(b->MethodTable[method_offset]));
459 b = b->Next;
460 goto loop;
462 /* Method not found, return NULL */
463 ReturnPtr ("IFMeta::findmethod", struct IFMethod *, NULL);
467 #undef OOPBase
469 /**********
470 Support
471 **********/
473 /*************************
474 ** init_ifmetaclass() **
475 *************************/
477 #define NUM_META_METHODS 5
478 #define NUM_ROOT_METHODS 1
479 BOOL init_ifmetaclass(struct IntOOPBase *OOPBase)
481 struct OOP_MethodDescr root_mdescr[NUM_ROOT_METHODS + 1]=
483 { (IPTR (*)())ifmeta_new, moRoot_New },
484 { NULL, 0UL }
487 struct OOP_MethodDescr meta_mdescr[NUM_META_METHODS + 1]=
489 { (IPTR (*)())ifmeta_allocdisptabs, MO_meta_allocdisptabs },
490 { (IPTR (*)())ifmeta_freedisptabs, MO_meta_freedisptabs },
491 { (IPTR (*)())ifmeta_getifinfo, MO_meta_getifinfo },
492 { (IPTR (*)())ifmeta_iterateifs, MO_meta_iterateifs },
493 { (IPTR (*)())ifmeta_findmethod, MO_meta_findmethod },
494 { NULL, 0UL }
498 struct OOP_InterfaceDescr meta_descr[] =
500 {root_mdescr, IID_Root, 1},
501 {meta_mdescr, IID_Meta, NUM_META_METHODS},
502 {NULL, NULL, 0UL}
505 struct ifmetaobject *imo = &(OOPBase->ob_IFMetaObject);
506 struct P_meta_allocdisptabs adt_msg;
507 OOP_Class *ifmeta_cl;
509 EnterFunc(bug("init_ifmetaclass()\n"));
511 ifmeta_cl = &(imo->inst.base.public);
513 D(bug("Got ifmeta classptr\n"));
515 imo->inst.base.superclass = BASEMETAPTR;
516 imo->inst.base.public.OOPBasePtr = (struct OOPBase *)OOPBase;
518 D(bug("Initialized ifmeta superclass\n"));
520 adt_msg.superclass = imo->inst.base.superclass;
521 adt_msg.ifdescr = meta_descr;
523 /* allocdisptabs() must know the OOPBase */
524 imo->inst.base.public.UserData = (APTR)OOPBase;
525 /* It must also have a valid DoSuperMethod(), more exatly
526 the DoSuperMethod() of the BaseMeta class
528 imo->inst.base.public.cl_DoSuperMethod = BASEMETAPTR->cl_DoSuperMethod;
531 D(bug("Allocating ifmeta disptabs\n"));
534 if (ifmeta_allocdisptabs(ifmeta_cl, (OOP_Object *)ifmeta_cl, &adt_msg))
536 D(bug("ifmeta disptabs allocated\n"));
537 /* initialize Class ID */
539 imo->inst.base.public.ClassNode.ln_Name = CLID_MIMeta;
540 imo->inst.base.public.InstOffset = sizeof (struct metadata);
542 D(bug("IFMeta DoMethod=%p\n", Meta_DoMethod));
543 imo->inst.base.public.cl_DoMethod = Meta_DoMethod;
544 imo->inst.base.public.cl_CoerceMethod = Meta_CoerceMethod;
546 imo->inst.base.instsize = sizeof (struct ifmeta_data);
547 imo->inst.base.subclasscount = 0UL;
548 imo->inst.base.objectcount = 0UL;
550 imo->inst.data.numinterfaces = 2UL;
552 /* This class' class is itself */
553 imo->oclass = &(imo->inst.base.public);
555 /* {
556 ULONG i;
557 D(bug("Trying to call get_if_info on ifmeta many times\n"));
558 for (i = 0; i < 10; i ++)
560 ULONG num_methods;
561 meta_getifinfo((OOP_Object *)imo->oclass, IID_Meta, &num_methods);
563 D(bug("IF has %ld methods\n", num_methods));
567 */ /* Make it public */
568 OOP_AddClass(ifmeta_cl);
569 ReturnBool ("init_metaclass", TRUE);
571 ReturnBool ("init_ifmetaclass", FALSE);
576 /************************
577 ** calc_ht_entries() **
578 ************************/
580 /* Calculates the number of interfaces the new class has
581 ( == number of buckets in the hashtable)
583 static ULONG calc_ht_entries(struct ifmeta_inst *cl
584 ,OOP_Class *super
585 ,struct OOP_InterfaceDescr *ifDescr
586 ,struct IntOOPBase *OOPBase)
588 ULONG num_if = 0;
590 EnterFunc(bug("calc_ht_entries(cl=%p, ifDescr=%p, super=%p)\n", cl, ifDescr, super));
594 if (super)
596 /* Get number of interfaces (method tables) in superclass */
599 num_if = MD(super)->numinterfaces;
601 D(bug("Super-interfaces: %ld\n", num_if));
603 /* Check if there are any new interfaces in this class */
605 for (; ifDescr->MethodTable; ifDescr ++)
607 struct P_meta_getifinfo gii_msg;
608 ULONG num_methods;
610 D(bug("Checking for interface %s\n", ifDescr->InterfaceID));
612 gii_msg.mid = OOP_GetMethodID(IID_Meta, MO_meta_getifinfo);
613 gii_msg.interface_id = ifDescr->InterfaceID;
614 gii_msg.num_methods_ptr = &num_methods;
617 /* Does super support interface ? */
618 D(bug("Calling CoerceMethod on class %s\n", OOP_OCLASS(super)->ClassNode.ln_Name));
619 if (!OOP_CoerceMethod(OOP_OCLASS(super), (OOP_Object *)super, (OOP_Msg)&gii_msg))
621 D(bug("Found new interface: %s\n", ifDescr->InterfaceID));
623 /* If it didn't then we have a new interface for this class */
624 num_if ++;
627 } /* for (each interface in the description for the class) */
630 else
632 /* This is a baseclass, count the interfaces */
633 for (; ifDescr->MethodTable; ifDescr ++)
635 num_if ++;
637 } /* for (each interface in the description for the class) */
639 ReturnInt ("calc_ht_entries", ULONG, num_if);
647 /*********************
648 ** createbucket() **
649 *********************/
650 /* Creates a new interface bucket */
651 static struct IFBucket *createbucket(
652 STRPTR interface_id
653 ,ULONG num_methods
654 ,struct IntOOPBase *OOPBase)
656 struct IFMethod *ifm = NULL;
657 ULONG mtab_size = UB (&ifm[num_methods]) - UB( &ifm[0]);
659 /* Allocate bucket */
660 struct IFBucket *ifb;
662 ifb = (struct IFBucket *)AllocMem( sizeof (struct IFBucket), MEMF_ANY );
663 if (ifb)
665 /* Allocate method table for this interface */
666 ifb->MethodTable = (struct IFMethod *)AllocVec(mtab_size, MEMF_ANY);
667 if (ifb->MethodTable)
669 /* Get correct ID for the interface (string ID => interface ID mapping) */
670 ifb->InterfaceID = 0;
671 if (init_mi_methodbase(interface_id, &(ifb->InterfaceID), OOPBase))
673 /* Save number of methods in the interface */
674 ifb->NumMethods = num_methods;
676 /* Save the global string representations of the ID */
677 ifb->GlobalInterfaceID = interface_id;
678 return (ifb);
682 FreeMem (ifb, sizeof (struct IFBucket));
684 return (NULL);
688 /***********************
689 ** Hash table hooks **
690 ***********************/
691 #define IB(x) ((struct IFBucket *)x)
693 VOID freebucket(struct Bucket *b, struct IntOOPBase *OOPBase)
696 /* Free methodtable */
697 FreeVec(IB(b)->MethodTable);
699 /* Free the bucket itself */
700 FreeMem(b, sizeof (struct IFBucket));
703 return;
706 /* Copies a hashtable bucket */
707 struct Bucket *copyBucket(struct Bucket *old_b, APTR data, struct IntOOPBase *OOPBase)
709 struct IFBucket *new_b;
711 EnterFunc(bug("CopyBucket(old_b=%p)\n", old_b));
713 /* Allocate memory for the new interface bucket */
714 new_b = (struct IFBucket *)AllocMem(sizeof (struct IFBucket), MEMF_ANY );
715 if (new_b)
717 struct IFMethod *ifm = NULL;
718 ULONG mtab_size;
720 /* Get number of methods in source methodtable */
721 ULONG numentries = IB(old_b)->NumMethods;
723 mtab_size = UB(&ifm[numentries]) - UB(&ifm[0]);
725 /* Allocate memory for methodtable of same size as source one */
726 new_b->MethodTable = (struct IFMethod *)AllocVec(mtab_size, MEMF_ANY);
727 if (new_b->MethodTable)
729 /* Copy methodtable to destination */
730 CopyMem(IB(old_b)->MethodTable, new_b->MethodTable, mtab_size);
732 /* Initialize bucket */
733 new_b->InterfaceID = IB(old_b)->InterfaceID;
734 new_b->NumMethods = IB(old_b)->NumMethods;
735 new_b->GlobalInterfaceID = IB(old_b)->GlobalInterfaceID;
737 ReturnPtr ("CopyBucket", struct Bucket *, (struct Bucket *)new_b );
739 FreeMem (new_b, sizeof (struct IFBucket));
742 ReturnPtr ("CopyBucket", struct Bucket *, NULL);
747 /* Default function for calling DoMethod() on a local object */
748 /*****************
749 ** DoMethod() **
750 *****************/
752 #define OOPBase ((struct IntOOPBase *)OOP_OOPBASE(object))
754 static IPTR Meta_DoMethod(OOP_Object *object, OOP_Msg msg)
756 struct metadata *cl = (struct metadata *)OOP_OCLASS(object);
759 /* Macro below defined in intern.h */
760 IntCallMethod(cl, object, msg);
765 /*******************
766 ** CoerceMethod **
767 *******************/
768 static IPTR Meta_CoerceMethod(OOP_Class *cl, OOP_Object *object, OOP_Msg msg)
770 IntCallMethod(cl, object, msg);
773 /********************
774 ** DoSuperMethod **
775 ********************/
776 static IPTR Meta_DoSuperMethod(OOP_Class *cl, OOP_Object *object, OOP_Msg msg)
778 cl = IFI(cl)->base.superclass;
779 IntCallMethod(cl, object, msg);
782 #undef OOPBase