class FFIDB::Exporter

Attributes

options[R]

Public Class Methods

for(format) click to toggle source
# File lib/ffidb/exporter.rb, line 9
def self.for(format) # TODO
  require_relative 'exporters'
  case format&.to_sym
    when :c, :c99, :c11, :c18 then Exporters::C
    when :'c++', :'c++11', :'c++14', :'c++17', :'c++20', :cpp, :cxx then Exporters::Cpp
    when :csv then Exporters::CSV
    when :dart, :flutter then Exporters::Dart
    when :go, :cgo then Exporters::Go
    when :java, :jna then Exporters::Java
    when :json then Exporters::JSON
    when :lisp, :'common-lisp' then Exporters::Lisp
    when :python, :py then Exporters::Python
    when :ruby, :rb then Exporters::Ruby
    # TODO: csharp, haskell, julia, luajit, nim, nodejs, ocaml, php, racket, rust, zig
    when :yaml then Exporters::YAML
    else raise "unknown output format: #{format}"
  end
end
new(stream = $stdout, **kwargs) click to toggle source
# File lib/ffidb/exporter.rb, line 30
def initialize(stream = $stdout, **kwargs)
  @stream = stream
  @options = kwargs.transform_keys(&:to_sym).freeze
end

Public Instance Methods

begin() click to toggle source
# File lib/ffidb/exporter.rb, line 65
def begin() end
begin_library(library) click to toggle source
# File lib/ffidb/exporter.rb, line 67
def begin_library(library)
  @library = library
  @libraries ||= []
  @libraries << library
  @typedefs ||= {}
  @enums ||= {}
  @structs ||= {}
  @unions ||= {}
  @functions ||= {}
end
close() click to toggle source
# File lib/ffidb/exporter.rb, line 117
def close() end
debug?() click to toggle source
# File lib/ffidb/exporter.rb, line 35
def debug?
  self.options[:debug]
end
dlopen_paths_for(library) click to toggle source
# File lib/ffidb/exporter.rb, line 57
def dlopen_paths_for(library)
  if library_path = self.options[:library_path]
    library.objects.map { |lib| library_path.delete_suffix('/') << "/" << lib }
  else
    library.objects + library.dlopen
  end
end
emit() { |self| ... } click to toggle source
# File lib/ffidb/exporter.rb, line 47
def emit(&block)
  begin
    self.begin
    yield self
    self.finish
  ensure
    self.close
  end
end
export_enum(enum, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 95
def export_enum(enum, disabled: nil)
  (@enums[@library] ||= []) << enum
end
export_function(function, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 107
def export_function(function, disabled: nil)
  (@functions[@library] ||= []) << self.resolve_function(function)
end
export_header(header) click to toggle source
# File lib/ffidb/exporter.rb, line 78
def export_header(header)
  header.typedefs.sort.each { |typedef| self.export_typedef(typedef) }
  header.enums.sort.each { |enum| self.export_enum(enum) }
  header.structs.sort.each { |struct| self.export_struct(struct) }
  header.unions.sort.each { |union| self.export_union(union) }
  header.functions.sort.each { |function| self.export_function(function) }
end
export_struct(struct, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 99
def export_struct(struct, disabled: nil)
  (@structs[@library] ||= []) << self.resolve_struct(struct)
end
export_symbol(symbol, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 86
def export_symbol(symbol, disabled: nil)
  self.__send__("export_#{symbol.kind}", symbol, disabled: disabled)
end
export_typedef(typedef, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 90
def export_typedef(typedef, disabled: nil)
  @typedefs[@library] ||= {}
  @typedefs[@library][typedef.name] = typedef
end
export_union(union, disabled: nil) click to toggle source
# File lib/ffidb/exporter.rb, line 103
def export_union(union, disabled: nil)
  (@unions[@library] ||= []) << self.resolve_union(union)
end
finish() click to toggle source
# File lib/ffidb/exporter.rb, line 115
def finish() end
finish_library() click to toggle source
# File lib/ffidb/exporter.rb, line 111
def finish_library
  @library = nil
end
header?() click to toggle source
# File lib/ffidb/exporter.rb, line 43
def header?
  self.options[:header]
end
verbose?() click to toggle source
# File lib/ffidb/exporter.rb, line 39
def verbose?
  self.options[:verbose] || self.debug?
end

Protected Instance Methods

format_comment(comment, prefix) click to toggle source

@param [String] comment @param [String] prefix @return [String]

# File lib/ffidb/exporter.rb, line 133
def format_comment(comment, prefix)
  prefix = prefix + ' '
  comment.each_line.map(&:strip).map { |s| s.prepend(prefix) }.join("\n")
end
load_template(template_name) click to toggle source
# File lib/ffidb/exporter.rb, line 242
def load_template(template_name)
  File.read(self.path_to_template(template_name)).freeze
end
load_typemap(typemap_name) click to toggle source
# File lib/ffidb/exporter.rb, line 229
def load_typemap(typemap_name)
  ::YAML.load(File.read(self.path_to_typemap(typemap_name))).freeze
end
lookup_symbol(type) click to toggle source

@param [Type] type @return [Symbolic]

# File lib/ffidb/exporter.rb, line 190
def lookup_symbol(type)
  self.lookup_typedef(type.name)
end
lookup_typedef(type_name) click to toggle source

@param [Symbol] type_name @return [Typedef]

# File lib/ffidb/exporter.rb, line 197
def lookup_typedef(type_name)
  @typedefs && @typedefs[@library] && @typedefs[@library][type_name]
end
param_type(c_type) click to toggle source

@param [Symbol, Type] c_type @return [#to_s]

# File lib/ffidb/exporter.rb, line 212
def param_type(c_type)
  return c_type if c_type.is_a?(Symbol) # a resolved typedef
  case
    when type = typemap[c_type.to_s] then type
    when c_type.enum? then typemap['int']
    when c_type.pointer? then typemap['void *']
    when c_type.array? then typemap['void *']
    else
      warn "#{$0}: unknown C type #{c_type}, mapping to enum (int)" if debug?
      typemap['int'] # TODO: typedef or enum
  end
end
path_to_template(template_name) click to toggle source
# File lib/ffidb/exporter.rb, line 246
def path_to_template(template_name)
  File.expand_path("../../etc/templates/#{template_name}", __dir__)
end
path_to_typemap(typemap_name) click to toggle source
# File lib/ffidb/exporter.rb, line 233
def path_to_typemap(typemap_name)
  File.expand_path("../../etc/mappings/#{typemap_name}", __dir__)
end
print(*args) click to toggle source
puts(*args) click to toggle source
# File lib/ffidb/exporter.rb, line 121
def puts(*args)
  @stream.puts *args
end
render_template(template_name) click to toggle source
# File lib/ffidb/exporter.rb, line 237
def render_template(template_name)
  #ERB.new(self.load_template(template_name)).result(binding)
  Tilt.new(self.path_to_template(template_name)).render(self)
end
resolve_function(function) click to toggle source

@param [Function] function @feturn [Function]

# File lib/ffidb/exporter.rb, line 141
def resolve_function(function)
  function.type = self.resolve_type(function.type)
  function.parameters.transform_values! do |param|
    param.type = self.resolve_type(param.type)
    param
  end
  function
end
resolve_struct(struct) click to toggle source

@param [Struct] struct @feturn [Struct]

# File lib/ffidb/exporter.rb, line 153
def resolve_struct(struct)
  struct.fields.each do |field_name, field_type|
    struct.fields[field_name] = self.resolve_type(field_type)
  end
  struct
end
resolve_type(type) click to toggle source

@param [Type] type @return [Type, Symbol]

# File lib/ffidb/exporter.rb, line 170
def resolve_type(type)
  case
    when type.struct_pointer?
      name = type.spec.gsub(/^const /, '').gsub(/^struct /, '').gsub(/\s*\*+$/, '')
      name.to_sym
    when type.struct? || type.union?
      type
    when typedef = lookup_typedef(type.name)
      case typedef.type.tag
        when :enum then type.name.to_sym
        when :struct then (type.pointer? ? type.name : "#{type.name}.by_value").to_sym # FIXME
        else typedef.type
      end
    else type
  end
end
resolve_union(union) click to toggle source

@param [Union] union @feturn [Union]

# File lib/ffidb/exporter.rb, line 163
def resolve_union(union)
  self.resolve_struct(union)
end
struct_type(c_type) click to toggle source

@param [Symbol, Type] c_type @return [#to_s]

# File lib/ffidb/exporter.rb, line 204
def struct_type(c_type)
  return c_type if c_type.is_a?(Symbol) # a resolved typedef
  self.param_type(c_type)
end
typemap() click to toggle source
# File lib/ffidb/exporter.rb, line 225
def typemap
  @typemap ||= self.load_typemap(self.class.const_get(:TYPE_MAP))
end