changeset 1:033d260cfc9b

First upload of the bridge
author Jacob Carlborg <doob@me.com>
date Thu, 18 Jun 2009 22:00:13 +0200
parents c7db221de6e8
children 9fd439a28ce3
files .hgignore dsss.conf dstep/Cocoa/NSAutoreleasePool.d dstep/Cocoa/NSObject.d dstep/Cocoa/NSString.d dstep/internal/String.d dstep/internal/Traits.d dstep/internal/Tuple.d dstep/internal/Types.d dstep/internal/Util.d dstep/internal/Version.d dstep/internal/collection/Array.d dstep/objc/bindings.d dstep/objc/bridge/Bridge.d dstep/objc/bridge/Capsule.d dstep/objc/bridge/ClassInitializer.d dstep/objc/bridge/Type.d dstep/objc/bridge/TypeEncoding.d dstep/objc/bridge/Wrapper.d dstep/objc/message.d dstep/objc/objc.d dstep/objc/runtime.d sciprts/dgen.rb sciprts/dstepgen.rb scripts/dgen.rb scripts/dstepgen.rb
diffstat 26 files changed, 5605 insertions(+), 2738 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sat Jan 31 17:22:44 2009 +0100
+++ b/.hgignore	Thu Jun 18 22:00:13 2009 +0200
@@ -8,4 +8,7 @@
 *.sh
 *.a
 *.rf
-*.dylib
\ No newline at end of file
+*.dylib
+*.dstep
+main.d
+main
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsss.conf	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,2 @@
+#[dstep]
+[main.d]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/Cocoa/NSAutoreleasePool.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,31 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Apr 19, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.Cocoa.NSAutoreleasePool;
+
+import dstep.Cocoa.NSObject;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+/*
+class NSAutoreleasePool : NSObject
+{
+	this (id object)
+	{
+		super(object);
+	}
+	
+	static NSAutoreleasePool alloc ()
+	{
+		id r = objc.getClass!("NSAutoreleasePool").msgSend(sel.registerName!("alloc"));
+		return r ? new NSAutoreleasePool(r) : null;
+	}
+	
+	NSAutoreleasePool init ()
+	{
+		return invokeObjcCall!(NSAutoreleasePool, "init");
+	}
+	
+}*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/Cocoa/NSObject.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,42 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Mar 28, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.Cocoa.NSObject;
+
+import mambo.io;
+
+import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.Wrapper;
+
+
+
+class NSObject : ObjcWrapper
+{
+	mixin ObjcWrap;
+	
+	int i = 34;
+	
+	NSObject foo (NSObject o)
+	{
+		println("foo in NSObject");
+		o.add(1, 2);
+		println(this is o);
+	    
+		this.add(3, 4);
+	
+		return this;
+	}
+	
+	mixin ObjcBindMethod!(foo);
+	
+	int add (int x, int y)
+	{
+		println(x + y);
+		return x + y;
+	}
+	
+	mixin ObjcBindMethod!(add);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/Cocoa/NSString.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,36 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Apr 19, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.Cocoa.NSString;
+
+import tango.stdc.stringz;
+
+import dstep.Cocoa.NSObject;
+import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.Wrapper;
+import dstep.internal.String;
+import dstep.objc.objc;
+
+import mambo.io;
+
+class NSString : NSObject
+{
+	mixin ObjcWrap;
+	
+	string UTF8String ()
+	{
+		char* s = invokeObjcSelf!(char*, "UTF8String");
+		return fromStringz(s);
+	}
+	
+	int add (int x, int y)
+	{
+		println("NSString");
+		return 0;
+	}
+	
+	mixin ObjcBindMethod!(add);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/String.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,10 @@
+/**
+ * Copyright: Copyright (c) 2008-2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: 2008
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.String;
+
+public import dstep.internal.collection.Array;
+public import mambo.string;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/Traits.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,109 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Apr 28, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.Traits;
+
+/**
+ * Returns the name of the given function
+ * 
+ * Params:
+ *     func = the function alias to get the name of
+ *     
+ * Returns: the name of the function 
+ */
+template functionNameOf (alias func)
+{
+	version(LDC)
+		const functionNameOf = (&func).stringof[1 .. $];
+	
+	else
+		const functionNameOf = (&func).stringof[2 .. $];
+}
+
+/**
+ * Returns the parameter names of the given function
+ * 
+ * Params:
+ *     func = the function alias to get the parameter names of
+ *     
+ * Returns: an array of strings containing the parameter names 
+ */
+template parameterNamesOf (alias func)
+{
+	const parameterNamesOf = parameterNamesOfImpl!(func);
+}
+
+private char[][] parameterNamesOfImpl (alias func) ()
+{
+	char[] funcStr = typeof(&func).stringof;
+	
+	auto start = funcStr.indexOf('(');
+	auto end = funcStr.indexOf(')');
+	
+	const firstPattern = ' ';
+	const secondPattern = ',';
+	
+	funcStr = funcStr[start + 1 .. end];
+	
+	if (funcStr == "")
+		return null;
+		
+	funcStr ~= secondPattern;
+	
+	char[] token;
+	char[][] arr;
+	
+	foreach (c ; funcStr)
+	{		
+		if (c != firstPattern && c != secondPattern)
+			token ~= c;
+		
+		else
+		{			
+			if (token)
+				arr ~= token;
+			
+			token = null;
+		}			
+	}
+	
+	char[][] result;
+	bool skip = false;
+	
+	foreach (str ; arr)
+	{
+		skip = !skip;
+		
+		if (skip)
+			continue;
+		
+		result ~= str;
+	}
+	
+	return result;
+}
+
+/**
+ * Compile-time function to get the index of the give element.
+ * 
+ * Performs a linear scan, returning the index of the first occurrence 
+ * of the specified element in the array, or U.max if the array does 
+ * not contain the element.
+ * 
+ * Params:
+ *     arr = the array to get the index of the element from
+ *     element = the element to find
+ *     
+ * Returns: the index of the element or size_t.max if the element was not found.
+ */
+private size_t indexOf (T) (T[] arr, T element)
+{
+	foreach (i, e ; arr)
+		if (e == element)
+			return i;
+	
+	return size_t.max;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/Tuple.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,9 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: May 10, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.Tuple;
+
+public import mambo.util.Tuple;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/Types.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,30 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.Types;
+
+import dstep.internal.Version;
+
+version (Windows)
+{
+	alias int c_long;
+	alias uint c_ulong;
+}
+
+else
+{
+	static if (D_LP64)
+	{
+		alias long c_long;
+		alias ulong c_ulong;
+	}
+
+	else
+	{
+		alias int c_long;
+		alias uint c_ulong;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/Util.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,7 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.Util;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/Version.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,141 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Mar 28, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.Version;
+
+public import mambo.util.Version;
+
+/*static if ((void*).sizeof > int.sizeof)
+	version = D_LP64;
+
+version (GNU)
+	version (darwin)
+		version = OSX;
+
+version (DigitalMars)
+	version (OSX)
+		version = darwin;
+
+//Compiler Vendors
+version (DigitalMars) const bool DigitalMars = true;
+else const bool DigitalMars = false;
+
+version (GNU) const bool GNU = true;
+else const bool GNU = false;
+
+version (LDC) const bool LDC = true;
+else const bool LDC = false;
+
+version (LLVM) const bool LLVM = true;
+else const bool LLVM = false;
+
+
+
+//Processors 
+version (PPC) const bool PPC = true;
+else const bool PPC = false;
+
+version (PPC64) const bool PPC64 = true;
+else const bool PPC64 = false;
+
+version (SPARC) const bool SPARC = true;
+else const bool SPARC = false;
+
+version (SPARC64) const bool SPARC64 = true;
+else const bool SPARC64 = false;
+
+version (X86) const bool X86 = true;
+else const bool X86 = false;
+
+version (X86_64) const bool X86_64 = true;
+else const bool X86_64 = false;
+
+
+
+//Operating Systems
+version (aix) const bool aix = true;
+else const bool aix = false;
+
+version (cygwin) const bool cygwin = true;
+else const bool cygwin = false;
+
+version (darwin) const bool darwin = true;
+else const bool darwin = false;
+
+version (OSX) const bool OSX = true;
+else const bool OSX = false;
+
+version (freebsd) const bool freebsd = true;
+else const bool freebsd = false;
+
+version (linux) const bool linux = true;
+else const bool linux = false;
+
+version (solaris) const bool solaris = true;
+else const bool solaris = false;
+
+version (Unix) const bool Unix = true;
+else const bool Unix = false;
+
+version (Win32) const bool Win32 = true;
+else const bool Win32 = false;
+
+version (Win64) const bool Win64 = true;
+else const bool Win64 = false;
+
+version (Windows) const bool Windows = true;
+else const bool Windows = false;
+
+
+
+//Rest
+version (BigEndian) const bool BigEndian = true;
+else const bool BigEndian = false;
+
+version (LittleEndian) const bool LittleEndian = true;
+else const bool LittleEndian = false;
+
+version (D_Coverage) const bool D_Coverage = true;
+else const bool D_Coverage = false;
+
+version (D_Ddoc) const bool D_Ddoc = true;
+else const bool D_Ddoc = false;
+
+version (D_InlineAsm_X86) const bool D_InlineAsm_X86 = true;
+else const bool D_InlineAsm_X86 = false;
+
+version (D_InlineAsm_X86_64) const bool D_InlineAsm_X86_64 = true;
+else const bool D_InlineAsm_X86_64 = false;
+
+version (D_LP64) const bool D_LP64 = true;
+else const bool D_LP64 = false;
+
+version (D_PIC) const bool D_PIC = true;
+else const bool D_PIC = false;
+
+version (GNU_BitsPerPointer32) const bool GNU_BitsPerPointer32 = true;
+else const bool GNU_BitsPerPointer32 = false;
+
+version (GNU_BitsPerPointer64) const bool GNU_BitsPerPointer64 = true;
+else const bool GNU_BitsPerPointer64 = false;
+
+version (all) const bool all = true;
+else const bool D_InlineAsm_X86_64 = false;
+
+version (none) const bool D_InlineAsm_X86_64 = true;
+else const bool none = false;
+
+version (Tango)
+{
+	const bool Tango = true;
+	const bool Phobos = false;
+}
+
+else
+{
+	const bool Tango = false;
+	const bool Phobos = true; 
+}*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/internal/collection/Array.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,9 @@
+/**
+ * Copyright: Copyright (c) 2008-2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: 2008
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.internal.collection.Array;
+
+public import mambo.collection.Array;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bindings.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,152 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bindings;
+
+import dstep.objc.message;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+import dstep.internal.Util;
+
+extern (C)
+{
+	// runtime.h
+	id object_copy (id obj, size_t size);
+	id object_dispose (id obj);
+	Class object_getClass (id obj);
+	Class object_setClass (id obj, Class cls);
+	char* object_getClassName (id obj);
+	void* object_getIndexedIvars (id obj);
+	id object_getIvar (id obj, Ivar ivar);
+	void object_setIvar (id obj, Ivar ivar, id value);
+	Ivar object_setInstanceVariable (id obj, char* name, void* value);
+	Ivar object_getInstanceVariable (id obj, char* name, void** outValue);
+	id objc_getClass (char* name);
+	id objc_getMetaClass (char* name);
+	id objc_lookUpClass (char* name);
+	id objc_getRequiredClass (char* name);
+	Class objc_getFutureClass (char* name);
+	void objc_setFutureClass (Class cls, char* name);
+	int objc_getClassList (Class* buffer, int bufferCount);
+	id objc_getProtocol (char* name);
+	Protocol** objc_copyProtocolList (uint* outCount);
+	char* class_getName (Class cls);
+	bool class_isMetaClass (Class cls);
+	Class class_getSuperclass (Class cls);
+	Class class_setSuperclass (Class cls, Class newSuper);
+	int class_getVersion (Class cls);
+	void class_setVersion (Class cls, int version_);
+	size_t class_getInstanceSize (Class cls);
+	Ivar class_getInstanceVariable (Class cls, char* name);
+	Ivar class_getClassVariable (Class cls, char* name);
+	Ivar* class_copyIvarList (Class cls, uint* outCount);
+	Method class_getInstanceMethod (Class cls, SEL name);
+	Method class_getClassMethod (Class cls, SEL name);
+	IMP class_getMethodImplementation (Class cls, SEL name);
+	IMP class_getMethodImplementation_stret (Class cls, SEL name);
+	bool class_respondsToSelector (Class cls, SEL sel);
+	Method* class_copyMethodList (Class cls, uint* outCount);
+	bool class_conformsToProtocol (Class cls, Protocol* protocol);
+	Protocol** class_copyProtocolList (Class cls, uint* outCount);
+	objc_property_t* class_getProperty (Class cls, char* name);
+	objc_property_t* class_copyPropertyList (Class cls, uint* outCount);
+	char* class_getIvarLayout (Class cls);
+	char* class_getWeakIvarLayout (Class cls);
+	id class_createInstance (Class cls, size_t extraBytes);
+	Class objc_allocateClassPair (Class superclass, char* name, size_t extraBytes);
+	void objc_registerClassPair (Class cls);
+	Class objc_duplicateClass (Class original, char* name, size_t extraBytes);
+	void objc_disposeClassPair (Class cls);
+	bool class_addMethod (Class cls, SEL name, IMP imp, char* types);
+	IMP class_replaceMethod (Class cls, SEL name, IMP imp, char* types);
+	bool class_addIvar (Class cls, char* name, size_t size, ubyte alignment, char* types);
+	bool class_addProtocol (Class cls, Protocol* protocol);
+	void class_setIvarLayout (Class cls, char* layout);
+	void class_setWeakIvarLayout (Class cls, char* layout);
+	SEL method_getName (Method m);
+	IMP method_getImplementation (Method m);
+	char* method_getTypeEncoding (Method m);
+	uint method_getNumberOfArguments (Method m);
+	char* method_copyReturnType (Method m);
+	char* method_copyArgumentType (Method m, uint index);
+	void method_getReturnType (Method m, char* dst, size_t dst_len);
+	void method_getArgumentType (Method m, uint index, char* dst, size_t dst_len);
+	objc_method_description* method_getDescription (Method m);
+	IMP method_setImplementation (Method m, IMP imp);
+	void method_exchangeImplementations (Method m1, Method m2);
+	char* ivar_getName (Ivar v);
+	char* ivar_getTypeEncoding (Ivar v);
+	ptrdiff_t ivar_getOffset (Ivar v);
+	char* property_getName (objc_property_t* property);
+	char* property_getAttributes (objc_property_t* property);
+	bool protocol_conformsToProtocol (id proto, id other);
+	bool protocol_isEqual (id proto, id other);
+	char* protocol_getName (id p);
+	objc_method_description protocol_getMethodDescription (id p, SEL aSel, bool isRequiredMethod, bool isInstanceMethod);
+	objc_method_description* protocol_copyMethodDescriptionList(id p, bool isRequiredMethod, bool isInstanceMethod, uint* outCount);
+	objc_property_t* protocol_getProperty (id proto, char* name, bool isRequiredProperty, bool isInstanceProperty);
+	objc_property_t* protocol_copyPropertyList (id proto, uint* outCount);
+	Protocol** protocol_copyProtocolList (id proto, uint* outCount);
+	char** objc_copyImageNames (uint* outCount);
+	char* class_getImageName (Class cls);
+	char** objc_copyClassNamesForImage (char* image, uint* outCount);
+	char* sel_getName (SEL sel);
+	SEL sel_getUid (char* str);
+	SEL sel_registerName (char* str);
+	bool sel_isEqual (SEL lhs, SEL rhs);
+	void objc_enumerationMutation (id arg0);
+	void objc_setForwardHandler (void* fwd, void* fwd_stret);
+	bool sel_isMapped (SEL sel);
+	id object_copyFromZone (id anObject, size_t nBytes, void* z);
+	id object_realloc (id anObject, size_t nBytes);
+	id object_reallocFromZone (id anObject, size_t nBytes, void* z);
+	void* objc_getClasses ();
+	void objc_addClass (Class myClass);
+	void objc_setMultithreaded (bool flag);
+	id class_createInstanceFromZone (Class arg0, size_t idxIvars, void* z);
+	void class_addMethods (Class arg0, objc_method_list* arg1);
+	void class_removeMethods (Class arg0, objc_method_list* arg1);
+	Class class_poseAs (Class imposter, Class original);
+	uint method_getSizeOfArguments (Method m);
+	uint method_getArgumentInfo (objc_method* m, int arg, char** type, int* offset);
+	bool class_respondsToMethod (Class arg0, SEL arg1);
+	IMP class_lookupMethod (Class arg0, SEL arg1);
+	Class objc_getOrigClass (char* name);
+	objc_method_list* class_nextMethodList (Class arg0, void* arg1);	
+	
+	// message.h
+	id objc_msgSend (id self, SEL op, ...);
+	id objc_msgSendSuper (objc_super* super_, SEL op, ...);
+	void objc_msgSend_stret (void* stretAddr, id self, SEL op, ...);
+	void objc_msgSendSuper_stret (void* stretAddr, objc_super* super_, SEL op, ...);
+	id objc_msgSendv (id self, SEL op, size_t arg_size, void* arg_frame);
+	void objc_msgSendv_stret (void* stretAddr, id self, SEL op, size_t arg_size, void* arg_frame);
+	
+	id method_invoke (id receiver, Method m, ...);
+	void method_invoke_stret (id receiver, Method m, ...);
+	
+	version (X86_64)
+		real objc_msgSend_fpret (id self, SEL op, ...);
+	
+	else version (X86)
+	{
+		double objc_msgSendv_fpret (id self, SEL op, uint arg_size, void* arg_frame);
+		double objc_msgSend_fpret (id self, SEL op, ...);
+	}
+}
+
+version (build)
+{
+	version (GNU)
+	{
+		pragma(link, "objc -framework Cocoa");
+	}
+	
+	else
+	{
+		pragma(link, "objc -L-framework -LCocoa");
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/Bridge.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,431 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 4, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.Bridge;
+
+import mambo.io;
+
+version (Tango)
+{
+	import tango.core.Memory;
+	import tango.core.Traits : ParameterTupleOf, ReturnTypeOf;
+	
+	alias GC.addRoot addRoot;
+}
+
+else
+{
+	import std.gc : addRoot;
+	import std.traits : ParameterTypeTuple, ReturnType;
+
+	alias ReturnType ReturnTypeOf;
+	alias ParameterTypeTuple ParameterTupleOf;
+}
+
+import dstep.internal.String;
+import dstep.internal.Tuple;
+import dstep.internal.Version;
+import dstep.objc.bridge.Capsule;
+import dstep.objc.bridge.ClassInitializer;
+import dstep.objc.bridge.TypeEncoding;
+import dstep.objc.bridge.Wrapper;
+import dstep.objc.message;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+
+/**
+ * Builds a string representing a selector out of the given function
+ * 
+ * It will build the string like this:
+ * 
+ * ---
+ * foo (int x, int y); // foo:y:
+ * bar (); // bar
+ * fooBar (int x); // fooBar:
+ * ---
+ * 
+ * Params:
+ *     func = the function alias to build the selector of
+ *     
+ * Returns: a string representing the selector
+ */
+template selector (alias func)
+{
+	const selector = buildSelector!(func);
+}
+
+template ObjcWrap ()
+{
+	mixin ObjcWrap!(this.stringof);
+}
+
+template ObjcWrap (string name)
+{
+	import dstep.objc.bridge.ClassInitializer : ObjcSubclassInitializer, subclassInit;
+	import dstep.objc.objc : Class, id, IMP, SEL;
+
+	static private Class objcClass_;
+	static private Class objcSuperClass_;
+
+	this (id object)
+	{
+		super(object);
+	}
+	
+	static typeof(this) alloc ()
+	{
+		return invokeObjcSelfClass!(typeof(this), "alloc");
+	}
+	
+	typeof(this) init ()
+	{
+		id ret = invokeObjcSelf!(id, "init");
+		
+		if (!ret)
+			return null;
+		
+		if (ret is objcObject)
+		{
+			dObject = this;
+			return this;
+		}
+		
+		auto object = new typeof(this) (ret);
+		object.dObject = this;
+		
+		return object;
+	}
+	
+	mixin ObjcSubclassInitializer!("D_" ~ name, name);
+}
+
+struct ObjcMethodDeclaration (alias imp, R, string name, ARGS...)
+{
+	alias imp methodImp;
+	alias R returnType;
+	const string methodName = name;
+	alias ARGS argsType;
+}
+
+template ObjcBindMethod (alias method)
+{
+	import dstep.objc.bridge.TypeEncoding : buildSelector, encode;
+
+	mixin ObjcBindMethod!(method, buildSelector!(method));
+}
+
+template ObjcBindMethod (alias method, string selector)
+{	
+	mixin ObjcBindMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method));
+}
+
+template ObjcBindMethod (alias method, R, string selector, ARGS...)
+{	
+	import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule, needsEncapsulation;
+	import dstep.internal.Tuple;
+   
+	private ObjcMethodDeclaration!(method, R, selector, ARGS) objcMethodDeclaration;	
+	
+	private R delegate (ARGS) resolveVirtualCall ()
+	{
+		return null;
+	}
+		
+	static if (needsEncapsulation!(R))
+	{
+        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+        
+		private static id forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs)
+		in
+		{
+			assert(isCapsule(self));
+		}
+		body
+		{
+			R delegate (ARGS) dg;
+			dg.funcptr = &method;
+			dg.ptr = Bridge.getDObject(self);
+			
+			ARGS args;
+			
+			foreach (i, a ; objcArgs)
+			{
+				alias typeof(args[i]) ArgType;
+				
+				args[i] = decapsule!(ArgType)(a);
+			}
+			
+			auto result = dg(args);
+			
+			return encapsule!(R)(result);
+		}
+	}
+	
+	else
+	{
+        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;        
+        
+		private static R forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs)
+		in
+		{
+			assert(isCapsule(self));
+		}
+		body
+		{
+			R delegate (ARGS) dg;            
+			dg.funcptr = &method;
+			dg.ptr = Bridge.getDObject(self);
+			
+			ARGS args;
+			
+			foreach (i, a ; objcArgs)
+			{
+				alias typeof(args[i]) ArgType;
+
+                args[i] = decapsule!(ArgType)(a);
+			}
+			
+			return dg(args);
+		}
+	}
+}
+
+template ObjcBindClassMethod (alias method, string selector)
+{
+	mixin ObjcBindClassMethod!(method, ReturnTypeOf!(method), selector, ParameterTupleOf!(method));
+}
+
+template ObjcBindClassMethod (alias method, R, string selector, ARGS...)
+{	
+	private ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
+		
+	static if (needsEncapsulation!(R))
+	{
+        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+        
+		private static id forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs)
+		in
+		{
+			assert(isCapsule(self));
+		}
+		body
+		{
+			R function (ARGS) dg = &method;
+			
+			ARGS args;
+			
+			foreach (i, a ; objcArgs)
+			{
+				alias typeof(args[i]) ArgType;
+				
+				args[i] = decapsule!(ArgType)(a);
+			}
+			
+			auto result = dg(args);
+			
+			return encapsule!(R)(result);
+		}
+	}
+	
+	else
+	{
+        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;        
+        
+		private static R forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs)
+		in
+		{
+			assert(isCapsule(self));
+		}
+		body
+		{
+			R function (ARGS) dg = &method;
+			
+			ARGS args;
+			
+			foreach (i, a ; objcArgs)
+			{
+				alias typeof(args[i]) ArgType;
+
+                args[i] = decapsule!(ArgType)(a);
+			}
+			
+			return dg(args);
+		}
+	}
+}
+
+struct Bridge
+{	
+	static:
+		
+	const objcMethodDeclarationVar = "objcMethodDeclaration";
+	const objcClassMethodDeclarationVar = "objcClassMethodDeclaration";
+	const dObjectVar = "dObject";
+	alias void* DObjectType;
+	private ClassInfo[string] registeredClasses;
+	
+	void registerClass (string className, ClassInfo classInfo)
+	{
+		if (className.length > 2 && className[0 .. 2] == "D_")
+			registeredClasses[className[0 .. 2]] = classInfo;
+		
+		else
+			registeredClasses[className] = classInfo;
+	}
+	
+	Object createRegisteredObject (T) (string className)
+	{
+		return null; 
+	}
+	
+	DObjectType getDObject (id self)
+	{
+		DObjectType dObject;
+		
+		self.getInstanceVariable!(DObjectType, dObjectVar)(dObject);
+		
+		return dObject;
+	}
+	
+	id setDObject (Object dObject, id objcObject)
+	{
+		auto o = cast(DObjectType) dObject;
+		addRoot(o);
+		
+		objcObject.setInstanceVariable!(DObjectType, Bridge.dObjectVar)(o);
+		
+		return objcObject;
+	}
+	
+	R invokeObjcMethod (R, string selector, ARGS...) (id self, ARGS args)
+	{
+		static if (!is(R : void))
+			R result;
+		
+		SEL sel = sel.registerName!(selector);
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		ObjcArgs objcArgs;
+		
+		foreach (i, a ; args)
+		{
+			alias typeof(a) ArgType;
+			
+			objcArgs[i] = encapsule!(ArgType)(a);
+		}	
+		
+		static if (is(R == struct))
+		{
+			self.msgSend_stret(result, sel, objcArgs);
+			return result;
+		}
+		
+		else static if (is(R == float) || is(R == double) || is(R == real))
+		{
+			version (X86)
+			{
+				static if (is(R == float))
+					return self.msgSend_fpret!(R)(sel, objcArgs);
+					
+				else
+					return self.msgSend_fpret(sel, objcArgs);
+			}
+			
+			else version (X86_64)
+			{
+				static if (is(R == real))
+					return self.msgSend_fpret(sel, objcArgs);
+				
+				else
+					return self.msgSend!(R)(sel, objcArgs);
+			}
+			
+			else
+				return self.msgSend!(R)(sel, objcArgs);
+		}
+		
+		else static if (is(R : ObjcWrapper))
+		{
+			id r = self.msgSend(sel, objcArgs);
+			
+			if (!r)
+				return null;
+			
+			if (isCapsule(r))
+			{
+				result = decapsule!(R)(r);
+				
+				if (result)
+					return result;
+			}				
+			
+			return new R(r);
+		}
+		
+		else static if (is(R : Object))
+		{
+			id r = self.msgSend(sel, objcArgs);
+			
+			if (!r)
+				return null;
+			
+			return decapsule!(R)(r);
+		}
+		
+		else
+			return self.msgSend!(R, ObjcArgs)(sel, objcArgs);
+	}
+	
+	R invokeObjcClassMethod (R = id, string selector, ARGS...) (Class cls, ARGS args)
+	{
+		return invokeObjcMethod!(R, selector, ARGS)(cast(id) cls, args);
+	}
+	
+	R invokeObjcSuperMethod (R = id, string selector, ARGS...) (objc_super* self, ARGS args)
+	{
+		R result;
+		SEL sel = sel.registerName!(selector);
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		ObjcArgs objcArgs;
+		
+		foreach (i, a ; args)
+		{
+			alias typeof(a) ArgType;
+			
+			objcArgs[i] = encapsule!(ArgType)(a);
+		}
+		
+		static if (is(R == struct))
+		{
+			self.msgSendSuper_stret(result, sel, objcArgs);
+		}
+		
+		else static if (is(R : ObjcWrapper))
+		{
+			id r = self.msgSendSuper(sel, objcArgs);
+			
+			if (isCapsule(r))
+			{
+				result = decapsule!(R)(r);
+				
+				if (result)
+					return result;
+			}				
+			
+			return r ? new R(r) : null;
+		}
+		
+		else static if (is(R : Object))
+		{
+			id r = self.msgSendSuper(sel, objcArgs);
+			return decapsule!(R)(r);
+		}
+		
+		else
+			return self.msgSend!(R)(sel, objcArgs);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/Capsule.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,177 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 3, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.Capsule;
+
+version (Tango)
+{
+	import tango.core.Memory;
+	import tango.math.Math : log2;
+	
+	alias GC.addRoot addRoot;
+	
+	import tango.core.Traits;
+}
+
+else
+{
+	import std.gc : addRoot;
+	import std.math : log2;
+}
+
+import dstep.internal.String;
+import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.TypeEncoding;
+import dstep.objc.bridge.Wrapper;
+import dstep.objc.message;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+import bindings = dstep.objc.bindings;
+
+import mambo.io;
+
+template ObjcType (T)
+{
+	static if (needsEncapsulation!(T))
+		alias id ObjcType;
+	
+	else
+		alias T ObjcType;
+}
+
+Class capsuleClass ()
+{
+	if (!Capsule.capsuleClass)
+		initCapsuleClass;
+	
+	return Capsule.capsuleClass;	
+}
+
+private struct Capsule
+{	
+	static Class capsuleClass;
+	
+	static id create (Object object, Class capsuleClass)
+	{
+		id capsule = objc.createInstance(capsuleClass, 0);
+		
+		Bridge.setDObject(object, capsule);
+		
+		return capsule;
+	}
+	
+	static id description (id self, SEL op)
+	in
+	{
+		assert(isCapsule(self));
+	}
+	body
+	{
+		return encapsuleString(decapsule!(Object)(self).toString);
+	}
+	
+	static hash_t hash (id self, SEL op)
+	in
+	{
+		assert(isCapsule(self));
+	}
+	body
+	{
+		return decapsule!(Object)(self).toHash;
+	}
+	
+	static byte isEqual (id self, SEL op, Object object)
+	in
+	{
+		assert(isCapsule(self));
+	}
+	body
+	{
+		return decapsule!(Object)(self) == object;
+	}
+}
+
+private void initCapsuleClass ()
+{
+	Class superClass = cast(Class) objc.getClass!("NSObject");
+	Capsule.capsuleClass = objc.allocateClassPair!("D_Object")(superClass, 0);
+	
+	ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof);
+
+	Capsule.capsuleClass.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment);
+	
+	Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.description))(sel.registerName!("description"), cast(IMP) &Capsule.description);
+	Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.hash))(sel.registerName!("hash"), cast(IMP) &Capsule.hash);
+	Capsule.capsuleClass.addMethod!(encodeCallable!(Capsule.isEqual))(sel.registerName!("isEqual"), cast (IMP) &Capsule.isEqual);
+	
+	objc.registerClassPair(capsuleClass);
+}
+
+bool isCapsule (id capsule)
+{
+	if (!capsule)
+		return false;
+	
+	Class cls = capsule.isa;
+	return cls.getInstanceVariable!(Bridge.dObjectVar) !is null;
+}
+
+template needsEncapsulation (T)
+{
+	static if (is(T == class))
+		const needsEncapsulation = true;
+	
+	else
+		const needsEncapsulation = false;
+}
+
+ObjcType!(T) encapsule (T) (T value)
+{	
+	static if (needsEncapsulation!(T))
+	{
+		if (!value)
+			return null;
+		
+		if (auto wrapper = cast(ObjcWrapper) value)
+			return wrapper.objcObject;
+		
+		return Capsule.create(value, capsuleClass);
+	}
+	
+	else
+		return value;
+}
+
+template decapsule (T)
+{
+	T decapsule (ObjcType!(T) value)
+	{
+		static if (needsEncapsulation!(T))
+		{
+			if (isCapsule(value))
+				return cast(T) Bridge.getDObject(value);
+			
+			else
+			{
+				static if (is(T : ObjcWrapper))
+					new T(value);
+				
+				else
+					return null;
+			}
+		}
+		
+		else
+			return value;
+	}
+}
+
+private id encapsuleString (string str)
+{
+	enum { NSUTF8StringEncoding = 4 }
+	
+	return objc.getClass!("NSString").msgSend(sel.registerName!("alloc")).msgSend(sel.registerName!("initWithBytes:length:encoding:"), str.ptr, str.length, NSUTF8StringEncoding);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/ClassInitializer.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,135 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Apr 7, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.ClassInitializer;
+
+version (Tango)
+	import tango.math.Math;
+
+else
+	import std.math;
+
+import dstep.internal.String;
+import bindings = dstep.objc.bindings;
+import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.TypeEncoding;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+
+package template ObjcSubclassInitializer (string subclassName, string superclassName)
+{	
+	import dstep.internal.String : string;
+	import dstep.objc.bridge.Bridge : ObjcBindMethod;
+	import dstep.objc.runtime : Method, objc_method, sel, objc;
+	import dstep.objc.bridge.TypeEncoding : encode;
+	
+	static Class objcClass ()
+	{		
+		if (objcClass_)
+			return objcClass_;
+		
+		Class superClass = cast(Class) objc.getClass!(superclassName);
+		
+		while (!superClass)
+			superClass = super.objcClass;		
+				
+		return objcClass_ = subclassInit!(subclassName)(superClass, collectObjcInstanceMethods, collectObjcClassMethods);
+	}
+	
+	private static Method[] collectObjcInstanceMethods ()
+	{
+		Method[] methods;
+		
+		mixin("alias " ~ superclassName ~ " Type;");
+		
+		foreach (i, f; typeof(Type.tupleof))
+		{
+			const len = Type.stringof.length;
+			const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
+			
+			static if (fieldName == Bridge.objcMethodDeclarationVar)
+			{
+				typeof(Type.tupleof[i]) field;
+
+				Method m = new objc_method;
+				m.method_name = sel.registerName!(field.methodName);
+				m.method_types = encode!(field.returnType, id, SEL, field.argsType).ptr;
+				m.method_imp = cast(IMP) &Type.ObjcBindMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardVirtualCall;
+				
+				methods ~= m;
+			}
+		}
+		
+		return methods;
+	}
+	
+	private static Method[] collectObjcClassMethods ()
+	{
+		Method[] methods;
+		
+		mixin("alias " ~ superclassName ~ " Type;");
+		
+		foreach (i, f; typeof(Type.tupleof))
+		{
+			const len = Type.stringof.length;
+			const fieldName = Type.tupleof[i].stringof[1 + len + 2 .. $];
+			
+			static if (fieldName == Bridge.objcClassMethodDeclarationVar)
+			{
+				typeof(Type.tupleof[i]) field;
+			
+				Method m = new objc_method;
+				m.method_name = sel.registerName!(field.methodName);
+				m.method_types = encode!(field.returnType, field.argsType).ptr;				
+				m.method_imp = cast(IMP) &Type.ObjcBindClassMethod!(field.methodImp, field.returnType, field.methodName, field.argsType).forwardStaticCall;
+				
+				methods ~= m;
+			}
+		}
+		
+		return methods;
+	}
+
+	private R invokeObjcSelf (R, string name, ARGS...) (ARGS args)
+	{
+		return Bridge.invokeObjcMethod!(R, name, ARGS)(objcObject, args);
+	}
+	
+	private R invokeObjcSuper (R, string name, ARGS...) (ARGS args)
+	{
+		return Bridge.invokeObjcMethod!(R, name, ARGS)(objcSuper, args);
+	}
+	
+	private static R invokeObjcSelfClass (R, string name, ARGS...) (ARGS args)
+	{
+		return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass, args);
+	}
+	
+	private static R invokeObjcSuperClass (R, string name, ARGS...) (ARGS args)
+	{
+		return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass.getSuperclass, args);
+	}
+}
+
+Class subclassInit (string className) (Class superClass, Method[] instanceMethods = null, Method[] classMethods = null)
+{
+	Class cls = objc.allocateClassPair!(className)(superClass, 0);
+	Class metaClass = (cast(id) cls).getClass;
+	
+	ubyte alignment = cast(ubyte) log2(Bridge.DObjectType.sizeof);
+
+	cls.addIvar!(Bridge.dObjectVar, encode!(Bridge.DObjectType))(Bridge.DObjectType.sizeof, alignment);
+	
+	foreach (method ; instanceMethods)
+		bindings.class_addMethod(cls, method.method_name, method.method_imp, method.method_types);
+	
+	foreach (method ; classMethods)
+		bindings.class_addMethod(metaClass, method.method_name, method.method_imp, method.method_types);
+	
+	objc.registerClassPair(cls);
+	
+	return cls;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/Type.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,36 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: May 16, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.Type;
+
+version (Tango)
+	import tango.core.Tuple;
+
+else
+	import std.typetuple;
+
+import dstep.objc.objc;
+
+template ObjcTypeTuple (TList...)
+{
+	alias replaceClasses!(TList).types ObjcTypeTuple;
+}
+
+private struct Wrap (TList...)
+{
+	TList types;
+}
+
+private Wrap!(TList) replaceClasses (TList...) ()
+{
+	alias Tuple!(TList) Types;
+	
+	foreach (ref type ; Types)
+		static if (is(type == class))
+			type = id;
+	
+	return Wrap!(Types);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/TypeEncoding.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,156 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 8, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.TypeEncoding;
+
+version (Tango)
+	import tango.core.Traits;
+
+else
+	import std.traits;
+
+import dstep.internal.String;
+import dstep.internal.Traits;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+
+/**
+ * Creates the encoded (mangled) form of a type for the
+ * Objective-C runtime. 
+ */
+template encode (TL...)
+{
+	const string encode = encodeImpl!(TL)();
+}
+
+private string encodeImpl (TL...) ()
+{
+	char[] s;
+	
+	foreach (T ; TL)
+	{
+		static if (is (T == id) || is (T == class))
+			s ~= _C_ID;
+
+		else static if (is (T == Class))
+			s ~= _C_CLASS;
+
+		else static if (is (T == SEL))
+			s ~= _C_SEL;
+		
+		else static if (is (T == byte))
+			s ~= _C_CHR;
+
+		else static if (is (T == ubyte))
+			s ~= _C_UCHR;
+
+		else static if (is (T == short))
+			s ~= _C_SHT;
+
+		else static if (is (T == ushort))
+			s ~= _C_USHT;
+
+		else static if (is (T == int))
+			s ~= _C_INT;
+
+		else static if (is (T == uint))
+			s ~= _C_UINT;
+
+		else static if (is (T == long))
+			s ~= _C_LNG_LNG;
+
+		else static if (is (T == ulong))
+			s ~= _C_ULNG_LNG;
+
+		else static if (is (T == float))
+			s ~= _C_FLT;
+
+		else static if (is (T == double))
+			s ~= _C_DBL;
+
+		else static if (is (T == bool))
+			s ~= _C_BOOL;
+
+		else static if (is (T == void))
+			s ~= _C_VOID;
+
+		else static if (is (T U : T*))
+			s ~= _C_VOID ~ encode!(U);
+
+		else static if (is (T : char*))
+			s ~= _C_CHARPTR;
+
+		else static if (is (T U : T))
+			s ~= _C_ARY_B ~ encode!(U) ~ _C_ARY_E;
+		
+		else static if (is (T == union))
+			s ~= _C_UNION_B ~ encode!(typeof(T.tupleof)) ~ _C_UNION_E;
+
+		else static if (is (T == struct))
+			s ~= _C_STRUCT_B ~ encode!(typeof(T.tupleof)) ~ _C_STRUCT_E;
+
+		else
+			s ~= _C_UNDEF;
+	}
+	
+	return s;
+}
+
+/**
+ * Create the encoded (mangled) form of a type for the
+ * Objective-C runtime out of the given callable type.
+ * This is a shortcut for encode
+ */
+template encodeCallable (alias Callable)
+{
+	static assert(isCallableType!(typeof(Callable)), "dstep.objc.bridge.TypeCoding.encodeCallable: The given type is not a callable type");
+	
+	const encodeCallable = encode!(ReturnTypeOf!(typeof(Callable)), id, SEL, ParameterTupleOf!(typeof(Callable)));
+}
+
+/**
+ * Builds a string representing a selector out of the given function
+ * 
+ * It will build the string like this:
+ * 
+ * ---
+ * foo (int x, int y); // foo:y:
+ * bar (); // bar
+ * fooBar (int x); // fooBar:
+ * ---
+ * 
+ * Params:
+ *     func = the function alias to build the selector of
+ *     
+ * Returns: a string representing the selector
+ */
+template buildSelector (alias method)
+{
+	const buildSelector = buildSelectorImpl!(method);
+}
+
+private string buildSelectorImpl (alias method) ()
+{
+	string result = functionNameOf!(method);
+	string[] parameterNames = parameterNamesOf!(method);
+	
+	if (parameterNames.length == 0)
+		return result;
+	
+	else if (parameterNames.length == 1)
+		return result ~ ':';
+	
+	else if (parameterNames.length >= 2)
+		parameterNames = parameterNames[1 .. $];
+	
+	result ~= ':';
+	
+	foreach (str ; parameterNames)
+		result ~= str ~ ':';		
+	
+	return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/bridge/Wrapper.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,80 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.bridge.Wrapper;
+
+import dstep.internal.String;
+import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.Capsule;
+import dstep.objc.message;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+
+class ObjcWrapper
+{	
+	package objc_super* objcSuper;
+	
+	static private Class objcClass_;
+	static private Class objcSuperClass_;
+	
+	private id objcObject_;
+		
+	/// Initialize object from an Objective-C object instance to wrap.
+	this (id object)
+	{
+		objcObject_ = object;
+		dObject = this;
+	}
+	
+	static Class objcClass ()
+	{
+		return capsuleClass;
+	}
+	
+	static Class objcSuperClass ()
+	{
+		if (!objcSuperClass_)
+			return objcSuperClass_ = objcClass.getSuperclass;
+		
+		return objcSuperClass_;
+	}
+	
+	id objcObject ()
+	{
+		return objcObject_;
+	}
+	
+	protected id objcObject (id object)
+	{
+		return objcObject_ = object;
+	}
+	
+	protected void dObject (Object dObject)
+	{
+		Bridge.setDObject(dObject, objcObject);
+	}
+	
+	/*this (bool init = true, bool alloc = true)
+	{
+		if (init && alloc)
+		{
+			id result = objc_msgSend!(id)(objc_getClass(this.classinfo.name), sel.registerName!("alloc"));
+			id result2;
+			
+			if (result)
+				result2 = objc_msgSend(result, sel.registerName!("init"));
+			
+			if (result2)
+				objc.object = result2;
+			
+			else
+				objc.object = result;
+		}
+		
+		else if (alloc)
+			objc.object = objc_msgSend(objc_getClass(this.classinfo.name), sel.registerName!("alloc"));
+	}*/
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/message.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,117 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.message;
+
+import dstep.internal.Version;
+import bindings = dstep.objc.bindings;
+import dstep.objc.objc;
+import dstep.objc.runtime;
+
+alias void* marg_list;
+
+version (X86)
+	const int STRUCT_SIZE_LIMIT = 8;
+
+else version (PPC)
+	const int STRUCT_SIZE_LIMIT = 4;
+
+else version (X86_64)
+	const int STRUCT_SIZE_LIMIT = 16;
+
+else version (PPC64) // Not sure about this
+	const int STRUCT_SIZE_LIMIT = 16;
+
+struct objc_super
+{
+    id receiver;
+    Class super_class;
+    
+    // for dwt compatibility
+    alias super_class cls;
+    
+	R msgSendSuper (R = id, ARGS...) (SEL op, ARGS args)
+	{
+		return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSendSuper)(this, op, args);
+	}
+	
+	void msgSendSuper_stret (T, ARGS...) (out T stretAddr, id self, SEL op, ARGS args)
+	{		
+	    if (T.sizeof > STRUCT_SIZE_LIMIT)
+			(cast(void function (T*, id, SEL, ARGS...))&bindings.objc_msgSendSuper_stret)(&stretAddr, self, op, args);
+	    
+	    else
+	        stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSendSuper)(self, op, args);
+	}
+}
+
+R objc_msgSend (R = id, ARGS...) (id self, SEL op, ARGS args)
+{
+	return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSend)(self, op, args);
+}
+
+R objc_msgSendSuper (R = id, ARGS...) (objc_super* super_, SEL op, ARGS args)
+{
+	return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSendSuper)(super_, op, args);
+}
+
+void objc_msgSend_stret (T, ARGS...) (out T stretAddr, id self, SEL op, ARGS args)
+{		
+    if (T.sizeof > STRUCT_SIZE_LIMIT)
+		(cast(void function (T*, id, SEL, ARGS...))&bindings.objc_msgSend_stret)(&stretAddr, self, op, args);
+    
+    else
+        stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSend)(self, op, args);
+}
+
+static if (X86 || X86_64)
+{
+	R objc_msgSend_fpret (R = id, ARGS...) (id self, SEL op, ARGS args)
+	{
+		version (X86_64)
+			static assert(!is(R : real), "Only real are legal return value for objc_msgSend_fpret");
+		
+		else
+			static assert(!is(R : double) && !is(R : float), "Only double and float are legal return values for objc_msgSend_fpret");
+			
+		return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSend_fpret)(self, op, args);
+	}
+}
+
+R method_invoke (R = id, ARGS...) (id receiver, Method m, ARGS args)
+{
+	static assert(receiver !is null);
+	return (cast(R function (id, SEL, ARGS...))&bindings.method_invoke)(receiver, m, args);
+}
+
+void method_invoke_stret (ARGS...) (id receiver, Method m, ARGS args)
+{
+	static assert(receiver !is null);
+	return (cast(R function (id, SEL, ARGS...))&bindings.method_invoke_stret)(receiver, m, args);
+}
+
+R objc_msgSendv (R = id, T) (id self, SEL op, size_t arg_size, T arg_frame)
+{
+	(cast(R function (id, SEL, size_t, T))&bindings.objc_msgSendv)(self, op, arg_size, arg_frame);
+}
+
+void objc_msgSendv_stret (R = id, T) (out T stretAddr, id self, SEL op, size_t arg_size, T arg_frame)
+{
+    if (R.sizeof > STRUCT_SIZE_LIMIT)
+		(cast(void function (R*, id, SEL, size_t, T))&bindings.objc_msgSendv_stret)(&stretAddr, self, op, arg_size, arg_frame);
+    
+    else
+        stretAddr = (*cast(R function (id, SEL, size_t, T))&bindings.objc_msgSendv)(self, op, arg_size, arg_frame);
+}
+
+version (X86)
+{
+	R objc_msgSendv_fpret (R = id, T) (id self, SEL op, uint arg_size, T arg_frame)
+	{
+		static assert(!is(R : double) && !is(R : float), "Only double and float are legal return values for objc_msgSendv_fpret");
+		return (cast(R function (id, SEL, uint, T))&bindings.objc_msgSendv_fpret)(self, op, arg_size, arg_frame);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/objc.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,220 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.objc;
+
+import dstep.internal.String;
+import dstep.internal.Types;
+import bindings = dstep.objc.bindings;
+import dstep.objc.message;
+import dstep.objc.runtime;
+
+import mambo.io;
+
+alias objc_object* id;
+alias objc_class* Class;
+alias objc_selector* SEL;
+alias extern (C) id function(id self, SEL op, ...) IMP;
+alias bool BOOL;
+alias char* STR;
+
+alias typeof(null) Nil;
+alias typeof(null) nil;
+
+alias c_long arith_t;
+alias c_ulong uarith_t;
+
+const bool YES = true;
+const bool NO = false;
+
+struct objc_object
+{
+	Class isa;
+	
+	
+	
+	// D Extensions:
+	
+	string getClassName ()
+	{
+		return fromStringz(bindings.object_getClassName(this));
+	}
+	
+	Ivar setInstanceVariable (T, string name) (T value)
+	{
+		return bindings.object_setInstanceVariable(this, name.ptr, value);
+	}
+	
+	Ivar getInstanceVariable (T, string name) (out T outValue)
+	{
+		return bindings.object_getInstanceVariable(this, name.ptr, &outValue);
+	}
+	
+	objc_property_t* getProperty (string name, bool isRequiredProperty, bool isInstanceProperty)
+	{
+		return bindings.protocol_getProperty(this, name.toStringz(), isRequiredProperty, isInstanceProperty);
+	}
+
+	objc_property_t* copyPropertyList (out uint outCount)
+	{
+		return bindings.protocol_copyPropertyList(this, &outCount);
+	}
+
+	Protocol** copyProtocolList (out uint outCount)
+	{
+		return bindings.protocol_copyProtocolList(this, &outCount);
+	}
+	
+	string getName ()
+	{
+		return fromStringz(bindings.protocol_getName(this));
+	}
+	
+	objc_method_description* copyMethodDescriptionList (bool isRequiredMethod, bool isInstanceMethod, out uint outCount)
+	{
+		return bindings.protocol_copyMethodDescriptionList(this, isRequiredMethod, isInstanceMethod, &outCount);
+	}
+	
+	id copy (size_t size)
+	{
+		return bindings.object_copy(this, size);
+	}
+	
+	id dispose ()
+	{
+		return bindings.object_dispose(this);
+	}
+	
+	Class getClass ()
+	{
+		return bindings.object_getClass(this);
+	}
+	
+	Class setClass (Class cls)
+	{
+		return bindings.object_setClass(this, cls);
+	}
+	
+	void* getIndexedIvars ()
+	{
+		return bindings.object_getIndexedIvars(this);
+	}
+	
+	id getIvar (Ivar ivar)
+	{
+		return bindings.object_getIvar(this, ivar);
+	}
+	
+	void setIvar (Ivar ivar, Protocol* value)
+	{
+		return bindings.object_setIvar(this, ivar, value);
+	}
+	
+	bool conformsToProtocol (Protocol* other)
+	{
+		return bindings.protocol_conformsToProtocol(this, other);
+	}
+	
+	bool isEqual (id other)
+	{
+		return bindings.protocol_isEqual(this, other);
+	}
+	
+	objc_method_description getMethodDescription (SEL aSel, bool isRequiredMethod, bool isInstanceMethod)
+	{
+		return bindings.protocol_getMethodDescription(this, aSel, isRequiredMethod, isInstanceMethod);
+	}
+	
+	
+	
+	// message.h
+
+	R msgSend (R = id, ARGS...) (SEL op, ARGS args)
+	{
+		return (cast(R function (id, SEL, ARGS))&bindings.objc_msgSend)(this, op, args);
+	}
+
+	void msgSend_stret (T, ARGS...) (out T stretAddr, SEL op, ARGS args)
+	{
+		if (T.sizeof > STRUCT_SIZE_LIMIT)
+			(cast(void function (T*, id, SEL, ARGS...))&bindings.objc_msgSend_stret)(&stretAddr, this, op, args);			
+		    
+		else
+			stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSend)(this, op, args);  
+	}
+
+	static if (dstep.internal.Version.X86 || X86_64)
+	{
+		R msgSend_fpret (R = id, ARGS...) (SEL op, ARGS args)
+		{
+			version (X86_64)
+				static assert(!is(R == real), "dstep.objc.objc.objc_object.msgSend_fpret: Only real are legal return value for objc_msgSend_fpret");
+			
+			else
+				static assert(!is(R == double) && !is(R == float), "dstep.objc.objc.objc_object.msgSend_fpret: Only double and float are legal return values for objc_msgSend_fpret");
+				
+			return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSend_fpret)(this, op, args);
+		}
+	}
+
+	R invoke (R = id, ARGS...) (Method m, ARGS args)
+	{
+		return (cast(R function (id, SEL, ARGS...))&bindings.method_invoke)(this, m, args);
+	}
+
+	void invoke_stret (ARGS...) (Method m, ARGS args)
+	{
+		return (cast(R function (id, SEL, ARGS...))&bindings.method_invoke_stret)(this, m, args);
+	}
+
+	R msgSendv (R = id, T) (SEL op, size_t arg_size, T arg_frame)
+	{
+		(cast(R function (id, SEL, size_t, T))&bindings.objc_msgSendv)(this, op, arg_size, arg_frame);
+	}
+
+	void msgSendv_stret (R = id, T) (out T stretAddr, SEL op, size_t arg_size, T arg_frame)
+	{
+	    if (R.sizeof > STRUCT_SIZE_LIMIT)
+			(cast(void function (R*, id, SEL, size_t, T))&bindings.objc_msgSendv_stret)(&stretAddr, this, op, arg_size, arg_frame);
+	    
+	    else
+	        stretAddr = (*cast(R function (id, SEL, size_t, T))&bindings.objc_msgSendv)(this, op, arg_size, arg_frame);
+	}
+
+	version (X86)
+	{
+		R msgSendv_fpret (R = id, T) (SEL op, uint arg_size, T arg_frame)
+		{
+			static assert(!is(R == double) && !is(R == float), "dstep.objc.objc.objc_object.msgSend_fpret: Only double and float are legal return values for objc_msgSendv_fpret");
+			return (cast(R function (id, SEL, uint, T))&bindings.objc_msgSendv_fpret)(this, op, arg_size, arg_frame);
+		}
+	}
+}
+
+struct objc_selector
+{
+	void* sel_id;
+	char* sel_types;
+	
+	
+	
+	// D Extensions:
+	
+	string getName ()
+	{
+		return fromStringz(bindings.sel_getName(this));
+	}
+	
+	bool isEqual (SEL rhs)
+	{
+		return bindings.sel_isEqual(this, rhs);
+	}
+	
+	bool isMapped ()
+	{
+		return bindings.sel_isMapped(this);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dstep/objc/runtime.d	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,896 @@
+/**
+ * Copyright: Copyright (c) 2009 Jacob Carlborg.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Feb 1, 2009
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module dstep.objc.runtime;
+
+import mambo.io;
+
+import dstep.internal.String;
+import dstep.internal.Types;
+import dstep.internal.Version;
+import bindings = dstep.objc.bindings;
+import dstep.objc.message;
+import dstep.objc.objc;
+
+alias objc_method* Method;
+alias objc_ivar* Ivar;
+alias objc_category* Category;
+alias void* objc_property;
+alias objc_property* objc_property_t;
+alias objc_object Protocol;
+alias objc_symtab* Symtab;
+alias objc_cache* Cache;
+
+const char _C_ID = '@';
+const char _C_CLASS = '#';
+const char _C_SEL = ':';
+const char _C_CHR = 'c';
+const char _C_UCHR = 'C';
+const char _C_SHT = 's';
+const char _C_USHT = 'S';
+const char _C_INT = 'i';
+const char _C_UINT = 'I';
+const char _C_LNG = 'l';
+const char _C_ULNG = 'L';
+const char _C_LNG_LNG = 'q';
+const char _C_ULNG_LNG = 'Q';
+const char _C_FLT = 'f';
+const char _C_DBL = 'd';
+const char _C_BFLD = 'b';
+const char _C_BOOL = 'B';
+const char _C_VOID = 'v';
+const char _C_UNDEF = '?';
+const char _C_PTR = '^';
+const char _C_CHARPTR = '*';
+const char _C_ATOM = '%';
+const char _C_ARY_B = '[';
+const char _C_ARY_E = ']';
+const char _C_UNION_B = '(';
+const char _C_UNION_E = ')';
+const char _C_STRUCT_B = '{';
+const char _C_STRUCT_E = '}';
+const char _C_VECTOR = '!';
+const char _C_CONST = 'r';
+
+struct objc_class
+{
+    Class isa;
+    Class super_class;
+    /*const*/ char* name;
+    c_long version_;
+    c_long info;
+    c_long instance_size;
+    objc_ivar_list* ivars;
+    objc_method_list** methodLists;
+    objc_cache* cache;
+    objc_protocol_list* protocols;
+    
+    
+    
+    // D Extensions:
+    
+	void setFutureClass (string name) ()
+	{
+		bindings.objc_setFutureClass(this, name.ptr);
+	}
+	
+	string getName ()
+	{
+		return fromStringz(bindings.class_getName(this));
+	}
+	
+	Ivar getInstanceVariable (string name) ()
+	{
+		return bindings.class_getInstanceVariable(this, name.ptr);
+	}
+
+	Ivar getClassVariable (string name) ()
+	{
+		return bindings.class_getClassVariable(this, name.ptr);
+	}
+	
+	Ivar[] copyIvarList ()
+	{
+		uint outCount;
+		
+		Ivar* list = bindings.class_copyIvarList(this, &outCount);
+		
+		if (list)
+			return list[0 .. outCount];
+		
+		return null;
+	}
+	
+	Method[] copyMethodList ()
+	{
+		uint outCount;
+		
+		Method* list = bindings.class_copyMethodList(this, &outCount);
+		
+		if (list)
+			return list[0 .. outCount];
+		
+		return null;
+	}
+	
+	Protocol*[] copyProtocolList ()
+	{
+		uint outCount;
+		
+		Protocol** list = bindings.class_copyProtocolList(this, &outCount);
+		
+		if (list)
+			return list[0 .. outCount];
+		
+		return null;
+	}
+	
+	string getIvarLayout ()
+	{
+		return fromStringz(bindings.class_getIvarLayout(this));
+	}
+	
+	string getWeakIvarLayout ()
+	{
+		return fromStringz(bindings.class_getWeakIvarLayout(this));
+	}
+	
+	Class duplicateClass (string name) (size_t extraBytes)
+	{
+		return bindings.objc_duplicateClass(this, name.ptr, extraBytes);
+	}
+	
+	bool addMethod (string types) (SEL name, IMP imp)
+	{
+		return bindings.class_addMethod(this, name, imp, types.ptr);
+	}
+	
+	IMP replaceMethod (string types) (SEL name, IMP imp)
+	{
+		return bindings.class_replaceMethod(this, name, imp, types.ptr);
+	}
+	
+	bool addIvar (string name, string types) (size_t size, ubyte alignment)
+	{
+		return bindings.class_addIvar(this, name.ptr, size, alignment, types.ptr);
+	}
+	
+	void setIvarLayout (string layout) ()
+	{
+		bindings.class_setIvarLayout(this, layout.ptr);
+	}
+	
+	void setWeakIvarLayout (string layout) ()
+	{
+		bindings.class_setWeakIvarLayout(this, layout.ptr);
+	}
+
+	objc_property_t* getProperty (string name) ()
+	{
+		return bindings.class_getProperty(this, name.ptr);
+	}
+	
+	string getImageName ()
+	{
+		return fromStringz(bindings.class_getImageName(this));
+	}
+	
+	bool isMetaClass ()
+	{
+		return bindings.class_isMetaClass(this);
+	}
+	
+	Class getSuperclass ()
+	{
+		return bindings.class_getSuperclass(this);
+	}
+	
+	Class setSuperClass (Class newSuper)
+	{
+		return bindings.class_setSuperclass(this, newSuper);
+	}
+	
+	int getVersion ()
+	{
+		return bindings.class_getVersion(this);
+	}
+	
+	void serVersion (int version_)
+	{
+		return bindings.class_setVersion(this, version_);
+	}
+	
+	size_t getInstanceSize ()
+	{
+		return bindings.class_getInstanceSize(this);
+	}
+	
+	Method getInstanceMethod (SEL name)
+	{
+		return bindings.class_getInstanceMethod(this, name);
+	}
+	
+	Method getClassMethod (SEL name)
+	{
+		return bindings.class_getClassMethod(this, name);
+	}
+	
+	IMP getMethodImplementation (SEL name)
+	{
+		return bindings.class_getMethodImplementation(this, name);
+	}
+	
+	IMP getMethodImplementation_stret (SEL name)
+	{
+		return bindings.class_getMethodImplementation_stret(this, name);
+	}
+	
+	bool respondsToSelector (SEL sel)
+	{
+		return bindings.class_respondsToSelector(this, sel);
+	}
+	
+	bool conformsToProtocol (Protocol* protocol)
+	{
+		return bindings.class_conformsToProtocol(this, protocol);
+	}
+	
+	void addProtocol (Protocol* protocol)
+	{
+		return bindings.class_addProtocol(this, protocol);
+	}
+	
+	id createInstanceFromZone (size_t idxIvars, void* z)
+	{
+		return bindings.class_createInstanceFromZone(this, idxIvars, z);
+	}
+	
+	void addMethods (objc_method_list* methodList)
+	{
+		return.class_addMethods(this, methodList);
+	}
+	
+	void removeMethods (objc_method_list* methodList)
+	{
+		return bindings.class_removeMethods(this, methodList);
+	}
+	
+	Class poseAs (Class original)
+	{
+		return bindings.class_poseAs(this, original);
+	}
+	
+	bool respondsToMethod (SEL sel)
+	{
+		return bindings.class_respondsToMethod(this, sel);
+	}
+	
+	objc_method_list* class_nextMethodList (void* arg)
+	{
+		return bindings.class_nextMethodList(this, arg);
+	}
+}
+
+struct objc_method_description
+{
+	SEL name;
+	char* types;
+}
+
+struct objc_method_description_list
+{
+	int count;
+	objc_method_description[1] list;
+}
+
+struct objc_protocol_list
+{
+	objc_protocol_list* next;
+	c_long count;
+	Protocol*[1] list;
+}
+
+struct objc_category
+{
+	char* category_name;
+	char* class_name;
+	objc_method_list* instance_methods;
+	objc_method_list* class_methods;
+	objc_protocol_list* protocols;
+}
+
+struct objc_ivar
+{
+    char* ivar_name;
+    char* ivar_type;
+    int ivar_offset;
+    
+    static if (D_LP64)
+    	int space;
+    
+    
+    
+    // D Extensions:
+    
+	string getName ()
+	{
+		return fromStringz(bindings.ivar_getName(this));
+	}
+
+	string getTypeEncoding ()
+	{
+		return fromStringz(bindings.ivar_getTypeEncoding(this));
+	}
+	
+	ptrdiff_t getOffset ()
+	{
+		return bindings.ivar_getOffset(this);
+	}
+}
+
+struct objc_ivar_list
+{
+    int ivar_count;
+    
+    static if (D_LP64)
+    	int space;
+    
+    /* variable length structure */
+    objc_ivar[1] ivar_list;
+}
+
+struct objc_method
+{
+    SEL method_name;
+    char* method_types;
+    IMP method_imp;
+    
+    
+    
+    // D Extensions:
+    
+	/*uint getArgumentInfo (string[] type) (int arg, int* offset)
+	{
+		char*[] arr;
+		arr.length = type.length;
+		
+		foreach (i, str ; type)
+			arr[i] = str.ptr;
+		
+		return bindings.method_getArgumentInfo(this, arg, arr.ptr, offset);
+	}*/
+	
+	string getTypeEncoding ()
+	{
+		return fromStringz(bindings.method_getTypeEncoding(this));
+	}
+	
+	string copyReturnType ()
+	{
+		return fromStringz(bindings.method_copyReturnType(this));
+	}
+
+	string copyArgumentType (uint index)
+	{
+		return fromStringz(bindings.method_copyArgumentType(this, index));
+	}
+
+	void getReturnType (string dst, size_t dst_len)
+	{
+		bindings.method_getReturnType(this, dst.toStringz(), dst_len);
+	}
+
+	void getArgumentType (uint index, string dst, size_t dst_len)
+	{
+		bindings.method_getArgumentType(this, index, dst.toStringz(), dst_len);
+	}
+	
+	SEL getName ()
+	{
+		return bindings.method_getName(this);
+	}
+	
+	IMP getImplementation ()
+	{
+		return bindings.method_getImplementation(this);
+	}
+	
+	uint getNumberOfArguments ()
+	{
+		return bindings.method_getNumberOfArguments(this);
+	}
+	
+	objc_method_description* getDescription ()
+	{
+		return bindings.method_getDescription(this);
+	}
+	
+	IMP setImplementation (IMP imp)
+	{
+		return bindings.method_setImplementation(this, imp);
+	}
+	
+	void exchangeImplementations (Method m2)
+	{
+		bindings.method_exchangeImplementations(this, m2);
+	}
+	
+	uint getSizeOfArguments ()
+	{
+		return bindings.method_getSizeOfArguments(this);
+	}
+}
+
+struct objc_method_list
+{
+    objc_method_list* obsolete;
+    
+    int method_count;
+    
+    static if (D_LP64)
+    	int space;
+    
+    /* variable length structure */
+    objc_method method_list[1];
+}
+
+struct objc_symtab
+{
+	c_ulong sel_ref_cnt;
+	SEL* refs;
+	ushort cls_def_cnt;
+	ushort cat_def_cnt;
+	void*[1] defs;
+}
+
+struct objc_cache
+{
+    uint mask /* total = mask + 1 */;
+    uint occupied;
+    Method[1] buckets;
+}
+
+struct objc_module
+{
+	c_ulong version_;
+	c_ulong size;
+	char* name;
+	Symtab symtab;
+}
+
+string object_getClassName (id obj)
+{
+	return fromStringz(bindings.object_getClassName(obj));
+}
+
+Ivar object_setInstanceVariable (T) (id obj, string name, T value)
+{
+	return bindings.object_setInstanceVariable(obj, name.toStringz(), value);
+}
+
+Ivar object_getInstanceVariable (T) (id obj, string name, out T outValue)
+{
+	return bindings.object_getInstanceVariable(obj, name.toStringz(), &outValue);
+}
+
+id objc_getClass (string name)
+{
+	return bindings.objc_getClass(name.toStringz());
+}
+
+id objc_getMetaClass (string name)
+{
+	return bindings.objc_getMetaClass(name.toStringz());
+}
+
+id objc_lookUpClass (string name)
+{
+	return bindings.objc_lookUpClass(name.toStringz());
+}
+
+id objc_getRequiredClass (string name)
+{
+	return bindings.objc_getRequiredClass(name.toStringz());
+}
+
+Class objc_getFutureClass (string name)
+{
+	return bindings.objc_getFutureClass(name.toStringz());
+}
+
+void objc_setFutureClass (Class cls, string name)
+{
+	bindings.objc_setFutureClass(cls, name.toStringz());
+}
+
+id objc_getProtocol (string name)
+{
+	return bindings.objc_getProtocol(name.toStringz());
+}
+
+Protocol** objc_copyProtocolList (out uint outCount)
+{
+	return bindings.objc_copyProtocolList(&outCount);
+}
+
+string class_getName (Class cls)
+{
+	return fromStringz(bindings.class_getName(cls));
+}
+
+Ivar class_getInstanceVariable (Class cls, string name)
+{
+	return bindings.class_getInstanceVariable(cls, name.toStringz());
+}
+
+Ivar class_getClassVariable (Class cls, string name)
+{
+	return bindings.class_getClassVariable(cls, name.toStringz());
+}
+
+Ivar* class_copyIvarList (Class cls, out uint outCount)
+{
+	return bindings.class_copyIvarList(cls, &outCount);
+}
+
+Method* class_copyMethodList (Class cls, out uint outCount)
+{
+	return bindings.class_copyMethodList(cls, &outCount);
+}
+
+Protocol** class_copyProtocolList (Class cls, out uint outCount)
+{
+	return bindings.class_copyProtocolList(cls, &outCount);
+}
+
+objc_property_t* class_getProperty (Class cls, string name)
+{
+	return bindings.class_getProperty(cls, name.toStringz());
+}
+
+objc_property_t* class_copyPropertyList (Class cls, out uint outCount)
+{
+	return bindings.class_copyPropertyList(cls, &outCount);
+}
+
+string class_getIvarLayout (Class cls)
+{
+	return fromStringz(bindings.class_getIvarLayout(cls));
+}
+
+string class_getWeakIvarLayout (Class cls)
+{
+	return fromStringz(bindings.class_getWeakIvarLayout(cls));
+}
+
+Class objc_allocateClassPair (Class superclass, string name, size_t extraBytes)
+{
+	return bindings.objc_allocateClassPair(superclass, name.toStringz(), extraBytes);
+}
+
+Class objc_duplicateClass (Class original, string name, size_t extraBytes)
+{
+	return bindings.objc_duplicateClass(original, name.toStringz(), extraBytes);
+}
+
+bool class_addMethod (Class cls, SEL name, IMP imp, string types)
+{
+	return bindings.class_addMethod(cls, name, imp, types.toStringz());
+}
+
+IMP class_replaceMethod (Class cls, SEL name, IMP imp, string types)
+{
+	return bindings.class_replaceMethod(cls, name, imp, types.toStringz());
+}
+
+bool class_addIvar (Class cls, string name, size_t size, ubyte alignment, string types)
+{
+	return bindings.class_addIvar(cls, name.toStringz(), size, alignment, types.toStringz());
+}
+
+void class_setIvarLayout (Class cls, string layout)
+{
+	bindings.class_setIvarLayout(cls, layout.toStringz());
+}
+
+void class_setWeakIvarLayout (Class cls, string layout)
+{
+	bindings.class_setWeakIvarLayout(cls, layout.toStringz());
+}
+
+string method_getTypeEncoding (Method m)
+{
+	return fromStringz(bindings.method_getTypeEncoding(m));
+}
+
+string method_copyReturnType (Method m)
+{
+	return fromStringz(bindings.method_copyReturnType(m));
+}
+
+string method_copyArgumentType (Method m, uint index)
+{
+	return fromStringz(bindings.method_copyArgumentType(m, index));
+}
+
+void method_getReturnType (Method m, string dst, size_t dst_len)
+{
+	bindings.method_getReturnType(m, dst.toStringz(), dst_len);
+}
+
+void method_getArgumentType (Method m, uint index, string dst, size_t dst_len)
+{
+	bindings.method_getArgumentType(m, index, dst.toStringz(), dst_len);
+}
+
+string ivar_getName (Ivar v)
+{
+	return fromStringz(bindings.ivar_getName(v));
+}
+
+string ivar_getTypeEncoding (Ivar v)
+{
+	return fromStringz(bindings.ivar_getTypeEncoding(v));
+}
+
+string property_getName (objc_property_t* property)
+{
+	return fromStringz(bindings.property_getName(property));
+}
+
+string property_getAttributes (objc_property_t* property)
+{
+	return fromStringz(bindings.property_getAttributes(property));
+}
+
+string protocol_getName (id p)
+{
+	return fromStringz(bindings.protocol_getName(p));
+}
+
+objc_method_description* protocol_copyMethodDescriptionList(id p, bool isRequiredMethod, bool isInstanceMethod, out uint outCount)
+{
+	return bindings.protocol_copyMethodDescriptionList(p, isRequiredMethod, isInstanceMethod, &outCount);
+}
+
+objc_property_t* protocol_getProperty (id proto, string name, bool isRequiredProperty, bool isInstanceProperty)
+{
+	return bindings.protocol_getProperty(proto, name.toStringz(), isRequiredProperty, isInstanceProperty);
+}
+
+objc_property_t* protocol_copyPropertyList (id proto, out uint outCount)
+{
+	return bindings.protocol_copyPropertyList(proto, &outCount);
+}
+
+Protocol** protocol_copyProtocolList (id proto, out uint outCount)
+{
+	return bindings.protocol_copyProtocolList(proto, &outCount);
+}
+
+static string[] objc_copyImageNames (out uint outCount)
+{
+	string[] ret;
+	
+	char** result = bindings.objc_copyImageNames(&outCount);
+	ret.length = outCount;
+	
+	for (size_t i = 0; i < outCount; i++)
+		ret[i] = fromStringz(result[i]);
+	
+	return ret;
+}
+
+string class_getImageName (Class cls)
+{
+	return fromStringz(bindings.class_getImageName(cls));
+}
+
+string[] objc_copyClassNamesForImage (string image, out uint outCount)
+{
+	string[] ret;
+	
+	char** result = bindings.objc_copyClassNamesForImage(image.toStringz(), &outCount);
+	ret.length = outCount;
+	
+	for (size_t i = 0; i < outCount; i++)
+		ret[i] = fromStringz(result[i]);
+	
+	return ret;
+}
+
+string sel_getName (SEL sel)
+{
+	return fromStringz(bindings.sel_getName(sel));
+}
+
+SEL sel_getUid (string str)
+{
+	return bindings.sel_getUid(str.toStringz());
+}
+
+SEL sel_registerName (string str)
+{
+	return bindings.sel_registerName(str.toStringz());
+}
+
+uint method_getArgumentInfo (objc_method* m, int arg, string[] type, int* offset)
+{
+	char*[] arr;
+	arr.length = type.length;
+	
+	foreach (i, str ; type)
+		arr[i] = str.toStringz();
+	
+	return bindings.method_getArgumentInfo(m, arg, arr.ptr, offset);
+}
+
+Class objc_getOrigClass (string name)
+{
+	return bindings.objc_getOrigClass(name.toStringz());
+}
+
+alias bindings.object_copy object_copy;
+alias bindings.object_dispose object_dispose;
+alias bindings.object_getClass object_getClass;
+alias bindings.object_setClass object_setClass;
+alias bindings.object_getIndexedIvars object_getIndexedIvars;
+alias bindings.object_getIvar object_getIvar;
+alias bindings.object_setIvar object_setIvar;
+alias bindings.objc_getClassList objc_getClassList;
+alias bindings.class_isMetaClass class_isMetaClass;
+alias bindings.class_getSuperclass class_getSuperclass;
+alias bindings.class_setSuperclass class_setSuperclass;
+alias bindings.class_getVersion class_getVersion;
+alias bindings.class_setVersion class_setVersion;
+alias bindings.class_getInstanceSize class_getInstanceSize;
+alias bindings.class_getInstanceMethod class_getInstanceMethod;
+alias bindings.class_getClassMethod class_getClassMethod;
+alias bindings.class_getMethodImplementation class_getMethodImplementation;
+alias bindings.class_getMethodImplementation_stret class_getMethodImplementation_stret;
+alias bindings.class_respondsToSelector class_respondsToSelector;
+alias bindings.class_conformsToProtocol class_conformsToProtocol;
+alias bindings.class_createInstance class_createInstance;
+alias bindings.objc_registerClassPair objc_registerClassPair;
+alias bindings.objc_disposeClassPair objc_disposeClassPair;
+alias bindings.class_addProtocol class_addProtocol;
+alias bindings.method_getName method_getName;
+alias bindings.method_getImplementation method_getImplementation;
+alias bindings.method_getNumberOfArguments method_getNumberOfArguments;
+alias bindings.method_getDescription method_getDescription;
+alias bindings.method_setImplementation method_setImplementation;
+alias bindings.method_exchangeImplementations method_exchangeImplementations;
+alias bindings.ivar_getOffset ivar_getOffset;
+alias bindings.protocol_conformsToProtocol protocol_conformsToProtocol;
+alias bindings.protocol_isEqual protocol_isEqual;
+alias bindings.protocol_getMethodDescription protocol_getMethodDescription;
+alias bindings.sel_isEqual sel_isEqual;
+alias bindings.objc_enumerationMutation objc_enumerationMutation;
+alias bindings.objc_setForwardHandler objc_setForwardHandler;
+alias bindings.sel_isMapped sel_isMapped;
+alias bindings.object_copyFromZone object_copyFromZone;
+alias bindings.object_realloc object_realloc;
+alias bindings.object_reallocFromZone object_reallocFromZone;
+alias bindings.objc_getClasses objc_getClasses;
+alias bindings.objc_addClass objc_addClass;
+alias bindings.objc_setMultithreaded objc_setMultithreaded;
+alias bindings.class_createInstanceFromZone class_createInstanceFromZone;
+alias bindings.class_addMethods class_addMethods;
+alias bindings.class_removeMethods class_removeMethods;
+alias bindings.class_poseAs class_poseAs;
+alias bindings.method_getSizeOfArguments method_getSizeOfArguments;
+alias bindings.class_respondsToMethod class_respondsToMethod;
+alias bindings.class_lookupMethod class_lookupMethod;
+alias bindings.class_nextMethodList class_nextMethodList;
+
+
+
+
+
+
+
+
+// D Extensions:
+
+struct objc
+{	
+	static string[] copyImageNames (out uint outCount)
+	{
+		string[] ret;
+		
+		char** result = bindings.objc_copyImageNames(&outCount);
+		ret.length = outCount;
+		
+		for (size_t i = 0; i < outCount; i++)
+			ret[i] = fromStringz(result[i]);
+		
+		return ret;
+	}
+	
+	alias bindings.objc_enumerationMutation objc_enumerationMutation;
+	alias bindings.objc_setForwardHandler objc_setForwardHandler;
+	alias bindings.objc_setMultithreaded objc_setMultithreaded;
+	
+	static id getClass (string name) ()
+	{
+		return bindings.objc_getClass(name.ptr);
+	}
+	
+	static id getMetaClass (string name) ()
+	{
+		return bindings.objc_getMetaClass(name.ptr);
+	}
+	
+	static id lookUpClass (string name) ()
+	{
+		return bindings.objc_lookUpClass(name.ptr);
+	}
+	
+	static id getRequiredClass (string name) ()
+	{
+		return bindings.objc_getRequiredClass(name.ptr);
+	}	
+	
+	static Class getFutureClass (string name) ()
+	{
+		return bindings.objc_getFutureClass(name.ptr);
+	}
+	
+	static string[] objc_copyClassNamesForImage (string image) (out uint outCount)
+	{
+		string[] ret;
+		
+		char** result = bindings.objc_copyClassNamesForImage(image.ptr, &outCount);
+		ret.length = outCount;
+		
+		for (size_t i = 0; i < outCount; i++)
+			ret[i] = fromStringz(result[i]);
+		
+		return ret;
+	}
+	
+	static Class objc_getOrigClass (string name) ()
+	{
+		return bindings.objc_getOrigClass(name.ptr);
+	}
+	
+	static Class allocateClassPair (string name) (Class superclass, size_t extraBytes)
+	{
+		return bindings.objc_allocateClassPair(superclass, name.ptr, extraBytes);
+	}
+	
+	alias bindings.objc_registerClassPair registerClassPair;
+	alias bindings.objc_disposeClassPair disposeClassPair;
+	alias bindings.objc_getClasses getClasses;
+	alias bindings.objc_addClass addClass;
+	alias bindings.class_createInstance createInstance;
+}
+
+struct property
+{
+	static string property_getName (objc_property_t* property)
+	{
+		return fromStringz(bindings.property_getName(property));
+	}
+
+	static string property_getAttributes (objc_property_t* property)
+	{
+		return fromStringz(bindings.property_getAttributes(property));
+	}
+}
+
+struct sel
+{	
+	static SEL getUid (string str) ()
+	{
+		return bindings.sel_getUid(str.ptr);
+	}
+	
+	static SEL registerName (string str) ()
+	{
+		return bindings.sel_registerName(str.ptr);
+	}
+}
\ No newline at end of file
--- a/sciprts/dgen.rb	Sat Jan 31 17:22:44 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1349 +0,0 @@
-#!/usr/bin/env ruby
-
-##
-# Copyright:: Copyright (c) 2009 Jacob Carlborg. All rights reserved.
-# Author:: Jacob Carlborg
-# Version:: Initial created: 2009
-# License:: [revised BSD license]http://opensource.org/licenses/bsd-license.php or
-# 		    [Academic Free License v3.0]http://opensource.org/licenses/afl-3.0.php
-#
-
-require "rubygems"
-gem "xml-simple"
-require "xmlsimple"
-require "optparse"
-
-# Extensions to String
-class String	
-	
-	# Passes each character to the supplied block
-	#
-	# === Example:
-	# "str".each_char { |c| puts c }
-	# # outputs below
-	# s
-	# t
-	# r
-	#
-	def each_char
-		if block_given?
-			scan(/./m) do |x|
-				yield x
-			end
-		else
-			scan(/./m)
-		end
-	end
-	
-	# Indents the string
-	# levels:: how many levels/tabs to indent
-	# 
-	# === Example:
-	# "str".indent		#=>		str
-	# "str".indent(3)	#=>				str
-	# 
-	def indent (levels = 1)
-		"\t" * levels << self
-	end
-	
-	# Appends a semicolon and a newline character on the string
-	# semicolon:: should a semicolon be appended
-	#
-	# === Example:
-	# "str".nl
-	# "str".nl(false)
-	# # outputs below
-	# str;
-	#
-	# str
-	# 
-	# 
-	def nl (semicolon = true)
-		if semicolon
-			if self[-1, 1] == "{" || self[-1, 1] == "}"
-				self << "\n"
-			else
-				self << ";\n"
-			end
-		else
-			self << "\n"
-		end
-	end
-	
-	# Returns the index of the given character or length of the string if not found
-	# char:: the character to look for
-	# start:: the index where to start the search
-	# 
-	# === Example:
-	# "012345789".index_of("1")		#=> 1
-	# "0123 0123".index_of("3", 6)	#=> 8
-	# 
-	def index_of (char, start = 0)
-		return self.length if start >= self.length
-		
-		i = 0
-		
-		if start == 0
-			self.each_char do |c|
-				return i if char == c
-				i += 1			
-			end
-		else
-			self[start + 1 .. -1].each_char do |c|
-				return i + start + 1 if char == c
-				i += 1			
-			end
-		end
-		
-		return self.length
-	end
-	
-	# Returns true if the string is an Objective-C struct
-	# 
-	# === Example:
-	# "{?=ii}".struct?		#=> true
-	# 
-	def struct?
-		self =~ /\{/
-	end
-end
-
-# Extensions that adds support for member access syntax
-class Hash	
-	def type
-		result = self["type"]
-		return result unless result.nil?
-		self[:type]
-	end
-	
-	def type= (type)
-		self[:type] = type
-	end
-	
-	def id
-		result = self["id"]
-		return result unless result.nil?
-		self[:id]
-	end
-	
-	def id= (id)
-		self[:id] = id
-	end
-	
-	def methods
-		result = self["methods"]
-		return result unless result.nil?
-		self[:methods]
-	end
-	
-	def methods= (methods)
-		self[:methods] = methods
-	end
-	
-	def method
-		result = self["method"]
-		return result unless result.nil?
-		self[:method]
-	end
-	
-	def method= (method)
-		self[:method] = method
-	end
-	
-	def method_missing (method, *args)
-		self.class.instance_eval do
-			define_method(method) do |*args|
-				if args.length > 0
-					self[method[0 ... -1]] = args[0]
-					self[eval(":#{method}"[0 ... -1])] = args[0]
-				else
-					result = self[method]
-					return result unless result.nil?
-					self[eval(":#{method}")]
-				end
-			end
-		end
-		
-		if (method = method.id2name) =~ /=/
-			eval("self.#{method} (args.length < 2 ? args[0] : args)")
-		else
-			eval("self.#{method}")
-		end
-	end
-end
-
-# This Struct represents an Objective-C Framework
-Framework = Struct.new(:name, :files) do
-	def initialize
-		self.files = []
-		self.name = ""
-	end
-end
-
-# This Struct represents a C/Objective-C header
-HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :d_constants, :d_constants_static_this, :defines, 
-			  			:enums, :functions, :function_wrappers, :imports, :path, :structs, :typedefs) do
-	def initialize
-		self.name = ""
-		self.cftypes = []
-		self.constants = []
-		self.defines = []
-		self.enums = []
-		self.framework = ""
-		self.functions = []
-		self.function_wrappers = []
-		self.imports = []
-		self.path = ""
-		self.structs = []
-		self.typedefs = []
-	end	
-end
-
-# Performs the conversion of an xml metadata file to the D programming language
-class ObjcToD
-	FIRST_YEAR = "2009"
-	VERSION = 1.0
-	
-	attr_accessor :out_dir, :files
-	
-	# Creates a new instance of the ObjcToD class
-	def initialize
-		@classes = {}
-		@copyright = nil
-		@d_constants = []
-		@d_constants_static_this = []
-		@files = []
-		@frameworks = []
-		@function_wrappers = []
-		@headers = []
-		@package = "dstep"
-	end	
-	
-	# Generates the D code from the xml metadata
-	def generate_code
-		@files.each do |dstep_file|
-			xml = XmlSimple.xml_in(dstep_file)
-
-			unless xml.framework.nil?
-				frameworks = xml.framework
-
-				frameworks.each do |frame|
-					framework = Framework.new
-					framework.name = frame.name
-
-					frame.file.each do |file|
-						header = HeaderFile.new
-						header.name = file.name
-						header.constants = constants(file.constant) unless file.constant.nil?
-						header.d_constants = d_constants unless file.constant.nil?
-						header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
-						header.enums = enums(file.enum) unless file.enum.nil?
-						header.functions = functions(file.function) unless file.function.nil?
-						header.function_wrappers = function_wrappers unless file.function.nil?
-						header.imports = imports(file.import, file.name, framework.name) unless file.import.nil?
-						header.structs = structs(file.struct) unless file.struct.nil?
-
-						header.typedefs = typedefs(file.typedef) unless file.typedef.nil?
-
-						framework.files << header
-					end
-
-					@frameworks << framework
-				end
-			end
-
-			unless xml.file.nil?
-				files = xml.file
-
-				file.each do |file|
-					header = HeaderFile.new
-					header.name = file.name
-					header.constants = constants(file.constant) unless file.constant.nil?
-					header.d_constants = d_constants unless file.constant.nil?
-					header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
-					header.enums = enums(file.enum) unless file.enum.nil?
-					header.functions = functions(file.function) unless file.function.nil?
-					header.function_wrappers = function_wrappers unless file.function.nil?
-					header.imports = imports(file.import, file.name) unless file.import.nil?
-					header.structs = structs(file.struct) unless file.struct.nil?
-					header.typedefs = typedefs(file.typedef) unless file.typedef.nil?
-
-					@headers << header
-				end
-			end
-
-			unless xml["class"].nil?
-				classes(xml["class"])
-			end
-		end
-	end
-	
-	# Outputs the generate D code
-	def output_code
-		@frameworks.each do |framework|
-			framework_path = framework_path = "#{@out_dir}/#{@package}/#{framework.name}"
-			
-			FileUtils.mkdir_p(framework_path) unless File.exist?(framework_path)
-			
-			framework.files.each do |header|
-				file_path = "#{framework_path}/#{header.name}.d"
-				
-				File.open(file_path, "w") do |file|
-					file << copyright
-					file << "module #{@package}.#{framework.name}.#{header.name};"
-					file << header.imports.nl(false)
-					file << header.defines
-					file << header.typedefs
-					file << header.cftypes				
-					file << header.constants
-					file << header.d_constants
-					file << header.enums
-					file << header.structs
-					
-					unless header.d_constants_static_this.nil?
-						file << "static this ()".nl(false)
-						file << "{".nl(false)
-						file << header.d_constants_static_this
-						file << "}".nl(false).nl(false)
-					end
-					
-					classes = get_classes(header.name)
-					
-					classes.each do |clazz, value|
-						file << value.code.nl(false)
-						@classes.delete(clazz)
-					end
-					
-					file << header.functions
-					file << header.function_wrappers
-				end
-			end
-		end
-		
-		package_path = "#{@out_dir}/#{@package}"
-		FileUtils.mkdir_p(package_path) unless File.exist?(package_path)
-		
-		@headers.each do |header|
-			header_path = "#{package_path}/#{header.name}.d"
-			
-			File.open(header_path, "w") do |file|
-				file << copyright
-				file << "module #{@package}.#{framework.name}.#{header.name};"
-				file << header.imports.nl(false)
-				file << header.defines
-				file << header.typedefs
-				file << header.cftypes				
-				file << header.constants
-				file << header.d_constants
-				file << header.enums
-				file << header.structs
-				
-				unless header.d_constants_static_this.nil?
-					file << "static this ()".nl(false)
-					file << "{".nl(false)
-					file << header.d_constants_static_this
-					file << "}".nl(false).nl(false)
-				end
-				
-				classes = get_classes(header.name)
-				
-				classes.each do |clazz, value|
-					file << value.code.nl(false)
-					@classes.delete(clazz)
-				end
-
-				file << header.functions
-				file << header.functions_wrappers
-			end			
-		end
-		
-		@classes.each do |clazz, value|
-			class_path = "#{package_path}/#{clazz}.d"
-			
-			File.open(class_path, "w") do |file|
-				file << value.code unless value.nil?
-			end
-		end
-	end
-	
-	# Creates and returns the copyright header that is included in the top of every file
-	def copyright
-		return @copyright unless @copyright.nil?
-		
-		# Add an extra empty string in the begining because array indices begin with zero and months don't
-		months = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
-		initialt_year = "2009"
-				
-		str = StringIO.new
-		date = Date.today
-		current_year = date.year.to_s
-		year = initialt_year
-		initial_created = "#{months[date.month]} #{date.day}, #{initialt_year}"
-
-		year << "-" << current_year unless initialt_year == current_year
-
-		str << "/**\n"
-		str << " * Copyright: Copyright (c) #{year} Jacob Carlborg. All rights reserved.\n"
-		str << " * Authors: Jacob Carlborg\n"
-		str << " * Version: Initial created: #{initial_created} \n"
-		str << " * License: $(LINK2 http://opensource.org/licenses/bsd-license.php, revised BSD license) or <br />\n"
-		str << " *	    	$(LINK2 http://opensource.org/licenses/afl-3.0.php, Academic Free License v3.0)\n"
-		str << " */\n"
-		
-		@copyright = str.string
-	end	
-	
-	# Gets name of the framework that the given class belongs to
-	def get_framework (class_name)
-		@frameworks.each do |framework|
-			framework.files.each do |file|
-				return framework.name if file.name == class_name
-			end
-		end
-		
-		return []
-	end	
-	
-	# Gets the classes that belongs to the given file
-	def get_classes (name)		
-		classes = @classes.find_all do |clazz, value|
-			value.file == name
-		end
-		
-		return classes
-	end	
-	
-	# Generates the D code for the classes
-	def classes (classes)
-		classes.each do |clazz|
-			str = StringIO.new
-			
-			str << "class "
-			
-			if clazz == ""
-				str << clazz.name.nl(false)
-			else
-				str << clazz.name
-				str << " : "
-				str << clazz.parent.nl(false)
-			end			
-			
-			str << "{".nl(false)
-			str << methods(clazz.method, clazz.name)
-			str << "}".nl(false)
-			
-			@classes[clazz.name] ||= {}
-			@classes[clazz.name].code = str.string
-			framework = get_framework(clazz.file)
-			@classes[clazz.name].framework = framework unless framework.nil?
-			@classes[clazz.name].file = clazz.file
-		end
-	end
-	
-	# Generates the D code for the constants/globals
-	def constants (constants)
-		str = StringIO.new
-		
-		str << "extern (C)".nl(false)
-		str << "{".nl(false)
-		str << "extern".indent.nl(false)
-		str << "{".indent.nl(false)
-		
-		constants.each do |constant|
-			type = get_type(constant.type, constant["type64"], constant["declaredType"])
-			const = constant["const"] == "true"
-			
-			if constant.type == "@"				
-				@d_constants << { :name => constant.name.dup, :type => constant.declaredType.gsub("*", ""), :const => const }
-				
-				if const
-					str << "const id".indent(2)
-				else
-					str << "id".indent(2)
-				end
-				
-				str << " "
-				str << constant["name"]
-				str << "_".nl
-			else
-				if const
-					str << "const ".indent(2)
-					str << type
-				else
-					str << "id".indent(2)
-				end
-				
-				str << " "
-				str << constant["name"].nl
-			end
-		end
-		
-		str << "}".indent.nl(false)
-		str << "}".nl(false).nl(false)
-		
-		str.string
-	end
-	
-    # Generates the D code for the constants that D can't handle directly, like classes
-	def d_constants
-		str = StringIO.new
-		
-		@d_constants.each do |constant|
-			# Deep copy constant
-			c = constant.dup
-			c.name = c.name.dup
-			c.type = c.type.dup
-			
-			str << "const " if constant.const
-			str << constant.type
-			str << " "			
-			str << constant.name.nl
-			@d_constants_static_this << c
-		end
-		
-		str << "\n"
-		@d_constants.clear
-		str.string
-	end
-	
-	# Generates the D code for the constants the has to be in a "static this"
-	def d_constants_static_this
-		str = StringIO.new
-		
-		@d_constants_static_this.each do |constant|
-			str << constant.name.indent
-			str << " = new "
-			str << constant.type
-			str << "("
-			str << constant.name
-			str << "_)".nl
-		end
-		
-		@d_constants_static_this.clear
-		str.string
-	end	
-	
-	# Generates the D code for the enums
-	def enums (enums)
-		str = StringIO.new
-		
-		enums.each do |enum|
-			str << "enum"
-								
-			if enum["name"] == ""
-				str << "\n{".nl
-				
-				enum.member.each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
-					str << member.value
-					str << ",".nl(false) unless i == enum.member.length - 1
-				end				
-			else
-				str << enum["name"].nl
-				str << "{"
-				
-				enum["member"].each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
-					str << member.value
-					str << ",".nl(false) unless i == enum.member.length - 1
-				end
-			end
-			
-			str << "\n}".nl.nl(false)
-		end
-		
-		str.string
-	end
-	
-	# Generates the D code for the function/method args
-	def args (args, variadic, method = false)
-		return "" if args.nil?
-		
-		str = StringIO.new
-		if variadic
-			#p args
-		end
-		args.each do |arg|
-			
-			if method || arg.type != "@"
-				type = get_type(arg.type, arg.type64, arg.declaredType)
-			else
-				type = "id"
-			end
-			
-			str << type
-			str << " "
-			str << arg["name"]
-			str << ", "
-		end
-		
-		if variadic
-		else
-		end
-		
-		str << "..." if variadic
-		
-		return str.string if variadic
-		return str.string[0 ... -2] unless variadic
-	end
-	
-	# A helper function that generates the D code for the functions/methods
-	def build_function (function, method = false, static = false)
-		str = StringIO.new
-		variadic = function["variadic"] == "true"
-		return_type  = ""
-		args = ""
-		original_type = function.returnValue[0].type
-		
-		if !method && original_type == "@"
-			return_type = "id"
-		else
-			return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType)
-			args(function.arg, variadic) unless function.arg.nil?
-		end
-		
-		str << "static " if static
-		str << return_type
-		str << " "
-		str << function["name"]
-		str << " ("
-		str << args(function["arg"], variadic, method)				
-		str << ")".nl
-		
-		str.string		
-	end
-	
-	# Generates the D code for the functions
-	def functions (functions)
-		str = StringIO.new
-		
-		str << "extern (C)".nl(false)
-		str << "{".nl(false)
-		
-		functions.each do |function|
-			wrapper_needed = false
-			original_type = function["returnValue"][0].type
-			
-			if original_type == "@"
-				@function_wrappers << function
-				wrapper_needed = true
-			else
-				function["arg"].each do |arg|
-					if (arg.type || arg["type64"]) == "@"
-						@function_wrappers << function
-						wrapper_needed = true
-					end
-				end unless function["arg"].nil?
-			end
-			
-			return_type = get_type(function["returnValue"][0].type, function["returnValue"][0]["type64"], function["returnValue"][0]["declaredType"])
-			variadic = function["variadic"] == "true"			
-
-			str << functions_helper(function, wrapper_needed)
-		end
-		
-		str << "}".nl(false).nl(false)
-		str.string
-	end
-	
-	# A helper function that generates the D code for the functions
-	def functions_helper (function, wrapper_needed)
-		str = StringIO.new
-
-		if wrapper_needed
-			declaration = build_function(function)
-			index = declaration.index_of(" ")
-			index = declaration.index_of(" ", index)
-			str << (declaration[0 ... index] + "_" + declaration[index .. -1]).indent
-		else
-			str << build_function(function).indent
-		end
-
-		str.string
-	end	
-	
-	# Generates the D code for the functions that D can't handle without wrappers, like functions that takes
-	# objects as arguments or returns an object
-	def function_wrappers
-		str = StringIO.new
-		
-		@function_wrappers.each do |function|
-			original_type = function["returnValue"][0].type
-			variadic = function["variadic"] == "true"
-			args = StringIO.new
-			out_args = []
-			return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType)
-			
-			function["arg"].each do |arg|
-				args << arg["name"]
-				
-				if arg.type == "@"
-					args << " !is null ? "
-					args << arg["name"]
-					args << ".id : null"
-				elsif arg.type == "^@"
-					type = get_type(arg.type, arg["type64"], arg["declaredType"])
-					out_args << { :type => type[4 .. -1], :name => arg["name"] }
-					
-					args << " &"
-					args << arg["name"]
-					args << "_.id"
-				end
-				
-				args << ", "
-			end unless function["arg"].nil?
-			
-			str << build_function(function, true)[0 ... -2].nl(false)
-			str << "{".nl(false)
-			
-			out_args.each do |arg|
-				str << arg.type.indent
-				str << " "
-				str << arg.name
-				str << "_ = new "
-				str << arg.type
-				str << "(false, false)".nl
-			end
-			
-			str << "\n" if out_args.length > 0
-			
-			if original_type == "@"
-				str << "id result = ".indent
-				str << function["name"]
-			elsif original_type != "v"
-				if out_args.length > 0					
-					str << return_type.indent				
-					str << " result = "
-				else
-					str << "return ".indent
-				end
-			end
-			
-			if original_type == "v"
-				str << function["name"].indent
-			elsif original_type != "@"
-				str << "cast("
-				str << return_type
-				str << ") "
-				str << function["name"]
-			end
-			
-			str << "_"
-			str << "("			
-			str << args.string[0 ... -2] unless function["arg"].nil?
-			str << ")".nl
-			str << "\n" if out_args.length > 0
-			
-			out_args.each do |arg|
-				str << arg.name.indent(2)
-				str << " = "
-				str << arg.name
-				str << "_".nl
-			end
-			
-			if out_args.length > 0
-				str << "\n"
-				str << "return result".indent unless original_type == "v"				
-			end
-
-			if original_type == "@"
-				str << "return result !is null ? new ".indent
-				str << return_type				
-				str << "(result)".nl
-			elsif original_type != "v" && out_args.length > 0
-				str << "".nl
-			end
-			
-			str << "}".nl(false).nl(false)
-		end
-		
-		@function_wrappers.clear		
-		str.string[0 ... -2]
-	end
-	
-	# Generates the D code for the imports
-	def imports (imports, filename, framework_name = nil)
-		str = StringIO.new
-		
-		imports.each do |import|			
-			str << "import #{@package}."
-			str << import.gsub("/", ".").gsub("Frameworks", "").gsub(".framework", "").gsub("Headers", "").gsub(/\.{2,}/, ".").nl
-		end
-		
-		str << "\n\n"
-		str = str.string.sort.to_s		
-		
-		return "\n\npublic:" << str if filename == framework_name
-		return str
-	end
-	
-	# Generates the D code for the methods
-	def methods (methods, class_name)
-		str = StringIO.new
-		
-		str << "this (bool init = true, bool alloc = true)".indent.nl(false)
-		str << "{".indent.nl(false)
-		str << "if (alloc && init)".indent(2).nl(false)
-		str << "{".indent(2).nl(false)
-		str << "id result = objc_msgSend(class_#{class_name}, sel_alloc)".indent(3).nl
-		str << "id result2".indent(3).nl.nl(false)
-		str << "if (result)".indent(3).nl(false)
-		str << "result2 = objc_msgSend(result, sel_init)".indent(4).nl.nl(false)
-		str << "if (result2)".indent(3).nl(false)
-		str << "this.id = result2".indent(4).nl.nl(false)
-		str << "else".indent(3).nl(false)
-		str << "this.id = result".indent(4).nl
-		str << "}".indent(2).nl(false).nl(false)
-		str << "else if (alloc)".indent(2).nl(false)
-		str << "this.id = objc_msgSend(this.id, sel_alloc)".indent(3).nl
-		str << "}".indent.nl(false).nl(false)
-		
-		str << "this (id object)".indent.nl(false)
-		str << "{".indent.nl(false)
-		str << "this.id = object".indent(2).nl
-		str << "}".indent.nl(false).nl(false)
-		
-		str << "this (id object)".indent.nl(false)
-		str << "{".indent.nl(false)
-		str << "this.id = object.id".indent(2).nl
-		str << "}".indent.nl(false).nl(false)
-		
-		str << "static #{class_name} alloc ()".indent.nl(false)
-		str << "{".indent.nl(false)
-		str << "id result = objc_msgSend(class_#{class_name}, sel_alloc)".indent(2).nl
-		str << "return result !is null ? new #{class_name}(result) : null".indent(2).nl
-		str << "}".indent.nl(false).nl(false)
-		
-		str << "#{class_name} init ()".indent.nl(false)
-		str << "{".indent.nl(false)
-		str << "id result = objc_msgSend(this.id, sel_init)".indent(2).nl
-		str << "return result is this.id ? this : (result !is null ? new #{class_name}(result) : null)".indent(2).nl
-		str << "}".indent.nl(false).nl(false)
-		
-		methods.each do |method|		
-			next if method.selector == ("alloc" || "init") && method.static == "true"
-				
-			return_type = get_type(method["returnValue"][0].type, method["returnValue"][0]["type64"], method["returnValue"][0]["declaredType"])
-			variadic = method["variadic"] == "true"
-			static = method["static"] == "true"
-			this = "this.id" unless static
-			this = "class_#{class_name}" if static
-			args = ""
-			out_args = []
-			original_type = method.returnValue[0].type
-			
-			if method.selector[0 ... 4] == "init" && return_type == "id"
-				return_type = class_name
-				method.returnValue[0].declaredType = class_name
-			end
-			
-			method["arg"].each do |arg|
-				args << " &" if arg.type == "^@"
-				args << arg["name"]
-				
-				if arg.type == "@"
-					args << " !is null ? "
-					args << arg["name"]
-					args << ".id : null"
-				elsif arg.type == "^@"
-					type = get_type(arg.type, arg.type, arg["declaredType"])
-					out_args << { :type => type[4 .. -1], :name => arg["name"] }
-					args << "_.id"
-				end
-
-				args << ", "
-			end unless method["arg"].nil?
-			
-			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
-			index = declaration.index_of(" ")
-			
-			str << (declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " ")
-			str << "{".indent.nl(false)
-			
-			out_args.each do |arg|
-				str << arg.type.indent(2)
-				str << " "
-				str << arg.name
-				str << "_ = new "
-				str << arg.type
-				str << "(false, false)".nl
-			end
-			
-			str << "\n" if out_args.length > 0
-			
-			
-			if method["returnValue"][0].type == "@"
-				str << "id result = objc_msgSend(#{this}, sel_".indent(2)
-				str << transform_selector(method["selector"])
-				str << ", " unless method.arg.nil?		
-				str << args[0 ... -2] unless method.arg.nil?
-				str << ")".nl					
-				str << "\n" if out_args.length > 0	
-				
-				out_args.each do |arg|
-					str << arg.name.indent(2)
-					str << " = "
-					str << arg.name
-					str << "_".nl
-				end
-				
-				str << "\n" if out_args.length > 0
-				
-				if method["returnValue"][0]["declaredType"] == class_name
-					str << "return result is this.id ? this : (return result ".indent(2)
-				else
-					str << "return result ".indent(2)
-				end
-				
-				str << "!is null ? new "
-				str << return_type					
-				str << "(result) : null"
-				
-				if method["returnValue"][0]["declaredType"] == class_name
-					str << ")".nl
-				else
-					str << "".nl
-				end
-				
-				str << "}".indent.nl(false).nl(false)				
-			else
-				if original_type == "d" || original_type == "f"
-					
-					str << "version (X86)".indent(2).nl(false)
-					
-					if out_args.length > 0
-						str << return_type.indent(3)
-						str << " result "
-					else						
-						if original_type == "d"
-							str << "return ".indent(3)
-						else
-							str << "return cast(".indent(3)
-							str << return_type
-							str << ") "
-						end							
-					end
-					
-					str << "objc_msgSend_fpret(#{this}, sel_"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl.nl(false)
-					
-					str << "else".indent(2).nl(false)
-					
-					if out_args.length > 0
-						str << return_type.indent(3)
-						str << " result "
-					else						
-						if original_type == "d"
-							str << "return ".indent(3)
-						else
-							str << "return cast(".indent(3)
-							str << return_type
-							str << ") "
-						end							
-					end
-					
-					str << "objc_msgSend(#{this}, sel_"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl
-					str << "\n" if out_args.length > 0					
-
-					out_args.each do |arg|
-						str << arg.name.indent(3)
-						str << " = "
-						str << arg.name
-						str << "_".nl
-					end
-
-					if out_args.length > 0
-						str << "\n"
-						str << "retrun result".indent(3).nl
-					end
-
-					str << "\n" if out_args.length > 0			
-					str << "}".indent.nl(false).nl(false)					
-				else
-					unless return_type == "void"					
-						if out_args.length > 0
-							str << return_type.indent(2)
-							str << " result "
-						else
-							str << "return cast(".indent(2)
-						end
-
-						str << return_type
-						str << ") "
-					end
-
-					str << "objc_msgSend(#{this}, sel_".indent(2) if return_type == "void"
-					str << "objc_msgSend(#{this}, sel_" unless return_type == "void"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl
-
-					str << "\n" if out_args.length > 0
-
-					out_args.each do |arg|
-						str << arg.name.indent(2)
-						str << " = "
-						str << arg.name
-						str << "_".nl
-					end
-
-					if out_args.length > 0
-						str << "\n"
-						str << "retrun result".indent(2).nl
-					end
-							
-					str << "}".indent.nl(false).nl(false)
-				end				
-			end
-		end
-		
-		str.string[0 .. -2]
-	end
-	
-	# Generates the D code for the structs
-	def structs (structs)
-		str = StringIO.new
-		
-		structs.each do |struct|
-			str << "struct "
-			str << struct.name.nl(false)
-			str << "{".nl
-			
-			struct.member.each do |member|
-				type = get_type(member.type, member.type64, member.declaredType)
-				
-				str << type.indent
-				str << " "
-				str << member.name.nl
-			end unless struct.member.nil?
-			
-			str << "}".nl
-			str << "\n\n"
-		end
-		
-		str.string[0 .. -2]
-	end
-	
-	# Generates the D code for the typedefs
-	def typedefs (typedefs)
-		str = StringIO.new
-
-		typedefs.each do |typedef|
-			
-			type = ""
-			struct = false
-			
-			if typedef.type.struct?
-				type = get_struct_type(typedef.type, typedef["type64"], typedef["declaredType"])
-				struct = true
-			else
-				type = get_type(typedef.type, typedef.type64, typedef.declaredType)
-			end
-			
-			# Special case
-			type = "wchar" if typedef.name == "unichar"				
-			
-			if struct
-				str << typedef["declaredType"].gsub("*", "").nl
-				str << "alias "				
-				str << type[:name]
-				str << " "
-				str << typedef["name"].nl
-			else
-				str << "alias "
-				str << type
-				str << " "
-				str << typedef.name.nl
-			end
-		end
-
-		str << "\n"
-		str.string
-	end
-	
-	# Adds specific D extensions to classes, like opIndex and opApply
-	def d_class_extensions (args)
-		
-	end
-	
-	# Checks if the declared type should be used instead of the type
-	# type:: the type to check
-	#
-	def check_declared_type (type)		
-		case type
-			when "unichar"; return "wchar"
-			when "BOOL"; return "bool"
-			when "CGFloat"; return type
-			when "NSInteger"; return type
-			when "NSUInteger"; return type
-				
-			when "unichar*"; return "wchar*"
-			when "BOOL*"; return "bool*"
-			when "CGFloat*"; return type
-			when "NSInteger*"; return type
-			when "NSUInteger*"; return type
-				
-			when "unichar**"; return "wchar**"
-			when "BOOL**"; return "bool**"
-			when "CGFloat**"; return type
-			when "NSInteger**"; return type
-			when "NSUInteger**"; return type
-			else return nil;
-		end
-	end
-	
-	# Gets the method name from the supplied selector
-	# selector:: the selector to get the method name from
-	#
-	# === Example:
-	# get_method_name("initWithContentsOfURL:options:error:")       #=> initWithContentsOfURL
-	#
-	def get_method_name (selector)
-		i = selector.index_of(":")
-		selector[0 ... i]
-	end
-	
-	# Gets the D type from the encoded C/Objective-C type
-	# type:: the type
-	# type64:: the type for 64bit targets
-	# declared_type:: the declared type
-	#
-	# === Example:
-	# get_type("I", "Q", "NSUInteger")      #=> NSUInteger
-	# get_type("I", "I", "unsigned int")    #=> uint
-	#
-	def get_type (type, type64, declared_type)
-				
-		t = check_declared_type(declared_type)
-		return t unless t.nil?
-		
-		unless type64 == "" || type64.nil?
-			return declared_type if type != type64
-		end
-		
-		case type
-		when "c"; return "byte"
-		when "i"; return "int"
-		when "s"; return "short"
-		when "l"; return "int"
-		when "q"; return "long"
-		when "C"; return "ubyte"
-		when "I"; return "uint"
-		when "S"; return "ushort"
-		when "L"; return "uint"
-		when "Q"; return "ulong"
-		when "f"; return "float"
-		when "d"; return "double"
-		when "B"; return "bool"
-		when "v"; return "void"
-		when "*"; return "char*"
-		when '#'; return "Class"
-		when ":"; return "SEL"					
-		when "@"
-			return declared_type.gsub(/\*+/, "") unless declared_type.nil?
-			raise "No declared type given"
-		else
-			case type[0, 1]
-			when "["
-				str = ""
-				t = type[1 ... -1]
-				count = $1 if t =~ /(\d+)/
-				str = get_type($', declared_type)
-				str << "[#{count}]"
-			
-				return str
-			when "("
-				resolved_types = []
-				types = $2 if type =~ /\((.+)=(.+)\)/
-				
-				types.each_char do |t|
-					resolved_types << get_type(t, declared_type)
-				end
-				
-				return resolved_types
-			when "^"				
-				if type == "^@"
-					return "out " << get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
-				elsif type.length > 2 && type[0 ... 2] == "^^"
-					return "out " << get_type(type[2 .. -1], type64[2 .. -1], declared_type).dup
-				elsif type == "^?"
-					tmp = cfp_to_dfp(type)
-					return tmp unless tmp.nil?
-				end
-				
-				if !type.nil? && !type64.nil?
-					return get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup << "*"
-				elsif !type.nil?
-					return get_type(type[1 .. -1], type64, declared_type).dup << "*"
-				end			
-			when "{"
-				return declared_type
-			end
-		end
-		
-		return declared_type
-	end
-	
-	# Gets the D type from the encoded C/Objective-C type when it's a struct
-	# type:: the type
-	# type64:: the type for 64bit targets
-	# declared_type:: the declared type
-	#
-	# === Example
-	# get_struct_type("{some=III}", "{some=III}", "struct some")
-	# # outputs below
-    # { :name => "some", :types => ["uint", "uint", "uint"] }
-	#
-	def get_struct_type (type, type64, declared_type)
-		
-		return { :name => declared_type } if declared_type[0 ... 2] == "NS"
-		
-		case type[0, 1]
-		when "{"
-			resolved_types = []
-		
-			name = $1 if type =~ /\^{0,}\{(.{0,})=(.{0,})\}/
-			types = $2
-		
-			unless types.nil?
-				types.each_char do |t|
-					resolved_types << get_type(t, type64, declared_type)
-				end
-			end
-		
-			return { :name => name, :types => resolved_types }
-		when "^"
-			get_struct_type(type[1 .. -1], type64, declared_type)
-			hash = get_struct_type(type[1 .. -1], type64, declared_type)
-			hash[:name].dup << "*"
-			return hash
-		end
-	end
-	
-	# C Function Pointer to D Function Pointer
-	def cfp_to_dfp (fp)
-		reg = /(\w+)\s*\(\*(\w*)\)\s*\((.*)\)/
-		
-		return nil if fp !~ reg
-		
-		return_type = $1
-		name = $2
-		arg_types = $3
-		
-		return "#{return_type} function (#{arg_types})"
-	end
-	
-	# Is the supplied argument an "out" argument
-	# arg:: the arg
-	#
-	# === Example:
-	# out_arg?("out NSError")       #=> true
-	#
-	def out_arg? (arg)
-		return arg[0 .. 4] == "out "
-	end	
-	
-	# Transform the supplied selector to a valid D representation
-	# selector:: the selector to transform
-	#
-	# === Example:
-	# transform_selector("initWithContentsOfURL:options:error:")
-	# # outputs below
-	# initWithContentsOfURL_options_error_
-	#
-	def transform_selector (selector)
-		selector.gsub(/:/, "_")
-	end	
-end
-
-# Prints the message to stderr, exits
-def die (*msg)
-	$stderr.puts msg
-	exit 1
-end
-
-if __FILE__ == $0
-	objc_to_d = ObjcToD.new
-	
-	OptionParser.new do |opts|
-		opts.banner = "Usage: #{File.basename(__FILE__)} [options] <dstep files...>"
-		opts.separator ""
-		opts.separator "Options:"
-		
-		opts.on("-o", "--output DIRECTORY", "Place the output files in this directory'") do |opt|
-			die "The specified directory \"#{opt}\" does not exists" if File.exist?(opt) == false
-			die "Output directory cannot be specified more than once" if objc_to_d.out_dir
-			objc_to_d.out_dir = opt
-		end		
-		
-		help_msg = "Use the `-h' flag or for help."	
-			
-		opts.on("-h", "--help", "Show this message.") do
-			puts opts, help_msg
-			exit
-		end
-		
-		opts.on('-v', '--version', 'Show version.') do
-			puts ObjcToD::VERSION
-			exit
-		end
-		
-		opts.separator ""
-		
-		if ARGV.empty?			
-			die opts.banner
-		else
-			begin
-				opts.parse!(ARGV)
-				
-				die "No output directory given" if objc_to_d.out_dir.nil?
-				
-				ARGV.each do |file|
-					objc_to_d.files << file
-				end
-				
-				objc_to_d.generate_code
-				objc_to_d.output_code
-			rescue => e
-				msg = e.message
-				msg = "Internal error" if msg.empty?
-				
-				die msg, opts.banner, help_msg
-			end
-		end
-	end
-end
\ No newline at end of file
--- a/sciprts/dstepgen.rb	Sat Jan 31 17:22:44 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1388 +0,0 @@
-#!/usr/bin/env ruby
-
-# Copyright (c) 2008-2009, Jacob Carlborg. All rights reserved.
-# Copyright (c) 2006-2007, Apple Inc. All rights reserved.
-# Copyright (c) 2005-2006 FUJIMOTO Hisakuni
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1.  Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer.
-# 2.  Redistributions in binary form must reproduce the above copyright
-#     notice, this list of conditions and the following disclaimer in the
-#     documentation and/or other materials provided with the distribution.
-# 3.  Neither the name of Apple Inc. ("Apple") nor the names of
-#     its contributors may be used to endorse or promote products derived
-#     from this software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
- 
-require "rubygems"
-gem "builder", "~> 2.0"
-require "builder"
-require "tmpdir"
-require "optparse"
-include Builder
-
-$KCODE = "UTF8"
-
-# Extensions that adds support for member access syntax
-class Hash	
-	def type
-		result = self["type"]
-		return result unless result.nil?
-		self[:type]
-	end
-	
-	def type= (type)
-		self[:type] = type
-	end
-	
-	def id
-		result = self["id"]
-		return result unless result.nil?
-		self[:id]
-	end
-	
-	def id= (id)
-		self[:id] = id
-	end
-	
-	def methods
-		result = self["methods"]
-		return result unless result.nil?
-		self[:methods]
-	end
-	
-	def methods= (methods)
-		self[:methods] = methods
-	end
-	
-	def method_missing (method, *args)
-		self.class.instance_eval do
-			define_method(method) do |*args|
-				if args.length > 0
-					self[method[0 ... -1]] = args[0]
-					self[eval(":#{method}"[0 ... -1])] = args[0]
-				else
-					result = self[method]
-					return result unless result.nil?
-					self[eval(":#{method}")]
-				end
-			end
-		end
-		
-		if (method = method.id2name) =~ /=/
-			eval("self.#{method} (args.length < 2 ? args[0] : args)")
-		else
-			eval("self.#{method}")
-		end
-	end
-end
-
-# This Struct represents an Objective-C Framework
-Framework = Struct.new(:name, :headers) do
-	def initialize
-		self.headers = []
-		self.name = ""
-	end
-end
-
-# This Struct represents a C/Objective-C header
-HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :defines, :enums, :externs, :functions,
-			  			:imports, :inline_functions, :opaques, :path, :structs, :typedefs) do
-	def initialize
-		self.name = ""
-		self.cftypes = []
-		self.constants = []
-		self.defines = []
-		self.enums = []
-		self.externs = []
-		self.framework = ""
-		self.functions = []
-		self.imports = []
-		self.inline_functions = []
-		self.opaques = []
-		self.path = ""
-		self.structs = []
-		self.typedefs = []
-	end	
-end
-
-# This class scans the headers
-class HeaderScaner
-	CPP = ['/usr/bin/cpp-4.0', '/usr/bin/cpp-3.3', '/usr/bin/cpp3'].find { |x| File.exist?(x) }
-	raise "cpp not found" if CPP.nil?
-	CPPFLAGS = "-D__APPLE_CPP__ -include /usr/include/AvailabilityMacros.h"
-	CPPFLAGS << "-D__GNUC__" unless /\Acpp-4/.match(File.basename(CPP))
-	
-	attr_accessor :frameworks, :headers, :do_64bit
-	
-	def initialize
-		@extern_name = 'extern'
-		@frameworks = []
-		@file_content = nil
-		@headers = []
-		@classes = {}
-		@informal_protocols = {}
-		@function_pointer_types = {}
-		@do_64bit = false
-	end
-	
-	def classes
-		@classes
-	end
-	
-	def protocols
-		@informal_protocols
-	end
-	
-	def cftypes (header)
-		re = /typedef\s+(const\s+)?(struct\s*\w+\s*\*\s*)([^\s]+Ref)\s*;/
-		@cpp_result.scan(re).each do |m|
-			header.cftypes << { :name => m[2], :type => m[1], :const => m[0] =~ /const/ ? true : false}
-		end
-	end
-	
-	def constants (header)
-		tmp = header.externs.map do |i|
-			constant?(i, true)
-		end
-		
-		header.constants = tmp.flatten.compact
-	end
-	
-	def defines (header)
-		re = /#define\s+([^\s]+)\s+(\([^)]+\)|[^\s]+)\s*$/
-		@file_content.scan(re).each do |m|
-			next unless !m[0].include?('(') && m[1] != '\\'
-			header.defines <<  { :name => m[0], :value => m[1] }
-		end
-	end
-	
-	def enums (header)
-		re = /\benum\b\s*(\w+\s+)?\{([^}]*)\}/
-		@cpp_result.scan(re).each do |m|
-			enum = { :name => m[0], :members => [] }
-			
-			m[1].split(",").map do |i|
-				name, value = i.split("=", 2).map do |x|
-					x.strip
-				end
-				
-				enum[:members] << { :name => name, :value => value } unless name.empty? || name[0] == ?#
-			end
-			
-			header.enums << enum
-		end
-	end
-	
-	def function_pointer_types (header)
-		re = /typedef\s+([\w\s]+)\s*\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*;/
-		data = @cpp_result.scan(re)
-		re = /typedef\s+([\w\s]+)\s*\(([^)]+)\)\s*;/
-		data |= @cpp_result.scan(re).map do |m|
-			ary = m[0].split(/(\w+)$/)
-			ary[1] << " *"
-			ary << m[1]
-			ary
-		end
-		
-		data.each do |m|
-			name = m[1]
-			args = m[2].split(",").map do |x|
-				if x.include?(" ")
-					ptr = x.sub!(/\[\]\s*$/, "")
-					x = x.sub(/\w+\s*$/, "").strip
-					ptr ? x + "*" : x
-				else
-					x.strip
-				end
-			end
-			
-			type = "#{m[0]}(*)(#{args.join(', ')})"
-			@function_pointer_types[name] = type
-		end
-	end
-	
-	def typedefs (header)
-		re = /^\s*typedef\s+(.+)\s+([\w\*]+)\s*;$/
-		data = @cpp_result
-		data.scan(re).each do |m|
-			var = get_var_info(m[0] + " " + m[1])
-			header.typedefs << get_var_info(m[0] + " " + m[1]) if var
-		end
-	end
-	
-	def externs (header)
-		re = /^\s*#{@extern_name}\s+\b(.*)\s*;.*$/
-		header.externs = @cpp_result.scan(re).map do |m|
-			m[0].strip
-		end
-	end
-	
-	def imports (header)
-		tmp = []
-			
-		@file_content.each do |line|
-			if line =~ /#(include|import) <(.+)\.h>/
-				next if $2 == header.name
-				tmp << $2
-			elsif line =~ /@class(\s+)(\w+)(,|;)/
-				next if $2 == header.name
-				
-				if $3 == ";"
-					tmp << header.framework + "/" + $2 unless header.framework == ""
-					tmp << $2 if header.framework == ""
-				elsif
-					str = line[6 + $1.length ... -2]
-					str.gsub!(" ", "")
-					arr = str.split(",")
-					
-					arr.each do |s|
-						tmp << header.framework + "/" + s unless header.framework == ""
-						tmp << s if header.framework == ""
-					end
-				end
-			end
-		end
-		
-		header.imports = tmp.compact.uniq
-	end
-	
-	def informal_protocols (header)
-		self.methods(header)
-	end	
-	
-	def methods (header)
-		interface_re = /^@(interface|protocol)\s+(\w+)\s*:?\s*(\w*)\s*(\([^)]+\))?/
-		
-		end_re = /^@end/
-		body_re = /^[-+]\s*(\([^)]+\))?\s*([^:\s;]+)/
-		args_re = /\w+\s*:/
-		prop_re = /^@property\s*(\([^)]+\))?\s*([^;]+);$/
-		current_interface = current_category = nil
-		i = 0
-		parent = nil	
-		
-		@cpp_result.each_line do |line|
-			size = line.size
-			line.strip!
-			
-			if md = interface_re.match(line)
-				parent = nil
-				current_interface = md[1] == "protocol" ? "NSObject" : md[2]
-				current_category = md[4].delete("()").strip if md[4]
-				parent = md[3] unless md[3] == ""
-				
-			elsif end_re.match(line)
-				current_interface = current_category = nil
-				
-			elsif current_interface && md = prop_re.match(line)
-				# Parsing Objective-C 2.0 properties
-				if (a = md[2].split(/\s/)).length >= 2 && /^\w+$/.match(name = a[-1]) && (type = a[0 .. -2].join(" ")).index(",").nil?
-					getter, setter = name, "set#{name[0].chr.upcase + name[1 .. -1]}"
-					readonly = false
-					
-					if attributes = md[1]
-						if md = /getter\s*=\s*(\w+)/.match(attributes)
-							getter = md[1]
-						end
-						
-						if md = /setter\s*=\s*(\w+)/.match(attributes)
-							setter = md[1]
-						end
-						
-						readonly = true if attributes.index("readonly")
-					end
-					
-					typeinfo = VarInfo.new(type, "", "")
-					
-					@classes[current_interface] ||= {}					
-					methods = (@classes[current_interface].methods ||= [])
-					methods << MethodInfo.new(typeinfo, getter, false, [], line)
-					
-					unless readonly
-						methods << MethodInfo.new(VarInfo.new("void", "", ""), setter + ":", false, [typeinfo], line)
-					end
-				end
-				
-			elsif current_interface && (line[0] == ?+ || line[0] == ?-)
-				mtype = line[0]
-				data = @cpp_result[i .. -1]
-				body_md = body_re.match(data)
-				
-				next if body_md.nil?
-				
-				rettype = body_md[1] ? body_md[1].delete("()") : "id"
-				retval = VarInfo.new(rettype, "", "")
-				args = []
-				selector = ""
-				data = data[0 .. data.index(";")]
-				args_data = []
-				
-				data.scan(args_re) do |x|
-					args_data << [$`, x, $']
-				end
-				
-				variadic = false
-				args_data.each_with_index do |ary, n|
-					before, argname, argtype = ary
-					arg_nameless = (n > 0 && /\)\s*$/.match(before))
-					argname = ":" if arg_nameless
-					realargname = nil
-					
-					if n < args_data.length - 1
-						argtype.sub!(args_data[n + 1][2], "")
-						
-						if arg_nameless
-							argtype.sub!(/(\w+\s*)?\w+\s*:\s*$/, "")
-						else
-							unless argtype.sub!(/(\w+)\s+\w+:\s*$/)	{ |s| realargname = $1; "" }
-								# maybe the next argument is nameless
-								argtype.sub!(/\w+\s*:\s*$/, "")
-							end
-						end
-					else
-						argtype.sub!(/\s+__attribute__\(\(.+\)\)/, "")
-						
-						if arg_nameless
-							argtype.sub!(/\w+\s*;$/, "")
-						else
-							unless argtype.sub!(/(\w+)\s*;$/) { |s| realargname = $1; "" }
-								variadic = argtype.sub!(/,\s*\.\.\.\s*;/, "") != nil
-								argtype.sub!(/\w+\s*$/, "") if variadic
-							end
-						end
-					end
-					
-					selector << argname
-					realargname ||= argname.sub(/:/, "")
-					args << VarInfo.new(argtype, realargname, "") unless argtype.empty?
-				end
-				
-				selector = body_md[2] if selector.empty?
-				args << VarInfo.new("...", "vararg", "") if variadic
-				method = MethodInfo.new(retval, selector, line[0] == ?+, args, data)
-				
-				if current_category && current_interface == "NSObject"
-					(@informal_protocols[current_category] ||= []) << method
-				end
-				
-				@classes[current_interface] ||= {}
-				
-				if header.name == current_interface				
-					@classes[current_interface].file = header.name
-				else
-					@classes[current_interface].file ||= header.name
-				end
-				
-				unless parent == current_interface || parent =~ /\s+/ || parent.nil?
-					@classes[current_interface].parent = parent
-				end				
-				
-				(@classes[current_interface].methods ||= []) << method
-			end
-			i += size
-		end
-	end	
-	
-	def structs (header)
-		re = /typedef\s+struct\s*\w*\s*((\w+)|\{([^{}]*(\{[^}]+\})?)*\}\s*([^\s]+))\s*(__attribute__\(.+\))?\s*;/
-		i = 0
-		body = nil
-		@cpp_result.scan(re).each do |m|
-			struct = { :name => m[4], :members => [] }
-			
-			unless struct[:name].nil?
-				if struct[:name][0, 1] == "*"
-					struct[:name].sub!("*", "")
-				end
-			end
-			
-			return_type = nil
-			stripped_return_type = nil
-			body = m[2]
-			
-			if m[2]
-				m[2].split(/,|;/).map do |i|				
-					str, bytes = i.split(":", 2).map do |x|
-						x.strip
-					end
-	
-					var = get_var_info(str, true)
-	
-					if var				
-						if var.return_type == "***dummy***"
-							var.return_type = return_type
-							var.stripped_return_type = stripped_return_type
-						else
-							return_type = var.return_type
-							stripped_return_type = var.stripped_return_type
-						end
-	
-						struct[:members] << { :name => var.name, :bytes => bytes, :declaredType => var.return_type, :type => "", :type64 => "" } unless str.empty? || str[0] == ?#
-						
-						names = []
-						
-						tmp = struct[:members].collect do |member|
-							unless names.include?(member[:name])
-								names << member[:name]
-								member
-							end
-						end
-						
-						struct[:members] = tmp.compact
-					end
-				end
-			end
-			
-			header.structs << struct if body
-		end
-	end
-	
-	def functions (header, inline = false)
-		if inline
-			inline_func_re = /(inline|__inline__)\s+((__attribute__\(\([^)]*\)\)\s+)?([\w\s\*<>]+)\s*\(([^)]*)\)\s*)\{/
-			res = @cpp_result.scan(inline_func_re)
-			res.each do |x|
-				x.delete_at(0)
-				x.delete_at(1)
-			end
-		else
-			skip_inline_re = /(static)?\s(inline|__inline__)[^{;]+(;|\{([^{}]*(\{[^}]+\})?)*\})\s*/
-			func_re = /(^([\w\s\*<>]+)\s*\(([^)]*)\)\s*)(__attribute__[^;]+)?;/
-			res = @cpp_result.gsub(skip_inline_re, '').scan(func_re)
-		end
-		
-		funcs = res.map do |m|
-			orig, base, args = m			
-			base.sub!(/^.*extern\s/, "")
-			func = constant?(base)
-			
-			if func
-				args = args.strip.split(",").map do |i|
-					constant?(i)
-				end
-				
-				next if args.any? do |x|
-					x.nil?
-				end
-				
-				args = [] if args.size == 1 && args[0].return_type == "void"	
-				FunctionInfo.new(func, args, orig, inline)
-			end
-		end.compact
-		
-		if inline
-			header.inline_functions = funcs
-		else
-			header.functions = funcs
-		end
-	end
-	
-	def prepare (path)		
-		@file_content = File.read(path)
-		@file_content.gsub!(%r{(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)}, "");
-		@complete_cpp_result, @cpp_result = do_cpp(path, false, true, "")
-	end	
-	
-	def scan (frameworks, headers)
-		@frameworks = frameworks
-		@headers = headers
-		
-		@frameworks.each do |framework|			
-			framework.headers.each do |header|
-				prepare(header.path)
-				
-				imports(header)
-				cftypes(header)
-				externs(header)
-				constants(header)
-				enums(header)
-				structs(header)
-				typedefs(header)
-				functions(header)
-				functions(header, true)
-				defines(header)
-				methods(header)
-				function_pointer_types(header)
-			end
-		end
-		
-		@headers.each do |header|
-			prepare(header.path)
-			
-			imports(header)
-			cftypes(header)
-			externs(header)
-			constants(header)
-			enums(header)
-			structs(header)
-			typedefs(header)
-			functions(header)
-			functions(header, true)
-			defines(header)
-			methods(header)
-			function_pointer_types(header)
-		end
-	end
-	
-	def get_var_info (str, multi = false)
-		str.strip!
-		
-		return nil if str.empty?
-		
-		if str == "..."
-			VarInfo.new("...", "...", str)
-		else
-			str = "***dummy*** " + str if str[-1].chr == '*' || str.index(/\s/).nil?	
-			tokens = multi ? str.split(',') : [str]
-			part = tokens.first
-			re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/
-			m = re.match(part)	
-	
-			if m
-				return nil if m[1].split(/\s+/).any? do |x|
-					['end', 'typedef'].include?(x)
-				end
-				
-				m = m.to_a[1..-1].compact.map do |i|
-					i.strip
-				end
-				
-				m[0] += m[2] if m.size == 3
-				m[0] = 'void' if m[1] == 'void'
-				
-				var = begin
-					VarInfo.new(m[0], m[1], part)
-				rescue
-					return nil
-				end
-				
-				if tokens.size > 1
-					[var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }]
-				else
-					var
-				end				
-			end
-		end
-	end
-	
-	def constant? (str, multi = false)
-		str.strip!
-		return nil if str.empty?
-		
-		if str == '...'
-			VarInfo.new('...', '...', str)
-		else
-			str << " dummy" if str[-1].chr == '*' or str.index(/\s/).nil?
-			tokens = multi ? str.split(',') : [str]
-			part = tokens.first
-			re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/
-			m = re.match(part)
-			
-			if m
-				return nil if m[1].split(/\s+/).any? do |x|
-					['end', 'typedef'].include?(x)
-				end
-				
-				m = m.to_a[1..-1].compact.map do |i|
-					i.strip
-				end
-				
-				m[0] += m[2] if m.size == 3
-				m[0] = 'void' if m[1] == 'void'
-				
-				var = begin
-					VarInfo.new(m[0], m[1], part)
-				rescue
-					return nil
-				end
-				
-				if tokens.size > 1
-					[var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }]
-				else
-					var
-				end
-			end
-		end
-	end	
-	
-	class VarInfo
-		
-		attr_reader :name, :orig, :const, :type_modifier
-		attr_accessor :octype, :resolved_type, :resolved_type64, :return_type, :stripped_return_type
-		
-		def initialize (type, name, orig)
-			@return_type = type.clone
-			@name = name
-			@orig = orig
-			@const = false
-			@type_modifier = ""
-			
-			@return_type.gsub!(/\[[^\]]*\]/, "*")
-			
-			if @return_type =~ /\bconst\b/
-				@const = true
-				@return_type.gsub!("const", "")
-			end
-			
-			if @return_type =~ /\b(in|out|inout|oneway|bycopy|byref)\b/
-				
-				case $1
-				when "in"
-					@type_modifier << "n"
-				when "out"
-					@type_modifier << "o"
-				when "inout"
-					@type_modifier << "N"
-				when "oneway"
-					@type_modifier << "w"
-				when "bycopy"
-					@type_modifier << "c"
-				when "byref"
-					@type_modifier << "r"
-				end
-				
-				@return_type.gsub!("#{$1}", "")
-			end
-			
-			@return_type.gsub!(/\s?\*\s?/, "*")
-			@return_type.gsub!(/^\(|\)$/, "")
-			@return_type.strip!
-			
-			t = type.gsub(/\b(__)?const\b/, "")
-			t.gsub!(/<[^>]*>/, '')
-			t.gsub!(/\b(in|out|inout|oneway|const)\b/, "")
-			t.gsub!(/\b__private_extern__\b/, "")
-			t.gsub!(/^\s*\(?\s*/, "")
-			t.gsub!(/\s*\)?\s*$/, "")
-			
-			raise "Empty type (was '#{type}')" if t.empty?
-			
-			@stripped_return_type = t
-		end
-		
-		def function_pointer? (function_pointer_types)
-			type = @function_pointer_types[@stripped_return_type] || @stripped_return_type
-			@function_pointer_type ||= FunctionPointerInfo.new_from_type(type)
-		end
-		
-		def <=>(x)
-			self.name <=> x.name
-		end					
-		
-		def hash
-			@name.hash
-		end
-		
-		def eql? (o)
-			@name == o.name
-		end
-	end
- 
-	class FunctionInfo < VarInfo
-		
-		attr_reader :args, :argc
-		
-		def initialize (function, args, orig, inline = false)
-			super(function.return_type, function.name, orig)
-			
-			@args = args
-			@argc = @args.size
-			@variadic = false
-			
-			if @args[-1] && @args[-1].return_type == "..."
-				@argc -= 1
-				@variadic = true
-				@args.pop
-			end
-			
-			@inline = inline
-			self
-		end
-		
-		def variadic?
-			@variadic
-		end
-		
-		def inline?
-			@inline
-		end
-	end
-	
-	class FunctionPointerInfo < FunctionInfo
-		def initialize (return_type, arg_types, orig)
-			args = arg_types.map do |x|
-				VarInfo.new(x, "", "")
-			end
-			
-			super(VarInfo.new(return_type, "", ""), args, orig)
-		end
-		
-		def self.new_from_type (type)
-			@cache ||= {}
-			info = @cache[type]
-			
-			return info if info
-			
-			tokens = type.split(/\(\*\)/)
-			return nil if tokens.size != 2
-			
-			return_type = tokens.first.strip
-			rest = tokens.last.sub(/^\s*\(\s*/, "").sub(/\s*\)\s*$/, "")
-			
-			arg_types = rest.split(/,/).map do |x|
-				x.strip
-			end
-			
-			@cache[type] = self.new(return_type, arg_types, type)
-		end
-	end
-	
-	class MethodInfo < FunctionInfo
-		
-		attr_reader :selector
-		
-		def initialize (method, selector, is_class, args, orig)
-			super(method, args, orig)
-			
-			@selector = selector
-			@is_class = is_class
-			self
-		end
-		
-		def class_method?
-			@is_class
-		end
-		
-		def <=>(o)
-			@selector <=> o.selector
-		end
-		
-		def hash
-			@selector.hash
-		end
-		
-		def eql? (o)
-			@selector == o.selector
-		end
-	end
-	
-	def do_cpp (path, fails_on_error = true, do_64 = true, flags = "")
-	    f_on = false
-	    err_file = '/tmp/.cpp.err'
-	    cpp_line = "#{CPP} #{CPPFLAGS} #{flags} #{do_64 ? '-D__LP64__' : ''} \"#{path}\" 2>#{err_file}"
-	    complete_result = `#{cpp_line}`
-		
-		if $?.to_i != 0 && fails_on_error
-			$stderr.puts File.read(err_file)
-			File.unlink(err_file)
-			raise "#{CPP} returned #{$?.to_int/256} exit status\nline was: #{cpp_line}"
-		end
-		
-		result = complete_result.select do |s|
-			# First pass to only grab non-empty lines and the pre-processed lines
-			# only from the target header (and not the entire pre-processing result).
-			next if s.strip.empty?
-			m = %r{^#\s*\d+\s+"([^"]+)"}.match(s)
-			f_on = (File.basename(m[1]) == File.basename(path)) if m
-			f_on
-		end.select do |s|
-			# Second pass to ignore all pro-processor comments that were left.
-			/^#/.match(s) == nil
-		end.join
-		
-		File.unlink(err_file)
-		return [complete_result, result]
-	end
-end
-
-class DStepGenerator
-	
-	VERSION = 1.0
-	
-	attr_accessor :out_file, :scaner
-	
-	def initialize
-		@do_64bit = false
-		@frameworks = []
-		@framework_paths = []
-		@headers = []
-		@import_directives = ""
-		@informal_protocols = []
-		@classes = []
-		@scaner = HeaderScaner.new
-		@scaner.do_64bit = @do_64bit
-	end
-	
-	def do_64bit
-		return @do_64bit
-	end
-	
-	def do_64bit= (do_64bit)
-		@do_64bit = do_64bit
-		@scaner.do_64bit = do_64bit
-	end	
-	
-	def collect		
-		scaner.scan(@frameworks, @headers)
-		@classes = scaner.classes
-		@informal_protocols = scaner.protocols
-	end
-	
-	def handle_framework (framework)
-		val = framework.name
-		path = framework_path(val)
-		
-		raise "Can't locate framework '#{val}'" if path.nil?
-		@framework_paths << File.dirname(path)
-		raise "Can't find framework '#{val}'" if path.nil?
-		
-		parent_path, name = path.scan(/^(.+)\/(\w+)\.framework\/?$/)[0]
-		
-		if @private
-			headers_path = File.join(path, "PrivateHeaders")
-			raise "Can't locate private framework headers at '#{headers_path}'" unless File.exist?(headers_path)
-			
-			headers = Dir.glob(File.join(headers_path, "**", "*.h"))
-			public_headers_path = File.join(path, "Headers")
-			public_headers = if File.exist?(public_headers_path)
-				HeaderScaner::CPPFLAGS << " -I#{public_headers_path} "
-				Dir.glob(File.join8(headers_path, "**", "*.h"))
-			else
-				[]
-			end
-		else
-			headers_path = File.join(path, "Headers")
-			raise "Can't locate public framework headers at '#{headers_path}'" unless File.exist?(headers_path)
-			public_headers = headers = Dir.glob(File.join(headers_path, "**", "*.h"))
-		end
-		
-		# We can't just "#import <x/x.h>" as the main Framework header might not include _all_ headers.
-			    # So we are tricking this by importing the main header first, then all headers.
-			    header_basenames = (headers | public_headers).map do |x|
-			    	x.sub(/#{headers_path}\/*/, "")
-			    end
-			
-		if idx = header_basenames.index("#{name}.h")
-			header_basenames.delete_at(idx)
-			header_basenames.unshift("#{name}.h")
-		end
-		
-		@import_directives = header_basenames.map do |x|
-			"#import <#{name}/#{x}>"
-		end.join("\n")
-		
-		@import_directives << "\n"
-		
-		@compiler_flags ||= "-F\"#{parent_path}\" -framework #{name}"
-		@cpp_flags ||= ""
-		@cpp_flags << "-F\"#{parent_path}\" "
-		
-		headers.each do |header|
-			header_file = HeaderFile.new
-			header_file.path = header
-			header_file.name = File.basename(header, File.extname(header))
-			header_file.framework = framework.name
-			
-			framework.headers << header_file
-		end
-		
-		# Memorize the dependencies.
-		@dependencies = DStepGenerator.dependencies_of_framework(path)
-	end
-	
-	def framework_path (val)
-		return path if File.exist?(val)
-		
-		val += ".framework" unless /\.framework$/.match(val)
-		paths = ["/System/Library/Frameworks", "/Library/Frameworks", "#{ENV['HOME']}/Library/Frameworks"]
-		paths << "/System/Library/PrivateFrameworks" if @private
-		
-		paths.each do |dir|
-			path = File.join(dir, val)
-			return path if File.exist?(path)
-		end
-		
-		return nil
-	end
-	
-	def self.dependencies_of_framework (path)
-		@dependencies ||= {}
-		name = File.basename(path, ".framework")
-		path = File.join(path, name)
-		deps = @dependencies[path]
-		
-		if deps.nil?
-			deps = `otool -L "#{path}"`.scan(/\t([^\s]+)/).map do |m|
-				dpath = m[0]
-				next if File.basename(dpath) == name
-				next if dpath.include?("PrivateFrameworks")
-				next unless dpath.sub!(/\.framework\/Versions\/\w+\/\w+$/, "")
-				dpath + ".framework"
-			end.compact
-			
-			@dependencies[path] = deps
-		end
-		
-		return deps
-	end
-	
-	def compile_and_execute (code, enable_64bit = false)
-		compiler_line = "gcc "				
-		src = File.new(unique_tmp_path("src", ".m"), "w")
-		src << code
-		src.close
-		
-		arch_flag = if enable_64bit
-					"-arch x86_64 -arch ppc64"
-				else
-					"-arch i386 -arch ppc"
-				end
-		
-		compiler_line << arch_flag
-		
-		bin = unique_tmp_path "bin"
-		log = unique_tmp_path "log"
-		
-		line = "#{compiler_line} -o #{bin} #{src.path} #{@compiler_flags}> #{log}"
-		
-		unless system(line)
-			msg = "Cannot compile Objective-C code ...aborting\nCommand was: #{line}\n\nLog:\n#{File.read(log)}\n\n"
-			$stderr << msg
-			File.delete src.path
-			raise msg
-		end
-		
-		result = `#{bin}`
-		
-		unless $?.success?
-			raise "Cannot execute compiled Objective-C code ... aborting\nCommand was: #{line}\nBinary is: #{bin}"
-		end
-		
-		File.delete bin
-		File.delete log
-		File.delete src.path
-		
-		return result
-	end
-	
-	def unique_tmp_path (base, extension = "", dir = Dir.tmpdir)
-		i = 0
-		loop do
-			path = File.join(dir, "#{base}-#{Process.pid}-#{i}#{extension}")
-			return path unless File.exists?(path)
-			i += 1
-		end
-	end
-	
-	def add_header (path)
-		header = HeaderFile.new
-		header.path = path
-		header.name = File.basename(path, File.extname(path))
-		@import_directives << "#include <#{path}>\n"
-		@headers << header
-	end
-	
-	def add_framework (name)
-		framework = Framework.new
-		framework.name = name
-		handle_framework(framework)
-		#@import_directives << "#import <#{framework.name}/#{framework.name}.h>\n"
-		@frameworks << framework
-	end
-	
-	def collect_header_types (header, enable_64bit)
-		types = []
-		
-		header.cftypes.each do |cftype|
-			types << cftype[:type]
-		end
-		
-		header.constants.each do |constant|
-			types << constant.stripped_return_type
-		end
-		
-		header.structs.each do |struct|
-			types << struct[:name]
-			
-			struct[:members].each do |member|
-				types << member[:declaredType]
-			end
-		end
-		
-		header.typedefs.each do |typedef|
-			types << typedef.stripped_return_type
-		end
-		
-		header.functions.each do |function|
-			types << function.stripped_return_type
-			
-			function.args.each do |arg|
-				types << arg.stripped_return_type
-			end
-		end
-		
-		types
-	end
-	
-	def collect_classes_types (enable_64bit)
-		types = []
-		
-		@classes.each do |clazz, value|
-			value.methods.each do |method|
-				types << method.stripped_return_type
-				
-				method.args.each do |arg|
-					types << arg.stripped_return_type
-				end
-			end
-		end
-		
-		types
-	end
-	
-	def collect_informal_protocols_types (enable_64bit)
-		types = []
-		
-		@informal_protocols.each do |name, methods|
-			methods.each do |method|
-				types << method.stripped_return_type
-				
-				method.args.each do |arg|
-					types << arg.stripped_return_type
-				end
-			end
-		end
-		
-		types
-	end
-	
-	def resolve_header_types (header, enable_64bit, resolved_types, x)
-		i = x
-		
-		header.cftypes.each do |cftype|
-			cftype[enable_64bit ? :type64 : :type] = resolved_types[i]
-			i += 1
-		end
-		
-		header.constants.each do |constant|
-			constant.resolved_type = resolved_types[i] unless enable_64bit
-			constant.resolved_type64 = resolved_types[i] if enable_64bit
-			i += 1
-		end
-		
-		header.structs.each do |struct|
-			struct[enable_64bit ? :type64 : :type] = resolved_types[i]
-			i += 1
-			
-			struct[:members].each do |member|
-				member[enable_64bit ? :type64 : :type] = resolved_types[i]
-				i += 1
-			end
-		end
-		
-		header.typedefs.each do |typedef|
-			typedef.resolved_type = resolved_types[i] unless enable_64bit
-			typedef.resolved_type64 = resolved_types[i] if enable_64bit
-			i += 1
-		end
-		
-		header.functions.each do |function|
-			function.resolved_type = resolved_types[i] unless enable_64bit
-			function.resolved_type64 = resolved_types[i] if enable_64bit
-			i += 1
-			
-			function.args.each do |arg|
-				arg.resolved_type = resolved_types[i] unless enable_64bit
-				arg.resolved_type64 = resolved_types[i] if enable_64bit
-				i += 1
-			end
-		end
-		
-		i
-	end
-	
-	def resolve_methods_types (enable_64bit, resolved_types, x)
-		i = x
-		
-		@classes.each do |clazz, value|
-			value.methods.each do |method|
-				method.resolved_type = resolved_types[i] unless enable_64bit
-				method.resolved_type64 = resolved_types[i] if enable_64bit
-				i += 1
-				
-				method.args.each do |arg|
-					arg.resolved_type = resolved_types[i] unless enable_64bit
-					arg.resolved_type64 = resolved_types[i] if enable_64bit
-					i += 1
-				end
-			end
-		end
-		
-		i
-	end
-	
-	def resolve_informal_protocols_types (enable_64bit, resolved_types, x)
-		i = x
-		
-		@informal_protocols.each do |name, methods|
-			methods.each do |method|
-				method.resolved_type = resolved_types[i] unless enable_64bit
-				method.resolved_type64 = resolved_types[i] if enable_64bit
-				i += 1
-				
-				method.args.each do |arg|
-					arg.resolved_type = resolved_types[i] unless enable_64bit
-					arg.resolved_type64 = resolved_types[i] if enable_64bit
-					i += 1
-				end
-			end
-		end
-		
-		i
-	end
-	
-	def resolve_types (enable_64bit = false)
-		code = "#include <stdio.h>\n"
-		code << @import_directives
-		types = []
-		
-		@frameworks.each do |framework|
-			framework.headers.each do |header|
-				types << collect_header_types(header, enable_64bit)
-			end
-		end
-
-		@headers.each do |header|
-			types << collect_header_types(header, enable_64bit)
-		end
-		
-		types << collect_classes_types(enable_64bit)
-		types << collect_informal_protocols_types(enable_64bit)
-		
-		code << "int main () \n{\n"
-		types.flatten!
-		
-		types.each do |type|
-			code << '	printf("%s\n", ' + "@encode(#{type}));\n"
-		end
-		
-		code << "	return 0;\n}"
-		
-		resolved_types = []
-		
-		compile_and_execute(code, enable_64bit).split("\n").each do |line|
-			resolved_types << line
-		end
-		
-		i = 0
-		
-		@frameworks.each do |framework|
-			framework.headers.each do |header|
-				i = resolve_header_types(header, enable_64bit, resolved_types, i)
-			end
-		end
-
-		@headers.each do |header|
-			i = resolve_header_types(header, enable_64bit, resolved_types, i)
-		end
-		
-		i = resolve_methods_types(enable_64bit, resolved_types, i)
-		i = resolve_informal_protocols_types(enable_64bit, resolved_types, i)
-	end
-	
-	def generate_header (xml, header)
-		xml.file :name => header.name do
-			header.imports.each	do |import|
-				xml.import import
-			end
-			
-			header.defines.each do |define|
-				xml.define define
-			end
-			
-			header.cftypes.each do |cftype|
-				xml.cftype cftype
-			end
-			
-			header.constants.each do |constant|
-				xml.constant :name => constant.name, :declaredType => constant.return_type, :type => constant.resolved_type, :type64 => constant.resolved_type64, :const => constant.const
-			end
-			
-			header.enums.each do |enum|
-				xml.enum :name => enum[:name] do
-					enum[:members].each do |member|
-						xml.member member
-					end
-				end
-			end
-			
-			header.structs.each do |struct|
-				xml.struct :name => struct[:name], :type => struct[:type], :type64 => struct[:type64] do
-					struct[:members].each do |member|
-						xml.member member
-					end
-				end	
-			end
-			
-			header.typedefs.each do |typedef|
-				xml.typedef :name => typedef.name, :declaredType => typedef.return_type, :type => typedef.resolved_type, :type64 => typedef.resolved_type64, :const => typedef.const
-			end
-			
-			header.functions.each do |function|
-				xml.function :name => function.name, :inline => function.inline?, :variadic => function.variadic? do
-					function.args.each do |arg|
-						xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
-					end
-					
-					xml.returnValue :declaredType => function.return_type, :type => function.resolved_type, :type64 => function.resolved_type64, :const => function.const, :typeModifier => function.type_modifier
-				end
-			end
-		end
-	end
-	
-	def generate_classes (xml)
-		@classes.each do |clazz, value|
-			xml.class :name => clazz, :parent => value.parent, :file => value.file do
-				value.methods.each do |method|
-					xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do
-						method.args.each do |arg|
-							xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
-						end
-						
-						xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier
-					end
-				end
-			end
-		end
-	end
-	
-	def generate_informal_protocols (xml)
-		@informal_protocols.each do |name, methods|
-			xml.informalProtocol :name => name do
-				methods.each do |method|
-					xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do
-						method.args.each do |arg|
-							xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
-						end
-						
-						xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier
-					end
-				end
-			end
-		end
-	end
-	
-	def generate
-		resolve_types
-		resolve_types(true) if @do_64bit
-		
-		file = STDOUT if @out_file == nil
-		file = File.open @out_file, "w" unless @out_file == nil
-		
-		xml = XmlMarkup.new(:target => file, :indent => 4)
-		xml.instruct!
-
-		xml.dstep :xmlns => "http://www.dsource.org/projects/dstep", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => "http://www.dsource.org/projects/dstep/trunk/scripts/dstep.xsd"   do
-			@frameworks.each do |framework|
-				xml.framework :name => framework.name do
-					framework.headers.each do |header|
-						generate_header(xml, header)
-					end
-				end
-			end
-			
-			@headers.each do |header|
-				generate_header(xml, header)
-			end
-			
-			generate_classes(xml)
-			generate_informal_protocols(xml)
-		end
-		
-		file.close unless file == STDOUT
-	end	
-end
-
-def die (*msg)
-	$stderr.puts msg
-	exit 1
-end
-
-if __FILE__ == $0
-	dstep_gen = DStepGenerator.new
-	
-	OptionParser.new do |opts|
-		opts.banner = "Usage: #{File.basename(__FILE__)} [options] <headers...>"
-		opts.separator ""
-		opts.separator "Options:"
-		
-		opts.on("-f", "--framework FRAMEWORK", "Generate metadata for the given framework.") do |opt|
-			dstep_gen.add_framework(opt)
-		end
-		
-		opts.on(nil, "--64-bit", "Write 64-bit annotations.") do
-			dstep_gen.do_64bit = true
-		end
-		
-		opts.on("-o", "--output FILE", "Write output to the given file.") do |opt|
-			die "Output file can't be specified more than once" if dstep_gen.out_file
-			dstep_gen.out_file = opt
-		end
-		
-		# opts.on("-d", "--output-dir PATH", "Write ouptut to the given paht, use this with the --framework option") do |opt|
-		# 	die "Output directory can't be specified more than once" if dstep_gen.out_dir
-		# 	dstep_gen.out_dir = opt
-		# end
-		
-		
-		
-		help_msg = "Use the `-h' flag or for help."	
-			
-		opts.on("-h", "--help", "Show this message.") do
-			puts opts, help_msg
-			exit
-		end
-		
-		opts.on('-v', '--version', 'Show version.') do
-			puts DStepGenerator::VERSION
-			exit
-		end
-		
-		opts.separator ""
-		
-		if ARGV.empty?			
-			die opts.banner
-		else
-			begin
-				opts.parse!(ARGV)
-				
-				ARGV.each do |header|
-					dstep_gen.add_header(header)
-				end
-				
-				dstep_gen.collect
-				dstep_gen.generate
-			rescue => e
-				msg = e.message
-				msg = "Internal error" if msg.empty?
-				
-				die msg, opts.banner, help_msg
-			end
-		end
-	end
-end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/dgen.rb	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,1324 @@
+#!/usr/bin/env ruby
+
+##
+# Copyright:: Copyright (c) 2009 Jacob Carlborg. All rights reserved.
+# Author:: Jacob Carlborg
+# Version:: Initial created: 2009
+# License:: [Boost Software License 1.0]http://www.boost.org/LICENSE_1_0.txt
+#
+
+require "rubygems"
+gem "xml-simple"
+require "xmlsimple"
+require "optparse"
+
+# Extensions to String
+class String	
+	
+	# Passes each character to the supplied block
+	#
+	# === Example:
+	# "str".each_char { |c| puts c }
+	# # outputs below
+	# s
+	# t
+	# r
+	#
+	def each_char
+		if block_given?
+			scan(/./m) do |x|
+				yield x
+			end
+		else
+			scan(/./m)
+		end
+	end
+	
+	# Indents the string
+	# levels:: how many levels/tabs to indent
+	# 
+	# === Example:
+	# "str".indent		#=>		str
+	# "str".indent(3)	#=>				str
+	# 
+	def indent (levels = 1)
+		"\t" * levels << self
+	end
+	
+	# Appends a semicolon and a newline character on the string
+	# semicolon:: should a semicolon be appended
+	#
+	# === Example:
+	# "str".nl
+	# "str".nl(false)
+	# # outputs below
+	# str;
+	#
+	# str
+	# 
+	# 
+	def nl (semicolon = true)
+		if semicolon
+			if self[-1, 1] == "{" || self[-1, 1] == "}"
+				self << "\n"
+			else
+				self << ";\n"
+			end
+		else
+			self << "\n"
+		end
+	end
+	
+	# Returns the index of the given character or length of the string if not found
+	# char:: the character to look for
+	# start:: the index where to start the search
+	# 
+	# === Example:
+	# "012345789".index_of("1")		#=> 1
+	# "0123 0123".index_of("3", 6)	#=> 8
+	# 
+	def index_of (char, start = 0)
+		return self.length if start >= self.length
+		
+		i = 0
+		
+		if start == 0
+			self.each_char do |c|
+				return i if char == c
+				i += 1			
+			end
+		else
+			self[start + 1 .. -1].each_char do |c|
+				return i + start + 1 if char == c
+				i += 1			
+			end
+		end
+		
+		return self.length
+	end
+	
+	# Returns true if the string is an Objective-C struct
+	# 
+	# === Example:
+	# "{?=ii}".struct?		#=> true
+	# 
+	def struct?
+		self =~ /\{/
+	end
+end
+
+# Extensions that adds support for member access syntax
+class Hash	
+	def type
+		result = self["type"]
+		return result unless result.nil?
+		self[:type]
+	end
+	
+	def type= (type)
+		self[:type] = type
+	end
+	
+	def id
+		result = self["id"]
+		return result unless result.nil?
+		self[:id]
+	end
+	
+	def id= (id)
+		self[:id] = id
+	end
+	
+	def methods
+		result = self["methods"]
+		return result unless result.nil?
+		self[:methods]
+	end
+	
+	def methods= (methods)
+		self[:methods] = methods
+	end
+	
+	def method
+		result = self["method"]
+		return result unless result.nil?
+		self[:method]
+	end
+	
+	def method= (method)
+		self[:method] = method
+	end
+	
+	def method_missing (method, *args)
+		self.class.instance_eval do
+			define_method(method) do |*args|
+				if args.length > 0
+					self[method[0 ... -1]] = args[0]
+					self[eval(":#{method}"[0 ... -1])] = args[0]
+				else
+					result = self[method]
+					return result unless result.nil?
+					self[eval(":#{method}")]
+				end
+			end
+		end
+		
+		if (method = method.id2name) =~ /=/
+			eval("self.#{method} (args.length < 2 ? args[0] : args)")
+		else
+			eval("self.#{method}")
+		end
+	end
+end
+
+# This Struct represents an Objective-C Framework
+Framework = Struct.new(:name, :files) do
+	def initialize
+		self.files = []
+		self.name = ""
+	end
+end
+
+# This Struct represents a C/Objective-C header
+HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :d_constants, :d_constants_static_this, :defines, 
+			  			:enums, :functions, :function_wrappers, :imports, :path, :structs, :typedefs) do
+	def initialize
+		self.name = ""
+		self.cftypes = []
+		self.constants = []
+		self.defines = []
+		self.enums = []
+		self.framework = ""
+		self.functions = []
+		self.function_wrappers = []
+		self.imports = []
+		self.path = ""
+		self.structs = []
+		self.typedefs = []
+	end	
+end
+
+# Performs the conversion of an xml metadata file to the D programming language
+class ObjcToD
+	FIRST_YEAR = "2009"
+	VERSION = 1.0
+	
+	attr_accessor :out_dir, :files
+	
+	# Creates a new instance of the ObjcToD class
+	def initialize
+		@classes = {}
+		@copyright = nil
+		@d_constants = []
+		@d_constants_static_this = []
+		@files = []
+		@frameworks = []
+		@function_wrappers = []
+		@headers = []
+		@package = "dstep"
+	end	
+	
+	# Generates the D code from the xml metadata
+	def generate_code
+		@files.each do |dstep_file|
+			xml = XmlSimple.xml_in(dstep_file)
+
+			unless xml.framework.nil?
+				frameworks = xml.framework
+
+				frameworks.each do |frame|
+					framework = Framework.new
+					framework.name = frame.name
+
+					frame.file.each do |file|
+						header = HeaderFile.new
+						header.name = file.name
+						header.constants = constants(file.constant) unless file.constant.nil?
+						header.d_constants = d_constants unless file.constant.nil?
+						header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
+						header.enums = enums(file.enum) unless file.enum.nil?
+						header.functions = functions(file.function) unless file.function.nil?
+						header.function_wrappers = function_wrappers unless file.function.nil?
+						header.imports = imports(file.import, file.name, framework.name) unless file.import.nil?
+						header.structs = structs(file.struct) unless file.struct.nil?
+
+						header.typedefs = typedefs(file.typedef) unless file.typedef.nil?
+
+						framework.files << header
+					end
+
+					@frameworks << framework
+				end
+			end
+
+			unless xml.file.nil?
+				files = xml.file
+
+				files.each do |file|
+					header = HeaderFile.new
+					header.name = file.name
+					header.constants = constants(file.constant) unless file.constant.nil?
+					header.d_constants = d_constants unless file.constant.nil?
+					header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
+					header.enums = enums(file.enum) unless file.enum.nil?
+					header.functions = functions(file.function) unless file.function.nil?
+					header.function_wrappers = function_wrappers unless file.function.nil?
+					header.imports = imports(file.import, file.name) unless file.import.nil?
+					header.structs = structs(file.struct) unless file.struct.nil?
+					header.typedefs = typedefs(file.typedef) unless file.typedef.nil?
+
+					@headers << header
+				end
+			end
+
+			unless xml["class"].nil?
+				classes(xml["class"])
+			end
+		end
+	end
+	
+	# Outputs the generate D code
+	def output_code
+		@frameworks.each do |framework|
+			framework_path = framework_path = "#{@out_dir}/#{@package}/#{framework.name}"
+			
+			FileUtils.mkdir_p(framework_path) unless File.exist?(framework_path)
+			
+			framework.files.each do |header|
+				file_path = "#{framework_path}/#{header.name}.d"
+				
+				File.open(file_path, "w") do |file|
+					file << copyright
+					file << "module #{@package}.#{framework.name}.#{header.name};"
+					file << header.imports.nl(false)
+					file << header.defines
+					file << header.typedefs
+					file << header.cftypes				
+					file << header.constants
+					file << header.d_constants
+					file << header.enums
+					file << header.structs
+					
+					unless header.d_constants_static_this.nil?
+						file << "static this ()".nl(false)
+						file << "{".nl(false)
+						file << header.d_constants_static_this
+						file << "}".nl(false).nl(false)
+					end
+					
+					classes = get_classes(header.name)
+					
+					classes.each do |clazz, value|
+						file << value.code.nl(false)
+						@classes.delete(clazz)
+					end
+					
+					file << header.functions
+					file << header.function_wrappers
+				end
+			end
+		end
+		
+		package_path = "#{@out_dir}/#{@package}"
+		FileUtils.mkdir_p(package_path) unless File.exist?(package_path)
+		
+		@headers.each do |header|
+			header_path = "#{package_path}/#{header.name}.d"
+			
+			File.open(header_path, "w") do |file|
+				file << copyright
+				file << "module #{@package}.#{header.name};"
+				file << header.imports.nl(false)
+				file << header.defines
+				file << header.typedefs
+				file << header.cftypes				
+				file << header.constants
+				file << header.d_constants
+				file << header.enums
+				file << header.structs
+				
+				unless header.d_constants_static_this.nil?
+					file << "static this ()".nl(false)
+					file << "{".nl(false)
+					file << header.d_constants_static_this
+					file << "}".nl(false).nl(false)
+				end
+				
+				classes = get_classes(header.name)
+				
+				classes.each do |clazz, value|
+					file << value.code.nl(false)
+					@classes.delete(clazz)
+				end
+
+				file << header.functions
+				file << header.function_wrappers
+			end			
+		end
+		
+		@classes.each do |clazz, value|
+			class_path = "#{package_path}/#{clazz}.d"
+			
+			File.open(class_path, "w") do |file|
+				file << value.code unless value.nil?
+			end
+		end
+	end
+	
+	# Creates and returns the copyright header that is included in the top of every file
+	def copyright
+		return @copyright unless @copyright.nil?
+		
+		# Add an extra empty string in the begining because array indices begin with zero and months don't
+		months = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+		initialt_year = "2009"
+				
+		str = StringIO.new
+		date = Date.today
+		current_year = date.year.to_s
+		year = initialt_year
+		initial_created = "#{months[date.month]} #{date.day}, #{initialt_year}"
+
+		year << "-" << current_year unless initialt_year == current_year
+
+		str << "/**\n"
+		str << " * Copyright: Copyright (c) #{year} Jacob Carlborg.\n"
+		str << " * Authors: Jacob Carlborg\n"
+		str << " * Version: Initial created: #{initial_created} \n"
+		str << " * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)\n"
+		str << " */\n"
+		
+		@copyright = str.string
+	end	
+	
+	# Gets name of the framework that the given class belongs to
+	def get_framework (class_name)
+		@frameworks.each do |framework|
+			framework.files.each do |file|
+				return framework.name if file.name == class_name
+			end
+		end
+		
+		return []
+	end	
+	
+	# Gets the classes that belongs to the given file
+	def get_classes (name)		
+		classes = @classes.find_all do |clazz, value|
+			value.file == name
+		end
+		
+		return classes
+	end	
+	
+	# Generates the D code for the classes
+	def classes (classes)
+		classes.each do |clazz|
+			str = StringIO.new
+			
+			str << "class "
+			
+			if clazz == ""
+				str << clazz.name.nl(false)
+			else
+				str << clazz.name
+				str << " : "
+				str << clazz.parent.nl(false)
+			end			
+			
+			str << "{".nl(false)
+			str << methods(clazz.method, clazz.name)
+			str << "}".nl(false)
+			
+			@classes[clazz.name] ||= {}
+			@classes[clazz.name].code = str.string
+			framework = get_framework(clazz.file)
+			@classes[clazz.name].framework = framework unless framework.nil?
+			@classes[clazz.name].file = clazz.file
+		end
+	end
+	
+	# Generates the D code for the constants/globals
+	def constants (constants)
+		str = StringIO.new
+		
+		str << "private extern (C)".nl(false)
+		str << "{".nl(false)
+		str << "extern".indent.nl(false)
+		str << "{".indent.nl(false)
+		
+		constants.each do |constant|
+			type = get_type(constant.type, constant["type64"], constant["declaredType"])
+			const = constant["const"] == "true"
+			
+			if constant.type == "@"				
+				@d_constants << { :name => constant.name.dup, :type => constant.declaredType.gsub("*", ""), :const => const }
+				
+				if const
+					str << "const id".indent(2)
+				else
+					str << "id".indent(2)
+				end
+				
+				str << " "
+				str << constant["name"]
+				str << "_".nl
+			else
+				if const
+					str << "const ".indent(2)
+					str << type
+				else
+					str << "id".indent(2)
+				end
+				
+				str << " "
+				str << constant["name"].nl
+			end
+		end
+		
+		str << "}".indent.nl(false)
+		str << "}".nl(false).nl(false)
+		
+		str.string
+	end
+	
+    # Generates the D code for the constants that D can't handle directly, like classes
+	def d_constants
+		str = StringIO.new
+		
+		@d_constants.each do |constant|
+			# Deep copy constant
+			c = constant.dup
+			c.name = c.name.dup
+			c.type = c.type.dup
+			
+			str << "const " if constant.const
+			str << constant.type
+			str << " "			
+			str << constant.name.nl
+			@d_constants_static_this << c
+		end
+		
+		str << "\n"
+		@d_constants.clear
+		str.string
+	end
+	
+	# Generates the D code for the constants the has to be in a "static this"
+	def d_constants_static_this
+		str = StringIO.new
+		
+		@d_constants_static_this.each do |constant|
+			str << constant.name.indent
+			str << " = new "
+			str << constant.type
+			str << "("
+			str << constant.name
+			str << "_)".nl
+		end
+		
+		@d_constants_static_this.clear
+		str.string
+	end	
+	
+	# Generates the D code for the enums
+	def enums (enums)
+		str = StringIO.new
+		
+		enums.each do |enum|
+			str << "enum"
+								
+			if enum["name"] == ""
+				str << "\n{".nl
+				
+				enum.member.each_with_index do |member, i|
+					str << member["name"].indent
+					str << " = "
+					str << member.value
+					str << ",".nl(false) unless i == enum.member.length - 1
+				end				
+			else
+				str << enum["name"].nl
+				str << "{"
+				
+				enum["member"].each_with_index do |member, i|
+					str << member["name"].indent
+					str << " = "
+					str << member.value
+					str << ",".nl(false) unless i == enum.member.length - 1
+				end
+			end
+			
+			str << "\n}".nl.nl(false)
+		end
+		
+		str.string
+	end
+	
+	# Generates the D code for the function/method args
+	def args (args, variadic, method = false)
+		return "" if args.nil?
+		
+		str = StringIO.new
+		if variadic
+			#p args
+		end
+		args.each do |arg|
+			
+			if method || arg.type != "@"
+				type = get_type(arg.type, arg.type64, arg.declaredType)
+			else
+				type = "id"
+			end
+			
+			str << type
+			str << " "
+			str << arg["name"]
+			str << ", "
+		end
+		
+		if variadic
+		else
+		end
+		
+		str << "..." if variadic
+		
+		return str.string if variadic
+		return str.string[0 ... -2] unless variadic
+	end
+	
+	# A helper function that generates the D code for the functions/methods
+	def build_function (function, method = false, static = false)
+		str = StringIO.new
+		variadic = function["variadic"] == "true"
+		return_type  = ""
+		args = ""
+		original_type = function.returnValue[0].type
+		
+		if !method && original_type == "@"
+			return_type = "id"
+		else
+			return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType)
+			args(function.arg, variadic) unless function.arg.nil?
+		end
+		
+		str << "static " if static
+		str << return_type
+		str << " "
+		str << function["name"]
+		str << " ("
+		str << args(function["arg"], variadic, method)				
+		str << ")".nl
+		
+		str.string		
+	end
+	
+	# Generates the D code for the functions
+	def functions (functions)
+		str = StringIO.new
+		
+		str << "private extern (C)".nl(false)
+		str << "{".nl(false)
+		
+		functions.each do |function|
+			wrapper_needed = false
+			original_type = function["returnValue"][0].type
+			
+			if original_type == "@"
+				@function_wrappers << function
+				wrapper_needed = true
+			else
+				function["arg"].each do |arg|
+					if (arg.type || arg["type64"]) == "@"
+						@function_wrappers << function
+						wrapper_needed = true
+					end
+				end unless function["arg"].nil?
+			end
+			
+			return_type = get_type(function["returnValue"][0].type, function["returnValue"][0]["type64"], function["returnValue"][0]["declaredType"])
+			variadic = function["variadic"] == "true"			
+
+			str << functions_helper(function, wrapper_needed)
+		end
+		
+		str << "}".nl(false).nl(false)
+		str.string
+	end
+	
+	# A helper function that generates the D code for the functions
+	def functions_helper (function, wrapper_needed)
+		str = StringIO.new
+
+		if wrapper_needed
+			declaration = build_function(function)
+			index = declaration.index_of(" ")
+			index = declaration.index_of(" ", index)
+			str << (declaration[0 ... index] + "_" + declaration[index .. -1]).indent
+		else
+			str << build_function(function).indent
+		end
+
+		str.string
+	end	
+	
+	# Generates the D code for the functions that D can't handle without wrappers, like functions that takes
+	# objects as arguments or returns an object
+	def function_wrappers
+		str = StringIO.new
+		
+		@function_wrappers.each do |function|
+			original_type = function["returnValue"][0].type
+			variadic = function["variadic"] == "true"
+			args = StringIO.new
+			out_args = []
+			return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType)
+			
+			function["arg"].each do |arg|
+				args << arg["name"]
+				
+				if arg.type == "@"
+					args << " !is null ? "
+					args << arg["name"]
+					args << ".id : null"
+				elsif arg.type == "^@"
+					type = get_type(arg.type, arg["type64"], arg["declaredType"])
+					out_args << { :type => type[4 .. -1], :name => arg["name"] }
+					
+					args << " &"
+					args << arg["name"]
+					args << "_.id"
+				end
+				
+				args << ", "
+			end unless function["arg"].nil?
+			
+			str << build_function(function, true)[0 ... -2].nl(false)
+			str << "{".nl(false)
+			
+			out_args.each do |arg|
+				str << arg.type.indent
+				str << " "
+				str << arg.name
+				str << "_ = new "
+				str << arg.type
+				str << "(false, false)".nl
+			end
+			
+			str << "\n" if out_args.length > 0
+			
+			if original_type == "@"
+				str << "id result = ".indent
+				str << function["name"]
+			elsif original_type != "v"
+				if out_args.length > 0					
+					str << return_type.indent				
+					str << " result = "
+				else
+					str << "return ".indent
+				end
+			end
+			
+			if original_type == "v"
+				str << function["name"].indent
+			elsif original_type != "@"
+				str << "cast("
+				str << return_type
+				str << ") "
+				str << function["name"]
+			end
+			
+			str << "_"
+			str << "("			
+			str << args.string[0 ... -2] unless function["arg"].nil?
+			str << ")".nl
+			str << "\n" if out_args.length > 0
+			
+			out_args.each do |arg|
+				str << arg.name.indent(2)
+				str << " = "
+				str << arg.name
+				str << "_".nl
+			end
+			
+			if out_args.length > 0
+				str << "\n"
+				str << "return result".indent unless original_type == "v"				
+			end
+
+			if original_type == "@"
+				str << "return result !is null ? new ".indent
+				str << return_type				
+				str << "(result)".nl
+			elsif original_type != "v" && out_args.length > 0
+				str << "".nl
+			end
+			
+			str << "}".nl(false).nl(false)
+		end
+		
+		@function_wrappers.clear		
+		str.string[0 ... -2]
+	end
+	
+	# Generates the D code for the imports
+	def imports (imports, filename, framework_name = nil)
+		str = StringIO.new
+		
+		imports.each do |import|			
+			str << "import #{@package}."			
+			i = import.index('/')
+			import = import[0 ... i].downcase + import[i .. -1] if i
+			str << import.gsub("/", ".").gsub("Frameworks", "").gsub(".framework", "").gsub("Headers", "").gsub(/\.{2,}/, ".").nl
+		end
+		
+		str << "\n\n"
+		str = str.string.sort.to_s		
+		
+		return "\n\npublic:" << str if filename == framework_name
+		return str
+	end
+	
+	# Generates the D code for the methods
+	def methods (methods, class_name)
+		str = StringIO.new
+		
+		methods.each do |method|		
+			next if method.selector == ("alloc" || "init")
+				
+			return_type = get_type(method["returnValue"][0].type, method["returnValue"][0]["type64"], method["returnValue"][0]["declaredType"])
+			variadic = method["variadic"] == "true"
+			static = method["static"] == "true"
+			args = ""
+			out_args = []
+			original_type = method.returnValue[0].type
+			
+			if method.selector[0 ... 4] == "init" && return_type == "id"
+				return_type = class_name
+				method.returnValue[0].declaredType = class_name
+			end
+			
+			method["arg"].each do |arg|
+				args << " &" if arg.type == "^@"
+				args << arg["name"]
+				
+				if arg.type == "@"
+					args << " !is null ? "
+					args << arg["name"]
+					args << ".id : null"
+				elsif arg.type == "^@"
+					type = get_type(arg.type, arg.type, arg["declaredType"])
+					out_args << { :type => type[4 .. -1], :name => arg["name"] }
+					args << "_.id"
+				end
+
+				args << ", "
+			end unless method["arg"].nil?
+			
+			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
+			index = declaration.index_of(" ")
+			
+			str << (declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " ")
+			str << "{".indent.nl(false)
+			
+			out_args.each do |arg|
+				str << arg.type.indent(2)
+				str << " "
+				str << arg.name
+				str << "_ = new "
+				str << arg.type
+				str << "(false, false)".nl
+			end
+			
+			str << "\n" if out_args.length > 0
+			
+			
+			if method["returnValue"][0].type == "@"
+				str << "id result = objc_msgSend(#{this}, sel_".indent(2)
+				str << transform_selector(method["selector"])
+				str << ", " unless method.arg.nil?		
+				str << args[0 ... -2] unless method.arg.nil?
+				str << ")".nl					
+				str << "\n" if out_args.length > 0	
+				
+				out_args.each do |arg|
+					str << arg.name.indent(2)
+					str << " = "
+					str << arg.name
+					str << "_".nl
+				end
+				
+				str << "\n" if out_args.length > 0
+				
+				if method["returnValue"][0]["declaredType"] == class_name
+					str << "return result is this.id ? this : (return result ".indent(2)
+				else
+					str << "return result ".indent(2)
+				end
+				
+				str << "!is null ? new "
+				str << return_type					
+				str << "(result) : null"
+				
+				if method["returnValue"][0]["declaredType"] == class_name
+					str << ")".nl
+				else
+					str << "".nl
+				end
+				
+				str << "}".indent.nl(false).nl(false)				
+			else
+				if original_type == "d" || original_type == "f"
+					
+					str << "version (X86)".indent(2).nl(false)
+					
+					if out_args.length > 0
+						str << return_type.indent(3)
+						str << " result "
+					else						
+						if original_type == "d"
+							str << "return ".indent(3)
+						else
+							str << "return cast(".indent(3)
+							str << return_type
+							str << ") "
+						end							
+					end
+					
+					str << "objc_msgSend_fpret(#{this}, sel_"
+					str << transform_selector(method["selector"])
+					str << ", " unless method.arg.nil?
+
+					args = ""
+
+					method["arg"].each do |arg| 
+						args << arg["name"]
+						args << ", "
+					end unless method["arg"].nil?
+
+					str << args[0 ... -2] if args.length > 0
+					str << ")".nl.nl(false)
+					
+					str << "else".indent(2).nl(false)
+					
+					if out_args.length > 0
+						str << return_type.indent(3)
+						str << " result "
+					else						
+						if original_type == "d"
+							str << "return ".indent(3)
+						else
+							str << "return cast(".indent(3)
+							str << return_type
+							str << ") "
+						end							
+					end
+					
+					str << "objc_msgSend(#{this}, sel_"
+					str << transform_selector(method["selector"])
+					str << ", " unless method.arg.nil?
+
+					args = ""
+
+					method["arg"].each do |arg| 
+						args << arg["name"]
+						args << ", "
+					end unless method["arg"].nil?
+
+					str << args[0 ... -2] if args.length > 0
+					str << ")".nl
+					str << "\n" if out_args.length > 0					
+
+					out_args.each do |arg|
+						str << arg.name.indent(3)
+						str << " = "
+						str << arg.name
+						str << "_".nl
+					end
+
+					if out_args.length > 0
+						str << "\n"
+						str << "retrun result".indent(3).nl
+					end
+
+					str << "\n" if out_args.length > 0			
+					str << "}".indent.nl(false).nl(false)					
+				else
+					unless return_type == "void"					
+						if out_args.length > 0
+							str << return_type.indent(2)
+							str << " result "
+						else
+							str << "return cast(".indent(2)
+						end
+
+						str << return_type
+						str << ") "
+					end
+
+					str << "objc_msgSend(#{this}, sel_".indent(2) if return_type == "void"
+					str << "objc_msgSend(#{this}, sel_" unless return_type == "void"
+					str << transform_selector(method["selector"])
+					str << ", " unless method.arg.nil?
+
+					args = ""
+
+					method["arg"].each do |arg| 
+						args << arg["name"]
+						args << ", "
+					end unless method["arg"].nil?
+
+					str << args[0 ... -2] if args.length > 0
+					str << ")".nl
+
+					str << "\n" if out_args.length > 0
+
+					out_args.each do |arg|
+						str << arg.name.indent(2)
+						str << " = "
+						str << arg.name
+						str << "_".nl
+					end
+
+					if out_args.length > 0
+						str << "\n"
+						str << "retrun result".indent(2).nl
+					end
+							
+					str << "}".indent.nl(false).nl(false)
+				end				
+			end
+		end
+		
+		str.string[0 .. -2]
+	end
+	
+	# Generates the D code for the structs
+	def structs (structs)
+		str = StringIO.new
+		
+		structs.each do |struct|
+			str << "struct "
+			str << struct.name.nl(false)
+			str << "{".nl
+			
+			struct.member.each do |member|
+				type = get_type(member.type, member.type64, member.declaredType)
+				
+				str << type.indent
+				str << " "
+				str << member.name.nl
+			end unless struct.member.nil?
+			
+			str << "}".nl
+			str << "\n\n"
+		end
+		
+		str.string[0 .. -2]
+	end
+	
+	# Generates the D code for the typedefs
+	def typedefs (typedefs)
+		str = StringIO.new
+
+		typedefs.each do |typedef|
+			
+			type = ""
+			struct = false
+			
+			if typedef.type.struct?
+				type = get_struct_type(typedef.type, typedef["type64"], typedef["declaredType"])
+				struct = true
+			else
+				type = get_type(typedef.type, typedef.type64, typedef.declaredType)
+			end
+			
+			# Special case
+			type = "wchar" if typedef.name == "unichar"	
+			
+			if struct
+				str << typedef["declaredType"].gsub("*", "").nl
+				str << "alias "				
+				str << type[:name]
+				str << " "
+				str << typedef["name"].nl
+			else
+				str << "alias "
+				str << type
+				str << " "
+				str << typedef.name.nl
+			end
+		end
+
+		str << "\n"
+		str.string
+	end
+	
+	# Adds specific D extensions to classes, like opIndex and opApply
+	def d_class_extensions (args)
+		
+	end
+	
+	# Checks if the declared type should be used instead of the type
+	# type:: the type to check
+	#
+	def check_declared_type (type)		
+		case type
+			when "unichar"; return "wchar"
+			when "BOOL"; return "bool"
+			when "CGFloat"; return type
+			when "NSInteger"; return type
+			when "NSUInteger"; return type
+				
+			when "unichar*"; return "wchar*"
+			when "BOOL*"; return "bool*"
+			when "CGFloat*"; return type
+			when "NSInteger*"; return type
+			when "NSUInteger*"; return type
+				
+			when "unichar**"; return "wchar**"
+			when "BOOL**"; return "bool**"
+			when "CGFloat**"; return type
+			when "NSInteger**"; return type
+			when "NSUInteger**"; return type
+			else return nil;
+		end
+	end
+	
+	# Gets the method name from the supplied selector
+	# selector:: the selector to get the method name from
+	#
+	# === Example:
+	# get_method_name("initWithContentsOfURL:options:error:")       #=> initWithContentsOfURL
+	#
+	def get_method_name (selector)
+		i = selector.index_of(":")
+		selector[0 ... i]
+	end
+	
+	# Gets the D type from the encoded C/Objective-C type
+	# type:: the type
+	# type64:: the type for 64bit targets
+	# declared_type:: the declared type
+	#
+	# === Example:
+	# get_type("I", "Q", "NSUInteger")      #=> NSUInteger
+	# get_type("I", "I", "unsigned int")    #=> uint
+	#
+	def get_type (type, type64, declared_type)
+				
+		return declared_type if type.nil? || type64.nil?			
+				
+		t = check_declared_type(declared_type)
+		return t unless t.nil?
+		
+		unless type64 == "" || type64.nil?
+			return declared_type if type != type64
+		end
+		
+		case type
+		when "c"; return "byte"
+		when "i"; return "int"
+		when "s"; return "short"
+		when "l"; return "int"
+		when "q"; return "long"
+		when "C"; return "ubyte"
+		when "I"; return "uint"
+		when "S"; return "ushort"
+		when "L"; return "uint"
+		when "Q"; return "ulong"
+		when "f"; return "float"
+		when "d"; return "double"
+		when "B"; return "bool"
+		when "v"; return "void"
+		when "*"; return "char*"
+		when '#'; return "Class"
+		when ":"; return "SEL"					
+		when "@"
+			return declared_type.gsub(/\*+/, "") unless declared_type.nil?
+			raise "No declared type given"
+		else
+			case type[0, 1]
+			when "["
+				str = ""
+				t = type[1 ... -1]
+				count = $1 if t =~ /(\d+)/				
+				t = $'
+				
+				t64 = type64[1 ... -1]
+				count = $1 if t64 =~ /(\d+)/				
+				t64 = $'
+				
+				str = get_type(t, t64, declared_type)
+				str << "[#{count}]"
+			
+				return str
+			when "("
+				resolved_types = []
+				types = $2 if type =~ /\((.+)=(.+)\)/
+				types64 = $2 if type64 =~ /\((.+)=(.+)\)/
+				
+				for i in types
+					resolved_types << get_type(types[i], types64[i], declared_type)
+				end
+				
+				return resolved_types
+			when "^"				
+				if type == "^@"
+					return "out " << get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
+				elsif type.length > 2 && type[0 ... 2] == "^^"
+					return "out " << get_type(type[2 .. -1], type64[2 .. -1], declared_type).dup
+				elsif type == "^?"
+					tmp = cfp_to_dfp(type)
+					return tmp unless tmp.nil?
+				end
+				
+				if !type.nil? && !type64.nil?
+					return get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup << "*"
+				elsif !type.nil?
+					return get_type(type[1 .. -1], type64, declared_type).dup << "*"
+				end			
+			when "{"
+				return declared_type
+			end
+		end
+		
+		return declared_type
+	end
+	
+	# Gets the D type from the encoded C/Objective-C type when it's a struct
+	# type:: the type
+	# type64:: the type for 64bit targets
+	# declared_type:: the declared type
+	#
+	# === Example
+	# get_struct_type("{some=III}", "{some=III}", "struct some")
+	# # outputs below
+    # { :name => "some", :types => ["uint", "uint", "uint"] }
+	#
+	def get_struct_type (type, type64, declared_type)
+		
+		return { :name => declared_type } if declared_type[0 ... 2] == "NS"
+		
+		case type[0, 1]
+		when "{"
+			resolved_types = []
+		
+			if type =~ /\^{0,}\{(.{0,})=(.{0,})\}/
+				name = $1
+				types = $2
+			elsif type =~ /\^{0,}\((.{0,})=(.{0,})\)/
+				name = $1
+				types = $2
+			end
+		
+			unless types.nil?
+				types.each_char do |t|
+					resolved_types << get_type(t, type64, declared_type)
+				end
+			end
+			
+			name = declared_type if name.nil?
+		
+			return { :name => name, :types => resolved_types }
+		when "^"
+			get_struct_type(type[1 .. -1], type64, declared_type)
+			hash = get_struct_type(type[1 .. -1], type64, declared_type)
+			hash[:name].dup << "*"
+			return hash
+		end
+	end
+	
+	# C Function Pointer to D Function Pointer
+	def cfp_to_dfp (fp)
+		reg = /(\w+)\s*\(\*(\w*)\)\s*\((.*)\)/
+		
+		return nil if fp !~ reg
+		
+		return_type = $1
+		name = $2
+		arg_types = $3
+		
+		return "#{return_type} function (#{arg_types})"
+	end
+	
+	# Is the supplied argument an "out" argument
+	# arg:: the arg
+	#
+	# === Example:
+	# out_arg?("out NSError")       #=> true
+	#
+	def out_arg? (arg)
+		return arg[0 .. 4] == "out "
+	end	
+	
+	# Transform the supplied selector to a valid D representation
+	# selector:: the selector to transform
+	#
+	# === Example:
+	# transform_selector("initWithContentsOfURL:options:error:")
+	# # outputs below
+	# initWithContentsOfURL_options_error_
+	#
+	def transform_selector (selector)
+		selector.gsub(/:/, "_")
+	end	
+end
+
+# Prints the message to stderr, exits
+def die (*msg)
+	$stderr.puts msg
+	exit 1
+end
+
+if __FILE__ == $0
+	objc_to_d = ObjcToD.new
+	
+	OptionParser.new do |opts|
+		opts.banner = "Usage: #{File.basename(__FILE__)} [options] <dstep files...>"
+		opts.separator ""
+		opts.separator "Options:"
+		
+		opts.on("-o", "--output DIRECTORY", "Place the output files in this directory'") do |opt|
+			die "The specified directory \"#{opt}\" does not exists" if File.exist?(opt) == false
+			die "Output directory cannot be specified more than once" if objc_to_d.out_dir
+			objc_to_d.out_dir = opt
+		end		
+		
+		help_msg = "Use the `-h' flag or for help."	
+			
+		opts.on("-h", "--help", "Show this message.") do
+			puts opts, help_msg
+			exit
+		end
+		
+		opts.on('-v', '--version', 'Show version.') do
+			puts ObjcToD::VERSION
+			exit
+		end
+		
+		opts.separator ""
+		
+		if ARGV.empty?			
+			die opts.banner
+		else
+			#begin
+				opts.parse!(ARGV)
+				
+				die "No output directory given" if objc_to_d.out_dir.nil?
+				
+				ARGV.each do |file|
+					objc_to_d.files << file
+				end
+				
+				objc_to_d.generate_code
+				objc_to_d.output_code
+			# rescue => e
+			# 	msg = e.message
+			# 	msg = "Internal error" if msg.empty?
+			# 	
+			# 	die msg, opts.banner, help_msg
+			# end
+		end
+	end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/dstepgen.rb	Thu Jun 18 22:00:13 2009 +0200
@@ -0,0 +1,1451 @@
+#!/usr/bin/env ruby
+
+# Copyright (c) 2008-2009, Jacob Carlborg. All rights reserved.
+# Copyright (c) 2006-2007, Apple Inc. All rights reserved.
+# Copyright (c) 2005-2006 FUJIMOTO Hisakuni
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+# 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+#     its contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+ 
+require "rubygems"
+gem "builder", "~> 2.0"
+require "builder"
+require "tmpdir"
+require "optparse"
+include Builder
+
+$KCODE = "UTF8"
+
+# Extensions that adds support for member access syntax
+class Hash	
+	def type
+		result = self["type"]
+		return result unless result.nil?
+		self[:type]
+	end
+	
+	def type= (type)
+		self[:type] = type
+	end
+	
+	def id
+		result = self["id"]
+		return result unless result.nil?
+		self[:id]
+	end
+	
+	def id= (id)
+		self[:id] = id
+	end
+	
+	def methods
+		result = self["methods"]
+		return result unless result.nil?
+		self[:methods]
+	end
+	
+	def methods= (methods)
+		self[:methods] = methods
+	end
+	
+	def method_missing (method, *args)
+		self.class.instance_eval do
+			define_method(method) do |*args|
+				if args.length > 0
+					self[method[0 ... -1]] = args[0]
+					self[eval(":#{method}"[0 ... -1])] = args[0]
+				else
+					result = self[method]
+					return result unless result.nil?
+					self[eval(":#{method}")]
+				end
+			end
+		end
+		
+		if (method = method.id2name) =~ /=/
+			eval("self.#{method} (args.length < 2 ? args[0] : args)")
+		else
+			eval("self.#{method}")
+		end
+	end
+end
+
+# This Struct represents an Objective-C Framework
+Framework = Struct.new(:name, :headers, :path) do
+	def initialize
+		self.headers = []
+		self.name = ""
+		self.path = ""
+	end
+end
+
+# This Struct represents a C/Objective-C header
+HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :defines, :enums, :externs, :functions,
+			  			:imports, :inline_functions, :opaques, :path, :structs, :typedefs) do
+	def initialize
+		self.name = ""
+		self.cftypes = []
+		self.constants = []
+		self.defines = []
+		self.enums = []
+		self.externs = []
+		self.framework = ""
+		self.functions = []
+		self.imports = []
+		self.inline_functions = []
+		self.opaques = []
+		self.path = ""
+		self.structs = []
+		self.typedefs = []
+	end	
+end
+
+# This class scans the headers
+class HeaderScaner
+	CPP = ['/usr/bin/cpp-4.0', '/usr/bin/cpp-3.3', '/usr/bin/cpp3'].find { |x| File.exist?(x) }
+	raise "cpp not found" if CPP.nil?
+	CPPFLAGS = "-D__APPLE_CPP__ -include /usr/include/AvailabilityMacros.h"
+	CPPFLAGS << "-D__GNUC__" unless /\Acpp-4/.match(File.basename(CPP))
+	
+	attr_accessor :frameworks, :headers, :do_64bit
+	
+	def initialize
+		@extern_name = 'extern'
+		@frameworks = []
+		@file_content = nil
+		@headers = []
+		@classes = {}
+		@informal_protocols = {}
+		@function_pointer_types = {}
+		@do_64bit = false
+	end
+	
+	def classes
+		@classes
+	end
+	
+	def protocols
+		@informal_protocols
+	end
+	
+	def cftypes (header)
+		re = /typedef\s+(const\s+)?(struct\s*\w+\s*\*\s*)([^\s]+Ref)\s*;/
+		@cpp_result.scan(re).each do |m|
+			header.cftypes << { :name => m[2], :type => m[1], :const => m[0] =~ /const/ ? true : false}
+		end
+	end
+	
+	def constants (header)
+		tmp = header.externs.map do |i|
+			constant?(i, true)
+		end
+		
+		header.constants = tmp.flatten.compact
+	end
+	
+	def defines (header)
+		re = /#define\s+([^\s]+)\s+(\([^)]+\)|[^\s]+)\s*$/
+		@file_content.scan(re).each do |m|
+			next unless !m[0].include?('(') && m[1] != '\\'
+			header.defines <<  { :name => m[0], :value => m[1] }
+		end
+	end
+	
+	def enums (header)
+		re = /\benum\b\s*(\w+\s+)?\{([^}]*)\}/
+		@cpp_result.scan(re).each do |m|
+			enum = { :name => m[0], :members => [] }
+			
+			m[1].split(",").map do |i|
+				name, value = i.split("=", 2).map do |x|
+					x.strip
+				end
+				
+				enum[:members] << { :name => name, :value => value } unless name.empty? || name[0] == ?#
+			end
+			
+			header.enums << enum
+		end
+	end
+	
+	def function_pointer_types (header)
+		re = /typedef\s+([\w\s]+)\s*\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*;/
+		data = @cpp_result.scan(re)
+		re = /typedef\s+([\w\s]+)\s*\(([^)]+)\)\s*;/
+		data |= @cpp_result.scan(re).map do |m|
+			ary = m[0].split(/(\w+)$/)
+			ary[1] << " *"
+			ary << m[1]
+			ary
+		end
+		
+		data.each do |m|
+			name = m[1]
+			args = m[2].split(",").map do |x|
+				if x.include?(" ")
+					ptr = x.sub!(/\[\]\s*$/, "")
+					x = x.sub(/\w+\s*$/, "").strip
+					ptr ? x + "*" : x
+				else
+					x.strip
+				end
+			end
+			
+			type = "#{m[0]}(*)(#{args.join(', ')})"
+			@function_pointer_types[name] = type
+		end
+	end
+	
+	def typedefs (header)
+		re = /^\s*typedef\s+(.+)\s+([\w\*]+)\s*;$/
+		data = @cpp_result
+		data.scan(re).each do |m|
+			var = get_var_info(m[0] + " " + m[1])
+			header.typedefs << get_var_info(m[0] + " " + m[1]) if var
+		end
+	end
+	
+	def externs (header)
+		re = /^\s*#{@extern_name}\s+\b(.*)\s*;.*$/
+		header.externs = @cpp_result.scan(re).map do |m|
+			m[0].strip
+		end
+	end
+	
+	def imports (header)
+		tmp = []
+			
+		@file_content.each do |line|
+			if line =~ /#(include|import) <(.+)\.h>/
+				next if $2 == header.name
+				tmp << $2
+			elsif line =~ /@class(\s+)(\w+)(,|;)/
+				next if $2 == header.name
+				
+				if $3 == ";"
+					tmp << header.framework + "/" + $2 unless header.framework == ""
+					tmp << $2 if header.framework == ""
+				elsif
+					str = line[6 + $1.length ... -2]
+					str.gsub!(" ", "")
+					arr = str.split(",")
+					
+					arr.each do |s|
+						tmp << header.framework + "/" + s unless header.framework == ""
+						tmp << s if header.framework == ""
+					end
+				end
+			end
+		end
+		
+		header.imports = tmp.compact.uniq
+	end
+	
+	def informal_protocols (header)
+		self.methods(header)
+	end	
+	
+	def methods (header)
+		interface_re = /^@(interface|protocol)\s+(\w+)\s*:?\s*(\w*)\s*(\([^)]+\))?/
+		
+		end_re = /^@end/
+		body_re = /^[-+]\s*(\([^)]+\))?\s*([^:\s;]+)/
+		args_re = /\w+\s*:/
+		prop_re = /^@property\s*(\([^)]+\))?\s*([^;]+);$/
+		current_interface = current_category = nil
+		i = 0
+		parent = nil	
+		
+		@cpp_result.each_line do |line|
+			size = line.size
+			line.strip!
+			
+			if md = interface_re.match(line)
+				parent = nil
+				current_interface = md[1] == "protocol" ? "NSObject" : md[2]
+				current_category = md[4].delete("()").strip if md[4]
+				parent = md[3] unless md[3] == ""
+				
+			elsif end_re.match(line)
+				current_interface = current_category = nil
+				
+			elsif current_interface && md = prop_re.match(line)
+				# Parsing Objective-C 2.0 properties
+				if (a = md[2].split(/\s/)).length >= 2 && /^\w+$/.match(name = a[-1]) && (type = a[0 .. -2].join(" ")).index(",").nil?
+					getter, setter = name, "set#{name[0].chr.upcase + name[1 .. -1]}"
+					readonly = false
+					
+					if attributes = md[1]
+						if md = /getter\s*=\s*(\w+)/.match(attributes)
+							getter = md[1]
+						end
+						
+						if md = /setter\s*=\s*(\w+)/.match(attributes)
+							setter = md[1]
+						end
+						
+						readonly = true if attributes.index("readonly")
+					end
+					
+					typeinfo = VarInfo.new(type, "", "")
+					
+					@classes[current_interface] ||= {}					
+					methods = (@classes[current_interface].methods ||= [])
+					methods << MethodInfo.new(typeinfo, getter, false, [], line)
+					
+					unless readonly
+						methods << MethodInfo.new(VarInfo.new("void", "", ""), setter + ":", false, [typeinfo], line)
+					end
+				end
+				
+			elsif current_interface && (line[0] == ?+ || line[0] == ?-)
+				mtype = line[0]
+				data = @cpp_result[i .. -1]
+				body_md = body_re.match(data)
+				
+				next if body_md.nil?
+				
+				rettype = body_md[1] ? body_md[1].delete("()") : "id"
+				retval = VarInfo.new(rettype, "", "")
+				args = []
+				selector = ""
+				data = data[0 .. data.index(";")]
+				args_data = []
+				
+				data.scan(args_re) do |x|
+					args_data << [$`, x, $']
+				end
+				
+				variadic = false
+				args_data.each_with_index do |ary, n|
+					before, argname, argtype = ary
+					arg_nameless = (n > 0 && /\)\s*$/.match(before))
+					argname = ":" if arg_nameless
+					realargname = nil
+					
+					if n < args_data.length - 1
+						argtype.sub!(args_data[n + 1][2], "")
+						
+						if arg_nameless
+							argtype.sub!(/(\w+\s*)?\w+\s*:\s*$/, "")
+						else
+							unless argtype.sub!(/(\w+)\s+\w+:\s*$/)	{ |s| realargname = $1; "" }
+								# maybe the next argument is nameless
+								argtype.sub!(/\w+\s*:\s*$/, "")
+							end
+						end
+					else
+						argtype.sub!(/\s+__attribute__\(\(.+\)\)/, "")
+						
+						if arg_nameless
+							argtype.sub!(/\w+\s*;$/, "")
+						else
+							unless argtype.sub!(/(\w+)\s*;$/) { |s| realargname = $1; "" }
+								variadic = argtype.sub!(/,\s*\.\.\.\s*;/, "") != nil
+								argtype.sub!(/\w+\s*$/, "") if variadic
+							end
+						end
+					end
+					
+					selector << argname
+					realargname ||= argname.sub(/:/, "")
+					args << VarInfo.new(argtype, realargname, "") unless argtype.empty?
+				end
+				
+				selector = body_md[2] if selector.empty?
+				args << VarInfo.new("...", "vararg", "") if variadic
+				method = MethodInfo.new(retval, selector, line[0] == ?+, args, data)
+				
+				if current_category && current_interface == "NSObject"
+					(@informal_protocols[current_category] ||= []) << method
+				end
+				
+				@classes[current_interface] ||= {}
+				
+				if header.name == current_interface				
+					@classes[current_interface].file = header.name
+				else
+					@classes[current_interface].file ||= header.name
+				end
+				
+				unless parent == current_interface || parent =~ /\s+/ || parent.nil?
+					@classes[current_interface].parent = parent
+				end				
+				
+				(@classes[current_interface].methods ||= []) << method
+			end
+			i += size
+		end
+	end	
+	
+	def structs (header)
+		re = /typedef\s+struct\s*\w*\s*((\w+)|\{([^{}]*(\{[^}]+\})?)*\}\s*([^\s]+))\s*(__attribute__\(.+\))?\s*;/
+		i = 0
+		body = nil
+		@cpp_result.scan(re).each do |m|
+			struct = { :name => m[4], :members => [] }
+			
+			unless struct[:name].nil?
+				if struct[:name][0, 1] == "*"
+					struct[:name].sub!("*", "")
+				end
+			end
+			
+			return_type = nil
+			stripped_return_type = nil
+			body = m[2]
+			
+			if m[2]
+				m[2].split(/,|;/).map do |i|				
+					str, bytes = i.split(":", 2).map do |x|
+						x.strip
+					end
+	
+					var = get_var_info(str, true)
+	
+					if var				
+						if var.return_type == "***dummy***"
+							var.return_type = return_type
+							var.stripped_return_type = stripped_return_type
+						else
+							return_type = var.return_type
+							stripped_return_type = var.stripped_return_type
+						end
+	
+						struct[:members] << { :name => var.name, :bytes => bytes, :declaredType => var.return_type, :type => "", :type64 => "" } unless str.empty? || str[0] == ?#
+						
+						names = []
+						
+						tmp = struct[:members].collect do |member|
+							unless names.include?(member[:name])
+								names << member[:name]
+								member
+							end
+						end
+						
+						struct[:members] = tmp.compact
+					end
+				end
+			end
+			
+			header.structs << struct if body
+		end
+	end
+	
+	def functions (header, inline = false)
+		if inline
+			inline_func_re = /(inline|__inline__)\s+((__attribute__\(\([^)]*\)\)\s+)?([\w\s\*<>]+)\s*\(([^)]*)\)\s*)\{/
+			res = @cpp_result.scan(inline_func_re)
+			res.each do |x|
+				x.delete_at(0)
+				x.delete_at(1)
+			end
+		else
+			skip_inline_re = /(static)?\s(inline|__inline__)[^{;]+(;|\{([^{}]*(\{[^}]+\})?)*\})\s*/
+			func_re = /(^([\w\s\*<>]+)\s*\(([^)]*)\)\s*)(__attribute__[^;]+)?;/
+			res = @cpp_result.gsub(skip_inline_re, '').scan(func_re)
+		end
+		
+		funcs = res.map do |m|
+			orig, base, args = m			
+			base.sub!(/^.*extern\s/, "")
+			func = constant?(base)
+			
+			if func
+				args = args.strip.split(",").map do |i|
+					constant?(i)
+				end
+				
+				next if args.any? do |x|
+					x.nil?
+				end
+				
+				args = [] if args.size == 1 && args[0].return_type == "void"	
+				FunctionInfo.new(func, args, orig, inline)
+			end
+		end.compact
+		
+		if inline
+			header.inline_functions = funcs
+		else
+			header.functions = funcs
+		end
+	end
+	
+	def prepare (path)		
+		@file_content = File.read(path)
+		@file_content.gsub!(%r{(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)}, "");
+		@complete_cpp_result, @cpp_result = do_cpp(path, false, true, "")
+	end	
+	
+	def scan (frameworks, headers)
+		@frameworks = frameworks
+		@headers = headers
+		
+		@frameworks.each do |framework|			
+			framework.headers.each do |header|
+				prepare(header.path)
+				
+				imports(header)
+				cftypes(header)
+				externs(header)
+				constants(header)
+				enums(header)
+				structs(header)
+				typedefs(header)
+				functions(header)
+				functions(header, true)
+				defines(header)
+				methods(header)
+				function_pointer_types(header)
+			end
+		end
+		
+		@headers.each do |header|
+			prepare(header.path)
+			
+			imports(header)
+			cftypes(header)
+			externs(header)
+			constants(header)
+			enums(header)
+			structs(header)
+			typedefs(header)
+			functions(header)
+			functions(header, true)
+			defines(header)
+			methods(header)
+			function_pointer_types(header)
+		end
+	end
+	
+	def get_var_info (str, multi = false)
+		str.strip!
+		
+		return nil if str.empty?
+		
+		if str == "..."
+			VarInfo.new("...", "...", str)
+		else
+			str = "***dummy*** " + str if str[-1].chr == '*' || str.index(/\s/).nil?	
+			tokens = multi ? str.split(',') : [str]
+			part = tokens.first
+			re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/
+			m = re.match(part)	
+	
+			if m
+				return nil if m[1].split(/\s+/).any? do |x|
+					['end', 'typedef'].include?(x)
+				end
+				
+				m = m.to_a[1..-1].compact.map do |i|
+					i.strip
+				end
+				
+				m[0] += m[2] if m.size == 3
+				m[0] = 'void' if m[1] == 'void'
+				
+				var = begin
+					VarInfo.new(m[0], m[1], part)
+				rescue
+					return nil
+				end
+				
+				if tokens.size > 1
+					[var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }]
+				else
+					var
+				end				
+			end
+		end
+	end
+	
+	def constant? (str, multi = false)
+		str.strip!
+		return nil if str.empty?
+		
+		if str == '...'
+			VarInfo.new('...', '...', str)
+		else
+			str << " dummy" if str[-1].chr == '*' or str.index(/\s/).nil?
+			tokens = multi ? str.split(',') : [str]
+			part = tokens.first
+			re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/
+			m = re.match(part)
+			
+			if m
+				return nil if m[1].split(/\s+/).any? do |x|
+					['end', 'typedef'].include?(x)
+				end
+				
+				m = m.to_a[1..-1].compact.map do |i|
+					i.strip
+				end
+				
+				m[0] += m[2] if m.size == 3
+				m[0] = 'void' if m[1] == 'void'
+				
+				var = begin
+					VarInfo.new(m[0], m[1], part)
+				rescue
+					return nil
+				end
+				
+				if tokens.size > 1
+					[var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }]
+				else
+					var
+				end
+			end
+		end
+	end	
+	
+	class VarInfo
+		
+		attr_reader :name, :orig, :const, :type_modifier
+		attr_accessor :octype, :resolved_type, :resolved_type64, :return_type, :stripped_return_type
+		
+		def initialize (type, name, orig)
+			@return_type = type.clone
+			@name = name
+			@orig = orig
+			@const = false
+			@type_modifier = ""
+			
+			@return_type.gsub!(/\[[^\]]*\]/, "*")
+			
+			if @return_type =~ /\bconst\b/
+				@const = true
+				@return_type.gsub!("const", "")
+			end
+			
+			if @return_type =~ /\b(in|out|inout|oneway|bycopy|byref)\b/
+				
+				case $1
+				when "in"
+					@type_modifier << "n"
+				when "out"
+					@type_modifier << "o"
+				when "inout"
+					@type_modifier << "N"
+				when "oneway"
+					@type_modifier << "w"
+				when "bycopy"
+					@type_modifier << "c"
+				when "byref"
+					@type_modifier << "r"
+				end
+				
+				@return_type.gsub!("#{$1}", "")
+			end
+			
+			@return_type.gsub!(/\s?\*\s?/, "*")
+			@return_type.gsub!(/^\(|\)$/, "")
+			@return_type.strip!
+			
+			t = type.gsub(/\b(__)?const\b/, "")
+			t.gsub!(/<[^>]*>/, '')
+			t.gsub!(/\b(in|out|inout|oneway|const)\b/, "")
+			t.gsub!(/\b__private_extern__\b/, "")
+			t.gsub!(/^\s*\(?\s*/, "")
+			t.gsub!(/\s*\)?\s*$/, "")
+			
+			raise "Empty type (was '#{type}')" if t.empty?
+			
+			@stripped_return_type = t
+		end
+		
+		def function_pointer? (function_pointer_types)
+			type = @function_pointer_types[@stripped_return_type] || @stripped_return_type
+			@function_pointer_type ||= FunctionPointerInfo.new_from_type(type)
+		end
+		
+		def <=>(x)
+			self.name <=> x.name
+		end					
+		
+		def hash
+			@name.hash
+		end
+		
+		def eql? (o)
+			@name == o.name
+		end
+	end
+ 
+	class FunctionInfo < VarInfo
+		
+		attr_reader :args, :argc
+		
+		def initialize (function, args, orig, inline = false)
+			super(function.return_type, function.name, orig)
+			
+			@args = args
+			@argc = @args.size
+			@variadic = false
+			
+			if @args[-1] && @args[-1].return_type == "..."
+				@argc -= 1
+				@variadic = true
+				@args.pop
+			end
+			
+			@inline = inline
+			self
+		end
+		
+		def variadic?
+			@variadic
+		end
+		
+		def inline?
+			@inline
+		end
+	end
+	
+	class FunctionPointerInfo < FunctionInfo
+		def initialize (return_type, arg_types, orig)
+			args = arg_types.map do |x|
+				VarInfo.new(x, "", "")
+			end
+			
+			super(VarInfo.new(return_type, "", ""), args, orig)
+		end
+		
+		def self.new_from_type (type)
+			@cache ||= {}
+			info = @cache[type]
+			
+			return info if info
+			
+			tokens = type.split(/\(\*\)/)
+			return nil if tokens.size != 2
+			
+			return_type = tokens.first.strip
+			rest = tokens.last.sub(/^\s*\(\s*/, "").sub(/\s*\)\s*$/, "")
+			
+			arg_types = rest.split(/,/).map do |x|
+				x.strip
+			end
+			
+			@cache[type] = self.new(return_type, arg_types, type)
+		end
+	end
+	
+	class MethodInfo < FunctionInfo
+		
+		attr_reader :selector
+		
+		def initialize (method, selector, is_class, args, orig)
+			super(method, args, orig)
+			
+			@selector = selector
+			@is_class = is_class
+			self
+		end
+		
+		def class_method?
+			@is_class
+		end
+		
+		def <=>(o)
+			@selector <=> o.selector
+		end
+		
+		def hash
+			@selector.hash
+		end
+		
+		def eql? (o)
+			@selector == o.selector
+		end
+	end
+	
+	def do_cpp (path, fails_on_error = true, do_64 = true, flags = "")
+	    f_on = false
+	    err_file = '/tmp/.cpp.err'
+	    cpp_line = "#{CPP} #{CPPFLAGS} #{flags} #{do_64 ? '-D__LP64__' : ''} \"#{path}\" 2>#{err_file}"
+	    complete_result = `#{cpp_line}`
+		
+		if $?.to_i != 0 && fails_on_error
+			$stderr.puts File.read(err_file)
+			File.unlink(err_file)
+			raise "#{CPP} returned #{$?.to_int/256} exit status\nline was: #{cpp_line}"
+		end
+		
+		result = complete_result.select do |s|
+			# First pass to only grab non-empty lines and the pre-processed lines
+			# only from the target header (and not the entire pre-processing result).
+			next if s.strip.empty?
+			m = %r{^#\s*\d+\s+"([^"]+)"}.match(s)
+			f_on = (File.basename(m[1]) == File.basename(path)) if m
+			f_on
+		end.select do |s|
+			# Second pass to ignore all pro-processor comments that were left.
+			/^#/.match(s) == nil
+		end.join
+		
+		File.unlink(err_file)
+		return [complete_result, result]
+	end
+end
+
+class DStepGenerator
+	
+	VERSION = 1.0
+	
+	attr_accessor :out_file, :scaner, :code_to_inject
+	
+	def initialize
+		@do_64bit = false
+		@frameworks = []
+		@framework_paths = []
+		@headers = []
+		@import_directives = "#import <Foundation/Foundation.h>\n"
+		@informal_protocols = []
+		@classes = []
+		@scaner = HeaderScaner.new
+		@scaner.do_64bit = @do_64bit
+		@umbrella_framework = nil
+		@handled_dependencies = []
+		
+		# link to foundation framework by default
+		@compiler_flags = "-framework Foundation"
+	end
+	
+	def do_64bit
+		return @do_64bit
+	end
+	
+	def do_64bit= (do_64bit)
+		@do_64bit = do_64bit
+		@scaner.do_64bit = do_64bit
+	end	
+	
+	def collect		
+		scaner.scan(@frameworks, @headers)
+		@classes = scaner.classes
+		@informal_protocols = scaner.protocols
+	end
+	
+	def handle_framework (framework, sub_framework = false, parent_framework = nil)
+		val = framework.name
+		path = framework_path(val)
+		
+		raise "Can't locate framework '#{val}'" if path.nil?
+		@framework_paths << File.dirname(path)
+		raise "Can't find framework '#{val}'" if path.nil?
+		
+		parent_path, name = path.scan(/^(.+)\/(\w+)\.framework\/?$/)[0]
+		
+		if @private
+			headers_path = File.join(path, "PrivateHeaders")
+			raise "Can't locate private framework headers at '#{headers_path}'" unless File.exist?(headers_path)
+			
+			headers = Dir.glob(File.join(headers_path, "**", "*.h"))
+			public_headers_path = File.join(path, "Headers")
+			public_headers = if File.exist?(public_headers_path)
+				HeaderScaner::CPPFLAGS << " -I#{public_headers_path} "
+				Dir.glob(File.join8(headers_path, "**", "*.h"))
+			else
+				[]
+			end
+		else
+			headers_path = File.join(path, "Headers")
+			raise "Can't locate public framework headers at '#{headers_path}'" unless File.exist?(headers_path)
+			public_headers = headers = Dir.glob(File.join(headers_path, "**", "*.h"))
+		end
+		
+		# We can't just "#import <x/x.h>" as the main Framework header might not include _all_ headers.
+		# So we are tricking this by importing the main header first, then all headers.
+	    header_basenames = (headers | public_headers).map do |x|
+	    	x.sub(/#{headers_path}\/*/, "")
+	    end
+			
+		if idx = header_basenames.index("#{name}.h")
+			header_basenames.delete_at(idx)
+			header_basenames.unshift("#{name}.h")
+		end
+		
+		if sub_framework
+			pp = framework_path(parent_framework.name)
+			tmp, pname = pp.scan(/^(.+)\/(\w+)\.framework\/?$/)[0]
+			@import_directives << "#import <#{pname}/#{pname}.h>"
+		else
+			@import_directives << header_basenames.map do |x|
+				"#import <#{name}/#{x}>"
+			end.join("\n")
+		end
+		
+		@import_directives << "\n"
+		
+		@compiler_flags ||= "-F\"#{parent_path}\" -framework #{name}"
+		@cpp_flags ||= ""
+		@cpp_flags << "-F\"#{parent_path}\" "
+		
+		headers.each do |header|
+			header_file = HeaderFile.new
+			header_file.path = header
+			header_file.name = File.basename(header, File.extname(header))
+			header_file.framework = framework.name
+			
+			framework.headers << header_file
+		end
+		
+		# Memorize the dependencies.
+		@dependencies = DStepGenerator.dependencies_of_framework(path)
+				
+		handle_sub_frameworks(framework)
+	end
+	
+	def handle_sub_frameworks (framework)
+		path = framework_path(framework.name)
+		frameworks_path = File.join(path, "Frameworks")
+		frameworks = Dir.glob(File.join(frameworks_path, "*.framework"))
+		
+		frameworks.each do |f|
+			add_framework(f, true, framework)
+		end
+	end	
+	
+	def framework_path (val)
+		return val if File.exist?(val)
+		
+		val += ".framework" unless /\.framework$/.match(val)
+		paths = ["/System/Library/Frameworks", "/Library/Frameworks", "#{ENV['HOME']}/Library/Frameworks"]
+		paths << "/System/Library/PrivateFrameworks" if @private
+		
+		paths.each do |dir|
+			path = File.join(dir, val)
+			return path if File.exist?(path)
+		end
+		
+		return nil
+	end
+	
+	def umbrella_framework (val)
+				
+		unless val == "" || val.nil?
+			@umbrella_framework = val
+			
+			unless @compiler_flags.nil? || @compiler_flags == ""
+				i = @compiler_flags.index("-framework")
+				@compiler_flags = @compiler_flags[0 .. i - 1] + "-framework #{val}"
+			else
+				@compiler_flags = "-framework #{val}"
+			end
+		end
+	end
+	
+	def self.dependencies_of_framework (path)
+		@dependencies ||= {}
+		name = File.basename(path, ".framework")
+		path = File.join(path, name)
+		deps = @dependencies[path]
+		
+		if deps.nil?
+			deps = `otool -L "#{path}"`.scan(/\t([^\s]+)/).map do |m|
+				dpath = m[0]
+				next if File.basename(dpath) == name
+				next if dpath.include?("PrivateFrameworks")
+				next unless dpath.sub!(/\.framework\/Versions\/\w+\/\w+$/, "")
+				dpath + ".framework"
+			end.compact
+			
+			@dependencies[path] = deps
+		end
+		
+		return deps
+	end
+	
+	def compile_and_execute (code, enable_64bit = false, clean_when_fail = false)
+		compiler_line = "gcc "				
+		src = File.new(unique_tmp_path("src", ".m", "/Users/doob/development/eclipse_workspace/dstep/bindings"), "w")
+		src << code
+		src.close
+		
+		arch_flag = if enable_64bit
+						"-arch x86_64 -arch ppc64"
+					else
+						"-arch i386 -arch ppc"
+					end
+		
+		compiler_line << arch_flag
+		
+		bin = unique_tmp_path "bin", "", "/Users/doob/development/eclipse_workspace/dstep/bindings"
+		log = unique_tmp_path "log", ".txt", "/Users/doob/development/eclipse_workspace/dstep/bindings"
+		
+		line = "#{compiler_line} -o #{bin} #{src.path} #{@compiler_flags} 2>#{log}"
+		
+		unless system(line)
+			msg = "Cannot compile Objective-C code ...aborting\nCommand was: #{line}\n\nLog:\n#{File.read(log)}\n\n"
+			$stderr << msg
+			File.delete src.path if clean_when_fail
+			raise msg
+		end
+		
+		result = `#{bin}`
+		
+		unless $?.success?
+			raise "Cannot execute compiled Objective-C code ... aborting\nCommand was: #{line}\nBinary is: #{bin}"
+		end
+		
+		File.delete bin
+		File.delete log
+		File.delete src.path
+		
+		return result
+	end
+	
+	def unique_tmp_path (base, extension = "", dir = Dir.tmpdir)
+		i = 0
+		loop do
+			path = File.join(dir, "#{base}-#{Process.pid}-#{i}#{extension}")
+			return path unless File.exists?(path)
+			i += 1
+		end
+	end
+	
+	def add_header (path)
+		header = HeaderFile.new
+		header.path = path
+		header.name = File.basename(path, File.extname(path))
+		@import_directives << "#include <#{path}>\n"
+		@headers << header
+	end
+	
+	def add_framework (name, sub_framework = false, parent_framework = nil)
+		framework = Framework.new
+		framework.name = name
+		handle_framework(framework, sub_framework, parent_framework)
+		#@import_directives << "#import <#{framework.name}/#{framework.name}.h>\n"
+		@frameworks << framework
+	end
+	
+	def collect_header_types (header, enable_64bit)
+		types = []
+		
+		header.cftypes.each do |cftype|			
+			types << cftype[:type]
+		end
+		
+		header.constants.each do |constant|
+			types << constant.stripped_return_type
+		end
+		
+		header.structs.each do |struct|
+			types << struct[:name]
+			
+			struct[:members].each do |member|
+				types << member[:declaredType]
+			end
+		end
+		
+		header.typedefs.each do |typedef|
+			types << typedef.stripped_return_type
+		end
+		
+		header.functions.each do |function|
+			types << function.stripped_return_type
+			
+			function.args.each do |arg|
+				types << arg.stripped_return_type
+			end
+		end
+		
+		types
+	end
+	
+	def collect_classes_types (enable_64bit)
+		types = []
+		
+		@classes.each do |clazz, value|
+			value.methods.each do |method|				
+				types << method.stripped_return_type
+				
+				method.args.each do |arg|					
+					types << arg.stripped_return_type
+				end
+			end
+		end
+		
+		types
+	end
+	
+	def collect_informal_protocols_types (enable_64bit)
+		types = []
+		
+		@informal_protocols.each do |name, methods|
+			methods.each do |method|				
+				types << method.stripped_return_type
+				
+				method.args.each do |arg|					
+					types << arg.stripped_return_type
+				end
+			end
+		end
+		
+		types
+	end
+	
+	def resolve_header_types (header, enable_64bit, resolved_types, x)
+		i = x
+		
+		header.cftypes.each do |cftype|
+			cftype[enable_64bit ? :type64 : :type] = resolved_types[i]
+			i += 1
+		end
+		
+		header.constants.each do |constant|
+			constant.resolved_type = resolved_types[i] unless enable_64bit
+			constant.resolved_type64 = resolved_types[i] if enable_64bit
+			i += 1
+		end
+		
+		header.structs.each do |struct|
+			struct[enable_64bit ? :type64 : :type] = resolved_types[i]
+			i += 1
+			
+			struct[:members].each do |member|
+				member[enable_64bit ? :type64 : :type] = resolved_types[i]
+				i += 1
+			end
+		end
+		
+		header.typedefs.each do |typedef|
+			typedef.resolved_type = resolved_types[i] unless enable_64bit
+			typedef.resolved_type64 = resolved_types[i] if enable_64bit
+			i += 1
+		end
+		
+		header.functions.each do |function|
+			function.resolved_type = resolved_types[i] unless enable_64bit
+			function.resolved_type64 = resolved_types[i] if enable_64bit
+			i += 1
+			
+			function.args.each do |arg|
+				arg.resolved_type = resolved_types[i] unless enable_64bit
+				arg.resolved_type64 = resolved_types[i] if enable_64bit
+				i += 1
+			end
+		end
+		
+		i
+	end
+	
+	def resolve_methods_types (enable_64bit, resolved_types, x)
+		i = x
+		
+		@classes.each do |clazz, value|
+			value.methods.each do |method|
+				method.resolved_type = resolved_types[i] unless enable_64bit
+				method.resolved_type64 = resolved_types[i] if enable_64bit
+				i += 1
+				
+				method.args.each do |arg|
+					arg.resolved_type = resolved_types[i] unless enable_64bit
+					arg.resolved_type64 = resolved_types[i] if enable_64bit
+					i += 1
+				end
+			end
+		end
+		
+		i
+	end
+	
+	def resolve_informal_protocols_types (enable_64bit, resolved_types, x)
+		i = x
+		
+		@informal_protocols.each do |name, methods|
+			methods.each do |method|
+				method.resolved_type = resolved_types[i] unless enable_64bit
+				method.resolved_type64 = resolved_types[i] if enable_64bit
+				i += 1
+				
+				method.args.each do |arg|
+					arg.resolved_type = resolved_types[i] unless enable_64bit
+					arg.resolved_type64 = resolved_types[i] if enable_64bit
+					i += 1
+				end
+			end
+		end
+		
+		i
+	end
+	
+	def resolve_types (enable_64bit = false)
+		code = "#include <stdio.h>\n"
+		code << "#import <objc/objc-class.h>\n"
+		
+		# @dependencies.each do |f|
+		# 	# get the framework name
+		# 	i = f.index('.')
+		# 	str = f[0 ... i]
+		# 	i = str.rindex('/')
+		# 	str = str[i + 1 .. -1]
+		# 	
+		# 	code << "#import <#{str}/#{str}.h>\n"
+		# end
+				
+		code << @import_directives
+		types = []
+		
+		code << @code_to_inject + ";\n" unless @code_to_inject.nil?
+		
+		@frameworks.each do |framework|
+			framework.headers.each do |header|
+				
+				header.imports do |import|
+					code << "#import <#{import}.h>\n"
+				end
+				
+				types << collect_header_types(header, enable_64bit)
+			end
+		end
+
+		@headers.each do |header|
+			types << collect_header_types(header, enable_64bit)
+		end
+		
+		types << collect_classes_types(enable_64bit)
+		types << collect_informal_protocols_types(enable_64bit)
+		
+		code << "int main ()\n{\n"
+		types.flatten!
+		
+		types.each do |type|
+			code << '	printf("%s\n", ' + "@encode(#{type}));\n"
+		end
+		
+		code << "	return 0;\n}"
+		
+		resolved_types = []
+		
+		compile_and_execute(code, enable_64bit).split("\n").each do |line|
+			resolved_types << line
+		end
+		
+		i = 0
+		
+		@frameworks.each do |framework|
+			framework.headers.each do |header|
+				i = resolve_header_types(header, enable_64bit, resolved_types, i)
+			end
+		end
+
+		@headers.each do |header|
+			i = resolve_header_types(header, enable_64bit, resolved_types, i)
+		end
+		
+		i = resolve_methods_types(enable_64bit, resolved_types, i)
+		i = resolve_informal_protocols_types(enable_64bit, resolved_types, i)
+	end
+	
+	def generate_header (xml, header)
+		xml.file :name => header.name do
+			header.imports.each	do |import|
+				xml.import import
+			end
+			
+			header.defines.each do |define|
+				xml.define define
+			end
+			
+			header.cftypes.each do |cftype|
+				xml.cftype cftype
+			end
+			
+			header.constants.each do |constant|
+				xml.constant :name => constant.name, :declaredType => constant.return_type, :type => constant.resolved_type, :type64 => constant.resolved_type64, :const => constant.const
+			end
+			
+			header.enums.each do |enum|
+				xml.enum :name => enum[:name] do
+					enum[:members].each do |member|
+						xml.member member
+					end
+				end
+			end
+			
+			header.structs.each do |struct|
+				xml.struct :name => struct[:name], :type => struct[:type], :type64 => struct[:type64] do
+					struct[:members].each do |member|
+						xml.member member
+					end
+				end	
+			end
+			
+			header.typedefs.each do |typedef|
+				xml.typedef :name => typedef.name, :declaredType => typedef.return_type, :type => typedef.resolved_type, :type64 => typedef.resolved_type64, :const => typedef.const
+			end
+			
+			header.functions.each do |function|
+				xml.function :name => function.name, :inline => function.inline?, :variadic => function.variadic? do
+					function.args.each do |arg|
+						xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
+					end
+					
+					xml.returnValue :declaredType => function.return_type, :type => function.resolved_type, :type64 => function.resolved_type64, :const => function.const, :typeModifier => function.type_modifier
+				end
+			end
+		end
+	end
+	
+	def generate_classes (xml)
+		@classes.each do |clazz, value|
+			xml.class :name => clazz, :parent => value.parent, :file => value.file do
+				value.methods.each do |method|
+					xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do
+						method.args.each do |arg|
+							xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
+						end
+						
+						xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier
+					end
+				end
+			end
+		end
+	end
+	
+	def generate_informal_protocols (xml)
+		@informal_protocols.each do |name, methods|
+			xml.informalProtocol :name => name do
+				methods.each do |method|
+					xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do
+						method.args.each do |arg|
+							xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier
+						end
+						
+						xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier
+					end
+				end
+			end
+		end
+	end
+	
+	def generate
+		resolve_types
+		resolve_types(true) if @do_64bit
+		
+		file = STDOUT if @out_file == nil
+		file = File.open @out_file, "w" unless @out_file == nil
+		
+		xml = XmlMarkup.new(:target => file, :indent => 4)
+		xml.instruct!
+
+		xml.dstep :xmlns => "http://www.dsource.org/projects/dstep", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => "http://www.dsource.org/projects/dstep/trunk/scripts/dstep.xsd"   do
+			@frameworks.each do |framework|
+				xml.framework :name => framework.name do
+					framework.headers.each do |header|
+						generate_header(xml, header)
+					end
+				end
+			end
+			
+			@headers.each do |header|
+				generate_header(xml, header)
+			end
+			
+			generate_classes(xml)
+			generate_informal_protocols(xml)
+		end
+		
+		file.close unless file == STDOUT
+	end	
+end
+
+def die (*msg)
+	$stderr.puts msg
+	exit 1
+end
+
+if __FILE__ == $0
+	dstep_gen = DStepGenerator.new
+	
+	OptionParser.new do |opts|
+		opts.banner = "Usage: #{File.basename(__FILE__)} [options] <headers...>"
+		opts.separator ""
+		opts.separator "Options:"
+		
+		opts.on("-f", "--framework FRAMEWORK", "Generate metadata for the given framework.") do |opt|
+			dstep_gen.add_framework(opt)
+		end
+		
+		opts.on("-u", "--umbrella FRAMEWORK", "Link againts the given umbrella framework.") do |opt|
+			dstep_gen.umbrella_framework(opt)
+		end
+		
+		opts.on(nil, "--64-bit", "Write 64-bit annotations.") do
+			dstep_gen.do_64bit = true
+		end
+		
+		opts.on("-o", "--output FILE", "Write output to the given file.") do |opt|
+			die "Output file can't be specified more than once" if dstep_gen.out_file
+			dstep_gen.out_file = opt
+		end
+		
+		# opts.on("-d", "--output-dir PATH", "Write ouptut to the given paht, use this with the --framework option") do |opt|
+		# 	die "Output directory can't be specified more than once" if dstep_gen.out_dir
+		# 	dstep_gen.out_dir = opt
+		# end
+		
+		opts.on("-C", "--code CODE", "Add code") do |opt|
+			dstep_gen.code_to_inject = opt
+		end
+		
+		help_msg = "Use the `-h' flag or for help."	
+			
+		opts.on("-h", "--help", "Show this message.") do
+			puts opts, help_msg
+			exit
+		end
+		
+		opts.on('-v', '--version', 'Show version.') do
+			puts DStepGenerator::VERSION
+			exit
+		end
+		
+		opts.separator ""
+		
+		if ARGV.empty?			
+			die opts.banner
+		else
+			#begin
+				opts.parse!(ARGV)
+				
+				ARGV.each do |header|
+					dstep_gen.add_header(header)
+				end
+				
+				dstep_gen.collect
+				dstep_gen.generate
+			# rescue => e
+			# 	msg = e.message
+			# 	msg = "Internal error" if msg.empty?
+			# 	
+			# 	die msg, opts.banner, help_msg
+			# end
+		end
+	end
+end