mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-02 09:31:07 +00:00
remove obsolete code and update other stuff fro new runtime api
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29840 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f0105597d3
commit
42e39c0df8
3 changed files with 117 additions and 830 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2010-03-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Headers/Additions/GNUstepBase/GSObjCRuntime.h:
|
||||||
|
* Source/Additions/GSObjCRuntime.m:
|
||||||
|
Old 'experimental/work-in-progress' functions mostly removed ...
|
||||||
|
GSAllocMethodList() GSAppendMethodToList() GSRemoveMethodFromList()
|
||||||
|
GSMethodListForSelector() GSMethodFromList() GSAddMethodList()
|
||||||
|
GSRemoveMethodList()
|
||||||
|
Other functions rewritten in terms of the new runtime API and marked
|
||||||
|
as deprecated if they add nothing.
|
||||||
|
|
||||||
2010-03-04 Richard Frith-Macdonald <rfm@gnu.org>
|
2010-03-04 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSKeyValueObserving.m: use class_addMethod() to add setters
|
* Source/NSKeyValueObserving.m: use class_addMethod() to add setters
|
||||||
|
|
|
@ -125,31 +125,6 @@ extern "C" {
|
||||||
#define _C_GCINVISIBLE '!'
|
#define _C_GCINVISIBLE '!'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NeXT_RUNTIME)
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__GNUSTEP_RUNTIME__)
|
|
||||||
|
|
||||||
#define class_nextMethodList(aClass,anIterator) (({\
|
|
||||||
if (*(anIterator) == 0) \
|
|
||||||
*((struct objc_method_list**)(anIterator)) = (aClass)->methods; \
|
|
||||||
else \
|
|
||||||
*(anIterator) = (*((struct objc_method_list**)(anIterator)))->method_next; \
|
|
||||||
}), *(anIterator))
|
|
||||||
|
|
||||||
#else /* Old GNU runtime */
|
|
||||||
|
|
||||||
|
|
||||||
#define class_nextMethodList(aClass,anIterator) (({\
|
|
||||||
if (*(anIterator) == 0) \
|
|
||||||
*((struct objc_method_list**)(anIterator)) = (aClass)->methods; \
|
|
||||||
else \
|
|
||||||
*(anIterator) = (*((struct objc_method_list**)(anIterator)))->method_next; \
|
|
||||||
}), *(anIterator))
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions for accessing instance variables directly -
|
* Functions for accessing instance variables directly -
|
||||||
* We can copy an ivar into arbitrary data,
|
* We can copy an ivar into arbitrary data,
|
||||||
|
@ -167,10 +142,10 @@ GS_EXPORT void
|
||||||
GSObjCSetVariable(id obj, int offset, unsigned int size, const void *data);
|
GSObjCSetVariable(id obj, int offset, unsigned int size, const void *data);
|
||||||
|
|
||||||
GS_EXPORT NSArray *
|
GS_EXPORT NSArray *
|
||||||
GSObjCMethodNames(id obj);
|
GSObjCMethodNames(id obj, BOOL recurse);
|
||||||
|
|
||||||
GS_EXPORT NSArray *
|
GS_EXPORT NSArray *
|
||||||
GSObjCVariableNames(id obj);
|
GSObjCVariableNames(id obj, BOOL recurse);
|
||||||
|
|
||||||
GS_EXPORT void
|
GS_EXPORT void
|
||||||
GSObjCAddClassBehavior(Class receiver, Class behavior);
|
GSObjCAddClassBehavior(Class receiver, Class behavior);
|
||||||
|
@ -181,6 +156,18 @@ GSObjCMakeClass(NSString *name, NSString *superName, NSDictionary *iVars);
|
||||||
GS_EXPORT void
|
GS_EXPORT void
|
||||||
GSObjCAddClasses(NSArray *classes);
|
GSObjCAddClasses(NSArray *classes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a NULL terminated list of methods, add them to the class.<br />
|
||||||
|
* If the method already exists in a superclass, the new version overrides
|
||||||
|
* that one, but if the method already exists in the class itsself, the
|
||||||
|
* new one is quietly ignored (replace==NO) or replaced with the new
|
||||||
|
* version (if replace==YES).<br />
|
||||||
|
* To add class methods, cls should be the metaclass of the class to
|
||||||
|
* which the methods are being added.
|
||||||
|
*/
|
||||||
|
GS_EXPORT void
|
||||||
|
GSObjCAddMethods(Class cls, Method *list, BOOL replace);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions for key-value encoding ... they access values in an object
|
* Functions for key-value encoding ... they access values in an object
|
||||||
* either by selector or directly, but do so using NSNumber for the
|
* either by selector or directly, but do so using NSNumber for the
|
||||||
|
@ -203,19 +190,7 @@ GSObjCSetVal(NSObject *self, const char *key, id val, SEL sel,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills a nil terminated array of Class objects referenced by buffer
|
* Deprecated ... use objc_getClassList()
|
||||||
* with max number of classes registered with the objc runtime.
|
|
||||||
* The provided buffer must be large enough to hold max + 1 Class objects.
|
|
||||||
* If buffer is nil, the function returns the number of Class
|
|
||||||
* objects that would be inserted if the buffer is large enough.
|
|
||||||
* Otherwise returns the number of Class objects that did not fit
|
|
||||||
* into the provided buffer. This function keeps a cache of the class
|
|
||||||
* list for future invocations when used with the GNU runtime. If
|
|
||||||
* clearCache is YES, this cache will be invalidated and rebuild. The
|
|
||||||
* flag has no effect for the NeXT runtime.
|
|
||||||
* This function is provided as consistent API to both runtimes.
|
|
||||||
* In the case of the GNU runtime it is likely more efficient to use
|
|
||||||
* objc_next_class() to iterate over the classes.
|
|
||||||
*/
|
*/
|
||||||
GS_EXPORT unsigned int
|
GS_EXPORT unsigned int
|
||||||
GSClassList(Class *buffer, unsigned int max, BOOL clearCache);
|
GSClassList(Class *buffer, unsigned int max, BOOL clearCache);
|
||||||
|
@ -325,9 +300,8 @@ GSRegisterProtocol(Protocol *proto);
|
||||||
* are incompatible between the GNU and NeXT/Apple runtimes.
|
* are incompatible between the GNU and NeXT/Apple runtimes.
|
||||||
* We introduce GSMethod, GSMethodList and GSIVar to allow portability.
|
* We introduce GSMethod, GSMethodList and GSIVar to allow portability.
|
||||||
*/
|
*/
|
||||||
typedef struct objc_method *GSMethod;
|
typedef Method GSMethod;
|
||||||
typedef struct objc_method_list *GSMethodList;
|
typedef Ivar GSIVar;
|
||||||
typedef struct objc_ivar *GSIVar;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pointer to the method structure
|
* Returns the pointer to the method structure
|
||||||
|
@ -349,208 +323,29 @@ GSGetMethod(Class cls, SEL sel,
|
||||||
BOOL searchSuperClasses);
|
BOOL searchSuperClasses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flushes the cached method dispatch table for the class.
|
* Deprecated .. does nothing.
|
||||||
* Call this function after any manipulations in the method structures.<br/>
|
|
||||||
* It should be safe to use this function in +load implementations.<br/>
|
|
||||||
* This function should currently (June 2003) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.
|
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void
|
GS_EXPORT void
|
||||||
GSFlushMethodCacheForClass (Class cls);
|
GSFlushMethodCacheForClass (Class cls);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pointer to the instance variable structure
|
* Deprecated .. use class_getInstanceVariable()
|
||||||
* for the instance variable name in the specified class.
|
|
||||||
* This function searches the specified class and its superclasses.<br/>
|
|
||||||
* It should be safe to use this function in +load implementations.<br/>
|
|
||||||
* This function should currently (June 2003) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.
|
|
||||||
*/
|
*/
|
||||||
GS_EXPORT GSIVar
|
GS_EXPORT GSIVar
|
||||||
GSCGetInstanceVariableDefinition(Class cls, const char *name);
|
GSCGetInstanceVariableDefinition(Class cls, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pointer to the instance variable structure
|
* Deprecated .. use class_getInstanceVariable()
|
||||||
* for the instance variable name in the specified class.
|
|
||||||
* This function searches the specified class and its superclasses.<br/>
|
|
||||||
* It is not necessarily safe to use this function
|
|
||||||
* in +load implementations.<br/>
|
|
||||||
* This function should currently (June 2003) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.
|
|
||||||
*/
|
*/
|
||||||
GS_EXPORT GSIVar
|
GS_EXPORT GSIVar
|
||||||
GSObjCGetInstanceVariableDefinition(Class cls, NSString *name);
|
GSObjCGetInstanceVariableDefinition(Class cls, NSString *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns a pointer to objc_malloc'ed memory large enough
|
|
||||||
* to hold a struct objc_method_list with 'count' number of
|
|
||||||
* struct objc_method entries. The memory returned is
|
|
||||||
* initialized with 0, including the method count and
|
|
||||||
* next method list fields. </p>
|
|
||||||
* <p> This function is intended for use in conjunction with
|
|
||||||
* GSAppendMethodToList() to fill the memory and GSAddMethodList()
|
|
||||||
* to activate the method list. </p>
|
|
||||||
* <p>After method list manipulation you should call
|
|
||||||
* GSFlushMethodCacheForClass() for the changes to take effect.</p>
|
|
||||||
* <p><em>WARNING:</em> Manipulating the runtime structures
|
|
||||||
* can be hazardous!</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
GSMethodList
|
|
||||||
GSAllocMethodList (unsigned int count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Inserts the method described by sel, types and imp
|
|
||||||
* into the slot of the list's method_count incremented by 1.
|
|
||||||
* This function does not and cannot check whether
|
|
||||||
* the list provided has the necessary capacity.</p>
|
|
||||||
* <p>The GNU runtime makes a difference between method lists
|
|
||||||
* that are "free standing" and those that "attached" to classes.
|
|
||||||
* For "free standing" method lists (e.g. created with GSAllocMethodList()
|
|
||||||
* that have not been added to a class or those which have been removed
|
|
||||||
* via GSRemoveMethodList()) isFree must be passed YES.
|
|
||||||
* When manipulating "attached" method lists, specify NO.</p>
|
|
||||||
* <p>This function is intended for use in conjunction with
|
|
||||||
* GSAllocMethodList() to allocate the list and GSAddMethodList()
|
|
||||||
* to activate the method list. </p>
|
|
||||||
* <p>After method list manipulation you should call
|
|
||||||
* GSFlushMethodCacheForClass() for the changes to take effect.</p>
|
|
||||||
* <p><em>WARNING:</em> Manipulating the runtime structures
|
|
||||||
* can be hazardous!</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
GSAppendMethodToList (GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
const char *types,
|
|
||||||
IMP imp,
|
|
||||||
BOOL isFree);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Removes the method identified by sel
|
|
||||||
* from the method list moving the following methods up in the list,
|
|
||||||
* leaving the last entry blank. After this call, all references
|
|
||||||
* of previous GSMethodFromList() calls with this list should be
|
|
||||||
* considered invalid. If the values they referenced are needed, they
|
|
||||||
* must be copied to external buffers before this function is called.</p>
|
|
||||||
* <p>Returns YES if the a matching method was found a removed,
|
|
||||||
* NO otherwise.</p>
|
|
||||||
* <p>The GNU runtime makes a difference between method lists
|
|
||||||
* that are "free standing" and those that "attached" to classes.
|
|
||||||
* For "free standing" method lists (e.g. created with GSAllocMethodList()
|
|
||||||
* that have not been added to a class or those which have been removed
|
|
||||||
* via GSRemoveMethodList()) isFree must be passed YES.
|
|
||||||
* When manipulating "attached" method lists, specify NO.</p>
|
|
||||||
* <p>After method list manipulation you should call
|
|
||||||
* GSFlushMethodCacheForClass() for the changes to take effect.</p>
|
|
||||||
* <p><em>WARNING:</em> Manipulating the runtime structures
|
|
||||||
* can be hazardous!</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
GSRemoveMethodFromList (GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
BOOL isFree);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns a method list of the class that contains the selector.
|
|
||||||
* Depending on searchInstanceMethods either instance or class methods
|
|
||||||
* are searched.
|
|
||||||
* Returns NULL if none are found.
|
|
||||||
* This function does not search the superclasses method lists.
|
|
||||||
* Call this method with the address of a <code>void *</code>
|
|
||||||
* pointing to NULL to obtain the first (active) method list
|
|
||||||
* containing the selector.
|
|
||||||
* Subsequent calls will return further method lists which contain the
|
|
||||||
* selector. If none are found, it returns NULL.
|
|
||||||
* You may instead pass NULL as the iterator in which case the first
|
|
||||||
* method list containing the selector will be returned.
|
|
||||||
* Do not call it with an uninitialized iterator.
|
|
||||||
* If either class or selector are NULL the function returns NULL.
|
|
||||||
* If subsequent calls to this function with the same non-NULL iterator yet
|
|
||||||
* different searchInstanceMethods value are called, the behavior
|
|
||||||
* is undefined.</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
GSMethodList
|
|
||||||
GSMethodListForSelector(Class cls,
|
|
||||||
SEL selector,
|
|
||||||
void **iterator,
|
|
||||||
BOOL searchInstanceMethods);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns the (first) GSMethod contained in the supplied list
|
|
||||||
* that corresponds to sel.
|
|
||||||
* Returns NULL if none is found.</p>
|
|
||||||
* <p>The GNU runtime makes a difference between method lists
|
|
||||||
* that are "free standing" and those that "attached" to classes.
|
|
||||||
* For "free standing" method lists (e.g. created with GSAllocMethodList()
|
|
||||||
* that have not been added to a class or those which have been removed
|
|
||||||
* via GSRemoveMethodList()) isFree must be passed YES.
|
|
||||||
* When manipulating "attached" method lists, specify NO.</p>
|
|
||||||
*/
|
|
||||||
GSMethod
|
|
||||||
GSMethodFromList(GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
BOOL isFree);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Add the method list to the class as the first list to be
|
|
||||||
* searched during method invocation for the given class.
|
|
||||||
* Depending on toInstanceMethods, this list will be added as
|
|
||||||
* an instance or a class method list.
|
|
||||||
* If the list is in use by another class, behavior is undefined.
|
|
||||||
* Create a new list with GSAllocMethodList() or use GSRemoveMethodList()
|
|
||||||
* to remove a list before inserting it in a class.</p>
|
|
||||||
* <p>After method list manipulation you should call
|
|
||||||
* GSFlushMethodCacheForClass() for the changes to take effect.</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
GSAddMethodList(Class cls,
|
|
||||||
GSMethodList list,
|
|
||||||
BOOL toInstanceMethods);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Removes the method list from the classes instance or class method
|
|
||||||
* lists depending on fromInstanceMethods.
|
|
||||||
* If the list is not part of the class, behavior is undefined.</p>
|
|
||||||
* <p>After method list manipulation you should call
|
|
||||||
* GSFlushMethodCacheForClass() for the changes to take effect.</p>
|
|
||||||
* <p>This function should currently (June 2004) be considered WIP.
|
|
||||||
* Please follow potential changes (Name, parameters, ...) closely until
|
|
||||||
* it stabilizes.</p>
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
GSRemoveMethodList(Class cls,
|
|
||||||
GSMethodList list,
|
|
||||||
BOOL fromInstanceMethods);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GSObjCVersion() is deprecated ... use class_getVersion()
|
* GSObjCVersion() is deprecated ... use class_getVersion()
|
||||||
*/
|
*/
|
||||||
GS_EXPORT int GSObjCVersion(Class cls);
|
GS_EXPORT int GSObjCVersion(Class cls);
|
||||||
|
|
||||||
#ifndef NeXT_Foundation_LIBRARY
|
#import <Foundation/NSZone.h>
|
||||||
#include <Foundation/NSZone.h>
|
|
||||||
#else
|
|
||||||
#include <Foundation/Foundation.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GSObjCZone() is deprecated ... use -zone
|
* GSObjCZone() is deprecated ... use -zone
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -186,11 +186,6 @@ GSTypesFromSelector(SEL sel)
|
||||||
void
|
void
|
||||||
GSFlushMethodCacheForClass (Class cls)
|
GSFlushMethodCacheForClass (Class cls)
|
||||||
{
|
{
|
||||||
#if NeXT_RUNTIME
|
|
||||||
#else
|
|
||||||
extern void __objc_update_dispatch_table_for_class (Class);
|
|
||||||
__objc_update_dispatch_table_for_class (cls);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
|
@ -250,7 +245,7 @@ GSObjCFindVariable(id obj, const char *name,
|
||||||
* Returns nil if obj is nil.
|
* Returns nil if obj is nil.
|
||||||
*/
|
*/
|
||||||
NSArray *
|
NSArray *
|
||||||
GSObjCMethodNames(id obj)
|
GSObjCMethodNames(id obj, BOOL recurse)
|
||||||
{
|
{
|
||||||
NSMutableSet *set;
|
NSMutableSet *set;
|
||||||
NSArray *array;
|
NSArray *array;
|
||||||
|
@ -286,6 +281,10 @@ GSObjCMethodNames(id obj)
|
||||||
{
|
{
|
||||||
free(meth);
|
free(meth);
|
||||||
}
|
}
|
||||||
|
if (NO == recurse)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
class = class_getSuperclass(class);
|
class = class_getSuperclass(class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +300,7 @@ GSObjCMethodNames(id obj)
|
||||||
* Returns nil if obj is nil.
|
* Returns nil if obj is nil.
|
||||||
*/
|
*/
|
||||||
NSArray *
|
NSArray *
|
||||||
GSObjCVariableNames(id obj)
|
GSObjCVariableNames(id obj, BOOL recurse)
|
||||||
{
|
{
|
||||||
NSMutableSet *set;
|
NSMutableSet *set;
|
||||||
NSArray *array;
|
NSArray *array;
|
||||||
|
@ -337,6 +336,10 @@ GSObjCVariableNames(id obj)
|
||||||
{
|
{
|
||||||
free(ivar);
|
free(ivar);
|
||||||
}
|
}
|
||||||
|
if (NO == recurse)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
class = class_getSuperclass(class);
|
class = class_getSuperclass(class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +375,6 @@ GSObjCSetVariable(id obj, int offset, unsigned int size, const void *data)
|
||||||
GS_EXPORT unsigned int
|
GS_EXPORT unsigned int
|
||||||
GSClassList(Class *buffer, unsigned int max, BOOL clearCache)
|
GSClassList(Class *buffer, unsigned int max, BOOL clearCache)
|
||||||
{
|
{
|
||||||
#ifdef NeXT_RUNTIME
|
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
|
@ -382,68 +384,6 @@ GSClassList(Class *buffer, unsigned int max, BOOL clearCache)
|
||||||
|
|
||||||
num = objc_getClassList(buffer, max);
|
num = objc_getClassList(buffer, max);
|
||||||
num = (num < 0) ? 0 : num;
|
num = (num < 0) ? 0 : num;
|
||||||
|
|
||||||
#else
|
|
||||||
static Class *cache = 0;
|
|
||||||
static unsigned cacheClassCount = 0;
|
|
||||||
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
unsigned int num;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&cache_lock);
|
|
||||||
|
|
||||||
if (clearCache)
|
|
||||||
{
|
|
||||||
if (cache)
|
|
||||||
{
|
|
||||||
free(cache);
|
|
||||||
cache = NULL;
|
|
||||||
}
|
|
||||||
cacheClassCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache == NULL)
|
|
||||||
{
|
|
||||||
void *iterator = 0;
|
|
||||||
Class cls;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
cacheClassCount = 0;
|
|
||||||
while ((cls = objc_next_class(&iterator)))
|
|
||||||
{
|
|
||||||
cacheClassCount++;
|
|
||||||
}
|
|
||||||
cache = malloc(sizeof(Class) * (cacheClassCount + 1));
|
|
||||||
/* Be extra careful as another thread may be loading classes. */
|
|
||||||
for (i = 0, iterator = 0, cls = objc_next_class(&iterator);
|
|
||||||
i < cacheClassCount && cls != NULL;
|
|
||||||
i++, cls = objc_next_class(&iterator))
|
|
||||||
{
|
|
||||||
cache[i] = cls;
|
|
||||||
}
|
|
||||||
cache[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer == NULL)
|
|
||||||
{
|
|
||||||
num = cacheClassCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size_t cpySize;
|
|
||||||
unsigned int cpyCnt;
|
|
||||||
|
|
||||||
cpyCnt = MIN(max, cacheClassCount);
|
|
||||||
cpySize = sizeof(Class) * cpyCnt;
|
|
||||||
memcpy(buffer, cache, cpySize);
|
|
||||||
buffer[cpyCnt] = NULL;
|
|
||||||
|
|
||||||
num = (max > cacheClassCount) ? 0 : (cacheClassCount - max);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&cache_lock);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,203 +485,39 @@ GSObjCBehaviorDebug(int i)
|
||||||
behavior_debug = i;
|
behavior_debug = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NeXT_RUNTIME
|
|
||||||
|
|
||||||
static GSMethod search_for_method_in_class (Class cls, SEL op);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GSObjCAddMethods (Class cls, GSMethodList methods)
|
GSObjCAddMethods(Class cls, Method *list, BOOL replace)
|
||||||
{
|
{
|
||||||
static SEL initialize_sel = 0;
|
unsigned int index = 0;
|
||||||
GSMethodList mlist;
|
Method m;
|
||||||
|
|
||||||
if (!initialize_sel)
|
if (cls == 0 || list == 0)
|
||||||
initialize_sel = sel_register_name ("initialize");
|
|
||||||
|
|
||||||
/* Add methods to cls->dtable and cls->methods */
|
|
||||||
mlist = methods;
|
|
||||||
{
|
{
|
||||||
int counter;
|
return;
|
||||||
GSMethodList new_list;
|
|
||||||
|
|
||||||
counter = mlist->method_count ? mlist->method_count - 1 : 1;
|
|
||||||
|
|
||||||
/* This is a little wasteful of memory, since not necessarily
|
|
||||||
all methods will go in here. */
|
|
||||||
new_list = (GSMethodList)
|
|
||||||
malloc (sizeof(struct objc_method_list) +
|
|
||||||
sizeof(struct objc_method[counter+1]));
|
|
||||||
new_list->method_count = 0;
|
|
||||||
|
|
||||||
while (counter >= 0)
|
|
||||||
{
|
|
||||||
GSMethod method = &(mlist->method_list[counter]);
|
|
||||||
|
|
||||||
BDBGPrintf(" processing method [%s] ... ",
|
|
||||||
GSNameFromSelector(method->method_name));
|
|
||||||
|
|
||||||
if (!search_for_method_in_class(cls, method->method_name)
|
|
||||||
&& !sel_isEqual(method->method_name, initialize_sel))
|
|
||||||
{
|
|
||||||
/* As long as the method isn't defined in the CLASS,
|
|
||||||
put the BEHAVIOR method in there. Thus, behavior
|
|
||||||
methods override the superclasses' methods. */
|
|
||||||
new_list->method_list[new_list->method_count] = *method;
|
|
||||||
(new_list->method_count)++;
|
|
||||||
|
|
||||||
BDBGPrintf("added.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BDBGPrintf("ignored.\n");
|
|
||||||
}
|
|
||||||
counter -= 1;
|
|
||||||
}
|
|
||||||
if (new_list->method_count)
|
|
||||||
{
|
|
||||||
class_add_method_list(cls, new_list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OBJC_FREE(new_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search for the named method's method structure. Return a pointer
|
|
||||||
to the method's method structure if found. NULL otherwise. */
|
|
||||||
static GSMethod
|
|
||||||
search_for_method_in_class (Class cls, SEL op)
|
|
||||||
{
|
|
||||||
void *iterator = 0;
|
|
||||||
GSMethodList method_list;
|
|
||||||
|
|
||||||
if (! sel_is_mapped (op))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* If not found then we'll search the list. */
|
|
||||||
while ((method_list = class_nextMethodList(cls, &iterator)))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Search the method list. */
|
|
||||||
for (i = 0; i < method_list->method_count; ++i)
|
|
||||||
{
|
|
||||||
GSMethod method = &method_list->method_list[i];
|
|
||||||
|
|
||||||
if (method->method_name)
|
|
||||||
{
|
|
||||||
if (sel_isEqual(method->method_name, op))
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
while ((m = list[index++]) != NULL)
|
||||||
}
|
|
||||||
|
|
||||||
#else /* GNU runtime */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following two functions are implemented in the GNU objc runtime
|
|
||||||
*/
|
|
||||||
extern Method_t search_for_method_in_list(MethodList_t list, SEL op);
|
|
||||||
extern void class_add_method_list(Class, MethodList_t);
|
|
||||||
|
|
||||||
static Method_t search_for_method_in_class (Class cls, SEL op);
|
|
||||||
|
|
||||||
extern objc_mutex_t __objc_runtime_mutex;
|
|
||||||
|
|
||||||
void
|
|
||||||
GSObjCAddMethods (Class cls, GSMethodList methods)
|
|
||||||
{
|
|
||||||
static SEL initialize_sel = 0;
|
|
||||||
GSMethodList mlist;
|
|
||||||
|
|
||||||
if (initialize_sel == 0)
|
|
||||||
{
|
{
|
||||||
initialize_sel = sel_register_name ("initialize");
|
SEL n = method_getName(m);
|
||||||
}
|
IMP i = method_getImplementation(m);
|
||||||
|
const char *t = method_getTypeEncoding(m);
|
||||||
|
|
||||||
objc_mutex_lock (__objc_runtime_mutex);
|
/* This will override a superclass method but will not replace a
|
||||||
|
* method which already exists in the class itsself.
|
||||||
/* Add methods to class->dtable and class->methods */
|
*/
|
||||||
for (mlist = methods; mlist; mlist = mlist->method_next)
|
if (NO == class_addMethod(cls, n, i, t) && YES == replace)
|
||||||
{
|
|
||||||
int counter;
|
|
||||||
GSMethodList new_list;
|
|
||||||
|
|
||||||
counter = mlist->method_count ? mlist->method_count - 1 : 1;
|
|
||||||
|
|
||||||
/* This is a little wasteful of memory, since not necessarily
|
|
||||||
all methods will go in here. */
|
|
||||||
new_list = (GSMethodList)
|
|
||||||
malloc (sizeof(struct objc_method_list) +
|
|
||||||
sizeof(struct objc_method[counter+1]));
|
|
||||||
new_list->method_count = 0;
|
|
||||||
new_list->method_next = NULL;
|
|
||||||
|
|
||||||
while (counter >= 0)
|
|
||||||
{
|
|
||||||
GSMethod method = &(mlist->method_list[counter]);
|
|
||||||
const char *name = GSNameFromSelector(method->method_name);
|
|
||||||
|
|
||||||
BDBGPrintf(" processing method [%s] ... ", name);
|
|
||||||
|
|
||||||
if (!search_for_method_in_list(cls->methods, method->method_name)
|
|
||||||
&& !sel_isEqual(method->method_name, initialize_sel))
|
|
||||||
{
|
|
||||||
/* As long as the method isn't defined in the CLASS,
|
|
||||||
put the BEHAVIOR method in there. Thus, behavior
|
|
||||||
methods override the superclasses' methods. */
|
|
||||||
new_list->method_list[new_list->method_count] = *method;
|
|
||||||
/*
|
|
||||||
* HACK ... the GNU runtime implementation of
|
|
||||||
* class_add_method_list() expects the method names to be
|
|
||||||
* C-strings rather than selectors ... so we must allow
|
|
||||||
* for that.
|
|
||||||
*/
|
|
||||||
new_list->method_list[new_list->method_count].method_name
|
|
||||||
= (SEL)name;
|
|
||||||
(new_list->method_count)++;
|
|
||||||
|
|
||||||
BDBGPrintf("added.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BDBGPrintf("ignored.\n");
|
|
||||||
}
|
|
||||||
counter -= 1;
|
|
||||||
}
|
|
||||||
if (new_list->method_count)
|
|
||||||
{
|
{
|
||||||
class_add_method_list(cls, new_list);
|
/* If we want to replace an existing implemetation ...
|
||||||
}
|
*/
|
||||||
else
|
method_setImplementation(class_getInstanceMethod(cls, n), i);
|
||||||
{
|
}
|
||||||
OBJC_FREE(new_list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
objc_mutex_unlock (__objc_runtime_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Method_t
|
|
||||||
search_for_method_in_class (Class cls, SEL op)
|
|
||||||
{
|
|
||||||
Method_t m;
|
|
||||||
|
|
||||||
objc_mutex_lock (__objc_runtime_mutex);
|
|
||||||
m = cls != NULL ? search_for_method_in_list(cls->methods, op) : NULL;
|
|
||||||
objc_mutex_unlock (__objc_runtime_mutex);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NeXT runtime */
|
|
||||||
|
|
||||||
GSMethod
|
GSMethod
|
||||||
GSGetMethod(Class cls, SEL sel,
|
GSGetMethod(Class cls, SEL sel,
|
||||||
BOOL searchInstanceMethods,
|
BOOL searchInstanceMethods,
|
||||||
BOOL searchSuperClasses)
|
BOOL searchSuperClasses)
|
||||||
{
|
{
|
||||||
if (cls == 0 || sel == 0)
|
if (cls == 0 || sel == 0)
|
||||||
{
|
{
|
||||||
|
@ -750,306 +526,44 @@ GSGetMethod(Class cls, SEL sel,
|
||||||
|
|
||||||
if (searchSuperClasses == NO)
|
if (searchSuperClasses == NO)
|
||||||
{
|
{
|
||||||
|
unsigned int count;
|
||||||
|
Method method = NULL;
|
||||||
|
Method *methods;
|
||||||
|
|
||||||
if (searchInstanceMethods == NO)
|
if (searchInstanceMethods == NO)
|
||||||
{
|
{
|
||||||
return search_for_method_in_class(cls->class_pointer, sel);
|
methods = class_copyMethodList(object_getClass(cls), &count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return search_for_method_in_class(cls, sel);
|
methods = class_copyMethodList(cls, &count);
|
||||||
}
|
}
|
||||||
}
|
if (methods != NULL)
|
||||||
else
|
|
||||||
{
|
|
||||||
if (searchInstanceMethods == NO)
|
|
||||||
{
|
{
|
||||||
/*
|
unsigned int index = 0;
|
||||||
We do not rely on the mapping supplied in objc_gnu2next.h
|
|
||||||
because we want to be explicit about the fact
|
|
||||||
that the expected parameters are different.
|
|
||||||
Therefor we refrain from simply using class_getClassMethod().
|
|
||||||
*/
|
|
||||||
#ifdef NeXT_RUNTIME
|
|
||||||
return class_getClassMethod(cls, sel);
|
|
||||||
#else
|
|
||||||
return class_get_class_method(cls->class_pointer, sel);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return class_get_instance_method(cls, sel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while ((method = methods[index++]) != NULL)
|
||||||
/* See header for documentation. */
|
|
||||||
GSMethodList
|
|
||||||
GSAllocMethodList (unsigned int count)
|
|
||||||
{
|
|
||||||
GSMethodList list;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
size = (sizeof (struct objc_method_list) +
|
|
||||||
sizeof (struct objc_method[count]));
|
|
||||||
list = malloc (size);
|
|
||||||
memset(list, 0, size);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
void
|
|
||||||
GSAppendMethodToList (GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
const char *types,
|
|
||||||
IMP imp,
|
|
||||||
BOOL isFree)
|
|
||||||
{
|
|
||||||
unsigned int num;
|
|
||||||
|
|
||||||
num = (list->method_count)++;
|
|
||||||
|
|
||||||
#ifdef GNU_RUNTIME
|
|
||||||
/*
|
|
||||||
Deal with typed selectors: No matter what kind of selector we get
|
|
||||||
convert it into a c-string. Cache that c-string incase the
|
|
||||||
selector isn't found, then search for corresponding typed selector.
|
|
||||||
If none is found use the cached name to register an new selector
|
|
||||||
with the corresponding types.
|
|
||||||
*/
|
|
||||||
sel = (SEL)GSNameFromSelector (sel);
|
|
||||||
|
|
||||||
if (isFree == NO)
|
|
||||||
{
|
|
||||||
const char *sel_save = (const char *)sel;
|
|
||||||
|
|
||||||
sel = sel_get_typed_uid (sel_save, types);
|
|
||||||
if (sel == 0)
|
|
||||||
{
|
|
||||||
sel = sel_register_typed_name (sel_save, types);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
list->method_list[num].method_name = sel;
|
|
||||||
list->method_list[num].method_types = strdup(types);
|
|
||||||
list->method_list[num].method_imp = imp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
BOOL
|
|
||||||
GSRemoveMethodFromList (GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
BOOL isFree)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef GNU_RUNTIME
|
|
||||||
if (isFree == YES)
|
|
||||||
{
|
|
||||||
sel = (SEL)GSNameFromSelector (sel);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Insure that we always use sel_isEqual on non GNU Runtimes. */
|
|
||||||
isFree = NO;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < list->method_count; i++)
|
|
||||||
{
|
|
||||||
SEL method_name = list->method_list[i].method_name;
|
|
||||||
|
|
||||||
/* For the GNU runtime we have use strcmp instead of sel_isEqual
|
|
||||||
for free standing method lists. */
|
|
||||||
if ((isFree == YES && strcmp((char *)method_name, (char *)sel) == 0)
|
|
||||||
|| (isFree == NO && sel_isEqual(method_name, sel)))
|
|
||||||
{
|
|
||||||
/* Found the list. Now fill up the gap. */
|
|
||||||
for ((list->method_count)--; i < list->method_count; i++)
|
|
||||||
{
|
|
||||||
list->method_list[i].method_name
|
|
||||||
= list->method_list[i+1].method_name;
|
|
||||||
list->method_list[i].method_types
|
|
||||||
= list->method_list[i+1].method_types;
|
|
||||||
list->method_list[i].method_imp
|
|
||||||
= list->method_list[i+1].method_imp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the last entry. */
|
|
||||||
/* NB: We may leak the types if they were previously
|
|
||||||
set by GSAppendMethodFromList. Yet as we can not
|
|
||||||
determine the origin, we shall leak. */
|
|
||||||
list->method_list[i].method_name = 0;
|
|
||||||
list->method_list[i].method_types = 0;
|
|
||||||
list->method_list[i].method_imp = 0;
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
GSMethodList
|
|
||||||
GSMethodListForSelector(Class cls,
|
|
||||||
SEL selector,
|
|
||||||
void **iterator,
|
|
||||||
BOOL searchInstanceMethods)
|
|
||||||
{
|
|
||||||
void *local_iterator = 0;
|
|
||||||
|
|
||||||
if (cls == 0 || selector == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchInstanceMethods == NO)
|
|
||||||
{
|
|
||||||
cls = cls->class_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sel_is_mapped(selector))
|
|
||||||
{
|
|
||||||
void **iterator_pointer;
|
|
||||||
GSMethodList method_list;
|
|
||||||
|
|
||||||
iterator_pointer = (iterator == 0 ? &local_iterator : iterator);
|
|
||||||
while ((method_list = class_nextMethodList(cls, iterator_pointer)))
|
|
||||||
{
|
|
||||||
/* Search the method in the current list. */
|
|
||||||
if (GSMethodFromList(method_list, selector, NO) != 0)
|
|
||||||
{
|
{
|
||||||
return method_list;
|
if (sel_isEqual(sel, method_getName(method)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
free(methods);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
GSMethod
|
|
||||||
GSMethodFromList(GSMethodList list,
|
|
||||||
SEL sel,
|
|
||||||
BOOL isFree)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
#ifdef GNU_RUNTIME
|
|
||||||
if (isFree)
|
|
||||||
{
|
|
||||||
sel = (SEL)GSNameFromSelector (sel);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
isFree = NO;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < list->method_count; ++i)
|
|
||||||
{
|
|
||||||
GSMethod method = &list->method_list[i];
|
|
||||||
SEL method_name = method->method_name;
|
|
||||||
|
|
||||||
/* For the GNU runtime we have use strcmp instead of sel_isEqual
|
|
||||||
for free standing method lists. */
|
|
||||||
if ((isFree == YES && strcmp((char *)method_name, (char *)sel) == 0)
|
|
||||||
|| (isFree == NO && sel_isEqual(method_name, sel)))
|
|
||||||
{
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
}
|
return method;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
void
|
|
||||||
GSAddMethodList(Class cls,
|
|
||||||
GSMethodList list,
|
|
||||||
BOOL toInstanceMethods)
|
|
||||||
{
|
|
||||||
if (cls == 0 || list == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toInstanceMethods == NO)
|
|
||||||
{
|
|
||||||
cls = cls->class_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
class_add_method_list(cls, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
gs_revert_selector_names_in_list(GSMethodList list)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
for (i = 0; i < list->method_count; i++)
|
|
||||||
{
|
|
||||||
name = GSNameFromSelector(list->method_list[i].method_name);
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
list->method_list[i].method_name = (SEL)name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See header for documentation. */
|
|
||||||
void
|
|
||||||
GSRemoveMethodList(Class cls,
|
|
||||||
GSMethodList list,
|
|
||||||
BOOL fromInstanceMethods)
|
|
||||||
{
|
|
||||||
if (cls == 0 || list == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fromInstanceMethods == NO)
|
|
||||||
{
|
|
||||||
cls = cls->class_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NeXT_RUNTIME
|
|
||||||
class_removeMethods(cls, list);
|
|
||||||
#else
|
|
||||||
if (list == cls->methods)
|
|
||||||
{
|
|
||||||
cls->methods = list->method_next;
|
|
||||||
list->method_next = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
The list has become "free standing".
|
|
||||||
Replace all selector references with selector names
|
|
||||||
so the runtime can convert them again
|
|
||||||
it the list gets reinserted.
|
|
||||||
*/
|
|
||||||
gs_revert_selector_names_in_list(list);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GSMethodList current_list;
|
if (searchInstanceMethods == NO)
|
||||||
for (current_list = cls->methods;
|
{
|
||||||
current_list != 0;
|
return class_getClassMethod(cls, sel);
|
||||||
current_list = current_list->method_next)
|
}
|
||||||
{
|
else
|
||||||
if (current_list->method_next == list)
|
{
|
||||||
{
|
return class_getInstanceMethod(cls, sel);
|
||||||
current_list->method_next = list->method_next;
|
}
|
||||||
list->method_next = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
The list has become "free standing".
|
|
||||||
Replace all selector references with selector names
|
|
||||||
so the runtime can convert them again
|
|
||||||
it the list gets reinserted.
|
|
||||||
*/
|
|
||||||
gs_revert_selector_names_in_list(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* NeXT_RUNTIME */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1057,16 +571,16 @@ static inline const char *
|
||||||
gs_skip_type_qualifier_and_layout_info (const char *types)
|
gs_skip_type_qualifier_and_layout_info (const char *types)
|
||||||
{
|
{
|
||||||
while (*types == '+'
|
while (*types == '+'
|
||||||
|| *types == '-'
|
|| *types == '-'
|
||||||
|| *types == _C_CONST
|
|| *types == _C_CONST
|
||||||
|| *types == _C_IN
|
|| *types == _C_IN
|
||||||
|| *types == _C_INOUT
|
|| *types == _C_INOUT
|
||||||
|| *types == _C_OUT
|
|| *types == _C_OUT
|
||||||
|| *types == _C_BYCOPY
|
|| *types == _C_BYCOPY
|
||||||
|| *types == _C_BYREF
|
|| *types == _C_BYREF
|
||||||
|| *types == _C_ONEWAY
|
|| *types == _C_ONEWAY
|
||||||
|| *types == _C_GCINVISIBLE
|
|| *types == _C_GCINVISIBLE
|
||||||
|| isdigit ((unsigned char) *types))
|
|| isdigit ((unsigned char) *types))
|
||||||
{
|
{
|
||||||
types++;
|
types++;
|
||||||
}
|
}
|
||||||
|
@ -1117,30 +631,13 @@ GSSelectorTypesMatch(const char *types1, const char *types2)
|
||||||
GSIVar
|
GSIVar
|
||||||
GSCGetInstanceVariableDefinition(Class cls, const char *name)
|
GSCGetInstanceVariableDefinition(Class cls, const char *name)
|
||||||
{
|
{
|
||||||
struct objc_ivar_list *list;
|
return class_getInstanceVariable(cls, name);
|
||||||
int i;
|
|
||||||
|
|
||||||
if (cls == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
list = cls->ivars;
|
|
||||||
for (i = 0; (list != 0) && i < list->ivar_count; i++)
|
|
||||||
{
|
|
||||||
if (strcmp (list->ivar_list[i].ivar_name, name) == 0)
|
|
||||||
return &(list->ivar_list[i]);
|
|
||||||
}
|
|
||||||
cls = GSObjCSuper(cls);
|
|
||||||
if (cls != 0)
|
|
||||||
{
|
|
||||||
return GSCGetInstanceVariableDefinition(cls, name);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GSIVar
|
GSIVar
|
||||||
GSObjCGetInstanceVariableDefinition(Class cls, NSString *name)
|
GSObjCGetInstanceVariableDefinition(Class cls, NSString *name)
|
||||||
{
|
{
|
||||||
return GSCGetInstanceVariableDefinition(cls, [name cString]);
|
return class_getInstanceVariable(cls, [name UTF8String]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1342,13 +839,15 @@ GSProtocolFromName(const char *name)
|
||||||
void
|
void
|
||||||
GSObjCAddClassBehavior(Class receiver, Class behavior)
|
GSObjCAddClassBehavior(Class receiver, Class behavior)
|
||||||
{
|
{
|
||||||
Class behavior_super_class = GSObjCSuper(behavior);
|
unsigned int count;
|
||||||
|
Method *methods;
|
||||||
|
Class behavior_super_class = class_getSuperclass(behavior);
|
||||||
|
|
||||||
NSCAssert(CLS_ISCLASS(receiver), NSInvalidArgumentException);
|
NSCAssert(NO == class_isMetaClass(receiver), NSInvalidArgumentException);
|
||||||
NSCAssert(CLS_ISCLASS(behavior), NSInvalidArgumentException);
|
NSCAssert(NO == class_isMetaClass(behavior), NSInvalidArgumentException);
|
||||||
|
|
||||||
/* If necessary, increase instance_size of CLASS. */
|
/* If necessary, increase instance_size of CLASS. */
|
||||||
if (receiver->instance_size < behavior->instance_size)
|
if (class_getInstanceSize(receiver) < class_getInstanceSize(behavior))
|
||||||
{
|
{
|
||||||
#if NeXT_RUNTIME
|
#if NeXT_RUNTIME
|
||||||
NSCAssert2(receiver->instance_size >= behavior->instance_size,
|
NSCAssert2(receiver->instance_size >= behavior->instance_size,
|
||||||
|
@ -1366,44 +865,26 @@ GSObjCAddClassBehavior(Class receiver, Class behavior)
|
||||||
receiver->instance_size = behavior->instance_size;
|
receiver->instance_size = behavior->instance_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
BDBGPrintf("Adding behavior to class %s\n", receiver->name);
|
BDBGPrintf("Adding behavior to class %s\n", class_getName(receiver));
|
||||||
BDBGPrintf(" instance methods from %s\n", behavior->name);
|
BDBGPrintf(" instance methods from %s\n", class_getName(behavior));
|
||||||
|
|
||||||
/* Add instance methods */
|
/* Add instance methods */
|
||||||
#if NeXT_RUNTIME
|
methods = class_copyMethodList(behavior, &count);
|
||||||
{
|
if (methods != NULL)
|
||||||
void *iterator = 0;
|
{
|
||||||
GSMethodList method_list;
|
GSObjCAddMethods (receiver, methods, NO);
|
||||||
|
free(methods);
|
||||||
method_list = class_nextMethodList(behavior, &iterator);
|
}
|
||||||
while (method_list != 0)
|
|
||||||
{
|
|
||||||
GSObjCAddMethods (receiver, method_list);
|
|
||||||
method_list = class_nextMethodList(behavior, &iterator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
GSObjCAddMethods (receiver, behavior->methods);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add class methods */
|
/* Add class methods */
|
||||||
BDBGPrintf("Adding class methods from %s\n",
|
BDBGPrintf("Adding class methods from %s\n",
|
||||||
behavior->class_pointer->name);
|
class_getName(object_getClass(behavior)));
|
||||||
#if NeXT_RUNTIME
|
methods = class_copyMethodList(object_getClass(behavior), &count);
|
||||||
{
|
if (methods != NULL)
|
||||||
void *iterator = 0;
|
{
|
||||||
GSMethodList method_list;
|
GSObjCAddMethods (object_getClass(receiver), methods, NO);
|
||||||
|
free(methods);
|
||||||
method_list = class_nextMethodList(behavior->class_pointer, &iterator);
|
}
|
||||||
while (method_list != 0)
|
|
||||||
{
|
|
||||||
GSObjCAddMethods (receiver->class_pointer, method_list);
|
|
||||||
method_list = class_nextMethodList(behavior->class_pointer, &iterator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
GSObjCAddMethods (receiver->class_pointer, behavior->class_pointer->methods);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add behavior's superclass, if not already there. */
|
/* Add behavior's superclass, if not already there. */
|
||||||
if (!GSObjCIsKindOf(receiver, behavior_super_class))
|
if (!GSObjCIsKindOf(receiver, behavior_super_class))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue