ffi-swig-generator 0.2.1 → 0.3.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 (89) hide show
  1. data/.hg/branch.cache +2 -0
  2. data/.hg/dirstate +0 -0
  3. data/.hg/store/00changelog.i +0 -0
  4. data/.hg/store/00manifest.i +0 -0
  5. data/.hg/store/data/.hgignore.i +0 -0
  6. data/.hg/store/data/.hgtags.i +0 -0
  7. data/.hg/store/data/_history.txt.i +0 -0
  8. data/.hg/store/data/_r_e_a_d_m_e.rdoc.i +0 -0
  9. data/.hg/store/data/_rakefile.i +0 -0
  10. data/.hg/store/data/cucumber.yml.i +0 -0
  11. data/.hg/store/data/examples/_rakefile.i +0 -0
  12. data/.hg/store/data/features/generate.feature.i +0 -0
  13. data/.hg/store/data/features/step__definitions/generate.rb.i +0 -0
  14. data/.hg/store/data/features/support/env.rb.i +0 -0
  15. data/.hg/store/data/features/support/results.rb.i +0 -0
  16. data/.hg/store/data/features/support/templates.rb.i +0 -0
  17. data/.hg/store/data/lib/ffi-swig-generator.rb.i +0 -0
  18. data/.hg/store/data/lib/generator/application.rb.i +0 -0
  19. data/.hg/store/data/lib/generator/constant.rb.i +0 -0
  20. data/.hg/store/data/lib/generator/enum.rb.i +0 -0
  21. data/.hg/store/data/lib/generator/function.rb.i +0 -0
  22. data/.hg/store/data/lib/generator/generator.rb.i +0 -0
  23. data/.hg/store/data/lib/generator/generatortask.rb.i +0 -0
  24. data/.hg/store/data/lib/generator/logger.rb.i +0 -0
  25. data/.hg/store/data/lib/generator/node.rb.i +0 -0
  26. data/.hg/store/data/lib/generator/parser.rb.i +0 -0
  27. data/.hg/store/data/lib/generator/struct.rb.i +0 -0
  28. data/.hg/store/data/lib/generator/type.rb.i +0 -0
  29. data/.hg/store/data/lib/generator/types.rb.i +0 -0
  30. data/.hg/store/data/spec/generator/constant__spec.rb.i +0 -0
  31. data/.hg/store/data/spec/generator/enum__spec.rb.i +0 -0
  32. data/.hg/store/data/spec/generator/function__spec.rb.i +0 -0
  33. data/.hg/store/data/spec/generator/generator__spec.rb.i +0 -0
  34. data/.hg/store/data/spec/generator/node__spec.rb.i +0 -0
  35. data/.hg/store/data/spec/generator/parser__spec.rb.i +0 -0
  36. data/.hg/store/data/spec/generator/struct__spec.rb.i +0 -0
  37. data/.hg/store/data/spec/generator/swig/constants.i.i +0 -0
  38. data/.hg/store/data/spec/generator/swig/functions.i.i +0 -0
  39. data/.hg/store/data/spec/generator/swig/testlib.i.i +0 -0
  40. data/.hg/store/data/spec/generator/swig/typedefs.i.i +0 -0
  41. data/.hg/store/data/spec/generator/swig/types.i.i +0 -0
  42. data/.hg/store/data/spec/generator/type__spec.rb.i +0 -0
  43. data/.hg/store/data/spec/spec__helper.rb.i +0 -0
  44. data/.hg/store/data/tasks/cucumber.rake.i +0 -0
  45. data/.hg/store/undo +0 -0
  46. data/.hg/undo.dirstate +0 -0
  47. data/.hgignore +3 -0
  48. data/.hgtags +1 -0
  49. data/History.txt +22 -2
  50. data/README.rdoc +26 -22
  51. data/Rakefile +2 -3
  52. data/cucumber.yml +1 -0
  53. data/examples/Rakefile +5 -3
  54. data/examples/generated/libc_wrap.rb +18 -0
  55. data/examples/generated/libc_wrap.xml +597 -0
  56. data/examples/generated/wiiuse_wrap.rb +322 -0
  57. data/examples/generated/wiiuse_wrap.xml +9025 -0
  58. data/features/generate.feature +45 -0
  59. data/features/step_definitions/generate.rb +32 -0
  60. data/features/support/env.rb +4 -0
  61. data/features/support/templates.rb +381 -0
  62. data/lib/ffi-swig-generator.rb +1 -1
  63. data/lib/generator/application.rb +1 -1
  64. data/lib/generator/constant.rb +24 -0
  65. data/lib/generator/enum.rb +38 -0
  66. data/lib/generator/function.rb +71 -0
  67. data/lib/generator/generatortask.rb +21 -9
  68. data/lib/generator/logger.rb +29 -0
  69. data/lib/generator/node.rb +19 -0
  70. data/lib/generator/parser.rb +168 -0
  71. data/lib/generator/struct.rb +76 -0
  72. data/lib/generator/type.rb +128 -0
  73. data/lib/generator/types.rb +36 -0
  74. data/spec/generator/constant_spec.rb +17 -0
  75. data/spec/generator/enum_spec.rb +29 -0
  76. data/spec/generator/function_spec.rb +66 -0
  77. data/spec/generator/parser_spec.rb +250 -0
  78. data/spec/generator/struct_spec.rb +77 -0
  79. data/spec/generator/swig/constants.i +5 -0
  80. data/spec/generator/swig/functions.i +8 -0
  81. data/spec/generator/swig/testlib.i +42 -0
  82. data/spec/generator/swig/typedefs.i +1 -0
  83. data/spec/generator/swig/types.i +1 -0
  84. data/spec/generator/type_spec.rb +38 -0
  85. data/spec/spec_helper.rb +6 -0
  86. data/tasks/cucumber.rake +8 -0
  87. metadata +58 -18
  88. data/lib/generator/generator.rb +0 -344
  89. data/spec/generator/generator_spec.rb +0 -248
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ include FFI
4
+
5
+ describe Generator::Struct do
6
+ it_should_behave_like 'All specs'
7
+ before :all do
8
+ @node = generate_xml_wrap_from('structs')
9
+ end
10
+ it 'should properly generate the layout of a FFI::Struct class' do
11
+ Generator::Struct.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
12
+ class TestStruct1 < FFI::Struct
13
+ layout(
14
+ :i, :int,
15
+ :c, :char,
16
+ :s, :pointer,
17
+ :a, [:char, 5]
18
+ )
19
+ def s=(str)
20
+ @s = FFI::MemoryPointer.from_string(str)
21
+ self[:s] = @s
22
+ end
23
+ def s
24
+ @s.get_string(0)
25
+ end
26
+
27
+ end
28
+ EOC
29
+
30
+ end
31
+ it 'should properly generate the layout of a FFI::Struct containing pointer field' do
32
+ Generator::Struct.new(:node => (@node / 'class')[1]).to_s.should == <<EOC
33
+ class TestStruct2 < FFI::Struct
34
+ layout(
35
+ :ptr, :pointer
36
+ )
37
+ end
38
+ EOC
39
+ end
40
+ it 'should properly generate the layout of a FFI::Struct containing array field' do
41
+ Generator::Struct.new(:node => (@node / 'class')[2]).to_s.should == <<EOC
42
+ class TestStruct3 < FFI::Struct
43
+ layout(
44
+ :c, [:char, 5]
45
+ )
46
+ end
47
+ EOC
48
+
49
+ end
50
+ it 'should properly generate the layout of a FFI::Struct containing array field' do
51
+ Generator::Struct.new(:node => (@node / 'class')[3]).to_s.should == <<EOC
52
+ class TestStruct4 < FFI::Struct
53
+ layout(
54
+ :s, [TestStruct3, 5]
55
+ )
56
+ end
57
+ EOC
58
+
59
+ end
60
+ end
61
+
62
+ describe Generator::Union do
63
+ it_should_behave_like 'All specs'
64
+ before :all do
65
+ @node = generate_xml_wrap_from('unions')
66
+ end
67
+ it 'should properly generate the layout of a FFI::Union class' do
68
+ Generator::Union.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
69
+ class UnionT < FFI::Union
70
+ layout(
71
+ :c, :char,
72
+ :f, :float
73
+ )
74
+ end
75
+ EOC
76
+ end
77
+ end
@@ -1,3 +1,8 @@
1
1
  %module constant_wrap
2
2
 
3
3
  #define CONST_1 0x10
4
+ #define CONST_2 1234U
5
+ #define CONST_3 1234L
6
+ #define CONST_4 1234UL
7
+
8
+
@@ -19,6 +19,14 @@ void func_12(void (*callback)(float));
19
19
  void func_13(int (*callback)(double, float));
20
20
  void func_14(void (*callback)(char* str));
21
21
  void func_15(void (*callback)(void));
22
+ const char* func_16();
23
+ const unsigned char * func_17();
24
+ void func_18(...);
25
+ volatile void func_19(volatile int value);
26
+ void func_20(void *p1, void (*callback)(const char* str, void *p2, void *p3 ), void *p4);
27
+ void func_21(void *p1, void (*callback)(const unsigned char uc, void *p2, void *p3 ), void *p4);
28
+
29
+
22
30
 
23
31
 
24
32
 
@@ -24,18 +24,60 @@ struct test_struct {
24
24
  byte b;
25
25
  };
26
26
 
27
+ struct CamelCaseStruct {
28
+ int i;
29
+ char c;
30
+ byte b;
31
+ };
32
+
27
33
  typedef struct {
28
34
  char c;
29
35
  } test_struct_3;
30
36
 
31
37
  typedef void (*cb)(char*, char*);
38
+ typedef void * (*cb_2)(char*, const char *);
39
+ typedef CamelCaseStruct (*cb_3)(char*, CamelCaseStruct);
32
40
 
33
41
  struct test_struct_2 {
34
42
  struct test_struct s;
43
+ CamelCaseStruct camel_case_struct;
35
44
  test_struct_3 s_3;
36
45
  enum_t e;
37
46
  cb func;
38
47
  union_t u;
48
+ cb callback;
49
+ void (*inline_callback)();
50
+ };
51
+
52
+ // struct with getter/setter method for strings and callbacks
53
+
54
+ struct _test_struct_4 {
55
+ char* string;
56
+ void (*inline_callback)();
57
+ };
58
+
59
+ struct test_struct_5 {
60
+ int i;
61
+ union {
62
+ struct {
63
+ int a;
64
+ int b;
65
+ } nested_struct_field_1;
66
+ struct {
67
+ int c;
68
+ int d;
69
+ } nested_struct_field_2;
70
+ struct {
71
+ int e;
72
+ int f;
73
+ } nested_struct_field_3;
74
+ union {
75
+ long l;
76
+ long long ll;
77
+ } union_field;
78
+ float f;
79
+ } big_union_field;
80
+ char c;
39
81
  };
40
82
 
41
83
  int get_int(struct test_struct* s);
@@ -3,3 +3,4 @@
3
3
  typedef unsigned char byte;
4
4
  byte b;
5
5
  typedef int *(PTF)(char*, char*)
6
+
@@ -38,6 +38,7 @@ signed long long sll;
38
38
  signed long long int slli;
39
39
  signed short ss;
40
40
  signed short int ssi;
41
+ size_t sizet;
41
42
  unsigned char uc;
42
43
  unsigned int ui;
43
44
  unsigned long ul;
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+ include FFI
3
+
4
+ describe Generator::Type do
5
+ it_should_behave_like 'All specs'
6
+ before :all do
7
+ @node = generate_xml_wrap_from('types')
8
+ end
9
+ it 'should generate string type' do
10
+ Generator::Type.new(:node => (@node / 'cdecl')[0]).to_s.should == ':string'
11
+ end
12
+ it 'should generate pointer type' do
13
+ Generator::Type.new(:node => (@node / 'cdecl')[1]).to_s.should == ':pointer'
14
+ Generator::Type.new(:node => (@node / 'cdecl')[2]).to_s.should == ':pointer'
15
+ end
16
+ it 'should generate array type' do
17
+ Generator::Type.new(:node => (@node / 'cdecl')[3]).to_s.should == '[:int, 5]'
18
+ Generator::Type.new(:node => (@node / 'cdecl')[4]).to_s.should == '[:string, 5]'
19
+ end
20
+ it 'should generate struct type' do
21
+ Generator::Type.new(:node => (@node / 'cdecl')[6]).to_s.should == 'TestStruct'
22
+ end
23
+ it 'should generate struct array type' do
24
+ Generator::Type.new(:node => (@node / 'cdecl')[7]).to_s.should == '[TestStruct, 5]'
25
+ end
26
+ it 'should generate enum array type' do
27
+ Generator::Type.new(:node => (@node / 'cdecl')[8]).to_s.should == '[:int, 5]'
28
+ end
29
+ it 'should generate const type' do
30
+ Generator::Type.new(:node => (@node / 'cdecl')[9]).to_s.should == ':int'
31
+ Generator::Type.new(:node => (@node / 'cdecl')[10]).to_s.should == ':string'
32
+ end
33
+ Generator::TYPES.sort.each_with_index do |type, i|
34
+ it "should generate #{type[0]} type" do
35
+ Generator::Type.new(:node => (@node / 'cdecl')[i + 11]).to_s.should == type[1]
36
+ end
37
+ end
38
+ end
data/spec/spec_helper.rb CHANGED
@@ -24,4 +24,10 @@ def remove_xml
24
24
  FileUtils.rm(Dir.glob('spec/generator/swig/*.xml'))
25
25
  end
26
26
 
27
+ share_examples_for "All specs" do
28
+ after :all do
29
+ remove_xml
30
+ end
31
+ end
32
+
27
33
  # EOF
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'cucumber/rake/task'
3
+ Cucumber::Rake::Task.new(:features) do |t|
4
+ t.cucumber_opts = "--format pretty"
5
+ end
6
+ rescue LoadError
7
+ nil
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-swig-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrea Fazzi
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-09 00:00:00 +01:00
12
+ date: 2009-04-20 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,17 +32,7 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.1.1
34
34
  version:
35
- - !ruby/object:Gem::Dependency
36
- name: bones
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 2.4.0
44
- version:
45
- description: ffi-swig-generator is a ruby-ffi wrapper code generator based on SWIG interface files. ffi-swig-generator is able to traverse a XML parse tree file generated by the +swig+ command and to produce a ruby-ffi interface file from it. ffi-swig-generator is shipped with a command line tool (ffi-gen) and a rake task that automates the code generation process. ffi-swig-generator XML capabilities are provided by nokogiri.
35
+ description: ffi-swig-generator is a ruby-ffi wrapper code generator that produce ruby-ffi glue code parsing C header files through SWIG. ffi-swig-generator is able to traverse an XML parse tree generated by the +swig+ command and to produce a ruby-ffi code from it. ffi-swig-generator is shipped with a command line tool and a rake task that automates the code generation process. ffi-swig-generator XML capabilities are provided by nokogiri.
46
36
  email: andrea.fazzi@alcacoop.it
47
37
  executables:
48
38
  - ffi-gen
@@ -55,22 +45,40 @@ extra_rdoc_files:
55
45
  files:
56
46
  - .hg/00changelog.i
57
47
  - .hg/branch
48
+ - .hg/branch.cache
58
49
  - .hg/dirstate
59
50
  - .hg/hgrc
60
51
  - .hg/requires
61
52
  - .hg/store/00changelog.i
62
53
  - .hg/store/00manifest.i
54
+ - .hg/store/data/.hgignore.i
55
+ - .hg/store/data/.hgtags.i
63
56
  - .hg/store/data/_history.txt.i
64
57
  - .hg/store/data/_r_e_a_d_m_e.rdoc.i
65
58
  - .hg/store/data/_rakefile.i
66
59
  - .hg/store/data/bin/ffi-gen.i
60
+ - .hg/store/data/cucumber.yml.i
67
61
  - .hg/store/data/examples/_rakefile.i
68
62
  - .hg/store/data/examples/interfaces/libc.i.i
69
63
  - .hg/store/data/examples/interfaces/wiiuse.i.i
64
+ - .hg/store/data/features/generate.feature.i
65
+ - .hg/store/data/features/step__definitions/generate.rb.i
66
+ - .hg/store/data/features/support/env.rb.i
67
+ - .hg/store/data/features/support/results.rb.i
68
+ - .hg/store/data/features/support/templates.rb.i
70
69
  - .hg/store/data/lib/ffi-swig-generator.rb.i
71
70
  - .hg/store/data/lib/generator/application.rb.i
71
+ - .hg/store/data/lib/generator/constant.rb.i
72
+ - .hg/store/data/lib/generator/enum.rb.i
73
+ - .hg/store/data/lib/generator/function.rb.i
72
74
  - .hg/store/data/lib/generator/generator.rb.i
73
75
  - .hg/store/data/lib/generator/generatortask.rb.i
76
+ - .hg/store/data/lib/generator/logger.rb.i
77
+ - .hg/store/data/lib/generator/node.rb.i
78
+ - .hg/store/data/lib/generator/parser.rb.i
79
+ - .hg/store/data/lib/generator/struct.rb.i
80
+ - .hg/store/data/lib/generator/type.rb.i
81
+ - .hg/store/data/lib/generator/types.rb.i
74
82
  - .hg/store/data/pkg/ffi-swig-generator-0.2.1.gem.i
75
83
  - .hg/store/data/pkg/ffi-swig-generator-0.2.1.tgz.i
76
84
  - .hg/store/data/pkg/ffi-swig-generator-0.2.1/.gitignore.i
@@ -111,7 +119,13 @@ files:
111
119
  - .hg/store/data/pkg/ffi-swig-generator-0.2.1/tasks/svn.rake.i
112
120
  - .hg/store/data/pkg/ffi-swig-generator-0.2.1/tasks/test.rake.i
113
121
  - .hg/store/data/spec/ffi-swig-generator__spec.rb.i
122
+ - .hg/store/data/spec/generator/constant__spec.rb.i
123
+ - .hg/store/data/spec/generator/enum__spec.rb.i
124
+ - .hg/store/data/spec/generator/function__spec.rb.i
114
125
  - .hg/store/data/spec/generator/generator__spec.rb.i
126
+ - .hg/store/data/spec/generator/node__spec.rb.i
127
+ - .hg/store/data/spec/generator/parser__spec.rb.i
128
+ - .hg/store/data/spec/generator/struct__spec.rb.i
115
129
  - .hg/store/data/spec/generator/swig/constants.i.i
116
130
  - .hg/store/data/spec/generator/swig/enums.i.i
117
131
  - .hg/store/data/spec/generator/swig/functions.i.i
@@ -120,10 +134,12 @@ files:
120
134
  - .hg/store/data/spec/generator/swig/typedefs.i.i
121
135
  - .hg/store/data/spec/generator/swig/types.i.i
122
136
  - .hg/store/data/spec/generator/swig/unions.i.i
137
+ - .hg/store/data/spec/generator/type__spec.rb.i
123
138
  - .hg/store/data/spec/spec.opts.i
124
139
  - .hg/store/data/spec/spec__helper.rb.i
125
140
  - .hg/store/data/tasks/ann.rake.i
126
141
  - .hg/store/data/tasks/bones.rake.i
142
+ - .hg/store/data/tasks/cucumber.rake.i
127
143
  - .hg/store/data/tasks/gem.rake.i
128
144
  - .hg/store/data/tasks/git.rake.i
129
145
  - .hg/store/data/tasks/notes.rake.i
@@ -138,19 +154,41 @@ files:
138
154
  - .hg/undo.branch
139
155
  - .hg/undo.dirstate
140
156
  - .hgignore
157
+ - .hgtags
141
158
  - History.txt
142
159
  - README.rdoc
143
160
  - Rakefile
144
161
  - bin/ffi-gen
162
+ - cucumber.yml
145
163
  - examples/Rakefile
164
+ - examples/generated/libc_wrap.rb
165
+ - examples/generated/libc_wrap.xml
166
+ - examples/generated/wiiuse_wrap.rb
167
+ - examples/generated/wiiuse_wrap.xml
146
168
  - examples/interfaces/libc.i
147
169
  - examples/interfaces/wiiuse.i
170
+ - features/generate.feature
171
+ - features/step_definitions/generate.rb
172
+ - features/support/env.rb
173
+ - features/support/templates.rb
148
174
  - lib/ffi-swig-generator.rb
149
175
  - lib/generator/application.rb
150
- - lib/generator/generator.rb
176
+ - lib/generator/constant.rb
177
+ - lib/generator/enum.rb
178
+ - lib/generator/function.rb
151
179
  - lib/generator/generatortask.rb
180
+ - lib/generator/logger.rb
181
+ - lib/generator/node.rb
182
+ - lib/generator/parser.rb
183
+ - lib/generator/struct.rb
184
+ - lib/generator/type.rb
185
+ - lib/generator/types.rb
152
186
  - spec/ffi-swig-generator_spec.rb
153
- - spec/generator/generator_spec.rb
187
+ - spec/generator/constant_spec.rb
188
+ - spec/generator/enum_spec.rb
189
+ - spec/generator/function_spec.rb
190
+ - spec/generator/parser_spec.rb
191
+ - spec/generator/struct_spec.rb
154
192
  - spec/generator/swig/constants.i
155
193
  - spec/generator/swig/enums.i
156
194
  - spec/generator/swig/functions.i
@@ -159,10 +197,12 @@ files:
159
197
  - spec/generator/swig/typedefs.i
160
198
  - spec/generator/swig/types.i
161
199
  - spec/generator/swig/unions.i
200
+ - spec/generator/type_spec.rb
162
201
  - spec/spec.opts
163
202
  - spec/spec_helper.rb
164
203
  - tasks/ann.rake
165
204
  - tasks/bones.rake
205
+ - tasks/cucumber.rake
166
206
  - tasks/gem.rake
167
207
  - tasks/git.rake
168
208
  - tasks/notes.rake
@@ -174,7 +214,7 @@ files:
174
214
  - tasks/svn.rake
175
215
  - tasks/test.rake
176
216
  has_rdoc: true
177
- homepage: http://kenai.com/projects/ruby-ffi
217
+ homepage: http://kenai.com/projects/ruby-ffi/sources/swig-generator/show
178
218
  post_install_message:
179
219
  rdoc_options:
180
220
  - --main
@@ -196,9 +236,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
236
  requirements: []
197
237
 
198
238
  rubyforge_project: ffi-swig-gen
199
- rubygems_version: 1.3.0
239
+ rubygems_version: 1.3.1
200
240
  signing_key:
201
241
  specification_version: 2
202
- summary: ffi-swig-generator is a ruby-ffi wrapper code generator based on SWIG interface files
242
+ summary: ffi-swig-generator is a ruby-ffi wrapper code generator that produce ruby-ffi glue code parsing C header files through SWIG
203
243
  test_files: []
204
244
 
@@ -1,344 +0,0 @@
1
- require 'rubygems'
2
- require 'nokogiri'
3
-
4
- module FFI
5
- module Generator
6
- @typedefs = {}
7
- TYPES = {
8
- 'char' => ':char',
9
- 'double' => ':double',
10
- 'float' => ':float',
11
- 'unsigned long' => ':ulong',
12
- 'unsigned char' => ':uchar',
13
- 'signed char' => ':char',
14
- 'unsigned char' => ':uchar',
15
- 'short' => ':short',
16
- 'signed short' => ':short',
17
- 'signed short int' => ':short',
18
- 'unsigned short' => ':ushort',
19
- 'unsigned short int' => ':ushort',
20
- 'int' => ':int',
21
- 'signed int' => ':int',
22
- 'unsigned int' => ':uint',
23
- 'long' => ':long',
24
- 'long int' => ':long',
25
- 'signed long' => ':long',
26
- 'signed long int' => ':long',
27
- 'unsigned long' => ':ulong',
28
- 'unsigned long int' => ':ulong',
29
- 'long unsigned int' => ':ulong',
30
- 'long long' => ':long_long',
31
- 'long long int' => ':long_long',
32
- 'signed long long' => ':long_long',
33
- 'signed long long int' => ':long_long',
34
- 'unsigned long long' => ':ulong_long',
35
- 'unsigned long long int' => ':ulong_long',
36
- 'void' => ':void'
37
- }
38
- class << self
39
- attr_reader :typedefs
40
- def add_type(ctype, rtype)
41
- @typedefs[ctype] = rtype
42
- end
43
- end
44
- class Node
45
- attr_reader :symname
46
- def initialize(params = { })
47
- params = { :indent => 0 }.merge(params)
48
- @node, @indent = params[:node], params[:indent]
49
- @indent_str = ' ' * @indent
50
- @symname = get_attr('name')
51
- end
52
- def get_attr(name)
53
- if @node
54
- attr = (@node / "./attributelist/attribute[@name='#{name}']").first
55
- attr['value'] if attr
56
- end
57
- end
58
- end
59
- class Type < Node
60
- def initialize(params = { })
61
- super
62
- @statement = params[:statement] || get_statement
63
- end
64
- def to_s
65
- get_type
66
- end
67
- private
68
- def get_statement
69
- get_attr('decl').to_s + get_attr('type').to_s if @node
70
- end
71
- def is_native?
72
- Generator::TYPES.has_key?(@statement)
73
- end
74
- def is_pointer?
75
- @statement[/^p\./] and not is_callback?
76
- end
77
- def is_enum?
78
- @statement[/^enum/]
79
- end
80
- def is_array?
81
- @statement and @statement[/\w+\(\d+\)/]
82
- end
83
- def is_struct?
84
- @statement[/^struct/]
85
- end
86
- def is_union?
87
- @statement[/^union/]
88
- end
89
- def is_constant?
90
- @statement[/^q\(const\)/]
91
- end
92
- def is_callback?
93
- @statement[/^p.f\(/]
94
- end
95
- def native
96
- if is_native?
97
- @statement = Generator::TYPES[@statement]
98
- get_type
99
- end
100
- end
101
- def constant
102
- if is_constant?
103
- @statement = @statement.scan(/^q\(const\)\.(.+)/).flatten[0]
104
- get_type
105
- end
106
- end
107
- def pointer
108
- if is_pointer?
109
- if @statement[/char/] and @statement.scan(/p\./).size == 1
110
- @statement = ':string'
111
- # @decl.gsub!(/p\./, '')
112
- get_type
113
- else
114
- return ':pointer'
115
- end
116
- end
117
- end
118
- def array
119
- if is_array?
120
- num = @statement.scan(/\w+\((\d+)\)/).flatten[0]
121
- @statement.gsub!(/\w+\(\d+\)\./, '')
122
- "[#{get_type}, #{num}]"
123
- end
124
- end
125
- def struct
126
- if is_struct?
127
- @statement = Structure.camelcase(@statement.scan(/^struct\s(\w+)/).flatten[0])
128
- get_type
129
- end
130
- end
131
- def union
132
- if is_union?
133
- @statement = Union.camelcase(@statement.scan(/^union\s(\w+)/).flatten[0])
134
- get_type
135
- end
136
- end
137
- def enum
138
- if is_enum?
139
- @statement = Generator::TYPES['int']
140
- get_type
141
- end
142
- end
143
- def callback
144
- Callback.new(:node => @node).to_s if is_callback?
145
- end
146
- def typedef
147
- if Generator.typedefs.has_key?(@statement)
148
- @statement = Generator.typedefs[@statement]
149
- get_type
150
- end
151
- end
152
- def get_type
153
- constant || pointer || enum || typedef || native || struct || union || array || callback || "#{@statement}"
154
- end
155
- end
156
- class Typedef < Type
157
- attr_reader :symname, :statement
158
- def initialize(params = { })
159
- super
160
- @symname = get_attr('name')
161
- # @type = is_pointer? ? ':pointer' : get_attr('type')
162
- # p @statement
163
- end
164
- end
165
- class Constant < Node
166
- def initialize(params = { })
167
- super
168
- @name, @value = get_attr('sym_name'), get_attr('value')
169
- end
170
- def to_s
171
- @indent_str + "#{@name} = #{@value}"
172
- end
173
- end
174
- class Enum < Node
175
- def initialize(params = { })
176
- super
177
- eval_items
178
- end
179
- def to_s
180
- @items.sort { |i1, i2| i1[1] <=> i2[1] }.inject("") do |result, item|
181
- result << assignment_str(item[0], item[1]) << "\n"
182
- end
183
- end
184
- private
185
- def assignment_str(name, value)
186
- @indent_str + "#{name} = #{value}"
187
- end
188
- def eval_expr(expr)
189
- if expr.include?('+')
190
- (@items[expr[/\w+/]].to_i + 1).to_s
191
- else
192
- 0.to_s
193
- end
194
- end
195
- def eval_items
196
- @items = {}
197
- get_items.each do |i|
198
- node = Node.new(:node => i)
199
- @items[node.get_attr('name')] = node.get_attr('enumvalueex') ? eval_expr(node.get_attr('enumvalueex')) : node.get_attr('enumvalue')
200
- end
201
- @items
202
- end
203
- def get_items
204
- @node / './enumitem'
205
- end
206
- end
207
- class Structure < Node
208
- def self.camelcase(name)
209
- name.gsub(/^\w|\_\w/).each {|c| c.upcase }.delete('_')
210
- end
211
- def initialize(params = { })
212
- super
213
- @name = self.class.camelcase(@symname)
214
- end
215
- def to_s
216
- fields_str = fields.inject("") do |str, f|
217
- str << @indent_str + ' ' * 9 << f.join(', ') << ",\n"
218
- end
219
- code = klass_string + @indent_str + " layout(\n" + fields_str.chomp.chomp(',') + "\n" + @indent_str + " )\n" + @indent_str + "end\n"
220
- end
221
- private
222
- def klass_string
223
- @indent_str + "class #{@name} < FFI::Struct\n"
224
- end
225
- def fields
226
- (@node / 'cdecl').inject([]) do |array, field|
227
- array << [":#{Node.new(:node => field).symname}", "#{Type.new(:node => field)}"]
228
- end
229
- end
230
- end
231
- class Union < Structure
232
- private
233
- def klass_string
234
- @indent_str + "class #{@name} < FFI::Union\n"
235
- end
236
- end
237
- class Function < Type
238
- class Argument < Type
239
- def to_s
240
- get_attr('type') == 'void' ? nil : super
241
- end
242
- end
243
- def initialize(params = { })
244
- super
245
- @type = get_attr('type')
246
- end
247
- def to_s
248
- params = get_params(@node).inject([]) do |array, node|
249
- array << Argument.new(:node => node).to_s
250
- end.collect { |p| "#{p}" }
251
- @indent_str + "attach_function :#{@symname}, [ #{params.join(', ')} ], #{get_rvalue}"
252
- end
253
- private
254
- def get_params(node)
255
- parmlist = node / './attributelist/parmlist/parm'
256
- end
257
- def get_rvalue
258
- Type.new(:node => @node, :statement => @statement.scan(/^f\(.*\)\.(.+)/).flatten[0]).to_s
259
- end
260
- end
261
- class Callback < Type
262
- def to_s
263
- params = get_params.inject([]) do |array, type|
264
- array << (type == 'void' ? '' : Type.new(:statement => type).to_s)
265
- end
266
- @indent_str + "callback(:#{@symname}, [ #{params.join(', ')} ], #{get_rtype})"
267
- end
268
- private
269
- def get_params
270
- @statement.scan(/p.f\((.*)\)/).flatten[0].split(',')
271
- end
272
- def get_rtype
273
- Type.new(:statement => @statement.scan(/\)\.(\w+)/).flatten[0]).to_s
274
- end
275
- end
276
- class Parser
277
- @indent = 2
278
- class << self
279
- def get_verbatim(node)
280
- node.xpath("./attributelist/attribute[@name='code']").first['value']
281
- end
282
- def is_insert_runtime?(node)
283
- section = node.xpath("./attributelist/attribute[@name='section']")
284
- section.first['value'] == 'runtime' if section.first
285
- end
286
- def is_constant?(node)
287
- node.name == 'constant'
288
- end
289
- def is_enum?(node)
290
- node.name == 'enum'
291
- end
292
- def is_function_decl?(node)
293
- node.name == 'cdecl' and (node / "./attributelist/attribute[@name='kind']").first['value'] == 'function'
294
- end
295
- def is_struct?(node)
296
- node.name == 'class' and (node / "./attributelist/attribute[@name='kind']").first['value'] == 'struct'
297
- end
298
- def is_union?(node)
299
- node.name == 'class' and (node / "./attributelist/attribute[@name='kind']").first['value'] == 'union'
300
- end
301
- def is_typedef?(node)
302
- node.name == 'cdecl' and (node / "./attributelist/attribute[@name='kind']").first['value'] == 'typedef'
303
- end
304
- def is_callback?(node)
305
- (node / "./attributelist/attribute[@name='decl']").first['value'] =~ /^p\.f\(/
306
- end
307
- def generate(node)
308
- result = ""
309
- node.traverse do |node|
310
- if is_constant?(node)
311
- result << Constant.new(:node => node, :indent => @indent).to_s << "\n"
312
- elsif is_typedef?(node)
313
- typedef = Typedef.new(:node => node)
314
- Generator.add_type(typedef.symname, typedef.statement)
315
- if is_callback?(node)
316
- cb = Callback.new(:node => node, :indent => @indent).to_s << "\n"
317
- Generator.add_type(typedef.symname, ":#{typedef.symname}")
318
- result << cb.to_s
319
- end
320
- elsif is_enum?(node)
321
- e = Enum.new(:node => node, :indent => @indent)
322
- Generator.add_type(e.symname, Generator::TYPES['int'])
323
- result << e.to_s << "\n"
324
- elsif is_struct?(node)
325
- s = Structure.new(:node => node, :indent => @indent)
326
- Generator.add_type(s.symname, "struct #{s.symname}")
327
- result << s.to_s
328
- elsif is_union?(node)
329
- s = Union.new(:node => node, :indent => @indent)
330
- Generator.add_type(s.symname, "union #{s.symname}")
331
- result << s.to_s
332
- elsif is_function_decl?(node)
333
- result << Function.new(:node => node, :indent => @indent).to_s << "\n"
334
- elsif node.name == 'insert' and not is_insert_runtime?(node)
335
- result << get_verbatim(node)
336
- end
337
- end
338
- result
339
- end
340
- end
341
- end
342
- end
343
- end
344
-