Change soft-fail to use the config, rather than env
[rbx.git] / stdlib / ext / win32ole / sample / olegen.rb
blob3946ffcb8c0c38772bbe7d6b3986535648b5d72c
1 #-----------------------------
2 # olegen.rb
3 # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
4 # $Revision: 11708 $
5 #-----------------------------
7 require 'win32ole'
9 class WIN32COMGen
10   def initialize(typelib)
11     @typelib = typelib
12     @reciever = ""
13   end
14   attr_reader :typelib
16   def ole_classes(typelib)
17     begin
18       @ole = WIN32OLE.new(typelib)
19       [@ole.ole_obj_help]
20     rescue
21       WIN32OLE_TYPE.ole_classes(typelib)
22     end
23   end
25   def generate_args(method)
26     args = []
27     if method.size_opt_params >= 0
28       size_required_params = method.size_params - method.size_opt_params
29     else
30       size_required_params = method.size_params - 1
31     end
32     size_required_params.times do |i|
33       if method.params[i] && method.params[i].optional?
34         args.push "arg#{i}=nil"
35       else
36         args.push "arg#{i}"
37       end
38     end
39     if method.size_opt_params >= 0
40       method.size_opt_params.times do |i|
41         args.push "arg#{i + size_required_params}=nil"
42       end
43     else
44       args.push "*arg"
45     end
46     args.join(", ")
47   end
49   def generate_argtype(typedetails)
50     ts = ''
51     typedetails.each do |t|
52       case t
53       when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8' 
54 #         raise "Sorry type\"" + t + "\" not supported"
55       ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
56       when 'USERDEFINED', 'Unknown Type 9'
57         ts << 'VT_DISPATCH'
58         break;
59       when 'SAFEARRAY'
60         ts << 'VT_ARRAY|'
61       when 'PTR'
62         ts << 'VT_BYREF|'
63       when 'INT'
64         ts << 'VT_I4'
65       else
66         if String === t
67           ts << 'VT_' + t
68         end
69       end
70     end
71     if ts.empty?
72       ts = 'VT_VARIANT'
73     elsif ts[-1] == ?|
74         ts += 'VT_VARIANT'
75     end
76     ts
77   end
79   def generate_argtypes(method, proptypes)
80     types = method.params.collect{|param|
81       generate_argtype(param.ole_type_detail)
82     }.join(", ")
83     if proptypes
84       types += ", " if types.size > 0 
85       types += generate_argtype(proptypes)
86     end
87     types
88   end
90   def generate_method_body(method, disptype, types=nil)
91     "    ret = #{@reciever}#{disptype}(#{method.dispid}, [" +
92     generate_args(method).gsub("=nil", "") +
93     "], [" +
94     generate_argtypes(method, types) +
95     "])\n" +
96     "    @lastargs = WIN32OLE::ARGV\n" +
97     "    ret"
98   end
100   def generate_method_help(method, type = nil)
101     str = "  # "  
102     if type 
103       str += type
104     else
105       str += method.return_type
106     end
107     str += " #{method.name}"
108     if method.event?
109       str += " EVENT"
110       str += " in #{method.event_interface}"
111     end
112     if method.helpstring && method.helpstring != ""
113       str += "\n  # "
114       str += method.helpstring
115     end
116     args_help = generate_method_args_help(method)
117     if args_help
118       str += "\n"
119       str += args_help
120     end
121     str
122   end
124   def generate_method_args_help(method)
125     args = []
126     method.params.each_with_index {|param, i|
127       h = "  #   #{param.ole_type} arg#{i} --- #{param.name}" 
128       inout = []
129       inout.push "IN" if param.input?
130       inout.push "OUT" if param.output?
131       h += " [#{inout.join('/')}]"
132       h += " ( = #{param.default})" if param.default
133       args.push h
134     }
135     if args.size > 0
136       args.join("\n")
137     else
138       nil
139     end
140   end
142   def generate_method(method, disptype, io = STDOUT, types = nil)
143     io.puts "\n"
144     io.puts  generate_method_help(method)
145     if method.invoke_kind == 'PROPERTYPUT'
146       io.print "  def #{method.name}=("
147     else
148       io.print "  def #{method.name}("
149     end
150     io.print generate_args(method)
151     io.puts ")"
152     io.puts generate_method_body(method, disptype, types)
153     io.puts "  end"
154   end
156   def generate_propputref_methods(klass, io = STDOUT)
157     klass.ole_methods.select {|method|
158       method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
159     }.each do |method|
160       generate_method(method, io)
161     end
162   end
164   def generate_properties_with_args(klass, io = STDOUT)
165     klass.ole_methods.select {|method|
166       method.invoke_kind == 'PROPERTYGET' &&
167       method.visible? &&
168       method.size_params > 0
169     }.each do |method|
170       types = method.return_type_detail 
171       io.puts "\n"
172       io.puts  generate_method_help(method, types[0])
173       io.puts  "  def #{method.name}"
174       if klass.ole_type == "Class"
175         io.print "    OLEProperty.new(@dispatch, #{method.dispid}, [" 
176       else
177         io.print "    OLEProperty.new(self, #{method.dispid}, [" 
178       end
179       io.print generate_argtypes(method, nil)
180       io.print "], ["
181       io.print generate_argtypes(method, types)
182       io.puts "])"
183       io.puts  "  end"
184     end
185   end
187   def generate_propput_methods(klass, io = STDOUT)
188     klass.ole_methods.select {|method|
189       method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
190       method.size_params == 1
191     }.each do |method|
192       ms = klass.ole_methods.select {|m|
193         m.invoke_kind == 'PROPERTYGET' &&
194         m.dispid == method.dispid
195       }
196       types = []
197       if ms.size == 1
198         types = ms[0].return_type_detail
199       end
200       generate_method(method, '_setproperty', io, types)
201     end
202   end
204   def generate_propget_methods(klass, io = STDOUT)
205     klass.ole_methods.select {|method|
206       method.invoke_kind == 'PROPERTYGET' && method.visible? &&
207       method.size_params == 0
208     }.each do |method|
209       generate_method(method, '_getproperty', io)
210     end
211   end
213   def generate_func_methods(klass, io = STDOUT)
214     klass.ole_methods.select {|method|
215       method.invoke_kind == "FUNC" && method.visible?
216     }.each do |method|
217       generate_method(method, '_invoke', io)
218     end
219   end
221   def generate_methods(klass, io = STDOUT)
222     generate_propget_methods(klass, io)
223     generate_propput_methods(klass, io)
224     generate_properties_with_args(klass, io)
225     generate_func_methods(klass, io)
226 #   generate_propputref_methods(klass, io)
227   end
229   def generate_constants(klass, io = STDOUT)
230     klass.variables.select {|v|
231       v.visible? && v.variable_kind == 'CONSTANT'
232     }.each do |v|
233       io.print "  "
234       io.print v.name.sub(/^./){|c| c.upcase}
235       io.print " = "
236       io.puts  v.value
237     end
238   end
240   def class_name(klass)
241     klass_name = klass.name
242     if klass.ole_type == "Class" &&
243        klass.guid &&
244        klass.progid
245        klass_name = klass.progid.gsub(/\./, '_')
246     end
247     if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
248       klass_name = 'OLE' + klass_name
249     end
250     klass_name
251   end
253   def define_initialize(klass)
254     <<STR
256   def initialize(obj = nil)
257     @clsid = "#{klass.guid}"
258     @progid = "#{klass.progid}"
259     if obj.nil?
260       @dispatch = WIN32OLE.new @progid
261     else
262       @dispatch = obj
263     end
264   end
266   end
268   def define_include
269     "  include WIN32OLE::VARIANT"
270   end
272   def define_instance_variables
273     "  attr_reader :lastargs"
274   end
276   def define_method_missing
277     <<STR
279   def method_missing(cmd, *arg)
280     @dispatch.method_missing(cmd, *arg)
281   end
283   end
285   def define_class(klass, io = STDOUT)
286     io.puts "class #{class_name(klass)} # #{klass.name}"
287     io.puts define_include
288     io.puts define_instance_variables
289     io.puts "  attr_reader :dispatch"
290     io.puts "  attr_reader :clsid"
291     io.puts "  attr_reader :progid"
292     io.puts define_initialize(klass)
293     io.puts define_method_missing
294   end
296   def define_module(klass, io = STDOUT)
297     io.puts "module #{class_name(klass)}"
298     io.puts define_include
299     io.puts define_instance_variables
300   end
302   def generate_class(klass, io = STDOUT)
303     io.puts "\n# #{klass.helpstring}"
304     if klass.ole_type == "Class" &&
305        klass.guid &&
306        klass.progid
307       @reciever = "@dispatch."
308       define_class(klass, io)
309     else
310       @reciever = ""
311       define_module(klass, io)
312     end
313     generate_constants(klass, io)
314     generate_methods(klass, io)
315     io.puts "end"
316   end
318   def generate(io = STDOUT)
319     io.puts "require 'win32ole'"
320     io.puts "require 'win32ole/property'"
322     ole_classes(typelib).select{|klass|
323       klass.visible? &&
324       (klass.ole_type == "Class" || 
325        klass.ole_type == "Interface" || 
326        klass.ole_type == "Dispatch" ||
327        klass.ole_type == "Enum")
328     }.each do |klass|
329       generate_class(klass, io)
330     end
331     begin
332       @ole.quit if @ole
333     rescue 
334     end
335   end
338 require 'win32ole'
339 if __FILE__ == $0
340   if ARGV.size == 0
341     $stderr.puts "usage: #{$0} Type Library [...]"
342     exit 1
343   end
344   ARGV.each do |typelib|
345     comgen = WIN32COMGen.new(typelib)
346     comgen.generate
347   end