c2ffi4rb 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -6
- data/exe/c2ffi4rb +16 -4
- data/lib/c2ffi4rb/bind_gen.rb +246 -0
- data/lib/c2ffi4rb/version.rb +1 -1
- data/lib/c2ffi4rb.rb +1 -1
- metadata +4 -4
- data/lib/c2ffi4rb/parser.rb +0 -187
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06ea739a36f2f4a6485ba3e65b6e91724eafed7f7440df1d26e7dfb5d5290897
|
4
|
+
data.tar.gz: 2eaf74991d02fd8b6e5beae79150cc1b40f5178c4bb27cf1277bf1bae0c744f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdc2f8439c2722a83b3a82aac50821d4bf4f9be35efa52e30202e44417ab29b3a203896ddc955e0046637667d50751a354902955df92560c22a4b74a9939fc61
|
7
|
+
data.tar.gz: 5bb0f1ba5929c3ba8dbc4ca176701fddc05a3fb836ac218a1606b935335af035972354cfb4ba0950f5a19daf04457486801fca9ea868685070c1134b90e6938b
|
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/c2ffi4rb.svg)](https://badge.fury.io/rb/c2ffi4rb)
|
4
4
|
[![test](https://github.com/kojix2/c2ffi4rb/actions/workflows/ci.yml/badge.svg)](https://github.com/kojix2/c2ffi4rb/actions/workflows/ci.yml)
|
5
5
|
|
6
|
-
|
7
6
|
[c2ffi](https://github.com/rpav/c2ffi) - FFI binding generator - for Ruby
|
8
7
|
|
9
8
|
## installation
|
@@ -14,21 +13,29 @@ gem install c2ffi4rb
|
|
14
13
|
|
15
14
|
## Usage
|
16
15
|
|
17
|
-
First, produce a `spec` file using `c2ffi
|
16
|
+
First, produce a `spec` file using `c2ffi`.
|
18
17
|
|
19
18
|
```sh
|
20
19
|
c2ffi -M macros.h -o example.json example.h
|
21
|
-
c2ffi -o macros.json macros.h
|
20
|
+
c2ffi -o macros.json example.h macros.h
|
22
21
|
```
|
23
22
|
|
24
|
-
|
25
|
-
`c2ffi-ruby`, as follows:
|
23
|
+
Next, use c2ffi4rb to generate ruby code.
|
26
24
|
|
27
25
|
```sh
|
28
26
|
c2ffi4rb example.json macro.json > simple.rb
|
29
27
|
```
|
30
28
|
|
31
|
-
|
29
|
+
Finally, improve simple.rb manually to complete the binding.
|
30
|
+
|
31
|
+
## Development
|
32
|
+
|
33
|
+
To run tests, install [c2ffi][c2ffi], [Cairo][cairo], and [pkg-config][pkg-config] in advance.
|
34
|
+
Then execute `rake test`.
|
35
|
+
|
36
|
+
[cairo]: https://www.cairographics.org/ "Cairo"
|
37
|
+
[pkg-config]: https://www.freedesktop.org/wiki/Software/pkg-config/ "freedesktop.org"
|
38
|
+
[c2ffi]: https://github.com/rpav/c2ffi "GitHub"
|
32
39
|
|
33
40
|
## Licence
|
34
41
|
|
data/exe/c2ffi4rb
CHANGED
@@ -8,16 +8,28 @@
|
|
8
8
|
require 'optparse'
|
9
9
|
require 'c2ffi4rb'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
Version = C2FFI4RB::VERSION # Fixme
|
11
|
+
type_table = {}
|
14
12
|
|
15
13
|
opts = OptionParser.new
|
16
14
|
opts.banner = 'Usage: c2ffi4rb [options] [file1, file2, ...]'
|
15
|
+
opts.on('-t FILE', '--table FILE', 'Type conversion table TSV') do |file|
|
16
|
+
File.open(file) do |io|
|
17
|
+
io.each_line do |line|
|
18
|
+
next if line =~ /^#/
|
19
|
+
|
20
|
+
from, to = line.chomp.split("\t")
|
21
|
+
type_table[from] = to
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
17
25
|
opts.on('-h', '--help', 'Show this message') do
|
18
26
|
puts opts
|
19
27
|
exit
|
20
28
|
end
|
29
|
+
opts.on('-v', '--version', 'Show version') do
|
30
|
+
puts C2FFI4RB::VERSION
|
31
|
+
exit
|
32
|
+
end
|
21
33
|
opts.parse!
|
22
34
|
|
23
35
|
if ARGV.empty?
|
@@ -32,4 +44,4 @@ ARGV.each do |file|
|
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
35
|
-
C2FFI4RB::
|
47
|
+
C2FFI4RB::BindGen.new(type_table).generate_bindings(spec)
|
@@ -0,0 +1,246 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module C2FFI4RB
|
6
|
+
class BindGen
|
7
|
+
DEFAULT_TYPE_TABLE = {
|
8
|
+
':signed-int' => ':int',
|
9
|
+
':unsigned-int' => ':uint',
|
10
|
+
':signed-char' => ':char',
|
11
|
+
':unsigned-char' => ':uchar',
|
12
|
+
':signed-short' => ':short',
|
13
|
+
':unsigned-short' => ':ushort',
|
14
|
+
':long-long' => ':long_long',
|
15
|
+
':ulong-long' => ':ulong_long',
|
16
|
+
':long-double' => ':long_double',
|
17
|
+
':signed-long' => ':long',
|
18
|
+
':unsigned-long' => ':ulong',
|
19
|
+
':unsigned-long-long' => ':ulong_long',
|
20
|
+
':function-pointer' => ':pointer'
|
21
|
+
}
|
22
|
+
|
23
|
+
def self.generate_bindings(arr)
|
24
|
+
new.generate_bindings(arr)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(type_table = {})
|
28
|
+
@type_table = DEFAULT_TYPE_TABLE.merge(type_table)
|
29
|
+
@struct_type = []
|
30
|
+
@toplevels = []
|
31
|
+
@anon_counter = 0
|
32
|
+
@anon_enum_ids = []
|
33
|
+
@typedefs = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_bindings(arr)
|
37
|
+
arr.each { |form| process_toplevel(form) }
|
38
|
+
puts @toplevels.join("\n\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def process_toplevel(form)
|
44
|
+
lines = parse_form(form)
|
45
|
+
@toplevels << lines
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_form(form)
|
49
|
+
case form[:tag]
|
50
|
+
when 'typedef' then generate_typedef(form)
|
51
|
+
when 'const' then generate_const(form)
|
52
|
+
when 'extern' then generate_extern(form)
|
53
|
+
when 'function' then generate_function(form)
|
54
|
+
when 'struct', 'union' then generate_struct_or_union(form)
|
55
|
+
when 'enum' then generate_enum(form)
|
56
|
+
else
|
57
|
+
raise "Unknown form: #{form[:tag]}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_typedef(form)
|
62
|
+
type = resolve_type(form[:type])
|
63
|
+
if @struct_type.include?(type)
|
64
|
+
name = define_struct(form[:name])
|
65
|
+
if name == type
|
66
|
+
"# #{name} = #{type}"
|
67
|
+
else
|
68
|
+
"#{name} = #{type}"
|
69
|
+
end
|
70
|
+
elsif type == ":{#{form[:name]}}"
|
71
|
+
warn "Ignoring self-referential typedef #{form[:name]}"
|
72
|
+
else
|
73
|
+
if @typedefs.has_key?(form[:name])
|
74
|
+
return "# typedef already defined? #{form[:name]}" if @typedefs[form[:name]] == type
|
75
|
+
|
76
|
+
warn "# Redefinition of #{form[:name]} from #{@typedefs[form[:name]]} to #{type}"
|
77
|
+
|
78
|
+
end
|
79
|
+
"typedef :pointer, :#{form[:name]} # #{type}" if form[:type][:tag] == ':array'
|
80
|
+
@typedefs[form[:name]] = type
|
81
|
+
"typedef #{type}, :#{form[:name]}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_const(form)
|
86
|
+
type = resolve_type(form[:type])
|
87
|
+
value = type == ':string' ? "\"#{form[:value]}\"" : form[:value]
|
88
|
+
"#{form[:name].upcase} = #{value}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate_extern(form)
|
92
|
+
"attach_variable :#{form[:name]}, :#{form[:name]}, #{resolve_type(form[:type])}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def generate_function(form)
|
96
|
+
params = form[:parameters].map do |f|
|
97
|
+
f[:type][:tag] == ':array' ? " :pointer, # #{resolve_type(f[:type])}" : " #{resolve_type(f[:type])},"
|
98
|
+
end.join("\n")
|
99
|
+
<<~FUNCTION
|
100
|
+
attach_function '#{form[:name]}', [
|
101
|
+
#{params}
|
102
|
+
], #{resolve_type(form[:'return-type'])}
|
103
|
+
FUNCTION
|
104
|
+
end
|
105
|
+
|
106
|
+
def generate_struct_or_union(form)
|
107
|
+
create_struct_definition(form)
|
108
|
+
end
|
109
|
+
|
110
|
+
def generate_enum(form)
|
111
|
+
id = form[:id]
|
112
|
+
if form[:name].empty?
|
113
|
+
return "# Already defined? anon_type_#{id}" if @anon_enum_ids.include?(id)
|
114
|
+
|
115
|
+
@anon_enum_ids << id
|
116
|
+
end
|
117
|
+
name = normalize_enum_name(form[:name], form[:id])
|
118
|
+
fields = form[:fields].map { |f| " :#{f[:name]}, #{f[:value]}," }.join("\n")
|
119
|
+
<<~ENUM
|
120
|
+
enum #{name}, [
|
121
|
+
#{fields}
|
122
|
+
]
|
123
|
+
ENUM
|
124
|
+
end
|
125
|
+
|
126
|
+
def normalize_struct_name(name)
|
127
|
+
# Anonymous structs are given a name
|
128
|
+
if name.empty?
|
129
|
+
@anon_counter += 1
|
130
|
+
name = "Anon_Type_#{@anon_counter}"
|
131
|
+
return name
|
132
|
+
end
|
133
|
+
|
134
|
+
# Do not allow names that start with an underscore
|
135
|
+
name = 'C' + name if name.start_with?('_')
|
136
|
+
|
137
|
+
# Convert snake_case to CamelCase
|
138
|
+
name = name[0].upcase + name[1..-1]
|
139
|
+
|
140
|
+
name.gsub!(/_([a-z])/) { |m| "#{m[1].upcase}" }
|
141
|
+
|
142
|
+
name
|
143
|
+
end
|
144
|
+
|
145
|
+
def register_struct(name)
|
146
|
+
if @struct_type.include? name
|
147
|
+
false
|
148
|
+
else
|
149
|
+
@struct_type << name
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def normalize_enum_name(name, id)
|
154
|
+
# Anonymous enums are given a name
|
155
|
+
name = "anon_enum_#{id}" if name.empty?
|
156
|
+
|
157
|
+
# All enums are prefixed with a colon
|
158
|
+
name = ":#{name}" unless name.start_with?(':')
|
159
|
+
name
|
160
|
+
end
|
161
|
+
|
162
|
+
def define_struct(name)
|
163
|
+
name = normalize_struct_name(name)
|
164
|
+
register_struct(name)
|
165
|
+
name
|
166
|
+
end
|
167
|
+
|
168
|
+
def create_struct_definition(form)
|
169
|
+
name = normalize_struct_name(form[:name])
|
170
|
+
# FIXME: This is a hack to avoid redefining structs
|
171
|
+
return "# Already defined? #{name}" if @struct_type.include?(name)
|
172
|
+
|
173
|
+
register_struct(name)
|
174
|
+
|
175
|
+
# FIXME: :FFI::Struct or FFI::Struct
|
176
|
+
type = form[:tag] == 'struct' ? '::FFI::Struct' : '::FFI::Union'
|
177
|
+
|
178
|
+
lines = ["class #{name} < #{type}"]
|
179
|
+
|
180
|
+
if form[:fields].any?
|
181
|
+
lines << ' layout \\'
|
182
|
+
anon_field_counter = 0
|
183
|
+
|
184
|
+
form[:fields].each_with_index do |f, i|
|
185
|
+
field_name = f[:name].empty? ? "anon_field_#{anon_field_counter}" : f[:name]
|
186
|
+
anon_field_counter += 1 if f[:name].empty?
|
187
|
+
|
188
|
+
sep = i == form[:fields].size - 1 ? '' : ','
|
189
|
+
lines << " :#{field_name}, #{resolve_type(f[:type])}#{sep}"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
lines << 'end'
|
194
|
+
lines.join("\n")
|
195
|
+
end
|
196
|
+
|
197
|
+
def resolve_type(form)
|
198
|
+
@type_table.fetch(form[:tag]) do
|
199
|
+
case form[:tag]
|
200
|
+
when ':pointer' then resolve_pointer_type(form)
|
201
|
+
when ':array' then resolve_array_type(form)
|
202
|
+
when ':struct', ':union' then define_struct(form[:name])
|
203
|
+
when ':enum' then normalize_enum_name(form[:name], form[:id])
|
204
|
+
when 'struct', 'union' then define_struct_or_union_type(form)
|
205
|
+
when 'enum' then normalize_enum_name_type(form)
|
206
|
+
else resolve_default_type(form)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def resolve_pointer_type(form)
|
212
|
+
pointee = resolve_type(form[:type])
|
213
|
+
if [':char', ':uchar'].include?(pointee)
|
214
|
+
':string'
|
215
|
+
elsif @struct_type.include?(pointee)
|
216
|
+
"#{pointee}.ptr"
|
217
|
+
else
|
218
|
+
':pointer'
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def resolve_array_type(form)
|
223
|
+
"[#{resolve_type(form[:type])}, #{form[:size]}]"
|
224
|
+
end
|
225
|
+
|
226
|
+
def normalize_enum_name_type(form)
|
227
|
+
form[:name] = normalize_enum_name(form[:name], form[:id])
|
228
|
+
process_toplevel(form)
|
229
|
+
form[:name]
|
230
|
+
end
|
231
|
+
|
232
|
+
def define_struct_or_union_type(form)
|
233
|
+
form[:name] = normalize_struct_name(form[:name])
|
234
|
+
process_toplevel(form)
|
235
|
+
form[:name]
|
236
|
+
end
|
237
|
+
|
238
|
+
def resolve_default_type(form)
|
239
|
+
## FIXME
|
240
|
+
st_name = normalize_struct_name(form[:tag])
|
241
|
+
return st_name if @struct_type.include?(st_name)
|
242
|
+
|
243
|
+
form[:tag].start_with?(':') ? form[:tag] : ":#{form[:tag]}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
data/lib/c2ffi4rb/version.rb
CHANGED
data/lib/c2ffi4rb.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-09-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -65,7 +65,7 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- exe/c2ffi4rb
|
67
67
|
- lib/c2ffi4rb.rb
|
68
|
-
- lib/c2ffi4rb/
|
68
|
+
- lib/c2ffi4rb/bind_gen.rb
|
69
69
|
- lib/c2ffi4rb/version.rb
|
70
70
|
homepage: https://github.com/kojix2/c2ffi4rb
|
71
71
|
licenses:
|
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
requirements: []
|
89
|
-
rubygems_version: 3.
|
89
|
+
rubygems_version: 3.5.11
|
90
90
|
signing_key:
|
91
91
|
specification_version: 4
|
92
92
|
summary: C2FFI for Ruby-FFI
|
data/lib/c2ffi4rb/parser.rb
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module C2FFI4RB
|
6
|
-
class Parser
|
7
|
-
TYPE_TABLE = {
|
8
|
-
':unsigned-int' => ':uint',
|
9
|
-
':unsigned-char' => ':uchar',
|
10
|
-
':unsigned-long' => ':ulong',
|
11
|
-
':function-pointer' => ':pointer'
|
12
|
-
}
|
13
|
-
|
14
|
-
def self.parse(arr)
|
15
|
-
Parser.new.parse(arr)
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@struct_type = []
|
20
|
-
@toplevels = []
|
21
|
-
@anon_counter = 0
|
22
|
-
end
|
23
|
-
|
24
|
-
def parse(arr)
|
25
|
-
arr.each do |form|
|
26
|
-
parse_toplevel(form)
|
27
|
-
end
|
28
|
-
|
29
|
-
puts @toplevels.join("\n\n")
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def parse_toplevel(form)
|
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
|
47
|
-
|
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
|
55
|
-
|
56
|
-
when 'extern'
|
57
|
-
'attach_variable ' \
|
58
|
-
":#{form[:name]}, :#{form[:name]}, #{parse_type(form[:type])}"
|
59
|
-
|
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")
|
82
|
-
end
|
83
|
-
|
84
|
-
@toplevels << lines
|
85
|
-
nil
|
86
|
-
end
|
87
|
-
|
88
|
-
def add_struct(name)
|
89
|
-
# Anonymous structs are given a name
|
90
|
-
if name == ''
|
91
|
-
@anon_counter += 1
|
92
|
-
name = "Anon_Type_#{@anon_counter}"
|
93
|
-
return name
|
94
|
-
end
|
95
|
-
|
96
|
-
# Do not allow names that start with an underscore
|
97
|
-
name = 'C' + name if name.start_with? '_'
|
98
|
-
|
99
|
-
# Convert snake_case to CamelCase
|
100
|
-
name = name.capitalize.gsub!(/_([a-z])/) { |m| "_#{m[1].upcase}" }
|
101
|
-
|
102
|
-
@struct_type << name unless @struct_type.include? name
|
103
|
-
name
|
104
|
-
end
|
105
|
-
|
106
|
-
def add_enum(name)
|
107
|
-
# Anonymous enums are given a name
|
108
|
-
if name == ''
|
109
|
-
@anon_counter += 1
|
110
|
-
name = ':anon_type_' + @anon_counter.to_s
|
111
|
-
return name
|
112
|
-
end
|
113
|
-
|
114
|
-
# All enums are prefixed with a colon
|
115
|
-
name = ":#{name}" unless name.start_with? ':'
|
116
|
-
name
|
117
|
-
end
|
118
|
-
|
119
|
-
def make_struct(form)
|
120
|
-
name = add_struct(form[:name])
|
121
|
-
|
122
|
-
type = if form[:tag] == ':struct'
|
123
|
-
'FFI::Struct'
|
124
|
-
else
|
125
|
-
'FFI::Union'
|
126
|
-
end
|
127
|
-
|
128
|
-
l = []
|
129
|
-
l << "class #{name} < #{type}"
|
130
|
-
|
131
|
-
if form[:fields].length.positive?
|
132
|
-
l << ' layout \\'
|
133
|
-
size = form[:fields].length
|
134
|
-
form[:fields].each_with_index do |f, i|
|
135
|
-
sep = i >= (size - 1) ? '' : ','
|
136
|
-
l << " :#{f[:name]}, #{parse_type(f[:type])}#{sep}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
l << 'end'
|
140
|
-
l.join("\n")
|
141
|
-
end
|
142
|
-
|
143
|
-
def parse_type(form)
|
144
|
-
tt = TYPE_TABLE[form[:tag]]
|
145
|
-
return tt if tt
|
146
|
-
|
147
|
-
case form[:tag]
|
148
|
-
when ':pointer'
|
149
|
-
pointee = parse_type(form[:type])
|
150
|
-
if [':char', ':uchar'].include?(pointee)
|
151
|
-
':string'
|
152
|
-
elsif @struct_type.include?(pointee)
|
153
|
-
"#{pointee}.ptr"
|
154
|
-
else
|
155
|
-
':pointer'
|
156
|
-
end
|
157
|
-
|
158
|
-
when ':array'
|
159
|
-
"[#{parse_type(form[:type])}, #{form[:size]}]"
|
160
|
-
|
161
|
-
when ':struct', ':union'
|
162
|
-
add_struct(form[:name])
|
163
|
-
|
164
|
-
when ':enum'
|
165
|
-
add_enum(form[:name])
|
166
|
-
|
167
|
-
when 'enum'
|
168
|
-
form[:name] = add_enum(form[:name])
|
169
|
-
parse_toplevel(form)
|
170
|
-
form[:name]
|
171
|
-
|
172
|
-
when 'struct', 'union'
|
173
|
-
form[:name] = add_struct(form[:name])
|
174
|
-
parse_toplevel(form)
|
175
|
-
form[:name]
|
176
|
-
|
177
|
-
else
|
178
|
-
# All non-Classy types are :-prefixed?
|
179
|
-
if form[:tag][0] != ':'
|
180
|
-
":#{form[:tag]}"
|
181
|
-
else
|
182
|
-
form[:tag]
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|