changeset 6:c0cfd40362ee

Fixed the bridge to work with ldc and dmd. Added a couple of hooks to manipulate the source code
author Jacob Carlborg <doob@me.com>
date Wed, 08 Jul 2009 14:29:59 +0200
parents 7a60c3c4d421
children 9e67a1122e85
files dstep/objc/message.d dstep/objc/objc.d scripts/dstepgen.rb
diffstat 3 files changed, 171 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/dstep/objc/message.d	Sun Jul 05 22:14:45 2009 +0200
+++ b/dstep/objc/message.d	Wed Jul 08 14:29:59 2009 +0200
@@ -35,36 +35,51 @@
     
 	R msgSendSuper (R = id, ARGS...) (SEL op, ARGS args)
 	{
-		return (cast(R function (id, SEL, ARGS...))&bindings.objc_msgSendSuper)(this, op, args);
+		alias extern (C) R function (id, SEL, ARGS) fp;
+		return (cast(fp)&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);
+	    {
+	    	alias extern (C) void function (T*, id, SEL, ARGS) fp;
+	    	(cast(fp)&bindings.objc_msgSendSuper_stret)(&stretAddr, self, op, args);
+	    }
 	    
 	    else
-	        stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSendSuper)(self, op, args);
+	    {
+	    	alias extern (C) T function (id, SEL, ARGS) fp;
+	    	stretAddr = (*cast(fp)&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);
+	alias extern(C) R function (id, SEL, ARGS) fp;
+	return (cast(fp)&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);
+	alias extern(C) R function (objc_super*, SEL, ARGS) fp;
+	return (cast(fp)&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);
+    {
+    	alias extern(C) void function (T*, id, SEL, ARGS) fp;
+    	(cast(void function (fp))&bindings.objc_msgSend_stret)(&stretAddr, self, op, args);
+    }
     
     else
-        stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSend)(self, op, args);
+    {
+    	alias extern (C) T function (id, SEL, ARGS) fp;
+        stretAddr = (*cast(fp)&bindings.objc_msgSend)(self, op, args);
+    }
 }
 
 static if (X86 || X86_64)
@@ -77,34 +92,44 @@
 		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);
+		alias extern (C) R function (id, SEL, ARGS) fp;
+		return (cast(fp)&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);
+	alias extern (C) R function (id, SEL, ARGS) fp;
+	return (cast(fp)&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);
+	alias extern (C) R function (id, SEL, ARGS) fp;
+	return (cast(fp)&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);
+	alias extern (C) R function (id, SEL, size_t, T) fp;
+	(cast(fp)&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);
+    {
+    	alias extern (C) void function (R*, id, SEL, size_t, T) fp;
+    	(cast(fp)&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);
+    {
+    	alias extern (C) R function (id, SEL, size_t, T) fp;
+    	stretAddr = (*cast(fp)&bindings.objc_msgSendv)(self, op, arg_size, arg_frame);
+    }
 }
 
 version (X86)
@@ -112,6 +137,7 @@
 	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);
+		alias extern (C) R function (id, SEL, uint, T) fp;
+		return (cast(fp)&bindings.objc_msgSendv_fpret)(self, op, arg_size, arg_frame);
 	}
 }
\ No newline at end of file
--- a/dstep/objc/objc.d	Sun Jul 05 22:14:45 2009 +0200
+++ b/dstep/objc/objc.d	Wed Jul 08 14:29:59 2009 +0200
@@ -134,16 +134,23 @@
 
 	R msgSend (R = id, ARGS...) (SEL op, ARGS args)
 	{
-		return (cast(R function (id, SEL, ARGS))&bindings.objc_msgSend)(this, op, args);
+		alias extern (C) R function (id, SEL, ARGS) fp;
+		return (cast(fp)&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);			
+		{
+			alias extern (C) void function (T*, id, SEL, ARGS...) fp;
+			(cast(fp)&bindings.objc_msgSend_stret)(&stretAddr, this, op, args);
+		}			
 		    
 		else
-			stretAddr = (*cast(T function (id, SEL, ARGS...))&bindings.objc_msgSend)(this, op, args);  
+		{
+			alias extern (C) T function (id, SEL, ARGS) fp;
+			stretAddr = (*cast(fp)&bindings.objc_msgSend)(this, op, args);
+		}  
 	}
 
 	static if (dstep.internal.Version.X86 || X86_64)
@@ -156,32 +163,42 @@
 			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);
+			alias extern (C) R function (id, SEL, ARGS) fp;
+			return (cast(fp)&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);
+		alias extern (C) R function (id, SEL, ARGS) fp;
+		return (cast(fp)&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);
+		alias extern (C) R function (id, SEL, ARGS) fp;
+		return (cast(fp)&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);
+		alias extern (C) R function (id, SEL, size_t, T) fp;
+		(cast(fp)&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);
+	    {
+	    	alias extern (C) void function (R*, id, SEL, size_t, T) fp;
+	    	(cast(fp)&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);
+	    {
+	    	alias extern (C) R function (id, SEL, size_t, T) fp;
+	    	stretAddr = (*cast(fp)&bindings.objc_msgSendv)(this, op, arg_size, arg_frame);
+	    }
 	}
 
 	version (X86)
@@ -189,7 +206,8 @@
 		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);
+			alias extern (C) R function (id, SEL, uint, T) fp;
+			return (cast(fp)&bindings.objc_msgSendv_fpret)(this, op, arg_size, arg_frame);
 		}
 	}
 }
--- a/scripts/dstepgen.rb	Sun Jul 05 22:14:45 2009 +0200
+++ b/scripts/dstepgen.rb	Wed Jul 08 14:29:59 2009 +0200
@@ -136,7 +136,7 @@
 	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
+	attr_accessor :frameworks, :headers, :do_64bit, :extra
 	
 	def initialize
 		@extern_name = 'extern'
@@ -488,28 +488,29 @@
 	end	
 	
 	def structs (header)
-		re = /typedef\s+struct\s*\w*\s*((\w+)|\{([^{}]*(\{[^}]+\})?)*\}\s*([^\s]+))\s*(__attribute__\(.+\))?\s*;/
+		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				
@@ -520,7 +521,7 @@
 							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 = []
@@ -531,12 +532,12 @@
 								member
 							end
 						end
-						
+				
 						struct[:members] = tmp.compact
 					end
 				end
 			end
-			
+
 			header.structs << struct if body
 		end
 	end
@@ -909,7 +910,7 @@
 	
 	VERSION = 1.0
 	
-	attr_accessor :out_file, :scaner, :code_to_inject, :dependencies_switch
+	attr_accessor :out_file, :scaner, :inject_path, :dependencies_switch, :options, :exclude
 	
 	def initialize
 		@do_64bit = false
@@ -926,6 +927,9 @@
 		@umbrella_framework = nil
 		@handled_dependencies = []
 		@dependencies_switch = false
+		@options = []
+		@extra = false
+		@exclude = []
 		
 		# link to foundation framework by default
 		@compiler_flags = "-framework Foundation"
@@ -940,6 +944,15 @@
 		@scaner.do_64bit = do_64bit
 	end
 	
+	def extra
+		@extra
+	end
+	
+	def extra= (extra)
+		@extra = extra
+		@scaner.extra = extra
+	end		
+	
 	def collect		
 		scaner.scan(@frameworks, @headers)
 		@classes = scaner.get_classes
@@ -987,6 +1000,14 @@
 			header_basenames.unshift("#{name}.h")
 		end
 		
+		exclude = false
+		
+		@exclude.each do |e|
+			p e
+			p pnames
+			exclude = true if e =~ pname
+		end
+		
 		if sub_framework
 			pp = framework_path(parent_framework.name)
 			tmp, pname = pp.scan(/^(.+)\/(\w+)\.framework\/?$/)[0]
@@ -995,11 +1016,13 @@
 			@import_directives << header_basenames.map do |x|
 				"#import <#{name}/#{x}>"
 			end.join("\n")
-		end
+		end unless exclude
+		
+		exclude = false
 		
 		@import_directives << "\n"
 		
-		@compiler_flags ||= "-F\"#{parent_path}\" -framework #{name}"
+		@compiler_flags << " -F\"#{parent_path}\" -framework #{name}" unless sub_framework?(framework.name)
 		@cpp_flags ||= ""
 		@cpp_flags << "-F\"#{parent_path}\" "
 		
@@ -1014,12 +1037,18 @@
 		
 		# Memorize the dependencies.
 		@dependencies = DStepGenerator.dependencies_of_framework(path)
-				
 		handle_sub_frameworks(framework)
 	end
 	
+	def sub_framework? (framework)
+		i = framework.index("framework")
+		return false if i.nil?
+		!framework.index("framework", i + 1).nil?
+	end
+	
 	def handle_sub_frameworks (framework)
 		path = framework_path(framework.name)
+		@compiler_flags << " -B #{path}/Headers/ "
 		frameworks_path = File.join(path, "Frameworks")
 		frameworks = Dir.glob(File.join(frameworks_path, "*.framework"))
 		
@@ -1095,6 +1124,10 @@
 		bin = unique_tmp_path "bin", ""
 		log = unique_tmp_path "log", ".txt"
 		
+		@options.each do |option|
+			@compiler_flags << " #{option} "
+		end
+		
 		line = "#{compiler_line} -o #{bin} #{src.path} #{@compiler_flags} 2>#{log}"
 		
 		unless system(line)
@@ -1178,7 +1211,7 @@
 			
 			value.args.each do |arg|
 				types << arg.type
-			end
+			end unless value.args.nil?
 		end
 		
 		types
@@ -1299,7 +1332,7 @@
 				arg.resolved_type = resolved_types[i] unless enable_64bit
 				arg.resolved_type64 = resolved_types[i] if enable_64bit
 				i += 1
-			end
+			end unless value.args.nil?
 		end
 		
 		i
@@ -1385,35 +1418,55 @@
 		i
 	end
 	
+	def get_framework_name (framework)
+		i = framework.rindex(".framework")
+		return framework if i.nil?
+		x = framework.rindex("/", i)
+		framework[x + 1 ... 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 = "#include <stdio.h>\n"				
 		code << @import_directives
 		types = []
 		
-		code << @code_to_inject + "\n" unless @code_to_inject.nil?
-		
-		@frameworks.each do |framework|
+		@frameworks.each do |framework|			
 			framework.headers.each do |header|
+				exclude = false
 				
-				header.imports do |import|
-					code << "#import <#{import}.h>\n"
+				@exclude.each do |e|
+					exclude = true if e =~ header.name
 				end
 				
+				if framework.name[0, 1] == "/"
+					code << "#import \"#{framework.name}/Headers/#{header.name}.h\"\n" unless header.name == "xmmintrin"
+				else
+					code << "#import <#{framework.name}/#{header.name}.h>\n" unless header.name == "xmmintrin"
+				end unless exclude
+				
 				types << collect_header_types(header, enable_64bit)
+				
+				exclude = false
 			end
-		end
+		end if @extra
+		
+		@headers.each do |header|
+			exclude = false
+			
+			@exclude.each do |e|
+				exclude = true if e =~ header.name
+			end
+			
+			code << "#import <#{header.name}.h>\n" unless exclude || header.name == "xmmintrin"
+			
+			exclude = false
+		end if @extra
+		
+		File.foreach(@inject_path) do |line|
+			code << line
+		end if !@inject_path.nil? && File.exist?(@inject_path)
+		
+		code << "\n\n"
 
 		@headers.each do |header|
 			types << collect_header_types(header, enable_64bit)
@@ -1428,7 +1481,7 @@
 		types.flatten!
 		
 		types.each do |type|
-			code << '	printf("%s\n", ' + "@encode(#{type}));\n"
+			code << '	printf("%s\n", ' + "@encode(__typeof__(#{type})));\n" unless type.nil? || type.length == 0
 		end
 		
 		code << "	return 0;\n}"
@@ -1509,7 +1562,7 @@
 				xml.functionPointer :name => fp, :variadic => value.variadic do
 					value.args.each do |arg|
 						xml.arg :declaredType => arg.type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const
-					end
+					end unless value.args.nil?
 					
 					xml.returnValue :declaredType => value.return_type, :type => value.resolved_type, :type64 => value.resolved_type64, :const => value.const
 				end
@@ -1662,14 +1715,26 @@
 		# 	dstep_gen.out_dir = opt
 		# end
 		
-		opts.on("-c", "--code CODE", "Add code") do |opt|
-			dstep_gen.code_to_inject = opt
+		opts.on("-c", "--code FILE", "The path to a file with code to inject") do |opt|
+			dstep_gen.inject_path = opt
 		end
 		
 		opts.on("-d", "--dependencies", "Write framework dependencies and exit") do |opt|
 			dstep_gen.dependencies_switch = true
 		end
 		
+		opts.on("-s", "--option OPTION", "Pass OPTION to the compiler") do |opt|
+			dstep_gen.options << opt
+		end
+		
+		opts.on("-e", "--extra", "Included extra headers headers") do |opt|
+			dstep_gen.extra = true
+		end
+		
+		opts.on("-x", "--exclude HEADER", "Exlude the given header file") do |opt|
+			dstep_gen.exclude << opt
+		end
+		
 		help_msg = "Use the `-h' flag or for help."	
 			
 		opts.on("-h", "--help", "Show this message.") do