diff --git a/ChangeLog b/ChangeLog index b082199ba..62a5b563f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2010-02-19 Richard Frith-Macdonald + + * configure.ac: Add check for ObjC2 support in runtime. + * config.mak.in: define OBJC2RUNTIME to yes or no + * configure: regenerate + * Source/GNUmakefile: Build/link ObjectiveC2 compat code if needed + * Source/ObjectiveC2/Availability.h: + * Source/ObjectiveC2/runtime.c: + * Source/ObjectiveC2/GNUmakefile: + * Source/ObjectiveC2/properties.m: + * Source/ObjectiveC2/sync.m: + * Source/ObjectiveC2/blocks_runtime.m: + Attempt to build in ObjectiveC2 compatibility functions when we don't + have an ObjC2 runtime. + 2010-02-19 Richard Frith-Macdonald Simplify header imports with common headers handled in the correct diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 52df87606..6ede738aa 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -65,8 +65,13 @@ ifneq ($(base),no) LIBRARY_NAME += libgnustep-base endif -libgnustep-base_SUBPROJECTS = Additions -libgnustep-baseadd_SUBPROJECTS = Additions +ifeq ($(OBJC2RUNTIME),no) +libgnustep-base_SUBPROJECTS = ObjectiveC2 +libgnustep-baseadd_SUBPROJECTS += Additions +endif + +libgnustep-base_SUBPROJECTS += Additions +libgnustep-baseadd_SUBPROJECTS += Additions ifeq ($(GNUSTEP_TARGET_OS), mingw32) libgnustep-base_SUBPROJECTS+=win32 @@ -473,7 +478,10 @@ libgnustep-baseadd_NEEDS_GUI = NO # build Additions as a subproject, causing concurrency issues). If it # can be guaranteed that they'll never be built together, this could # be removed. -SUBPROJECTS = Additions +ifeq ($(OBJC2RUNTIME),no) +SUBPROJECTS = ObjectiveC2 +endif +SUBPROJECTS += Additions -include Makefile.preamble diff --git a/Source/ObjectiveC2/Availability.h b/Source/ObjectiveC2/Availability.h new file mode 100644 index 000000000..81d4cf952 --- /dev/null +++ b/Source/ObjectiveC2/Availability.h @@ -0,0 +1,12 @@ + +#ifdef STRICT_MACOS_X +# define OBJC_NONPORTABLE __attribute__((error("Function not supported by the Apple runtime"))) +#else +# define OBJC_NONPORTABLE +#endif + +#if !defined(__DEPRECATE_DIRECT_ACCESS) || defined(__OBJC_LEGACY_GNU_MODE__) || defined(__OBJC_RUNTIME_INTERNAL__) +# define OBJC_DEPRECATED +#else +# define OBJC_DEPRECATED __attribute__((deprecated)) +#endif diff --git a/Source/ObjectiveC2/GNUmakefile b/Source/ObjectiveC2/GNUmakefile index 613152e7f..f82aee78a 100644 --- a/Source/ObjectiveC2/GNUmakefile +++ b/Source/ObjectiveC2/GNUmakefile @@ -1,41 +1,59 @@ +# +# src makefile for the GNUstep Base Library +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# Written by: Richard Frith-Macdonald +# +# This file is part of the GNUstep Base Library. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser 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 Lesser General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02111 USA. +# + +PACKAGE_NAME = gnustep-base +GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES=../../base.make + include $(GNUSTEP_MAKEFILES)/common.make +include ../../config.mak -# -# Application -# -VERSION = 0.1 -FRAMEWORK_NAME = ObjectiveC2 - -# -# Resource files -# -ObjectiveC2_LANGUAGES = English +SUBPROJECT_NAME = ObjectiveC2 ObjectiveC2_OBJC_FILES = \ - blocks_runtime.m\ - properties.m\ - sync.m - + blocks_runtime.m\ + properties.m\ + sync.m ObjectiveC2_C_FILES = \ - runtime.c + runtime.c ObjectiveC2_HEADER_FILES = \ - Availability.h\ - blocks_runtime.h\ - runtime.h - -ADDITIONAL_CFLAGS = -std=c99 -fexceptions -ADDITIONAL_OBJCFLAGS = -fobjc-exceptions -fexceptions + Availability.h\ + blocks_runtime.h\ + runtime.h ifeq ($(CC), clang) - ADDITIONAL_OBJCFLAGS = -fblocks + ADDITIONAL_OBJCFLAGS = -fblocks endif ifeq ($(GNUSTEP_TARGET_CPU), ix86) - ADDITIONAL_OBJCFLAGS += -march=i686 + ADDITIONAL_OBJCFLAGS += -march=i686 endif -ObjectiveC2_OBJCFLAGS += -std=c99 +-include Makefile.preamble + +include $(GNUSTEP_MAKEFILES)/subproject.make + +-include Makefile.postamble -include $(GNUSTEP_MAKEFILES)/framework.make --include ../../etoile.make diff --git a/Source/ObjectiveC2/blocks_runtime.m b/Source/ObjectiveC2/blocks_runtime.m index 6e5aa5a4b..b6671a951 100644 --- a/Source/ObjectiveC2/blocks_runtime.m +++ b/Source/ObjectiveC2/blocks_runtime.m @@ -23,8 +23,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#import "objc/blocks_runtime.h" -#import "objc/runtime.h" +#import "blocks_runtime.h" +#import "runtime.h" #include #include #include @@ -38,47 +38,47 @@ // Descriptor attributes enum { - BLOCK_HAS_COPY_DISPOSE = (1 << 25), - BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code - BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code + BLOCK_IS_GLOBAL = (1 << 28), + BLOCK_HAS_DESCRIPTOR = (1 << 29), // interim until complete world build is accomplished }; // _Block_object_assign() and _Block_object_dispose() flag helpers. enum { - BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... - BLOCK_FIELD_IS_BLOCK = 7, // a block variable - BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable - - BLOCK_FIELD_IS_WEAK = 16, // declared __weak - - BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers + BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... + BLOCK_FIELD_IS_BLOCK = 7, // a block variable + BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable + + BLOCK_FIELD_IS_WEAK = 16, // declared __weak + + BLOCK_BYREF_CALLER = 128, // called from byref copy/dispose helpers }; // Helper structure struct psy_block_literal { - void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock - int flags; - int reserved; - void (*invoke)(void *, ...); - struct { - unsigned long int reserved; // NULL - unsigned long int size; // sizeof(struct Block_literal_1) - // optional helper functions - void (*copy_helper)(void *dst, void *src); - void (*dispose_helper)(void *src); - } *descriptor; - const char *types; + void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int flags; + int reserved; + void (*invoke)(void *, ...); + struct { + unsigned long int reserved; // NULL + unsigned long int size; // sizeof(struct Block_literal_1) + // optional helper functions + void (*copy_helper)(void *dst, void *src); + void (*dispose_helper)(void *src); + } *descriptor; + const char *types; }; // Helper structure struct psy_block_byref_obj { - void *isa; // uninitialized - struct psy_block_byref_obj *forwarding; - int flags; //refcount; - int size; - void (*byref_keep)(struct psy_block_byref_obj *dst, struct psy_block_byref_obj *src); - void (*byref_dispose)(struct psy_block_byref_obj *); + void *isa; // uninitialized + struct psy_block_byref_obj *forwarding; + int flags; //refcount; + int size; + void (*byref_keep)(struct psy_block_byref_obj *dst, struct psy_block_byref_obj *src); + void (*byref_dispose)(struct psy_block_byref_obj *); }; /* Certain field types require runtime assistance when being copied to the @@ -88,53 +88,58 @@ struct psy_block_byref_obj { * the other choices which are mutually exclusive. Only in a Block copy helper * will one see BLOCK_FIELD_IS_BYREF. */ -void _Block_object_assign(void *destAddr, void *object, const int flags) +void +_Block_object_assign(void *destAddr, void *object, const int flags) { - //printf("Copying %x to %x with flags %x\n", object, destAddr, flags); - // FIXME: Needs to be implemented - if(flags & BLOCK_FIELD_IS_WEAK) + //printf("Copying %x to %x with flags %x\n", object, destAddr, flags); + // FIXME: Needs to be implemented + if (flags & BLOCK_FIELD_IS_WEAK) { } - else + else { - if(flags & BLOCK_FIELD_IS_BYREF) + if (flags & BLOCK_FIELD_IS_BYREF) { - struct psy_block_byref_obj *src = object; - struct psy_block_byref_obj **dst = destAddr; + struct psy_block_byref_obj *src = object; + struct psy_block_byref_obj **dst = destAddr; - /* I followed Apple's specs saying byref's "flags" field should - * represent the refcount but it still contains real flag, so this - * is a little hack... - */ - if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) + /* I followed Apple's specs saying byref's "flags" field should + * represent the refcount but it still contains real flag, so this + * is a little hack... + */ + if ((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) { - *dst = malloc(src->size); - memcpy(*dst, src, src->size); - if (src->forwarding == src) - { - (*dst)->forwarding = *dst; - } - if(src->size >= sizeof(struct psy_block_byref_obj)) - { - src->byref_keep(*dst, src); - } + *dst = malloc(src->size); + memcpy(*dst, src, src->size); + if (src->forwarding == src) + { + (*dst)->forwarding = *dst; + } + if (src->size >= sizeof(struct psy_block_byref_obj)) + { + src->byref_keep(*dst, src); + } } - else *dst = src; + else + { + *dst = src; + } - (*dst)->flags++; + (*dst)->flags++; } - else if((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) + else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) { - struct psy_block_literal *src = object; - struct psy_block_literal **dst = destAddr; + struct psy_block_literal *src = object; + struct psy_block_literal **dst = destAddr; - *dst = Block_copy(src); + *dst = Block_copy(src); } - else if((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) + else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) { - id src = object; - id *dst = destAddr; - *dst = [src retain]; + id src = object; + id *dst = destAddr; + + *dst = [src retain]; } } } @@ -145,103 +150,113 @@ void _Block_object_assign(void *destAddr, void *object, const int flags) * The same flags used in the copy helper should be used for each call * generated to this function: */ -void _Block_object_dispose(void *object, const int flags) +void +_Block_object_dispose(void *object, const int flags) { - // FIXME: Needs to be implemented - if(flags & BLOCK_FIELD_IS_WEAK) + // FIXME: Needs to be implemented + if (flags & BLOCK_FIELD_IS_WEAK) { } - else + else { - if(flags & BLOCK_FIELD_IS_BYREF) + if (flags & BLOCK_FIELD_IS_BYREF) { - struct psy_block_byref_obj *src = object; - - src->flags--; - if((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) + struct psy_block_byref_obj *src = object; + + src->flags--; + if ((src->flags & ~BLOCK_HAS_COPY_DISPOSE) == 0) { - if(src->size >= sizeof(struct psy_block_byref_obj)) - src->byref_dispose(src); + if (src->size >= sizeof(struct psy_block_byref_obj)) + src->byref_dispose(src); - free(src); + free(src); } } - else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK) + else if ((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_BLOCK) { - struct psy_block_literal *src = object; - Block_release(src); + struct psy_block_literal *src = object; + Block_release(src); } - else if((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT) + else if ((flags & ~BLOCK_BYREF_CALLER) == BLOCK_FIELD_IS_OBJECT) { - id src = object; - [src release]; + id src = object; + [src release]; } } } struct StackBlockClass { - void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock - int flags; - int reserved; - void (*invoke)(void *, ...); - struct { - unsigned long int reserved; // NULL - unsigned long int size; // sizeof(struct Block_literal_1) - // optional helper functions - void (*copy_helper)(void *dst, void *src); - void (*dispose_helper)(void *src); - } *descriptor; - const char *types; + void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int flags; + int reserved; + void (*invoke)(void *, ...); + struct { + unsigned long int reserved; // NULL + unsigned long int size; // sizeof(struct Block_literal_1) + // optional helper functions + void (*copy_helper)(void *dst, void *src); + void (*dispose_helper)(void *src); + } *descriptor; + const char *types; }; -// Copy a block to the heap if it's still on the stack or increments its retain count. -void *_Block_copy(void *src) +/* Copy a block to the heap if it's still on the stack or + * increments its retain count. + */ +void * +_Block_copy(void *src) { - struct StackBlockClass *self = src; - struct StackBlockClass *ret = self; + struct StackBlockClass *self = src; + struct StackBlockClass *ret = self; - extern void _NSConcreteStackBlock __attribute__((weak)); + extern void _NSConcreteStackBlock __attribute__((weak)); - // If the block is Global, there's no need to copy it on the heap. - if(self->isa == &_NSConcreteStackBlock && self->flags & BLOCK_HAS_DESCRIPTOR) + // If the block is Global, there's no need to copy it on the heap. + if (self->isa == &_NSConcreteStackBlock + && self->flags & BLOCK_HAS_DESCRIPTOR) { - if(self->reserved == 0) + if (self->reserved == 0) { - ret = malloc(self->descriptor->size); - memcpy(ret, self, self->descriptor->size); - if(self->flags & BLOCK_HAS_COPY_DISPOSE) - self->descriptor->copy_helper(ret, self); - memcpy(self, ret, self->descriptor->size); + ret = malloc(self->descriptor->size); + memcpy(ret, self, self->descriptor->size); + if (self->flags & BLOCK_HAS_COPY_DISPOSE) + self->descriptor->copy_helper(ret, self); + memcpy(self, ret, self->descriptor->size); } - ret->reserved++; + ret->reserved++; } - return ret; + return ret; } // Release a block and frees the memory when the retain count hits zero. -void _Block_release(void *src) +void +_Block_release(void *src) { - struct StackBlockClass *self = src; + struct StackBlockClass *self = src; - extern void _NSConcreteStackBlock __attribute__((weak)); + extern void _NSConcreteStackBlock __attribute__((weak)); - if(self->isa == &_NSConcreteStackBlock && // A Global block doesn't need to be released - self->flags & BLOCK_HAS_DESCRIPTOR && // Should always be true... - self->reserved > 0) // If false, then it's not allocated on the heap, we won't release auto memory ! + if (self->isa == &_NSConcreteStackBlock + // A Global block doesn't need to be released + && self->flags & BLOCK_HAS_DESCRIPTOR + // Should always be true... + && self->reserved > 0) + // If false, then it's not allocated on the heap, we won't release auto memory ! { - self->reserved--; - if(self->reserved == 0) + self->reserved--; + if (self->reserved == 0) { - if(self->flags & BLOCK_HAS_COPY_DISPOSE) - self->descriptor->dispose_helper(self); - free(self); + if (self->flags & BLOCK_HAS_COPY_DISPOSE) + self->descriptor->dispose_helper(self); + free(self); } } } -const char *_Block_get_types(void *blk) +const char * +_Block_get_types(void *blk) { - struct psy_block_literal *block = blk; - return block->types; + struct psy_block_literal *block = blk; + return block->types; } diff --git a/Source/ObjectiveC2/properties.m b/Source/ObjectiveC2/properties.m index 903e2f05e..af9e20960 100644 --- a/Source/ObjectiveC2/properties.m +++ b/Source/ObjectiveC2/properties.m @@ -8,40 +8,51 @@ - (void)release; @end -id objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic) +id +objc_getProperty(id obj, SEL _cmd, ptrdiff_t offset, BOOL isAtomic) { - if (isAtomic) + char *addr; + id ret; + + if (isAtomic) + { + @synchronized(obj) { - @synchronized(obj) { - return objc_getProperty(obj, _cmd, offset, NO); - } + return objc_getProperty(obj, _cmd, offset, NO); } - char *addr = (char*)obj; - addr += offset; - id ret = *(id*)addr; - return [[ret retain] autorelease]; + } + addr = (char*)obj; + addr += offset; + ret = *(id*)addr; + return [[ret retain] autorelease]; } -void objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic, BOOL isCopy) +void +objc_setProperty(id obj, SEL _cmd, ptrdiff_t offset, id arg, BOOL isAtomic, + BOOL isCopy) { - if (isAtomic) + char *addr; + id old; + + if (isAtomic) + { + @synchronized(obj) { - @synchronized(obj) { - objc_setProperty(obj, _cmd, offset, arg, NO, isCopy); - return; - } + objc_setProperty(obj, _cmd, offset, arg, NO, isCopy); + return; } - if (isCopy) - { - arg = [arg copy]; - } - else - { - arg = [arg retain]; - } - char *addr = (char*)obj; - addr += offset; - id old = *(id*)addr; - *(id*)addr = arg; - [old release]; + } + if (isCopy) + { + arg = [arg copy]; + } + else + { + arg = [arg retain]; + } + addr = (char*)obj; + addr += offset; + old = *(id*)addr; + *(id*)addr = arg; + [old release]; } diff --git a/Source/ObjectiveC2/runtime.c b/Source/ObjectiveC2/runtime.c index 99dfff677..016faf9d7 100644 --- a/Source/ObjectiveC2/runtime.c +++ b/Source/ObjectiveC2/runtime.c @@ -3,7 +3,7 @@ /* Make glibc export strdup() */ #if defined __GLIBC__ - #define __USE_BSD 1 + #define __USE_BSD 1 #endif #undef __objc_INCLUDE_GNU @@ -16,8 +16,8 @@ #define IMP objc_imp_gnu #define Method objc_method_gnu -#define object_copy gnu_object_copy -#define object_dispose gnu_object_dispose +#define object_copy gnu_object_copy +#define object_dispose gnu_object_dispose #define objc_super gnu_objc_super #define objc_msg_lookup gnu_objc_msg_lookup #define objc_msg_lookup_super gnu_objc_msg_lookup_super @@ -82,817 +82,980 @@ extern objc_mutex_t __objc_runtime_mutex; * Looks up the instance method in a specific class, without recursing into * superclasses. */ -static Method class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector) +static Method +class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector) { - const char *name = sel_get_name(aSelector); - const char *types = sel_get_type(aSelector); + struct objc_method_list *methods; + const char *name = sel_get_name(aSelector); + const char *types = sel_get_type(aSelector); - for (struct objc_method_list *methods = aClass->methods; - methods != NULL ; methods = methods->method_next) + for (methods = aClass->methods; + methods != NULL; methods = methods->method_next) + { + int i; + + for (i = 0; i < methods->method_count; i++) { - for (int i=0 ; imethod_count ; i++) + Method_t method = &methods->method_list[i]; + + if (strcmp(sel_get_name(method->method_name), name) == 0) + { + if (NULL == types + || strcmp(types, method->method_types) == 0) { - Method_t method = &methods->method_list[i]; - if (strcmp(sel_get_name(method->method_name), name) == 0) - { - if (NULL == types || - strcmp(types, method->method_types) == 0) - { - return method; - } - // Return NULL if the method exists with this name but has the - // wrong types - return NULL; - } + return method; } + // Return NULL if the method exists with this name but has the + // wrong types + return NULL; + } } - return NULL; + } + return NULL; } -static void objc_updateDtableForClassContainingMethod(Method m) +static void +objc_updateDtableForClassContainingMethod(Method m) { - Class nextClass = Nil; - void *state; - SEL sel = method_getName(m); - while (Nil != (nextClass = objc_next_class(&state))) + Class nextClass = Nil; + void *state; + SEL sel = method_getName(m); + + while (Nil != (nextClass = objc_next_class(&state))) + { + if (class_getInstanceMethodNonrecursive(nextClass, sel) == m) { - if (class_getInstanceMethodNonrecursive(nextClass, sel) == m) - { - __objc_update_dispatch_table_for_class(nextClass); - return; - } + __objc_update_dispatch_table_for_class(nextClass); + return; } + } } -BOOL class_addIvar(Class cls, - const char *name, - size_t size, - uint8_t alignment, - const char *types) +BOOL +class_addIvar(Class cls, + const char *name, + size_t size, + uint8_t alignment, + const char *types) { - if (CLS_ISRESOLV(cls) || CLS_ISMETA(cls)) - { - return NO; - } + struct objc_ivar_list *ivarlist; + Ivar ivar; - struct objc_ivar_list *ivarlist = cls->ivars; + if (CLS_ISRESOLV(cls) || CLS_ISMETA(cls)) + { + return NO; + } - if (class_getInstanceVariable(cls, name) != NULL) { return NO; } + if (class_getInstanceVariable(cls, name) != NULL) + { + return NO; + } - if (NULL == ivarlist) - { - cls->ivars = objc_malloc(sizeof(struct objc_ivar_list)); - cls->ivars->ivar_count = 1; - } - else - { - ivarlist->ivar_count++; - // objc_ivar_list contains one ivar. Others follow it. - cls->ivars = objc_realloc(ivarlist, sizeof(struct objc_ivar_list) - + (ivarlist->ivar_count - 1) * sizeof(struct objc_ivar)); - } + ivarlist = cls->ivars; - Ivar ivar = &cls->ivars->ivar_list[cls->ivars->ivar_count - 1]; - ivar->ivar_name = strdup(name); - ivar->ivar_type = strdup(types); - // Round up the offset of the ivar so it is correctly aligned. - ivar->ivar_offset = cls->instance_size + (cls->instance_size % alignment); - // Increase the instance size to make space for this. - cls->instance_size = ivar->ivar_offset + size; - return YES; + if (NULL == ivarlist) + { + cls->ivars = objc_malloc(sizeof(struct objc_ivar_list)); + cls->ivars->ivar_count = 1; + } + else + { + ivarlist->ivar_count++; + // objc_ivar_list contains one ivar. Others follow it. + cls->ivars = objc_realloc(ivarlist, sizeof(struct objc_ivar_list) + + (ivarlist->ivar_count - 1) * sizeof(struct objc_ivar)); + } + + ivar = &cls->ivars->ivar_list[cls->ivars->ivar_count - 1]; + ivar->ivar_name = strdup(name); + ivar->ivar_type = strdup(types); + // Round up the offset of the ivar so it is correctly aligned. + ivar->ivar_offset = cls->instance_size + (cls->instance_size % alignment); + // Increase the instance size to make space for this. + cls->instance_size = ivar->ivar_offset + size; + return YES; } -BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) +BOOL +class_addMethod(Class cls, SEL name, IMP imp, const char *types) { - const char *methodName = sel_get_name(name); - struct objc_method_list *methods; - for (methods=cls->methods; methods!=NULL ; methods=methods->method_next) + const char *methodName = sel_get_name(name); + struct objc_method_list *methods; + + for (methods = cls->methods; methods != NULL; methods = methods->method_next) + { + int i; + + for (i = 0; i < methods->method_count; i++) { - for (int i=0 ; imethod_count ; i++) - { - Method_t method = &methods->method_list[i]; - if (strcmp(sel_get_name(method->method_name), methodName) == 0) - { - return NO; - } - } + Method_t method = &methods->method_list[i]; + + if (strcmp(sel_get_name(method->method_name), methodName) == 0) + { + return NO; + } } + } - methods = objc_malloc(sizeof(struct objc_method_list)); - methods->method_next = cls->methods; - cls->methods = methods; + methods = objc_malloc(sizeof(struct objc_method_list)); + methods->method_next = cls->methods; + cls->methods = methods; - methods->method_count = 1; - methods->method_list[0].method_name = sel_register_typed_name(methodName, types); - methods->method_list[0].method_types = strdup(types); - methods->method_list[0].method_imp = (objc_imp_gnu)imp; + methods->method_count = 1; + methods->method_list[0].method_name + = sel_register_typed_name(methodName, types); + methods->method_list[0].method_types = strdup(types); + methods->method_list[0].method_imp = (objc_imp_gnu)imp; - if (CLS_ISRESOLV(cls)) - { - __objc_update_dispatch_table_for_class(cls); - } + if (CLS_ISRESOLV(cls)) + { + __objc_update_dispatch_table_for_class(cls); + } - return YES; + return YES; } -BOOL class_addProtocol(Class cls, Protocol *protocol) +BOOL +class_addProtocol(Class cls, Protocol *protocol) { - if (class_conformsToProtocol(cls, protocol)) { return NO; } - struct objc_protocol_list *protocols = cls->protocols; - protocols = objc_malloc(sizeof(struct objc_protocol_list)); - if (protocols == NULL) { return NO; } - protocols->next = cls->protocols; - protocols->count = 1; - protocols->list[0] = protocol; - cls->protocols = protocols; + struct objc_protocol_list *protocols; - return YES; + if (class_conformsToProtocol(cls, protocol)) + { + return NO; + } + protocols = cls->protocols; + protocols = objc_malloc(sizeof(struct objc_protocol_list)); + if (protocols == NULL) + { + return NO; + } + protocols->next = cls->protocols; + protocols->count = 1; + protocols->list[0] = protocol; + cls->protocols = protocols; + + return YES; } -BOOL class_conformsToProtocol(Class cls, Protocol *protocol) +BOOL +class_conformsToProtocol(Class cls, Protocol *protocol) { - for (struct objc_protocol_list *protocols = cls->protocols; - protocols != NULL ; protocols = protocols->next) + struct objc_protocol_list *protocols; + + for (protocols = cls->protocols; + protocols != NULL; protocols = protocols->next) + { + int i; + + for (i = 0; i < protocols->count; i++) { - for (int i=0 ; icount ; i++) - { - if (strcmp(protocols->list[i]->protocol_name, - protocol->protocol_name) == 0) - { - return YES; - } - } + if (strcmp(protocols->list[i]->protocol_name, + protocol->protocol_name) == 0) + { + return YES; + } } - return NO; + } + return NO; } -Ivar * class_copyIvarList(Class cls, unsigned int *outCount) +Ivar * +class_copyIvarList(Class cls, unsigned int *outCount) { - struct objc_ivar_list *ivarlist = cls->ivars; - unsigned int count = 0; - if (ivarlist != NULL) - { - count = ivarlist->ivar_count; - } - if (outCount != NULL) - { - *outCount = count; - } - if (count == 0) - { - return NULL; - } + struct objc_ivar_list *ivarlist = cls->ivars; + unsigned int count = 0; + unsigned int i; + Ivar *list; - Ivar *list = malloc(count * sizeof(struct objc_ivar *)); - for (unsigned int i=0; iivar_count; i++) - { - list[i] = &(ivarlist->ivar_list[i]); - } - return list; + if (ivarlist != NULL) + { + count = ivarlist->ivar_count; + } + if (outCount != NULL) + { + *outCount = count; + } + if (count == 0) + { + return NULL; + } + + list = malloc(count * sizeof(struct objc_ivar *)); + for (i = 0; i < ivarlist->ivar_count; i++) + { + list[i] = &(ivarlist->ivar_list[i]); + } + return list; } -Method * class_copyMethodList(Class cls, unsigned int *outCount) +Method * +class_copyMethodList(Class cls, unsigned int *outCount) { - unsigned int count = 0; - for (struct objc_method_list *methods = cls->methods; - methods != NULL ; methods = methods->method_next) - { - count += methods->method_count; - } - if (outCount != NULL) - { - *outCount = count; - } - if (count == 0) - { - return NULL; - } + unsigned int count = 0; + Method *list; + Method *copyDest; + struct objc_method_list *methods; - Method *list = malloc(count * sizeof(struct objc_method *)); - Method *copyDest = list; + for (methods = cls->methods; methods != NULL; methods = methods->method_next) + { + count += methods->method_count; + } + if (outCount != NULL) + { + *outCount = count; + } + if (count == 0) + { + return NULL; + } - for (struct objc_method_list *methods = cls->methods; - methods != NULL ; methods = methods->method_next) + list = malloc(count * sizeof(struct objc_method *)); + copyDest = list; + + for (methods = cls->methods; methods != NULL; methods = methods->method_next) + { + unsigned int i; + + for (i = 0; i < methods->method_count; i++) { - for (unsigned int i=0; imethod_count; i++) - { - copyDest[i] = &(methods->method_list[i]); - } - copyDest += methods->method_count; + copyDest[i] = &(methods->method_list[i]); } + copyDest += methods->method_count; + } - return list; + return list; } -Protocol ** class_copyProtocolList(Class cls, unsigned int *outCount) +Protocol ** +class_copyProtocolList(Class cls, unsigned int *outCount) { - struct objc_protocol_list *protocolList = cls->protocols; - int listSize = 0; - for (struct objc_protocol_list *list = protocolList ; - list != NULL ; - list = list->next) + struct objc_protocol_list *protocolList = cls->protocols; + struct objc_protocol_list *list; + int listSize = 0; + Protocol **protocols; + int index; + + for (list = protocolList; list != NULL; list = list->next) + { + listSize += list->count; + } + if (listSize == 0) + { + *outCount = 0; + return NULL; + } + + protocols = calloc(listSize, sizeof(Protocol*) + 1); + index = 0; + for (list = protocolList; list != NULL; list = list->next) + { + memcpy(&protocols[index], list->list, list->count * sizeof(Protocol*)); + index += list->count; + } + protocols[listSize] = NULL; + *outCount = listSize + 1; + return protocols; +} + +id +class_createInstance(Class cls, size_t extraBytes) +{ + id obj = objc_malloc(cls->instance_size + extraBytes); + obj->isa = cls; + return obj; +} + +Method +class_getInstanceMethod(Class aClass, SEL aSelector) +{ + Method method = class_getInstanceMethodNonrecursive(aClass, aSelector); + + if (method == NULL) + { + // TODO: Check if this should be NULL or aClass + Class superclass = class_getSuperclass(aClass); + + if (superclass == NULL) { - listSize += list->count; + return NULL; } - if (listSize == 0) + return class_getInstanceMethod(superclass, aSelector); + } + return method; +} + +Method +class_getClassMethod(Class aClass, SEL aSelector) +{ + return class_getInstanceMethod(aClass->class_pointer, aSelector); +} + +Ivar +class_getClassVariable(Class cls, const char* name) +{ + assert(0 && "Class variables not implemented"); + return NULL; +} + +size_t +class_getInstanceSize(Class cls) +{ + return cls->instance_size; +} + +Ivar +class_getInstanceVariable(Class cls, const char* name) +{ + struct objc_ivar_list *ivarlist = cls->ivars; + int i; + + if (NULL == ivarlist) + { + return NULL; + } + + for (i = 0; i < ivarlist->ivar_count; i++) + { + Ivar ivar = &ivarlist->ivar_list[i]; + + if (strcmp(ivar->ivar_name, name) == 0) { - *outCount = 0; - return NULL; + return ivar; } - - Protocol **protocols = calloc(listSize, sizeof(Protocol*) + 1); - int index = 0; - for (struct objc_protocol_list *list = protocolList ; - list != NULL ; - list = list->next) - { - memcpy(&protocols[index], list->list, list->count * sizeof(Protocol*)); - index += list->count; - } - protocols[listSize] = NULL; - *outCount = listSize + 1; - return protocols; -} - -id class_createInstance(Class cls, size_t extraBytes) -{ - id obj = objc_malloc(cls->instance_size + extraBytes); - obj->isa = cls; - return obj; -} - -Method class_getInstanceMethod(Class aClass, SEL aSelector) -{ - Method method = class_getInstanceMethodNonrecursive(aClass, aSelector); - if (method == NULL) - { - // TODO: Check if this should be NULL or aClass - Class superclass = class_getSuperclass(aClass); - if (superclass == NULL) - { - return NULL; - } - return class_getInstanceMethod(superclass, aSelector); - } - return method; -} - -Method class_getClassMethod(Class aClass, SEL aSelector) -{ - return class_getInstanceMethod(aClass->class_pointer, aSelector); -} - -Ivar class_getClassVariable(Class cls, const char* name) -{ - assert(0 && "Class variables not implemented"); - return NULL; -} - -size_t class_getInstanceSize(Class cls) -{ - return cls->instance_size; -} - -Ivar class_getInstanceVariable(Class cls, const char* name) -{ - struct objc_ivar_list *ivarlist = cls->ivars; - if (NULL == ivarlist) { return NULL; } - - for (int i=0 ; iivar_count ; i++) - { - Ivar ivar = &ivarlist->ivar_list[i]; - if (strcmp(ivar->ivar_name, name) == 0) - { - return ivar; - } - } - return NULL; + } + return NULL; } // The format of the char* is undocumented. This function is only ever used in // conjunction with class_setIvarLayout(). -const char *class_getIvarLayout(Class cls) +const char * +class_getIvarLayout(Class cls) { - return (char*)cls->ivars; + return (char*)cls->ivars; } -IMP class_getMethodImplementation(Class cls, SEL name) +IMP +class_getMethodImplementation(Class cls, SEL name) { - struct objc_object_gnu obj = { cls }; - return (IMP)objc_msg_lookup((id)&obj, name); + struct objc_object_gnu obj = { cls }; + return (IMP)objc_msg_lookup((id)&obj, name); } -IMP class_getMethodImplementation_stret(Class cls, SEL name) +IMP +class_getMethodImplementation_stret(Class cls, SEL name) { - struct objc_object_gnu obj = { cls }; - return (IMP)objc_msg_lookup((id)&obj, name); + struct objc_object_gnu obj = { cls }; + return (IMP)objc_msg_lookup((id)&obj, name); } -const char * class_getName(Class cls) +const char * +class_getName(Class cls) { - return class_get_class_name(cls); + return class_get_class_name(cls); } void __objc_resolve_class_links(void); -Class class_getSuperclass(Class cls) + +Class +class_getSuperclass(Class cls) { - if (!CLS_ISRESOLV(cls)) - { - __objc_resolve_class_links(); - } - return cls->super_class; + if (!CLS_ISRESOLV(cls)) + { + __objc_resolve_class_links(); + } + return cls->super_class; } -int class_getVersion(Class theClass) +int +class_getVersion(Class theClass) { - return class_get_version(theClass); + return class_get_version(theClass); } -const char *class_getWeakIvarLayout(Class cls) +const char * +class_getWeakIvarLayout(Class cls) { - assert(0 && "Weak ivars not supported"); - return NULL; + assert(0 && "Weak ivars not supported"); + return NULL; } -BOOL class_isMetaClass(Class cls) +BOOL +class_isMetaClass(Class cls) { - return CLS_ISMETA(cls); + return CLS_ISMETA(cls); } -IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) +IMP +class_replaceMethod(Class cls, SEL name, IMP imp, const char *types) { - Method method = class_getInstanceMethodNonrecursive(cls, name); - if (method == NULL) - { - class_addMethod(cls, name, imp, types); - return NULL; - } - IMP old = (IMP)method->method_imp; - method->method_imp = (objc_imp_gnu)imp; - return old; + Method method = class_getInstanceMethodNonrecursive(cls, name); + IMP old; + + if (method == NULL) + { + class_addMethod(cls, name, imp, types); + return NULL; + } + old = (IMP)method->method_imp; + method->method_imp = (objc_imp_gnu)imp; + return old; } -BOOL class_respondsToSelector(Class cls, SEL sel) +BOOL +class_respondsToSelector(Class cls, SEL sel) { - return __objc_responds_to(cls, sel); + return __objc_responds_to(cls, sel); } -void class_setIvarLayout(Class cls, const char *layout) +void +class_setIvarLayout(Class cls, const char *layout) { - struct objc_ivar_list *list = (struct objc_ivar_list*)layout; - size_t listsize = sizeof(struct objc_ivar_list) + - sizeof(struct objc_ivar) * (list->ivar_count - 1); - cls->ivars = malloc(listsize); - memcpy(cls->ivars, list, listsize); + struct objc_ivar_list *list = (struct objc_ivar_list*)layout; + size_t listsize = sizeof(struct objc_ivar_list) + + sizeof(struct objc_ivar) * (list->ivar_count - 1); + cls->ivars = malloc(listsize); + memcpy(cls->ivars, list, listsize); } __attribute__((deprecated)) -Class class_setSuperclass(Class cls, Class newSuper) +Class +class_setSuperclass(Class cls, Class newSuper) { - Class oldSuper = cls->super_class; - cls->super_class = newSuper; - return oldSuper; + Class oldSuper = cls->super_class; + cls->super_class = newSuper; + return oldSuper; } -void class_setVersion(Class theClass, int version) +void +class_setVersion(Class theClass, int version) { - class_set_version(theClass, version); + class_set_version(theClass, version); } -void class_setWeakIvarLayout(Class cls, const char *layout) +void +class_setWeakIvarLayout(Class cls, const char *layout) { - assert(0 && "Not implemented"); + assert(0 && "Not implemented"); } -const char * ivar_getName(Ivar ivar) +const char * +ivar_getName(Ivar ivar) { - return ivar->ivar_name; + return ivar->ivar_name; } -ptrdiff_t ivar_getOffset(Ivar ivar) +ptrdiff_t +ivar_getOffset(Ivar ivar) { - return ivar->ivar_offset; + return ivar->ivar_offset; } -const char * ivar_getTypeEncoding(Ivar ivar) +const char * +ivar_getTypeEncoding(Ivar ivar) { - return ivar->ivar_type; + return ivar->ivar_type; } -static size_t lengthOfTypeEncoding(const char *types) +static size_t +lengthOfTypeEncoding(const char *types) { - const char *end = objc_skip_argspec(types); - end--; - while (isdigit(*end)) { end--; } - size_t length = end - types + 1; - return length; + const char *end = objc_skip_argspec(types); + size_t length; + + end--; + while (isdigit(*end)) + { + end--; + } + length = end - types + 1; + return length; } -static char *copyTypeEncoding(const char *types) + +static char * +copyTypeEncoding(const char *types) { - size_t length = lengthOfTypeEncoding(types); - char *copy = malloc(length + 1); - memcpy(copy, types, length); - copy[length] = '\0'; - return copy; + size_t length = lengthOfTypeEncoding(types); + char *copy = malloc(length + 1); + + memcpy(copy, types, length); + copy[length] = '\0'; + return copy; } -static const char * findParameterStart(const char *types, unsigned int index) + +static const char * +findParameterStart(const char *types, unsigned int index) { - for (unsigned int i=0 ; imethod_types, index); - if (NULL == types) + const char *types = findParameterStart(method->method_types, index); + + if (NULL == types) + { + return NULL; + } + return copyTypeEncoding(types); +} + +char * +method_copyReturnType(Method method) +{ + return copyTypeEncoding(method->method_types); +} + +void +method_exchangeImplementations(Method m1, Method m2) +{ + IMP tmp = (IMP)m1->method_imp; + + m1->method_imp = m2->method_imp; + m2->method_imp = (objc_imp_gnu)tmp; + objc_updateDtableForClassContainingMethod(m1); + objc_updateDtableForClassContainingMethod(m2); +} + +void +method_getArgumentType(Method method, + unsigned int index, + char *dst, + size_t dst_len) +{ + const char *types; + size_t length; + + types = findParameterStart(method->method_types, index); + if (NULL == types) + { + strncpy(dst, "", dst_len); + return; + } + length = lengthOfTypeEncoding(types); + if (length < dst_len) + { + memcpy(dst, types, length); + dst[length] = '\0'; + } + else + { + memcpy(dst, types, dst_len); + } +} + +IMP +method_getImplementation(Method method) +{ + return (IMP)method->method_imp; +} + +SEL +method_getName(Method method) +{ + return method->method_name; +} + +unsigned +method_getNumberOfArguments(Method method) +{ + const char *types = method->method_types; + unsigned int count = 0; + + while('\0' != *types) + { + types = objc_skip_argspec(types); + count++; + } + return count - 1; +} + +void +method_getReturnType(Method method, char *dst, size_t dst_len) +{ + //TODO: Coped and pasted code. Factor it out. + const char *types = method->method_types; + size_t length = lengthOfTypeEncoding(types); + + if (length < dst_len) + { + memcpy(dst, types, length); + dst[length] = '\0'; + } + else + { + memcpy(dst, types, dst_len); + } +} + +const char * +method_getTypeEncoding(Method method) +{ + return method->method_types; +} + +IMP +method_setImplementation(Method method, IMP imp) +{ + IMP old = (IMP)method->method_imp; + + method->method_imp = (objc_imp_gnu)old; + objc_updateDtableForClassContainingMethod(method); + return old; +} + +id +objc_getClass(const char *name) +{ + return (id)objc_get_class(name); +} + +int +objc_getClassList(Class *buffer, int bufferLen) +{ + int count = 0; + + if (buffer == NULL) + { + void *state = NULL; + while(Nil != objc_next_class(&state)) { - return NULL; + count++; } - return copyTypeEncoding(types); -} + } + else + { + Class nextClass; + void *state = NULL; -char * method_copyReturnType(Method method) -{ - return copyTypeEncoding(method->method_types); -} - -void method_exchangeImplementations(Method m1, Method m2) -{ - IMP tmp = (IMP)m1->method_imp; - m1->method_imp = m2->method_imp; - m2->method_imp = (objc_imp_gnu)tmp; - objc_updateDtableForClassContainingMethod(m1); - objc_updateDtableForClassContainingMethod(m2); -} -void method_getArgumentType(Method method, - unsigned int index, - char *dst, - size_t dst_len) -{ - const char *types = findParameterStart(method->method_types, index); - if (NULL == types) + while (Nil != (nextClass = objc_next_class(&state)) && bufferLen > 0) { - strncpy(dst, "", dst_len); - return; + count++; + bufferLen--; + *(buffer++) = nextClass; } - size_t length = lengthOfTypeEncoding(types); - if (length < dst_len) + } + return count; +} + +id +objc_getMetaClass(const char *name) +{ + Class cls = (Class)objc_getClass(name); + return cls == Nil ? nil : (id)cls->class_pointer; +} + +id +objc_getRequiredClass(const char *name) +{ + id cls = objc_getClass(name); + + if (nil == cls) + { + abort(); + } + return cls; +} + +id +objc_lookUpClass(const char *name) +{ + // TODO: Check these are the right way around. + return (id)objc_lookup_class(name); +} + +static void +freeMethodLists(Class aClass) +{ + struct objc_method_list *methods = aClass->methods; + struct objc_method_list *current; + + while (methods != NULL) + { + int i; + + for (i = 0; i < methods->method_count; i++) { - memcpy(dst, types, length); - dst[length] = '\0'; - } - else - { - memcpy(dst, types, dst_len); + free((void*)methods->method_list[i].method_types); } + current = methods; + methods = methods->method_next; + free(current); + } } -IMP method_getImplementation(Method method) +static void +freeIvarLists(Class aClass) { - return (IMP)method->method_imp; -} + struct objc_ivar_list *ivarlist = aClass->ivars; + int i; -SEL method_getName(Method method) -{ - return method->method_name; -} + if (NULL == ivarlist) + { + return; + } -unsigned method_getNumberOfArguments(Method method) -{ - const char *types = method->method_types; - unsigned int count = 0; - while('\0' != *types) - { - types = objc_skip_argspec(types); - count++; - } - return count - 1; -} + for (i = 0; i < ivarlist->ivar_count; i++) + { + Ivar ivar = &ivarlist->ivar_list[i]; -void method_getReturnType(Method method, char *dst, size_t dst_len) -{ - //TODO: Coped and pasted code. Factor it out. - const char *types = method->method_types; - size_t length = lengthOfTypeEncoding(types); - if (length < dst_len) - { - memcpy(dst, types, length); - dst[length] = '\0'; - } - else - { - memcpy(dst, types, dst_len); - } -} - -const char * method_getTypeEncoding(Method method) -{ - return method->method_types; -} - -IMP method_setImplementation(Method method, IMP imp) -{ - IMP old = (IMP)method->method_imp; - method->method_imp = (objc_imp_gnu)old; - objc_updateDtableForClassContainingMethod(method); - return old; -} - -id objc_getClass(const char *name) -{ - return (id)objc_get_class(name); -} - -int objc_getClassList(Class *buffer, int bufferLen) -{ - int count = 0; - if (buffer == NULL) - { - void *state = NULL; - while(Nil != objc_next_class(&state)) - { - count++; - } - } - else - { - Class nextClass; - void *state = NULL; - while (Nil != (nextClass = objc_next_class(&state)) && bufferLen > 0) - { - count++; - bufferLen--; - *(buffer++) = nextClass; - } - } - return count; -} - -id objc_getMetaClass(const char *name) -{ - Class cls = (Class)objc_getClass(name); - return cls == Nil ? nil : (id)cls->class_pointer; -} - -id objc_getRequiredClass(const char *name) -{ - id cls = objc_getClass(name); - if (nil == cls) - { - abort(); - } - return cls; -} - -id objc_lookUpClass(const char *name) -{ - // TODO: Check these are the right way around. - return (id)objc_lookup_class(name); -} - -static void freeMethodLists(Class aClass) -{ - struct objc_method_list *methods = aClass->methods; - while(methods != NULL) - { - for (int i=0 ; imethod_count ; i++) - { - free((void*)methods->method_list[i].method_types); - } - struct objc_method_list *current = methods; - methods = methods->method_next; - free(current); - } -} - -static void freeIvarLists(Class aClass) -{ - struct objc_ivar_list *ivarlist = aClass->ivars; - if (NULL == ivarlist) { return; } - - for (int i=0 ; iivar_count ; i++) - { - Ivar ivar = &ivarlist->ivar_list[i]; - free((void*)ivar->ivar_type); - free((void*)ivar->ivar_name); - } - free(ivarlist); + free((void*)ivar->ivar_type); + free((void*)ivar->ivar_name); + } + free(ivarlist); } /* * Removes a class from the subclass list found on its super class. * Must be called with the objc runtime mutex locked. */ -static inline void safe_remove_from_subclass_list(Class cls) +static inline void +safe_remove_from_subclass_list(Class cls) { - Class sub = cls->super_class->subclass_list; - if (sub == cls) + Class sub = cls->super_class->subclass_list; + + if (sub == cls) + { + cls->super_class->subclass_list = cls->sibling_class; + } + else + { + while (sub != NULL) { - cls->super_class->subclass_list = cls->sibling_class; - } - else - { - while (sub != NULL) - { - if (sub->sibling_class == cls) - { - sub->sibling_class = cls->sibling_class; - break; - } - sub = sub->sibling_class; - } + if (sub->sibling_class == cls) + { + sub->sibling_class = cls->sibling_class; + break; + } + sub = sub->sibling_class; } + } } -void objc_disposeClassPair(Class cls) +void +objc_disposeClassPair(Class cls) { - Class meta = ((id)cls)->isa; - // Remove from the runtime system so nothing tries updating the dtable - // while we are freeing the class. - objc_mutex_lock(__objc_runtime_mutex); - safe_remove_from_subclass_list(meta); - safe_remove_from_subclass_list(cls); - objc_mutex_unlock(__objc_runtime_mutex); + Class meta = ((id)cls)->isa; - // Free the method and ivar lists. - freeMethodLists(cls); - freeMethodLists(meta); - freeIvarLists(cls); + // Remove from the runtime system so nothing tries updating the dtable + // while we are freeing the class. + objc_mutex_lock(__objc_runtime_mutex); + safe_remove_from_subclass_list(meta); + safe_remove_from_subclass_list(cls); + objc_mutex_unlock(__objc_runtime_mutex); - // Free the class and metaclass - free(meta); - free(cls); + // Free the method and ivar lists. + freeMethodLists(cls); + freeMethodLists(meta); + freeIvarLists(cls); + + // Free the class and metaclass + free(meta); + free(cls); } -Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) +Class +objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) { - // Check the class doesn't already exist. - if (nil != objc_lookUpClass(name)) { return Nil; } + Class newClass; + Class metaClass; - Class newClass = calloc(1, sizeof(struct objc_class) + extraBytes); + // Check the class doesn't already exist. + if (nil != objc_lookUpClass(name)) + { + return Nil; + } - if (Nil == newClass) { return Nil; } + newClass = calloc(1, sizeof(struct objc_class) + extraBytes); - // Create the metaclass - Class metaClass = calloc(1, sizeof(struct objc_class)); + if (Nil == newClass) + { + return Nil; + } - // Initialize the metaclass - metaClass->class_pointer = superclass->class_pointer->class_pointer; - metaClass->super_class = superclass->class_pointer; - metaClass->name = strdup(name); - metaClass->info = _CLS_META; - metaClass->dtable = __objc_uninstalled_dtable; - metaClass->instance_size = sizeof(struct objc_class); + // Create the metaclass + metaClass = calloc(1, sizeof(struct objc_class)); - // Set up the new class - newClass->class_pointer = metaClass; - // Set the superclass pointer to the name. The runtime will fix this when - // the class links are resolved. - newClass->super_class = (Class)superclass->name; - newClass->name = strdup(name); - newClass->info = _CLS_CLASS; - newClass->dtable = __objc_uninstalled_dtable; - newClass->instance_size = superclass->instance_size; + // Initialize the metaclass + metaClass->class_pointer = superclass->class_pointer->class_pointer; + metaClass->super_class = superclass->class_pointer; + metaClass->name = strdup(name); + metaClass->info = _CLS_META; + metaClass->dtable = __objc_uninstalled_dtable; + metaClass->instance_size = sizeof(struct objc_class); - return newClass; + // Set up the new class + newClass->class_pointer = metaClass; + // Set the superclass pointer to the name. The runtime will fix this when + // the class links are resolved. + newClass->super_class = (Class)superclass->name; + newClass->name = strdup(name); + newClass->info = _CLS_CLASS; + newClass->dtable = __objc_uninstalled_dtable; + newClass->instance_size = superclass->instance_size; + + return newClass; } -void *object_getIndexedIvars(id obj) +void * +object_getIndexedIvars(id obj) { - if (class_isMetaClass(obj->isa)) - { - return ((char*)obj) + sizeof(struct objc_class); - } - return ((char*)obj) + obj->isa->instance_size; + if (class_isMetaClass(obj->isa)) + { + return ((char*)obj) + sizeof(struct objc_class); + } + return ((char*)obj) + obj->isa->instance_size; } -Class object_getClass(id obj) +Class +object_getClass(id obj) { - if (nil != obj) - { - return obj->isa; - } - return Nil; + if (nil != obj) + { + return obj->isa; + } + return Nil; } -Class object_setClass(id obj, Class cls) +Class +object_setClass(id obj, Class cls) { - if (nil != obj) - { - Class oldClass = obj->isa; - obj->isa = cls; - return oldClass; - } - return Nil; + if (nil != obj) + { + Class oldClass = obj->isa; + + obj->isa = cls; + return oldClass; + } + return Nil; } -const char *object_getClassName(id obj) +const char * +object_getClassName(id obj) { - return class_getName(object_getClass(obj)); + return class_getName(object_getClass(obj)); } void __objc_add_class_to_hash(Class cls); void __objc_resolve_class_links(void); -void objc_registerClassPair(Class cls) +void +objc_registerClassPair(Class cls) { - Class metaClass = cls->class_pointer; + Class metaClass = cls->class_pointer; - // Initialize the dispatch table for the class and metaclass. - __objc_update_dispatch_table_for_class(metaClass); - __objc_update_dispatch_table_for_class(cls); - __objc_add_class_to_hash(cls); - // Add pointer from super class - __objc_resolve_class_links(); + // Initialize the dispatch table for the class and metaclass. + __objc_update_dispatch_table_for_class(metaClass); + __objc_update_dispatch_table_for_class(cls); + __objc_add_class_to_hash(cls); + // Add pointer from super class + __objc_resolve_class_links(); } -static id objectNew(id cls) +static id +objectNew(id cls) { - static SEL newSel = NULL; - if (NULL == newSel) - { - newSel = sel_get_uid("new"); - } - IMP newIMP = (IMP)objc_msg_lookup((void*)cls, newSel); - return newIMP((id)cls, newSel); + static SEL newSel = NULL; + IMP newIMP; + + if (NULL == newSel) + { + newSel = sel_get_uid("new"); + } + newIMP = (IMP)objc_msg_lookup((void*)cls, newSel); + return newIMP((id)cls, newSel); } -Protocol *objc_getProtocol(const char *name) +Protocol * +objc_getProtocol(const char *name) { - // Protocols are not centrally registered in the GNU runtime. - Protocol *protocol = (Protocol*)(objectNew(objc_getClass("Protocol"))); - protocol->protocol_name = (char*)name; - return protocol; + // Protocols are not centrally registered in the GNU runtime. + Protocol *protocol = (Protocol*)(objectNew(objc_getClass("Protocol"))); + + protocol->protocol_name = (char*)name; + return protocol; } -BOOL protocol_conformsToProtocol(Protocol *p, Protocol *other) +BOOL +protocol_conformsToProtocol(Protocol *p, Protocol *other) { - return NO; + return NO; } -struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, - BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count) +struct objc_method_description * +protocol_copyMethodDescriptionList(Protocol *p, + BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count) { - *count = 0; - return NULL; + *count = 0; + return NULL; } -Protocol **protocol_copyProtocolList(Protocol *p, unsigned int *count) +Protocol ** +protocol_copyProtocolList(Protocol *p, unsigned int *count) { - *count = 0; - return NULL; + *count = 0; + return NULL; } -const char *protocol_getName(Protocol *p) +const char * +protocol_getName(Protocol *p) { - if (NULL != p) - { - return p->protocol_name; - } - return NULL; + if (NULL != p) + { + return p->protocol_name; + } + return NULL; } -BOOL protocol_isEqual(Protocol *p, Protocol *other) +BOOL +protocol_isEqual(Protocol *p, Protocol *other) { - if (NULL == p || NULL == other) - { - return NO; - } - if (p == other || - 0 == strcmp(p->protocol_name, other->protocol_name)) - { - return YES; - } - return NO; + if (NULL == p || NULL == other) + { + return NO; + } + if (p == other + || 0 == strcmp(p->protocol_name, other->protocol_name)) + { + return YES; + } + return NO; } -const char *sel_getName(SEL sel) +const char * +sel_getName(SEL sel) { - return sel_get_name(sel); + return sel_get_name(sel); } -SEL sel_getUid(const char *selName) +SEL +sel_getUid(const char *selName) { - return sel_get_uid(selName); + return sel_get_uid(selName); } -BOOL sel_isEqual(SEL sel1, SEL sel2) +BOOL +sel_isEqual(SEL sel1, SEL sel2) { - // FIXME: Is this correct? - return (0 == strcmp(sel_get_name(sel1), sel_get_name(sel2))); + return sel_eq(sel1, sel2) ? YES : NO; } -SEL sel_registerName(const char *selName) +SEL +sel_registerName(const char *selName) { - return sel_register_name(selName); + return sel_register_name(selName); } diff --git a/Source/ObjectiveC2/sync.m b/Source/ObjectiveC2/sync.m index 571086dff..f60f2953c 100644 --- a/Source/ObjectiveC2/sync.m +++ b/Source/ObjectiveC2/sync.m @@ -2,7 +2,7 @@ /* Ensure Unix98 compatible pthreads for glibc */ #if defined __GLIBC__ - #define __USE_UNIX98 1 +# define __USE_UNIX98 1 #endif #include @@ -20,88 +20,104 @@ IMP objc_msg_lookup(id, SEL); static void deallocLockClass(id obj, SEL _cmd); -static inline Class findLockClass(id obj) +static inline Class +findLockClass(id obj) { - struct objc_object object = { obj->isa }; - SEL dealloc = @selector(dealloc); - // Find the first class where this lookup is correct - if (objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass) + struct objc_object object = { obj->isa }; + SEL dealloc = @selector(dealloc); + Class lastClass; + + // Find the first class where this lookup is correct + if (objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass) + { + do { + object.isa = class_getSuperclass(object.isa); + } while (Nil != object.isa + && objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass); + } + if (Nil == object.isa) + { + return Nil; + } + /* object->isa is now either the lock class, or a class which inherits from + * the lock class + */ + do { + lastClass = object.isa; + object.isa = class_getSuperclass(object.isa); + } while (Nil != object.isa + && objc_msg_lookup((id)&object, dealloc) == (IMP)deallocLockClass); + return lastClass; +} + +static inline Class +initLockObject(id obj) +{ + char nameBuffer[40]; + Class lockClass; + const char *types; + pthread_mutex_t *lock; + + snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++); + lockClass = objc_allocateClassPair(obj->isa, nameBuffer, + sizeof(pthread_mutex_t)); + types = method_getTypeEncoding(class_getInstanceMethod(obj->isa, + @selector(dealloc))); + class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, types); + objc_registerClassPair(lockClass); + + lock = object_getIndexedIvars(lockClass); + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(lock, &attr); + pthread_mutexattr_destroy(&attr); + + obj->isa = lockClass; + return lockClass; +} + +static void +deallocLockClass(id obj, SEL _cmd) +{ + Class lockClass = findLockClass(obj); + Class realClass = class_getSuperclass(lockClass); + // Free the lock + pthread_mutex_t *lock = object_getIndexedIvars(lockClass); + + pthread_mutex_destroy(lock); + // Free the class + objc_disposeClassPair(lockClass); + // Reset the class then call the real -dealloc + obj->isa = realClass; + [obj dealloc]; +} + +void +objc_sync_enter(id obj) +{ + Class lockClass = findLockClass(obj); + pthread_mutex_t *lock; + + if (Nil == lockClass) + { + pthread_mutex_lock(&at_sync_init_lock); + // Test again in case two threads call objc_sync_enter at once + lockClass = findLockClass(obj); + if (Nil == lockClass) { - do { - object.isa = class_getSuperclass(object.isa); - } while (Nil != object.isa && - objc_msg_lookup((id)&object, dealloc) != (IMP)deallocLockClass); + lockClass = initLockObject(obj); } - if (Nil == object.isa) { return Nil; } - // object->isa is now either the lock class, or a class which inherits from - // the lock class - Class lastClass; - do { - lastClass = object.isa; - object.isa = class_getSuperclass(object.isa); - } while (Nil != object.isa && - objc_msg_lookup((id)&object, dealloc) == (IMP)deallocLockClass); - return lastClass; + pthread_mutex_unlock(&at_sync_init_lock); + } + lock = object_getIndexedIvars(lockClass); + pthread_mutex_lock(lock); } -static inline Class initLockObject(id obj) +void +objc_sync_exit(id obj) { - char nameBuffer[40]; - snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++); - Class lockClass = objc_allocateClassPair(obj->isa, nameBuffer, - sizeof(pthread_mutex_t)); - const char *types = - method_getTypeEncoding(class_getInstanceMethod(obj->isa, - @selector(dealloc))); - class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, - types); - objc_registerClassPair(lockClass); - - pthread_mutex_t *lock = object_getIndexedIvars(lockClass); - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(lock, &attr); - pthread_mutexattr_destroy(&attr); - - obj->isa = lockClass; - return lockClass; -} - -static void deallocLockClass(id obj, SEL _cmd) -{ - Class lockClass = findLockClass(obj); - Class realClass = class_getSuperclass(lockClass); - // Free the lock - pthread_mutex_t *lock = object_getIndexedIvars(lockClass); - pthread_mutex_destroy(lock); - // Free the class - objc_disposeClassPair(lockClass); - // Reset the class then call the real -dealloc - obj->isa = realClass; - [obj dealloc]; -} - -void objc_sync_enter(id obj) -{ - Class lockClass = findLockClass(obj); - if (Nil == lockClass) - { - pthread_mutex_lock(&at_sync_init_lock); - // Test again in case two threads call objc_sync_enter at once - lockClass = findLockClass(obj); - if (Nil == lockClass) - { - lockClass = initLockObject(obj); - } - pthread_mutex_unlock(&at_sync_init_lock); - } - pthread_mutex_t *lock = object_getIndexedIvars(lockClass); - pthread_mutex_lock(lock); -} -void objc_sync_exit(id obj) -{ - Class lockClass = findLockClass(obj); - pthread_mutex_t *lock = object_getIndexedIvars(lockClass); - pthread_mutex_unlock(lock); + Class lockClass = findLockClass(obj); + pthread_mutex_t *lock = object_getIndexedIvars(lockClass); + pthread_mutex_unlock(lock); } diff --git a/config.mak.in b/config.mak.in index 97920c78c..70a737f02 100644 --- a/config.mak.in +++ b/config.mak.in @@ -18,6 +18,7 @@ WITH_FFI=@WITH_FFI@ NX_CONST_STRING_CLASS=@NX_CONST_STRING_CLASS@ OBJCFLAGS=@OBJCFLAGS@ +OBJC2RUNTIME=@OBJC2RUNTIME@ HAVE_INET_PTON=@HAVE_INET_PTON@ HAVE_INET_NTOP=@HAVE_INET_NTOP@ diff --git a/configure b/configure index ea7ec1ce4..d566aeb52 100755 --- a/configure +++ b/configure @@ -310,7 +310,7 @@ ac_includes_default="\ #endif" ac_subdirs_all="$ac_subdirs_all Source/pathconfig Source/mframe SSL" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP WHOAMI EGREP OBJC_WITH_GC GS_WORDS_BIGENDIAN GS_SINT8 GS_UINT8 ac_cv_sizeof_short ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long ac_cv_sizeof_float ac_cv_sizeof_double ac_cv_sizeof_voidp GS_SADDR GS_UADDR GS_SINT16 GS_UINT16 GS_SINT32 GS_UINT32 GS_SINT64 GS_UINT64 GS_HAVE_I64 GS_SINT128 GS_UINT128 GS_HAVE_I128 GS_FLT32 GS_FLT64 _GSC_S_SHT _GSC_S_INT _GSC_S_LNG _GSC_S_LNG_LNG DYNAMIC_LINKER NX_CONST_STRING_OBJCFLAGS NX_CONST_STRING_CLASS HAVE_OBJC_SYNC_ENTER GS_SIZEOF_MUTEX_T GS_SIZEOF_COND_T HAVE_PTS_STREAM_MODULES INCLUDE_STDINT DEFINE_INT8_T DEFINE_UINT8_T DEFINE_INT16_T DEFINE_UINT16_T DEFINE_INT32_T DEFINE_UINT32_T DEFINE_INT64_T DEFINE_UINT64_T DEFINE_INTPTR_T DEFINE_UINTPTR_T USE_ZLIB HAVE_INET_PTON HAVE_INET_NTOP GS_PASS_ARGUMENTS GS_FAKE_MAIN OBJCFLAGS WITH_FFI XML2_CONFIG XML_CONFIG XML_CFLAGS XML_LIBS HAVE_LIBXSLT HAVE_LIBXML TLS_CONFIG TLS_CFLAGS TLS_LIBS HAVE_GNUTLS HAVE_MDNS USE_GMP INCLUDE_FLAGS LDIR_FLAGS subdirs VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP WHOAMI EGREP OBJC_WITH_GC GS_WORDS_BIGENDIAN GS_SINT8 GS_UINT8 ac_cv_sizeof_short ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long ac_cv_sizeof_float ac_cv_sizeof_double ac_cv_sizeof_voidp GS_SADDR GS_UADDR GS_SINT16 GS_UINT16 GS_SINT32 GS_UINT32 GS_SINT64 GS_UINT64 GS_HAVE_I64 GS_SINT128 GS_UINT128 GS_HAVE_I128 GS_FLT32 GS_FLT64 _GSC_S_SHT _GSC_S_INT _GSC_S_LNG _GSC_S_LNG_LNG DYNAMIC_LINKER NX_CONST_STRING_OBJCFLAGS NX_CONST_STRING_CLASS OBJC2RUNTIME HAVE_OBJC_SYNC_ENTER GS_SIZEOF_MUTEX_T GS_SIZEOF_COND_T HAVE_PTS_STREAM_MODULES INCLUDE_STDINT DEFINE_INT8_T DEFINE_UINT8_T DEFINE_INT16_T DEFINE_UINT16_T DEFINE_INT32_T DEFINE_UINT32_T DEFINE_INT64_T DEFINE_UINT64_T DEFINE_INTPTR_T DEFINE_UINTPTR_T USE_ZLIB HAVE_INET_PTON HAVE_INET_NTOP GS_PASS_ARGUMENTS GS_FAKE_MAIN OBJCFLAGS WITH_FFI XML2_CONFIG XML_CONFIG XML_CFLAGS XML_LIBS HAVE_LIBXSLT HAVE_LIBXML TLS_CONFIG TLS_CFLAGS TLS_LIBS HAVE_GNUTLS HAVE_MDNS USE_GMP INCLUDE_FLAGS LDIR_FLAGS subdirs VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -8647,6 +8647,118 @@ fi done +#-------------------------------------------------------------------- +# Check for ObjC2 support in runtime +#-------------------------------------------------------------------- + +for ac_func in objc_setProperty +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test $ac_cv_func_objc_setProperty = yes ; then + OBJC2RUNTIME=yes +else + OBJC2RUNTIME=no +fi + + # Don't revert any Objective-C flags as they are used in the next test #-------------------------------------------------------------------- @@ -21401,6 +21513,7 @@ s,@_GSC_S_LNG_LNG@,$_GSC_S_LNG_LNG,;t t s,@DYNAMIC_LINKER@,$DYNAMIC_LINKER,;t t s,@NX_CONST_STRING_OBJCFLAGS@,$NX_CONST_STRING_OBJCFLAGS,;t t s,@NX_CONST_STRING_CLASS@,$NX_CONST_STRING_CLASS,;t t +s,@OBJC2RUNTIME@,$OBJC2RUNTIME,;t t s,@HAVE_OBJC_SYNC_ENTER@,$HAVE_OBJC_SYNC_ENTER,;t t s,@GS_SIZEOF_MUTEX_T@,$GS_SIZEOF_MUTEX_T,;t t s,@GS_SIZEOF_COND_T@,$GS_SIZEOF_COND_T,;t t diff --git a/configure.ac b/configure.ac index 23f4fb747..0ab38afc8 100644 --- a/configure.ac +++ b/configure.ac @@ -658,6 +658,17 @@ fi #-------------------------------------------------------------------- AC_CHECK_FUNCS(objc_thread_add) +#-------------------------------------------------------------------- +# Check for ObjC2 support in runtime +#-------------------------------------------------------------------- +AC_CHECK_FUNCS(objc_setProperty) +if test $ac_cv_func_objc_setProperty = yes ; then + OBJC2RUNTIME=yes +else + OBJC2RUNTIME=no +fi +AC_SUBST(OBJC2RUNTIME) + # Don't revert any Objective-C flags as they are used in the next test #--------------------------------------------------------------------