changeset 2:9fd439a28ce3

Adapted the scripts for the new bridge + a lot more
author Jacob Carlborg <doob@me.com>
date Sun, 05 Jul 2009 17:16:19 +0200
parents 033d260cfc9b
children d0162d8ca0f2
files dsss.conf 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 scripts/dgen.rb scripts/dstepgen.rb
diffstat 8 files changed, 1067 insertions(+), 591 deletions(-) [+]
line wrap: on
line diff
--- a/dsss.conf	Thu Jun 18 22:00:13 2009 +0200
+++ b/dsss.conf	Sun Jul 05 17:16:19 2009 +0200
@@ -1,2 +1,2 @@
-#[dstep]
-[main.d]
\ No newline at end of file
+[dstep]
+exlude += dstep/Cocoa
\ No newline at end of file
--- a/dstep/objc/bridge/Bridge.d	Thu Jun 18 22:00:13 2009 +0200
+++ b/dstep/objc/bridge/Bridge.d	Sun Jul 05 17:16:19 2009 +0200
@@ -64,11 +64,25 @@
 
 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_;
+	private
+	{
+		import dstep.objc.bridge.ClassInitializer : ObjcSubclassInitializer, subclassInit;
+		import dstep.objc.objc : Class, id, IMP, SEL;
+	
+		static Class objcClass_;
+		static Class objcSuperClass_;
+	}
+	
+	this ()
+	{
+		objcObject = invokeObjcSelfClass!(id, "alloc");
+		id ret = invokeObjcSelf!(id, "init");
+		
+		if (ret)
+			objcObject = ret;
+		
+		dObject = this;
+	}
 
 	this (id object)
 	{
@@ -124,21 +138,22 @@
 
 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 ()
+	private
 	{
-		return null;
-	}
+		import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule;
+		import dstep.objc.bridge.Type : needsEncapsulation, ObjcType;
+		import dstep.internal.Tuple;
+	
+		ObjcMethodDeclaration!(method, R, selector, ARGS) objcMethodDeclaration;
 		
-	static if (needsEncapsulation!(R))
-	{
-        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-        
-		private static id forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs)
+		R delegate (ARGS) resolveVirtualCall ()
+		{
+			return null;
+		}
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		
+		static ObjcType!(R) forwardVirtualCall (id self, SEL cmd, ObjcArgs objcArgs)
 		in
 		{
 			assert(isCapsule(self));
@@ -158,37 +173,11 @@
 				args[i] = decapsule!(ArgType)(a);
 			}
 			
-			auto result = dg(args);
+			static if (is(R == void))
+				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);
+			else
+				return encapsule!(R)(dg(args));
 		}
 	}
 }
@@ -200,13 +189,16 @@
 
 template ObjcBindClassMethod (alias method, R, string selector, ARGS...)
 {	
-	private ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
-		
-	static if (needsEncapsulation!(R))
+	private
 	{
-        private alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
-        
-		private static id forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs)
+		import dstep.objc.bridge.Capsule : decapsule, encapsule, isCapsule, needsEncapsulation, ObjcType;
+		import dstep.internal.Tuple;
+		
+		ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		
+		static ObjcType!(R) forwardStaticCall (id self, SEL cmd, ObjcArgs objcArgs)
 		in
 		{
 			assert(isCapsule(self));
@@ -224,35 +216,47 @@
 				args[i] = decapsule!(ArgType)(a);
 			}
 			
-			auto result = dg(args);
+			static if (needsEncapsulation!(R))
+				return encapsule!(R)(dg(args));
 			
-			return encapsule!(R)(result);
+			else
+				return dg(args);
 		}
 	}
-	
-	else
+}
+
+template ObjcBindFunction (alias func)
+{
+	mixin ObjcBindFunction!(func, ReturnTypeOf!(func), ParameterTupleOf!(func));
+}
+
+template ObjcBindFunction (alias func, R, ARGS...)
+{
+	private
 	{
-        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;
-			
+		import dstep.objc.bridge.Capsule : decapsule, encapsule, needsEncapsulation, ObjcType;
+		import dstep.internal.Tuple;
+		
+		ObjcMethodDeclaration!(method, R, selector, ARGS) objcClassMethodDeclaration;
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		
+		extern (C) ObjcType!(R) forwardFunctionCall (ObjcArgs objcArgs)
+		{			
 			ARGS args;
 			
 			foreach (i, a ; objcArgs)
 			{
 				alias typeof(args[i]) ArgType;
-
-                args[i] = decapsule!(ArgType)(a);
+				
+				args[i] = decapsule!(ArgType)(a);
 			}
 			
-			return dg(args);
+			static if (needsEncapsulation!(R))
+				return encapsule!(R)(dg(args));
+			
+			else
+				return dg(args);
 		}
 	}
 }
@@ -428,4 +432,53 @@
 		else
 			return self.msgSend!(R)(sel, objcArgs);
 	}
+	
+	R invokeObjcFunction (R, alias func, ARGS...) (ARGS args)
+	{
+		static if (!is(R : void))
+			R result;
+		
+		auto funcPtr = &func; // use a function pointer instead of the alias because the function can be private.
+		
+		alias ReplaceAllClasses!(id, ARGS) ObjcArgs;
+		ObjcArgs objcArgs;
+		
+		foreach (i, a ; args)
+		{
+			alias typeof(a) ArgType;
+			
+			objcArgs[i] = encapsule!(ArgType)(a);
+		}
+		
+		static if (is(R : ObjcWrapper))
+		{
+			id r = funcPtr(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 = funcPtr(objcArgs);
+			
+			if (!r)
+				return null;
+			
+			return decapsule!(R)(r);
+		}
+		
+		else
+			return funcPtr(objcArgs);
+	}
 }
\ No newline at end of file
--- a/dstep/objc/bridge/Capsule.d	Thu Jun 18 22:00:13 2009 +0200
+++ b/dstep/objc/bridge/Capsule.d	Sun Jul 05 17:16:19 2009 +0200
@@ -24,6 +24,7 @@
 
 import dstep.internal.String;
 import dstep.objc.bridge.Bridge;
+import dstep.objc.bridge.Type;
 import dstep.objc.bridge.TypeEncoding;
 import dstep.objc.bridge.Wrapper;
 import dstep.objc.message;
@@ -33,15 +34,6 @@
 
 import mambo.io;
 
-template ObjcType (T)
-{
-	static if (needsEncapsulation!(T))
-		alias id ObjcType;
-	
-	else
-		alias T ObjcType;
-}
-
 Class capsuleClass ()
 {
 	if (!Capsule.capsuleClass)
@@ -119,17 +111,8 @@
 	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)
@@ -145,28 +128,25 @@
 		return value;
 }
 
-template decapsule (T)
+T decapsule (T) (ObjcType!(T) value)
 {
-	T decapsule (ObjcType!(T) value)
+	static if (needsEncapsulation!(T))
 	{
-		static if (needsEncapsulation!(T))
+		if (isCapsule(value))
+			return cast(T) Bridge.getDObject(value);
+		
+		else
 		{
-			if (isCapsule(value))
-				return cast(T) Bridge.getDObject(value);
+			static if (is(T : ObjcWrapper))
+				new T(value);
 			
 			else
-			{
-				static if (is(T : ObjcWrapper))
-					new T(value);
-				
-				else
-					return null;
-			}
+				return null;
 		}
-		
-		else
-			return value;
 	}
+	
+	else
+		return value;
 }
 
 private id encapsuleString (string str)
--- a/dstep/objc/bridge/ClassInitializer.d	Thu Jun 18 22:00:13 2009 +0200
+++ b/dstep/objc/bridge/ClassInitializer.d	Sun Jul 05 17:16:19 2009 +0200
@@ -110,7 +110,7 @@
 	
 	private static R invokeObjcSuperClass (R, string name, ARGS...) (ARGS args)
 	{
-		return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcClass.getSuperclass, args);
+		return Bridge.invokeObjcClassMethod!(R, name, ARGS)(objcSuperClass, args);
 	}
 }
 
--- a/dstep/objc/bridge/Type.d	Thu Jun 18 22:00:13 2009 +0200
+++ b/dstep/objc/bridge/Type.d	Sun Jul 05 17:16:19 2009 +0200
@@ -14,6 +14,24 @@
 
 import dstep.objc.objc;
 
+template ObjcType (T)
+{
+	static if (needsEncapsulation!(T))
+		alias id ObjcType;
+	
+	else
+		alias T ObjcType;
+}
+
+template needsEncapsulation (T)
+{
+	static if (is(T == class))
+		const needsEncapsulation = true;
+	
+	else
+		const needsEncapsulation = false;
+}
+
 template ObjcTypeTuple (TList...)
 {
 	alias replaceClasses!(TList).types ObjcTypeTuple;
--- a/dstep/objc/bridge/Wrapper.d	Thu Jun 18 22:00:13 2009 +0200
+++ b/dstep/objc/bridge/Wrapper.d	Sun Jul 05 17:16:19 2009 +0200
@@ -15,12 +15,22 @@
 
 class ObjcWrapper
 {	
-	package objc_super* objcSuper;
-	
 	static private Class objcClass_;
 	static private Class objcSuperClass_;
 	
 	private id objcObject_;
+	private objc_super* objcSuper_;
+	
+	this ()
+	{
+		objcObject = Bridge.invokeObjcClassMethod!(id, "alloc")(objcClass);
+		id ret = Bridge.invokeObjcMethod!(id, "init")(objcObject);
+		
+		if (ret)
+			objcObject = ret;
+		
+		dObject = this;
+	}
 		
 	/// Initialize object from an Objective-C object instance to wrap.
 	this (id object)
@@ -57,24 +67,15 @@
 		Bridge.setDObject(dObject, objcObject);
 	}
 	
-	/*this (bool init = true, bool alloc = true)
+	objc_super* objcSuper ()
 	{
-		if (init && alloc)
+		if (!objcSuper_)
 		{
-			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;
+			objcSuper_ = new objc_super;
+			objcSuper_.receiver = objcObject;
+			objcSuper_.cls = objcSuperClass;
 		}
 		
-		else if (alloc)
-			objc.object = objc_msgSend(objc_getClass(this.classinfo.name), sel.registerName!("alloc"));
-	}*/
+		return objcSuper_;
+	}
 }
\ No newline at end of file
--- a/scripts/dgen.rb	Thu Jun 18 22:00:13 2009 +0200
+++ b/scripts/dgen.rb	Sun Jul 05 17:16:19 2009 +0200
@@ -1,7 +1,7 @@
 #!/usr/bin/env ruby
 
 ##
-# Copyright:: Copyright (c) 2009 Jacob Carlborg. All rights reserved.
+# Copyright:: Copyright (c) 2009 Jacob Carlborg.
 # Author:: Jacob Carlborg
 # Version:: Initial created: 2009
 # License:: [Boost Software License 1.0]http://www.boost.org/LICENSE_1_0.txt
@@ -11,6 +11,7 @@
 gem "xml-simple"
 require "xmlsimple"
 require "optparse"
+require "date"
 
 # Extensions to String
 class String	
@@ -180,8 +181,8 @@
 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
+HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :c_constants, :d_constants, :d_constants_static_this, :defines, 
+			  			:enums, :functions, :c_functions, :function_wrappers, :imports, :path, :structs, :typedefs) do
 	def initialize
 		self.name = ""
 		self.cftypes = []
@@ -190,11 +191,13 @@
 		self.enums = []
 		self.framework = ""
 		self.functions = []
+		self.c_functions = []
 		self.function_wrappers = []
 		self.imports = []
 		self.path = ""
 		self.structs = []
 		self.typedefs = []
+		self.d_constants_static_this = []
 	end	
 end
 
@@ -208,12 +211,17 @@
 	# Creates a new instance of the ObjcToD class
 	def initialize
 		@classes = {}
+		@interfaces = {}
+		@interfaces2 = []
+		@templates = {}
 		@copyright = nil
+		@c_constants = []
 		@d_constants = []
 		@d_constants_static_this = []
 		@files = []
 		@frameworks = []
 		@function_wrappers = []
+		@c_functions = []
 		@headers = []
 		@package = "dstep"
 	end	
@@ -234,10 +242,12 @@
 						header = HeaderFile.new
 						header.name = file.name
 						header.constants = constants(file.constant) unless file.constant.nil?
+						header.c_constants = c_constants 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.c_functions = c_functions 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?
@@ -258,10 +268,12 @@
 					header = HeaderFile.new
 					header.name = file.name
 					header.constants = constants(file.constant) unless file.constant.nil?
+					header.c_constants = c_constants 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.c_functions = c_functions 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?
@@ -270,36 +282,41 @@
 					@headers << header
 				end
 			end
-
-			unless xml["class"].nil?
-				classes(xml["class"])
-			end
+			
+			interfaces(xml.protocol) unless xml.protocol.nil?
+			templates(xml.category) unless xml.category.nil?
+			classes(xml["class"]) unless xml["class"].nil?						
 		end
 	end
 	
 	# Outputs the generate D code
 	def output_code
 		@frameworks.each do |framework|
-			framework_path = framework_path = "#{@out_dir}/#{@package}/#{framework.name}"
+			framework_path = framework_path = "#{@out_dir}/#{@package}/#{get_identifier(get_framework_name(framework.name.downcase))}"
 			
 			FileUtils.mkdir_p(framework_path) unless File.exist?(framework_path)
 			
 			framework.files.each do |header|
-				file_path = "#{framework_path}/#{header.name}.d"
+				file_path = "#{framework_path}/#{get_identifier(header.name)}"
+				bindings_file_path = file_path + "_bindings.d"
+				file_path << ".d"
+				mod = "#{@package}.#{get_identifier(get_framework_name(framework.name.downcase))}.#{get_identifier(header.name)}"
 				
 				File.open(file_path, "w") do |file|
 					file << copyright
-					file << "module #{@package}.#{framework.name}.#{header.name};"
-					file << header.imports.nl(false)
+					file << "module #{mod};"
+					file << header.imports
+					file << "\n" unless @d_constants.length > 0 || @function_wrappers.length > 0
+					file << "import bindings = #{mod}_bindings".nl.nl(false) if @d_constants.length > 0 || @function_wrappers.length > 0
 					file << header.defines
 					file << header.typedefs
-					file << header.cftypes				
-					file << header.constants
+					file << header.cftypes
+					file << header.c_constants
 					file << header.d_constants
 					file << header.enums
 					file << header.structs
 					
-					unless header.d_constants_static_this.nil?
+					unless header.d_constants_static_this.length == 0
 						file << "static this ()".nl(false)
 						file << "{".nl(false)
 						file << header.d_constants_static_this
@@ -313,26 +330,54 @@
 						@classes.delete(clazz)
 					end
 					
-					file << header.functions
+					interfaces = get_interfaces(header.name)
+					
+					interfaces.each do |interface, value|
+						file << value.code.nl(false)
+						@interfaces.delete(interface)
+					end
+					
+					templates = get_templates(header.name)
+					
+					templates.each do |template, value|
+						file << value.code.nl(false)
+						@templates.delete(template)
+					end
+					
 					file << header.function_wrappers
+					file << header.c_functions									
 				end
+				
+				File.open(bindings_file_path, "w") do |file|
+					file << "module "
+					file << mod
+					file << "_bindings;"
+					file << header.imports.nl(false)
+					file << header.constants
+					file << header.functions
+				end if @d_constants.length > 0 || @function_wrappers.length > 0	
 			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"
+		@headers.each do |header|			
+			header_path = "#{package_path}/#{get_identifier(header.name)}"
+			bindings_file_path = header_path + "_bindings.d"
+			header_path << ".d"
+			mod = "#{@package}.#{get_identifier(header.name)}"
 			
 			File.open(header_path, "w") do |file|
 				file << copyright
-				file << "module #{@package}.#{header.name};"
-				file << header.imports.nl(false)
+				file << "module #{mod};"
+				file << header.imports
+				file << "\n" unless @d_constants.length > 0 || @function_wrappers.length > 0
+				file << "import bindings = #{mod}_bindings".nl.nl(false) if @d_constants.length > 0 || @function_wrappers.length > 0
 				file << header.defines
 				file << header.typedefs
-				file << header.cftypes				
-				file << header.constants
+				file << header.cftypes
+				file << header.c_constants
 				file << header.d_constants
 				file << header.enums
 				file << header.structs
@@ -350,14 +395,37 @@
 					file << value.code.nl(false)
 					@classes.delete(clazz)
 				end
+				
+				interfaces = get_interfaces(header.name)
+				
+				interfaces.each do |interface, value|
+					file << value.code.nl(false)
+					@interfaces.delete(interface)
+				end
+				
+				templates = get_templates(header.name)
+				
+				templates.each do |template, value|
+					file << value.code.nl(false)
+					@templates.delete(template)
+				end
 
+				file << header.function_wrappers
+				file << header.c_functions	
+			end
+				
+			File.open(bindings_file_path, "w") do |file|
+				file << "module "
+				file << mod
+				file << "_bindings;"
+				file << header.imports.nl(false)
+				file << header.constants
 				file << header.functions
-				file << header.function_wrappers
-			end			
+			end if @d_constants.length > 0 || @function_wrappers.length > 0					
 		end
 		
 		@classes.each do |clazz, value|
-			class_path = "#{package_path}/#{clazz}.d"
+			class_path = "#{package_path}/#{get_identifier(clazz)}.d"
 			
 			File.open(class_path, "w") do |file|
 				file << value.code unless value.nil?
@@ -395,7 +463,7 @@
 	def get_framework (class_name)
 		@frameworks.each do |framework|
 			framework.files.each do |file|
-				return framework.name if file.name == class_name
+				return get_identifier(framework.name) if file.name == class_name
 			end
 		end
 		
@@ -409,70 +477,194 @@
 		end
 		
 		return classes
-	end	
+	end
+	
+	# Gets the interfaces that belongs to the given file
+	def get_interfaces (name)		
+		interfaces = @interfaces.find_all do |interface, value|
+			value.file == name
+		end
+		
+		return interfaces
+	end
+	
+	# Gets the templates that belongs to the given file
+	def get_templates (name)		
+		templates = @templates.find_all do |template, value|
+			value.file == name
+		end
+		
+		return templates
+	end
 	
 	# Generates the D code for the classes
 	def classes (classes)
 		classes.each do |clazz|
 			str = StringIO.new
+			protocols = []
 			
 			str << "class "
 			
 			if clazz == ""
-				str << clazz.name.nl(false)
+				str << get_identifier(clazz.name).nl(false)
 			else
-				str << clazz.name
-				str << " : "
-				str << clazz.parent.nl(false)
+				str << get_identifier(clazz.name)
+				
+				unless clazz.parent == ""
+					str << " : "
+					str << get_identifier(clazz.parent)
+				end
+				
+				unless clazz.protocols.length == 0
+					protocols = clazz.protocols.split(",")
+					
+					str2 = StringIO.new
+					
+					str2 << ", " unless clazz.parent.length == 0
+					str2 << " : " if clazz.parent.length == 0
+					
+					protocols.each do |protocol|
+						str2 << "I"
+						str2 << get_identifier(protocol)
+						str2 << ", "
+					end
+					
+					str << str2.string[0 .. -3]
+				end
+				
+				str << "\n"
 			end			
 			
 			str << "{".nl(false)
+			str << "mixin ObjcWrap".indent.nl
+			
+			templates_for_class(clazz.name).each do |template, value|
+				str << "mixin #{template}".indent.nl
+			end
+			
+			str << "\n"
+
 			str << methods(clazz.method, clazz.name)
+			str << "\n" if protocols.length > 0
+			
+			# implement the interfaces/protocols
+			protocols.each_with_index do |protocol, i|
+				interface = interface_for_protocol(protocol)
+				
+				unless interface.nil?
+					str << methods(interface.method, interface.name)
+					str << "\n" unless i == protocols.length - 1
+				end
+			end			
+			
 			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
+			@classes[clazz.name].file = get_identifier(clazz.file)
+		end
+	end
+	
+	# Generates the D code for the interfaces
+	def interfaces (interfaces)
+		interfaces.each do |interface|
+			str = StringIO.new
+			
+			str << "interface I" # prepend I to the interface name, because it can be the same as a class name
+			
+			if interface == ""
+				str << get_identifier(interface.name).nl(false)
+			else
+				str << get_identifier(interface.name)
+				
+				unless interface.parent == ""
+					str << " : "
+					str << get_identifier(interface.parent)
+				end
+				
+				unless interface.protocols.length == 0
+					protocols = interface.protocols
+					protocols = protocols.split(",")
+					
+					str2 = StringIO.new
+					
+					str2 << ", " unless interface.parent.length == 0
+					str2 << " : " if interface.parent.length == 0
+					
+					protocols.each do |protocol|
+						str2 << "I"
+						str2 << get_identifier(protocol)
+						str2 << ", "
+					end
+					
+					str << str2.string[0 .. -3]
+				end
+				
+				str << "\n"
+			end
+			
+			str << "{".nl(false)
+			str << interface_methods(interface.method, interface.name)
+			str << "}".nl(false)
+			
+			@interfaces[interface.name] ||= {}
+			@interfaces[interface.name].code = str.string
+			framework = get_framework(interface.file)
+			@interfaces[interface.name].framework = framework unless framework.nil?
+			@interfaces[interface.name].file = get_identifier(interface.file)
+			@interfaces2 << interface
+		end
+	end
+	
+	# Generates the D code for the templates
+	def templates (templates)
+		templates.each do |template|
+			str = StringIO.new
+
+			str << "template "			
+			str << get_identifier(template.name)
+			str << " ()".nl(false)
+			str << "{".nl(false)
+			str << interface_methods(template.method, template.name) if template["class"] == "NSObject"
+			str << methods(template.method, template.name) unless template["class"] == "NSObject"
+			str << "}".nl(false)
+
+			@templates[template.name] ||= {}
+			@templates[template.name].code = str.string
+			framework = get_framework(template.file)
+			@templates[template.name].framework = framework unless framework.nil?
+			@templates[template.name].file = get_identifier(template.file)
+			@templates[template.name][:class] = get_identifier(template["class"])
 		end
 	end
 	
 	# Generates the D code for the constants/globals
 	def constants (constants)
+		return "" if constants.length == 0
+			
 		str = StringIO.new
 		
-		str << "private extern (C)".nl(false)
+		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"
+			type = get_type(constant.type, constant.type64, constant.declaredType)
+			const = constant.const == "true"
 			
-			if constant.type == "@"				
+			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 << "private ".indent(2)
+				str << "const id" if const
+				str << "id" unless const				
 				str << " "
-				str << constant["name"]
-				str << "_".nl
+				str << get_identifier(constant["name"]).nl
 			else
-				if const
-					str << "const ".indent(2)
-					str << type
-				else
-					str << "id".indent(2)
-				end
-				
-				str << " "
-				str << constant["name"].nl
+				@c_constants << { :name => constant.name.dup, :type => type, :const => const }
 			end
 		end
 		
@@ -482,8 +674,40 @@
 		str.string
 	end
 	
+	def c_constants
+		return "" if @c_constants.length == 0
+		
+		str = StringIO.new
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)
+		str << "extern".indent.nl(false)
+		str << "{".indent.nl(false)
+		
+		@c_constants.each do |constant|
+			if constant.const
+				str << "const ".indent(2)
+				str << constant.type
+			else
+				str << constant.type.indent(2)
+			end
+			
+			str << " "
+			str << get_identifier(constant.name).nl
+		end
+		
+		str << "}".indent.nl(false)
+		str << "}".nl(false).nl(false)
+		
+		@c_constants.clear
+		str.string
+	end
+	
+	
     # Generates the D code for the constants that D can't handle directly, like classes
 	def d_constants
+		return "" if @d_constants.length == 0
+			
 		str = StringIO.new
 		
 		@d_constants.each do |constant|
@@ -493,9 +717,9 @@
 			c.type = c.type.dup
 			
 			str << "const " if constant.const
-			str << constant.type
+			str << get_identifier(constant.type)
 			str << " "			
-			str << constant.name.nl
+			str << get_identifier(constant.name).nl
 			@d_constants_static_this << c
 		end
 		
@@ -506,15 +730,18 @@
 	
 	# Generates the D code for the constants the has to be in a "static this"
 	def d_constants_static_this
+		return "" if @d_constants_static_this.length == 0
+		
 		str = StringIO.new
 		
 		@d_constants_static_this.each do |constant|
 			str << constant.name.indent
 			str << " = new "
-			str << constant.type
+			str << get_identifier(constant.type)
 			str << "("
-			str << constant.name
-			str << "_)".nl
+			str << "bindings."
+			str << get_identifier(constant.name)
+			str << ")".nl
 		end
 		
 		@d_constants_static_this.clear
@@ -523,33 +750,36 @@
 	
 	# Generates the D code for the enums
 	def enums (enums)
+		return "" if enums.length == 0
+		
 		str = StringIO.new
 		
 		enums.each do |enum|
 			str << "enum"
 								
-			if enum["name"] == ""
-				str << "\n{".nl
+			if enum.name.length == 0
+				str << "\n{".nl(false)
 				
 				enum.member.each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
+					str << get_identifier(member["name"]).indent
+					str << " = " if member.value.length > 0
 					str << member.value
 					str << ",".nl(false) unless i == enum.member.length - 1
 				end				
 			else
-				str << enum["name"].nl
-				str << "{"
+				str << " "
+				str << get_identifier(enum["name"]).nl(false)
+				str << "{".nl(false)
 				
 				enum["member"].each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
+					str << get_identifier(member["name"]).indent
+					str << " = " if member.value.length > 0
 					str << member.value
 					str << ",".nl(false) unless i == enum.member.length - 1
 				end
 			end
 			
-			str << "\n}".nl.nl(false)
+			str << "\n}".nl(false).nl(false)
 		end
 		
 		str.string
@@ -573,7 +803,7 @@
 			
 			str << type
 			str << " "
-			str << arg["name"]
+			str << get_identifier(arg["name"])
 			str << ", "
 		end
 		
@@ -590,7 +820,7 @@
 	# 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"
+		variadic = function.variadic == "true"
 		return_type  = ""
 		args = ""
 		original_type = function.returnValue[0].type
@@ -615,49 +845,65 @@
 	
 	# Generates the D code for the functions
 	def functions (functions)
-		str = StringIO.new
+		return "" if functions.length == 0
 		
-		str << "private extern (C)".nl(false)
-		str << "{".nl(false)
+		str = StringIO.new
+		wrapper_needed = false
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)		
 		
 		functions.each do |function|
-			wrapper_needed = false
-			original_type = function["returnValue"][0].type
+			wrapper_needed = false		
+			original_type = function.returnValue[0].type
 			
 			if original_type == "@"
 				@function_wrappers << function
 				wrapper_needed = true
+				str << functions_helper(function, wrapper_needed)
 			else
-				function["arg"].each do |arg|
-					if (arg.type || arg["type64"]) == "@"
+				function.arg.each do |arg|
+					if (arg.type || arg.type64) == "@"
 						@function_wrappers << function
 						wrapper_needed = true
+						break
 					end
-				end unless function["arg"].nil?
+				end unless function.arg.nil?
+				
+				str << functions_helper(function, wrapper_needed) if wrapper_needed
+				@c_functions << function unless wrapper_needed
 			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 << "}"
 		str.string
 	end
 	
+	def c_functions	
+		return "" if @c_functions.length == 0
+		
+		str = StringIO.new
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)
+		
+		@c_functions.each do |function|
+			str << functions_helper(function, false)
+		end
+		
+		str << "}"
+		
+		@c_functions.clear
+		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 << ("private " + build_function(function)).indent if wrapper_needed
+		str << build_function(function).indent unless wrapper_needed
 
 		str.string
 	end	
@@ -665,113 +911,70 @@
 	# 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
+		return "" if @function_wrappers.length == 0
+			
 		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?
-			
+			return_type = get_type(function.returnValue[0].type, function.returnValue[0].type64, function.returnValue[0].declaredType)
+			variadic = function.variadic == "true"
+
 			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"				
+			str << "return Bridge.invokeObjcFunction!(".indent
+			str << return_type
+			str << ", bindings."
+			str << function.name
+
+			function.arg.each do |arg|
+				str << ", "
+				str << get_type(arg.type, arg.type, arg.declaredType)
+			end unless function.arg.nil?
+
+			unless function.arg.nil?
+				str << ")"
+				str << "("
 			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
-			
+			function.arg.each_with_index do |arg, i|
+				str << arg.name
+				str << ", " unless i == function.arg.length - 1
+			end unless function.arg.nil?
+
+			str << ")".nl
+
 			str << "}".nl(false).nl(false)
 		end
 		
 		@function_wrappers.clear		
-		str.string[0 ... -2]
+		str.string
 	end
 	
 	# Generates the D code for the imports
 	def imports (imports, filename, framework_name = nil)
+		return "" if imports.length == 0
+		
 		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
+			str << "import #{@package}."
+			import = import.gsub("/", ".").gsub("Frameworks", "").gsub(".framework", "").gsub("Headers", "").gsub(/\.{2,}/, ".").nl
+			
+			splits = import.split('.')
+			import = ""
+			
+			splits[0 .. -2].each do |s|
+				import << get_identifier(s.downcase)
+				import << '.'
+			end
+			
+			str << import
+			str << splits[-1 .. -1]
 		end
 		
+		str << "import dstep.objc.bridge.Bridge".nl
+		str << "import dstep.objc.objc : id".nl
+		
 		str << "\n\n"
 		str = str.string.sort.to_s		
 		
@@ -781,225 +984,83 @@
 	
 	# Generates the D code for the methods
 	def methods (methods, class_name)
+		return "" if methods.length == 0
+		
 		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
+		methods.each do |method|				
+			return_type = get_type(method.returnValue[0].type, method.returnValue[0].type64, method.returnValue[0].declaredType)
+			variadic = method.variadic == "true"
+			static = method.classMethod == "true"
 			
-			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?
-			
+			index = 0
 			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
-			index = declaration.index_of(" ")
+			index = declaration.index_of(" ") if static
+			index = declaration.index_of(" ", index) 
 			
 			str << (declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " ")
 			str << "{".indent.nl(false)
+			str << "return invokeObjcSelf!(".indent(2) unless static
+			str << "return invokeObjcSelfClass!(".indent(2) if static
+			str << return_type
+			str << ', "'
+			str << method.selector
+			str << '"'
 			
-			out_args.each do |arg|
-				str << arg.type.indent(2)
-				str << " "
-				str << arg.name
-				str << "_ = new "
-				str << arg.type
-				str << "(false, false)".nl
+			method.arg.each do |arg|
+				str << ", "
+				str << get_type(arg.type, arg.type, arg.declaredType)
+			end unless method.arg.nil?
+			
+			unless method.arg.nil?
+				str << ")"
+				str << "("
 			end
 			
-			str << "\n" if out_args.length > 0
-			
+			method.arg.each_with_index do |arg, i|
+				str << arg.name
+				str << ", " unless i == method.arg.length - 1
+			end unless method.arg.nil?
 			
-			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
+			str << ")".nl
+			
+			str << "}".indent.nl(false).nl(false)
 		end
 		
 		str.string[0 .. -2]
 	end
 	
+	# Generates the D code for the interface methods
+	def interface_methods (methods, interface_name)
+		return "" if methods.length == 0
+		
+		str = StringIO.new
+		
+		methods.each do |method|
+			return_type = get_type(method.returnValue[0].type, method.returnValue[0].type64, method.returnValue[0].declaredType)
+			
+			variadic = method.variadic == "true"
+			static = method.classMethod == "true"
+			
+			index = 0
+			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
+			index = declaration.index_of(" ", index)
+			str << ((declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " "))[0 .. -2]
+			str << ";\n"
+		end
+		
+		str.string
+	end	
+	
 	# Generates the D code for the structs
 	def structs (structs)
+		return "" if structs.length == 0
+		
 		str = StringIO.new
 		
 		structs.each do |struct|
 			str << "struct "
-			str << struct.name.nl(false)
+			str << get_identifier(struct.name).nl(false)
 			str << "{".nl
 			
 			struct.member.each do |member|
@@ -1007,7 +1068,7 @@
 				
 				str << type.indent
 				str << " "
-				str << member.name.nl
+				str << get_identifier(member.name).nl
 			end unless struct.member.nil?
 			
 			str << "}".nl
@@ -1019,6 +1080,8 @@
 	
 	# Generates the D code for the typedefs
 	def typedefs (typedefs)
+		return "" if typedefs.length == 0
+		
 		str = StringIO.new
 
 		typedefs.each do |typedef|
@@ -1027,26 +1090,24 @@
 			struct = false
 			
 			if typedef.type.struct?
-				type = get_struct_type(typedef.type, typedef["type64"], typedef["declaredType"])
+				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 << typedef.declaredType.gsub("*", "").nl
 				str << "alias "				
-				str << type[:name]
+				str << get_identifier(type.name)
+				str << "*" if typedef.declaredType =~ /\*/
 				str << " "
-				str << typedef["name"].nl
+				str << get_identifier(typedef.name).nl
 			else
 				str << "alias "
 				str << type
 				str << " "
-				str << typedef.name.nl
+				str << get_identifier(typedef.name).nl
 			end
 		end
 
@@ -1064,19 +1125,23 @@
 	#
 	def check_declared_type (type)		
 		case type
-			when "unichar"; return "wchar"
+			when "unichar"
+			when "UniChar"; return "wchar"
 			when "BOOL"; return "bool"
 			when "CGFloat"; return type
 			when "NSInteger"; return type
 			when "NSUInteger"; return type
+			when "IMP"; return type;
 				
-			when "unichar*"; return "wchar*"
+			when "unichar*"
+			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 "unichar**"
+			when "UniChar**"; return "wchar**"
 			when "BOOL**"; return "bool**"
 			when "CGFloat**"; return type
 			when "NSInteger**"; return type
@@ -1093,7 +1158,7 @@
 	#
 	def get_method_name (selector)
 		i = selector.index_of(":")
-		selector[0 ... i]
+		get_identifier(selector[0 ... i])
 	end
 	
 	# Gets the D type from the encoded C/Objective-C type
@@ -1106,14 +1171,14 @@
 	# get_type("I", "I", "unsigned int")    #=> uint
 	#
 	def get_type (type, type64, declared_type)
-				
-		return declared_type if type.nil? || type64.nil?			
-				
+		
+		return get_identifier(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
+			return get_identifier(declared_type) if type != type64
 		end
 		
 		case type
@@ -1135,9 +1200,15 @@
 		when '#'; return "Class"
 		when ":"; return "SEL"					
 		when "@"
-			return declared_type.gsub(/\*+/, "") unless declared_type.nil?
+			unless declared_type.nil?
+				t = declared_type.gsub(/\*+/, "")
+				return t == "id" ? "Object" : t
+			end
+			
 			raise "No declared type given"
 		else
+			return declared_type if type =~ /\{/
+			
 			case type[0, 1]
 			when "["
 				str = ""
@@ -1152,7 +1223,7 @@
 				str = get_type(t, t64, declared_type)
 				str << "[#{count}]"
 			
-				return str
+				return get_identifier(str)
 			when "("
 				resolved_types = []
 				types = $2 if type =~ /\((.+)=(.+)\)/
@@ -1162,28 +1233,34 @@
 					resolved_types << get_type(types[i], types64[i], declared_type)
 				end
 				
-				return resolved_types
-			when "^"				
+				return get_identifier(resolved_types)
+			when "^"	
 				if type == "^@"
-					return "out " << get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
+					return get_identifier(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 == "^?"
+					return get_identifier(get_type(type[2 .. -1], type64[2 .. -1], declared_type).dup + "**")
+				elsif type == "^?" # assuming function pointer
 					tmp = cfp_to_dfp(type)
-					return tmp unless tmp.nil?
+					return get_identifier(tmp) unless tmp.nil?
 				end
 				
 				if !type.nil? && !type64.nil?
-					return get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup << "*"
+					t = get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
+					
+					return get_identifier(t) if t =~ /\*/
+					return get_identifier(t + "*") if t !~ /\*/
 				elsif !type.nil?
-					return get_type(type[1 .. -1], type64, declared_type).dup << "*"
+					t = get_type(type[1 .. -1], type64, declared_type).dup << "*"
+					
+					return get_identifier(t) if t =~ /\*/
+					return get_identifier(t + "*") if t !~ /\*/
 				end			
 			when "{"
-				return declared_type
+				return get_identifier(declared_type)
 			end
 		end
 		
-		return declared_type
+		return get_identifier(declared_type)
 	end
 	
 	# Gets the D type from the encoded C/Objective-C type when it's a struct
@@ -1197,7 +1274,6 @@
     # { :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]
@@ -1205,11 +1281,11 @@
 			resolved_types = []
 		
 			if type =~ /\^{0,}\{(.{0,})=(.{0,})\}/
-				name = $1
-				types = $2
+				name = get_identifier($1)
+				types = get_identifier($2)
 			elsif type =~ /\^{0,}\((.{0,})=(.{0,})\)/
-				name = $1
-				types = $2
+				name = get_identifier($1)
+				types = get_identifier($2)
 			end
 		
 			unless types.nil?
@@ -1239,7 +1315,7 @@
 		name = $2
 		arg_types = $3
 		
-		return "#{return_type} function (#{arg_types})"
+		return "#{get_identifier(return_type)} function (#{arg_types})"
 	end
 	
 	# Is the supplied argument an "out" argument
@@ -1262,7 +1338,162 @@
 	#
 	def transform_selector (selector)
 		selector.gsub(/:/, "_")
+	end
+	
+	# Gets the identifier, if it's a D keyoword it
+	# will return string appended with a _ otherwise the string
+	def get_identifier (str)
+		return is_keyword?(str) ? str + "_" : str
 	end	
+	
+	# Returns true if the given string is a D(2) keyword
+	def is_keyword? (str)		
+		case str
+			when "abstract"; return true
+			when "alias"; return true
+			when "align"; return true
+			when "asm"; return true
+			when "assert"; return true
+			when "auto"; return true
+
+			when "body"; return true
+			when "bool"; return true
+			when "break"; return true
+			when "byte"; return true
+
+			when "case"; return true
+			when "cast"; return true
+			when "catch"; return true
+			when "cdouble"; return true
+			when "cent"; return true
+			when "cfloat"; return true
+			when "char"; return true
+			when "class"; return true
+			when "const"; return true
+			when "continue"; return true
+			when "creal"; return true
+
+			when "dchar"; return true
+			when "debug"; return true
+			when "default"; return true
+			when "delegate"; return true
+			when "delete"; return true
+			when "deprecated"; return true
+			when "do"; return true
+			when "double"; return true
+
+			when "else"; return true
+			when "enum"; return true
+			when "export"; return true
+			when "extern"; return true
+
+			when "false"; return true
+			when "final"; return true
+			when "finally"; return true
+			when "float"; return true
+			when "for"; return true
+			when "foreach"; return true
+			when "foreach_reverse"; return true
+			when "function"; return true
+
+			when "goto"; return true
+
+			when "idouble"; return true
+			when "if"; return true
+			when "ifloat"; return true
+			when "import"; return true
+			when "in"; return true
+			when "inout"; return true
+			when "int"; return true
+			when "interface"; return true
+			when "invariant"; return true
+			when "ireal"; return true
+			when "is"; return true
+
+			when "lazy"; return true
+			when "long"; return true
+
+			when "macro"; return true
+			when "mixin"; return true
+			when "module"; return true
+
+			when "new"; return true
+			when "nothrow"; return true
+			when "null"; return true
+
+			when "out"; return true
+			when "override"; return true
+
+			when "package"; return true
+			when "pragma"; return true
+			when "private"; return true
+			when "protected"; return true
+			when "public"; return true
+			when "pure"; return true
+
+			when "real"; return true
+			when "ref"; return true
+			when "return"; return true
+
+			when "scope"; return true
+			when "shared"; return true;s
+			when "short"; return true
+			when "static"; return true
+			when "struct"; return true
+			when "super"; return true
+			when "switch"; return true
+			when "synchronized"; return true
+
+			when "template"; return true
+			when "this"; return true
+			when "throw"; return true
+			when "true"; return true
+			when "try"; return true
+			when "typedef"; return true
+			when "typeid"; return true
+			when "typeof"; return true
+
+			when "ubyte"; return true
+			when "ucent"; return true
+			when "uint"; return true
+			when "ulong"; return true
+			when "union"; return true
+			when "unittest"; return true
+			when "ushort"; return true
+
+			when "version"; return true
+			when "void"; return true
+			when "volatile"; return true
+
+			when "wchar"; return true
+			when "while"; return true
+			when "with"; return true
+			else return false;
+		end
+	end
+	
+	def templates_for_class (clazz)		
+		templates = @templates.find_all do |template, value|
+			value[:class] == clazz
+		end
+		
+		return templates
+	end
+	
+	def interface_for_protocol (protocol)
+		interface = @interfaces2.find do |interface|
+			interface.name == protocol
+		end
+		
+		return interface
+	end	
+	
+	def get_framework_name (framework)
+		i = framework.rindex(".framework")
+		return framework if i.nil?
+		x = framework.rindex("/", i)
+		framework[x + 1 ... i]
+	end
 end
 
 # Prints the message to stderr, exits
--- a/scripts/dstepgen.rb	Thu Jun 18 22:00:13 2009 +0200
+++ b/scripts/dstepgen.rb	Sun Jul 05 17:16:19 2009 +0200
@@ -121,6 +121,13 @@
 	end	
 end
 
+Category = Struct.new(:name, :class) do
+	def initialize
+		self.name = ""
+		self.class = ""
+	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) }
@@ -136,19 +143,29 @@
 		@file_content = nil
 		@headers = []
 		@classes = {}
-		@informal_protocols = {}
+		@protocols = {}
+		@categories = {}
+		#@informal_protocols = {}
 		@function_pointer_types = {}
 		@do_64bit = false
 	end
 	
-	def classes
+	def get_classes
 		@classes
 	end
 	
-	def protocols
-		@informal_protocols
+	def get_protocols
+		@protocols
 	end
 	
+	def get_categories
+		@categories
+	end		
+	
+	# def get_informal_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|
@@ -262,12 +279,24 @@
 		header.imports = tmp.compact.uniq
 	end
 	
-	def informal_protocols (header)
-		self.methods(header)
+	# def informal_protocols (header)
+	# 	methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\([^)]+\))?/, @protocols, false)
+	# end
+	
+	def classes (header)
+		methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?$/, @classes, false)
 	end	
 	
-	def methods (header)
-		interface_re = /^@(interface|protocol)\s+(\w+)\s*:?\s*(\w*)\s*(\([^)]+\))?/
+	def protocols (header)
+		methods(header, /^@(protocol)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?(\([^)]+\))?/, @protocols, true)
+	end	
+
+	def categories (header)
+		methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?(\([^)]+\))/, @categories, false, true)
+	end	
+	
+	def methods (header, regex, array, protocol, category = false)
+		interface_re = regex
 		
 		end_re = /^@end/
 		body_re = /^[-+]\s*(\([^)]+\))?\s*([^:\s;]+)/
@@ -275,17 +304,28 @@
 		prop_re = /^@property\s*(\([^)]+\))?\s*([^;]+);$/
 		current_interface = current_category = nil
 		i = 0
-		parent = nil	
+		parent = nil
+		protocols = nil
+		cat = nil	
 		
-		@cpp_result.each_line do |line|
+		@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]
+				protocols = nil
+				current_category = md[6].delete("()").strip if md[6]
+				current_interface = md[2] unless category
+				current_interface = current_category if category	
 				parent = md[3] unless md[3] == ""
+				protocols = md[5] if md[5]
+				
+				if category
+					cat = Category.new if category
+					cat.name = current_category
+					cat.class = md[2]
+				end
 				
 			elsif end_re.match(line)
 				current_interface = current_category = nil
@@ -310,8 +350,10 @@
 					
 					typeinfo = VarInfo.new(type, "", "")
 					
-					@classes[current_interface] ||= {}					
-					methods = (@classes[current_interface].methods ||= [])
+					array[current_interface] ||= {} unless category
+					array[cat] ||= {} if category
+					methods = (array[current_interface].methods ||= []) unless category
+					methods = (array[cat].methods ||= []) if category
 					methods << MethodInfo.new(typeinfo, getter, false, [], line)
 					
 					unless readonly
@@ -377,23 +419,34 @@
 				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
+				# if protocol && current_category && current_interface == "NSObject"
+				# 	(@informal_protocols[current_category] ||= []) << method
+				# end
 				
-				@classes[current_interface] ||= {}
+				array[current_interface] ||= {} unless category
+				array[cat] ||= {} if category
 				
 				if header.name == current_interface				
-					@classes[current_interface].file = header.name
+					array[current_interface].file = header.name unless category
+					array[cat].file = header.name if category
 				else
-					@classes[current_interface].file ||= header.name
+					array[current_interface].file ||= header.name unless category
+					array[cat].file ||= header.name if category
 				end
 				
 				unless parent == current_interface || parent =~ /\s+/ || parent.nil?
-					@classes[current_interface].parent = parent
-				end				
+					array[current_interface].parent = parent unless category
+					array[cat].parent = parent if category
+				end
 				
-				(@classes[current_interface].methods ||= []) << method
+				unless protocols.nil?					
+					protocols.gsub!(/ /, "")										
+					array[current_interface].protocols = protocols unless category
+					array[cat].protocols = protocols if category
+				end
+				
+				(array[current_interface].methods ||= []) << method unless category
+				(array[cat].methods ||= []) << method if category
 			end
 			i += size
 		end
@@ -493,7 +546,7 @@
 		end
 	end
 	
-	def prepare (path)		
+	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, "")
@@ -517,7 +570,10 @@
 				functions(header)
 				functions(header, true)
 				defines(header)
-				methods(header)
+				classes(header)
+				protocols(header)
+				#informal_protocols(header)
+				categories(header)
 				function_pointer_types(header)
 			end
 		end
@@ -535,7 +591,10 @@
 			functions(header)
 			functions(header, true)
 			defines(header)
-			methods(header)
+			classes(header)
+			protocols(header)
+			#informal_protocols(header)
+			categories(header)
 			function_pointer_types(header)
 		end
 	end
@@ -815,7 +874,7 @@
 	
 	VERSION = 1.0
 	
-	attr_accessor :out_file, :scaner, :code_to_inject
+	attr_accessor :out_file, :scaner, :code_to_inject, :dependencies_switch
 	
 	def initialize
 		@do_64bit = false
@@ -823,12 +882,15 @@
 		@framework_paths = []
 		@headers = []
 		@import_directives = "#import <Foundation/Foundation.h>\n"
-		@informal_protocols = []
+		#@informal_protocols = []
 		@classes = []
+		@protocols = []
+		@categories = []
 		@scaner = HeaderScaner.new
 		@scaner.do_64bit = @do_64bit
 		@umbrella_framework = nil
 		@handled_dependencies = []
+		@dependencies_switch = false
 		
 		# link to foundation framework by default
 		@compiler_flags = "-framework Foundation"
@@ -841,12 +903,14 @@
 	def do_64bit= (do_64bit)
 		@do_64bit = do_64bit
 		@scaner.do_64bit = do_64bit
-	end	
+	end
 	
 	def collect		
 		scaner.scan(@frameworks, @headers)
-		@classes = scaner.classes
-		@informal_protocols = scaner.protocols
+		@classes = scaner.get_classes
+		@protocols = scaner.get_protocols
+		@categories = scaner.get_categories
+		#@informal_protocols = scaner.get_informal_protocols
 	end
 	
 	def handle_framework (framework, sub_framework = false, parent_framework = nil)
@@ -981,7 +1045,7 @@
 	
 	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 = File.new(unique_tmp_path("src", ".m"), "w")
 		src << code
 		src.close
 		
@@ -993,8 +1057,8 @@
 		
 		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"
+		bin = unique_tmp_path "bin", ""
+		log = unique_tmp_path "log", ".txt"
 		
 		line = "#{compiler_line} -o #{bin} #{src.path} #{@compiler_flags} 2>#{log}"
 		
@@ -1093,11 +1157,43 @@
 		types
 	end
 	
-	def collect_informal_protocols_types (enable_64bit)
+	def collect_protocols_types (enable_64bit)
 		types = []
 		
-		@informal_protocols.each do |name, methods|
-			methods.each do |method|				
+		@protocols.each do |protocol, 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 collect_categories_types (enable_64bit)
+		types = []
+		
+		@categories.each do |category, value|
+			value.methods.each do |method|				
 				types << method.stripped_return_type
 				
 				method.args.each do |arg|					
@@ -1154,7 +1250,7 @@
 		i
 	end
 	
-	def resolve_methods_types (enable_64bit, resolved_types, x)
+	def resolve_classes_types (enable_64bit, resolved_types, x)
 		i = x
 		
 		@classes.each do |clazz, value|
@@ -1174,11 +1270,51 @@
 		i
 	end
 	
-	def resolve_informal_protocols_types (enable_64bit, resolved_types, x)
+	def resolve_protocols_types (enable_64bit, resolved_types, x)
 		i = x
 		
-		@informal_protocols.each do |name, methods|
-			methods.each do |method|
+		@protocols.each do |protocol, 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_categories_types (enable_64bit, resolved_types, x)
+		i = x
+		
+		@categories.each do |category, 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
@@ -1211,7 +1347,7 @@
 		code << @import_directives
 		types = []
 		
-		code << @code_to_inject + ";\n" unless @code_to_inject.nil?
+		code << @code_to_inject + "\n" unless @code_to_inject.nil?
 		
 		@frameworks.each do |framework|
 			framework.headers.each do |header|
@@ -1229,7 +1365,9 @@
 		end
 		
 		types << collect_classes_types(enable_64bit)
-		types << collect_informal_protocols_types(enable_64bit)
+		types << collect_protocols_types(enable_64bit)
+		#types << collect_informal_protocols_types(enable_64bit)
+		types << collect_categories_types(enable_64bit)
 		
 		code << "int main ()\n{\n"
 		types.flatten!
@@ -1257,9 +1395,11 @@
 		@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)
+				
+		i = resolve_classes_types(enable_64bit, resolved_types, i)
+		i = resolve_protocols_types(enable_64bit, resolved_types, i)
+		#i = resolve_informal_protocols_types(enable_64bit, resolved_types, i)
+		i = resolve_categories_types(enable_64bit, resolved_types, i)
 	end
 	
 	def generate_header (xml, header)
@@ -1314,7 +1454,7 @@
 	
 	def generate_classes (xml)
 		@classes.each do |clazz, value|
-			xml.class :name => clazz, :parent => value.parent, :file => value.file do
+			xml.class :name => clazz, :parent => value.parent, :protocols => value.protocols, :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|
@@ -1328,10 +1468,42 @@
 		end
 	end
 	
-	def generate_informal_protocols (xml)
-		@informal_protocols.each do |name, methods|
-			xml.informalProtocol :name => name do
-				methods.each do |method|
+	def generate_protocols (xml)
+		@protocols.each do |protocol, value|
+			xml.protocol :name => protocol, :parent => value.parent, :protocols => value.protocols, :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_categories (xml)
+		@categories.each do |category, value|			
+			xml.category :name => category.name, :class => category.class, :parent => value.parent, :protocols => value.protocols, :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
@@ -1368,10 +1540,25 @@
 			end
 			
 			generate_classes(xml)
-			generate_informal_protocols(xml)
+			generate_protocols(xml)
+			#generate_informal_protocols(xml)
+			generate_categories(xml)
 		end
 		
 		file.close unless file == STDOUT
+	end
+	
+	def write_dependencies
+		file = STDOUT if @out_file == nil
+		file = File.open @out_file, "w" unless @out_file == nil
+		
+		@dependencies.each do |dep|
+			file << dep + "\n"
+		end
+		
+		file.close unless file == STDOUT
+		
+		exit 0
 	end	
 end
 
@@ -1410,10 +1597,14 @@
 		# 	dstep_gen.out_dir = opt
 		# end
 		
-		opts.on("-C", "--code CODE", "Add code") do |opt|
+		opts.on("-c", "--code CODE", "Add code") do |opt|
 			dstep_gen.code_to_inject = opt
 		end
 		
+		opts.on("-d", "--dependencies", "Write framework dependencies and exit") do |opt|
+			dstep_gen.dependencies_switch = true
+		end
+		
 		help_msg = "Use the `-h' flag or for help."	
 			
 		opts.on("-h", "--help", "Show this message.") do
@@ -1434,6 +1625,8 @@
 			#begin
 				opts.parse!(ARGV)
 				
+				dstep_gen.write_dependencies if dstep_gen.dependencies_switch
+				
 				ARGV.each do |header|
 					dstep_gen.add_header(header)
 				end
@@ -1448,4 +1641,4 @@
 			# end
 		end
 	end
-end
+end
\ No newline at end of file