@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;
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();
}
}
+ (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 ;-) */
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);
/* 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;
/* adjust current size */
currentSize = ivarOffset + typeLen;
}
- va_end(va);
}
-
+
// TODO: move the following to a subclass method
/* determine root class */
}
#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;
+ }
+ va_end(va);
+
+ 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 */