summaryrefslogtreecommitdiff
path: root/Objective-C/PyObjC
diff options
context:
space:
mode:
Diffstat (limited to 'Objective-C/PyObjC')
-rw-r--r--Objective-C/PyObjC/libffi_support.h21
-rw-r--r--Objective-C/PyObjC/libffi_support.m401
-rw-r--r--Objective-C/PyObjC/objc-runtime-apple.h137
-rw-r--r--Objective-C/PyObjC/objc-runtime-apple.m159
-rw-r--r--Objective-C/PyObjC/objc-runtime-gnu.h174
-rw-r--r--Objective-C/PyObjC/objc-runtime-gnu.m217
-rw-r--r--Objective-C/PyObjC/objc_support.h46
-rw-r--r--Objective-C/PyObjC/objc_support.m505
-rw-r--r--Objective-C/PyObjC/pyobjc.h46
9 files changed, 1706 insertions, 0 deletions
diff --git a/Objective-C/PyObjC/libffi_support.h b/Objective-C/PyObjC/libffi_support.h
new file mode 100644
index 0000000..ca04c6b
--- /dev/null
+++ b/Objective-C/PyObjC/libffi_support.h
@@ -0,0 +1,21 @@
+#ifndef PyObjC_FFI_SUPPORT_H
+#define PyObjC_FFI_SUPPORT_H
+
+#ifdef USE_LIBFFI
+#ifdef HAVE_FFI_H
+#include <ffi.h>
+#elif HAVE_FFI_FFI_H
+#include <ffi/ffi.h>
+#else
+/* We are using our own build of libffi. */
+#include <ffi.h>
+#endif
+#endif
+
+ffi_type*
+objcl_pyobjc_signature_to_ffi_return_type (const char* argtype);
+
+ffi_type*
+objcl_pyobjc_arg_signature_to_ffi_type (const char* argtype);
+
+#endif /* PyObjC_FFI_SUPPORT_H */
diff --git a/Objective-C/PyObjC/libffi_support.m b/Objective-C/PyObjC/libffi_support.m
new file mode 100644
index 0000000..4bc1137
--- /dev/null
+++ b/Objective-C/PyObjC/libffi_support.m
@@ -0,0 +1,401 @@
+/*
+ * Support for libffi (http://sources.redhat.com/libffi)
+ *
+ * libffi is a library that makes it possible to dynamicly create calls
+ * to C functions (without knowing the signature at compile-time). It also
+ * provides a way to create closures, that is dynamicly create functions with
+ * a runtime specified interface.
+ *
+ * This file contains functions to dynamicly call objc_msgSendSuper and to
+ * dynamicly create IMPs for use in Objective-C method dispatch tables. The
+ * file 'register.m' contains compile-time generated equivalents of these.
+ */
+#include "pyobjc.h"
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSHost.h>
+
+#ifdef MACOSX
+/*
+ * Define SMALL_STRUCT_LIMIT as the largest struct that will be returned
+ * in registers instead of with a hidden pointer argument.
+ */
+
+#if defined(__ppc__)
+
+# define SMALL_STRUCT_LIMIT 4
+
+#elif defined(__i386__)
+
+# define SMALL_STRUCT_LIMIT 8
+
+#else
+
+# error "Unsupported MACOSX platform"
+
+#endif
+
+#endif /* MACOSX */
+
+
+
+#if 0 /* Usefull during debugging, only used in the debugger */
+static void describe_ffitype(ffi_type* type)
+{
+ switch (type->type) {
+ case FFI_TYPE_VOID: printf("%s", "void"); break;
+ case FFI_TYPE_INT: printf("%s", "int"); break;
+ case FFI_TYPE_FLOAT: printf("%s", "float"); break;
+ case FFI_TYPE_DOUBLE: printf("%s", "double"); break;
+ case FFI_TYPE_UINT8: printf("%s", "uint8"); break;
+ case FFI_TYPE_SINT8: printf("%s", "sint8"); break;
+ case FFI_TYPE_UINT16: printf("%s", "uint16"); break;
+ case FFI_TYPE_SINT16: printf("%s", "sint16"); break;
+ case FFI_TYPE_UINT32: printf("%s", "uint32"); break;
+ case FFI_TYPE_SINT32: printf("%s", "sint32"); break;
+ case FFI_TYPE_UINT64: printf("%s", "uint64"); break;
+ case FFI_TYPE_SINT64: printf("%s", "sint64"); break;
+ case FFI_TYPE_POINTER: printf("%s", "*"); break;
+ case FFI_TYPE_STRUCT: {
+ ffi_type** elems = type->elements;
+
+ printf("%s", "struct { ");
+ if (elems) {
+ while (*elems) {
+ describe_ffitype(*(elems++));
+ printf("%s", "; ");
+ }
+ }
+ printf("%s", "}");
+ }
+ break;
+
+ default:
+ // Don't abort, this is called from the debugger
+ printf("?(%d)", type->type);
+ }
+}
+
+static void describe_cif(ffi_cif* cif)
+{
+ size_t i;
+ printf("<ffi_cif abi=%d nargs=%d bytes=%d flags=%#x args=[",
+ cif->abi, cif->nargs, cif->bytes, cif->flags);
+ for (i = 0; i < cif->nargs; i++) {
+ describe_ffitype(cif->arg_types[i]);
+ printf("%s", ", ");
+ }
+ printf("%s", "] rettype=");
+ describe_ffitype(cif->rtype);
+ printf("%s", ">\n");
+}
+
+#endif
+
+
+static Py_ssize_t
+num_struct_fields(const char* argtype)
+{
+ Py_ssize_t res = 0;
+
+ if (*argtype != _C_STRUCT_B) return -1;
+ while (*argtype != _C_STRUCT_E && *argtype != '=') argtype++;
+ if (*argtype == _C_STRUCT_E) return 0;
+
+ argtype++;
+ while (*argtype != _C_STRUCT_E) {
+ argtype = PyObjCRT_SkipTypeSpec(argtype);
+ if (argtype == NULL) return -1;
+ res ++;
+ }
+ return res;
+}
+
+
+static void
+free_type(void *obj)
+{
+ PyMem_Free(((ffi_type*)obj)->elements);
+ PyMem_Free(obj);
+}
+
+static ffi_type* signature_to_ffi_type(const char* argtype);
+
+static ffi_type*
+array_to_ffi_type(const char* argtype)
+{
+ static NSMutableDictionary* array_types = nil;
+ NSValue *v;
+ ffi_type* type;
+ Py_ssize_t field_count;
+ Py_ssize_t i;
+ const NSString* key = [NSString stringWithUTF8String: argtype];
+
+ if (array_types == NULL || array_types == nil) {
+ array_types = [NSMutableDictionary dictionaryWithCapacity: 100];
+ if (array_types == NULL || array_types == nil) return NULL;
+ }
+
+ v = [array_types objectForKey: key];
+ if (v != nil) {
+ return (ffi_type*)[v pointerValue];
+ }
+
+ /* We don't have a type description yet, dynamicly
+ * create it.
+ */
+ field_count = atoi(argtype+1);
+
+ type = PyMem_Malloc(sizeof(*type));
+ if (type == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ type->size = PyObjCRT_SizeOfType(argtype);
+ type->alignment = PyObjCRT_AlignOfType(argtype);
+
+ /* Libffi doesn't really know about arrays as part of larger
+ * data-structres (e.g. struct foo { int field[3]; };). We fake it
+ * by treating the nested array as a struct. This seems to work
+ * fine on MacOS X.
+ */
+ type->type = FFI_TYPE_STRUCT;
+ type->elements = PyMem_Malloc((1+field_count) * sizeof(ffi_type*));
+ if (type->elements == NULL) {
+ PyMem_Free(type);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ while (isdigit(*++argtype));
+ type->elements[0] = signature_to_ffi_type(argtype);
+ for (i = 1; i < field_count; i++) {
+ type->elements[i] = type->elements[0];
+ }
+ type->elements[field_count] = 0;
+
+ v = [NSValue valueWithPointer: type];
+ if (v == NULL || v == nil) {
+ free_type(type);
+ return NULL;
+ }
+
+ NS_DURING
+ {
+ [array_types setObject: v forKey: key];
+ }
+ NS_HANDLER
+ {
+ NS_VALUERETURN (NULL, ffi_type*);
+ }
+ NS_ENDHANDLER
+
+ return type;
+}
+
+static ffi_type*
+struct_to_ffi_type(const char* argtype)
+{
+ static NSMutableDictionary* struct_types = nil;
+ NSValue* v;
+ ffi_type* type;
+ Py_ssize_t field_count;
+ const char* curtype;
+ const NSString* key = [NSString stringWithUTF8String: argtype];
+
+ if (struct_types == NULL || struct_types == nil) {
+ struct_types = [NSMutableDictionary dictionaryWithCapacity: 100];
+ if (struct_types == NULL || struct_types == nil) return NULL;
+ }
+
+ v = [struct_types objectForKey: key];
+ if (v != nil) {
+ return (ffi_type*)[v pointerValue];
+ }
+
+ /* We don't have a type description yet, dynamicly
+ * create it.
+ */
+ field_count = num_struct_fields(argtype);
+ if (field_count == -1) {
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCExc_InternalError"
+ reason: [NSString stringWithFormat: @"Cannot determine layout of %s", argtype]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCExc_InternalError: Cannot determine layout of %s", argtype);
+#endif
+ return NULL;
+ }
+
+ type = PyMem_Malloc(sizeof(*type));
+ if (type == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ type->size = PyObjCRT_SizeOfType(argtype);
+ type->alignment = PyObjCRT_AlignOfType(argtype);
+ type->type = FFI_TYPE_STRUCT;
+ type->elements = PyMem_Malloc((1+field_count) * sizeof(ffi_type*));
+ if (type->elements == NULL) {
+ PyMem_Free(type);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ field_count = 0;
+ curtype = argtype+1;
+ while (*curtype != _C_STRUCT_E && *curtype != '=') curtype++;
+ if (*curtype == '=') {
+ curtype ++;
+ while (*curtype != _C_STRUCT_E) {
+ type->elements[field_count] =
+ signature_to_ffi_type(curtype);
+ if (type->elements[field_count] == NULL) {
+ PyMem_Free(type->elements);
+ return NULL;
+ }
+ field_count++;
+ curtype = PyObjCRT_SkipTypeSpec(curtype);
+ if (curtype == NULL) {
+ PyMem_Free(type->elements);
+ return NULL;
+ }
+ }
+ }
+ type->elements[field_count] = NULL;
+
+ v = [NSValue valueWithPointer: type];
+ if (v == NULL || v == nil) {
+ free_type(type);
+ return NULL;
+ }
+
+ NS_DURING
+ {
+ [struct_types setObject: v forKey: key];
+ }
+ NS_HANDLER
+ {
+ NS_VALUERETURN (NULL, ffi_type*);
+ }
+ NS_ENDHANDLER
+
+ return type;
+}
+
+ffi_type*
+objcl_pyobjc_signature_to_ffi_return_type(const char* argtype)
+{
+ switch (*argtype) {
+ case _C_CHR: case _C_SHT:
+ return &ffi_type_sint;
+ case _C_UCHR: case _C_USHT:
+ return &ffi_type_uint;
+#ifdef _C_BOOL
+ case _C_BOOL: return &ffi_type_sint;
+#endif
+ default:
+ return signature_to_ffi_type(argtype);
+ }
+}
+
+
+static ffi_type*
+signature_to_ffi_type(const char* argtype)
+{
+ switch (*argtype) {
+ case _C_VOID: return &ffi_type_void;
+ case _C_ID: return &ffi_type_pointer;
+ case _C_CLASS: return &ffi_type_pointer;
+ case _C_SEL: return &ffi_type_pointer;
+ case _C_CHR: return &ffi_type_schar;
+#ifdef _C_BOOL
+ case _C_BOOL: return &ffi_type_sint;
+#endif
+ case _C_UCHR: return &ffi_type_uchar;
+ case _C_SHT: return &ffi_type_sshort;
+ case _C_USHT: return &ffi_type_ushort;
+ case _C_INT: return &ffi_type_sint;
+ case _C_UINT: return &ffi_type_uint;
+
+ /* The next to defintions are incorrect, but the correct definitions
+ * don't work (e.g. give testsuite failures). We should be fine
+ * as long as sizeof(long) == sizeof(int)
+ */
+ case _C_LNG: return &ffi_type_sint; /* ffi_type_slong */
+ case _C_ULNG: return &ffi_type_uint; /* ffi_type_ulong */
+ case _C_LNGLNG: return &ffi_type_sint64;
+ case _C_ULNGLNG: return &ffi_type_uint64;
+ case _C_FLT: return &ffi_type_float;
+ case _C_DBL: return &ffi_type_double;
+ case _C_CHARPTR: return &ffi_type_pointer;
+ case _C_PTR: return &ffi_type_pointer;
+ case _C_ARY_B:
+ return array_to_ffi_type(argtype);
+ case _C_IN: case _C_OUT: case _C_INOUT: case _C_CONST:
+ return signature_to_ffi_type(argtype+1);
+ case _C_STRUCT_B:
+ return struct_to_ffi_type(argtype);
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyExc_NotImplementedError"
+ reason: [NSString stringWithFormat: @"Type '%c' not supported", *argtype]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyExc_NotImplementedError: Type '%#x' not supported", *argtype);
+#endif
+ return NULL;
+ }
+}
+
+/*
+ * arg_signature_to_ffi_type: Make the ffi_type for the call to the method IMP,
+ * on MacOS X this is the same as the normal signature_to_ffi_type, but on
+ * Linux/GNUstep we need a slightly different function.
+ */
+#ifdef MACOSX
+
+#ifdef __ppc__
+ffi_type*
+objcl_pyobjc_arg_signature_to_ffi_type(const char* argtype)
+{
+ return signature_to_ffi_type (argtype);
+}
+
+#else
+ffi_type*
+objcl_pyobjc_arg_signature_to_ffi_type(const char* argtype)
+{
+ /* NOTE: This is the minimal change to pass the unittests, it is not
+ * based on analysis of the calling conventions.
+ */
+ switch (*argtype) {
+ case _C_CHR: return &ffi_type_sint;
+ case _C_UCHR: return &ffi_type_uint;
+ case _C_SHT: return &ffi_type_sint;
+ case _C_USHT: return &ffi_type_uint;
+ default: return signature_to_ffi_type(argtype);
+ }
+}
+#endif
+
+#else /* GNUstep */
+
+ffi_type*
+objcl_pyobjc_arg_signature_to_ffi_type(const char* argtype)
+{
+ /* NOTE: This is the minimal change to pass the unittests, it is not
+ * based on analysis of the calling conventions.
+ */
+ switch (*argtype) {
+ case _C_CHR: return &ffi_type_sint;
+ case _C_UCHR: return &ffi_type_uint;
+ case _C_SHT: return &ffi_type_sint;
+ case _C_USHT: return &ffi_type_uint;
+ default: return signature_to_ffi_type(argtype);
+ }
+}
+
+#endif /* GNUstep */
diff --git a/Objective-C/PyObjC/objc-runtime-apple.h b/Objective-C/PyObjC/objc-runtime-apple.h
new file mode 100644
index 0000000..8d050a1
--- /dev/null
+++ b/Objective-C/PyObjC/objc-runtime-apple.h
@@ -0,0 +1,137 @@
+/* Copyright (c) 1996,97,98 by Lele Gaifax. All Rights Reserved
+ * Copyright (c) 2003 Ronald Oussoren
+ *
+ * This software may be used and distributed freely for any purpose
+ * provided that this notice is included unchanged on any and all
+ * copies. The author does not warrant or guarantee this software in
+ * any way.
+ *
+ * This file is part of the PyObjC package.
+ *
+ * RCSfile: objc_support.h,v
+ * Revision: 1.16
+ * Date: 1998/08/18 15:35:57
+ *
+ * Created Tue Sep 10 14:11:38 1996.
+ */
+
+#ifndef PyObjC_RUNTIME_APPLE_H
+#define PyObjC_RUNTIME_APPLE_H
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSString.h>
+
+#include <objc/objc-runtime.h>
+#include <objc/Protocol.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+
+static inline int
+PyObjCRT_SameSEL(SEL a, SEL b)
+{
+ return a == b;
+}
+
+static inline const char*
+PyObjCRT_SELName(SEL sel)
+{
+ return sel_getName(sel);
+}
+
+static inline SEL
+PyObjCRT_SELUID(const char* str)
+{
+ return sel_getUid(str);
+}
+
+static inline Class
+PyObjCRT_LookUpClass(const char* name)
+{
+ return objc_lookUpClass(name);
+}
+
+static inline struct objc_method_list *
+PyObjCRT_NextMethodList(Class c, void ** p)
+{
+ return class_nextMethodList(c, p);
+}
+
+static inline void
+PyObjCRT_InitMethod(Method m, SEL name, const char* types, IMP imp)
+{
+ memset(m, 0, sizeof(*m));
+ m->method_name = name;
+ m->method_types = strdup((char*)types);
+ m->method_imp = imp;
+}
+
+static inline void
+PyObjCRT_ClassAddMethodList(Class cls, struct objc_method_list* lst)
+{
+ class_addMethods(cls, lst);
+}
+
+
+extern struct objc_method_list* PyObjCRT_AllocMethodList(ssize_t);
+extern struct objc_protocol_list* PyObjCRT_AllocProtocolList(ssize_t);
+
+typedef Method PyObjCRT_Method_t;
+typedef Ivar PyObjCRT_Ivar_t;
+
+#define GETISA(c) ((c)->isa)
+
+#define RECEIVER(c) ((c).receiver)
+
+#define _C_CONST 'r'
+#define _C_IN 'n'
+#define _C_INOUT 'N'
+#define _C_OUT 'o'
+#define _C_BYCOPY 'O'
+#define _C_ONEWAY 'V'
+#define _C_LNGLNG 'q'
+#define _C_ULNGLNG 'Q'
+#define _C_BOOL 'B' /* (Objective-)C++ 'bool' */
+
+
+/* Return a number that is likely to change when the method list changes,
+ * and is cheap to compute.
+ */
+static inline int
+objc_methodlist_magic(Class cls)
+{
+ int res = 0;
+ int cnt = 0;
+
+ /* This is the documented way of enumerating the method list. It
+ * is slower than the obvious way, but does not explode under
+ * esoteric situations.
+ */
+ void *iterator = NULL;
+ struct objc_method_list *mlist;
+
+ if (cls == NULL) return -1;
+
+ while ( (mlist = class_nextMethodList( cls, &iterator )) != NULL ) {
+ res += mlist->method_count;
+ cnt++;
+ }
+
+ return (cnt << 16) | (res & 0xFFFF);
+}
+
+static inline const char *
+get_selector_encoding (id self, SEL sel)
+{
+ struct objc_method* m = class_getInstanceMethod(self->isa, sel);
+
+ if (!m) {
+ return NULL;
+ } else {
+ return m->method_types;
+ }
+}
+
+#endif /* PyObjC_RUNTIME_APPLE_H */
diff --git a/Objective-C/PyObjC/objc-runtime-apple.m b/Objective-C/PyObjC/objc-runtime-apple.m
new file mode 100644
index 0000000..b2888ac
--- /dev/null
+++ b/Objective-C/PyObjC/objc-runtime-apple.m
@@ -0,0 +1,159 @@
+/* This file is part of the PyObjC package. */
+/*
+ * Support code for the Apple runtime
+ */
+#include "pyobjc.h"
+
+#if defined(APPLE_RUNTIME)
+#include "objc-runtime-apple.h"
+
+int PyObjCRT_SetupClass(
+ Class cls,
+ Class metaCls,
+ const char*name,
+ Class superCls,
+ Class rootCls,
+ ssize_t ivarSize,
+ struct objc_ivar_list* ivarList,
+ struct objc_protocol_list* protocolList
+)
+
+{
+ /* Initialize the structure */
+ memset(cls, 0, sizeof(*cls));
+ memset(metaCls, 0, sizeof(*cls));
+
+ cls->methodLists = NULL;
+ metaCls->methodLists = NULL;
+ cls->isa = metaCls;
+
+ cls->info = CLS_CLASS; // |CLS_METHOD_ARRAY;
+ metaCls->info = CLS_META; // |CLS_METHOD_ARRAY;
+
+ cls->name = strdup(name);
+ if (cls->name == NULL) {
+ return -1;
+ }
+ metaCls->name = strdup(name);
+ if (metaCls->name == NULL) {
+ free((char*)(cls->name));
+ cls->name = NULL;
+ return -1;
+ }
+
+ cls->methodLists = malloc(sizeof(struct objc_method_list*));
+ if (cls->methodLists == NULL) {
+ PyErr_NoMemory();
+ free((char*)(cls->name));
+ cls->name = NULL;
+ free((char*)(metaCls->name));
+ metaCls->name = NULL;
+ return -1;
+ }
+ memset(cls->methodLists, 0, sizeof(*(cls->methodLists)));
+
+ metaCls->methodLists = malloc(sizeof(struct objc_method_list*));
+ if (cls->methodLists == NULL) {
+ PyErr_NoMemory();
+ free((char*)(cls->name));
+ cls->name = NULL;
+ free((char*)(metaCls->name));
+ metaCls->name = NULL;
+ free(cls->methodLists);
+ cls->methodLists = NULL;
+ return -1;
+ }
+ memset(metaCls->methodLists, 0, sizeof(*(metaCls->methodLists)));
+
+ /*
+ * This is MacOS X specific, and an undocumented feature (long live
+ * Open Source!).
+ *
+ * The code in the objc runtime assumes that the method lists are
+ * terminated by '-1', and will happily overwite existing data if
+ * they aren't.
+ *
+ * Ronald filed a bugreport for this: Radar #3317376
+ */
+ cls->methodLists[0] = (struct objc_method_list*)-1;
+ metaCls->methodLists[0] = (struct objc_method_list*)-1;
+
+ cls->super_class = superCls;
+ metaCls->super_class = superCls->isa;
+ metaCls->isa = rootCls->isa;
+
+ cls->instance_size = ivarSize;
+ cls->ivars = ivarList;
+
+ metaCls->instance_size = metaCls->super_class->instance_size;
+ metaCls->ivars = NULL;
+
+ metaCls->protocols = cls->protocols = protocolList;
+
+ return 0;
+}
+
+void PyObjCRT_ClearClass(Class cls)
+{
+ if (cls->methodLists) {
+ if (cls->methodLists) {
+ struct objc_method_list** cur;
+
+ cur = cls->methodLists;
+ while (*cur != (struct objc_method_list*)-1) {
+ if (*cur != NULL) {
+ free(*cur);
+ *cur = NULL;
+ }
+ cur++;
+ }
+ free(cls->methodLists);
+ cls->methodLists = NULL;
+ }
+ cls->methodLists = NULL;
+ }
+
+ if (cls->name) {
+ free((char*)(cls->name));
+ }
+}
+
+struct objc_method_list *PyObjCRT_AllocMethodList(ssize_t numMethods)
+{
+ struct objc_method_list *mlist;
+
+ mlist = malloc(sizeof(struct objc_method_list)
+ + ((numMethods+1) * sizeof(struct objc_method)));
+
+ if (mlist == NULL) {
+ return NULL;
+ }
+
+ mlist->method_count = 0;
+ mlist->obsolete = NULL;
+
+ return mlist;
+}
+
+struct objc_protocol_list* PyObjCRT_AllocProtocolList(ssize_t numProtocols)
+{
+ struct objc_protocol_list *plist;
+
+ plist = malloc(sizeof(struct objc_protocol_list)
+ + ((numProtocols+1) * sizeof(Protocol *)));
+
+ if (plist == NULL) {
+ return NULL;
+ }
+
+ plist->count = 0;
+ plist->next = NULL;
+
+ return plist;
+}
+
+#else /* !APPLE_RUNTIME */
+
+static int dummy __attribute__((__unused__));
+
+#endif /* !APPLE_RUNTIME */
diff --git a/Objective-C/PyObjC/objc-runtime-gnu.h b/Objective-C/PyObjC/objc-runtime-gnu.h
new file mode 100644
index 0000000..5c87b6d
--- /dev/null
+++ b/Objective-C/PyObjC/objc-runtime-gnu.h
@@ -0,0 +1,174 @@
+#ifndef PyObjC_RUNTIME_GNU_H
+#define PyObjC_RUNTIME_GNU_H
+
+/*
+ * Specific support for the GNU Objective-C runtime
+ */
+
+#include <Foundation/NSException.h>
+#include <Foundation/NSString.h>
+
+#define objc_msgSendSuper(super, op, args...) \
+ ((super)->self == NULL \
+ ? 0 \
+ : ( \
+ class_get_instance_method( \
+ (super)->class, (op) \
+ )->method_imp)( \
+ (super)->self, \
+ (op) ,##args))
+
+
+/*
+ * XXX: AFAIK as I (Ronald) know, there should be an include named
+ * <objc/runtime.h> on systems with the GNU runtime. However, this file
+ * not present on my Linux playmachine (running Debian testing)...
+ *
+ * The alternative is to declare some prototypes ourselves...
+ */
+#if 0
+# include <objc/runtime.h>
+#else
+ extern void class_add_method_list(Class, MethodList_t);
+ extern void __objc_add_class_to_hash(Class);
+#endif
+
+
+#ifndef nil
+#define nil NULL
+#endif
+
+/* What we call _C_LNGLNG is actually _C_LNG_LNG in the GNU runtime */
+#define _C_LNGLNG _C_LNG_LNG
+#define _C_ULNGLNG _C_ULNG_LNG
+
+/* XXX: names don't conform to the coding-style! */
+extern Ivar_t class_getInstanceVariable(Class aClass, const char *name);
+extern Ivar_t object_getInstanceVariable(id obj, const char *name, void **out);
+extern Ivar_t object_setInstanceVariable(id obj, const char *name, void *value);
+extern void objc_addClass(Class aClass);
+//extern id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
+extern void objc_freeMethodList(struct objc_method_list *list);
+
+static inline int PyObjCRT_SameSEL(SEL a, SEL b)
+{
+ return sel_eq(a, b);
+}
+
+
+static inline const char*
+PyObjCRT_SELName(SEL sel)
+{
+ return sel_get_name(sel);
+}
+
+static inline SEL
+PyObjCRT_SELUID(const char* str)
+{
+ return sel_get_uid(str);
+}
+
+static inline void
+PyObjCRT_ClassAddMethodList(Class cls, MethodList_t lst)
+{
+ int i;
+
+ /* First convert the method_names to strings, class_add_method_list
+ * assumes the method_names are strings and converts these back
+ * to selectors.
+ */
+ for (i = 0; i < lst->method_count; i++) {
+ lst->method_list[i].method_name = (SEL)PyObjCRT_SELName(lst->method_list[i].method_name);
+ }
+
+ class_add_method_list(cls, lst);
+}
+
+static inline Class
+PyObjCRT_LookUpClass(const char* name)
+{
+ return objc_lookup_class(name);
+}
+
+static inline struct objc_method_list *
+PyObjCRT_NextMethodList(Class c, void ** p)
+{
+ if (*p == 0) {
+ *p = c->methods;
+ } else {
+ *p = (*((MethodList_t*)p))->method_next;
+ }
+ return *(MethodList_t*)p;
+}
+
+static inline void
+PyObjCRT_InitMethod(Method_t m, SEL name, const char* types, IMP imp)
+{
+ /* XXX: With some versions of the GNU runtime, the runtime assumes
+ * that method_name is initialy a string instead of a selector, other
+ * versions do not. The version on my development box currently
+ * doesn't.
+ *
+ * m->method_name = (SEL)PyObjCRT_SELName(name);
+ */
+ m->method_name = name;
+ m->method_types = types;
+ m->method_imp = imp;
+}
+
+
+extern MethodList_t PyObjCRT_AllocMethodList(ssize_t);
+extern struct objc_protocol_list* PyObjCRT_AllocProtocolList(ssize_t);
+
+
+typedef Method_t PyObjCRT_Method_t;
+typedef Ivar_t PyObjCRT_Ivar_t;
+
+static inline Class GETISA(id obj)
+{
+ return obj->class_pointer;
+}
+
+//#define GETISA(c) (*((struct objc_object**)&(c))->class_pointer)
+#define CLS_CLASS _CLS_CLASS
+#define CLS_META _CLS_META
+#define RECEIVER(c) (c).self
+
+static inline const char *
+get_selector_encoding (id self, SEL sel)
+{
+ return sel->sel_types;
+}
+
+
+
+extern void PyObjCRT_AddClass(Class cls);
+#define objc_addClass PyObjCRT_AddClass
+
+/* Return a number that is likely to change when the method list changes,
+ * and is cheap to compute.
+ */
+static inline int
+objc_methodlist_magic(Class cls)
+{
+ struct objc_method_list *mlist;
+ int res, cnt;
+ void *iterator = 0;
+
+ res = cnt = 0;
+
+ if (cls == NULL)
+ return -1;
+
+ while ((mlist = PyObjCRT_NextMethodList(cls, &iterator)))
+ {
+ res += mlist->method_count;
+ cnt ++;
+ }
+
+ return (cnt << 16) | (res & 0xFFFF);
+}
+
+
+
+#endif /* PyObjC_RUNTIME_GNU_H */
diff --git a/Objective-C/PyObjC/objc-runtime-gnu.m b/Objective-C/PyObjC/objc-runtime-gnu.m
new file mode 100644
index 0000000..df868e4
--- /dev/null
+++ b/Objective-C/PyObjC/objc-runtime-gnu.m
@@ -0,0 +1,217 @@
+/* This file is part of the PyObjC package. */
+/*
+ * Support code for the GNU runtime
+ *
+ * NOTE: This file uses some private functions in the GNU runtime as that seems
+ * to be the only way to properly interface with that runtime.
+ */
+#include "pyobjc.h"
+
+#if defined(GNU_RUNTIME)
+#include "objc-runtime-gnu.h"
+
+struct objc_protocol_list* PyObjCRT_AllocProtocolList(int numProtocols)
+{
+ struct objc_protocol_list *plist;
+
+ plist = malloc(sizeof(struct objc_protocol_list)
+ + ((numProtocols+1) * sizeof(Protocol *)));
+
+ if (plist == NULL) {
+ return NULL;
+ }
+
+ plist->count = 0;
+ plist->next = NULL;
+
+ return plist;
+}
+
+int PyObjCRT_SetupClass(
+ Class cls,
+ Class metaCls,
+ const char*name,
+ Class superCls,
+ Class rootCls,
+ int ivarSize,
+ struct objc_ivar_list* ivarList,
+ struct objc_protocol_list* protocolList
+)
+
+{
+ /* This is a private function, but seems to be the only way to
+ * really create the class.
+ */
+ extern void __objc_install_premature_dtable (Class);
+
+ /* Initialize the structure */
+ memset(cls, 0, sizeof(*cls));
+ memset(metaCls, 0, sizeof(*cls));
+
+ cls->version = 0;
+ metaCls->version = 0;
+ cls->subclass_list = NULL;
+ metaCls->subclass_list = NULL;
+ cls->sibling_class = NULL;
+ metaCls->sibling_class = NULL;
+
+ cls->methods = NULL;
+ metaCls->methods = NULL;
+ cls->class_pointer = metaCls;
+
+ cls->info = CLS_CLASS;
+ metaCls->info = CLS_META;
+
+ cls->name = strdup(name);
+ if (cls->name == NULL) {
+ return -1;
+ }
+ metaCls->name = strdup(name);
+ if (metaCls->name == NULL) {
+ free((char*)(cls->name));
+ cls->name = NULL;
+ return -1;
+ }
+
+ cls->methods = NULL;
+ metaCls->methods = NULL;
+
+ cls->super_class = superCls;
+ metaCls->super_class = superCls->class_pointer;
+ metaCls->class_pointer = rootCls->class_pointer;
+ CLS_SETRESOLV(cls);
+ CLS_SETRESOLV(metaCls);
+
+ cls->instance_size = ivarSize;
+ cls->ivars = ivarList;
+
+ metaCls->instance_size = metaCls->super_class->instance_size;
+ metaCls->ivars = NULL;
+
+ metaCls->protocols = cls->protocols = protocolList;
+
+ metaCls->dtable = objc_get_uninstalled_dtable();
+ cls->dtable = objc_get_uninstalled_dtable();
+
+ return 0;
+}
+
+void PyObjCRT_AddClass(Class cls)
+{
+ cls->sibling_class = cls->super_class->subclass_list;
+ cls->super_class->subclass_list = cls;
+ cls->class_pointer->sibling_class = cls->super_class->class_pointer->subclass_list;
+ cls->super_class->class_pointer->subclass_list = cls->class_pointer;
+ __objc_add_class_to_hash(cls);
+}
+
+
+void PyObjCRT_ClearClass(Class cls)
+{
+ if (cls->methods) {
+ MethodList_t next, cur;
+
+ cur = cls->methods;
+
+ while (cur != NULL) {
+ next = cur->method_next;
+
+ objc_free(cur);
+ cur = next;
+ }
+ cls->methods = NULL;
+ }
+
+ if (cls->name) {
+ free((char*)(cls->name));
+ cls->name = NULL;
+ }
+}
+
+struct objc_method_list *PyObjCRT_AllocMethodList(int numMethods)
+{
+ struct objc_method_list *mlist;
+
+ mlist = objc_malloc(sizeof(struct objc_method_list)
+ + ((numMethods+1) * sizeof(struct objc_method)));
+
+ if (mlist == NULL) {
+ return NULL;
+ }
+
+ mlist->method_count = 0;
+ mlist->method_next = NULL;
+
+ return mlist;
+}
+
+/*
+ * XXX: This functions should be renamed to avoid name classes with
+ * the actual ObjC runtime
+ */
+
+Ivar_t class_getInstanceVariable(Class aClass, const char *name)
+{
+ if (!aClass || !name)
+ return NULL;
+
+ for (; aClass != Nil; aClass = aClass->super_class)
+ {
+ int i;
+
+ if (!aClass->ivars)
+ continue;
+
+ for (i = 0; i < aClass->ivars->ivar_count; i++)
+ {
+ if (!strcmp(aClass->ivars->ivar_list[i].ivar_name, name))
+ return &aClass->ivars->ivar_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+Ivar_t object_getInstanceVariable(id obj, const char *name, void **out)
+{
+ Ivar_t var = NULL;
+
+ if (obj && name)
+ {
+ void **varIndex = NULL;
+
+ if ((var = class_getInstanceVariable(obj->class_pointer, name)))
+ varIndex = (void **)((char *)obj + var->ivar_offset);
+
+ if (out)
+ *out = *varIndex;
+ }
+
+ return var;
+}
+
+Ivar_t object_setInstanceVariable(id obj, const char *name, void *value)
+{
+ Ivar_t var = NULL;
+
+ if (obj && name)
+ {
+ void **varIndex;
+
+ if ((var = class_getInstanceVariable(obj->class_pointer, name)))
+ {
+ varIndex = (void **)((char *)obj + var->ivar_offset);
+
+ *varIndex = value;
+ }
+ }
+
+ return var;
+}
+
+
+#else /* !GNU_RUNTIME */
+
+static int dummy __attribute__((__unused__));
+
+#endif /* !GNU_RUNTIME */
diff --git a/Objective-C/PyObjC/objc_support.h b/Objective-C/PyObjC/objc_support.h
new file mode 100644
index 0000000..a9b4b28
--- /dev/null
+++ b/Objective-C/PyObjC/objc_support.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 1996,97,98 by Lele Gaifax. All Rights Reserved
+ * Copyright (2) 2003 Ronald Oussoren
+ *
+ * This software may be used and distributed freely for any purpose
+ * provided that this notice is included unchanged on any and all
+ * copies. The author does not warrant or guarantee this software in
+ * any way.
+ *
+ * This file is part of the PyObjC package.
+ *
+ * RCSfile: objc_support.h,v
+ * Revision: 1.16
+ * Date: 1998/08/18 15:35:57
+ *
+ * Created Tue Sep 10 14:11:38 1996.
+ *
+ * TODO: the functions exported by this file should be changed, the names
+ * should start with 'PyObjC' and should be the same as the names used in
+ * pyobjc-api.h (where appropriate).
+ */
+
+#ifndef _objc_support_H
+#define _objc_support_H
+
+#ifdef GNU_RUNTIME
+
+# include "objc-runtime-gnu.h"
+
+#else /* NeXTSTEP / Mac OS X */
+
+# include "objc-runtime-apple.h"
+
+#endif
+
+extern ssize_t PyObjCRT_SizeOfReturnType(const char* type);
+extern ssize_t PyObjCRT_SizeOfType(const char *type);
+extern ssize_t PyObjCRT_AlignOfType(const char *type);
+extern const char *PyObjCRT_SkipTypeSpec (const char *type);
+extern const char* PyObjCRT_SkipTypeQualifiers (const char* type);
+
+extern int PyObjCRT_SetupClass(
+ Class, Class, const char*, Class, Class, ssize_t, struct objc_ivar_list*,
+ struct objc_protocol_list*);
+extern void PyObjCRT_ClearClass(Class cls);
+
+#endif /* _objc_support_H */
diff --git a/Objective-C/PyObjC/objc_support.m b/Objective-C/PyObjC/objc_support.m
new file mode 100644
index 0000000..862879c
--- /dev/null
+++ b/Objective-C/PyObjC/objc_support.m
@@ -0,0 +1,505 @@
+/* Copyright (c) 1996,97,98 by Lele Gaifax. All Rights Reserved
+ * Copyright (c) 2002, 2003 Ronald Oussoren
+ *
+ * This software may be used and distributed freely for any purpose
+ * provided that this notice is included unchanged on any and all
+ * copies. The author does not warrant or guarantee this software in
+ * any way.
+ *
+ * This file is part of the PyObjC package.
+ *
+ * RCSfile: objc_support.m,v
+ * Revision: 1.24
+ * Date: 1998/08/18 15:35:58
+ *
+ * Created Tue Sep 10 14:16:02 1996.
+ */
+
+#include "objc_support.h"
+#include "pyobjc.h"
+
+#include <objc/Protocol.h>
+
+#include <unistd.h>
+
+#ifdef MACOSX
+/* OSX 10.1 doesn't define LLONG_MIN, LLONG_MAX and ULLONG_MAX */
+#ifndef LLONG_MIN
+#error "Mac OS X 10.1 not supported"
+#endif
+#endif
+
+#import <Foundation/NSInvocation.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSValue.h>
+#import <Foundation/NSDecimalNumber.h>
+
+#ifdef MACOSX
+#include <CoreFoundation/CFNumber.h>
+#endif /* MACOSX */
+
+
+/* Define in order to throw exceptions when a typespec cannot be parsed. */
+#undef STRICT_TYPE_PARSING
+
+
+#ifndef MAX
+static inline ssize_t
+MAX(ssize_t x, ssize_t y)
+{
+ return x > y ? x : y;
+}
+#endif
+
+static inline ssize_t
+ROUND(ssize_t v, ssize_t a)
+{
+ if (v % a == 0) {
+ return v;
+ } else {
+ return v + a - (v % a);
+ }
+}
+
+
+const char*
+PyObjCRT_SkipTypeQualifiers (const char* type)
+{
+ while (
+ *type == _C_CONST ||
+ *type == _C_IN ||
+ *type == _C_INOUT ||
+ *type == _C_OUT ||
+ *type == _C_BYCOPY ||
+ *type == _C_ONEWAY) {
+ type++;
+ }
+ while (*type && isdigit(*type)) type++;
+ return type;
+}
+
+
+const char *
+PyObjCRT_SkipTypeSpec (const char *type)
+{
+ type = PyObjCRT_SkipTypeQualifiers (type);
+
+ switch (*type) {
+ /* The following are one character type codes */
+ case _C_UNDEF:
+ case _C_CLASS:
+ case _C_SEL:
+ case _C_CHR:
+ case _C_UCHR:
+ case _C_CHARPTR:
+#ifdef _C_ATOM
+ case _C_ATOM:
+#endif
+#ifdef _C_BOOL
+ case _C_BOOL:
+#endif
+ case _C_SHT:
+ case _C_USHT:
+ case _C_INT:
+ case _C_UINT:
+ case _C_LNG:
+ case _C_ULNG:
+ case _C_FLT:
+ case _C_DBL:
+ case _C_VOID:
+ case _C_LNGLNG:
+ case _C_ULNGLNG:
+ case _C_BFLD: /* Not really 1 character, but close enough */
+ ++type;
+ break;
+
+ case _C_ID:
+ ++type;
+#ifdef MACOSX
+ if (*type == '"') {
+ /* embedded field name in an ivar_type */
+ type=strchr(type+1, '"');
+ if (type != NULL) {
+ type++;
+ }
+ }
+#endif
+ break;
+
+ case _C_ARY_B:
+ /* skip digits, typespec and closing ']' */
+
+ while (isdigit (*++type));
+ type = PyObjCRT_SkipTypeSpec (type);
+ assert (type == NULL || *type == _C_ARY_E);
+ if (type) type++;
+ break;
+
+ case _C_STRUCT_B:
+ /* skip name, and elements until closing '}' */
+ while (*type != _C_STRUCT_E && *type++ != '=');
+ while (type && *type != _C_STRUCT_E) {
+ if (*type == '"') {
+ /* embedded field names */
+ type = strchr(type+1, '"');
+ if (type != NULL) {
+ type++;
+ } else {
+ return NULL;
+ }
+ }
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (type) type++;
+ break;
+
+ case _C_UNION_B:
+ /* skip name, and elements until closing ')' */
+ while (*type != _C_UNION_E && *type++ != '=');
+ while (type && *type != _C_UNION_E) {
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (type) type++;
+ break;
+
+ case _C_PTR:
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+
+ /* Just skip the following typespec */
+ type = PyObjCRT_SkipTypeSpec (type+1);
+ break;
+
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return NULL;
+ }
+
+ /* The compiler inserts a number after the actual signature,
+ * this number may or may not be usefull depending on the compiler
+ * version. We never use it.
+ */
+ while (type && *type && isdigit(*type)) type++;
+ return type;
+}
+
+/*
+Return the alignment of an object specified by type
+*/
+
+/*
+* On MacOS X, the elements of a struct are aligned differently inside the
+* struct than outside. That is, the maximum alignment of any struct field
+* (except the first) is 4, doubles outside of a struct have an alignment of
+* 8.
+*
+* Other platform don't seem to have this inconsistency.
+*
+* XXX: sizeof_struct, alignof_struct and {de,}pythonify_c_struct should
+* probably be moved to platform dependend files. As long as this is the
+* only platform dependent code this isn't worth the effort.
+*/
+#ifdef MACOSX
+
+static inline ssize_t
+PyObjC_EmbeddedAlignOfType (const char* type)
+{
+ ssize_t align = PyObjCRT_AlignOfType(type);
+
+#ifdef __i386__
+ return align;
+
+#else
+ if (align < 4 || align == 16) {
+ return align;
+ } else {
+ return 4;
+ }
+#endif
+}
+
+#else
+
+static inline int
+PyObjC_EmbeddedAlignOfType (const char* type)
+{
+ ssize_t align = PyObjCRT_AlignOfType(type);
+
+ /* GNUstep/ix86 seems to behave like this: */
+ if (align < 4) {
+ return align;
+ } else {
+ return 4;
+ }
+}
+
+#endif
+
+ssize_t
+PyObjCRT_AlignOfType (const char *type)
+{
+ switch (*type) {
+ case _C_ID: return __alignof__ (id);
+ case _C_CLASS: return __alignof__ (Class);
+ case _C_SEL: return __alignof__ (SEL);
+ case _C_CHR: return __alignof__ (char);
+ case _C_UCHR: return __alignof__ (unsigned char);
+ case _C_SHT: return __alignof__ (short);
+ case _C_USHT: return __alignof__ (unsigned short);
+#ifdef _C_BOOL
+ case _C_BOOL: return __alignof__ (bool);
+#endif
+ case _C_INT: return __alignof__ (int);
+ case _C_UINT: return __alignof__ (unsigned int);
+ case _C_LNG: return __alignof__ (long);
+ case _C_ULNG: return __alignof__ (unsigned long);
+ case _C_FLT: return __alignof__ (float);
+ case _C_DBL:
+#if defined(__APPLE__) && defined(__i386__)
+ /* The ABI says natural alignment is 4 bytes, but
+ * GCC's __alignof__ says 8. The latter is wrong.
+ */
+ return 4;
+#else
+ return __alignof__ (double);
+#endif
+
+ case _C_CHARPTR: return __alignof__ (char *);
+#ifdef _C_ATOM
+ case _C_ATOM: return __alignof__ (char *);
+#endif
+ case _C_PTR: return __alignof__ (void *);
+#if defined(__APPLE__) && defined(__i386__)
+ /* The ABI says natural alignment is 4 bytes, but
+ * GCC's __alignof__ says 8. The latter is wrong.
+ */
+ case _C_LNGLNG: return 4;
+ case _C_ULNGLNG: return 4;
+#else
+ case _C_LNGLNG: return __alignof__(long long);
+ case _C_ULNGLNG: return __alignof__(unsigned long long);
+#endif
+
+ case _C_ARY_B:
+ while (isdigit(*++type)) /* do nothing */;
+ return PyObjCRT_AlignOfType (type);
+
+ case _C_STRUCT_B:
+ {
+ struct { int x; double y; } fooalign;
+ while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
+ if (*type != _C_STRUCT_E) {
+ int have_align = 0;
+ ssize_t align = 0;
+
+ while (type != NULL && *type != _C_STRUCT_E) {
+ if (*type == '"') {
+ type = strchr(type+1, '"');
+ if (type) type++;
+ }
+ if (have_align) {
+ align = MAX(align,
+ PyObjC_EmbeddedAlignOfType(type));
+ } else {
+ align = PyObjCRT_AlignOfType(type);
+ have_align = 1;
+ }
+ type = PyObjCRT_SkipTypeSpec(type);
+ }
+ if (type == NULL) return -1;
+ return align;
+ } else {
+ return __alignof__ (fooalign);
+ }
+ }
+
+ case _C_UNION_B:
+ {
+ int maxalign = 0;
+ type++;
+ while (*type != _C_UNION_E)
+ {
+ int item_align = PyObjCRT_AlignOfType(type);
+ if (item_align == -1) return -1;
+ maxalign = MAX (maxalign, item_align);
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ return maxalign;
+ }
+
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+ return PyObjCRT_AlignOfType(type+1);
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return -1;
+ }
+}
+
+/*
+The aligned size if the size rounded up to the nearest alignment.
+*/
+
+static ssize_t
+PyObjCRT_AlignedSize (const char *type)
+{
+ ssize_t size = PyObjCRT_SizeOfType (type);
+ ssize_t align = PyObjCRT_AlignOfType (type);
+
+ if (size == -1 || align == -1) return -1;
+ return ROUND(size, align);
+}
+
+/*
+return the size of an object specified by type
+*/
+
+ssize_t
+PyObjCRT_SizeOfType (const char *type)
+{
+ ssize_t itemSize;
+ switch (*type) {
+ case _C_VOID: return 0;
+ case _C_ID: return sizeof(id);
+ case _C_CLASS: return sizeof(Class);
+ case _C_SEL: return sizeof(SEL);
+ case _C_CHR: return sizeof(char);
+ case _C_UCHR: return sizeof(unsigned char);
+ case _C_SHT: return sizeof(short);
+ case _C_USHT: return sizeof(unsigned short);
+#ifdef _C_BOOL
+ case _C_BOOL: return sizeof(bool);
+#endif
+ case _C_INT: return sizeof(int);
+ case _C_UINT: return sizeof(unsigned int);
+ case _C_LNG: return sizeof(long);
+ case _C_ULNG: return sizeof(unsigned long);
+ case _C_FLT: return sizeof(float);
+ case _C_DBL: return sizeof(double);
+ case _C_LNGLNG: return sizeof(long long);
+ case _C_ULNGLNG: return sizeof(unsigned long long);
+
+ case _C_PTR:
+ case _C_CHARPTR:
+#ifdef _C_ATOM
+ case _C_ATOM:
+#endif
+ return sizeof(char*);
+
+ case _C_ARY_B:
+ {
+ ssize_t len = atoi(type+1);
+ ssize_t item_align;
+ while (isdigit(*++type))
+ ;
+ item_align = PyObjCRT_AlignedSize(type);
+ if (item_align == -1) return -1;
+ return len*item_align;
+ }
+ break;
+
+ case _C_STRUCT_B:
+ {
+ ssize_t acc_size = 0;
+ int have_align = 0;
+ ssize_t align;
+ ssize_t max_align = 0;
+
+ while (*type != _C_STRUCT_E && *type++ != '=')
+ ; /* skip "<name>=" */
+ while (*type != _C_STRUCT_E) {
+ if (*type == '"') {
+ type = strchr(type+1, '"');
+ if (type) type++;
+ }
+ if (have_align) {
+ align = PyObjC_EmbeddedAlignOfType(type);
+ if (align == -1) return -1;
+ } else {
+ align = PyObjCRT_AlignOfType(type);
+ if (align == -1) return -1;
+ have_align = 1;
+ }
+ max_align = MAX(align, max_align);
+ acc_size = ROUND (acc_size, align);
+
+ itemSize = PyObjCRT_SizeOfType (type);
+ if (itemSize == -1) return -1;
+ acc_size += itemSize;
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (max_align) {
+ acc_size = ROUND(acc_size, max_align);
+ }
+ return acc_size;
+ }
+
+ case _C_UNION_B:
+ {
+ ssize_t max_size = 0;
+ type++;
+ while (*type != _C_UNION_E) {
+ itemSize = PyObjCRT_SizeOfType (type);
+ if (itemSize == -1) return -1;
+ max_size = MAX (max_size, itemSize);
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ return max_size;
+ }
+
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+ return PyObjCRT_SizeOfType(type+1);
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return -1;
+ }
+}
+
+
+ssize_t
+PyObjCRT_SizeOfReturnType(const char* type)
+{
+ switch(*type) {
+ case _C_CHR:
+ case _C_UCHR:
+ case _C_SHT:
+ case _C_USHT:
+ return sizeof(int);
+ default:
+ return PyObjCRT_SizeOfType(type);
+ }
+}
diff --git a/Objective-C/PyObjC/pyobjc.h b/Objective-C/PyObjC/pyobjc.h
new file mode 100644
index 0000000..6a2d6b4
--- /dev/null
+++ b/Objective-C/PyObjC/pyobjc.h
@@ -0,0 +1,46 @@
+/* Copyright 2007, Matthias Andreas Benkard. */
+
+#ifndef __pyobjc_H
+#define __pyobjc_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "libobjcl.h"
+
+
+#ifdef __NEXT_RUNTIME__
+
+#ifndef APPLE_RUNTIME
+#define APPLE_RUNTIME
+#endif
+
+#import <objc/objc-class.h>
+
+#else /* !__NEXT_RUNTIME__ */
+
+#ifndef GNU_RUNTIME
+#define GNU_RUNTIME
+#endif
+
+#import <objc/objc-api.h>
+#ifndef __CXX__
+#define bool BOOL
+#endif
+
+#endif /* __NEXT_RUNTIME__ */
+
+
+#define PyMem_Free free
+#define PyMem_Malloc malloc
+#define Py_ssize_t ssize_t
+
+#ifdef OOM_KILL
+#define PyErr_NoMemory() [objcl_oom_exception raise]
+#else
+#define PyErr_NoMemory() NSLog (@"ERROR: Memory exhausted.");
+#endif
+
+#include "objc_support.h"
+#include "libffi_support.h"
+
+#endif /* __pyobjc_H */