rubber-generate 0.0.21 → 0.0.22
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.
- data/lib/rubber/codegen.rb +12 -5
- data/lib/rubber/codegen/class.rb +3 -3
- data/lib/rubber/codegen/function.rb +4 -4
- data/lib/rubber/scanner.rb +539 -494
- data/lib/rubber/tokens.rb +13 -0
- data/lib/rubber/version.rb +1 -1
- metadata +5 -4
data/lib/rubber/codegen.rb
CHANGED
@@ -5,11 +5,18 @@ def generate_c_source(scanner, io)
|
|
5
5
|
if scanner.options.gnu
|
6
6
|
io.puts "#define _GNU_SOURCE 1"
|
7
7
|
end
|
8
|
-
io.puts
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
io.puts <<-EOX
|
9
|
+
/* Includes */
|
10
|
+
#include <ruby.h>
|
11
|
+
#include <stdlib.h>
|
12
|
+
#include <stdio.h>
|
13
|
+
#include <string.h>
|
14
|
+
#if defined GCC
|
15
|
+
#define OPTIONAL_ATTR __attribute__((unused))
|
16
|
+
#else
|
17
|
+
#define OPTIONAL_ATTR
|
18
|
+
#endif
|
19
|
+
EOX
|
13
20
|
if scanner.incs
|
14
21
|
scanner.incs.each { |i| io.puts "#include #{i.inspect}"}
|
15
22
|
end
|
data/lib/rubber/codegen/class.rb
CHANGED
@@ -38,16 +38,16 @@ class C_Class < C_Module
|
|
38
38
|
io.puts " c#{name} = #{cname};"
|
39
39
|
else
|
40
40
|
if parent and parent.cname
|
41
|
-
io.puts " #{cname} = rb_define_class_under(#{parent.cname}, #{name.inspect}, #{Rubber
|
41
|
+
io.puts " #{cname} = rb_define_class_under(#{parent.cname}, #{name.inspect}, #{Rubber.find_class(superclass) || 'rb_cObject'});"
|
42
42
|
else
|
43
|
-
io.puts " #{cname} = rb_define_class(#{name.inspect}, #{Rubber
|
43
|
+
io.puts " #{cname} = rb_define_class(#{name.inspect}, #{Rubber.find_class(superclass) || 'rb_cObject'});"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
register_children(io)
|
47
47
|
end
|
48
48
|
include RegisterChildren
|
49
49
|
def default_cname
|
50
|
-
"c"
|
50
|
+
"c#{name}"
|
51
51
|
end
|
52
52
|
def check_wrap_ok(io, fn, where)
|
53
53
|
case where
|
@@ -57,8 +57,8 @@ class C_Function
|
|
57
57
|
if @multi
|
58
58
|
io.write "int __p_argc, VALUE *__p_argv, VALUE self"
|
59
59
|
else
|
60
|
-
io.write "VALUE self"
|
61
|
-
io.write(args.reject {|i| i.block }.collect { |i| ', VALUE ' + i.cname }.join(''))
|
60
|
+
io.write "VALUE self OPTIONAL_ATTR "
|
61
|
+
io.write(args.reject {|i| i.block }.collect { |i| ', VALUE ' + i.cname + " OPTIONAL_ATTR" }.join(''))
|
62
62
|
#io.write ", " if args.size > 1 or (args.size > 0 and not @block)
|
63
63
|
end
|
64
64
|
io.write ")"
|
@@ -131,7 +131,7 @@ class C_Function
|
|
131
131
|
if arg.auto_convert?
|
132
132
|
io.puts(" __orig_#{arg.name} = #{arg.name} = #{Rubber::explicit_cast(arg.cname, 'VALUE', arg.ctype)};")
|
133
133
|
elsif arg.block
|
134
|
-
io.puts(" VALUE #{arg.name} = #{arg.init_value()};")
|
134
|
+
io.puts(" VALUE #{arg.name} OPTIONAL_ATTR = #{arg.init_value()};")
|
135
135
|
else
|
136
136
|
arg.check_type(io) if arg.rtype
|
137
137
|
end
|
@@ -218,7 +218,7 @@ class C_Function
|
|
218
218
|
io = oio
|
219
219
|
|
220
220
|
|
221
|
-
io.puts " VALUE __p_retval = #{default()};" if returned
|
221
|
+
io.puts " VALUE __p_retval OPTIONAL_ATTR = #{default()};" if returned
|
222
222
|
io.puts setupvars
|
223
223
|
io.puts "\n do {" if @vars and not @vars.empty?
|
224
224
|
io.puts code
|
data/lib/rubber/scanner.rb
CHANGED
@@ -1,516 +1,561 @@
|
|
1
1
|
require 'rubber/struct'
|
2
2
|
require 'rubber/version'
|
3
3
|
module Rubber
|
4
|
-
class ScanState
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
class Options
|
9
|
-
attr_accessor :gtk, :glib, :gnu
|
10
|
-
alias :gtk? :gtk
|
11
|
-
alias :glib? :glib
|
12
|
-
def []=(name,val)
|
13
|
-
instance_variable_set("@"+name,val)
|
14
|
-
end
|
15
|
-
def [](name)
|
16
|
-
instance_variable_get("@"+name)
|
17
|
-
end
|
18
|
-
end
|
4
|
+
class ScanState
|
5
|
+
define_members(:in_code, :in_class, :in_func, :braces)
|
6
|
+
end
|
19
7
|
|
20
|
-
class
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@classes = {}
|
30
|
-
@calls = []
|
31
|
-
@allocs = []
|
32
|
-
@options = Options.new
|
33
|
-
# Default settings
|
34
|
-
@options.glib= true
|
35
|
-
@options.gtk= true
|
36
|
-
@options.gnu= false
|
37
|
-
@current_file = file
|
38
|
-
end
|
39
|
-
attr_reader :current_file
|
40
|
-
def scan_args()
|
41
|
-
args = []
|
42
|
-
return args unless @str.peep(1) == '('
|
43
|
-
brackets = 1
|
44
|
-
arg = ''
|
45
|
-
@str.get_byte # Get first bracket
|
46
|
-
until @str.peep(1) == ')' and brackets == 1
|
47
|
-
brackets += 1 if @str.peep(1) == '('
|
48
|
-
brackets -= 1 if @str.peep(1) == ')'
|
49
|
-
if brackets == 1 and @str.peep(1) == ','
|
50
|
-
@str.pos = @str.pos + 1
|
51
|
-
arg.strip!
|
52
|
-
args.push arg unless arg.empty?
|
53
|
-
arg = ''
|
54
|
-
else
|
55
|
-
arg += @str.get_byte
|
8
|
+
class Options
|
9
|
+
attr_accessor :gtk, :glib, :gnu
|
10
|
+
alias :gtk? :gtk
|
11
|
+
alias :glib? :glib
|
12
|
+
def []=(name,val)
|
13
|
+
instance_variable_set("@"+name,val)
|
14
|
+
end
|
15
|
+
def [](name)
|
16
|
+
instance_variable_get("@"+name)
|
56
17
|
end
|
57
18
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
#p @stack
|
65
|
-
@stack
|
66
|
-
end
|
67
|
-
attr_accessor :state
|
68
|
-
def scan(fp)
|
69
|
-
_scan(fp)
|
70
|
-
rescue Exception
|
71
|
-
off,ind = 0,0
|
72
|
-
for line in @lines
|
73
|
-
off += line.size
|
74
|
-
break if off > @str.pos
|
75
|
-
ind += 1
|
19
|
+
|
20
|
+
class TokenStringScanner < StringScanner
|
21
|
+
def skip(*args)
|
22
|
+
x = super
|
23
|
+
#p [x, *args] if x
|
24
|
+
x
|
76
25
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
26
|
+
def scan(*args)
|
27
|
+
x = super
|
28
|
+
#p [x, *args] if x
|
29
|
+
x
|
30
|
+
end
|
31
|
+
def scan_number
|
32
|
+
scan(/(0x[0-9A-Fa-f]+|[0-9]+[.][0-9]+(e[0-9]+)?|[0-9]+)/)
|
33
|
+
end
|
34
|
+
def scan_lit_string
|
35
|
+
scan(/(".*?[^\\]")/)
|
36
|
+
end
|
37
|
+
def scan_float
|
38
|
+
scan(/(\d[.]\d+)/)
|
39
|
+
end
|
40
|
+
def scan_lit_integer
|
41
|
+
scan(/([0-9]+)/)
|
42
|
+
end
|
43
|
+
def scan_constant
|
44
|
+
scan(/([A-Z][a-z_0-9A-Z]*)/)
|
45
|
+
end
|
46
|
+
def scan_upcase_constant
|
47
|
+
scan(/([A-Z][0-9A-Z_]*)/)
|
48
|
+
end
|
49
|
+
def scan_literal
|
50
|
+
scan(/([A-Za-z0-9_]+)/)
|
51
|
+
end
|
52
|
+
def skip_ws
|
53
|
+
skip(/\s+/)
|
54
|
+
end
|
55
|
+
def scan_nil
|
56
|
+
scan(/NULL|nil/i)
|
57
|
+
end
|
58
|
+
def scan_lit_bool
|
59
|
+
scan(/TRUE|FALSE/i)
|
60
|
+
end
|
61
|
+
def scan_pc_block
|
62
|
+
raw = scan_until(/%\}/)
|
112
63
|
raw[-2..-1] = ""
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
@
|
128
|
-
@
|
129
|
-
|
130
|
-
|
131
|
-
@
|
132
|
-
|
133
|
-
@
|
134
|
-
@
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
elsif @str.skip(/%map\s+([^->]+?)\>([^:]+):([^@\n]+) *@? *(.*)\n/) # Skip single-line comment
|
154
|
-
from, to, code = *[@str[1], @str[2], @str[3]].collect { |i| i.strip }
|
155
|
-
free_code = @str[4]
|
156
|
-
from.gsub!(/ /,'')
|
157
|
-
to.gsub!(/ /,'')
|
158
|
-
puts "Mapping #{from} -> #{to}"
|
159
|
-
($custom_maps[from] ||= {})[to] = code
|
160
|
-
$custom_frees[to] = free_code
|
161
|
-
elsif state.in_class > 0 and state.in_func == false and @str.skip(/%flag\s+([a-z0-9_A-Z]+)/)
|
162
|
-
flag = ("flag_"+@str[1]+"=").intern
|
163
|
-
if stack.last.respond_to?(flag)
|
164
|
-
stack.last.__send__(flag, true)
|
165
|
-
else
|
166
|
-
syntax_error "%flags directive cannot be used here (#{stack.last.class} doesn't respond to #{flag})"
|
167
|
-
end
|
168
|
-
elsif state.in_class > 0 and state.in_func == false and @str.skip(/%feature\s+([a-z0-9_A-Z]+)/)
|
169
|
-
flag = ("feature_"+@str[1]).intern
|
170
|
-
@str.skip(/\s+/)
|
171
|
-
args = []
|
172
|
-
if @str.skip(/\(/)
|
173
|
-
args = @str.scan_until(/\)/)[0..-2].split(/, */).map { |i| i.strip }
|
64
|
+
raw
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class CRScanner
|
69
|
+
attr_reader :file, :functions, :nested_functions, :classes, :calls, :allocs, :stack, :ext, :pkgs, :incs, :doc, :raw, :libs, :defs, :pre_init_code, :post_init_code, :inc_dirs, :lib_dirs
|
70
|
+
attr_reader :options
|
71
|
+
def initialize(file)
|
72
|
+
@file = file
|
73
|
+
@ext = File::basename(file).gsub(/\..*$/, '')
|
74
|
+
@nested_functions = {}
|
75
|
+
@functions = {}
|
76
|
+
@modules = {}
|
77
|
+
@classes = {}
|
78
|
+
@calls = []
|
79
|
+
@allocs = []
|
80
|
+
@options = Options.new
|
81
|
+
# Default settings
|
82
|
+
@options.glib= true
|
83
|
+
@options.gtk= true
|
84
|
+
@options.gnu= false
|
85
|
+
@current_file = file
|
86
|
+
end
|
87
|
+
attr_reader :current_file
|
88
|
+
def scan_args()
|
89
|
+
args = []
|
90
|
+
return args unless @str.peep(1) == '('
|
91
|
+
brackets = 1
|
92
|
+
arg = ''
|
93
|
+
@str.get_byte # Get first bracket
|
94
|
+
until @str.peep(1) == ')' and brackets == 1
|
95
|
+
brackets += 1 if @str.peep(1) == '('
|
96
|
+
brackets -= 1 if @str.peep(1) == ')'
|
97
|
+
if brackets == 1 and @str.peep(1) == ','
|
98
|
+
@str.pos = @str.pos + 1
|
99
|
+
arg.strip!
|
100
|
+
args.push arg unless arg.empty?
|
101
|
+
arg = ''
|
102
|
+
else
|
103
|
+
arg += @str.get_byte
|
174
104
|
end
|
175
|
-
@str.skip(/;/)
|
176
|
-
if stack.last.respond_to?(flag)
|
177
|
-
stack.last.__send__(flag, *args)
|
178
|
-
else
|
179
|
-
syntax_error "%feature '#{@str[1]}' directive cannot be used here (#{stack.last.class} doesn't support it)"
|
180
|
-
end
|
181
|
-
elsif @str.skip(/%/) # Skip single-line comment
|
182
|
-
@str.skip_until(/\n/)
|
183
|
-
|
184
|
-
|
185
|
-
####### Comments
|
186
|
-
|
187
|
-
elsif state.in_func == false and @str.skip(/#.*/) # Comment
|
188
|
-
|
189
|
-
elsif state.in_func == false and @str.skip(/\/\/.*/) # Comment
|
190
|
-
|
191
|
-
elsif state.in_func == false and @str.skip(/\/\*(.|\n)*\*\//) # Multi-line Comment
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
####### Code
|
196
|
-
|
197
|
-
elsif txt = @str.scan(/['"]/) #' Skip quoted string
|
198
|
-
txt += @str.scan_until(/(^|[^\\])#{txt}/) # Skip until unescaped quote
|
199
|
-
func.text += txt if state.in_func
|
200
|
-
elsif state.in_func == false and @str.skip(/module(?= )/x) # Module defn
|
201
|
-
@str.skip(/\s+/)
|
202
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
203
|
-
@classes[name] = C_Module.new(name, [], [], [])
|
204
|
-
@classes[name].parent = stack.last
|
205
|
-
stack.last.classes.push(@classes[name])
|
206
|
-
stack.push(@class = @classes[name])
|
207
|
-
puts "module "+ @class.fullname + "-#{@class.name}"
|
208
|
-
state.in_class += 1
|
209
|
-
elsif state.in_func == false and @str.skip(/class(?= )/x) # Class defn
|
210
|
-
@str.skip(/\s+/)
|
211
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
212
|
-
superclass = nil
|
213
|
-
@str.skip(/\s*/)
|
214
|
-
if @str.skip(/</)
|
215
|
-
@str.skip(/\s*/)
|
216
|
-
superclass = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
217
|
-
end
|
218
|
-
@classes[name] = C_Class.new(name, superclass, [], [], [])
|
219
|
-
@classes[name].parent = stack.last
|
220
|
-
stack.last.classes.push(@classes[name])
|
221
|
-
stack.push(@class = @classes[name])
|
222
|
-
puts "class "+ @class.fullname
|
223
|
-
state.in_class += 1
|
224
|
-
|
225
|
-
elsif state.in_func == false and @str.skip(/struct(?= )/x) # Ruby Struct
|
226
|
-
@str.skip(/\s+/)
|
227
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
228
|
-
@str.skip(/\s+/)
|
229
|
-
if @str.skip(/\(/)
|
230
|
-
args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
|
231
|
-
end
|
232
|
-
# NB. struct Name(arg0...argN)
|
233
|
-
if @str.skip(/\s*;/)
|
234
|
-
stack.last.classes.push(C_Struct.new(name, args, stack.last))
|
235
|
-
else
|
236
|
-
@classes[name] = C_Struct.new(name, args, stack.last)
|
237
|
-
stack.last.classes.push(@classes[name])
|
238
|
-
stack.push(@class = @classes[name])
|
239
|
-
puts "struct "+ @class.fullname
|
240
|
-
state.in_class += 1
|
241
|
-
end
|
242
|
-
elsif state.in_func == false and @str.skip(/gcpool(?= )/x) # GC Pool
|
243
|
-
@str.skip(/\s+/)
|
244
|
-
name = @str.scan(/[a-z_0-9A-Z]*/)
|
245
|
-
puts "GCPool #{name}"
|
246
|
-
stack.first.classes.push(C_GCRefPool.new(name))
|
247
|
-
|
248
|
-
elsif state.in_func == false and @str.skip(/(enum|flags)(?= )/x) # C Enum as module wrapper
|
249
|
-
what = @str[1]
|
250
|
-
@str.skip(/\s+/)
|
251
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
252
|
-
@str.skip(/\s+/)
|
253
|
-
if @str.skip(/\(/)
|
254
|
-
args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
|
255
105
|
end
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
106
|
+
@str.get_byte # Get last bracket
|
107
|
+
arg.strip!
|
108
|
+
args.push arg unless arg.empty?
|
109
|
+
args
|
110
|
+
end
|
111
|
+
def stack()
|
112
|
+
#p @stack
|
113
|
+
@stack
|
114
|
+
end
|
115
|
+
attr_accessor :state
|
116
|
+
def scan(fp)
|
117
|
+
_scan(fp)
|
118
|
+
rescue Exception
|
119
|
+
off,ind = 0,0
|
120
|
+
for line in @lines
|
121
|
+
off += line.size
|
122
|
+
break if off > @str.pos
|
123
|
+
ind += 1
|
260
124
|
end
|
125
|
+
#p @state, @str, ind
|
126
|
+
raise
|
127
|
+
end
|
128
|
+
def _scan(fp)
|
129
|
+
@lines = IO.readlines(@file)
|
130
|
+
@str = TokenStringScanner.new(@string = @lines.join)
|
131
|
+
tokens = []
|
132
|
+
@state = ScanState.new(0,0,false,0)
|
133
|
+
@stack = [C_RootModule.new]
|
134
|
+
func = nil
|
135
|
+
until @str.empty?
|
136
|
+
######## Doc
|
137
|
+
if @str.skip(/=begin([ \t][^\n]*)?\n/) # skip =begin/=end blocks
|
138
|
+
lines = @str.scan_until(/\n=end([ \t].*)?/).split("\n")
|
139
|
+
lines.pop
|
140
|
+
if state.in_func
|
141
|
+
(func.doc ||= "") << lines.join("\n")
|
142
|
+
elsif @class and not @class.kind_of?(C_RootModule)
|
143
|
+
(@class.doc ||= "") << lines.join("\n")
|
144
|
+
else
|
145
|
+
(@doc ||= "") << lines.join("\n")
|
146
|
+
end
|
261
147
|
|
262
|
-
|
263
|
-
what = @str[1]
|
264
|
-
@str.skip(/\s+/)
|
265
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
266
|
-
@str.skip(/\s+/)
|
267
|
-
g_type = @str.scan(/[A-Z][_0-9A-Z]*/)
|
268
|
-
@str.skip(/\s+/)
|
269
|
-
prefix = @str.scan(/(prefix=)?[A-Z][_0-9A-Z]*/i).to_s.sub(/^prefix=/i,'')
|
270
|
-
@str.skip(/\s*/)
|
271
|
-
define_on_self = @str.scan(/define_on_self/)
|
272
|
-
@str.skip(/\s*;/)
|
273
|
-
if what == "gflags"
|
274
|
-
obj = C_GFlags.new(name, g_type, prefix, stack.last)
|
275
|
-
else
|
276
|
-
obj = C_GEnum.new(name, g_type, prefix, stack.last)
|
277
|
-
obj.define_on_self = !! define_on_self;
|
278
|
-
end
|
279
|
-
stack.last.classes.push(obj)
|
280
|
-
elsif state.in_func == false and @str.skip(/(gobject|ginterface|gboxed)(?= )/x) # Class defn
|
281
|
-
type=@str[1]
|
282
|
-
@str.skip(/\s+/)
|
283
|
-
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
284
|
-
superclass = nil
|
285
|
-
@str.skip(/\s*/)
|
286
|
-
if @str.skip(/\</)
|
287
|
-
@str.skip(/\s*/)
|
288
|
-
gtype = @str.scan(/[A-Z_]+/)
|
289
|
-
end
|
290
|
-
@str.skip(/\s*/)
|
291
|
-
if @str.skip(/:/)
|
292
|
-
@str.skip(/\s*/)
|
293
|
-
gparent_class = @str.scan(/[A-Z_:a-z0-9]+/)
|
294
|
-
end
|
295
|
-
case type
|
296
|
-
when "gobject"
|
297
|
-
@classes[name] = C_GObject.new(name, gtype, [], [], [])
|
298
|
-
when "ginterface"
|
299
|
-
@classes[name] = C_GInterface.new(name, gtype, [], [], [])
|
300
|
-
when "gboxed"
|
301
|
-
@classes[name] = C_GBoxed.new(name, gtype, [], [], [])
|
302
|
-
else
|
303
|
-
syntax_error "#{name} is not a GObject or GInterface..."
|
304
|
-
end
|
305
|
-
@classes[name].gparent_class = gparent_class
|
306
|
-
@classes[name].parent = stack.last
|
307
|
-
stack.last.classes.push(@classes[name])
|
308
|
-
stack.push(@class = @classes[name])
|
309
|
-
puts "class "+ @class.fullname
|
310
|
-
state.in_class += 1
|
311
|
-
elsif @str.scan(/@type\s+([A-Za-z_0-9]+)/)
|
312
|
-
type = @str[1]
|
313
|
-
prev = stack.last
|
314
|
-
if prev.is_a?(C_GObject)
|
315
|
-
# p c_type, self
|
316
|
-
puts "Converting #{type}* to & from VALUE"
|
317
|
-
prev.c_type_name = type
|
318
|
-
($custom_maps[type+'*'] ||= {})["VALUE"] = "GOBJ2RVAL(%%)"
|
319
|
-
($custom_maps["VALUE"] ||= {})[type+'*'] = "RVAL2GOBJ(%%)"
|
320
|
-
elsif prev.is_a?(C_GBoxed)
|
321
|
-
prev.c_type_name = type
|
148
|
+
######## Config
|
322
149
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
150
|
+
elsif @str.skip(/%\{/) # Scan raw
|
151
|
+
(@raw ||= "") << @str.scan_pc_block
|
152
|
+
elsif @str.skip(/%pre_init\{/) # Scan raw
|
153
|
+
(@pre_init_code ||= "") << @str.scan_pc_block
|
154
|
+
elsif @str.skip(/%post_init\{/) # Scan raw
|
155
|
+
(@post_init_code ||= "") << @str.scan_pc_block
|
156
|
+
elsif @str.skip_ws # skip
|
157
|
+
func.text += " " if state.in_func
|
158
|
+
elsif @str.skip(/%name */) # Extension name
|
159
|
+
@ext = @str.scan_literal
|
160
|
+
elsif @str.skip(/%min-version */)
|
161
|
+
@version = @str.scan(/([0-9]+)\.([0-9]+)\.([0-9]+)/)
|
162
|
+
version = [1,2,3].map{|i|@str[i].to_i}
|
163
|
+
Rubber::VERSION.each_with_index do |ver,idx|
|
164
|
+
if ver < version[idx]
|
165
|
+
misc_error "This version of rubber-generate (#{Rubber::VERSION}) is too old: #{@file} requires version #{version.map{|i|i.to_s}.join('.')}", false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
elsif @str.skip(/%pkg-config\s*([-a-z.0-9+]+)/) # pkg-config library
|
169
|
+
@pkgs ||= []
|
170
|
+
@pkgs << @str[1]
|
171
|
+
elsif @str.skip(/%include_dir\s+(.+)\n/) # Include dirs
|
172
|
+
@inc_dirs ||= []
|
173
|
+
@inc_dirs << @str[1].strip
|
174
|
+
elsif @str.skip(/%lib_dir\s+(.+)\n/) # Library dir
|
175
|
+
@lib_dirs ||= []
|
176
|
+
@lib_dirs << @str[1].strip
|
177
|
+
elsif @str.skip(/%include\s+(.+)\n/) # Include file
|
178
|
+
@incs ||= []
|
179
|
+
@incs << @str[1].strip
|
180
|
+
elsif @str.skip(/%option +([a-z]+)=(yes|no)\n/) # Option
|
181
|
+
case @str[1]
|
182
|
+
when 'glib', 'gtk', 'gnu'
|
183
|
+
@options[@str[1]] = (@str[2] == 'yes')
|
184
|
+
else
|
185
|
+
syntax_error "Unknown option #{@str[1]}"
|
186
|
+
end
|
187
|
+
elsif @str.skip(/%lib\s+(.+)\n/) # Skip single-line comment
|
188
|
+
@libs ||= []
|
189
|
+
@libs << @str[1].strip
|
190
|
+
elsif @str.skip(/%define\s+(.+)\n/) # Skip single-line comment
|
191
|
+
@defs ||= []
|
192
|
+
@defs << @str[1].strip
|
193
|
+
elsif @str.skip(/%equiv[a-z]*\s+([^=\n]+)=([^=\n]+)\n/) # Skip single-line comment
|
194
|
+
$equivalents[@str[1].gsub(/ /,'').strip] = @str[2].gsub(/ /,'').strip
|
195
|
+
elsif @str.skip(/%map\s+([^->]+?)\>([^:]+):([^@\n]+) *@? *(.*)\n/) # Skip single-line comment
|
196
|
+
from, to, code = *[@str[1], @str[2], @str[3]].collect { |i| i.strip }
|
197
|
+
free_code = @str[4]
|
198
|
+
from.gsub!(/ /,'')
|
199
|
+
to.gsub!(/ /,'')
|
200
|
+
puts "Mapping #{from} -> #{to}"
|
201
|
+
($custom_maps[from] ||= {})[to] = code
|
202
|
+
$custom_frees[to] = free_code
|
203
|
+
elsif state.in_class > 0 and state.in_func == false and @str.skip(/%flag\s+([a-z0-9_A-Z]+)/)
|
204
|
+
flag = ("flag_"+@str[1]+"=").intern
|
205
|
+
if stack.last.respond_to?(flag)
|
206
|
+
stack.last.__send__(flag, true)
|
207
|
+
else
|
208
|
+
syntax_error "%flags directive cannot be used here (#{stack.last.class} doesn't respond to #{flag})"
|
209
|
+
end
|
210
|
+
elsif state.in_class > 0 and state.in_func == false and @str.skip(/%feature\s+([a-z0-9_A-Z]+)/)
|
211
|
+
flag = ("feature_"+@str[1]).intern
|
212
|
+
@str.skip(/\s+/)
|
213
|
+
args = []
|
214
|
+
if @str.skip(/\(/)
|
215
|
+
args = @str.scan_until(/\)/)[0..-2].split(/, */).map { |i| i.strip }
|
216
|
+
end
|
217
|
+
@str.skip(/;/)
|
218
|
+
if stack.last.respond_to?(flag)
|
219
|
+
stack.last.__send__(flag, *args)
|
220
|
+
else
|
221
|
+
syntax_error "%feature '#{@str[1]}' directive cannot be used here (#{stack.last.class} doesn't support it)"
|
222
|
+
end
|
223
|
+
elsif @str.skip(/%/) # Skip single-line comment
|
224
|
+
@str.skip_until(/\n/)
|
225
|
+
|
226
|
+
|
227
|
+
####### Comments
|
228
|
+
|
229
|
+
elsif state.in_func == false and @str.skip(/#.*/) # Comment
|
230
|
+
|
231
|
+
elsif state.in_func == false and @str.skip(/\/\/.*/) # Comment
|
232
|
+
|
233
|
+
elsif state.in_func == false and @str.skip(/\/\*(.|\n)*\*\//) # Multi-line Comment
|
234
|
+
|
235
|
+
|
236
|
+
####### Code
|
237
|
+
|
238
|
+
elsif txt = @str.scan(/['"]/) #' Skip quoted string
|
239
|
+
txt += @str.scan_until(/(^|[^\\])#{txt}/) # Skip until unescaped quote
|
240
|
+
func.text += txt if state.in_func
|
241
|
+
elsif state.in_func == false and @str.skip(/module(?= )/x) # Module defn
|
242
|
+
@str.skip(/\s+/)
|
243
|
+
name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
|
244
|
+
@classes[name] = C_Module.new(name, [], [], [])
|
245
|
+
@classes[name].parent = stack.last
|
246
|
+
stack.last.classes.push(@classes[name])
|
247
|
+
stack.push(@class = @classes[name])
|
248
|
+
puts "module "+ @class.fullname + "-#{@class.name}"
|
249
|
+
state.in_class += 1
|
250
|
+
elsif state.in_func == false and @str.skip(/class(?= )/x) # Class defn
|
251
|
+
@str.skip_ws
|
252
|
+
name = @str.scan_constant
|
253
|
+
superclass = nil
|
254
|
+
@str.skip(/\s*/)
|
255
|
+
if @str.skip(/</)
|
256
|
+
@str.skip_ws
|
257
|
+
superclass = @str.scan_constant
|
258
|
+
end
|
259
|
+
@classes[name] = C_Class.new(name, superclass, [], [], [])
|
260
|
+
@classes[name].parent = stack.last
|
261
|
+
stack.last.classes.push(@classes[name])
|
262
|
+
stack.push(@class = @classes[name])
|
263
|
+
puts "class "+ @class.fullname
|
264
|
+
state.in_class += 1
|
265
|
+
|
266
|
+
elsif state.in_func == false and @str.skip(/struct(?= )/x) # Ruby Struct
|
267
|
+
@str.skip_ws
|
268
|
+
name = @str.scan_constant
|
269
|
+
@str.skip_ws
|
270
|
+
if @str.skip(/\(/)
|
271
|
+
args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
|
272
|
+
end
|
273
|
+
# NB. struct Name(arg0...argN)
|
274
|
+
if @str.skip(/\s*;/)
|
275
|
+
stack.last.classes.push(C_Struct.new(name, args, stack.last))
|
276
|
+
else
|
277
|
+
@classes[name] = C_Struct.new(name, args, stack.last)
|
278
|
+
stack.last.classes.push(@classes[name])
|
279
|
+
stack.push(@class = @classes[name])
|
280
|
+
puts "struct "+ @class.fullname
|
281
|
+
state.in_class += 1
|
282
|
+
end
|
283
|
+
elsif state.in_func == false and @str.skip(/gcpool(?= )/x) # GC Pool
|
284
|
+
@str.skip_ws
|
285
|
+
name = @str.scan_literal
|
286
|
+
puts "GCPool #{name}"
|
287
|
+
stack.first.classes.push(C_GCRefPool.new(name))
|
288
|
+
|
289
|
+
elsif state.in_func == false and @str.skip(/(enum|flags)(?= )/x) # C Enum as module wrapper
|
290
|
+
what = @str[1]
|
291
|
+
@str.skip_ws
|
292
|
+
name = @str.scan_constant
|
293
|
+
@str.skip_ws
|
294
|
+
if @str.skip(/\(/)
|
295
|
+
args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
|
296
|
+
end
|
297
|
+
if what == "flags"
|
298
|
+
stack.last.classes.push(C_Flags.new(name, args, stack.last))
|
299
|
+
else
|
300
|
+
stack.last.classes.push(C_Enum.new(name, args, stack.last))
|
301
|
+
end
|
302
|
+
|
303
|
+
elsif state.in_func == false and @str.skip(/(genum|gflags)(?= )/x) # C GEnum as module wrapper
|
304
|
+
what = @str[1]
|
305
|
+
@str.skip_ws
|
306
|
+
name = @str.scan_constant
|
307
|
+
@str.skip_ws
|
308
|
+
g_type = @str.scan_upcase_constant
|
309
|
+
@str.skip_ws
|
310
|
+
prefix = @str.scan(/(prefix=)?[A-Z][_0-9A-Z]*/i).to_s.sub(/^prefix=/i,'')
|
311
|
+
@str.skip_ws
|
312
|
+
define_on_self = @str.scan(/define_on_self/)
|
313
|
+
@str.skip(/\s*;/)
|
314
|
+
if what == "gflags"
|
315
|
+
obj = C_GFlags.new(name, g_type, prefix, stack.last)
|
316
|
+
else
|
317
|
+
obj = C_GEnum.new(name, g_type, prefix, stack.last)
|
318
|
+
obj.define_on_self = !! define_on_self;
|
319
|
+
end
|
320
|
+
stack.last.classes.push(obj)
|
321
|
+
elsif state.in_func == false and @str.skip(/(gobject|ginterface|gboxed)(?= )/x) # Class defn
|
322
|
+
type=@str[1]
|
323
|
+
@str.skip_ws
|
324
|
+
name = @str.scan_constant
|
325
|
+
superclass = nil
|
326
|
+
@str.skip_ws
|
327
|
+
if @str.skip(/\</)
|
328
|
+
@str.skip_ws
|
329
|
+
gtype = @str.scan_upcase_constant
|
330
|
+
end
|
331
|
+
@str.skip_ws
|
332
|
+
if @str.skip(/:/)
|
333
|
+
@str.skip_ws
|
334
|
+
gparent_class = @str.scan(/[A-Z_:a-z0-9]+/)
|
335
|
+
end
|
336
|
+
case type
|
337
|
+
when "gobject"
|
338
|
+
@classes[name] = C_GObject.new(name, gtype, [], [], [])
|
339
|
+
when "ginterface"
|
340
|
+
@classes[name] = C_GInterface.new(name, gtype, [], [], [])
|
341
|
+
when "gboxed"
|
342
|
+
@classes[name] = C_GBoxed.new(name, gtype, [], [], [])
|
343
|
+
else
|
344
|
+
syntax_error "#{name} is not a GObject or GInterface..."
|
345
|
+
end
|
346
|
+
@classes[name].gparent_class = gparent_class
|
347
|
+
@classes[name].parent = stack.last
|
348
|
+
stack.last.classes.push(@classes[name])
|
349
|
+
stack.push(@class = @classes[name])
|
350
|
+
puts "class "+ @class.fullname
|
351
|
+
state.in_class += 1
|
352
|
+
elsif @str.scan(/@type\s+/)
|
353
|
+
type = @str.scan_literal
|
354
|
+
prev = stack.last
|
355
|
+
if prev.is_a?(C_GObject)
|
356
|
+
# p c_type, self
|
357
|
+
puts "Converting #{type}* to & from VALUE"
|
358
|
+
prev.c_type_name = type
|
359
|
+
($custom_maps[type+'*'] ||= {})["VALUE"] = "GOBJ2RVAL(%%)"
|
360
|
+
($custom_maps["VALUE"] ||= {})[type+'*'] = "RVAL2GOBJ(%%)"
|
361
|
+
elsif prev.is_a?(C_GBoxed)
|
362
|
+
prev.c_type_name = type
|
363
|
+
|
364
|
+
($custom_maps[type+'*'] ||= {})["VALUE"] = "BOXED2RVAL(%%, #{prev.superclass})"
|
365
|
+
($custom_maps["VALUE"] ||= {})[type+'*'] = "RVAL2BOXED(%%, #{prev.superclass})"
|
366
|
+
else
|
367
|
+
# Invalid type directive
|
368
|
+
end
|
369
|
+
elsif @str.skip(/end(?=\s)/x)
|
370
|
+
last = stack.pop
|
371
|
+
puts "#{last.class} - #{last.name}"
|
372
|
+
case last
|
373
|
+
when C_Module, C_Class, C_Enum, C_Flags, C_Struct, C_GObject, C_GInterface, C_GBoxed
|
374
|
+
state.in_class -= 1
|
375
|
+
@class = stack.last
|
376
|
+
when C_Function
|
377
|
+
state.in_func = false
|
378
|
+
else
|
379
|
+
STDERR.puts "Remaining code: #{@str.rest}"
|
380
|
+
STDERR.puts "Defined Classes: #{@classes.keys.join(', ')}"
|
381
|
+
p stack
|
382
|
+
syntax_error "Invalid stack entry #{last.class}"
|
383
|
+
end
|
384
|
+
elsif @str.skip(/alias\s+:([A-Za-z0-9_]*[\[\]]{0,2}[?!=]?)\s+:([A-Za-z0-9_]*[\[\]]{0,2}[?!=]?)/) # Alias
|
385
|
+
@class.add_alias(@str[1], @str[2]) if @class.respond_to?(:add_alias)
|
386
|
+
elsif @str.skip(/(pre|post)_func\s+do/)
|
387
|
+
where = @str[1]
|
388
|
+
str = @str.scan_until(/\bend/)#[0,-4]
|
389
|
+
unless str
|
390
|
+
syntax_error "Invalid #{where}_func definition"
|
391
|
+
end
|
392
|
+
str = str[0..-4].strip
|
393
|
+
except = only = nil
|
394
|
+
@str.skip(/\s*/)
|
395
|
+
if @str.skip(/,\s*:(only|except)\s*=\>\s*(\[[^\]]+\])/)
|
396
|
+
if @str[1] == 'only'
|
397
|
+
only = eval(@str[2]).map{|i|i.to_s}
|
398
|
+
else
|
399
|
+
except = eval(@str[2]).map{|i|i.to_s}
|
400
|
+
end
|
401
|
+
end
|
402
|
+
if where == 'pre'
|
403
|
+
@class.pre_func = str
|
404
|
+
@class.pre_only = only if only
|
405
|
+
@class.pre_except = except if except
|
406
|
+
else
|
407
|
+
@class.post_func = str
|
408
|
+
@class.post_only = only if only
|
409
|
+
@class.post_except = except if except
|
410
|
+
end
|
411
|
+
elsif @str.skip(/pre_func\s+(.*)/) # Pre func code
|
412
|
+
@class.pre_func= @str[1] if @class.respond_to?(:pre_func)
|
413
|
+
elsif @str.skip(/post_func\s+(.*)/) # Post func code
|
414
|
+
@class.post_func= @str[1] if @class.respond_to?(:post_func)
|
415
|
+
elsif @str.skip(/def(?=\s+)/x) # Function defn
|
416
|
+
@str.skip(/\s+/)
|
417
|
+
if @str.scan(/([a-zA-Z_* 0-9]+):/)
|
418
|
+
returntype = @str[1]
|
419
|
+
elsif @str.skip(/(GS?List)[{]([^}]+)[}]:/)
|
420
|
+
container = @str[1]
|
421
|
+
ct = @str[2]
|
422
|
+
cn = ct.gsub(/\s+/,'').gsub(/[*]/,'__p')
|
423
|
+
rule = container+'{'+ct+'}'
|
424
|
+
returntype = rule
|
425
|
+
|
426
|
+
#syntax_error "Auto converting (#{rule}) GSList of #{ct} is not yet supported"
|
427
|
+
# sane
|
428
|
+
unless $custom_maps[rule] && $custom_maps[rule]['VALUE']
|
429
|
+
function = "rubber_#{container}_of_#{cn}_to_array"
|
430
|
+
@raw = @raw.to_s + <<-EOADD
|
390
431
|
inline VALUE #{function}(#{container} *list) {
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
432
|
+
#{container} *p; volatile VALUE ary;
|
433
|
+
ary = rb_ary_new();
|
434
|
+
for(p = list ; p ; p = p->next) {
|
435
|
+
rb_ary_push(ary, #{Rubber.explicit_cast('(('+ct+') p->data )', ct, 'VALUE')});
|
436
|
+
}
|
437
|
+
return ary;
|
397
438
|
}
|
398
|
-
EOADD
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
439
|
+
EOADD
|
440
|
+
$custom_maps[rule] ||={}
|
441
|
+
$custom_maps[rule]['VALUE'] = function+"(%%)"
|
442
|
+
end
|
443
|
+
else
|
444
|
+
returntype = 'VALUE'
|
445
|
+
end
|
446
|
+
prename = ''
|
447
|
+
prename = @str.scan(/self\./)
|
448
|
+
name = @str.scan(/[a-z_0-9A-Z.]+[?!=]?/)
|
449
|
+
unless name
|
450
|
+
name = @str.scan(/[-\[\]<>~=+|&]{1,3}/)
|
451
|
+
end
|
452
|
+
oname = name
|
453
|
+
name = prename.to_s + oname
|
454
|
+
#p [prename, oname, name]
|
455
|
+
@str.skip(/\s*/)
|
456
|
+
args = scan_args().collect { |i| C_Param.new(i) }
|
457
|
+
func = @functions[name] = C_Function.new(name, args, '')
|
458
|
+
func.returntype = returntype
|
459
|
+
func.parent = @class
|
460
|
+
stack.last.functions.push(func)
|
461
|
+
puts "def "+ func.fullname
|
462
|
+
stack.push(func)
|
463
|
+
func.source_line = current_line
|
464
|
+
func.source_file = current_file
|
465
|
+
state.in_func = true
|
466
|
+
|
467
|
+
elsif state.in_func == false and @str.skip(/(string|integer|float|double|int)(?= )/x) # C String as module wrapper
|
468
|
+
type= @str[1]
|
469
|
+
@str.skip_ws
|
470
|
+
name = @str.scan_constant
|
471
|
+
@str.skip(/\s*=\s*/)
|
472
|
+
if @str.skip(/"/) #"
|
473
|
+
string = '"' + @str.scan_until(/[^\\]?"/) #"
|
474
|
+
elsif t = @str.scan_constant
|
475
|
+
string = @str[1]
|
476
|
+
elsif type =~ /^(flo|dou|int)/ and t = @str.scan_number #@str.scan(/(0x)?([0-9]+(\.[0-9]+)?(e[0-9]+)?)/)
|
477
|
+
string = @str[1]
|
478
|
+
end
|
479
|
+
klass = nil
|
480
|
+
case type
|
481
|
+
when /^str/
|
482
|
+
klass = C_String
|
483
|
+
when /^int/
|
484
|
+
klass = C_Integer
|
485
|
+
when /^(flo|dou)/
|
486
|
+
klass = C_Float
|
487
|
+
end
|
488
|
+
stack.last.classes.push(klass.new(name, string, stack.last)) if klass
|
489
|
+
elsif state.in_func == false && @str.skip(/(array)(?= )/x)
|
490
|
+
type = @str[1]
|
491
|
+
@str.skip_ws
|
492
|
+
name = @str.scan_constant
|
493
|
+
@str.skip_ws
|
494
|
+
@str.skip(/=/)
|
495
|
+
@str.skip_ws
|
496
|
+
values = []
|
497
|
+
if @str.skip(/\[/)
|
498
|
+
@str.skip_ws
|
499
|
+
until @str.skip(/\]/)
|
500
|
+
if @str.scan_lit_string
|
501
|
+
values << { :string => @str[1] } # unescape escaped chars?
|
502
|
+
elsif @str.scan_lit_float
|
503
|
+
values << { :float => @str[1] }
|
504
|
+
elsif @str.scan_lit_integer
|
505
|
+
values << { :int => @str[1] }
|
506
|
+
elsif @str.skip_nil
|
507
|
+
values << { :nil => true }
|
508
|
+
elsif @str.scan_lit_bool
|
509
|
+
values << { :bool => @str[1].upcase.eql?('TRUE') }
|
510
|
+
elsif @str.scan_literal
|
511
|
+
values << { :int => @str[1] } # Assume a constant
|
512
|
+
else
|
513
|
+
syntax_error "Unrecognised array value"
|
514
|
+
end
|
515
|
+
@str.skip_ws
|
516
|
+
@str.skip(/,/)
|
517
|
+
@str.skip_ws
|
518
|
+
end
|
519
|
+
stack.last.classes.push(C_Array.new(name, values, stack.last))
|
520
|
+
p [ :create_array, values ]
|
521
|
+
else
|
522
|
+
syntax_error "Arrays should be in the form: [value1, value2, ... valueN]"
|
523
|
+
end
|
524
|
+
elsif txt = @str.get_byte # Spare chars
|
525
|
+
if state.in_func
|
526
|
+
func.text += txt
|
527
|
+
else
|
528
|
+
syntax_error "Invalid character #{txt}"
|
529
|
+
end
|
530
|
+
end
|
446
531
|
end
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
if @str.skip(/(".*?[^\\]")/)
|
458
|
-
values << { :string => @str[1] } # unescape escaped chars?
|
459
|
-
elsif @str.skip(/(\d[.]\d+)/)
|
460
|
-
values << { :float => @str[1] }
|
461
|
-
elsif @str.skip(/(\d+)/)
|
462
|
-
values << { :int => @str[1] }
|
463
|
-
elsif @str.skip(/NULL/)
|
464
|
-
values << { :nil => true }
|
465
|
-
elsif @str.skip(/(TRUE|FALSE)/)
|
466
|
-
values << { :bool => @str[1] == 'TRUE' }
|
467
|
-
elsif @str.skip(/([A-Za-z0-9_]+)/)
|
468
|
-
values << { :int => @str[1] } # Assume a constant
|
469
|
-
else
|
470
|
-
syntax_error "Unrecognised array value"
|
471
|
-
end
|
472
|
-
@str.skip(/\s*,\s*/)
|
473
|
-
end
|
474
|
-
stack.last.classes.push(C_Array.new(name, values, stack.last))
|
475
|
-
p [ :create_array, values ]
|
476
|
-
else
|
477
|
-
syntax_error "Arrays should be in the form: [value1, value2, ... valueN]"
|
478
|
-
end
|
479
|
-
elsif txt = @str.get_byte # Spare chars
|
480
|
-
if state.in_func
|
481
|
-
func.text += txt
|
532
|
+
end
|
533
|
+
def current_line
|
534
|
+
count = 0
|
535
|
+
@string[0..@str.pos].each_byte { |b| count += 1 if b == 10 }
|
536
|
+
count
|
537
|
+
end
|
538
|
+
def syntax_error(message)
|
539
|
+
STDERR.puts "Syntax Error: #{message} at line #{current_line}\n"
|
540
|
+
if @str.rest.size > 255
|
541
|
+
STDERR.puts @str.rest[0..255]+"..."
|
482
542
|
else
|
483
|
-
|
543
|
+
STDERR.puts @str.rest
|
484
544
|
end
|
545
|
+
exit 1
|
546
|
+
end
|
547
|
+
def misc_error(message, show_location=true)
|
548
|
+
STDERR.puts "Error: #{message} at line #{current_line}\n"
|
549
|
+
if show_location
|
550
|
+
if @str.rest.size > 255
|
551
|
+
STDERR.puts @str.rest[0..255]+"..."
|
552
|
+
else
|
553
|
+
STDERR.puts @str.rest
|
554
|
+
end
|
555
|
+
end
|
556
|
+
exit 1
|
485
557
|
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
def current_line
|
489
|
-
count = 0
|
490
|
-
@string[0..@str.pos].each_byte { |b| count += 1 if b == 10 }
|
491
|
-
count
|
492
|
-
end
|
493
|
-
def syntax_error(message)
|
494
|
-
STDERR.puts "Syntax Error: #{message} at line #{current_line}\n"
|
495
|
-
if @str.rest.size > 255
|
496
|
-
STDERR.puts @str.rest[0..255]+"..."
|
497
|
-
else
|
498
|
-
STDERR.puts @str.rest
|
499
|
-
end
|
500
|
-
exit 1
|
501
|
-
end
|
502
|
-
def misc_error(message, show_location=true)
|
503
|
-
STDERR.puts "Error: #{message} at line #{current_line}\n"
|
504
|
-
if show_location
|
505
|
-
if @str.rest.size > 255
|
506
|
-
STDERR.puts @str.rest[0..255]+"..."
|
507
|
-
else
|
508
|
-
STDERR.puts @str.rest
|
509
|
-
end
|
510
|
-
end
|
511
|
-
exit 1
|
512
|
-
end
|
513
558
|
|
514
|
-
end
|
559
|
+
end
|
515
560
|
|
516
561
|
end # m Rubber
|
data/lib/rubber/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubber-generate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 22
|
10
|
+
version: 0.0.22
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Geoff Youngs
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-
|
18
|
+
date: 2013-10-29 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: " rubber-c-binder allows a rubyish means of generating bindings for C libraries,\n including (but not limited to) GObject based libraries.\n\n It allows C code to be written in the context of a ruby style class/method layout\n and eases type checking and conversion between Ruby & C datatypes.\n"
|
@@ -28,6 +28,7 @@ extra_rdoc_files:
|
|
28
28
|
- README.textile
|
29
29
|
files:
|
30
30
|
- bin/rubber-generate
|
31
|
+
- lib/rubber/tokens.rb
|
31
32
|
- lib/rubber/codegen/param.rb
|
32
33
|
- lib/rubber/codegen/ginterface.rb
|
33
34
|
- lib/rubber/codegen/genum.rb
|