mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	g -L frozen_string_literal ext/**/*.rb|xargs ruby -Ka -e'ARGV.each{|fn|puts
fn;open(fn,"r+"){|f|s=f.read.sub(/\A(#!.*\n)?(#.*coding.*\n)?/,"\\&#
frozen_string_literal: false\n");f.rewind;f.write s}}'
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53143 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
	
			
		
			
				
	
	
		
			348 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			348 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: false
 | 
						|
#-----------------------------
 | 
						|
# olegen.rb
 | 
						|
# $Revision$
 | 
						|
#-----------------------------
 | 
						|
 | 
						|
require 'win32ole'
 | 
						|
 | 
						|
class WIN32COMGen
 | 
						|
  def initialize(typelib)
 | 
						|
    @typelib = typelib
 | 
						|
    @receiver = ""
 | 
						|
  end
 | 
						|
  attr_reader :typelib
 | 
						|
 | 
						|
  def ole_classes(typelib)
 | 
						|
    begin
 | 
						|
      @ole = WIN32OLE.new(typelib)
 | 
						|
      [@ole.ole_obj_help]
 | 
						|
    rescue
 | 
						|
      WIN32OLE_TYPE.ole_classes(typelib)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_args(method)
 | 
						|
    args = []
 | 
						|
    if method.size_opt_params >= 0
 | 
						|
      size_required_params = method.size_params - method.size_opt_params
 | 
						|
    else
 | 
						|
      size_required_params = method.size_params - 1
 | 
						|
    end
 | 
						|
    size_required_params.times do |i|
 | 
						|
      if method.params[i] && method.params[i].optional?
 | 
						|
        args.push "arg#{i}=nil"
 | 
						|
      else
 | 
						|
        args.push "arg#{i}"
 | 
						|
      end
 | 
						|
    end
 | 
						|
    if method.size_opt_params >= 0
 | 
						|
      method.size_opt_params.times do |i|
 | 
						|
        args.push "arg#{i + size_required_params}=nil"
 | 
						|
      end
 | 
						|
    else
 | 
						|
      args.push "*arg"
 | 
						|
    end
 | 
						|
    args.join(", ")
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_argtype(typedetails)
 | 
						|
    ts = ''
 | 
						|
    typedetails.each do |t|
 | 
						|
      case t
 | 
						|
      when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8'
 | 
						|
#	  raise "Sorry type\"" + t + "\" not supported"
 | 
						|
      ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
 | 
						|
      when 'USERDEFINED', 'Unknown Type 9'
 | 
						|
        ts << 'VT_DISPATCH'
 | 
						|
        break;
 | 
						|
      when 'SAFEARRAY'
 | 
						|
        ts << 'VT_ARRAY|'
 | 
						|
      when 'PTR'
 | 
						|
        ts << 'VT_BYREF|'
 | 
						|
      when 'INT'
 | 
						|
        ts << 'VT_I4'
 | 
						|
      else
 | 
						|
        if String === t
 | 
						|
          ts << 'VT_' + t
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
    if ts.empty?
 | 
						|
      ts = 'VT_VARIANT'
 | 
						|
    elsif ts[-1] == ?|
 | 
						|
	ts += 'VT_VARIANT'
 | 
						|
    end
 | 
						|
    ts
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_argtypes(method, proptypes)
 | 
						|
    types = method.params.collect{|param|
 | 
						|
      generate_argtype(param.ole_type_detail)
 | 
						|
    }.join(", ")
 | 
						|
    if proptypes
 | 
						|
      types += ", " if types.size > 0
 | 
						|
      types += generate_argtype(proptypes)
 | 
						|
    end
 | 
						|
    types
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_method_body(method, disptype, types=nil)
 | 
						|
    "    ret = #{@receiver}#{disptype}(#{method.dispid}, [" +
 | 
						|
    generate_args(method).gsub("=nil", "") +
 | 
						|
    "], [" +
 | 
						|
    generate_argtypes(method, types) +
 | 
						|
    "])\n" +
 | 
						|
    "    @lastargs = WIN32OLE::ARGV\n" +
 | 
						|
    "    ret"
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_method_help(method, type = nil)
 | 
						|
    str = "  # "
 | 
						|
    if type
 | 
						|
      str += type
 | 
						|
    else
 | 
						|
      str += method.return_type
 | 
						|
    end
 | 
						|
    str += " #{method.name}"
 | 
						|
    if method.event?
 | 
						|
      str += " EVENT"
 | 
						|
      str += " in #{method.event_interface}"
 | 
						|
    end
 | 
						|
    if method.helpstring && method.helpstring != ""
 | 
						|
      str += "\n  # "
 | 
						|
      str += method.helpstring
 | 
						|
    end
 | 
						|
    args_help = generate_method_args_help(method)
 | 
						|
    if args_help
 | 
						|
      str += "\n"
 | 
						|
      str += args_help
 | 
						|
    end
 | 
						|
    str
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_method_args_help(method)
 | 
						|
    args = []
 | 
						|
    method.params.each_with_index {|param, i|
 | 
						|
      h = "  #   #{param.ole_type} arg#{i} --- #{param.name}"
 | 
						|
      inout = []
 | 
						|
      inout.push "IN" if param.input?
 | 
						|
      inout.push "OUT" if param.output?
 | 
						|
      h += " [#{inout.join('/')}]"
 | 
						|
      h += " ( = #{param.default})" if param.default
 | 
						|
      args.push h
 | 
						|
    }
 | 
						|
    if args.size > 0
 | 
						|
      args.join("\n")
 | 
						|
    else
 | 
						|
      nil
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_method(method, disptype, io = STDOUT, types = nil)
 | 
						|
    io.puts "\n"
 | 
						|
    io.puts  generate_method_help(method)
 | 
						|
    if method.invoke_kind == 'PROPERTYPUT'
 | 
						|
      io.print "  def #{method.name}=("
 | 
						|
    else
 | 
						|
      io.print "  def #{method.name}("
 | 
						|
    end
 | 
						|
    io.print generate_args(method)
 | 
						|
    io.puts ")"
 | 
						|
    io.puts generate_method_body(method, disptype, types)
 | 
						|
    io.puts "  end"
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_propputref_methods(klass, io = STDOUT)
 | 
						|
    klass.ole_methods.select {|method|
 | 
						|
      method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
 | 
						|
    }.each do |method|
 | 
						|
      generate_method(method, io)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_properties_with_args(klass, io = STDOUT)
 | 
						|
    klass.ole_methods.select {|method|
 | 
						|
      method.invoke_kind == 'PROPERTYGET' &&
 | 
						|
      method.visible? &&
 | 
						|
      method.size_params > 0
 | 
						|
    }.each do |method|
 | 
						|
      types = method.return_type_detail
 | 
						|
      io.puts "\n"
 | 
						|
      io.puts  generate_method_help(method, types[0])
 | 
						|
      io.puts  "  def #{method.name}"
 | 
						|
      if klass.ole_type == "Class"
 | 
						|
        io.print "    OLEProperty.new(@dispatch, #{method.dispid}, ["
 | 
						|
      else
 | 
						|
        io.print "    OLEProperty.new(self, #{method.dispid}, ["
 | 
						|
      end
 | 
						|
      io.print generate_argtypes(method, nil)
 | 
						|
      io.print "], ["
 | 
						|
      io.print generate_argtypes(method, types)
 | 
						|
      io.puts "])"
 | 
						|
      io.puts  "  end"
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_propput_methods(klass, io = STDOUT)
 | 
						|
    klass.ole_methods.select {|method|
 | 
						|
      method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
 | 
						|
      method.size_params == 1
 | 
						|
    }.each do |method|
 | 
						|
      ms = klass.ole_methods.select {|m|
 | 
						|
        m.invoke_kind == 'PROPERTYGET' &&
 | 
						|
        m.dispid == method.dispid
 | 
						|
      }
 | 
						|
      types = []
 | 
						|
      if ms.size == 1
 | 
						|
        types = ms[0].return_type_detail
 | 
						|
      end
 | 
						|
      generate_method(method, '_setproperty', io, types)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_propget_methods(klass, io = STDOUT)
 | 
						|
    klass.ole_methods.select {|method|
 | 
						|
      method.invoke_kind == 'PROPERTYGET' && method.visible? &&
 | 
						|
      method.size_params == 0
 | 
						|
    }.each do |method|
 | 
						|
      generate_method(method, '_getproperty', io)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_func_methods(klass, io = STDOUT)
 | 
						|
    klass.ole_methods.select {|method|
 | 
						|
      method.invoke_kind == "FUNC" && method.visible?
 | 
						|
    }.each do |method|
 | 
						|
      generate_method(method, '_invoke', io)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_methods(klass, io = STDOUT)
 | 
						|
    generate_propget_methods(klass, io)
 | 
						|
    generate_propput_methods(klass, io)
 | 
						|
    generate_properties_with_args(klass, io)
 | 
						|
    generate_func_methods(klass, io)
 | 
						|
#   generate_propputref_methods(klass, io)
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_constants(klass, io = STDOUT)
 | 
						|
    klass.variables.select {|v|
 | 
						|
      v.visible? && v.variable_kind == 'CONSTANT'
 | 
						|
    }.each do |v|
 | 
						|
      io.print "  "
 | 
						|
      io.print v.name.sub(/^./){$&.upcase}
 | 
						|
      io.print " = "
 | 
						|
      io.puts  v.value
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def class_name(klass)
 | 
						|
    klass_name = klass.name
 | 
						|
    if klass.ole_type == "Class" &&
 | 
						|
       klass.guid &&
 | 
						|
       klass.progid
 | 
						|
       klass_name = klass.progid.gsub(/\./, '_')
 | 
						|
    end
 | 
						|
    if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
 | 
						|
      klass_name = 'OLE' + klass_name
 | 
						|
    end
 | 
						|
    klass_name
 | 
						|
  end
 | 
						|
 | 
						|
  def define_initialize(klass)
 | 
						|
    <<STR
 | 
						|
 | 
						|
  def initialize(obj = nil)
 | 
						|
    @clsid = "#{klass.guid}"
 | 
						|
    @progid = "#{klass.progid}"
 | 
						|
    if obj.nil?
 | 
						|
      @dispatch = WIN32OLE.new @progid
 | 
						|
    else
 | 
						|
      @dispatch = obj
 | 
						|
    end
 | 
						|
  end
 | 
						|
STR
 | 
						|
  end
 | 
						|
 | 
						|
  def define_include
 | 
						|
    "  include WIN32OLE::VARIANT"
 | 
						|
  end
 | 
						|
 | 
						|
  def define_instance_variables
 | 
						|
    "  attr_reader :lastargs"
 | 
						|
  end
 | 
						|
 | 
						|
  def define_method_missing
 | 
						|
    <<STR
 | 
						|
 | 
						|
  def method_missing(cmd, *arg)
 | 
						|
    @dispatch.method_missing(cmd, *arg)
 | 
						|
  end
 | 
						|
STR
 | 
						|
  end
 | 
						|
 | 
						|
  def define_class(klass, io = STDOUT)
 | 
						|
    io.puts "class #{class_name(klass)} # #{klass.name}"
 | 
						|
    io.puts define_include
 | 
						|
    io.puts define_instance_variables
 | 
						|
    io.puts "  attr_reader :dispatch"
 | 
						|
    io.puts "  attr_reader :clsid"
 | 
						|
    io.puts "  attr_reader :progid"
 | 
						|
    io.puts define_initialize(klass)
 | 
						|
    io.puts define_method_missing
 | 
						|
  end
 | 
						|
 | 
						|
  def define_module(klass, io = STDOUT)
 | 
						|
    io.puts "module #{class_name(klass)}"
 | 
						|
    io.puts define_include
 | 
						|
    io.puts define_instance_variables
 | 
						|
  end
 | 
						|
 | 
						|
  def generate_class(klass, io = STDOUT)
 | 
						|
    io.puts "\n# #{klass.helpstring}"
 | 
						|
    if klass.ole_type == "Class" &&
 | 
						|
       klass.guid &&
 | 
						|
       klass.progid
 | 
						|
      @receiver = "@dispatch."
 | 
						|
      define_class(klass, io)
 | 
						|
    else
 | 
						|
      @receiver = ""
 | 
						|
      define_module(klass, io)
 | 
						|
    end
 | 
						|
    generate_constants(klass, io)
 | 
						|
    generate_methods(klass, io)
 | 
						|
    io.puts "end"
 | 
						|
  end
 | 
						|
 | 
						|
  def generate(io = STDOUT)
 | 
						|
    io.puts "require 'win32ole'"
 | 
						|
    io.puts "require 'win32ole/property'"
 | 
						|
 | 
						|
    ole_classes(typelib).select{|klass|
 | 
						|
      klass.visible? &&
 | 
						|
      (klass.ole_type == "Class" ||
 | 
						|
       klass.ole_type == "Interface" ||
 | 
						|
       klass.ole_type == "Dispatch" ||
 | 
						|
       klass.ole_type == "Enum")
 | 
						|
    }.each do |klass|
 | 
						|
      generate_class(klass, io)
 | 
						|
    end
 | 
						|
    begin
 | 
						|
      @ole.quit if @ole
 | 
						|
    rescue
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
require 'win32ole'
 | 
						|
if __FILE__ == $0
 | 
						|
  if ARGV.size == 0
 | 
						|
    $stderr.puts "usage: #{$0} Type Library [...]"
 | 
						|
    exit 1
 | 
						|
  end
 | 
						|
  ARGV.each do |typelib|
 | 
						|
    comgen = WIN32COMGen.new(typelib)
 | 
						|
    comgen.generate
 | 
						|
  end
 | 
						|
end
 |