diff --git a/Source/behavior.c b/Source/behavior.c deleted file mode 100644 index 93bb377cb..000000000 --- a/Source/behavior.c +++ /dev/null @@ -1,433 +0,0 @@ -/* Behaviors for Objective-C, "for Protocols with implementations". - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - - Written by: R. Andrew McCallum - Date: March 1995 - - This file is part of the GNU Objective C Class Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* A Behavior can be seen as a "Protocol with an implementation" or a - "Class without any instance variables". A key feature of behaviors - is that they give a degree of multiple inheritance. - - Behavior methods override the class's superclass methods, but not - the class's methods. - - xxx not necessarily on the "no instance vars". The behavior just has - to have the same layout as the class. - - The following function is a sneaky hack way that provides Behaviors - without adding any new syntax to the Objective C language. Simply - define a class with the methods you want in the behavior, then call - this function with that class as the BEHAVIOR argument. - - This function should be called in CLASS's +initialize method. - - If you add several behaviors to a class, be aware that the order of - the additions is significant. - - McCallum talking to himself: - "Yipes. Be careful with [super ...] calls. - BEHAVIOR methods running in CLASS will now have a different super class. - No; wrong. See objc-api.h; typedef struct objc_super." - - */ - -#include -#include -#include -#include -#include - -static int behavior_debug = 0; - -static Method_t search_for_method_in_list (MethodList_t list, SEL op); -static void __objc_send_initialize(Class class); -#if 0 -static void __objc_init_protocols (struct objc_protocol_list* protos); -static void __objc_class_add_protocols (Class class, - struct objc_protocol_list* protos); -#endif -static BOOL class_is_kind_of(Class self, Class class); -static void check_class_methods(Class class); - -void class_add_methods_if_not_there(Class class, Class behavior); - -/* The uninstalled dispatch table, declared in gcc/objc/sendmsg.c. */ -extern struct sarray* __objc_uninstalled_dtable; - -/* xxx consider using sendmsg.c:__objc_update_dispatch_table_for_class, - but, I think it will be slower than the current method. */ - -void -set_behavior_debug(int i) -{ - behavior_debug = i; -} - -void -class_add_behavior (Class class, Class behavior) -{ - Class behavior_super_class = class_get_super_class(behavior); - - assert(CLS_ISCLASS(class)); - assert(CLS_ISCLASS(behavior)); - - __objc_send_initialize(class); - __objc_send_initialize(behavior); - - /* If necessary, increase instance_size of CLASS. */ - if (class->instance_size < behavior->instance_size) - class->instance_size = behavior->instance_size; - -#if 0 - /* xxx Do protocols */ - if (behavior->protocols) - { - /* xxx Make sure they are not already there before adding. */ - __objc_init_protocols (behavior->protocols); - __objc_class_add_protocols (class, behavior->protocols); - } -#endif - - /* Add instance methods */ - if (behavior_debug) - { - fprintf(stderr, "Adding instance methods from %s\n", - behavior->name); - } - class_add_methods_if_not_there(class, behavior); - - /* Add class methods */ - if (behavior_debug) - { - fprintf(stderr, "Adding class methods from %s\n", - behavior->class_pointer->name); - } - class_add_methods_if_not_there(class->class_pointer, - behavior->class_pointer); - - /* Add behavior's superclass, if not already there. */ - { - if (!class_is_kind_of(class, behavior_super_class)) - class_add_behavior(class, behavior_super_class); - } - - return; -} - -void -class_add_methods_if_not_there(Class class, Class behavior) -{ - static SEL initialize_sel = 0; - MethodList_t mlist; - - if (!initialize_sel) - initialize_sel = sel_register_name ("initialize"); - - /* Add methods to class->dtable and class->methods */ - for (mlist = behavior->methods; mlist; mlist = mlist->method_next) - { - int counter; - MethodList_t new_list; - - counter = mlist->method_count - 1; - - /* xxx This is a little wasteful of memory, since not necessarily - all methods will go in here. */ - new_list = (MethodList_t) - (*objc_malloc) - (sizeof(MethodList) + sizeof(struct objc_method[counter+1])); - new_list->method_count = 0; - - while (counter >= 0) - { - Method_t method = &(mlist->method_list[counter]); - - if (behavior_debug) - fprintf(stderr, " processing method [%s]\n", - sel_get_name(method->method_name)); - - if (!search_for_method_in_list(class->methods, method->method_name) - && method->method_name->sel_id != initialize_sel->sel_id) - { - /* As long as the method isn't defined in the CLASS, - put the BEHAVIOR method in there. Thus, behavior - methods override the superclasses' methods. */ - - /* If dtable is already installed, go ahead and put it in - the dtable sarray, but if it isn't, let - __objc_install_dispatch_table_for_class do it. */ - - if (class->dtable != __objc_uninstalled_dtable) - { - sarray_at_put_safe (class->dtable, - (sidx) method->method_name->sel_id, - method->method_imp); - if (behavior_debug) - fprintf(stderr, "\tinstalled method\n"); - } - else - { - if (behavior_debug) - fprintf(stderr, "\tappended method\n"); - } - new_list->method_list[new_list->method_count] = *method; - (new_list->method_count)++; - } - counter -= 1; - } - if (new_list->method_count) - { - new_list->method_next = class->methods; - class->methods = new_list; - } - else - { - OBJC_FREE(new_list); - } - } -} - -/* Should implement this too: -class_add_behavior_category(), -and perhaps something like: -class_add_methods_if_not_there_or_inherited() */ - -#if 0 -/* This is like class_add_method_list(), except is doesn't balk at - duplicates; it simply ignores them. Thus, a method implemented - in CLASS overrides a method implemented in BEHAVIOR. */ - -void -class_add_behavior_method_list (Class class, MethodList_t list) -{ - int i; - static SEL initialize_sel = 0; - if (!initialize_sel) - initialize_sel = sel_register_name ("initialize"); - - /* Passing of a linked list is not allowed. Do multiple calls. */ - assert (!list->method_next); - - /* Check for duplicates. */ - for (i = 0; i < list->method_count; ++i) - { - Method_t method = &list->method_list[i]; - - if (method->method_name) /* Sometimes these are NULL */ - { - if (search_for_method_in_list (class->methods, method->method_name) - && method->method_name->sel_id != initialize_sel->sel_id) - { - /* Duplication. Print a error message an change the method name - to NULL. */ - fprintf (stderr, "attempt to add a existing method: %s\n", - sel_get_name(method->method_name)); - method->method_name = 0; - } - else - { - /* Behavior method not implemented in class. Add it. */ - sarray_at_put_safe (class->dtable, - (sidx) method->method_name->sel_id, - method->method_imp); - } - } - } - - /* Add the methods to the class's method list. */ - list->method_next = class->methods; - class->methods = list; -} -#endif - -/* Given a linked list of method and a method's name. Search for the named - method's method structure. Return a pointer to the method's method - structure if found. NULL otherwise. */ -static Method_t -search_for_method_in_list (MethodList_t list, SEL op) -{ - MethodList_t method_list = list; - - if (! sel_is_mapped (op)) - return NULL; - - /* If not found then we'll search the list. */ - while (method_list) - { - int i; - - /* Search the method list. */ - for (i = 0; i < method_list->method_count; ++i) - { - Method_t method = &method_list->method_list[i]; - - if (method->method_name) - if (method->method_name->sel_id == op->sel_id) - return method; - } - - /* The method wasn't found. Follow the link to the next list of - methods. */ - method_list = method_list->method_next; - } - - return NULL; -} - -/* Send +initialize to class if not already done */ -static void __objc_send_initialize(Class class) -{ - /* This *must* be a class object */ - assert(CLS_ISCLASS(class)); - assert(!CLS_ISMETA(class)); - - if (!CLS_ISINITIALIZED(class)) - { - CLS_SETINITIALIZED(class); - CLS_SETINITIALIZED(class->class_pointer); - - if(class->super_class) - __objc_send_initialize(class->super_class); - - { - MethodList_t method_list = class->class_pointer->methods; - SEL op = sel_register_name ("initialize"); - - /* If not found then we'll search the list. */ - while (method_list) - { - int i; - - /* Search the method list. */ - for (i = 0; i < method_list->method_count; ++i) - { - Method_t method = &method_list->method_list[i]; - - - if (method->method_name->sel_id == op->sel_id) - (*method->method_imp)((id) class, op); - } - - /* The method wasn't found. Follow the link to the next list of - methods. */ - method_list = method_list->method_next; - } - } - } -} - -#if 0 -static void -__objc_init_protocols (struct objc_protocol_list* protos) -{ - int i; - static Class proto_class = 0; - - if (! protos) - return; - - if (!proto_class) - proto_class = objc_lookup_class("Protocol"); - - if (!proto_class) - { - unclaimed_proto_list = list_cons (protos, unclaimed_proto_list); - return; - } - -#if 0 - assert (protos->next == 0); /* only single ones allowed */ -#endif - - for(i = 0; i < protos->count; i++) - { - struct objc_protocol* aProto = protos->list[i]; - if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION) - { - /* assign class pointer */ - aProto->class_pointer = proto_class; - - /* init super protocols */ - __objc_init_protocols (aProto->protocol_list); - } - else if (protos->list[i]->class_pointer != proto_class) - { - fprintf (stderr, - "Version %d doesn't match runtime protocol version %d\n", - (int)((char*)protos->list[i]->class_pointer-(char*)0), - PROTOCOL_VERSION); - abort (); - } - } -} - -static void __objc_class_add_protocols (Class class, - struct objc_protocol_list* protos) -{ - /* Well... */ - if (! protos) - return; - - /* Add it... */ - protos->next = class->protocols; - class->protocols = protos; -} -#endif /* 0 */ - -static BOOL class_is_kind_of(Class self, Class aClassObject) -{ - Class class; - - for (class = self; class!=Nil; class = class_get_super_class(class)) - if (class==aClassObject) - return YES; - return NO; -} - -void -check_class_methods(Class class) -{ - int counter; - MethodList_t mlist; - - if (class->dtable == __objc_uninstalled_dtable) - return; - - for (mlist = class->methods; mlist; mlist = mlist->method_next) - { - counter = mlist->method_count - 1; - while (counter >= 0) - { - Method_t method = &(mlist->method_list[counter]); - IMP imp = sarray_get(class->dtable, - (size_t)method->method_name->sel_id); - assert((imp == method->method_imp)); - sarray_at_put_safe (class->dtable, - (sidx) method->method_name->sel_id, - method->method_imp); - counter -= 1; - } - } - if (class->super_class) - check_class_methods(class->super_class); - - (void) &check_class_methods; /* to prevent compiler warning about unused */ -} -