Mercurial > projects > dstep
annotate scripts/dstepgen.rb @ 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 |
rev | line source |
---|---|
1 | 1 #!/usr/bin/env ruby |
2 | |
3 # Copyright (c) 2008-2009, Jacob Carlborg. All rights reserved. | |
4 # Copyright (c) 2006-2007, Apple Inc. All rights reserved. | |
5 # Copyright (c) 2005-2006 FUJIMOTO Hisakuni | |
6 # | |
7 # Redistribution and use in source and binary forms, with or without | |
8 # modification, are permitted provided that the following conditions | |
9 # are met: | |
10 # 1. Redistributions of source code must retain the above copyright | |
11 # notice, this list of conditions and the following disclaimer. | |
12 # 2. Redistributions in binary form must reproduce the above copyright | |
13 # notice, this list of conditions and the following disclaimer in the | |
14 # documentation and/or other materials provided with the distribution. | |
15 # 3. Neither the name of Apple Inc. ("Apple") nor the names of | |
16 # its contributors may be used to endorse or promote products derived | |
17 # from this software without specific prior written permission. | |
18 # | |
19 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND | |
20 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 # ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR | |
23 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
27 # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
28 # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 # POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 require "rubygems" | |
32 gem "builder", "~> 2.0" | |
33 require "builder" | |
34 require "tmpdir" | |
35 require "optparse" | |
36 include Builder | |
37 | |
38 $KCODE = "UTF8" | |
39 | |
40 # Extensions that adds support for member access syntax | |
41 class Hash | |
42 def type | |
43 result = self["type"] | |
44 return result unless result.nil? | |
45 self[:type] | |
46 end | |
47 | |
48 def type= (type) | |
49 self[:type] = type | |
50 end | |
51 | |
52 def id | |
53 result = self["id"] | |
54 return result unless result.nil? | |
55 self[:id] | |
56 end | |
57 | |
58 def id= (id) | |
59 self[:id] = id | |
60 end | |
61 | |
62 def methods | |
63 result = self["methods"] | |
64 return result unless result.nil? | |
65 self[:methods] | |
66 end | |
67 | |
68 def methods= (methods) | |
69 self[:methods] = methods | |
70 end | |
71 | |
72 def method_missing (method, *args) | |
73 self.class.instance_eval do | |
74 define_method(method) do |*args| | |
75 if args.length > 0 | |
76 self[method[0 ... -1]] = args[0] | |
77 self[eval(":#{method}"[0 ... -1])] = args[0] | |
78 else | |
79 result = self[method] | |
80 return result unless result.nil? | |
81 self[eval(":#{method}")] | |
82 end | |
83 end | |
84 end | |
85 | |
86 if (method = method.id2name) =~ /=/ | |
87 eval("self.#{method} (args.length < 2 ? args[0] : args)") | |
88 else | |
89 eval("self.#{method}") | |
90 end | |
91 end | |
92 end | |
93 | |
94 # This Struct represents an Objective-C Framework | |
95 Framework = Struct.new(:name, :headers, :path) do | |
96 def initialize | |
97 self.headers = [] | |
98 self.name = "" | |
99 self.path = "" | |
100 end | |
101 end | |
102 | |
103 # This Struct represents a C/Objective-C header | |
104 HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :defines, :enums, :externs, :functions, | |
105 :imports, :inline_functions, :opaques, :path, :structs, :typedefs) do | |
106 def initialize | |
107 self.name = "" | |
108 self.cftypes = [] | |
109 self.constants = [] | |
110 self.defines = [] | |
111 self.enums = [] | |
112 self.externs = [] | |
113 self.framework = "" | |
114 self.functions = [] | |
115 self.imports = [] | |
116 self.inline_functions = [] | |
117 self.opaques = [] | |
118 self.path = "" | |
119 self.structs = [] | |
120 self.typedefs = [] | |
121 end | |
122 end | |
123 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
124 Category = Struct.new(:name, :class) do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
125 def initialize |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
126 self.name = "" |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
127 self.class = "" |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
128 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
129 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
130 |
1 | 131 # This class scans the headers |
132 class HeaderScaner | |
133 CPP = ['/usr/bin/cpp-4.0', '/usr/bin/cpp-3.3', '/usr/bin/cpp3'].find { |x| File.exist?(x) } | |
134 raise "cpp not found" if CPP.nil? | |
135 CPPFLAGS = "-D__APPLE_CPP__ -include /usr/include/AvailabilityMacros.h" | |
136 CPPFLAGS << "-D__GNUC__" unless /\Acpp-4/.match(File.basename(CPP)) | |
137 | |
138 attr_accessor :frameworks, :headers, :do_64bit | |
139 | |
140 def initialize | |
141 @extern_name = 'extern' | |
142 @frameworks = [] | |
143 @file_content = nil | |
144 @headers = [] | |
145 @classes = {} | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
146 @protocols = {} |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
147 @categories = {} |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
148 #@informal_protocols = {} |
1 | 149 @function_pointer_types = {} |
150 @do_64bit = false | |
151 end | |
152 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
153 def get_classes |
1 | 154 @classes |
155 end | |
156 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
157 def get_protocols |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
158 @protocols |
1 | 159 end |
160 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
161 def get_categories |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
162 @categories |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
163 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
164 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
165 # def get_informal_protocols |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
166 # @informal_protocols |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
167 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
168 |
1 | 169 def cftypes (header) |
170 re = /typedef\s+(const\s+)?(struct\s*\w+\s*\*\s*)([^\s]+Ref)\s*;/ | |
171 @cpp_result.scan(re).each do |m| | |
172 header.cftypes << { :name => m[2], :type => m[1], :const => m[0] =~ /const/ ? true : false} | |
173 end | |
174 end | |
175 | |
176 def constants (header) | |
177 tmp = header.externs.map do |i| | |
178 constant?(i, true) | |
179 end | |
180 | |
181 header.constants = tmp.flatten.compact | |
182 end | |
183 | |
184 def defines (header) | |
185 re = /#define\s+([^\s]+)\s+(\([^)]+\)|[^\s]+)\s*$/ | |
186 @file_content.scan(re).each do |m| | |
187 next unless !m[0].include?('(') && m[1] != '\\' | |
188 header.defines << { :name => m[0], :value => m[1] } | |
189 end | |
190 end | |
191 | |
192 def enums (header) | |
193 re = /\benum\b\s*(\w+\s+)?\{([^}]*)\}/ | |
194 @cpp_result.scan(re).each do |m| | |
195 enum = { :name => m[0], :members => [] } | |
196 | |
197 m[1].split(",").map do |i| | |
198 name, value = i.split("=", 2).map do |x| | |
199 x.strip | |
200 end | |
201 | |
202 enum[:members] << { :name => name, :value => value } unless name.empty? || name[0] == ?# | |
203 end | |
204 | |
205 header.enums << enum | |
206 end | |
207 end | |
208 | |
209 def function_pointer_types (header) | |
210 re = /typedef\s+([\w\s]+)\s*\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*;/ | |
211 data = @cpp_result.scan(re) | |
212 re = /typedef\s+([\w\s]+)\s*\(([^)]+)\)\s*;/ | |
213 data |= @cpp_result.scan(re).map do |m| | |
214 ary = m[0].split(/(\w+)$/) | |
215 ary[1] << " *" | |
216 ary << m[1] | |
217 ary | |
218 end | |
219 | |
220 data.each do |m| | |
221 name = m[1] | |
222 args = m[2].split(",").map do |x| | |
223 if x.include?(" ") | |
224 ptr = x.sub!(/\[\]\s*$/, "") | |
225 x = x.sub(/\w+\s*$/, "").strip | |
226 ptr ? x + "*" : x | |
227 else | |
228 x.strip | |
229 end | |
230 end | |
231 | |
232 type = "#{m[0]}(*)(#{args.join(', ')})" | |
233 @function_pointer_types[name] = type | |
234 end | |
235 end | |
236 | |
237 def typedefs (header) | |
238 re = /^\s*typedef\s+(.+)\s+([\w\*]+)\s*;$/ | |
239 data = @cpp_result | |
240 data.scan(re).each do |m| | |
241 var = get_var_info(m[0] + " " + m[1]) | |
242 header.typedefs << get_var_info(m[0] + " " + m[1]) if var | |
243 end | |
244 end | |
245 | |
246 def externs (header) | |
247 re = /^\s*#{@extern_name}\s+\b(.*)\s*;.*$/ | |
248 header.externs = @cpp_result.scan(re).map do |m| | |
249 m[0].strip | |
250 end | |
251 end | |
252 | |
253 def imports (header) | |
254 tmp = [] | |
255 | |
256 @file_content.each do |line| | |
257 if line =~ /#(include|import) <(.+)\.h>/ | |
258 next if $2 == header.name | |
259 tmp << $2 | |
260 elsif line =~ /@class(\s+)(\w+)(,|;)/ | |
261 next if $2 == header.name | |
262 | |
263 if $3 == ";" | |
264 tmp << header.framework + "/" + $2 unless header.framework == "" | |
265 tmp << $2 if header.framework == "" | |
266 elsif | |
267 str = line[6 + $1.length ... -2] | |
268 str.gsub!(" ", "") | |
269 arr = str.split(",") | |
270 | |
271 arr.each do |s| | |
272 tmp << header.framework + "/" + s unless header.framework == "" | |
273 tmp << s if header.framework == "" | |
274 end | |
275 end | |
276 end | |
277 end | |
278 | |
279 header.imports = tmp.compact.uniq | |
280 end | |
281 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
282 # def informal_protocols (header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
283 # methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\([^)]+\))?/, @protocols, false) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
284 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
285 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
286 def classes (header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
287 methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?$/, @classes, false) |
1 | 288 end |
289 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
290 def protocols (header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
291 methods(header, /^@(protocol)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?(\([^)]+\))?/, @protocols, true) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
292 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
293 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
294 def categories (header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
295 methods(header, /^@(interface)\s+(\w+)\s*:?\s*(\w*)\s*(\<([\w,\s]+)>)?(\([^)]+\))/, @categories, false, true) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
296 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
297 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
298 def methods (header, regex, array, protocol, category = false) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
299 interface_re = regex |
1 | 300 |
301 end_re = /^@end/ | |
302 body_re = /^[-+]\s*(\([^)]+\))?\s*([^:\s;]+)/ | |
303 args_re = /\w+\s*:/ | |
304 prop_re = /^@property\s*(\([^)]+\))?\s*([^;]+);$/ | |
305 current_interface = current_category = nil | |
306 i = 0 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
307 parent = nil |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
308 protocols = nil |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
309 cat = nil |
1 | 310 |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
311 @cpp_result.each_line do |line| |
1 | 312 size = line.size |
313 line.strip! | |
314 | |
315 if md = interface_re.match(line) | |
316 parent = nil | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
317 protocols = nil |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
318 current_category = md[6].delete("()").strip if md[6] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
319 current_interface = md[2] unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
320 current_interface = current_category if category |
1 | 321 parent = md[3] unless md[3] == "" |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
322 protocols = md[5] if md[5] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
323 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
324 if category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
325 cat = Category.new if category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
326 cat.name = current_category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
327 cat.class = md[2] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
328 end |
1 | 329 |
330 elsif end_re.match(line) | |
331 current_interface = current_category = nil | |
332 | |
333 elsif current_interface && md = prop_re.match(line) | |
334 # Parsing Objective-C 2.0 properties | |
335 if (a = md[2].split(/\s/)).length >= 2 && /^\w+$/.match(name = a[-1]) && (type = a[0 .. -2].join(" ")).index(",").nil? | |
336 getter, setter = name, "set#{name[0].chr.upcase + name[1 .. -1]}" | |
337 readonly = false | |
338 | |
339 if attributes = md[1] | |
340 if md = /getter\s*=\s*(\w+)/.match(attributes) | |
341 getter = md[1] | |
342 end | |
343 | |
344 if md = /setter\s*=\s*(\w+)/.match(attributes) | |
345 setter = md[1] | |
346 end | |
347 | |
348 readonly = true if attributes.index("readonly") | |
349 end | |
350 | |
351 typeinfo = VarInfo.new(type, "", "") | |
352 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
353 array[current_interface] ||= {} unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
354 array[cat] ||= {} if category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
355 methods = (array[current_interface].methods ||= []) unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
356 methods = (array[cat].methods ||= []) if category |
1 | 357 methods << MethodInfo.new(typeinfo, getter, false, [], line) |
358 | |
359 unless readonly | |
360 methods << MethodInfo.new(VarInfo.new("void", "", ""), setter + ":", false, [typeinfo], line) | |
361 end | |
362 end | |
363 | |
364 elsif current_interface && (line[0] == ?+ || line[0] == ?-) | |
365 mtype = line[0] | |
366 data = @cpp_result[i .. -1] | |
367 body_md = body_re.match(data) | |
368 | |
369 next if body_md.nil? | |
370 | |
371 rettype = body_md[1] ? body_md[1].delete("()") : "id" | |
372 retval = VarInfo.new(rettype, "", "") | |
373 args = [] | |
374 selector = "" | |
375 data = data[0 .. data.index(";")] | |
376 args_data = [] | |
377 | |
378 data.scan(args_re) do |x| | |
379 args_data << [$`, x, $'] | |
380 end | |
381 | |
382 variadic = false | |
383 args_data.each_with_index do |ary, n| | |
384 before, argname, argtype = ary | |
385 arg_nameless = (n > 0 && /\)\s*$/.match(before)) | |
386 argname = ":" if arg_nameless | |
387 realargname = nil | |
388 | |
389 if n < args_data.length - 1 | |
390 argtype.sub!(args_data[n + 1][2], "") | |
391 | |
392 if arg_nameless | |
393 argtype.sub!(/(\w+\s*)?\w+\s*:\s*$/, "") | |
394 else | |
395 unless argtype.sub!(/(\w+)\s+\w+:\s*$/) { |s| realargname = $1; "" } | |
396 # maybe the next argument is nameless | |
397 argtype.sub!(/\w+\s*:\s*$/, "") | |
398 end | |
399 end | |
400 else | |
401 argtype.sub!(/\s+__attribute__\(\(.+\)\)/, "") | |
402 | |
403 if arg_nameless | |
404 argtype.sub!(/\w+\s*;$/, "") | |
405 else | |
406 unless argtype.sub!(/(\w+)\s*;$/) { |s| realargname = $1; "" } | |
407 variadic = argtype.sub!(/,\s*\.\.\.\s*;/, "") != nil | |
408 argtype.sub!(/\w+\s*$/, "") if variadic | |
409 end | |
410 end | |
411 end | |
412 | |
413 selector << argname | |
414 realargname ||= argname.sub(/:/, "") | |
415 args << VarInfo.new(argtype, realargname, "") unless argtype.empty? | |
416 end | |
417 | |
418 selector = body_md[2] if selector.empty? | |
419 args << VarInfo.new("...", "vararg", "") if variadic | |
420 method = MethodInfo.new(retval, selector, line[0] == ?+, args, data) | |
421 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
422 # if protocol && current_category && current_interface == "NSObject" |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
423 # (@informal_protocols[current_category] ||= []) << method |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
424 # end |
1 | 425 |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
426 array[current_interface] ||= {} unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
427 array[cat] ||= {} if category |
1 | 428 |
429 if header.name == current_interface | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
430 array[current_interface].file = header.name unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
431 array[cat].file = header.name if category |
1 | 432 else |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
433 array[current_interface].file ||= header.name unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
434 array[cat].file ||= header.name if category |
1 | 435 end |
436 | |
437 unless parent == current_interface || parent =~ /\s+/ || parent.nil? | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
438 array[current_interface].parent = parent unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
439 array[cat].parent = parent if category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
440 end |
1 | 441 |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
442 unless protocols.nil? |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
443 protocols.gsub!(/ /, "") |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
444 array[current_interface].protocols = protocols unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
445 array[cat].protocols = protocols if category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
446 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
447 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
448 (array[current_interface].methods ||= []) << method unless category |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
449 (array[cat].methods ||= []) << method if category |
1 | 450 end |
451 i += size | |
452 end | |
453 end | |
454 | |
455 def structs (header) | |
456 re = /typedef\s+struct\s*\w*\s*((\w+)|\{([^{}]*(\{[^}]+\})?)*\}\s*([^\s]+))\s*(__attribute__\(.+\))?\s*;/ | |
457 i = 0 | |
458 body = nil | |
459 @cpp_result.scan(re).each do |m| | |
460 struct = { :name => m[4], :members => [] } | |
461 | |
462 unless struct[:name].nil? | |
463 if struct[:name][0, 1] == "*" | |
464 struct[:name].sub!("*", "") | |
465 end | |
466 end | |
467 | |
468 return_type = nil | |
469 stripped_return_type = nil | |
470 body = m[2] | |
471 | |
472 if m[2] | |
473 m[2].split(/,|;/).map do |i| | |
474 str, bytes = i.split(":", 2).map do |x| | |
475 x.strip | |
476 end | |
477 | |
478 var = get_var_info(str, true) | |
479 | |
480 if var | |
481 if var.return_type == "***dummy***" | |
482 var.return_type = return_type | |
483 var.stripped_return_type = stripped_return_type | |
484 else | |
485 return_type = var.return_type | |
486 stripped_return_type = var.stripped_return_type | |
487 end | |
488 | |
489 struct[:members] << { :name => var.name, :bytes => bytes, :declaredType => var.return_type, :type => "", :type64 => "" } unless str.empty? || str[0] == ?# | |
490 | |
491 names = [] | |
492 | |
493 tmp = struct[:members].collect do |member| | |
494 unless names.include?(member[:name]) | |
495 names << member[:name] | |
496 member | |
497 end | |
498 end | |
499 | |
500 struct[:members] = tmp.compact | |
501 end | |
502 end | |
503 end | |
504 | |
505 header.structs << struct if body | |
506 end | |
507 end | |
508 | |
509 def functions (header, inline = false) | |
510 if inline | |
511 inline_func_re = /(inline|__inline__)\s+((__attribute__\(\([^)]*\)\)\s+)?([\w\s\*<>]+)\s*\(([^)]*)\)\s*)\{/ | |
512 res = @cpp_result.scan(inline_func_re) | |
513 res.each do |x| | |
514 x.delete_at(0) | |
515 x.delete_at(1) | |
516 end | |
517 else | |
518 skip_inline_re = /(static)?\s(inline|__inline__)[^{;]+(;|\{([^{}]*(\{[^}]+\})?)*\})\s*/ | |
519 func_re = /(^([\w\s\*<>]+)\s*\(([^)]*)\)\s*)(__attribute__[^;]+)?;/ | |
520 res = @cpp_result.gsub(skip_inline_re, '').scan(func_re) | |
521 end | |
522 | |
523 funcs = res.map do |m| | |
524 orig, base, args = m | |
525 base.sub!(/^.*extern\s/, "") | |
526 func = constant?(base) | |
527 | |
528 if func | |
529 args = args.strip.split(",").map do |i| | |
530 constant?(i) | |
531 end | |
532 | |
533 next if args.any? do |x| | |
534 x.nil? | |
535 end | |
536 | |
537 args = [] if args.size == 1 && args[0].return_type == "void" | |
538 FunctionInfo.new(func, args, orig, inline) | |
539 end | |
540 end.compact | |
541 | |
542 if inline | |
543 header.inline_functions = funcs | |
544 else | |
545 header.functions = funcs | |
546 end | |
547 end | |
548 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
549 def prepare (path) |
1 | 550 @file_content = File.read(path) |
551 @file_content.gsub!(%r{(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)}, ""); | |
552 @complete_cpp_result, @cpp_result = do_cpp(path, false, true, "") | |
553 end | |
554 | |
555 def scan (frameworks, headers) | |
556 @frameworks = frameworks | |
557 @headers = headers | |
558 | |
559 @frameworks.each do |framework| | |
560 framework.headers.each do |header| | |
561 prepare(header.path) | |
562 | |
563 imports(header) | |
564 cftypes(header) | |
565 externs(header) | |
566 constants(header) | |
567 enums(header) | |
568 structs(header) | |
569 typedefs(header) | |
570 functions(header) | |
571 functions(header, true) | |
572 defines(header) | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
573 classes(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
574 protocols(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
575 #informal_protocols(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
576 categories(header) |
1 | 577 function_pointer_types(header) |
578 end | |
579 end | |
580 | |
581 @headers.each do |header| | |
582 prepare(header.path) | |
583 | |
584 imports(header) | |
585 cftypes(header) | |
586 externs(header) | |
587 constants(header) | |
588 enums(header) | |
589 structs(header) | |
590 typedefs(header) | |
591 functions(header) | |
592 functions(header, true) | |
593 defines(header) | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
594 classes(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
595 protocols(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
596 #informal_protocols(header) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
597 categories(header) |
1 | 598 function_pointer_types(header) |
599 end | |
600 end | |
601 | |
602 def get_var_info (str, multi = false) | |
603 str.strip! | |
604 | |
605 return nil if str.empty? | |
606 | |
607 if str == "..." | |
608 VarInfo.new("...", "...", str) | |
609 else | |
610 str = "***dummy*** " + str if str[-1].chr == '*' || str.index(/\s/).nil? | |
611 tokens = multi ? str.split(',') : [str] | |
612 part = tokens.first | |
613 re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/ | |
614 m = re.match(part) | |
615 | |
616 if m | |
617 return nil if m[1].split(/\s+/).any? do |x| | |
618 ['end', 'typedef'].include?(x) | |
619 end | |
620 | |
621 m = m.to_a[1..-1].compact.map do |i| | |
622 i.strip | |
623 end | |
624 | |
625 m[0] += m[2] if m.size == 3 | |
626 m[0] = 'void' if m[1] == 'void' | |
627 | |
628 var = begin | |
629 VarInfo.new(m[0], m[1], part) | |
630 rescue | |
631 return nil | |
632 end | |
633 | |
634 if tokens.size > 1 | |
635 [var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }] | |
636 else | |
637 var | |
638 end | |
639 end | |
640 end | |
641 end | |
642 | |
643 def constant? (str, multi = false) | |
644 str.strip! | |
645 return nil if str.empty? | |
646 | |
647 if str == '...' | |
648 VarInfo.new('...', '...', str) | |
649 else | |
650 str << " dummy" if str[-1].chr == '*' or str.index(/\s/).nil? | |
651 tokens = multi ? str.split(',') : [str] | |
652 part = tokens.first | |
653 re = /^([^()]*)\b(\w+)\b\s*(\[[^\]]*\])*$/ | |
654 m = re.match(part) | |
655 | |
656 if m | |
657 return nil if m[1].split(/\s+/).any? do |x| | |
658 ['end', 'typedef'].include?(x) | |
659 end | |
660 | |
661 m = m.to_a[1..-1].compact.map do |i| | |
662 i.strip | |
663 end | |
664 | |
665 m[0] += m[2] if m.size == 3 | |
666 m[0] = 'void' if m[1] == 'void' | |
667 | |
668 var = begin | |
669 VarInfo.new(m[0], m[1], part) | |
670 rescue | |
671 return nil | |
672 end | |
673 | |
674 if tokens.size > 1 | |
675 [var, *tokens[1..-1].map { |x| constant?(m[0] + x.strip.sub(/^\*+/, '')) }] | |
676 else | |
677 var | |
678 end | |
679 end | |
680 end | |
681 end | |
682 | |
683 class VarInfo | |
684 | |
685 attr_reader :name, :orig, :const, :type_modifier | |
686 attr_accessor :octype, :resolved_type, :resolved_type64, :return_type, :stripped_return_type | |
687 | |
688 def initialize (type, name, orig) | |
689 @return_type = type.clone | |
690 @name = name | |
691 @orig = orig | |
692 @const = false | |
693 @type_modifier = "" | |
694 | |
695 @return_type.gsub!(/\[[^\]]*\]/, "*") | |
696 | |
697 if @return_type =~ /\bconst\b/ | |
698 @const = true | |
699 @return_type.gsub!("const", "") | |
700 end | |
701 | |
702 if @return_type =~ /\b(in|out|inout|oneway|bycopy|byref)\b/ | |
703 | |
704 case $1 | |
705 when "in" | |
706 @type_modifier << "n" | |
707 when "out" | |
708 @type_modifier << "o" | |
709 when "inout" | |
710 @type_modifier << "N" | |
711 when "oneway" | |
712 @type_modifier << "w" | |
713 when "bycopy" | |
714 @type_modifier << "c" | |
715 when "byref" | |
716 @type_modifier << "r" | |
717 end | |
718 | |
719 @return_type.gsub!("#{$1}", "") | |
720 end | |
721 | |
722 @return_type.gsub!(/\s?\*\s?/, "*") | |
723 @return_type.gsub!(/^\(|\)$/, "") | |
724 @return_type.strip! | |
725 | |
726 t = type.gsub(/\b(__)?const\b/, "") | |
727 t.gsub!(/<[^>]*>/, '') | |
728 t.gsub!(/\b(in|out|inout|oneway|const)\b/, "") | |
729 t.gsub!(/\b__private_extern__\b/, "") | |
730 t.gsub!(/^\s*\(?\s*/, "") | |
731 t.gsub!(/\s*\)?\s*$/, "") | |
732 | |
733 raise "Empty type (was '#{type}')" if t.empty? | |
734 | |
735 @stripped_return_type = t | |
736 end | |
737 | |
738 def function_pointer? (function_pointer_types) | |
739 type = @function_pointer_types[@stripped_return_type] || @stripped_return_type | |
740 @function_pointer_type ||= FunctionPointerInfo.new_from_type(type) | |
741 end | |
742 | |
743 def <=>(x) | |
744 self.name <=> x.name | |
745 end | |
746 | |
747 def hash | |
748 @name.hash | |
749 end | |
750 | |
751 def eql? (o) | |
752 @name == o.name | |
753 end | |
754 end | |
755 | |
756 class FunctionInfo < VarInfo | |
757 | |
758 attr_reader :args, :argc | |
759 | |
760 def initialize (function, args, orig, inline = false) | |
761 super(function.return_type, function.name, orig) | |
762 | |
763 @args = args | |
764 @argc = @args.size | |
765 @variadic = false | |
766 | |
767 if @args[-1] && @args[-1].return_type == "..." | |
768 @argc -= 1 | |
769 @variadic = true | |
770 @args.pop | |
771 end | |
772 | |
773 @inline = inline | |
774 self | |
775 end | |
776 | |
777 def variadic? | |
778 @variadic | |
779 end | |
780 | |
781 def inline? | |
782 @inline | |
783 end | |
784 end | |
785 | |
786 class FunctionPointerInfo < FunctionInfo | |
787 def initialize (return_type, arg_types, orig) | |
788 args = arg_types.map do |x| | |
789 VarInfo.new(x, "", "") | |
790 end | |
791 | |
792 super(VarInfo.new(return_type, "", ""), args, orig) | |
793 end | |
794 | |
795 def self.new_from_type (type) | |
796 @cache ||= {} | |
797 info = @cache[type] | |
798 | |
799 return info if info | |
800 | |
801 tokens = type.split(/\(\*\)/) | |
802 return nil if tokens.size != 2 | |
803 | |
804 return_type = tokens.first.strip | |
805 rest = tokens.last.sub(/^\s*\(\s*/, "").sub(/\s*\)\s*$/, "") | |
806 | |
807 arg_types = rest.split(/,/).map do |x| | |
808 x.strip | |
809 end | |
810 | |
811 @cache[type] = self.new(return_type, arg_types, type) | |
812 end | |
813 end | |
814 | |
815 class MethodInfo < FunctionInfo | |
816 | |
817 attr_reader :selector | |
818 | |
819 def initialize (method, selector, is_class, args, orig) | |
820 super(method, args, orig) | |
821 | |
822 @selector = selector | |
823 @is_class = is_class | |
824 self | |
825 end | |
826 | |
827 def class_method? | |
828 @is_class | |
829 end | |
830 | |
831 def <=>(o) | |
832 @selector <=> o.selector | |
833 end | |
834 | |
835 def hash | |
836 @selector.hash | |
837 end | |
838 | |
839 def eql? (o) | |
840 @selector == o.selector | |
841 end | |
842 end | |
843 | |
844 def do_cpp (path, fails_on_error = true, do_64 = true, flags = "") | |
845 f_on = false | |
846 err_file = '/tmp/.cpp.err' | |
847 cpp_line = "#{CPP} #{CPPFLAGS} #{flags} #{do_64 ? '-D__LP64__' : ''} \"#{path}\" 2>#{err_file}" | |
848 complete_result = `#{cpp_line}` | |
849 | |
850 if $?.to_i != 0 && fails_on_error | |
851 $stderr.puts File.read(err_file) | |
852 File.unlink(err_file) | |
853 raise "#{CPP} returned #{$?.to_int/256} exit status\nline was: #{cpp_line}" | |
854 end | |
855 | |
856 result = complete_result.select do |s| | |
857 # First pass to only grab non-empty lines and the pre-processed lines | |
858 # only from the target header (and not the entire pre-processing result). | |
859 next if s.strip.empty? | |
860 m = %r{^#\s*\d+\s+"([^"]+)"}.match(s) | |
861 f_on = (File.basename(m[1]) == File.basename(path)) if m | |
862 f_on | |
863 end.select do |s| | |
864 # Second pass to ignore all pro-processor comments that were left. | |
865 /^#/.match(s) == nil | |
866 end.join | |
867 | |
868 File.unlink(err_file) | |
869 return [complete_result, result] | |
870 end | |
871 end | |
872 | |
873 class DStepGenerator | |
874 | |
875 VERSION = 1.0 | |
876 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
877 attr_accessor :out_file, :scaner, :code_to_inject, :dependencies_switch |
1 | 878 |
879 def initialize | |
880 @do_64bit = false | |
881 @frameworks = [] | |
882 @framework_paths = [] | |
883 @headers = [] | |
884 @import_directives = "#import <Foundation/Foundation.h>\n" | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
885 #@informal_protocols = [] |
1 | 886 @classes = [] |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
887 @protocols = [] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
888 @categories = [] |
1 | 889 @scaner = HeaderScaner.new |
890 @scaner.do_64bit = @do_64bit | |
891 @umbrella_framework = nil | |
892 @handled_dependencies = [] | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
893 @dependencies_switch = false |
1 | 894 |
895 # link to foundation framework by default | |
896 @compiler_flags = "-framework Foundation" | |
897 end | |
898 | |
899 def do_64bit | |
900 return @do_64bit | |
901 end | |
902 | |
903 def do_64bit= (do_64bit) | |
904 @do_64bit = do_64bit | |
905 @scaner.do_64bit = do_64bit | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
906 end |
1 | 907 |
908 def collect | |
909 scaner.scan(@frameworks, @headers) | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
910 @classes = scaner.get_classes |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
911 @protocols = scaner.get_protocols |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
912 @categories = scaner.get_categories |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
913 #@informal_protocols = scaner.get_informal_protocols |
1 | 914 end |
915 | |
916 def handle_framework (framework, sub_framework = false, parent_framework = nil) | |
917 val = framework.name | |
918 path = framework_path(val) | |
919 | |
920 raise "Can't locate framework '#{val}'" if path.nil? | |
921 @framework_paths << File.dirname(path) | |
922 raise "Can't find framework '#{val}'" if path.nil? | |
923 | |
924 parent_path, name = path.scan(/^(.+)\/(\w+)\.framework\/?$/)[0] | |
925 | |
926 if @private | |
927 headers_path = File.join(path, "PrivateHeaders") | |
928 raise "Can't locate private framework headers at '#{headers_path}'" unless File.exist?(headers_path) | |
929 | |
930 headers = Dir.glob(File.join(headers_path, "**", "*.h")) | |
931 public_headers_path = File.join(path, "Headers") | |
932 public_headers = if File.exist?(public_headers_path) | |
933 HeaderScaner::CPPFLAGS << " -I#{public_headers_path} " | |
934 Dir.glob(File.join8(headers_path, "**", "*.h")) | |
935 else | |
936 [] | |
937 end | |
938 else | |
939 headers_path = File.join(path, "Headers") | |
940 raise "Can't locate public framework headers at '#{headers_path}'" unless File.exist?(headers_path) | |
941 public_headers = headers = Dir.glob(File.join(headers_path, "**", "*.h")) | |
942 end | |
943 | |
944 # We can't just "#import <x/x.h>" as the main Framework header might not include _all_ headers. | |
945 # So we are tricking this by importing the main header first, then all headers. | |
946 header_basenames = (headers | public_headers).map do |x| | |
947 x.sub(/#{headers_path}\/*/, "") | |
948 end | |
949 | |
950 if idx = header_basenames.index("#{name}.h") | |
951 header_basenames.delete_at(idx) | |
952 header_basenames.unshift("#{name}.h") | |
953 end | |
954 | |
955 if sub_framework | |
956 pp = framework_path(parent_framework.name) | |
957 tmp, pname = pp.scan(/^(.+)\/(\w+)\.framework\/?$/)[0] | |
958 @import_directives << "#import <#{pname}/#{pname}.h>" | |
959 else | |
960 @import_directives << header_basenames.map do |x| | |
961 "#import <#{name}/#{x}>" | |
962 end.join("\n") | |
963 end | |
964 | |
965 @import_directives << "\n" | |
966 | |
967 @compiler_flags ||= "-F\"#{parent_path}\" -framework #{name}" | |
968 @cpp_flags ||= "" | |
969 @cpp_flags << "-F\"#{parent_path}\" " | |
970 | |
971 headers.each do |header| | |
972 header_file = HeaderFile.new | |
973 header_file.path = header | |
974 header_file.name = File.basename(header, File.extname(header)) | |
975 header_file.framework = framework.name | |
976 | |
977 framework.headers << header_file | |
978 end | |
979 | |
980 # Memorize the dependencies. | |
981 @dependencies = DStepGenerator.dependencies_of_framework(path) | |
982 | |
983 handle_sub_frameworks(framework) | |
984 end | |
985 | |
986 def handle_sub_frameworks (framework) | |
987 path = framework_path(framework.name) | |
988 frameworks_path = File.join(path, "Frameworks") | |
989 frameworks = Dir.glob(File.join(frameworks_path, "*.framework")) | |
990 | |
991 frameworks.each do |f| | |
992 add_framework(f, true, framework) | |
993 end | |
994 end | |
995 | |
996 def framework_path (val) | |
997 return val if File.exist?(val) | |
998 | |
999 val += ".framework" unless /\.framework$/.match(val) | |
1000 paths = ["/System/Library/Frameworks", "/Library/Frameworks", "#{ENV['HOME']}/Library/Frameworks"] | |
1001 paths << "/System/Library/PrivateFrameworks" if @private | |
1002 | |
1003 paths.each do |dir| | |
1004 path = File.join(dir, val) | |
1005 return path if File.exist?(path) | |
1006 end | |
1007 | |
1008 return nil | |
1009 end | |
1010 | |
1011 def umbrella_framework (val) | |
1012 | |
1013 unless val == "" || val.nil? | |
1014 @umbrella_framework = val | |
1015 | |
1016 unless @compiler_flags.nil? || @compiler_flags == "" | |
1017 i = @compiler_flags.index("-framework") | |
1018 @compiler_flags = @compiler_flags[0 .. i - 1] + "-framework #{val}" | |
1019 else | |
1020 @compiler_flags = "-framework #{val}" | |
1021 end | |
1022 end | |
1023 end | |
1024 | |
1025 def self.dependencies_of_framework (path) | |
1026 @dependencies ||= {} | |
1027 name = File.basename(path, ".framework") | |
1028 path = File.join(path, name) | |
1029 deps = @dependencies[path] | |
1030 | |
1031 if deps.nil? | |
1032 deps = `otool -L "#{path}"`.scan(/\t([^\s]+)/).map do |m| | |
1033 dpath = m[0] | |
1034 next if File.basename(dpath) == name | |
1035 next if dpath.include?("PrivateFrameworks") | |
1036 next unless dpath.sub!(/\.framework\/Versions\/\w+\/\w+$/, "") | |
1037 dpath + ".framework" | |
1038 end.compact | |
1039 | |
1040 @dependencies[path] = deps | |
1041 end | |
1042 | |
1043 return deps | |
1044 end | |
1045 | |
1046 def compile_and_execute (code, enable_64bit = false, clean_when_fail = false) | |
1047 compiler_line = "gcc " | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1048 src = File.new(unique_tmp_path("src", ".m"), "w") |
1 | 1049 src << code |
1050 src.close | |
1051 | |
1052 arch_flag = if enable_64bit | |
1053 "-arch x86_64 -arch ppc64" | |
1054 else | |
1055 "-arch i386 -arch ppc" | |
1056 end | |
1057 | |
1058 compiler_line << arch_flag | |
1059 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1060 bin = unique_tmp_path "bin", "" |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1061 log = unique_tmp_path "log", ".txt" |
1 | 1062 |
1063 line = "#{compiler_line} -o #{bin} #{src.path} #{@compiler_flags} 2>#{log}" | |
1064 | |
1065 unless system(line) | |
1066 msg = "Cannot compile Objective-C code ...aborting\nCommand was: #{line}\n\nLog:\n#{File.read(log)}\n\n" | |
1067 $stderr << msg | |
1068 File.delete src.path if clean_when_fail | |
1069 raise msg | |
1070 end | |
1071 | |
1072 result = `#{bin}` | |
1073 | |
1074 unless $?.success? | |
1075 raise "Cannot execute compiled Objective-C code ... aborting\nCommand was: #{line}\nBinary is: #{bin}" | |
1076 end | |
1077 | |
1078 File.delete bin | |
1079 File.delete log | |
1080 File.delete src.path | |
1081 | |
1082 return result | |
1083 end | |
1084 | |
1085 def unique_tmp_path (base, extension = "", dir = Dir.tmpdir) | |
1086 i = 0 | |
1087 loop do | |
1088 path = File.join(dir, "#{base}-#{Process.pid}-#{i}#{extension}") | |
1089 return path unless File.exists?(path) | |
1090 i += 1 | |
1091 end | |
1092 end | |
1093 | |
1094 def add_header (path) | |
1095 header = HeaderFile.new | |
1096 header.path = path | |
1097 header.name = File.basename(path, File.extname(path)) | |
1098 @import_directives << "#include <#{path}>\n" | |
1099 @headers << header | |
1100 end | |
1101 | |
1102 def add_framework (name, sub_framework = false, parent_framework = nil) | |
1103 framework = Framework.new | |
1104 framework.name = name | |
1105 handle_framework(framework, sub_framework, parent_framework) | |
1106 #@import_directives << "#import <#{framework.name}/#{framework.name}.h>\n" | |
1107 @frameworks << framework | |
1108 end | |
1109 | |
1110 def collect_header_types (header, enable_64bit) | |
1111 types = [] | |
1112 | |
1113 header.cftypes.each do |cftype| | |
1114 types << cftype[:type] | |
1115 end | |
1116 | |
1117 header.constants.each do |constant| | |
1118 types << constant.stripped_return_type | |
1119 end | |
1120 | |
1121 header.structs.each do |struct| | |
1122 types << struct[:name] | |
1123 | |
1124 struct[:members].each do |member| | |
1125 types << member[:declaredType] | |
1126 end | |
1127 end | |
1128 | |
1129 header.typedefs.each do |typedef| | |
1130 types << typedef.stripped_return_type | |
1131 end | |
1132 | |
1133 header.functions.each do |function| | |
1134 types << function.stripped_return_type | |
1135 | |
1136 function.args.each do |arg| | |
1137 types << arg.stripped_return_type | |
1138 end | |
1139 end | |
1140 | |
1141 types | |
1142 end | |
1143 | |
1144 def collect_classes_types (enable_64bit) | |
1145 types = [] | |
1146 | |
1147 @classes.each do |clazz, value| | |
1148 value.methods.each do |method| | |
1149 types << method.stripped_return_type | |
1150 | |
1151 method.args.each do |arg| | |
1152 types << arg.stripped_return_type | |
1153 end | |
1154 end | |
1155 end | |
1156 | |
1157 types | |
1158 end | |
1159 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1160 def collect_protocols_types (enable_64bit) |
1 | 1161 types = [] |
1162 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1163 @protocols.each do |protocol, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1164 value.methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1165 types << method.stripped_return_type |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1166 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1167 method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1168 types << arg.stripped_return_type |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1169 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1170 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1171 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1172 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1173 types |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1174 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1175 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1176 # def collect_informal_protocols_types (enable_64bit) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1177 # types = [] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1178 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1179 # @informal_protocols.each do |name, methods| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1180 # methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1181 # types << method.stripped_return_type |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1182 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1183 # method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1184 # types << arg.stripped_return_type |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1185 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1186 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1187 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1188 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1189 # types |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1190 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1191 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1192 def collect_categories_types (enable_64bit) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1193 types = [] |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1194 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1195 @categories.each do |category, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1196 value.methods.each do |method| |
1 | 1197 types << method.stripped_return_type |
1198 | |
1199 method.args.each do |arg| | |
1200 types << arg.stripped_return_type | |
1201 end | |
1202 end | |
1203 end | |
1204 | |
1205 types | |
1206 end | |
1207 | |
1208 def resolve_header_types (header, enable_64bit, resolved_types, x) | |
1209 i = x | |
1210 | |
1211 header.cftypes.each do |cftype| | |
1212 cftype[enable_64bit ? :type64 : :type] = resolved_types[i] | |
1213 i += 1 | |
1214 end | |
1215 | |
1216 header.constants.each do |constant| | |
1217 constant.resolved_type = resolved_types[i] unless enable_64bit | |
1218 constant.resolved_type64 = resolved_types[i] if enable_64bit | |
1219 i += 1 | |
1220 end | |
1221 | |
1222 header.structs.each do |struct| | |
1223 struct[enable_64bit ? :type64 : :type] = resolved_types[i] | |
1224 i += 1 | |
1225 | |
1226 struct[:members].each do |member| | |
1227 member[enable_64bit ? :type64 : :type] = resolved_types[i] | |
1228 i += 1 | |
1229 end | |
1230 end | |
1231 | |
1232 header.typedefs.each do |typedef| | |
1233 typedef.resolved_type = resolved_types[i] unless enable_64bit | |
1234 typedef.resolved_type64 = resolved_types[i] if enable_64bit | |
1235 i += 1 | |
1236 end | |
1237 | |
1238 header.functions.each do |function| | |
1239 function.resolved_type = resolved_types[i] unless enable_64bit | |
1240 function.resolved_type64 = resolved_types[i] if enable_64bit | |
1241 i += 1 | |
1242 | |
1243 function.args.each do |arg| | |
1244 arg.resolved_type = resolved_types[i] unless enable_64bit | |
1245 arg.resolved_type64 = resolved_types[i] if enable_64bit | |
1246 i += 1 | |
1247 end | |
1248 end | |
1249 | |
1250 i | |
1251 end | |
1252 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1253 def resolve_classes_types (enable_64bit, resolved_types, x) |
1 | 1254 i = x |
1255 | |
1256 @classes.each do |clazz, value| | |
1257 value.methods.each do |method| | |
1258 method.resolved_type = resolved_types[i] unless enable_64bit | |
1259 method.resolved_type64 = resolved_types[i] if enable_64bit | |
1260 i += 1 | |
1261 | |
1262 method.args.each do |arg| | |
1263 arg.resolved_type = resolved_types[i] unless enable_64bit | |
1264 arg.resolved_type64 = resolved_types[i] if enable_64bit | |
1265 i += 1 | |
1266 end | |
1267 end | |
1268 end | |
1269 | |
1270 i | |
1271 end | |
1272 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1273 def resolve_protocols_types (enable_64bit, resolved_types, x) |
1 | 1274 i = x |
1275 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1276 @protocols.each do |protocol, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1277 value.methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1278 method.resolved_type = resolved_types[i] unless enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1279 method.resolved_type64 = resolved_types[i] if enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1280 i += 1 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1281 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1282 method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1283 arg.resolved_type = resolved_types[i] unless enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1284 arg.resolved_type64 = resolved_types[i] if enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1285 i += 1 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1286 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1287 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1288 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1289 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1290 i |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1291 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1292 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1293 # def resolve_informal_protocols_types (enable_64bit, resolved_types, x) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1294 # i = x |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1295 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1296 # @informal_protocols.each do |name, methods| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1297 # methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1298 # method.resolved_type = resolved_types[i] unless enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1299 # method.resolved_type64 = resolved_types[i] if enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1300 # i += 1 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1301 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1302 # method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1303 # arg.resolved_type = resolved_types[i] unless enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1304 # arg.resolved_type64 = resolved_types[i] if enable_64bit |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1305 # i += 1 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1306 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1307 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1308 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1309 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1310 # i |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1311 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1312 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1313 def resolve_categories_types (enable_64bit, resolved_types, x) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1314 i = x |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1315 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1316 @categories.each do |category, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1317 value.methods.each do |method| |
1 | 1318 method.resolved_type = resolved_types[i] unless enable_64bit |
1319 method.resolved_type64 = resolved_types[i] if enable_64bit | |
1320 i += 1 | |
1321 | |
1322 method.args.each do |arg| | |
1323 arg.resolved_type = resolved_types[i] unless enable_64bit | |
1324 arg.resolved_type64 = resolved_types[i] if enable_64bit | |
1325 i += 1 | |
1326 end | |
1327 end | |
1328 end | |
1329 | |
1330 i | |
1331 end | |
1332 | |
1333 def resolve_types (enable_64bit = false) | |
1334 code = "#include <stdio.h>\n" | |
1335 code << "#import <objc/objc-class.h>\n" | |
1336 | |
1337 # @dependencies.each do |f| | |
1338 # # get the framework name | |
1339 # i = f.index('.') | |
1340 # str = f[0 ... i] | |
1341 # i = str.rindex('/') | |
1342 # str = str[i + 1 .. -1] | |
1343 # | |
1344 # code << "#import <#{str}/#{str}.h>\n" | |
1345 # end | |
1346 | |
1347 code << @import_directives | |
1348 types = [] | |
1349 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1350 code << @code_to_inject + "\n" unless @code_to_inject.nil? |
1 | 1351 |
1352 @frameworks.each do |framework| | |
1353 framework.headers.each do |header| | |
1354 | |
1355 header.imports do |import| | |
1356 code << "#import <#{import}.h>\n" | |
1357 end | |
1358 | |
1359 types << collect_header_types(header, enable_64bit) | |
1360 end | |
1361 end | |
1362 | |
1363 @headers.each do |header| | |
1364 types << collect_header_types(header, enable_64bit) | |
1365 end | |
1366 | |
1367 types << collect_classes_types(enable_64bit) | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1368 types << collect_protocols_types(enable_64bit) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1369 #types << collect_informal_protocols_types(enable_64bit) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1370 types << collect_categories_types(enable_64bit) |
1 | 1371 |
1372 code << "int main ()\n{\n" | |
1373 types.flatten! | |
1374 | |
1375 types.each do |type| | |
1376 code << ' printf("%s\n", ' + "@encode(#{type}));\n" | |
1377 end | |
1378 | |
1379 code << " return 0;\n}" | |
1380 | |
1381 resolved_types = [] | |
1382 | |
1383 compile_and_execute(code, enable_64bit).split("\n").each do |line| | |
1384 resolved_types << line | |
1385 end | |
1386 | |
1387 i = 0 | |
1388 | |
1389 @frameworks.each do |framework| | |
1390 framework.headers.each do |header| | |
1391 i = resolve_header_types(header, enable_64bit, resolved_types, i) | |
1392 end | |
1393 end | |
1394 | |
1395 @headers.each do |header| | |
1396 i = resolve_header_types(header, enable_64bit, resolved_types, i) | |
1397 end | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1398 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1399 i = resolve_classes_types(enable_64bit, resolved_types, i) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1400 i = resolve_protocols_types(enable_64bit, resolved_types, i) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1401 #i = resolve_informal_protocols_types(enable_64bit, resolved_types, i) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1402 i = resolve_categories_types(enable_64bit, resolved_types, i) |
1 | 1403 end |
1404 | |
1405 def generate_header (xml, header) | |
1406 xml.file :name => header.name do | |
1407 header.imports.each do |import| | |
1408 xml.import import | |
1409 end | |
1410 | |
1411 header.defines.each do |define| | |
1412 xml.define define | |
1413 end | |
1414 | |
1415 header.cftypes.each do |cftype| | |
1416 xml.cftype cftype | |
1417 end | |
1418 | |
1419 header.constants.each do |constant| | |
1420 xml.constant :name => constant.name, :declaredType => constant.return_type, :type => constant.resolved_type, :type64 => constant.resolved_type64, :const => constant.const | |
1421 end | |
1422 | |
1423 header.enums.each do |enum| | |
1424 xml.enum :name => enum[:name] do | |
1425 enum[:members].each do |member| | |
1426 xml.member member | |
1427 end | |
1428 end | |
1429 end | |
1430 | |
1431 header.structs.each do |struct| | |
1432 xml.struct :name => struct[:name], :type => struct[:type], :type64 => struct[:type64] do | |
1433 struct[:members].each do |member| | |
1434 xml.member member | |
1435 end | |
1436 end | |
1437 end | |
1438 | |
1439 header.typedefs.each do |typedef| | |
1440 xml.typedef :name => typedef.name, :declaredType => typedef.return_type, :type => typedef.resolved_type, :type64 => typedef.resolved_type64, :const => typedef.const | |
1441 end | |
1442 | |
1443 header.functions.each do |function| | |
1444 xml.function :name => function.name, :inline => function.inline?, :variadic => function.variadic? do | |
1445 function.args.each do |arg| | |
1446 xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier | |
1447 end | |
1448 | |
1449 xml.returnValue :declaredType => function.return_type, :type => function.resolved_type, :type64 => function.resolved_type64, :const => function.const, :typeModifier => function.type_modifier | |
1450 end | |
1451 end | |
1452 end | |
1453 end | |
1454 | |
1455 def generate_classes (xml) | |
1456 @classes.each do |clazz, value| | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1457 xml.class :name => clazz, :parent => value.parent, :protocols => value.protocols, :file => value.file do |
1 | 1458 value.methods.each do |method| |
1459 xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do | |
1460 method.args.each do |arg| | |
1461 xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier | |
1462 end | |
1463 | |
1464 xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier | |
1465 end | |
1466 end | |
1467 end | |
1468 end | |
1469 end | |
1470 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1471 def generate_protocols (xml) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1472 @protocols.each do |protocol, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1473 xml.protocol :name => protocol, :parent => value.parent, :protocols => value.protocols, :file => value.file do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1474 value.methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1475 xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1476 method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1477 xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1478 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1479 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1480 xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1481 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1482 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1483 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1484 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1485 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1486 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1487 # def generate_informal_protocols (xml) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1488 # @informal_protocols.each do |name, methods| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1489 # xml.informalProtocol :name => name do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1490 # methods.each do |method| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1491 # xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1492 # method.args.each do |arg| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1493 # xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1494 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1495 # |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1496 # xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1497 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1498 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1499 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1500 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1501 # end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1502 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1503 def generate_categories (xml) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1504 @categories.each do |category, value| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1505 xml.category :name => category.name, :class => category.class, :parent => value.parent, :protocols => value.protocols, :file => value.file do |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1506 value.methods.each do |method| |
1 | 1507 xml.method :selector => method.selector, :classMethod => method.class_method?, :variadic => method.variadic? do |
1508 method.args.each do |arg| | |
1509 xml.arg :name => arg.name, :declaredType => arg.return_type, :type => arg.resolved_type, :type64 => arg.resolved_type64, :const => arg.const, :typeModifier => arg.type_modifier | |
1510 end | |
1511 | |
1512 xml.returnValue :declaredType => method.return_type, :type => method.resolved_type, :type64 => method.resolved_type64, :const => method.const, :typeModifier => method.type_modifier | |
1513 end | |
1514 end | |
1515 end | |
1516 end | |
1517 end | |
1518 | |
1519 def generate | |
1520 resolve_types | |
1521 resolve_types(true) if @do_64bit | |
1522 | |
1523 file = STDOUT if @out_file == nil | |
1524 file = File.open @out_file, "w" unless @out_file == nil | |
1525 | |
1526 xml = XmlMarkup.new(:target => file, :indent => 4) | |
1527 xml.instruct! | |
1528 | |
1529 xml.dstep :xmlns => "http://www.dsource.org/projects/dstep", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => "http://www.dsource.org/projects/dstep/trunk/scripts/dstep.xsd" do | |
1530 @frameworks.each do |framework| | |
1531 xml.framework :name => framework.name do | |
1532 framework.headers.each do |header| | |
1533 generate_header(xml, header) | |
1534 end | |
1535 end | |
1536 end | |
1537 | |
1538 @headers.each do |header| | |
1539 generate_header(xml, header) | |
1540 end | |
1541 | |
1542 generate_classes(xml) | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1543 generate_protocols(xml) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1544 #generate_informal_protocols(xml) |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1545 generate_categories(xml) |
1 | 1546 end |
1547 | |
1548 file.close unless file == STDOUT | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1549 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1550 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1551 def write_dependencies |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1552 file = STDOUT if @out_file == nil |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1553 file = File.open @out_file, "w" unless @out_file == nil |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1554 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1555 @dependencies.each do |dep| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1556 file << dep + "\n" |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1557 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1558 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1559 file.close unless file == STDOUT |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1560 |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1561 exit 0 |
1 | 1562 end |
1563 end | |
1564 | |
1565 def die (*msg) | |
1566 $stderr.puts msg | |
1567 exit 1 | |
1568 end | |
1569 | |
1570 if __FILE__ == $0 | |
1571 dstep_gen = DStepGenerator.new | |
1572 | |
1573 OptionParser.new do |opts| | |
1574 opts.banner = "Usage: #{File.basename(__FILE__)} [options] <headers...>" | |
1575 opts.separator "" | |
1576 opts.separator "Options:" | |
1577 | |
1578 opts.on("-f", "--framework FRAMEWORK", "Generate metadata for the given framework.") do |opt| | |
1579 dstep_gen.add_framework(opt) | |
1580 end | |
1581 | |
1582 opts.on("-u", "--umbrella FRAMEWORK", "Link againts the given umbrella framework.") do |opt| | |
1583 dstep_gen.umbrella_framework(opt) | |
1584 end | |
1585 | |
1586 opts.on(nil, "--64-bit", "Write 64-bit annotations.") do | |
1587 dstep_gen.do_64bit = true | |
1588 end | |
1589 | |
1590 opts.on("-o", "--output FILE", "Write output to the given file.") do |opt| | |
1591 die "Output file can't be specified more than once" if dstep_gen.out_file | |
1592 dstep_gen.out_file = opt | |
1593 end | |
1594 | |
1595 # opts.on("-d", "--output-dir PATH", "Write ouptut to the given paht, use this with the --framework option") do |opt| | |
1596 # die "Output directory can't be specified more than once" if dstep_gen.out_dir | |
1597 # dstep_gen.out_dir = opt | |
1598 # end | |
1599 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1600 opts.on("-c", "--code CODE", "Add code") do |opt| |
1 | 1601 dstep_gen.code_to_inject = opt |
1602 end | |
1603 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1604 opts.on("-d", "--dependencies", "Write framework dependencies and exit") do |opt| |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1605 dstep_gen.dependencies_switch = true |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1606 end |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1607 |
1 | 1608 help_msg = "Use the `-h' flag or for help." |
1609 | |
1610 opts.on("-h", "--help", "Show this message.") do | |
1611 puts opts, help_msg | |
1612 exit | |
1613 end | |
1614 | |
1615 opts.on('-v', '--version', 'Show version.') do | |
1616 puts DStepGenerator::VERSION | |
1617 exit | |
1618 end | |
1619 | |
1620 opts.separator "" | |
1621 | |
1622 if ARGV.empty? | |
1623 die opts.banner | |
1624 else | |
1625 #begin | |
1626 opts.parse!(ARGV) | |
1627 | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1628 dstep_gen.write_dependencies if dstep_gen.dependencies_switch |
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1629 |
1 | 1630 ARGV.each do |header| |
1631 dstep_gen.add_header(header) | |
1632 end | |
1633 | |
1634 dstep_gen.collect | |
1635 dstep_gen.generate | |
1636 # rescue => e | |
1637 # msg = e.message | |
1638 # msg = "Internal error" if msg.empty? | |
1639 # | |
1640 # die msg, opts.banner, help_msg | |
1641 # end | |
1642 end | |
1643 end | |
2
9fd439a28ce3
Adapted the scripts for the new bridge + a lot more
Jacob Carlborg <doob@me.com>
parents:
1
diff
changeset
|
1644 end |