Mercurial > projects > dstep
diff scripts/dgen.rb @ 11:07194b026fa4
Added bindings to a couple of frameworks, new license + some other things
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sat, 01 Aug 2009 15:03:28 +0200 |
parents | 27e00625790b |
children | 4f583f7e242e |
line wrap: on
line diff
--- a/scripts/dgen.rb Thu Jul 09 23:25:18 2009 +0200 +++ b/scripts/dgen.rb Sat Aug 01 15:03:28 2009 +0200 @@ -182,13 +182,15 @@ # This Struct represents a C/Objective-C header HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :c_constants, :d_constants, :d_constants_static_this, :defines, - :enums, :functions, :c_functions, :function_pointers, :function_wrappers, :imports, :path, :structs, :typedefs) do + :enums, :enums_gnu, :needs_type_encoding, :functions, :c_functions, :function_pointers, :function_wrappers, :imports, :path, :structs, :typedefs) do def initialize self.name = "" self.cftypes = [] self.constants = [] self.defines = [] self.enums = [] + self.enums_gnu = [] + self.needs_type_encoding = false self.framework = "" self.functions = [] self.c_functions = [] @@ -225,12 +227,19 @@ @c_functions = [] @headers = [] @package = "dstep" + @needs_bridge = false end # Generates the D code from the xml metadata def generate_code @files.each do |dstep_file| xml = XmlSimple.xml_in(dstep_file) + + @needs_bridge = !xml.protocol.nil? || !xml.category.nil? || !xml["class"].nil? + + interfaces(xml.protocol) unless xml.protocol.nil? + templates(xml.category) unless xml.category.nil? + classes(xml["class"]) unless xml["class"].nil? unless xml.framework.nil? frameworks = xml.framework @@ -246,12 +255,12 @@ 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.enums, header.enums_gnu, header.needs_type_encoding = enums(file.enum, header.name) unless file.enum.nil? header.functions = functions(file.function) unless file.function.nil? header.c_functions = c_functions unless file.function.nil? header.function_pointers = function_pointers(file.functionPointer) unless file.functionPointer.nil? header.function_wrappers = function_wrappers unless file.function.nil? - header.imports = imports(file.import, file.name, framework.name) unless file.import.nil? + header.imports = imports(header, 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? @@ -273,29 +282,26 @@ 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.enums, header.enums_gnu, header.needs_type_encoding = enums(file.enum) unless file.enum.nil? header.functions = functions(file.function) unless file.function.nil? header.function_pointers = function_pointers(file.functionPointer) unless file.functionPointer.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.imports = imports(header, 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 - - interfaces(xml.protocol) unless xml.protocol.nil? - templates(xml.category) unless xml.category.nil? - classes(xml["class"]) unless xml["class"].nil? + end end end # Outputs the generate D code def output_code @frameworks.each do |framework| - framework_path = framework_path = "#{@out_dir}/#{@package}/#{get_identifier(get_framework_name(framework.name.downcase))}" + framework_path = framework_path = "#{@out_dir}/#{@package}/#{get_identifier(get_framework_name(framework.name.downcase))}" unless sub_framework?(framework.name.downcase) + framework_path = framework_path = "#{@out_dir}/#{@package}/#{get_identifier(get_parent_framework_name(framework.name.downcase))}/#{get_identifier(get_framework_name(framework.name.downcase))}" if sub_framework?(framework.name.downcase) FileUtils.mkdir_p(framework_path) unless File.exist?(framework_path) @@ -303,13 +309,13 @@ 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)}" + mod = "#{@package}.#{get_identifier(get_framework_name(framework.name.downcase))}.#{get_identifier(header.name)}" unless sub_framework?(framework.name.downcase) + mod = "#{@package}.#{get_identifier(get_parent_framework_name(framework.name.downcase))}.#{get_identifier(get_framework_name(framework.name.downcase))}.#{get_identifier(header.name)}" if sub_framework?(framework.name.downcase) File.open(file_path, "w") do |file| file << copyright file << "module #{mod};" file << header.imports - file << "\n" if header.d_constants.nil? || header.function_wrappers.nil? file << "import bindings = #{mod}_bindings".nl.nl(false) unless header.d_constants.nil? || header.function_wrappers.nil? file << header.defines file << header.typedefs @@ -317,6 +323,7 @@ file << header.function_pointers file << header.c_constants file << header.d_constants + file << header.enums_gnu if header.needs_type_encoding file << header.enums file << header.structs @@ -376,7 +383,6 @@ file << copyright file << "module #{mod};" file << header.imports - file << "\n" if header.d_constants.nil? || header.function_wrappers.nil? file << "import bindings = #{mod}_bindings".nl.nl(false) unless header.d_constants.nil? || header.function_wrappers.nil? file << header.defines file << header.typedefs @@ -384,6 +390,7 @@ file << header.function_pointers file << header.c_constants file << header.d_constants + file << header.enums_gnu if header.needs_type_encoding file << header.enums file << header.structs @@ -754,42 +761,108 @@ end # Generates the D code for the enums - def enums (enums) + def enums (enums, header_name) return "" if enums.length == 0 str = StringIO.new + str_gnu = StringIO.new + consts = [] enums.each do |enum| + localConsts = [] + str_gnu2 = StringIO.new str << "enum" - + needs_type_encoding = false + if enum.name.length == 0 str << "\n{".nl(false) - enum.member.each_with_index do |member, i| - 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 + needs_type_encoding, localConsts = enum_helper(enum, str, str_gnu2, header_name) else str << " " str << get_identifier(enum["name"]).nl(false) str << "{".nl(false) - enum["member"].each_with_index do |member, i| - str << get_identifier(member["name"]).indent - str << " = " if member.value.length > 0 + needs_type_encoding, localConsts = enum_helper(enum, str, str_gnu2, header_name) + end + + str << "\n}".nl(false).nl(false) + + # if needs_type_encoding + # str_gnu << "// This is needed otherwise the enums will fail compiling with gdc\n" + # str_gnu << "version (GNU)\n{\n" + # str_gnu << "private\n".indent + # str_gnu << "{\n".indent + # str_gnu << str_gnu2.string + # str_gnu << "\n" + # str_gnu << "}".indent + # str_gnu << "\n}".nl(false).nl(false) + # end + + consts << localConsts + end + + consts.flatten! + + if @needs_type_encoding && consts.length > 0 + str_gnu << "// This is needed otherwise the enums will fail compiling with gdc\n" + str_gnu << "version (GNU)\n{\n" + str_gnu << "private\n".indent + str_gnu << "{\n".indent + + consts.each do |const| + str_gnu << "const __".indent(2) + str_gnu << const.name + str_gnu << ' = getOSType!("' + str_gnu << const.value + str_gnu << '")'.nl + end + + str_gnu << "}".indent + str_gnu << "\n}".nl(false).nl(false) + end + + needs_type_encoding = @needs_type_encoding + @needs_type_encoding = false + + return str.string, str_gnu.string, needs_type_encoding + end + + def enum_helper (enum, str, str_gnu, header_name) + needs_type_encoding = false + consts = [] + + enum.member.each_with_index do |member, i| + str << get_identifier(member.name).indent + + if member.value.length > 0 + needs_type_encoding = true if member.value[0, 1] == "'" + @needs_type_encoding = true if needs_type_encoding + str << " = " + + if member.value[0, 1] == "'" + str << 'getOSType!("' + str << member.value[1 ... -1] + str << '")' + + consts << { :name => get_identifier(member.name), :value => member.value[1 ... -1] } + # str_gnu << "const __".indent(2) + # str_gnu << get_identifier(member.name) + # str_gnu << " = " + # str_gnu << 'getOSType!("' + # str_gnu << member.value[1 ... -1] + # str_gnu << '")'.nl + else str << member.value - str << ",".nl(false) unless i == enum.member.length - 1 end end - str << "\n}".nl(false).nl(false) + str << ",".nl(false) unless i == enum.member.length - 1 end - str.string + return needs_type_encoding, consts end - + # Generates the D code for the function/method args def args (args, variadic, method = false) return "" if args.nil? @@ -975,7 +1048,7 @@ end # Generates the D code for the imports - def imports (imports, filename, framework_name = nil) + def imports (header, imports, filename, framework_name = nil) return "" if imports.length == 0 str = StringIO.new @@ -996,13 +1069,19 @@ str << splits[-1 .. -1] end - str << "import dstep.objc.bridge.Bridge".nl - str << "import dstep.objc.objc : id".nl + str << "import dstep.objc.bridge.TypeEncoding".nl if header.needs_type_encoding && !@needs_bridge + + if @needs_bridge + str << "import dstep.objc.bridge.Bridge".nl + str << "import dstep.objc.bridge.TypeEncoding".nl if header.needs_type_encoding + str << "import dstep.objc.objc : id".nl + end str << "\n\n" - str = str.string.sort.to_s + str = str.string.sort.to_s + str << "\n" - return "\n\npublic:" << str if filename == framework_name + return "\n\npublic:" << str if filename == get_framework_name(framework_name) return str end @@ -1121,13 +1200,24 @@ type = get_type(typedef.type, typedef.type64, typedef.declaredType) end - if struct - str << typedef.declaredType.gsub("*", "").nl - str << "alias " - str << get_identifier(type.name) - str << "*" if typedef.declaredType =~ /\*/ - str << " " - str << get_identifier(typedef.name).nl + if struct + unless type.name == typedef.name + declaredType = typedef.declaredType + declaredType = declaredType[7 .. -1] if declaredType.length > 7 && declaredType[0 ... 6] == "struct" + + unless declaredType == typedef.name + str << "alias " + str << get_identifier(declaredType) + str << " " + str << get_identifier(typedef.name).nl + end + + # str << "alias " + # str << get_identifier(type.name) + # str << "*" if typedef.declaredType =~ /\*{1}/ + # str << " " + # str << get_identifier(typedef.name).nl + end else str << "alias " str << type @@ -1186,6 +1276,18 @@ get_identifier(selector[0 ... i]) end + def get_matching_close_char (char) + case char + when "{"; return "}" + when "("; return ")" + when "["; return "]" + else + char + end + end + + + # Gets the D type from the encoded C/Objective-C type # type:: the type # type64:: the type for 64bit targets @@ -1243,9 +1345,15 @@ count = $1 if t =~ /(\d+)/ t = $' - t64 = type64[1 ... -1] - count = $1 if t64 =~ /(\d+)/ - t64 = $' + t64 = "" + + unless type64.nil? + t64 = type64[1 ... -1] + count = $1 if t64 =~ /(\d+)/ + t64 = $' + else + t64 = t + end str = get_type(t, t64, declared_type) str << "[#{count}]" @@ -1255,33 +1363,51 @@ resolved_types = [] types = $2 if type =~ /\((.+)=(.+)\)/ types64 = $2 if type64 =~ /\((.+)=(.+)\)/ + i = 0 - for i in types - resolved_types << get_type(types[i], types64[i], declared_type) - end + while i < types.length + t = types[i, 1] + t64 = types64.nil? ? t : types64[i, 1] + + index = t =~ /(\(|\[|\{)/ + + unless index.nil? + x = types.index(get_matching_close_char($1), index) + t = types[index .. x] + t64 = types64.nil? ? t : types64[index .. x] + i += x - index + end + + resolved_types << get_type(t, t64, declared_type) + i += 1 + end unless types.nil? - return get_identifier(resolved_types) - when "^" - if type == "^@" - return get_identifier(get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup + "*") - elsif type.length > 2 && type[0 ... 2] == "^^" - 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 get_identifier(tmp) unless tmp.nil? - end + get_identifier(resolved_types) + when "^" + t = type[1 .. -1] + t64 = type64.nil? ? t : type64[1 .. -1] + get_identifier(get_type(t, t64, declared_type).dup + "*") - if !type.nil? && !type64.nil? - 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? - t = get_type(type[1 .. -1], type64, declared_type).dup << "*" - - return get_identifier(t) if t =~ /\*/ - return get_identifier(t + "*") if t !~ /\*/ - end + # if type == "^@" + # return get_identifier(get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup + "*") + # elsif type.length > 2 && type[0 ... 2] == "^^" + # 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 get_identifier(tmp) unless tmp.nil? + # end + # + # if !type.nil? && !type64.nil? + # 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? + # 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 get_identifier(declared_type) end @@ -1521,6 +1647,22 @@ x = framework.rindex("/", i) framework[x + 1 ... i] end + + def sub_framework? (framework) + i = framework.index("framework") + return false if i.nil? + !framework.index("framework", i + 1).nil? + end + + def get_parent_framework_name (framework) + return get_framework_name(framework) unless sub_framework?(framework) + i = framework.index(".framework") + return framework if i.nil? + str = framework[0 ... i] + x = str.rindex("/") + return str if x.nil? + str[x + 1 .. -1] + end end # Prints the message to stderr, exits