mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
Initial revision
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@206 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ccdd9fa46c
commit
c10655a5bc
4 changed files with 788 additions and 0 deletions
43
Headers/gnustep/base/behavior.h
Normal file
43
Headers/gnustep/base/behavior.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* Interface for behaviors for Obj-C, "for Protocols with implementations".
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __behavior_h_OBJECTS_INCLUDE
|
||||
#define __behavior_h_OBJECTS_INCLUDE
|
||||
|
||||
/* Call this method from CLASS's +initialize method to add a behavior
|
||||
to CLASS. A "behavior" is like a protocol with an implementation.
|
||||
|
||||
This functions adds to CLASS all the instance and factory methods
|
||||
of BEHAVIOR as well as the instance and factory methods of
|
||||
BEHAVIOR's superclasses (We stop adding super classes as soon as we
|
||||
encounter a common ancestor.) CLASS and BEHAVIOR should share the
|
||||
same instance variable layout.
|
||||
|
||||
xxx We do not yet deal with Protocols, but we should. */
|
||||
void class_add_behavior (Class class, Class behavior);
|
||||
|
||||
|
||||
/* Set to non-zero if you want debugging messages on stderr. */
|
||||
void set_behavior_debug(int i);
|
||||
|
||||
#endif /* __behavior_h_OBJECTS_INCLUDE */
|
351
Source/behavior.c
Normal file
351
Source/behavior.c
Normal file
|
@ -0,0 +1,351 @@
|
|||
/* Behaviors for Objective-C, "for Protocols with implementations".
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <objc/objc-api.h>
|
||||
#include <objc/sarray.h>
|
||||
#include <objects/objc-malloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
static int debug_behavior = 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);
|
||||
void class_add_methods_if_not_there(Class class, MethodList_t mlist);
|
||||
|
||||
/* 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 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 */
|
||||
class_add_methods_if_not_there(class,
|
||||
behavior->methods);
|
||||
|
||||
/* Add class methods */
|
||||
class_add_methods_if_not_there(class->class_pointer,
|
||||
behavior->class_pointer->methods);
|
||||
|
||||
/* 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, MethodList_t mlist)
|
||||
{
|
||||
static SEL initialize_sel = 0;
|
||||
|
||||
if (!initialize_sel)
|
||||
initialize_sel = sel_register_name ("initialize");
|
||||
|
||||
/* Add methods to class->dtable and class->methods */
|
||||
for ( ; 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]));
|
||||
new_list->method_count = 0;
|
||||
|
||||
while (counter >= 0)
|
||||
{
|
||||
Method_t method = &(mlist->method_list[counter]);
|
||||
|
||||
if (debug_behavior)
|
||||
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. */
|
||||
sarray_at_put_safe (class->dtable,
|
||||
(sidx) method->method_name->sel_id,
|
||||
method->method_imp);
|
||||
new_list->method_list[new_list->method_count] = *method;
|
||||
(new_list->method_count)++;
|
||||
if (debug_behavior)
|
||||
fprintf(stderr, "added method %s\n",
|
||||
sel_get_name(method->method_name));
|
||||
}
|
||||
counter -= 1;
|
||||
}
|
||||
new_list->method_next = class->methods;
|
||||
class->methods = new_list;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
351
Source/behavior.m
Normal file
351
Source/behavior.m
Normal file
|
@ -0,0 +1,351 @@
|
|||
/* Behaviors for Objective-C, "for Protocols with implementations".
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <objc/objc-api.h>
|
||||
#include <objc/sarray.h>
|
||||
#include <objects/objc-malloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
static int debug_behavior = 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);
|
||||
void class_add_methods_if_not_there(Class class, MethodList_t mlist);
|
||||
|
||||
/* 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 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 */
|
||||
class_add_methods_if_not_there(class,
|
||||
behavior->methods);
|
||||
|
||||
/* Add class methods */
|
||||
class_add_methods_if_not_there(class->class_pointer,
|
||||
behavior->class_pointer->methods);
|
||||
|
||||
/* 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, MethodList_t mlist)
|
||||
{
|
||||
static SEL initialize_sel = 0;
|
||||
|
||||
if (!initialize_sel)
|
||||
initialize_sel = sel_register_name ("initialize");
|
||||
|
||||
/* Add methods to class->dtable and class->methods */
|
||||
for ( ; 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]));
|
||||
new_list->method_count = 0;
|
||||
|
||||
while (counter >= 0)
|
||||
{
|
||||
Method_t method = &(mlist->method_list[counter]);
|
||||
|
||||
if (debug_behavior)
|
||||
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. */
|
||||
sarray_at_put_safe (class->dtable,
|
||||
(sidx) method->method_name->sel_id,
|
||||
method->method_imp);
|
||||
new_list->method_list[new_list->method_count] = *method;
|
||||
(new_list->method_count)++;
|
||||
if (debug_behavior)
|
||||
fprintf(stderr, "added method %s\n",
|
||||
sel_get_name(method->method_name));
|
||||
}
|
||||
counter -= 1;
|
||||
}
|
||||
new_list->method_next = class->methods;
|
||||
class->methods = new_list;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
43
Source/objects/behavior.h
Normal file
43
Source/objects/behavior.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* Interface for behaviors for Obj-C, "for Protocols with implementations".
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __behavior_h_OBJECTS_INCLUDE
|
||||
#define __behavior_h_OBJECTS_INCLUDE
|
||||
|
||||
/* Call this method from CLASS's +initialize method to add a behavior
|
||||
to CLASS. A "behavior" is like a protocol with an implementation.
|
||||
|
||||
This functions adds to CLASS all the instance and factory methods
|
||||
of BEHAVIOR as well as the instance and factory methods of
|
||||
BEHAVIOR's superclasses (We stop adding super classes as soon as we
|
||||
encounter a common ancestor.) CLASS and BEHAVIOR should share the
|
||||
same instance variable layout.
|
||||
|
||||
xxx We do not yet deal with Protocols, but we should. */
|
||||
void class_add_behavior (Class class, Class behavior);
|
||||
|
||||
|
||||
/* Set to non-zero if you want debugging messages on stderr. */
|
||||
void set_behavior_debug(int i);
|
||||
|
||||
#endif /* __behavior_h_OBJECTS_INCLUDE */
|
Loading…
Reference in a new issue