/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
Object.m
Copyright 1988-1996 NeXT Software, Inc.
*/
#import <objc/Object.h>
#import "objc-private.h"
#import <objc/objc-auto.h>
#import <objc/objc-runtime.h>
#import <objc/Protocol.h>
#import <stdarg.h>
#import <string.h>
OBJC_EXPORT id (*_cvtToId)(const char *);
OBJC_EXPORT id (*_poseAs)();
// Error Messages
static const char
_errNoMem[] = "failed -- out of memory( _errReAllocNil[] = "reallocating nil object",
_errReAllocFreed[] = "reallocating freed object",
_errReAllocTooSmall[] = "( _errShouldHaveImp[] = "should have implemented the '%s' method.",
_errShouldNotImp[] = "should NOT have implemented the '%s' method.",
_errLeftUndone[] = "method '%s' not implemented",
_errBadSel[] = "method _errDoesntRecognize[] = "does not recognize selector
@implementation Object
+ initialize
{
return self;
}
- awake
{
return self;
}
+ poseAs: aFactory
{
return (*_poseAs)(self, aFactory);
}
+ new
{
id newObject = (*_alloc)((Class)self, 0);
struct objc_class * metaClass = ((struct objc_class *) self)->isa;
if (metaClass->version > 1)
return [newObject init];
else
return newObject;
}
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
+ allocFromZone:(void *) z
{
return (*_zoneAlloc)((Class)self, 0, z);
}
- init
{
return self;
}
- (const char *)name
{
return ((struct objc_class *)isa)->name;
}
+ (const char *)name
{
return ((struct objc_class *)self)->name;
}
- (unsigned)hash
{
return ((uarith_t)self) >> 2;
}
- (BOOL)isEqual:anObject
{
return anObject == self;
}
- free
{
return (*_dealloc)(self);
}
+ free
{
return nil;
}
- self
{
return self;
}
- class
{
return (id)isa;
}
+ class
{
return self;
}
- (void *)zone
{
void *z = malloc_zone_from_ptr(self);
return z ? z : malloc_default_zone();
}
+ superclass
{
return ((struct objc_class *)self)->super_class;
}
- superclass
{
return ((struct objc_class *)isa)->super_class;
}
+ (int) version
{
struct objc_class * class = (struct objc_class *) self;
return class->version;
}
+ setVersion: (int) aVersion
{
struct objc_class * class = (struct objc_class *) self;
class->version = aVersion;
return self;
}
- (BOOL)isKindOf:aClass
{
register Class cls;
for (cls = isa; cls; cls = ((struct objc_class *)cls)->super_class)
if (cls == (Class)aClass)
return YES;
return NO;
}
- (BOOL)isMemberOf:aClass
{
return isa == (Class)aClass;
}
- (BOOL)isKindOfClassNamed:(const char *)aClassName
{
register Class cls;
for (cls = isa; cls; cls = ((struct objc_class *)cls)->super_class)
if (strcmp(aClassName, ((struct objc_class *)cls)->name) == 0)
return YES;
return NO;
}
- (BOOL)isMemberOfClassNamed:(const char *)aClassName
{
return strcmp(aClassName, ((struct objc_class *)isa)->name) == 0;
}
+ (BOOL)instancesRespondTo:(SEL)aSelector
{
return class_respondsToMethod((Class)self, aSelector);
}
- (BOOL)respondsTo:(SEL)aSelector
{
return class_respondsToMethod(isa, aSelector);
}
- copy
{
return [self copyFromZone: [self zone]];
}
- copyFromZone:(void *)z
{
return (*_zoneCopy)(self, 0, z);
}
- (IMP)methodFor:(SEL)aSelector
{
return class_lookupMethod(isa, aSelector);
}
+ (IMP)instanceMethodFor:(SEL)aSelector
{
return class_lookupMethod(self, aSelector);
}
#if defined(__alpha__)
#define MAX_RETSTRUCT_SIZE 256
typedef struct _foolGCC {
char c[MAX_RETSTRUCT_SIZE];
} _variableStruct;
typedef _variableStruct (*callReturnsStruct)();
OBJC_EXPORT long sizeOfReturnedStruct(char **);
long sizeOfType(char **pp)
{
char *p = *pp;
long stack_size = 0, n = 0;
switch(*p) {
case 'c':
case 'C':
stack_size += sizeof(char); // Alignment ?
break;
case 's':
case 'S':
stack_size += sizeof(short);// Alignment ?
break;
case 'i':
case 'I':
case '!':
stack_size += sizeof(int);
break;
case 'l':
case 'L':
stack_size += sizeof(long int);
break;
case 'f':
stack_size += sizeof(float);
break;
case 'd':
stack_size += sizeof(double);
break;
case '*':
case ':':
case '@':
case '%':
stack_size += sizeof(char*);
break;
case '{':
stack_size += sizeOfReturnedStruct(&p);
while(*p!='}') p++;
break;
case '[':
p++;
while(isdigit(*p))
n = 10 * n + (*p++ - '0');
stack_size += (n * sizeOfType(&p));
break;
default:
break;
}
*pp = p;
return stack_size;
}
long
sizeOfReturnedStruct(char **pp)
{
char *p = *pp;
long stack_size = 0, n = 0;
while(p!=NULL && *++p!='=') ; // skip the struct name
while(p!=NULL && *++p!='}')
stack_size += sizeOfType(&p);
return stack_size + 8; // Add 8 as a 'forfait value'
// to take alignment into account
}
- perform:(SEL)aSelector
{
char *p;
long stack_size;
_variableStruct *dummyRetVal;
Method method;
if (aSelector) {
method = class_getInstanceMethod((Class)self->isa,
aSelector);
if(method==NULL)
method = class_getClassMethod((Class)self->isa,
aSelector);
if(method!=NULL) {
p = &method->method_types[0];
if(*p=='{') {
// Method returns a structure
stack_size = sizeOfReturnedStruct(&p);
if(stack_size<MAX_RETSTRUCT_SIZE)
{
//
// The MAX_RETSTRUCT_SIZE value allow us to support methods that
// return structures whose size is not grater than
// MAX_RETSTRUCT_SIZE.
// This is because the compiler allocates space on the stack
// for the size of the return structure, and when the method
// returns, the structure is copied on the space allocated
// on the stack: if the structure is greater than the space
// allocated... bang! (the stack is gone:-)
//
((callReturnsStruct)objc_msgSend)(self, aSelector);
}
else
{
dummyRetVal = (_variableStruct*) malloc(stack_size);
// Following asm code is equivalent to:
// *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector);
#if 0
asm("ldq $16, asm("ldq $17, asm("ldq $18, asm("bis $31,1,$25");
asm("lda $27,objc_msgSend");
asm("jsr $26,($27),objc_msgSend");
asm("ldgp $29,0($26)");
#else
*dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector);
#endif
free(dummyRetVal);
}
// When the method return a structure, we cannot return it here
// becuse we're not called in the right way, so we must return
// something else: wether it is self or NULL is a matter of taste.
return (id)NULL;
}
}
// We fall back here either because the method doesn't return
// a structure, or because method is NULL: in this latter
// case the call to msgSend will try to forward the message.
return objc_msgSend(self, aSelector);
}
// We fallback here only when aSelector is NULL
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
- perform:(SEL)aSelector with:anObject
{
char *p;
long stack_size;
_variableStruct *dummyRetVal;
Method method;
if (aSelector) {
method = class_getInstanceMethod((Class)self->isa,
aSelector);
if(method==NULL)
method = class_getClassMethod((Class)self->isa,
aSelector);
if(method!=NULL) {
p = &method->method_types[0];
if(*p=='{') {
// Method returns a structure
stack_size = sizeOfReturnedStruct(&p);
if(stack_size<MAX_RETSTRUCT_SIZE)
{
//
// The MAX_RETSTRUCT_SIZE value allow us to support methods that
// return structures whose size is not grater than
// MAX_RETSTRUCT_SIZE.
// This is because the compiler allocates space on the stack
// for the size of the return structure, and when the method
// returns, the structure is copied on the space allocated
// on the stack: if the structure is greater than the space
// allocated... bang! (the stack is gone:-)
//
((callReturnsStruct)objc_msgSend)(self, aSelector, anObject);
}
else
{
dummyRetVal = (_variableStruct*) malloc(stack_size);
// Following asm code is equivalent to:
// *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,anObject);
#if 0
asm("ldq $16, asm("ldq $17, asm("ldq $18, asm("ldq $19, asm("bis $31,1,$25");
asm("lda $27,objc_msgSend");
asm("jsr $26,($27),objc_msgSend");
asm("ldgp $29,0($26)");
#else
*dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,anObject);
#endif
free(dummyRetVal);
}
// When the method return a structure, we cannot return it here
// becuse we're not called in the right way, so we must return
// something else: wether it is self or NULL is a matter of taste.
return (id)NULL;
}
}
// We fall back here either because the method doesn't return
// a structure, or because method is NULL: in this latter
// case the call to msgSend will try to forward the message.
return objc_msgSend(self, aSelector, anObject);
}
// We fallback here only when aSelector is NULL
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
- perform:(SEL)aSelector with:obj1 with:obj2
{
char *p;
long stack_size;
_variableStruct *dummyRetVal;
Method method;
if (aSelector) {
method = class_getInstanceMethod((Class)self->isa,
aSelector);
if(method==NULL)
method = class_getClassMethod((Class)self->isa,
aSelector);
if(method!=NULL) {
p = &method->method_types[0];
if(*p=='{') {
// Method returns a structure
stack_size = sizeOfReturnedStruct(&p);
if(stack_size<MAX_RETSTRUCT_SIZE)
{
//
// The MAX_RETSTRUCT_SIZE value allow us to support methods that
// return structures whose size is not grater than
// MAX_RETSTRUCT_SIZE.
// This is because the compiler allocates space on the stack
// for the size of the return structure, and when the method
// returns, the structure is copied on the space allocated
// on the stack: if the structure is greater than the space
// allocated... bang! (the stack is gone:-)
//
((callReturnsStruct)objc_msgSend)(self, aSelector, obj1, obj2);
}
else
{
dummyRetVal = (_variableStruct*) malloc(stack_size);
// Following asm code is equivalent to:
// *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,obj1,obj2);
#if 0
asm("ldq $16, asm("ldq $17, asm("ldq $18, asm("ldq $19, asm("ldq $20, asm("bis $31,1,$25");
asm("lda $27,objc_msgSend");
asm("jsr $26,($27),objc_msgSend");
asm("ldgp $29,0($26)");
#else
*dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,obj1,obj2);
#endif
free(dummyRetVal);
}
// When the method return a structure, we cannot return it here
// becuse we're not called in the right way, so we must return
// something else: wether it is self or NULL is a matter of taste.
return (id)NULL;
}
}
// We fall back here either because the method doesn't return
// a structure, or because method is NULL: in this latter
// case the call to msgSend will try to forward the message.
return objc_msgSend(self, aSelector, obj1, obj2);
}
// We fallback here only when aSelector is NULL
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
#else
- perform:(SEL)aSelector
{
if (aSelector)
return objc_msgSend(self, aSelector);
else
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
- perform:(SEL)aSelector with:anObject
{
if (aSelector)
return objc_msgSend(self, aSelector, anObject);
else
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
- perform:(SEL)aSelector with:obj1 with:obj2
{
if (aSelector)
return objc_msgSend(self, aSelector, obj1, obj2);
else
return [self error:_errBadSel, SELNAME(_cmd), aSelector];
}
#endif
- subclassResponsibility:(SEL)aSelector
{
return [self error:_errShouldHaveImp, sel_getName(aSelector)];
}
- notImplemented:(SEL)aSelector
{
return [self error:_errLeftUndone, sel_getName(aSelector)];
}
- doesNotRecognize:(SEL)aMessage
{
return [self error:_errDoesntRecognize,
ISMETA (isa) ? '+' : '-', SELNAME(aMessage)];
}
- error:(const char *)aCStr, ...
{
va_list ap;
va_start(ap,aCStr);
(*_error)(self, aCStr, ap);
_objc_error (self, aCStr, ap); /* In case (*_error)() returns. */
va_end(ap);
return nil;
}
- (void) printForDebugger:(void *)stream
{
}
- write:(void *) stream
{
return self;
}
- read:(void *) stream
{
return self;
}
- forward: (SEL) sel : (marg_list) args
{
return [self doesNotRecognize: sel];
}
/* this method is not part of the published API */
- (unsigned)methodArgSize:(SEL)sel
{
Method method = class_getInstanceMethod((Class)isa, sel);
if (! method) return 0;
return method_getSizeOfArguments(method);
}
#if defined(__alpha__)
typedef struct {
unsigned long int i16;
unsigned long int i17;
unsigned long int i18;
unsigned long int i19;
unsigned long int i20;
unsigned long int i21;
unsigned long int i25;
unsigned long int f16;
unsigned long int f17;
unsigned long int f18;
unsigned long int f19;
unsigned long int f20;
unsigned long int f21;
unsigned long int sp;
} *_m_args_p;
- performv: (SEL) sel : (marg_list) args
{
char * p;
long stack_size;
Method method;
unsigned long int size;
char scratchMem[MAX_RETSTRUCT_SIZE];
char * scratchMemP;
// Messages to nil object always return nil
if (! self) return nil;
// Got to have a selector
if (!sel)
return [self error:_errBadSel, SELNAME(_cmd), sel];
// Handle a method which returns a structure and
// has been called as such
if (((_m_args_p)args)->i25){
// Calculate size of the marg_list from the method's
// signature. This looks for the method in self
// and its superclasses.
size = [self methodArgSize: sel];
// If neither self nor its superclasses implement
// the method, forward the message because self
// might know someone who does. This is a
// "chained" forward...
if (! size) return [self forward: sel: args];
// Message self with the specified selector and arguments
return objc_msgSendv (self, sel, size, args);
}
// Look for instance method in self's class and superclasses
method = class_getInstanceMethod((Class)self->isa,sel);
// Look for class method in self's class and superclass
if(method==NULL)
method = class_getClassMethod((Class)self->isa,sel);
// If neither self nor its superclasses implement
// the method, forward the message because self
// might know someone who does. This is a
// "chained" forward...
if(method==NULL)
return [self forward: sel: args];
// Calculate size of the marg_list from the method's
// signature.
size = method_getSizeOfArguments(method);
// Ready to send message now if the return type
// is not a structure
p = &method->method_types[0];
if(*p!='{')
return objc_msgSendv(self, sel, size, args);
// Method returns a structure
stack_size = sizeOfReturnedStruct(&p);
if(stack_size>=MAX_RETSTRUCT_SIZE)
scratchMemP = (char*)malloc(stack_size);
else
scratchMemP = &scratchMem[0];
// Set i25 so objc_msgSendv will know that method returns a structure
((_m_args_p)args)->i25 = 1;
// Set first param of method to be called to safe return address
((_m_args_p)args)->i16 = (unsigned long int) scratchMemP;
objc_msgSendv(self, sel, size, args);
if(stack_size>=MAX_RETSTRUCT_SIZE)
free(scratchMemP);
return (id)NULL;
}
#else
- performv: (SEL) sel : (marg_list) args
{
unsigned size;
#if hppa && 0
void *ret;
// Save ret0 so methods that return a struct might work.
asm("copy #endif hppa
// Messages to nil object always return nil
if (! self) return nil;
// Calculate size of the marg_list from the method's
// signature. This looks for the method in self
// and its superclasses.
size = [self methodArgSize: sel];
// If neither self nor its superclasses implement
// it, forward the message because self might know
// someone who does. This is a "chained" forward...
if (! size) return [self forward: sel: args];
#if hppa && 0
// Unfortunately, it looks like the compiler puts something else in
// r28 right after this instruction, so this is all for naught.
asm("copy #endif hppa
// Message self with the specified selector and arguments
return objc_msgSendv (self, sel, size, args);
}
#endif
/* Testing protocol conformance */
- (BOOL) conformsTo: (Protocol *)aProtocolObj
{
return [(id)isa conformsTo:aProtocolObj];
}
+ (BOOL) conformsTo: (Protocol *)aProtocolObj
{
struct objc_class * class;
for (class = self; class; class = class->super_class)
{
if (class->isa->version >= 3)
{
struct objc_protocol_list *protocols = class->protocols;
while (protocols)
{
int i;
for (i = 0; i < protocols->count; i++)
{
Protocol *p = protocols->list[i];
if ([p conformsTo:aProtocolObj])
return YES;
}
if (class->isa->version <= 4)
break;
protocols = protocols->next;
}
}
}
return NO;
}
/* Looking up information for a method */
- (struct objc_method_description *) descriptionForMethod:(SEL)aSelector
{
struct objc_class * cls;
struct objc_method_description *m;
/* Look in the protocols first. */
for (cls = isa; cls; cls = cls->super_class)
{
if (cls->isa->version >= 3)
{
struct objc_protocol_list *protocols = cls->protocols;
while (protocols)
{
int i;
for (i = 0; i < protocols->count; i++)
{
Protocol *p = protocols->list[i];
if (ISMETA (cls))
m = [p descriptionForClassMethod:aSelector];
else
m = [p descriptionForInstanceMethod:aSelector];
if (m) {
return m;
}
}
if (cls->isa->version <= 4)
break;
protocols = protocols->next;
}
}
}
/* Then try the class implementations. */
for (cls = isa; cls; cls = cls->super_class) {
void *iterator = 0;
int i;
struct objc_method_list *mlist;
while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
for (i = 0; i < mlist->method_count; i++)
if (mlist->method_list[i].method_name == aSelector) {
struct objc_method_description *m;
m = (struct objc_method_description *)&mlist->method_list[i];
return m;
}
}
}
return 0;
}
+ (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSelector
{
struct objc_class * cls;
/* Look in the protocols first. */
for (cls = self; cls; cls = cls->super_class)
{
if (cls->isa->version >= 3)
{
struct objc_protocol_list *protocols = cls->protocols;
while (protocols)
{
int i;
for (i = 0; i < protocols->count; i++)
{
Protocol *p = protocols->list[i];
struct objc_method_description *m;
if ((m = [p descriptionForInstanceMethod:aSelector]))
return m;
}
if (cls->isa->version <= 4)
break;
protocols = protocols->next;
}
}
}
/* Then try the class implementations. */
for (cls = self; cls; cls = cls->super_class) {
void *iterator = 0;
int i;
struct objc_method_list *mlist;
while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
for (i = 0; i < mlist->method_count; i++)
if (mlist->method_list[i].method_name == aSelector) {
struct objc_method_description *m;
m = (struct objc_method_description *)&mlist->method_list[i];
return m;
}
}
}
return 0;
}
/* Obsolete methods (for binary compatibility only). */
+ superClass
{
return [self superclass];
}
- superClass
{
return [self superclass];
}
- (BOOL)isKindOfGivenName:(const char *)aClassName
{
return [self isKindOfClassNamed: aClassName];
}
- (BOOL)isMemberOfGivenName:(const char *)aClassName
{
return [self isMemberOfClassNamed: aClassName];
}
- (struct objc_method_description *) methodDescFor:(SEL)aSelector
{
return [self descriptionForMethod: aSelector];
}
+ (struct objc_method_description *) instanceMethodDescFor:(SEL)aSelector
{
return [self descriptionForInstanceMethod: aSelector];
}
- findClass:(const char *)aClassName
{
return (*_cvtToId)(aClassName);
}
- shouldNotImplement:(SEL)aSelector
{
return [self error:_errShouldNotImp, sel_getName(aSelector)];
}
@end
static id _internal_object_copyFromZone(Object *anObject, unsigned nBytes, void *z)
{
id obj;
register unsigned siz;
if (anObject == nil)
return nil;
obj = (*_zoneAlloc)(anObject->isa, nBytes, z);
siz = ((struct objc_class *)anObject->isa)->instance_size + nBytes;
bcopy((const char*)anObject, (char*)obj, siz);
return obj;
}
static id _internal_object_copy(Object *anObject, unsigned nBytes)
{
void *z= malloc_zone_from_ptr(anObject);
return _internal_object_copyFromZone(anObject,
nBytes,
z ? z : malloc_default_zone());
}
static id _internal_object_dispose(Object *anObject)
{
if (anObject==nil) return nil;
object_cxxDestruct((id)anObject);
anObject->isa = _objc_getFreedObjectClass ();
free(anObject);
return nil;
}
static id _internal_object_reallocFromZone(Object *anObject, unsigned nBytes, void *z)
{
Object *newObject;
struct objc_class * tmp;
if (anObject == nil)
__objc_error(nil, _errReAllocNil, 0);
if (anObject->isa == _objc_getFreedObjectClass ())
__objc_error(anObject, _errReAllocFreed, 0);
if (nBytes < ((struct objc_class *)anObject->isa)->instance_size)
__objc_error(anObject, _errReAllocTooSmall,
object_getClassName(anObject), nBytes);
// Make sure not to modify space that has been declared free
tmp = anObject->isa;
anObject->isa = _objc_getFreedObjectClass ();
newObject = (Object*)malloc_zone_realloc(z, (void*)anObject, (size_t)nBytes);
if (newObject) {
newObject->isa = tmp;
return newObject;
}
else
{
__objc_error(anObject, _errNoMem,
object_getClassName(anObject), nBytes);
return nil;
}
}
static id _internal_object_realloc(Object *anObject, unsigned nBytes)
{
void *z= malloc_zone_from_ptr(anObject);
return _internal_object_reallocFromZone(anObject,
nBytes,
z ? z : malloc_default_zone());
}
/* Functional Interface to system primitives */
id object_copy(Object *anObject, unsigned nBytes)
{
return (*_copy)(anObject, nBytes);
}
id object_copyFromZone(Object *anObject, unsigned nBytes, void *z)
{
return (*_zoneCopy)(anObject, nBytes, z);
}
id object_dispose(Object *anObject)
{
return (*_dealloc)(anObject);
}
id object_realloc(Object *anObject, unsigned nBytes)
{
return (*_realloc)(anObject, nBytes);
}
id object_reallocFromZone(Object *anObject, unsigned nBytes, void *z)
{
return (*_zoneRealloc)(anObject, nBytes, z);
}
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
{
Ivar ivar = 0;
if (obj && name) {
if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
objc_assign_ivar((id)value, obj, ivar->ivar_offset);
}
}
return ivar;
}
Ivar object_getInstanceVariable(id obj, const char *name, void **value)
{
Ivar ivar = 0;
if (obj && name) {
void **ivaridx;
if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
ivaridx = (void **)((char *)obj + ivar->ivar_offset);
*value = *ivaridx;
} else
*value = 0;
}
return ivar;
}
id (*_copy)(id, unsigned) = _internal_object_copy;
id (*_realloc)(id, unsigned) = _internal_object_realloc;
id (*_dealloc)(id) = _internal_object_dispose;
id (*_cvtToId)(const char *) = objc_lookUpClass;
SEL (*_cvtToSel)(const char *) = sel_getUid;
void (*_error)() = (void(*)())_objc_error;
id (*_zoneCopy)(id, unsigned, void *) = _internal_object_copyFromZone;
id (*_zoneRealloc)(id, unsigned, void *) = _internal_object_reallocFromZone;