ffidb 0.12.0

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.
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