c2ffi4rb 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/exe/c2ffi4rb +0 -1
- data/lib/c2ffi4rb/parser.rb +75 -76
- data/lib/c2ffi4rb/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a7511b48117f836d65991de99d5aeaf1a4dc5f4c9a9b99e4a9577fe415c941a
|
4
|
+
data.tar.gz: 3ee454048f080abae9a07ab3a11293d1af7a8f57518d6ae1ae12eaac6fd7d2ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b75a019a77528b7ceac118bc3108991c0cae5aba439ef330a1480fe6dd7390ce04e5780f7263dfab9dd626f98bf754166a9780272277267098e5e1871625d9fe
|
7
|
+
data.tar.gz: 3aa7cf6cf49094f75d9ff220c90e66edda3b80092fe96d087c1471b22f71d9d9c5b56a3f5bab914ec0db908222f90c7d0be26f2c9e6eac0a406b806b82f56936
|
data/README.md
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# c2ffi4rb
|
2
2
|
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/c2ffi4rb.svg)](https://badge.fury.io/rb/c2ffi4rb)
|
4
|
+
[![test](https://github.com/kojix2/c2ffi4rb/actions/workflows/ci.yml/badge.svg)](https://github.com/kojix2/c2ffi4rb/actions/workflows/ci.yml)
|
5
|
+
|
6
|
+
|
3
7
|
[c2ffi](https://github.com/rpav/c2ffi) - FFI binding generator - for Ruby
|
4
8
|
|
5
|
-
|
9
|
+
## installation
|
6
10
|
|
7
11
|
```sh
|
8
12
|
gem install c2ffi4rb
|
data/exe/c2ffi4rb
CHANGED
data/lib/c2ffi4rb/parser.rb
CHANGED
@@ -1,120 +1,119 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
4
|
+
|
3
5
|
module C2FFI4RB
|
4
6
|
class Parser
|
5
7
|
TYPE_TABLE = {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
}
|
8
|
+
':unsigned-int' => ':uint',
|
9
|
+
':unsigned-char' => ':uchar',
|
10
|
+
':unsigned-long' => ':ulong',
|
11
|
+
':function-pointer' => ':pointer'
|
12
|
+
}
|
11
13
|
|
12
14
|
def self.parse(arr)
|
13
15
|
Parser.new.parse(arr)
|
14
16
|
end
|
15
17
|
|
16
18
|
def initialize
|
17
|
-
@struct_type =
|
19
|
+
@struct_type = []
|
18
20
|
@toplevels = []
|
19
21
|
@anon_counter = 0
|
20
22
|
end
|
21
23
|
|
22
24
|
def parse(arr)
|
23
25
|
arr.each do |form|
|
24
|
-
|
25
|
-
@toplevels << s if s
|
26
|
+
parse_toplevel(form)
|
26
27
|
end
|
27
28
|
|
28
|
-
@toplevels.
|
29
|
-
puts
|
30
|
-
case t
|
31
|
-
when String
|
32
|
-
puts "#{t}"
|
33
|
-
when Array
|
34
|
-
t.each do |l|
|
35
|
-
puts "#{l}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
29
|
+
puts @toplevels.join("\n\n")
|
39
30
|
end
|
40
31
|
|
41
32
|
private
|
42
33
|
|
43
34
|
def parse_toplevel(form)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
35
|
+
lines = \
|
36
|
+
case form[:tag]
|
37
|
+
when 'typedef'
|
38
|
+
type = parse_type(form[:type])
|
39
|
+
|
40
|
+
# I don't think typedef works right with structs, so assign
|
41
|
+
if @struct_type.include?(type)
|
42
|
+
name = add_struct(form[:name])
|
43
|
+
"#{name} = #{type}"
|
44
|
+
else
|
45
|
+
"typedef #{type}, :#{form[:name]}"
|
46
|
+
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
48
|
+
when 'const'
|
49
|
+
type = parse_type(form[:type])
|
50
|
+
if type == ':string'
|
51
|
+
"#{form[:name].upcase} = \"#{form[:value]}\""
|
52
|
+
else
|
53
|
+
"#{form[:name].upcase} = #{form[:value]}"
|
54
|
+
end
|
63
55
|
|
64
|
-
|
65
|
-
|
66
|
-
|
56
|
+
when 'extern'
|
57
|
+
'attach_variable ' \
|
58
|
+
":#{form[:name]}, :#{form[:name]}, #{parse_type(form[:type])}"
|
67
59
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
60
|
+
when 'function'
|
61
|
+
l = []
|
62
|
+
l << "attach_function '#{form[:name]}', ["
|
63
|
+
form[:parameters].each do |f|
|
64
|
+
l << " #{parse_type(f[:type])},"
|
65
|
+
end
|
66
|
+
l << "], #{parse_type(form['return-type'.intern])}"
|
67
|
+
# emacs doesn't like :"foo" ---^
|
68
|
+
l.join("\n")
|
69
|
+
|
70
|
+
when 'struct', 'union'
|
71
|
+
make_struct(form)
|
72
|
+
|
73
|
+
when 'enum'
|
74
|
+
name = add_enum(form[:name])
|
75
|
+
l = []
|
76
|
+
l << "enum #{name}, ["
|
77
|
+
form[:fields].each do |f|
|
78
|
+
l << " :#{f[:name]}, #{f[:value]},"
|
79
|
+
end
|
80
|
+
l << ']'
|
81
|
+
l.join("\n")
|
73
82
|
end
|
74
|
-
s << "], #{parse_type(form['return-type'.intern])}"
|
75
|
-
# emacs doesn't like :"foo" ---^
|
76
83
|
|
77
|
-
|
78
|
-
|
79
|
-
make_struct(form)
|
80
|
-
|
81
|
-
when 'enum'
|
82
|
-
name = add_enum(form[:name])
|
83
|
-
s = []
|
84
|
-
s << "enum #{name}, ["
|
85
|
-
form[:fields].each do |f|
|
86
|
-
s << " :#{f[:name]}, #{f[:value]},"
|
87
|
-
end
|
88
|
-
s << ']'
|
89
|
-
end
|
84
|
+
@toplevels << lines
|
85
|
+
nil
|
90
86
|
end
|
91
87
|
|
92
88
|
def add_struct(name)
|
89
|
+
# Anonymous structs are given a name
|
93
90
|
if name == ''
|
94
91
|
@anon_counter += 1
|
95
|
-
name =
|
92
|
+
name = "Anon_Type_#{@anon_counter}"
|
96
93
|
return name
|
97
94
|
end
|
98
95
|
|
96
|
+
# Do not allow names that start with an underscore
|
99
97
|
name = 'C' + name if name.start_with? '_'
|
100
98
|
|
99
|
+
# Convert snake_case to CamelCase
|
101
100
|
name = name.capitalize.gsub!(/_([a-z])/) { |m| "_#{m[1].upcase}" }
|
102
|
-
|
101
|
+
|
102
|
+
@struct_type << name unless @struct_type.include? name
|
103
103
|
name
|
104
104
|
end
|
105
105
|
|
106
106
|
def add_enum(name)
|
107
|
+
# Anonymous enums are given a name
|
107
108
|
if name == ''
|
108
109
|
@anon_counter += 1
|
109
110
|
name = ':anon_type_' + @anon_counter.to_s
|
110
111
|
return name
|
111
112
|
end
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
name
|
117
|
-
end
|
114
|
+
# All enums are prefixed with a colon
|
115
|
+
name = ":#{name}" unless name.start_with? ':'
|
116
|
+
name
|
118
117
|
end
|
119
118
|
|
120
119
|
def make_struct(form)
|
@@ -126,19 +125,19 @@ module C2FFI4RB
|
|
126
125
|
'FFI::Union'
|
127
126
|
end
|
128
127
|
|
129
|
-
|
130
|
-
|
128
|
+
l = []
|
129
|
+
l << "class #{name} < #{type}"
|
131
130
|
|
132
131
|
if form[:fields].length.positive?
|
133
|
-
|
132
|
+
l << ' layout \\'
|
134
133
|
size = form[:fields].length
|
135
|
-
sep = ','
|
136
134
|
form[:fields].each_with_index do |f, i|
|
137
|
-
sep =
|
138
|
-
|
135
|
+
sep = i >= (size - 1) ? '' : ','
|
136
|
+
l << " :#{f[:name]}, #{parse_type(f[:type])}#{sep}"
|
139
137
|
end
|
140
138
|
end
|
141
|
-
|
139
|
+
l << 'end'
|
140
|
+
l.join("\n")
|
142
141
|
end
|
143
142
|
|
144
143
|
def parse_type(form)
|
@@ -150,8 +149,8 @@ module C2FFI4RB
|
|
150
149
|
pointee = parse_type(form[:type])
|
151
150
|
if [':char', ':uchar'].include?(pointee)
|
152
151
|
':string'
|
153
|
-
elsif @struct_type
|
154
|
-
"#{
|
152
|
+
elsif @struct_type.include?(pointee)
|
153
|
+
"#{pointee}.ptr"
|
155
154
|
else
|
156
155
|
':pointer'
|
157
156
|
end
|
data/lib/c2ffi4rb/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: c2ffi4rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
8
8
|
- Ryan Pavlik
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-09-
|
12
|
+
date: 2023-09-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -71,7 +71,7 @@ homepage: https://github.com/kojix2/c2ffi4rb
|
|
71
71
|
licenses:
|
72
72
|
- LGPL-2
|
73
73
|
metadata: {}
|
74
|
-
post_install_message:
|
74
|
+
post_install_message:
|
75
75
|
rdoc_options: []
|
76
76
|
require_paths:
|
77
77
|
- lib
|
@@ -86,8 +86,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
requirements: []
|
89
|
-
rubygems_version: 3.4.
|
90
|
-
signing_key:
|
89
|
+
rubygems_version: 3.4.14
|
90
|
+
signing_key:
|
91
91
|
specification_version: 4
|
92
92
|
summary: C2FFI for Ruby-FFI
|
93
93
|
test_files: []
|