summaryrefslogtreecommitdiff
path: root/Objective-C
diff options
context:
space:
mode:
Diffstat (limited to 'Objective-C')
-rw-r--r--Objective-C/GNUmakefile12
-rw-r--r--Objective-C/libobjcl.h62
-rw-r--r--Objective-C/libobjcl.m295
3 files changed, 369 insertions, 0 deletions
diff --git a/Objective-C/GNUmakefile b/Objective-C/GNUmakefile
new file mode 100644
index 0000000..231a78b
--- /dev/null
+++ b/Objective-C/GNUmakefile
@@ -0,0 +1,12 @@
+include $(GNUSTEP_MAKEFILES)/common.make
+
+include ../version.make
+
+LIBRARY_NAME = libobjcl
+
+RPM_DISABLE_RELOCATABLE = YES
+ADDITIONAL_OBJCFLAGS = -Wall -g -DVERSION=\"$(VERSION)\"
+libobjcl_OBJC_FILES = libobjcl.m
+LIBRARIES_DEPEND_UPON = $(FND_LIBS) $(GUI_LIBS) $(OBJC_LIBS) $(SYSTEM_LIBS) $(CONFIG_SYSTEM_LIBS)
+
+include $(GNUSTEP_MAKEFILES)/library.make
diff --git a/Objective-C/libobjcl.h b/Objective-C/libobjcl.h
new file mode 100644
index 0000000..4d6d092
--- /dev/null
+++ b/Objective-C/libobjcl.h
@@ -0,0 +1,62 @@
+/* -*- mode: objc; coding: utf-8 -*- */
+
+#import "Foundation/Foundation.h"
+#include <objc/objc-api.h>
+
+typedef struct objcl_object
+{
+ char* type;
+
+ union
+ {
+ id id_val;
+ Class class_val;
+ NSException *exc_val;
+ SEL sel_val;
+ char char_val;
+ short short_val;
+ int int_val;
+ long long_val;
+ long long long_long_val;
+ float float_val;
+ double double_val;
+ BOOL bool_val;
+ char *charptr_val;
+ void *ptr_val;
+ } data;
+} *OBJCL_OBJ_DATA;
+
+
+#define EXCEPTION_TYPESPEC "ERROR"
+
+
+void
+objcl_initialise_runtime (void);
+
+void
+objcl_shutdown_runtime (void);
+
+void *
+objcl_invoke_instance_method (OBJCL_OBJ_DATA receiver,
+ const char *method_name,
+ int argc,
+ ...);
+
+void *
+objcl_invoke_class_method (OBJCL_OBJ_DATA class,
+ const char *method_name,
+ int argc,
+ ...);
+
+void *
+objcl_find_class (const char *class_name);
+
+/* Return a null-terminated list of type information strings.
+ The first entry describes the type of the method's return value. */
+char **
+objcl_query_arglist_info (void *receiver,
+ const char *method_name);
+
+
+const char *
+objcl_class_name (OBJCL_OBJ_DATA class);
diff --git a/Objective-C/libobjcl.m b/Objective-C/libobjcl.m
new file mode 100644
index 0000000..41d165c
--- /dev/null
+++ b/Objective-C/libobjcl.m
@@ -0,0 +1,295 @@
+/* -*- mode: objc; coding: utf-8 -*- */
+
+#import "libobjcl.h"
+#import "Foundation/Foundation.h"
+#include <stdarg.h>
+#include <objc/objc-api.h>
+
+
+static NSAutoreleasePool *objcl_autorelease_pool = NULL;
+
+
+void
+objcl_initialise_runtime ()
+{
+ objcl_autorelease_pool = [[NSAutoreleasePool alloc] init];
+}
+
+
+void
+objcl_shutdown_runtime ()
+{
+ [objcl_autorelease_pool release];
+}
+
+
+#define _OBJCL_ARG_CASE(typespec, field_name) \
+ case typespec: \
+ memmove (buffer, &argdata->data.field_name##_val, \
+ objc_sizeof_type (argdata->type)); \
+ break;
+
+
+static void
+_objcl_get_arg_pointer (void *buffer, OBJCL_OBJ_DATA argdata)
+{
+ switch (argdata->type[0])
+ {
+ _OBJCL_ARG_CASE(_C_ID, id);
+ _OBJCL_ARG_CASE(_C_CLASS, id);
+ _OBJCL_ARG_CASE(_C_SEL, sel);
+ _OBJCL_ARG_CASE(_C_CHR, char);
+ _OBJCL_ARG_CASE(_C_UCHR, char);
+ _OBJCL_ARG_CASE(_C_SHT, short);
+ _OBJCL_ARG_CASE(_C_USHT, short);
+ _OBJCL_ARG_CASE(_C_INT, int);
+ _OBJCL_ARG_CASE(_C_UINT, int);
+ _OBJCL_ARG_CASE(_C_LNG, long);
+ _OBJCL_ARG_CASE(_C_ULNG, long);
+ _OBJCL_ARG_CASE(_C_LNG_LNG, long_long);
+ _OBJCL_ARG_CASE(_C_ULNG_LNG, long_long);
+ _OBJCL_ARG_CASE(_C_FLT, float);
+ _OBJCL_ARG_CASE(_C_DBL, double);
+ _OBJCL_ARG_CASE(_C_BOOL, bool);
+ _OBJCL_ARG_CASE(_C_PTR, ptr);
+ _OBJCL_ARG_CASE(_C_CHARPTR, charptr);
+/*
+ _OBJCL_ARG_CASE(_C_VOID, void);
+ _OBJCL_ARG_CASE(_C_BFLD, bitfield);
+ _OBJCL_ARG_CASE(_C_ATOM, atom);
+ _OBJCL_ARG_CASE(_C_ARY_B, );
+ _OBJCL_ARG_CASE(_C_UNION_B, );
+ _OBJCL_ARG_CASE(_C_STRUCT_B, );
+ _OBJCL_ARG_CASE(_C_VECTOR, );
+ _OBJCL_ARG_CASE(_C_COMPLEX, );
+*/
+ case _C_UNDEF:
+ default:
+ NSLog (@"Dammit. What the heck is `%s' supposed to mean?",
+ argdata->type);
+ break;
+ }
+}
+
+
+static void
+_objcl_invoke_method (id self_,
+ OBJCL_OBJ_DATA result,
+ NSMethodSignature *signature,
+ SEL selector,
+ int argc,
+ va_list arglist)
+{
+ int i;
+ NSInvocation *invocation;
+ void *result_ptr = NULL;
+ const char *type = [signature methodReturnType];
+
+ result->type = malloc (strlen (type) + 1);
+ strcpy (result->type, type);
+
+ if (signature == NULL)
+ {
+ [[NSException exceptionWithName: @"MLKNoSignatureFoundException"
+ reason: @"No signature found"
+ userInfo: NULL] raise];
+ }
+
+
+ switch (type[0])
+ {
+ case _C_ID: result_ptr = &(result->data.id_val); break;
+ case _C_CLASS: result_ptr = &result->data.id_val; break;
+ case _C_SEL: result_ptr = &result->data.sel_val; break;
+ case _C_CHR: result_ptr = &result->data.char_val; break;
+ case _C_UCHR: result_ptr = &result->data.char_val; break;
+ case _C_SHT: result_ptr = &result->data.short_val; break;
+ case _C_USHT: result_ptr = &result->data.short_val; break;
+ case _C_INT: result_ptr = &result->data.int_val; break;
+ case _C_UINT: result_ptr = &result->data.int_val; break;
+ case _C_LNG: result_ptr = &result->data.long_val; break;
+ case _C_ULNG: result_ptr = &result->data.long_val; break;
+ case _C_LNG_LNG: result_ptr = &result->data.long_long_val; break;
+ case _C_ULNG_LNG: result_ptr = &result->data.long_long_val; break;
+ case _C_FLT: result_ptr = &result->data.float_val; break;
+ case _C_DBL: result_ptr = &result->data.double_val; break;
+ case _C_BOOL: result_ptr = &result->data.bool_val; break;
+ case _C_PTR: result_ptr = &result->data.ptr_val; break;
+ case _C_CHARPTR: result_ptr = &result->data.charptr_val; break;
+ /*
+ case _C_BFLD: result_ptr = &result->data._val; break;
+ case _C_VOID: result_ptr = &result->data._val; break;
+ case _C_UNDEF: result_ptr = &result->data._val; break;
+ case _C_ATOM: result_ptr = &result->data._val; break;
+ case _C_ARY_B: result_ptr = &result->data._val; break;
+ case _C_ARY_E: result_ptr = &result->data._val; break;
+ case _C_UNION_B: result_ptr = &result->data._val; break;
+ case _C_UNION_E: result_ptr = &result->data._val; break;
+ case _C_STRUCT_B: result_ptr = &result->data._val; break;
+ case _C_STRUCT_E: result_ptr = &result->data._val; break;
+ case _C_VECTOR: result_ptr = &result->data._val; break;
+ case _C_COMPLEX: result_ptr = &result->data._val; break;
+ */
+ }
+
+ invocation = [NSInvocation invocationWithMethodSignature: signature];
+ [invocation setTarget: self_];
+ [invocation setSelector: selector];
+
+ for (i = 0; i < argc; i++)
+ {
+ const char* type = [signature getArgumentTypeAtIndex: (i + 2)];
+ void *buffer = malloc (objc_sizeof_type (type));
+ OBJCL_OBJ_DATA arg = va_arg (arglist, OBJCL_OBJ_DATA);
+ _objcl_get_arg_pointer (buffer, arg);
+
+ if (type[0] == '#')
+ NSLog (@"Argument %d: %@ (type %s)", i, buffer, type);
+ else
+ NSLog (@"Argument %d: type %s.", i, type);
+
+ [invocation setArgument: buffer
+ atIndex: (i + 2)];
+
+ free (buffer);
+ }
+
+ [invocation retainArguments];
+ NSLog (@"Invoking %@ on %@.", invocation, self_);
+ [invocation invoke];
+ NSLog (@"Fetching return value.");
+ [invocation getReturnValue: result_ptr];
+ if (result->type[0] == '#')
+ NSLog (@"Returning: %@", result->data.id_val);
+}
+
+
+void *
+objcl_invoke_instance_method (OBJCL_OBJ_DATA receiver,
+ const char *method_name,
+ int argc,
+ ...)
+{
+ va_list arglist;
+ id self_ = NULL;
+ SEL selector;
+ NSMethodSignature *signature;
+ OBJCL_OBJ_DATA result = malloc (sizeof (struct objcl_object));
+
+ NS_DURING
+ {
+ /* fprintf (stderr, "! ---------> %s <--------\n", receiver->type); */
+ assert (receiver->type[0] == '#'
+ || receiver->type[0] == '@'
+ || receiver->type[0] == 'E');
+ switch (receiver->type[0])
+ {
+ case '#': self_ = receiver->data.class_val;
+ case '@': self_ = receiver->data.id_val;
+ case 'E': self_ = receiver->data.exc_val;
+ }
+
+ selector = NSSelectorFromString ([NSString
+ stringWithUTF8String: method_name]);
+
+ signature = [self_ instanceMethodSignatureForSelector: selector];
+
+ va_start (arglist, argc);
+ _objcl_invoke_method (self_, result, signature, selector, argc, arglist);
+ va_end (arglist);
+ }
+ NS_HANDLER
+ {
+ result->type = malloc (strlen (EXCEPTION_TYPESPEC) + 1);
+ strcpy (result->type, EXCEPTION_TYPESPEC);
+ result->data.exc_val = localException;
+ NS_VALUERETURN (result, void *);
+ }
+ NS_ENDHANDLER
+
+ return result;
+}
+
+
+void *
+objcl_invoke_class_method (OBJCL_OBJ_DATA class,
+ const char *method_name,
+ int argc,
+ ...)
+{
+ va_list arglist;
+ id self_ = NULL;
+ SEL selector;
+ NSMethodSignature *signature;
+ OBJCL_OBJ_DATA result = malloc (sizeof (struct objcl_object));
+
+ NS_DURING
+ {
+ /* fprintf (stderr, "? ---------> %s <--------\n", class->type); */
+ assert (class->type[0] == '#'
+ || class->type[0] == '@'
+ || class->type[0] == 'E');
+ switch (class->type[0])
+ {
+ case '#': self_ = class->data.class_val;
+ case '@': self_ = class->data.id_val;
+ case 'E': self_ = class->data.exc_val;
+ }
+
+ selector = NSSelectorFromString ([NSString
+ stringWithUTF8String: method_name]);
+
+ signature = [self_ methodSignatureForSelector: selector];
+
+ va_start (arglist, argc);
+ _objcl_invoke_method (self_, result, signature, selector, argc, arglist);
+ va_end (arglist);
+ }
+ NS_HANDLER
+ {
+ result->type = malloc (strlen (EXCEPTION_TYPESPEC) + 1);
+ strcpy (result->type, EXCEPTION_TYPESPEC);
+ result->data.exc_val = localException;
+ NS_VALUERETURN (result, void *);
+ }
+ NS_ENDHANDLER
+
+ return result;
+}
+
+
+void *
+objcl_find_class (const char *class_name)
+{
+ Class class =
+ NSClassFromString ([NSString stringWithUTF8String: class_name]);
+ OBJCL_OBJ_DATA result = malloc (sizeof (struct objcl_object));
+ const char *const typespec = "#8@0:4";
+
+ result->type = malloc (strlen (typespec) + 1);
+ strcpy (result->type, typespec);
+ result->data.class_val = class;
+
+ return result;
+}
+
+
+const char *
+objcl_class_name (OBJCL_OBJ_DATA class)
+{
+ Class cls = NULL;
+
+ /* fprintf (stderr, "---------> %s <--------\n", class->type); */
+ fflush (stderr);
+ assert (class->type[0] == '#'
+ || class->type[0] == '@'
+ || class->type[0] == 'E');
+ switch (class->type[0])
+ {
+ case '#': cls = class->data.class_val;
+ case '@': cls = class->data.id_val;
+ case 'E': cls = (id) class->data.exc_val;
+ }
+
+ return class_get_class_name (cls);
+}