ffi 1.12.2-java → 1.14.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/Gemfile +17 -0
- data/LICENSE.SPECS +22 -0
- data/README.md +10 -2
- data/Rakefile +31 -43
- data/ffi.gemspec +43 -0
- data/lib/ffi.rb +28 -0
- data/lib/ffi/abstract_memory.rb +44 -0
- data/lib/ffi/autopointer.rb +203 -0
- data/lib/ffi/buffer.rb +4 -0
- data/lib/ffi/callback.rb +4 -0
- data/lib/ffi/data_converter.rb +67 -0
- data/lib/ffi/enum.rb +296 -0
- data/lib/ffi/errno.rb +43 -0
- data/lib/ffi/ffi.rb +47 -0
- data/lib/ffi/io.rb +62 -0
- data/lib/ffi/library.rb +592 -0
- data/lib/ffi/managedstruct.rb +84 -0
- data/lib/ffi/memorypointer.rb +1 -0
- data/lib/ffi/platform.rb +188 -0
- data/lib/ffi/platform/aarch64-darwin/types.conf +130 -0
- data/lib/ffi/platform/aarch64-freebsd/types.conf +128 -0
- data/lib/ffi/platform/aarch64-freebsd12/types.conf +128 -0
- data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
- data/lib/ffi/platform/aarch64-openbsd/types.conf +134 -0
- data/lib/ffi/platform/arm-freebsd/types.conf +152 -0
- data/lib/ffi/platform/arm-freebsd12/types.conf +152 -0
- data/lib/ffi/platform/arm-linux/types.conf +132 -0
- data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
- data/lib/ffi/platform/i386-darwin/types.conf +100 -0
- data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
- data/lib/ffi/platform/i386-freebsd12/types.conf +152 -0
- data/lib/ffi/platform/i386-gnu/types.conf +107 -0
- data/lib/ffi/platform/i386-linux/types.conf +103 -0
- data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
- data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
- data/lib/ffi/platform/i386-solaris/types.conf +122 -0
- data/lib/ffi/platform/i386-windows/types.conf +52 -0
- data/lib/ffi/platform/ia64-linux/types.conf +104 -0
- data/lib/ffi/platform/mips-linux/types.conf +102 -0
- data/lib/ffi/platform/mips64-linux/types.conf +104 -0
- data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
- data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsisa32r6-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsisa32r6el-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsisa64r6-linux/types.conf +104 -0
- data/lib/ffi/platform/mipsisa64r6el-linux/types.conf +104 -0
- data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
- data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
- data/lib/ffi/platform/powerpc-linux/types.conf +130 -0
- data/lib/ffi/platform/powerpc-openbsd/types.conf +156 -0
- data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
- data/lib/ffi/platform/s390-linux/types.conf +102 -0
- data/lib/ffi/platform/s390x-linux/types.conf +102 -0
- data/lib/ffi/platform/sparc-linux/types.conf +102 -0
- data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
- data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
- data/lib/ffi/platform/sparcv9-openbsd/types.conf +156 -0
- data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
- data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
- data/lib/ffi/platform/x86_64-darwin/types.conf +130 -0
- data/lib/ffi/platform/x86_64-dragonflybsd/types.conf +130 -0
- data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
- data/lib/ffi/platform/x86_64-freebsd12/types.conf +158 -0
- data/lib/ffi/platform/x86_64-haiku/types.conf +117 -0
- data/lib/ffi/platform/x86_64-linux/types.conf +132 -0
- data/lib/ffi/platform/x86_64-msys/types.conf +119 -0
- data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
- data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
- data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
- data/lib/ffi/platform/x86_64-windows/types.conf +52 -0
- data/lib/ffi/pointer.rb +167 -0
- data/lib/ffi/struct.rb +316 -0
- data/lib/ffi/struct_by_reference.rb +72 -0
- data/lib/ffi/struct_layout.rb +96 -0
- data/lib/ffi/struct_layout_builder.rb +227 -0
- data/lib/ffi/tools/const_generator.rb +230 -0
- data/lib/ffi/tools/generator.rb +105 -0
- data/lib/ffi/tools/generator_task.rb +32 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +137 -0
- data/lib/ffi/types.rb +194 -0
- data/lib/ffi/union.rb +43 -0
- data/lib/ffi/variadic.rb +78 -0
- data/lib/ffi/version.rb +3 -0
- data/samples/getlogin.rb +8 -0
- data/samples/getpid.rb +8 -0
- data/samples/gettimeofday.rb +18 -0
- data/samples/hello.rb +8 -0
- data/samples/inotify.rb +60 -0
- data/samples/pty.rb +75 -0
- data/samples/qsort.rb +20 -0
- metadata +175 -29
- checksums.yaml.gz.sig +0 -3
- data.tar.gz.sig +0 -3
- metadata.gz.sig +0 -4
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'ffi/tools/struct_generator'
|
|
2
|
+
require 'ffi/tools/const_generator'
|
|
3
|
+
|
|
4
|
+
module FFI
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Generate files with C structs for FFI::Struct and C constants.
|
|
8
|
+
#
|
|
9
|
+
# == A simple example
|
|
10
|
+
#
|
|
11
|
+
# In file +zlib.rb.ffi+:
|
|
12
|
+
# module Zlib
|
|
13
|
+
# @@@
|
|
14
|
+
# constants do |c|
|
|
15
|
+
# c.include "zlib.h"
|
|
16
|
+
# c.const :ZLIB_VERNUM
|
|
17
|
+
# end
|
|
18
|
+
# @@@
|
|
19
|
+
#
|
|
20
|
+
# class ZStream < FFI::Struct
|
|
21
|
+
#
|
|
22
|
+
# struct do |s|
|
|
23
|
+
# s.name "struct z_stream_s"
|
|
24
|
+
# s.include "zlib.h"
|
|
25
|
+
#
|
|
26
|
+
# s.field :next_in, :pointer
|
|
27
|
+
# s.field :avail_in, :uint
|
|
28
|
+
# s.field :total_in, :ulong
|
|
29
|
+
# end
|
|
30
|
+
# @@@
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# Translate the file:
|
|
35
|
+
# require "ffi/tools/generator"
|
|
36
|
+
# FFI::Generator.new "zlib.rb.ffi", "zlib.rb"
|
|
37
|
+
#
|
|
38
|
+
# Generates the file +zlib.rb+ with constant values and offsets:
|
|
39
|
+
# module Zlib
|
|
40
|
+
# ZLIB_VERNUM = 4784
|
|
41
|
+
#
|
|
42
|
+
# class ZStream < FFI::Struct
|
|
43
|
+
# layout :next_in, :pointer, 0,
|
|
44
|
+
# :avail_in, :uint, 8,
|
|
45
|
+
# :total_in, :ulong, 16
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# @see FFI::Generator::Task for easy integration in a Rakefile
|
|
49
|
+
class Generator
|
|
50
|
+
|
|
51
|
+
def initialize(ffi_name, rb_name, options = {})
|
|
52
|
+
@ffi_name = ffi_name
|
|
53
|
+
@rb_name = rb_name
|
|
54
|
+
@options = options
|
|
55
|
+
@name = File.basename rb_name, '.rb'
|
|
56
|
+
|
|
57
|
+
file = File.read @ffi_name
|
|
58
|
+
|
|
59
|
+
new_file = file.gsub(/^( *)@@@(.*?)@@@/m) do
|
|
60
|
+
@constants = []
|
|
61
|
+
@structs = []
|
|
62
|
+
|
|
63
|
+
indent = $1
|
|
64
|
+
original_lines = $2.count "\n"
|
|
65
|
+
|
|
66
|
+
instance_eval $2, @ffi_name, $`.count("\n")
|
|
67
|
+
|
|
68
|
+
new_lines = []
|
|
69
|
+
@constants.each { |c| new_lines << c.to_ruby }
|
|
70
|
+
@structs.each { |s| new_lines << s.generate_layout }
|
|
71
|
+
|
|
72
|
+
new_lines = new_lines.join("\n").split "\n" # expand multiline blocks
|
|
73
|
+
new_lines = new_lines.map { |line| indent + line }
|
|
74
|
+
|
|
75
|
+
padding = original_lines - new_lines.length
|
|
76
|
+
new_lines += [nil] * padding if padding >= 0
|
|
77
|
+
|
|
78
|
+
new_lines.join "\n"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
open @rb_name, 'w' do |f|
|
|
82
|
+
f.puts "# This file is generated from `#{@ffi_name}'. Do not edit."
|
|
83
|
+
f.puts
|
|
84
|
+
f.puts new_file
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def constants(options = {}, &block)
|
|
89
|
+
@constants << FFI::ConstGenerator.new(@name, @options.merge(options), &block)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def struct(options = {}, &block)
|
|
93
|
+
@structs << FFI::StructGenerator.new(@name, @options.merge(options), &block)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# Utility converter for constants
|
|
98
|
+
|
|
99
|
+
def to_s
|
|
100
|
+
proc { |obj| obj.to_s.inspect }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'ffi/tools/generator'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rake/tasklib'
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Add Rake tasks that generate files with C structs for FFI::Struct and C constants.
|
|
7
|
+
#
|
|
8
|
+
# @example a simple example for your Rakefile
|
|
9
|
+
# require "ffi/tools/generator_task"
|
|
10
|
+
# # Add a task to generate my_object.rb out of my_object.rb.ffi
|
|
11
|
+
# FFI::Generator::Task.new ["my_object.rb"], cflags: "-I/usr/local/mylibrary"
|
|
12
|
+
#
|
|
13
|
+
# The generated files are also added to the 'clear' task.
|
|
14
|
+
#
|
|
15
|
+
# @see FFI::Generator for a description of the file content
|
|
16
|
+
class FFI::Generator::Task < Rake::TaskLib
|
|
17
|
+
|
|
18
|
+
def initialize(rb_names, options={})
|
|
19
|
+
task :clean do rm_f rb_names end
|
|
20
|
+
|
|
21
|
+
rb_names.each do |rb_name|
|
|
22
|
+
ffi_name = "#{rb_name}.ffi"
|
|
23
|
+
|
|
24
|
+
file rb_name => ffi_name do |t|
|
|
25
|
+
puts "Generating #{rb_name}..." if Rake.application.options.trace
|
|
26
|
+
|
|
27
|
+
FFI::Generator.new ffi_name, rb_name, options
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module FFI
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Generates an FFI Struct layout.
|
|
7
|
+
#
|
|
8
|
+
# Given the @@@ portion in:
|
|
9
|
+
#
|
|
10
|
+
# class Zlib::ZStream < FFI::Struct
|
|
11
|
+
# @@@
|
|
12
|
+
# name "struct z_stream_s"
|
|
13
|
+
# include "zlib.h"
|
|
14
|
+
#
|
|
15
|
+
# field :next_in, :pointer
|
|
16
|
+
# field :avail_in, :uint
|
|
17
|
+
# field :total_in, :ulong
|
|
18
|
+
#
|
|
19
|
+
# # ...
|
|
20
|
+
# @@@
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# StructGenerator will create the layout:
|
|
24
|
+
#
|
|
25
|
+
# layout :next_in, :pointer, 0,
|
|
26
|
+
# :avail_in, :uint, 4,
|
|
27
|
+
# :total_in, :ulong, 8,
|
|
28
|
+
# # ...
|
|
29
|
+
#
|
|
30
|
+
# StructGenerator does its best to pad the layout it produces to preserve
|
|
31
|
+
# line numbers. Place the struct definition as close to the top of the file
|
|
32
|
+
# for best results.
|
|
33
|
+
|
|
34
|
+
class StructGenerator
|
|
35
|
+
@options = {}
|
|
36
|
+
attr_accessor :size
|
|
37
|
+
attr_reader :fields
|
|
38
|
+
|
|
39
|
+
def initialize(name, options = {})
|
|
40
|
+
@name = name
|
|
41
|
+
@struct_name = nil
|
|
42
|
+
@includes = []
|
|
43
|
+
@fields = []
|
|
44
|
+
@found = false
|
|
45
|
+
@size = nil
|
|
46
|
+
|
|
47
|
+
if block_given? then
|
|
48
|
+
yield self
|
|
49
|
+
calculate self.class.options.merge(options)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
def self.options=(options)
|
|
53
|
+
@options = options
|
|
54
|
+
end
|
|
55
|
+
def self.options
|
|
56
|
+
@options
|
|
57
|
+
end
|
|
58
|
+
def calculate(options = {})
|
|
59
|
+
binary = File.join Dir.tmpdir, "rb_struct_gen_bin_#{Process.pid}"
|
|
60
|
+
|
|
61
|
+
raise "struct name not set" if @struct_name.nil?
|
|
62
|
+
|
|
63
|
+
Tempfile.open("#{@name}.struct_generator") do |f|
|
|
64
|
+
f.puts "#include <stdio.h>"
|
|
65
|
+
|
|
66
|
+
@includes.each do |inc|
|
|
67
|
+
f.puts "#include <#{inc}>"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
f.puts "#include <stddef.h>\n\n"
|
|
71
|
+
f.puts "int main(int argc, char **argv)\n{"
|
|
72
|
+
f.puts " #{@struct_name} s;"
|
|
73
|
+
f.puts %[ printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));]
|
|
74
|
+
|
|
75
|
+
@fields.each do |field|
|
|
76
|
+
f.puts <<-EOF
|
|
77
|
+
printf("#{field.name} %u %u\\n", (unsigned int) offsetof(#{@struct_name}, #{field.name}),
|
|
78
|
+
(unsigned int) sizeof(s.#{field.name}));
|
|
79
|
+
EOF
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
f.puts "\n return 0;\n}"
|
|
83
|
+
f.flush
|
|
84
|
+
|
|
85
|
+
output = `gcc #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`
|
|
86
|
+
|
|
87
|
+
unless $?.success? then
|
|
88
|
+
@found = false
|
|
89
|
+
output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
|
|
90
|
+
raise "Compilation error generating struct #{@name} (#{@struct_name}):\n#{output}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
output = `#{binary}`.split "\n"
|
|
95
|
+
File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
|
|
96
|
+
sizeof = output.shift
|
|
97
|
+
unless @size
|
|
98
|
+
m = /\s*sizeof\([^)]+\) (\d+)/.match sizeof
|
|
99
|
+
@size = m[1]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
line_no = 0
|
|
103
|
+
output.each do |line|
|
|
104
|
+
md = line.match(/.+ (\d+) (\d+)/)
|
|
105
|
+
@fields[line_no].offset = md[1].to_i
|
|
106
|
+
@fields[line_no].size = md[2].to_i
|
|
107
|
+
|
|
108
|
+
line_no += 1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
@found = true
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def field(name, type=nil)
|
|
115
|
+
field = Field.new(name, type)
|
|
116
|
+
@fields << field
|
|
117
|
+
return field
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def found?
|
|
121
|
+
@found
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def dump_config(io)
|
|
125
|
+
io.puts "rbx.platform.#{@name}.sizeof = #{@size}"
|
|
126
|
+
|
|
127
|
+
@fields.each { |field| io.puts field.to_config(@name) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def generate_layout
|
|
131
|
+
buf = ""
|
|
132
|
+
|
|
133
|
+
@fields.each_with_index do |field, i|
|
|
134
|
+
if buf.empty?
|
|
135
|
+
buf << "layout :#{field.name}, :#{field.type}, #{field.offset}"
|
|
136
|
+
else
|
|
137
|
+
buf << " :#{field.name}, :#{field.type}, #{field.offset}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
if i < @fields.length - 1
|
|
141
|
+
buf << ",\n"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
buf
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def get_field(name)
|
|
149
|
+
@fields.find { |f| name == f.name }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def include(i)
|
|
153
|
+
@includes << i
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def name(n)
|
|
157
|
+
@struct_name = n
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# A field in a Struct.
|
|
164
|
+
|
|
165
|
+
class StructGenerator::Field
|
|
166
|
+
|
|
167
|
+
attr_reader :name
|
|
168
|
+
attr_reader :type
|
|
169
|
+
attr_reader :offset
|
|
170
|
+
attr_accessor :size
|
|
171
|
+
|
|
172
|
+
def initialize(name, type)
|
|
173
|
+
@name = name
|
|
174
|
+
@type = type
|
|
175
|
+
@offset = nil
|
|
176
|
+
@size = nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def offset=(o)
|
|
180
|
+
@offset = o
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def to_config(name)
|
|
184
|
+
buf = []
|
|
185
|
+
buf << "rbx.platform.#{name}.#{@name}.offset = #{@offset}"
|
|
186
|
+
buf << "rbx.platform.#{name}.#{@name}.size = #{@size}"
|
|
187
|
+
buf << "rbx.platform.#{name}.#{@name}.type = #{@type}" if @type
|
|
188
|
+
buf
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module FFI
|
|
4
|
+
|
|
5
|
+
# @private
|
|
6
|
+
class TypesGenerator
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Maps different C types to the C type representations we use
|
|
10
|
+
|
|
11
|
+
TYPE_MAP = {
|
|
12
|
+
"char" => :char,
|
|
13
|
+
"signed char" => :char,
|
|
14
|
+
"__signed char" => :char,
|
|
15
|
+
"unsigned char" => :uchar,
|
|
16
|
+
|
|
17
|
+
"short" => :short,
|
|
18
|
+
"signed short" => :short,
|
|
19
|
+
"signed short int" => :short,
|
|
20
|
+
"unsigned short" => :ushort,
|
|
21
|
+
"unsigned short int" => :ushort,
|
|
22
|
+
|
|
23
|
+
"int" => :int,
|
|
24
|
+
"signed int" => :int,
|
|
25
|
+
"unsigned int" => :uint,
|
|
26
|
+
|
|
27
|
+
"long" => :long,
|
|
28
|
+
"long int" => :long,
|
|
29
|
+
"signed long" => :long,
|
|
30
|
+
"signed long int" => :long,
|
|
31
|
+
"unsigned long" => :ulong,
|
|
32
|
+
"unsigned long int" => :ulong,
|
|
33
|
+
"long unsigned int" => :ulong,
|
|
34
|
+
|
|
35
|
+
"long long" => :long_long,
|
|
36
|
+
"long long int" => :long_long,
|
|
37
|
+
"signed long long" => :long_long,
|
|
38
|
+
"signed long long int" => :long_long,
|
|
39
|
+
"unsigned long long" => :ulong_long,
|
|
40
|
+
"unsigned long long int" => :ulong_long,
|
|
41
|
+
|
|
42
|
+
"char *" => :string,
|
|
43
|
+
"void *" => :pointer,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def self.generate(options = {})
|
|
47
|
+
typedefs = nil
|
|
48
|
+
Tempfile.open 'ffi_types_generator' do |io|
|
|
49
|
+
io.puts <<-C
|
|
50
|
+
#include <stdint.h>
|
|
51
|
+
#include <stddef.h>
|
|
52
|
+
#include <sys/types.h>
|
|
53
|
+
#if !(defined(WIN32))
|
|
54
|
+
#include <sys/socket.h>
|
|
55
|
+
#include <netinet/in.h>
|
|
56
|
+
#include <sys/resource.h>
|
|
57
|
+
#endif
|
|
58
|
+
C
|
|
59
|
+
|
|
60
|
+
io.close
|
|
61
|
+
cc = ENV['CC'] || 'gcc'
|
|
62
|
+
cmd = "#{cc} -E -x c #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -c"
|
|
63
|
+
if options[:input]
|
|
64
|
+
typedefs = File.read(options[:input])
|
|
65
|
+
elsif options[:remote]
|
|
66
|
+
typedefs = `ssh #{options[:remote]} #{cmd} - < #{io.path}`
|
|
67
|
+
else
|
|
68
|
+
typedefs = `#{cmd} #{io.path}`
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
code = []
|
|
73
|
+
|
|
74
|
+
typedefs.each_line do |type|
|
|
75
|
+
# We only care about single line typedef
|
|
76
|
+
next unless type =~ /typedef/
|
|
77
|
+
# Ignore unions or structs
|
|
78
|
+
next if type =~ /union|struct/
|
|
79
|
+
|
|
80
|
+
# strip off the starting typedef and ending ;
|
|
81
|
+
type.gsub!(/^(.*typedef\s*)/, "")
|
|
82
|
+
type.gsub!(/\s*;\s*$/, "")
|
|
83
|
+
|
|
84
|
+
parts = type.split(/\s+/)
|
|
85
|
+
def_type = parts.join(" ")
|
|
86
|
+
|
|
87
|
+
# GCC does mapping with __attribute__ stuf, also see
|
|
88
|
+
# http://hal.cs.berkeley.edu/cil/cil016.html section 16.2.7. Problem
|
|
89
|
+
# with this is that the __attribute__ stuff can either occur before or
|
|
90
|
+
# after the new type that is defined...
|
|
91
|
+
if type =~ /__attribute__/
|
|
92
|
+
if parts.last =~ /__QI__|__HI__|__SI__|__DI__|__word__/
|
|
93
|
+
|
|
94
|
+
# In this case, the new type is BEFORE __attribute__ we need to
|
|
95
|
+
# find the final_type as the type before the part that starts with
|
|
96
|
+
# __attribute__
|
|
97
|
+
final_type = ""
|
|
98
|
+
parts.each do |p|
|
|
99
|
+
break if p =~ /__attribute__/
|
|
100
|
+
final_type = p
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
final_type = parts.pop
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def_type = case type
|
|
107
|
+
when /__QI__/ then "char"
|
|
108
|
+
when /__HI__/ then "short"
|
|
109
|
+
when /__SI__/ then "int"
|
|
110
|
+
when /__DI__/ then "long long"
|
|
111
|
+
when /__word__/ then "long"
|
|
112
|
+
else "int"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def_type = "unsigned #{def_type}" if type =~ /unsigned/
|
|
116
|
+
else
|
|
117
|
+
final_type = parts.pop
|
|
118
|
+
def_type = parts.join(" ")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if type = TYPE_MAP[def_type]
|
|
122
|
+
code << "rbx.platform.typedef.#{final_type} = #{type}"
|
|
123
|
+
TYPE_MAP[final_type] = TYPE_MAP[def_type]
|
|
124
|
+
else
|
|
125
|
+
# Fallback to an ordinary pointer if we don't know the type
|
|
126
|
+
if def_type =~ /\*/
|
|
127
|
+
code << "rbx.platform.typedef.#{final_type} = pointer"
|
|
128
|
+
TYPE_MAP[final_type] = :pointer
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
code.sort.join("\n")
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|