]> err.no Git - sope/blobdiff - sope-core/NGExtensions/NGObjCRuntime.m
Drop apache 1 build-dependency
[sope] / sope-core / NGExtensions / NGObjCRuntime.m
index 3003fb608b760db9f36f0fd37c81331d1772a98f..b8aa29d72649caf95c6ff8e70b17a9c2e4fe2094 100644 (file)
@@ -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
   }