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,52 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the C programming language.
8
+ class C < FFIDB::Exporter
9
+ SYMBOL_INDENT = 0
10
+ EXTERN_QUALIFIER = 'extern'
11
+
12
+ def finish
13
+ puts self.render_template('c.erb')
14
+ end
15
+
16
+ def _export_function(function, **kwargs)
17
+ parameters = function.parameters.each_value.map do |p|
18
+ p_type = case
19
+ when p.type.function_pointer?
20
+ p.type.to_s.sub('(*)', "(*#{p.name})")
21
+ when self.options[:parameter_names] == false
22
+ p.type.to_s.gsub(' *', '*')
23
+ else "#{p.type.to_s.gsub(' *', '*')} #{p.name}"
24
+ end
25
+ p_type.gsub('const char *const[]', 'const char* const*') # FIXME
26
+ end
27
+ print ' '*self.symbol_indent if self.symbol_indent.nonzero?
28
+ print self.extern_qualifier, ' ' if self.extern_qualifier
29
+ if function.type.function_pointer?
30
+ print function.type.to_s.sub('(*)', "(*#{function.name}(#{parameters.join(', ')}))")
31
+ else
32
+ print function.type, ' ', function.name, '('
33
+ parameters.each_with_index do |p, i|
34
+ print ', ' if i.nonzero?
35
+ print p
36
+ end
37
+ print ')'
38
+ end
39
+ puts (self.options[:semicolon] == false ? '' : ';')
40
+ end
41
+
42
+ protected
43
+
44
+ def symbol_indent
45
+ self.class.const_get(:SYMBOL_INDENT)
46
+ end
47
+
48
+ def extern_qualifier
49
+ self.class.const_get(:EXTERN_QUALIFIER)
50
+ end
51
+ end # C
52
+ end # FFIDB::Exporters
@@ -0,0 +1,13 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative 'c'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the C++ programming language.
8
+ class Cpp < C
9
+ def finish
10
+ puts self.render_template('cpp.erb')
11
+ end
12
+ end # Cpp
13
+ end # FFIDB::Exporters
@@ -0,0 +1,6 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://docs.microsoft.com/en-us/dotnet/framework/interop/platform-invoke-examples
4
+ # TODO: https://docs.microsoft.com/en-us/dotnet/framework/interop/
5
+ # TODO: https://docs.microsoft.com/en-us/dotnet/framework/interop/consuming-unmanaged-dll-functions
6
+ # TODO: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportattribute
@@ -0,0 +1,24 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the CSV file format.
8
+ class CSV < FFIDB::Exporter
9
+ DELIMITER = ','
10
+
11
+ def begin
12
+ puts [:library, :kind, :name].join(DELIMITER) # TODO: definition
13
+ end
14
+
15
+ def export_symbol(symbol, **kwargs)
16
+ puts [@library&.name, symbol.kind, symbol.name].join(DELIMITER)
17
+ end
18
+ alias_method :export_typedef, :export_symbol
19
+ alias_method :export_enum, :export_symbol
20
+ alias_method :export_struct, :export_symbol
21
+ alias_method :export_union, :export_symbol
22
+ alias_method :export_function, :export_symbol
23
+ end # CSV
24
+ end # FFIDB::Exporters
@@ -0,0 +1,60 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Dart programming language.
8
+ #
9
+ # @see https://dart.dev/guides/libraries/c-interop
10
+ # @see https://flutter.dev/docs/development/platform-integration/c-interop
11
+ # @see https://api.dart.dev/dev/dart-ffi/dart-ffi-library.html
12
+ class Dart < FFIDB::Exporter
13
+ TYPE_MAP_FFI = ::YAML.load(File.read(File.expand_path("../../../etc/mappings/dart.yaml", __dir__)))
14
+ .freeze
15
+
16
+ # @see https://dart.dev/guides/language/language-tour
17
+ TYPE_MAP_DART = {
18
+ :Void => :void,
19
+ :Int8 => :int,
20
+ :Int16 => :int,
21
+ :Int32 => :int,
22
+ :Int64 => :int,
23
+ :Uint8 => :int,
24
+ :Uint16 => :int,
25
+ :Uint32 => :int,
26
+ :Uint64 => :int,
27
+ :Float => :double,
28
+ :Double => :double,
29
+ :IntPtr => :int,
30
+ 'Pointer<Int8>' => 'Pointer<Int8>',
31
+ nil => 'Pointer<Void>',
32
+ }
33
+
34
+ def finish
35
+ puts self.render_template('dart.erb')
36
+ end
37
+
38
+ protected
39
+
40
+ ##
41
+ # @param [FFIDB::Type] c_type
42
+ # @return [#to_s]
43
+ def dart_param_type(c_type)
44
+ TYPE_MAP_DART[self.ffi_param_type(c_type)] || TYPE_MAP_DART[nil]
45
+ end
46
+ alias_method :dart_struct_type, :dart_param_type
47
+
48
+ ##
49
+ # @param [FFIDB::Type] c_type
50
+ # @return [#to_s]
51
+ def ffi_param_type(c_type)
52
+ case
53
+ #when c_type.array? then # TODO: https://github.com/dart-lang/sdk/issues/35763
54
+ when c_type.enum? then :Int32
55
+ else TYPE_MAP_FFI[c_type.to_s] || TYPE_MAP_FFI['void *']
56
+ end
57
+ end
58
+ alias_method :ffi_struct_type, :ffi_param_type
59
+ end # Dart
60
+ end # FFIDB::Exporters
@@ -0,0 +1,16 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative 'c'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Go programming language (using Cgo).
8
+ #
9
+ # @see https://golang.org/cmd/cgo/
10
+ # @see https://github.com/golang/go/wiki/cgo
11
+ class Go < C
12
+ def finish
13
+ puts self.render_template('go.erb')
14
+ end
15
+ end # Go
16
+ end # FFIDB::Exporters
@@ -0,0 +1,3 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://wiki.haskell.org/Foreign_Function_Interface
@@ -0,0 +1,39 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Java programming language (using JNA).
8
+ #
9
+ # @see https://github.com/java-native-access/jna/blob/master/www/GettingStarted.md
10
+ class Java < FFIDB::Exporter
11
+ TYPE_MAP = ::YAML.load(File.read(File.expand_path("../../../etc/mappings/java.yaml", __dir__)))
12
+ .freeze
13
+
14
+ def begin_library(library)
15
+ if library
16
+ interface_name = self.options[:module] || library.name.capitalize
17
+ library.define_singleton_method(:interface_name) { interface_name }
18
+ end
19
+ super(library)
20
+ end
21
+
22
+ def finish
23
+ puts self.render_template('java.erb')
24
+ end
25
+
26
+ protected
27
+
28
+ ##
29
+ # @param [FFIDB::Type] c_type
30
+ # @return [#to_s]
31
+ def param_type(c_type)
32
+ case
33
+ when c_type.enum? then :int
34
+ else TYPE_MAP[c_type.to_s] || TYPE_MAP['void *']
35
+ end
36
+ end
37
+ alias_method :struct_type, :param_type
38
+ end # Java
39
+ end # FFIDB::Exporters
@@ -0,0 +1,38 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ require 'json'
6
+
7
+ module FFIDB::Exporters
8
+ ##
9
+ # Code generator for the JSON data interchange language.
10
+ class JSON < FFIDB::Exporter
11
+ def begin
12
+ # No header, because JSON doesn't support comments
13
+ @json = {}
14
+ end
15
+
16
+ def begin_library(library)
17
+ @library = library
18
+ @json[@library&.name] ||= {}
19
+ end
20
+
21
+ def export_symbol(symbol, **kwargs)
22
+ @json[@library&.name][symbol.name] = {kind: symbol.kind.to_s}.merge!(symbol.to_h)
23
+ end
24
+ alias_method :export_typedef, :export_symbol
25
+ alias_method :export_enum, :export_symbol
26
+ alias_method :export_struct, :export_symbol
27
+ alias_method :export_union, :export_symbol
28
+ alias_method :export_function, :export_symbol
29
+
30
+ def finish_library
31
+ @library = nil
32
+ end
33
+
34
+ def finish
35
+ puts ::JSON.pretty_generate(@json)
36
+ end
37
+ end # JSON
38
+ end # FFIDB::Exporters
@@ -0,0 +1,3 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/
@@ -0,0 +1,41 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Common Lisp programming language (using CFFI).
8
+ #
9
+ # @see https://common-lisp.net/project/cffi/
10
+ class Lisp < FFIDB::Exporter
11
+ TYPE_MAP = ::YAML.load(File.read(File.expand_path("../../../etc/mappings/lisp.yaml", __dir__)))
12
+ .transform_values(&:to_sym)
13
+ .freeze
14
+
15
+ def finish
16
+ puts self.render_template('lisp.erb')
17
+ end
18
+
19
+ protected
20
+
21
+ ##
22
+ # @param [FFIDB::Type] c_type
23
+ # @return [#inspect]
24
+ def struct_type(c_type)
25
+ case
26
+ when c_type.array? then [c_type.array_type.to_s.to_sym, :count, c_type.array_size]
27
+ else [self.param_type(c_type)]
28
+ end
29
+ end
30
+
31
+ ##
32
+ # @param [FFIDB::Type] c_type
33
+ # @return [#inspect]
34
+ def param_type(c_type)
35
+ case
36
+ when c_type.enum? then :int
37
+ else TYPE_MAP[c_type.to_s] || TYPE_MAP['void *']
38
+ end
39
+ end
40
+ end # Lisp
41
+ end # FFIDB::Exporters
@@ -0,0 +1,3 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://luajit.org/ext_ffi.html
@@ -0,0 +1,4 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://nim-lang.org/docs/manual.html#foreign-function-interface
4
+ # TODO: https://livebook.manning.com/book/nim-in-action/chapter-8/
@@ -0,0 +1,4 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://github.com/node-ffi/node-ffi
4
+ # TODO: https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial
@@ -0,0 +1,4 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://ocamlverse.github.io/content/ffi.html
4
+ # TODO: http://ocamllabs.io/ocaml-ctypes/PosixTypes.html
@@ -0,0 +1,4 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://wiki.php.net/rfc/ffi
4
+ # TODO: https://www.php.net/manual/en/book.ffi.php
@@ -0,0 +1,35 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Python programming language (using ctypes).
8
+ #
9
+ # @see https://docs.python.org/3/library/ctypes.html
10
+ class Python < FFIDB::Exporter
11
+ TYPE_MAP = ::YAML.load(File.read(File.expand_path("../../../etc/mappings/python.yaml", __dir__)))
12
+ .freeze
13
+
14
+ def finish
15
+ puts self.render_template('python.erb')
16
+ end
17
+
18
+ protected
19
+
20
+ ##
21
+ # @param [FFIDB::Type] c_type
22
+ # @return [#to_s]
23
+ def param_type(c_type)
24
+ case
25
+ when c_type.enum? then 'ctypes.c_int'
26
+ when c_type.array? then [self.param_type(c_type.array_type), '*', c_type.array_size].join(' ')
27
+ else case py_type = TYPE_MAP[c_type.to_s] || TYPE_MAP['void *']
28
+ when 'None' then py_type
29
+ else "ctypes.#{py_type}"
30
+ end
31
+ end
32
+ end
33
+ alias_method :struct_type, :param_type
34
+ end # Python
35
+ end # FFIDB::Exporters
@@ -0,0 +1,3 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://docs.racket-lang.org/foreign/intro.html
@@ -0,0 +1,33 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the Ruby programming language (using FFI).
8
+ #
9
+ # @see https://github.com/ffi/ffi/wiki
10
+ class Ruby < FFIDB::Exporter
11
+ TYPE_MAP = ::YAML.load(File.read(File.expand_path("../../../etc/mappings/ruby.yaml", __dir__)))
12
+ .transform_values(&:to_sym)
13
+ .freeze
14
+
15
+ def finish
16
+ puts self.render_template('ruby.erb')
17
+ end
18
+
19
+ protected
20
+
21
+ ##
22
+ # @param [FFIDB::Type] c_type
23
+ # @return [#inspect]
24
+ def param_type(c_type)
25
+ case
26
+ when c_type.enum? then :int
27
+ when c_type.array? then [self.param_type(c_type.array_type), c_type.array_size]
28
+ else TYPE_MAP[c_type.to_s] || TYPE_MAP['void *']
29
+ end
30
+ end
31
+ alias_method :struct_type, :param_type
32
+ end # Ruby
33
+ end # FFIDB::Exporters
@@ -0,0 +1,5 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ # TODO: https://doc.rust-lang.org/nomicon/ffi.html
4
+ # TODO: https://doc.rust-lang.org/1.0.0/book/ffi.html
5
+ # TODO: https://rust-embedded.github.io/book/interoperability/c-with-rust.html
@@ -0,0 +1,31 @@
1
+ # This is free and unencumbered software released into the public domain.
2
+
3
+ require_relative '../exporter'
4
+
5
+ module FFIDB::Exporters
6
+ ##
7
+ # Code generator for the YAML markup language.
8
+ class YAML < FFIDB::Exporter
9
+ def begin
10
+ puts "# #{FFIDB.header}" if self.header?
11
+ puts if self.header?
12
+ end
13
+
14
+ def begin_library(library) end
15
+
16
+ def export_symbol(symbol, **kwargs)
17
+ @counter ||= 0
18
+ puts unless @counter.zero?
19
+ puts "# #{symbol.instance_variable_get(:@debug)}" if self.debug? && symbol.instance_variable_get(:@debug)
20
+ puts symbol.to_yaml
21
+ @counter += 1
22
+ end
23
+ alias_method :export_typedef, :export_symbol
24
+ alias_method :export_enum, :export_symbol
25
+ alias_method :export_struct, :export_symbol
26
+ alias_method :export_union, :export_symbol
27
+ alias_method :export_function, :export_symbol
28
+
29
+ def finish_library() end
30
+ end # YAML
31
+ end # FFIDB::Exporters