ffidb 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/CHANGES.md +7 -0
  4. data/CREDITS.md +2 -0
  5. data/README.md +201 -0
  6. data/UNLICENSE +24 -0
  7. data/VERSION +1 -0
  8. data/bin/ffidb +387 -0
  9. data/etc/mappings/dart.yaml +35 -0
  10. data/etc/mappings/java.yaml +36 -0
  11. data/etc/mappings/lisp.yaml +35 -0
  12. data/etc/mappings/python.yaml +35 -0
  13. data/etc/mappings/ruby.yaml +35 -0
  14. data/etc/templates/c.erb +46 -0
  15. data/etc/templates/cpp.erb +45 -0
  16. data/etc/templates/dart.erb +64 -0
  17. data/etc/templates/go.erb +50 -0
  18. data/etc/templates/java.erb +56 -0
  19. data/etc/templates/lisp.erb +49 -0
  20. data/etc/templates/python.erb +59 -0
  21. data/etc/templates/ruby.erb +48 -0
  22. data/lib/ffidb.rb +34 -0
  23. data/lib/ffidb/enum.rb +37 -0
  24. data/lib/ffidb/errors.rb +64 -0
  25. data/lib/ffidb/exporter.rb +141 -0
  26. data/lib/ffidb/exporters.rb +28 -0
  27. data/lib/ffidb/exporters/c.rb +52 -0
  28. data/lib/ffidb/exporters/cpp.rb +13 -0
  29. data/lib/ffidb/exporters/csharp.rb +6 -0
  30. data/lib/ffidb/exporters/csv.rb +24 -0
  31. data/lib/ffidb/exporters/dart.rb +60 -0
  32. data/lib/ffidb/exporters/go.rb +16 -0
  33. data/lib/ffidb/exporters/haskell.rb +3 -0
  34. data/lib/ffidb/exporters/java.rb +39 -0
  35. data/lib/ffidb/exporters/json.rb +38 -0
  36. data/lib/ffidb/exporters/julia.rb +3 -0
  37. data/lib/ffidb/exporters/lisp.rb +41 -0
  38. data/lib/ffidb/exporters/luajit.rb +3 -0
  39. data/lib/ffidb/exporters/nim.rb +4 -0
  40. data/lib/ffidb/exporters/nodejs.rb +4 -0
  41. data/lib/ffidb/exporters/ocaml.rb +4 -0
  42. data/lib/ffidb/exporters/php.rb +4 -0
  43. data/lib/ffidb/exporters/python.rb +35 -0
  44. data/lib/ffidb/exporters/racket.rb +3 -0
  45. data/lib/ffidb/exporters/ruby.rb +33 -0
  46. data/lib/ffidb/exporters/rust.rb +5 -0
  47. data/lib/ffidb/exporters/yaml.rb +31 -0
  48. data/lib/ffidb/exporters/zig.rb +3 -0
  49. data/lib/ffidb/function.rb +70 -0
  50. data/lib/ffidb/glob.rb +28 -0
  51. data/lib/ffidb/header.rb +19 -0
  52. data/lib/ffidb/header_parser.rb +339 -0
  53. data/lib/ffidb/library.rb +120 -0
  54. data/lib/ffidb/library_parser.rb +132 -0
  55. data/lib/ffidb/location.rb +17 -0
  56. data/lib/ffidb/parameter.rb +35 -0
  57. data/lib/ffidb/registry.rb +87 -0
  58. data/lib/ffidb/release.rb +14 -0
  59. data/lib/ffidb/struct.rb +41 -0
  60. data/lib/ffidb/symbol_table.rb +90 -0
  61. data/lib/ffidb/symbolic.rb +67 -0
  62. data/lib/ffidb/sysexits.rb +21 -0
  63. data/lib/ffidb/type.rb +214 -0
  64. data/lib/ffidb/typedef.rb +38 -0
  65. data/lib/ffidb/union.rb +37 -0
  66. data/lib/ffidb/version.rb +21 -0
  67. metadata +197 -0
@@ -0,0 +1,90 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative 'symbolic'
4
+
5
+ module FFIDB
6
+ module SymbolTable
7
+ include Enumerable
8
+
9
+ ##
10
+ # @return [Array<Type>]
11
+ def types
12
+ self.each_type.to_a
13
+ end
14
+
15
+ ##
16
+ # @yield [type]
17
+ # @yieldparam [type] Type
18
+ # @return [Enumerator]
19
+ def each_type(&block)
20
+ return self.to_enum(:each_type) unless block_given?
21
+ types = {}
22
+ self.each_function do |function| # TODO: each_symbol
23
+ types[function.type.to_s] ||= function.type
24
+ function.parameters.each_value do |parameter|
25
+ types[parameter.type.to_s] ||= parameter.type
26
+ end
27
+ end
28
+ types.values.sort.each(&block)
29
+ end
30
+
31
+ ##
32
+ # @yield [symbol]
33
+ # @yieldparam [symbol] Symbolic
34
+ # @return [Enumerator]
35
+ def each_symbol(&block)
36
+ return self.to_enum(:each_symbol) unless block_given?
37
+ self.each_typedef(&block)
38
+ self.each_enum(&block)
39
+ self.each_struct(&block)
40
+ self.each_union(&block)
41
+ self.each_function(&block)
42
+ end
43
+ alias_method :each, :each_symbol
44
+
45
+ ##
46
+ # @yield [typedef]
47
+ # @yieldparam [symbol] Symbolic
48
+ # @return [Enumerator]
49
+ def each_typedef(&block)
50
+ return self.to_enum(:each_typedef) unless block_given?
51
+ self.typedefs.each(&block)
52
+ end
53
+
54
+ ##
55
+ # @yield [enum]
56
+ # @yieldparam [enum] Enum
57
+ # @return [Enumerator]
58
+ def each_enum(&block)
59
+ return self.to_enum(:each_enum) unless block_given?
60
+ self.enums.each(&block)
61
+ end
62
+
63
+ ##
64
+ # @yield [struct]
65
+ # @yieldparam [struct] Struct
66
+ # @return [Enumerator]
67
+ def each_struct(&block)
68
+ return self.to_enum(:each_struct) unless block_given?
69
+ self.structs.each(&block)
70
+ end
71
+
72
+ ##
73
+ # @yield [union]
74
+ # @yieldparam [union] Union
75
+ # @return [Enumerator]
76
+ def each_union(&block)
77
+ return self.to_enum(:each_union) unless block_given?
78
+ self.unions.each(&block)
79
+ end
80
+
81
+ ##
82
+ # @yield [function]
83
+ # @yieldparam [function] Function
84
+ # @return [Enumerator]
85
+ def each_function(&block)
86
+ return self.to_enum(:each_function) unless block_given?
87
+ self.functions.each(&block)
88
+ end
89
+ end # SymbolTable
90
+ end # FFIDB
@@ -0,0 +1,67 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ module FFIDB
4
+ module Symbolic
5
+ include Comparable
6
+
7
+ ##
8
+ # @param [Symbolic] other
9
+ # @return [Integer]
10
+ def <=>(other)
11
+ self.name <=> other.name
12
+ end
13
+
14
+ ##
15
+ # @return [Symbol]
16
+ def kind
17
+ case
18
+ when self.typedef? then :typedef
19
+ when self.enum? then :enum
20
+ when self.struct? then :struct
21
+ when self.union? then :union
22
+ when self.function? then :function
23
+ end
24
+ end
25
+
26
+ ##
27
+ # @return [Integer]
28
+ def kind_weight
29
+ case
30
+ when self.typedef? then 1
31
+ when self.enum? then 2
32
+ when self.struct? then 3
33
+ when self.union? then 4
34
+ when self.function? then 5
35
+ end
36
+ end
37
+
38
+ ##
39
+ # @return [Boolean]
40
+ def typedef?() return false end
41
+
42
+ ##
43
+ # @return [Boolean]
44
+ def enum?() return false end
45
+
46
+ ##
47
+ # @return [Boolean]
48
+ def struct?() return false end
49
+
50
+ ##
51
+ # @return [Boolean]
52
+ def union?() return false end
53
+
54
+ ##
55
+ # @return [Boolean]
56
+ def function?() return false end
57
+
58
+ ##
59
+ # @return [String]
60
+ def to_yaml
61
+ h = self.to_h
62
+ h.transform_keys!(&:to_s)
63
+ h.transform_values! { |v| v.is_a?(Hash) ? v.transform_keys!(&:to_s) : v }
64
+ YAML.dump(h).gsub!("---\n", "--- !#{self.kind}\n")
65
+ end
66
+ end # Symbolic
67
+ end # FFIDB
@@ -0,0 +1,21 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ module FFIDB
4
+ module Sysexits
5
+ EX_USAGE = 64
6
+ EX_DATAERR = 65
7
+ EX_NOINPUT = 66
8
+ EX_NOUSER = 67
9
+ EX_NOHOST = 68
10
+ EX_UNAVAILABLE = 69
11
+ EX_SOFTWARE = 70
12
+ EX_OSERR = 71
13
+ EX_OSFILE = 72
14
+ EX_CANTCREAT = 73
15
+ EX_IOERR = 74
16
+ EX_TEMPFAIL = 75
17
+ EX_PROTOCOL = 76
18
+ EX_NOPERM = 77
19
+ EX_CONFIG = 78
20
+ end # Sysexits
21
+ end # FFIDB
@@ -0,0 +1,214 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ module FFIDB
4
+ class Type < ::Struct.new(:spec)
5
+ include Comparable
6
+
7
+ ##
8
+ # @param [String, #to_s] spec
9
+ # @return [Type]
10
+ def self.for(type_spec)
11
+ return type_spec if type_spec.is_a?(Type)
12
+ self.new(type_spec)
13
+ end
14
+
15
+ ##
16
+ # @param [String, #to_s] spec
17
+ def initialize(spec)
18
+ super(spec.to_s)
19
+ end
20
+
21
+ ##
22
+ # @param [Type] other
23
+ # @return [Integer]
24
+ def <=>(other) self.spec <=> other.spec end
25
+
26
+ ##
27
+ # @return [Boolean]
28
+ def const_qualified?
29
+ self.spec.start_with?('const ')
30
+ end
31
+
32
+ ##
33
+ # @return [Boolean]
34
+ def atomic?
35
+ self.bool? || self.integer? || self.floating_point? || self.pointer? || nil # TODO
36
+ end
37
+
38
+ ##
39
+ # @return [Boolean]
40
+ def void?
41
+ self.spec == 'void'
42
+ end
43
+
44
+ ##
45
+ # @return [Boolean]
46
+ def bool?
47
+ self.spec == '_Bool'
48
+ end
49
+
50
+ ##
51
+ # @return [Boolean]
52
+ def enum?
53
+ !(self.pointer?) && self.spec.start_with?('enum ')
54
+ end
55
+
56
+ ##
57
+ # @return [Boolean]
58
+ def struct?
59
+ !(self.pointer?) && (self.spec.start_with?('struct ') || self.spec.start_with?('const struct '))
60
+ end
61
+
62
+ ##
63
+ # @return [Boolean]
64
+ def union?
65
+ !(self.pointer?) && (self.spec.start_with?('union ') || self.spec.start_with?('const union '))
66
+ end
67
+
68
+ ##
69
+ # @return [Boolean]
70
+ def integer?
71
+ case self.spec
72
+ when 'char', 'short', 'int', 'long', 'long long' then true
73
+ when 'unsigned char', 'unsigned short', 'unsigned int', 'unsigned long', 'unsigned long long' then true
74
+ when 'size_t', 'wchar_t' then true # <stddef.h>
75
+ when 'ssize_t', 'off_t' then true # <sys/types.h>
76
+ when /^u?int\d+_t$/ then true
77
+ else false
78
+ end
79
+ end
80
+
81
+ ##
82
+ # @return [Boolean]
83
+ def signed_integer?
84
+ return false unless self.integer?
85
+ case self.spec
86
+ when 'char', 'short', 'int', 'long', 'long long' then true
87
+ when 'wchar_t' then nil # <stddef.h>
88
+ when 'ssize_t' then true # <sys/types.h>
89
+ when /^int\d+_t$/ then true
90
+ else false
91
+ end
92
+ end
93
+
94
+ ##
95
+ # @return [Boolean]
96
+ def unsigned_integer?
97
+ return false unless self.integer?
98
+ return true if self.spec.start_with?('u')
99
+ case self.spec
100
+ when 'unsigned char', 'unsigned short', 'unsigned int', 'unsigned long', 'unsigned long long' then true
101
+ when 'size_t' then true # <stddef.h>
102
+ when 'wchar_t' then nil # <stddef.h>
103
+ when 'off_t' then true # <sys/types.h>
104
+ when /^uint\d+_t$/ then true
105
+ else false
106
+ end
107
+ end
108
+
109
+ ##
110
+ # @return [Boolean]
111
+ def floating_point?
112
+ case self.spec
113
+ when 'float', 'double', 'long double' then true
114
+ else false
115
+ end
116
+ end
117
+
118
+ ##
119
+ # @return [Boolean]
120
+ def array?
121
+ self.spec.include?('[')
122
+ end
123
+
124
+ ##
125
+ # @return [Type]
126
+ def array_type
127
+ if self.array?
128
+ self.class.for(self.spec.gsub(/\s+(\[[^\]]+\])/, ''))
129
+ end
130
+ end
131
+
132
+ ##
133
+ # @return [Integer]
134
+ def array_size
135
+ if self.array?
136
+ (/\[([^\]]+)\]/ =~ self.spec) && $1.to_i
137
+ end
138
+ end
139
+
140
+ ##
141
+ # @return [Boolean]
142
+ def pointer?
143
+ self.spec.end_with?('*') ||
144
+ self.array_pointer? ||
145
+ self.function_pointer? ||
146
+ case self.spec
147
+ when 'intptr_t', 'uintptr_t' then true
148
+ when 'va_list' then true
149
+ else false
150
+ end
151
+ end
152
+
153
+ ##
154
+ # @return [Boolean]
155
+ def array_pointer?
156
+ self.spec.end_with?('[]')
157
+ end
158
+
159
+ ##
160
+ # @return [Boolean]
161
+ def enum_pointer?
162
+ self.pointer? && self.spec.start_with?('enum ')
163
+ end
164
+
165
+ ##
166
+ # @return [Boolean]
167
+ def struct_pointer?
168
+ self.pointer? && (self.spec.start_with?('struct ') || self.spec.start_with?('const struct '))
169
+ end
170
+
171
+ ##
172
+ # @return [Boolean]
173
+ def union_pointer?
174
+ self.pointer? && (self.spec.start_with?('union ') || self.spec.start_with?('const union '))
175
+ end
176
+
177
+ ##
178
+ # @return [Boolean]
179
+ def function_pointer?
180
+ self.spec.include?('(*)')
181
+ end
182
+
183
+ ##
184
+ # @return [Integer, Range, nil]
185
+ def sizeof
186
+ nil # TODO
187
+ end
188
+ alias_method :size, :sizeof
189
+
190
+ ##
191
+ # @return [Integer, Range, nil]
192
+ def alignof
193
+ nil # TODO
194
+ end
195
+
196
+ ##
197
+ # @return [String]
198
+ def to_s
199
+ self.spec
200
+ end
201
+
202
+ ##
203
+ # @return [Hash<Symbol, Object>]
204
+ def to_h
205
+ {spec: self.spec}
206
+ end
207
+
208
+ ##
209
+ # @return [String]
210
+ def inspect
211
+ "#{self.class}(#{self.spec.inspect})"
212
+ end
213
+ end # Type
214
+ end # FFIDB
@@ -0,0 +1,38 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative 'symbolic'
4
+ require_relative 'type'
5
+
6
+ module FFIDB
7
+ class Typedef < ::Struct.new(:name, :type, :comment)
8
+ include Symbolic
9
+
10
+ ##
11
+ # @param [Symbol, #to_sym] name
12
+ # @param [Type] type
13
+ # @param [String, #to_s] comment
14
+ def initialize(name, type, comment = nil)
15
+ super(name.to_sym, Type.for(type), comment&.to_s)
16
+ end
17
+
18
+ ##
19
+ # @return [Boolean]
20
+ def typedef?() return true end
21
+
22
+ ##
23
+ # @return [String]
24
+ def to_s
25
+ "typedef #{self.type} #{self.name}"
26
+ end
27
+
28
+ ##
29
+ # @return [Hash<Symbol, Type>]
30
+ def to_h
31
+ {
32
+ name: self.name.to_s,
33
+ type: self.type.to_s,
34
+ comment: self.comment,
35
+ }.delete_if { |k, v| v.nil? }
36
+ end
37
+ end # Typedef
38
+ end # FFIDB
@@ -0,0 +1,37 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative 'symbolic'
4
+
5
+ module FFIDB
6
+ class Union < ::Struct.new(:name, :fields, :comment)
7
+ include Symbolic
8
+
9
+ ##
10
+ # @param [Symbol, #to_sym] name
11
+ # @param [Map<Symbol, Type>] fields
12
+ # @param [String, #to_s] comment
13
+ def initialize(name, fields = {}, comment = nil)
14
+ super(name.to_sym, fields || {}, comment&.to_s)
15
+ end
16
+
17
+ ##
18
+ # @return [Boolean]
19
+ def union?() return true end
20
+
21
+ ##
22
+ # @return [String]
23
+ def to_s
24
+ "union #{self.name}"
25
+ end
26
+
27
+ ##
28
+ # @return [Hash<Symbol, Type>]
29
+ def to_h
30
+ {
31
+ name: self.name.to_s,
32
+ comment: self.comment,
33
+ fields: self.fields,
34
+ }.delete_if { |k, v| v.nil? }
35
+ end
36
+ end # Union
37
+ end # FFIDB