X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=sope-core%2FNGExtensions%2FNGObjCRuntime.m;h=b8aa29d72649caf95c6ff8e70b17a9c2e4fe2094;hb=da4fee939ad67e8da731714f06358d6bdd3ee617;hp=3003fb608b760db9f36f0fd37c81331d1772a98f;hpb=7eadc020be39163d31271943ebe303a97725794e;p=sope diff --git a/sope-core/NGExtensions/NGObjCRuntime.m b/sope-core/NGExtensions/NGObjCRuntime.m index 3003fb60..b8aa29d7 100644 --- a/sope-core/NGExtensions/NGObjCRuntime.m +++ b/sope-core/NGExtensions/NGObjCRuntime.m @@ -1,24 +1,23 @@ /* - Copyright (C) 2000-2004 SKYRIX Software AG + Copyright (C) 2000-2005 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOPE. - OGo is free software; you can redistribute it and/or modify it under + SOPE 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, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with OGo; see the file COPYING. If not, write to the + License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id$ #include "NGObjCRuntime.h" #include "NGMemoryAllocation.h" @@ -75,6 +74,26 @@ void class_add_behavior(Class class, Class behavior) { @end +#if NeXT_RUNTIME || APPLE_RUNTIME + +static __inline__ unsigned NGGetSizeOfType(char *ivarType) { + // TODO: add more types ... + switch (*ivarType) { + /* the Apple runtime has no func to calc a type size ?! */ + case '@': return sizeof(id); + case ':': return sizeof(SEL); + case 'c': return sizeof(signed char); + case 's': return sizeof(signed short); + case 'i': return sizeof(signed int); + case 'C': return sizeof(unsigned char); + case 'S': return sizeof(unsigned short); + case 'I': return sizeof(unsigned int); + default: return 0xDEAFBEAF; + } +} + +#endif + @implementation NSObject(NGObjCRuntime) static NSArray *emptyArray = nil; @@ -115,7 +134,7 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) unsigned count; selector = _selector; - signature = selector ? va_arg(*va, NSString *) : nil; + signature = selector ? va_arg(*va, NSString *) : (NSString *)nil; imp = signature ? va_arg(*va, IMP) : NULL; count = 0; while ((selector != NULL) && (signature != nil) && (imp != NULL)) { @@ -385,8 +404,36 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) void __objc_resolve_class_links(); #endif - //printf("execute class\n"); + /* + This is the main entry function in the GNU runtime. It does a LOT of + work, including the setup of global hashes if missing. Some things (like + the global hashes) are not relevant for us, since the runtime itself is + already up. + This function uses the internal lock for runtime modifications. + + The method does with the runtime lock applied (2.95.3): + - setup globals + - registers typed selectors for symtab->refs + - walks over all classes + - adds the class to the hash + - registers the selectors of the class + - registers the selectors of the metaclass + - install dtable's (just assigns NULL?) + - registers instance methods as class methods for root classes + - inits protocols + - add superclasses to unresolved-classes + - walks over all categories + - register uninitialized statics + - walk over unclaimed categories + - walk over unclaimed protocols + - send the +load message + + Actually this function just calls __objc_exec_module(), don't know why + we call this one instead. + */ + // printf("execute class\n"); __objc_exec_class(module); + //printf("resolve links\n"); __objc_resolve_class_links(); } @@ -396,21 +443,14 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) } + (Class)subclass:(NSString *)_className - ivars:(NSString *)_name1,... + ivarNames:(NSString **)_ivarNames + ivarTypes:(NSString **)_ivarTypes + ivarCount:(unsigned)ivarCount { - va_list va; - unsigned ivarCount, currentSize; - NSString *n, *t; + unsigned currentSize; currentSize = ((Class)self)->instance_size; - va_start(va, _name1); - for (n = _name1, t = va_arg(va, NSString *), ivarCount = 0; - (n != nil && t != nil); - n = va_arg(va, NSString *), t = va_arg(va, NSString *)) - ivarCount++; - va_end(va); - #if NeXT_RUNTIME || APPLE_RUNTIME { /* some tricks for Apple inspired by PyObjC, long live OpenSource ;-) */ @@ -423,17 +463,20 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) ivars = NULL; if (ivarCount > 0) { + unsigned i; + ivars = calloc(sizeof(struct objc_ivar_list) + (ivarCount) * sizeof(struct objc_ivar), sizeof(char)); - va_start(va, _name1); - for (n = _name1, t = va_arg(va, NSString *), ivarCount = 0; - (n != nil && t != nil); - n = va_arg(va, NSString *), t=va_arg(va, NSString *), ivarCount++) { + for (i = 0; i < ivarCount; i++) { + NSString *n, *t; Ivar var; char *ivarName, *ivarType; int ivarOffset; unsigned len, typeAlign, typeLen; + + n = _ivarNames[i]; + t = _ivarTypes[i]; len = [n cStringLength]; ivarName = malloc(len + 2); @@ -447,24 +490,13 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) /* calc ivarOffset */ typeAlign = 0; // TODO: alignment?! - // TODO: add more types ... - switch (*ivarType) { - /* the Apple runtime has no func to calc a type size ?! */ - case '@': typeLen = sizeof(id); break; - case ':': typeLen = sizeof(SEL); break; - case 'c': typeLen = sizeof(signed char); break; - case 's': typeLen = sizeof(signed short); break; - case 'i': typeLen = sizeof(signed int); break; - case 'C': typeLen = sizeof(unsigned char); break; - case 'S': typeLen = sizeof(unsigned short); break; - case 'I': typeLen = sizeof(unsigned int); break; - default: - NSAssert1(NO, @"does not support ivars of type '%s'", ivarType); - break; - } + + typeLen = NGGetSizeOfType(ivarType); + NSAssert1(typeLen != 0xDEAFBEAF, + @"does not support ivars of type '%s'", ivarType); ivarOffset = currentSize; - - var = ivars->ivar_list + ivars->ivar_count; + + var = ivars->ivar_list + ivars->ivar_count; ivars->ivar_count++; var->ivar_name = ivarName; @@ -474,9 +506,8 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) /* adjust current size */ currentSize = ivarOffset + typeLen; } - va_end(va); } - + // TODO: move the following to a subclass method /* determine root class */ @@ -526,53 +557,99 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) } #else { - IvarList_t ivars; - - ivars = malloc(sizeof(IvarList) + (sizeof(struct objc_ivar) * ivarCount)); - ivars->ivar_count = ivarCount; + unsigned i; + IvarList_t ivars; - va_start(va, _name1); - for (n = _name1, t = va_arg(va, NSString *), ivarCount = 0; - (n != nil && t != nil); - n = va_arg(va, NSString *), t = va_arg(va, NSString *), ivarCount++) { - char *ivarName, *ivarType; - int ivarOffset; - unsigned len, typeAlign, typeLen; - - len = [n cStringLength]; - ivarName = malloc(len + 2); - [n getCString:ivarName]; - ivarName[len] = '\0'; - - len = [t cStringLength]; - ivarType = malloc(len + 2); - [t getCString:ivarType]; - ivarType[len] = '\0'; - - /* calc ivarOffset */ - typeAlign = objc_alignof_type(ivarType); - typeLen = objc_sizeof_type(ivarType); - ivarOffset = currentSize; + ivars = malloc(sizeof(IvarList) + (sizeof(struct objc_ivar) * ivarCount)); + ivars->ivar_count = ivarCount; - /* check if offset is aligned */ - if ((ivarOffset % typeAlign) != 0) { - /* align offset */ - len = (typeAlign - (ivarOffset % typeAlign)); - ivarOffset += len; - } + for (i = 0; i < ivarCount; i++) { + NSString *n, *t; + char *ivarName, *ivarType; + int ivarOffset; + unsigned len, typeAlign, typeLen; + + n = _ivarNames[i]; + t = _ivarTypes[i]; + + len = [n cStringLength]; + ivarName = malloc(len + 2); + [n getCString:ivarName]; + ivarName[len] = '\0'; + + len = [t cStringLength]; + ivarType = malloc(len + 2); + [t getCString:ivarType]; + ivarType[len] = '\0'; + + /* calc ivarOffset */ + typeAlign = objc_alignof_type(ivarType); + typeLen = objc_sizeof_type(ivarType); + ivarOffset = currentSize; + + /* check if offset is aligned */ + if ((ivarOffset % typeAlign) != 0) { + /* align offset */ + len = (typeAlign - (ivarOffset % typeAlign)); + ivarOffset += len; + } - /* adjust current size */ - currentSize = ivarOffset + typeLen; + /* adjust current size */ + currentSize = ivarOffset + typeLen; - ivars->ivar_list[ivarCount].ivar_name = ivarName; - ivars->ivar_list[ivarCount].ivar_type = ivarType; - ivars->ivar_list[ivarCount].ivar_offset = ivarOffset; + ivars->ivar_list[ivarCount].ivar_name = ivarName; + ivars->ivar_list[ivarCount].ivar_type = ivarType; + ivars->ivar_list[ivarCount].ivar_offset = ivarOffset; + } + + return [self subclass:_className ivarsList:ivars]; } +#endif +} + ++ (Class)subclass:(NSString *)_className + ivars:(NSString *)_name1,... +{ + va_list va; /* contains: name1, type1, name2, type2, ... */ + unsigned ivarCount; + NSString *n, *t; + NSString **ivarNames = NULL; + NSString **ivarTypes = NULL; + Class clazz; + + /* determine number of args */ + + va_start(va, _name1); + for (n = _name1, t = va_arg(va, NSString *), ivarCount = 0; + (n != nil && t != nil); + n = va_arg(va, NSString *), t = va_arg(va, NSString *)) + ivarCount++; va_end(va); - return [self subclass:_className ivarsList:ivars]; + /* collect args */ + + if (ivarCount > 0) { + ivarNames = calloc(ivarCount, sizeof(NSString *)); + ivarTypes = calloc(ivarCount, sizeof(NSString *)); + va_start(va, _name1); + for (n = _name1, t = va_arg(va, NSString *), ivarCount = 0; + (n != nil && t != nil); + n = va_arg(va, NSString *), t = va_arg(va, NSString *)) { + ivarNames[ivarCount] = n; + ivarTypes[ivarCount] = t; + ivarCount++; + } + va_end(va); } -#endif + + /* call primary method */ + + clazz = [self subclass:_className + ivarNames:ivarNames ivarTypes:ivarTypes ivarCount:ivarCount]; + + if (ivarNames != NULL) free(ivarNames); + if (ivarTypes != NULL) free(ivarTypes); + return clazz; } /* instance variables */ @@ -600,9 +677,10 @@ fillMethodListWithSpecs(MethodList_t methods, SEL _selector, va_list *va) } #if !LIB_FOUNDATION_LIBRARY - names[i] = [NSString stringWithCString:ivarName]; + names[i] = [NSString stringWithCString:(char *)ivarName]; #else - names[i] = [NSString stringWithCStringNoCopy:ivarName freeWhenDone:NO]; + names[i] = [NSString stringWithCStringNoCopy:(char *)ivarName + freeWhenDone:NO]; #endif }