summaryrefslogtreecommitdiff
path: root/Objective-C
diff options
context:
space:
mode:
Diffstat (limited to 'Objective-C')
-rw-r--r--Objective-C/libobjcl.h23
-rw-r--r--Objective-C/libobjcl.m141
2 files changed, 164 insertions, 0 deletions
diff --git a/Objective-C/libobjcl.h b/Objective-C/libobjcl.h
index afe9f56..56654fc 100644
--- a/Objective-C/libobjcl.h
+++ b/Objective-C/libobjcl.h
@@ -45,6 +45,7 @@ typedef struct objc_ivar *IVAR_T;
#ifdef HAVE_SYS_SEM_H
#include <sys/sem.h>
+#ifndef __APPLE__
/* According to the Single Unix Specification, Version 3, the semun
union type must be defined by the application writer as follows: */
union semun
@@ -54,6 +55,7 @@ union semun
unsigned short *array; /* Array for GETALL, SETALL */
};
#endif
+#endif
extern NSException *objcl_oom_exception;
extern id objcl_current_exception;
@@ -174,3 +176,24 @@ objcl_release_lock (void *lock);
void
objcl_initialise_lock (void **lock);
+
+Class
+objcl_create_class (const char *class_name,
+ const char *superclass,
+ int protocol_number,
+ const char *protocol_names[],
+ int ivar_number,
+ const char *ivar_names[],
+ const char *ivar_typespecs[]);
+
+void
+objcl_add_method (Class class,
+ SEL method_name,
+ IMP callback,
+ int argc,
+ const char *return_typespec,
+ const char *arg_typespecs[],
+ const char *signature);
+
+void
+objcl_finalise_class (Class class);
diff --git a/Objective-C/libobjcl.m b/Objective-C/libobjcl.m
index 993ebed..c75ebea 100644
--- a/Objective-C/libobjcl.m
+++ b/Objective-C/libobjcl.m
@@ -19,6 +19,7 @@
#import "libobjcl.h"
#import "PyObjC/libffi_support.h"
+#import "JIGS/ObjcRuntimeUtilities.h"
#import <Foundation/Foundation.h>
#include <stdarg.h>
@@ -49,12 +50,16 @@ NSException *objcl_oom_exception = NULL;
id objcl_current_exception = NULL;
void *objcl_current_exception_lock = NULL;
+static NSMutableDictionary *method_lists = NULL;
+static NSMutableDictionary *method_list_lengths = NULL;
+
void
objcl_initialise_runtime (void)
{
if (!objcl_autorelease_pool)
objcl_autorelease_pool = [[NSAutoreleasePool alloc] init];
+
if (!objcl_oom_exception)
{
objcl_oom_exception = [NSException exceptionWithName: @"MLKOutOfMemoryException"
@@ -68,6 +73,12 @@ objcl_initialise_runtime (void)
#endif
objcl_initialise_lock (&objcl_current_exception_lock);
+
+ if (!method_lists)
+ method_lists = [[NSMutableDictionary alloc] init];
+
+ if (!method_list_lengths)
+ method_list_lengths = [[NSMutableDictionary alloc] init];
}
@@ -625,3 +636,133 @@ objcl_release_lock (void *lock)
#warning "I do not know how to do locking on this platform."
#endif
}
+
+
+Class
+objcl_create_class (const char *class_name,
+ const char *superclass,
+ int protocol_number,
+ const char *protocol_names[],
+ int ivar_number,
+ const char *ivar_names[],
+ const char *ivar_typespecs[])
+{
+#ifdef __NEXT_RUNTIME__
+ int i;
+ Class class;
+
+ objc_allocateClassPair (objcl_find_class (superclass), class_name, 0);
+ class = objcl_find_class (class_name);
+
+ for (i = 0; i < ivar_number; i++)
+ preclass_addIvar (class,
+ ivar_names[i],
+ objcl_sizeof_type (ivar_typespecs[i]),
+ objcl_alignof_type (ivar_typespecs[i]),
+ ivar_typespecs[i]);
+
+ for (i = 0; i < protocol_number; i++)
+ preclass_addProtocol (class,
+#ifdef __OBJC2__
+ objc_getProtocol ((char *) protocol_names[i])
+#else
+ objc_getClass (protocol_names[i])
+#endif
+ );
+
+ return class;
+#else
+ ffi_cif cif;
+ ffi_status status;
+ ffi_type *arg_types[3 + ivar_number*2];
+ void *argv[3 + ivar_number*2];
+ int i;
+ BOOL return_value;
+
+ arg_types[0] = &ffi_type_pointer;
+ arg_types[1] = &ffi_type_pointer;
+ arg_types[2] = &ffi_type_sint;
+ for (i = 0; i < ivar_number*2; i++)
+ arg_types[3 + i] = &ffi_type_pointer;
+
+ argv[0] = &class_name;
+ argv[1] = &superclass;
+ argv[2] = &ivar_number;
+ for (i = 0; i < ivar_number; i++)
+ {
+ argv[3 + 2*i] = (void *) &ivar_names[2*i];
+ argv[3 + 2*i + 1] = (void *) &ivar_names[2*i + 1];
+ }
+
+ status = ffi_prep_cif (&cif, FFI_DEFAULT_ABI, ivar_number + 3, &ffi_type_uchar, arg_types);
+ if (status != FFI_OK)
+ {
+ [[NSException exceptionWithName: @"MLKInvalidFFITypeException"
+ reason: @"FFI type is invalid (this is probably a bug)."
+ userInfo: nil] raise];
+ }
+
+ ffi_call (&cif, FFI_FN (ObjcUtilities_new_class), &return_value, argv);
+
+ NSString *ns_class_name = [NSString stringWithUTF8String: class_name];
+ [method_lists setObject:
+ [NSValue valueWithPointer: ObjcUtilities_alloc_method_list]
+ forKey: ns_class_name];
+ [method_list_lengths setObject: [NSNumber numberWithInt: 0]
+ forKey: ns_class_name];
+
+ return objcl_find_class (class_name);
+#endif
+}
+
+
+void
+objcl_add_method (Class class,
+ SEL method_name,
+ IMP callback,
+ int argc,
+ const char *return_typespec,
+ const char *arg_typespecs[],
+ const char *signature)
+{
+ IMP imp;
+
+ imp = objcl_create_imp (callback, argc, return_typespec, arg_typespecs);
+
+#ifdef __NEXT_RUNTIME__
+ preclass_addMethod (class, method_name, imp, signature);
+#else
+ NSString *class_name = [NSString stringWithUTF8String: objcl_class_name (class)];
+ MethodList *method_list = [[method_lists objectForKey: class_name] pointerValue];
+ int index = [[method_list_lengths objectForKey: class_name] intValue];
+
+ ObjcUtilities_insert_method_in_list
+ (method_list,
+ index,
+ objcl_selector_name (method_name),
+ ObjcUtilities_build_runtime_Objc_signature (signature),
+ imp);
+
+ [method_list_lengths setObject: [NSNumber numberWithInt: index]
+ forKey: class_name];
+#endif
+}
+
+
+void
+objcl_finalise_class (Class class)
+{
+#ifdef __NEXT_RUNTIME__
+ /* FIXME: Should we do this if class is a metaclass? */
+ objc_registerClassPair (class);
+#else
+ NSString *class_name = [NSString stringWithUTF8String:
+ objcl_class_name (class)];
+ ObjcUtilities_register_method_list
+ (class, [[method_lists objectForKey: class_name]
+ pointerValue]);
+
+ [method_lists removeObjectForKey: class_name];
+ [method_list_lengths removeObjectForKey: class_name];
+#endif
+}