class FFI::Generators::Types

Constants

TYPE_MAP

Maps different C types to the C type representations we use

Public Class Methods

generate() click to toggle source
# File lib/ffi2/generators/types.rb, line 43
def self.generate
  new.generate
end
new() click to toggle source
# File lib/ffi2/generators/types.rb, line 47
def initialize
  @platform = Platform.new
end

Public Instance Methods

generate() click to toggle source
# File lib/ffi2/generators/types.rb, line 72
def generate
  typedefs = BodyGuard.new(self, "ffi_types_generator", @platform).perform

  code = ""

  typedefs.split(/\n/).each do |type|
    # We only care about single line typedef
    next unless type =~ /typedef/
    # Ignore unions or structs
    next if type =~ /union|struct/

    # strip off the starting typedef and ending ;
    type.gsub!(/^(.*typedef\s*)/, "")
    type.gsub!(/\s*;\s*$/, "")

    parts = type.split(/\s+/)
    def_type   = parts.join(" ")

    # GCC does mapping with __attribute__ stuf, also see
    # http://hal.cs.berkeley.edu/cil/cil016.html section 16.2.7.  Problem
    # with this is that the __attribute__ stuff can either occur before or
    # after the new type that is defined...
    if type =~ /__attribute__/
      if parts.last =~ /__QI__|__HI__|__SI__|__DI__|__word__/

        # In this case, the new type is BEFORE __attribute__ we need to
        # find the final_type as the type before the part that starts with
        # __attribute__
        final_type = ""
        parts.each do |p|
          break if p =~ /__attribute__/
          final_type = p
        end
      else
        final_type = parts.pop
      end

      def_type = case type
                 when /__QI__/   then "char"
                 when /__HI__/   then "short"
                 when /__SI__/   then "int"
                 when /__DI__/   then "long long"
                 when /__word__/ then "long"
                 else                 "int"
                 end

      def_type = "unsigned #{def_type}" if type =~ /unsigned/
    else
      final_type = parts.pop
      def_type   = parts.join(" ")
    end

    if type = TYPE_MAP[def_type]
      code << "rbx.platform.typedef.#{final_type} = #{type}\n"
      TYPE_MAP[final_type] = TYPE_MAP[def_type]
    else
      # Fallback to an ordinary pointer if we don't know the type
      if def_type =~ /\*/
        code << "rbx.platform.typedef.#{final_type} = pointer\n"
        TYPE_MAP[final_type] = :pointer
      end
    end
  end

  code
end
prepare(name, target) click to toggle source
# File lib/ffi2/generators/types.rb, line 60
def prepare(name, target)
  # we have nothing to do in this stage
end
process(target) click to toggle source
# File lib/ffi2/generators/types.rb, line 64
def process(target)
  "#{@platform.compiler} -E #{@platform.defines} #{target}"
end
process_failed() click to toggle source
# File lib/ffi2/generators/types.rb, line 68
def process_failed
  "Error generating C types"
end
source(io) click to toggle source
# File lib/ffi2/generators/types.rb, line 51
def source(io)
  io.puts "#include <stdint.h>"
  io.puts "#include <sys/types.h>"
  unless @platform.windows?
    io.puts "#include <sys/socket.h>"
    io.puts "#include <sys/resource.h>"
  end
end