rubber-generate 0.0.5
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/README.md +58 -0
- data/bin/rubber-generate +54 -0
- data/lib/rubber/autord.rb +10 -0
- data/lib/rubber/codegen.rb +131 -0
- data/lib/rubber/codegen/class.rb +79 -0
- data/lib/rubber/codegen/enum.rb +231 -0
- data/lib/rubber/codegen/flags.rb +229 -0
- data/lib/rubber/codegen/float.rb +41 -0
- data/lib/rubber/codegen/function.rb +268 -0
- data/lib/rubber/codegen/gboxed.rb +30 -0
- data/lib/rubber/codegen/gcrefpool.rb +53 -0
- data/lib/rubber/codegen/genum.rb +33 -0
- data/lib/rubber/codegen/gflags.rb +38 -0
- data/lib/rubber/codegen/ginterface.rb +25 -0
- data/lib/rubber/codegen/gobject.rb +42 -0
- data/lib/rubber/codegen/integer.rb +41 -0
- data/lib/rubber/codegen/module.rb +63 -0
- data/lib/rubber/codegen/param.rb +92 -0
- data/lib/rubber/codegen/string.rb +41 -0
- data/lib/rubber/codegen/struct.rb +63 -0
- data/lib/rubber/mkextconf.rb +95 -0
- data/lib/rubber/scanner.rb +419 -0
- data/lib/rubber/struct.rb +52 -0
- data/lib/rubber/types.rb +222 -0
- metadata +85 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
module Rubber
|
2
|
+
|
3
|
+
class C_Flags
|
4
|
+
define_members :name, :args, :parent
|
5
|
+
attr_reader :child_names
|
6
|
+
@@declared_base = false
|
7
|
+
@@declared_register = false
|
8
|
+
def init()
|
9
|
+
($custom_maps[name] ||= {})["VALUE"] = "flags_#{name}_to_ruby((%%))"
|
10
|
+
($custom_maps["VALUE"] ||= {})[name] = "flags_ruby_to_#{name}((%%))"
|
11
|
+
@splits = strip_prefixes(args)
|
12
|
+
@strip = args.first.length - @splits.first.length
|
13
|
+
end
|
14
|
+
def code(io)
|
15
|
+
end
|
16
|
+
def declare(io)
|
17
|
+
io.puts "static VALUE #{cname};"
|
18
|
+
unless @@declared_base
|
19
|
+
@@declared_base = true
|
20
|
+
io.puts "
|
21
|
+
|
22
|
+
static VALUE flagsBaseClass;
|
23
|
+
|
24
|
+
typedef struct {
|
25
|
+
int value;
|
26
|
+
char *name;
|
27
|
+
char *fullname;
|
28
|
+
} FlagsData;
|
29
|
+
|
30
|
+
static VALUE make_flags_value(VALUE klass, int value, char *name, char *fullname)
|
31
|
+
{
|
32
|
+
FlagsData *data = NULL;
|
33
|
+
|
34
|
+
data = ALLOC(FlagsData);
|
35
|
+
data->value = value;
|
36
|
+
data->name = name;
|
37
|
+
data->fullname = fullname;
|
38
|
+
|
39
|
+
return Data_Wrap_Struct(klass, NULL, free, data);
|
40
|
+
}
|
41
|
+
static int value_to_int(VALUE value, VALUE klass)
|
42
|
+
{
|
43
|
+
switch (TYPE(value))
|
44
|
+
{
|
45
|
+
case T_FIXNUM:
|
46
|
+
case T_FLOAT:
|
47
|
+
return NUM2INT(value);
|
48
|
+
break;
|
49
|
+
case T_DATA:
|
50
|
+
if (rb_obj_is_kind_of(value, flagsBaseClass))
|
51
|
+
{
|
52
|
+
FlagsData *data = NULL;
|
53
|
+
|
54
|
+
if ((klass != Qnil) && (!rb_obj_is_kind_of(value, klass)))
|
55
|
+
{
|
56
|
+
rb_raise(rb_eTypeError, \"Wrong type of flags %s (%s required)\", rb_obj_classname(value), rb_class2name(klass));
|
57
|
+
}
|
58
|
+
|
59
|
+
Data_Get_Struct(value, FlagsData, data);
|
60
|
+
return data->value;
|
61
|
+
}
|
62
|
+
break;
|
63
|
+
}
|
64
|
+
return 0;
|
65
|
+
|
66
|
+
}
|
67
|
+
|
68
|
+
static VALUE rubber_flags_inspect(VALUE value)
|
69
|
+
{
|
70
|
+
FlagsData *data = NULL;
|
71
|
+
volatile VALUE str = rb_str_new(\"#<\", 2);
|
72
|
+
char number[16] = \"\";
|
73
|
+
|
74
|
+
Data_Get_Struct(value, FlagsData, data);
|
75
|
+
|
76
|
+
rb_str_cat2(str, rb_obj_classname(value));
|
77
|
+
rb_str_cat2(str, \" - \");
|
78
|
+
rb_str_cat2(str, data->name);
|
79
|
+
rb_str_cat2(str, \"(\");
|
80
|
+
sprintf(number, \"%i\", data->value);
|
81
|
+
rb_str_cat2(str, number);
|
82
|
+
rb_str_cat2(str, \")>\");
|
83
|
+
|
84
|
+
return str;
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE rubber_flags_to_s(VALUE value)
|
88
|
+
{
|
89
|
+
FlagsData *data = NULL;
|
90
|
+
|
91
|
+
Data_Get_Struct(value, FlagsData, data);
|
92
|
+
|
93
|
+
return rb_str_new2(data->fullname);
|
94
|
+
}
|
95
|
+
static VALUE rubber_flags_name(VALUE value)
|
96
|
+
{
|
97
|
+
FlagsData *data = NULL;
|
98
|
+
|
99
|
+
Data_Get_Struct(value, FlagsData, data);
|
100
|
+
|
101
|
+
return rb_str_new2(data->name);
|
102
|
+
}
|
103
|
+
|
104
|
+
static VALUE rubber_flags_cmp(VALUE value, VALUE other)
|
105
|
+
{
|
106
|
+
VALUE a,b;
|
107
|
+
a = rb_funcall(value, rb_intern(\"to_i\"), 0);
|
108
|
+
b = rb_funcall(other, rb_intern(\"to_i\"), 0);
|
109
|
+
return rb_num_coerce_cmp(a, b);
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE rubber_flags_to_i(VALUE value)
|
113
|
+
{
|
114
|
+
FlagsData *data = NULL;
|
115
|
+
|
116
|
+
Data_Get_Struct(value, FlagsData, data);
|
117
|
+
|
118
|
+
return INT2FIX(data->value);
|
119
|
+
}
|
120
|
+
|
121
|
+
static VALUE rubber_flags_coerce(VALUE value, VALUE other)
|
122
|
+
{
|
123
|
+
FlagsData *data = NULL;
|
124
|
+
|
125
|
+
Data_Get_Struct(value, FlagsData, data);
|
126
|
+
|
127
|
+
switch(TYPE(other))
|
128
|
+
{
|
129
|
+
case T_FIXNUM:
|
130
|
+
case T_BIGNUM:
|
131
|
+
return INT2FIX(data->value);
|
132
|
+
case T_FLOAT:
|
133
|
+
return Qnil;
|
134
|
+
default:
|
135
|
+
return Qnil;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
"
|
140
|
+
end
|
141
|
+
args.each do |arg|
|
142
|
+
io.puts "static VALUE #{default_cname}_#{arg} = Qnil;"
|
143
|
+
end
|
144
|
+
io.puts "typedef int #{name};
|
145
|
+
#ifdef __GNUC__
|
146
|
+
// No point in declaring these unless we're using GCC
|
147
|
+
// They're ahead of any code that uses them anyway.
|
148
|
+
static VALUE flags_#{name}_to_ruby(int value)
|
149
|
+
__attribute__ ((unused))
|
150
|
+
;
|
151
|
+
static int flags_ruby_to_#{name}(VALUE val)
|
152
|
+
__attribute__ ((unused))
|
153
|
+
;
|
154
|
+
#endif
|
155
|
+
|
156
|
+
"
|
157
|
+
io.puts "static VALUE flags_#{name}_to_ruby(int value) { switch(value) {"
|
158
|
+
args.each do |arg|
|
159
|
+
io.puts " case #{arg}: return #{default_cname}_#{arg};"
|
160
|
+
end
|
161
|
+
io.puts "}; return Qnil; }"
|
162
|
+
io.puts "static int flags_ruby_to_#{name}(VALUE val) { return value_to_int(val, #{cname}); }"
|
163
|
+
end
|
164
|
+
include RegisterChildren
|
165
|
+
def default_cname
|
166
|
+
"flags"+name
|
167
|
+
end
|
168
|
+
def doc_rd(io)
|
169
|
+
depth = (fullname.gsub(/[^:]/,'').size >> 1)
|
170
|
+
io.puts "=#{'=' * depth} flags #{fullname}"
|
171
|
+
end
|
172
|
+
def get_root(); is_root? ? self : parent.get_root; end; def is_root?()
|
173
|
+
not parent.respond_to?(:fullname)
|
174
|
+
end
|
175
|
+
def fullname()
|
176
|
+
if parent and parent.respond_to?(:fullname)
|
177
|
+
"#{parent.fullname}::#{name}"
|
178
|
+
else
|
179
|
+
name
|
180
|
+
end
|
181
|
+
end
|
182
|
+
def same_prefix(arr)
|
183
|
+
for i in arr
|
184
|
+
return false if arr.first.first != i.first
|
185
|
+
end
|
186
|
+
return true
|
187
|
+
end
|
188
|
+
def strip_prefixes(arr)
|
189
|
+
splits = arr.collect { |i| i.strip.split(/_/) }
|
190
|
+
while (same_prefix(splits))
|
191
|
+
splits.each { |i| i.shift }
|
192
|
+
end
|
193
|
+
splits.collect!{|i| i.join('_') }
|
194
|
+
splits
|
195
|
+
end
|
196
|
+
def get_root(); is_root? ? self : parent.get_root; end;
|
197
|
+
def is_root?()
|
198
|
+
not parent.respond_to?(:fullname)
|
199
|
+
end
|
200
|
+
def register(io, already_defined=false)
|
201
|
+
unless @@declared_register
|
202
|
+
@@declared_register = true
|
203
|
+
io.puts " flagsBaseClass = rb_define_class(\"Flags\", rb_cObject);"
|
204
|
+
io.puts ' rb_define_method(flagsBaseClass, "inspect", rubber_flags_inspect, 0);'
|
205
|
+
io.puts ' rb_define_method(flagsBaseClass, "to_i", rubber_flags_to_i, 0);'
|
206
|
+
io.puts ' rb_define_method(flagsBaseClass, "coerce", rubber_flags_coerce, 1);'
|
207
|
+
io.puts ' rb_define_method(flagsBaseClass, "to_s", rubber_flags_to_s, 0);'
|
208
|
+
io.puts ' rb_define_method(flagsBaseClass, "to_str", rubber_flags_to_s, 0);'
|
209
|
+
io.puts ' rb_define_method(flagsBaseClass, "fullname", rubber_flags_to_s, 0);'
|
210
|
+
io.puts ' rb_define_method(flagsBaseClass, "name", rubber_flags_name, 0);'
|
211
|
+
io.puts ' rb_define_method(flagsBaseClass, "<=>", rubber_flags_cmp, 0);'
|
212
|
+
io.puts ' '
|
213
|
+
end
|
214
|
+
if parent
|
215
|
+
io.puts " #{cname} = rb_define_class_under(#{parent.cname}, #{name.inspect}, flagsBaseClass);"
|
216
|
+
else
|
217
|
+
io.puts " #{cname} = rb_define_class(#{name.inspect}, flagsBaseClass);"
|
218
|
+
end
|
219
|
+
|
220
|
+
args.each do |arg|
|
221
|
+
uniq = arg[@strip..-1]
|
222
|
+
io.puts " #{default_cname}_#{arg} = make_flags_value(#{cname}, #{arg}, #{uniq.downcase.gsub(/_/,'-').inspect}, #{arg.inspect});"
|
223
|
+
io.puts " rb_obj_freeze(#{default_cname}_#{arg});"
|
224
|
+
io.puts " rb_define_const(#{cname}, #{uniq.upcase.inspect}, #{default_cname}_#{arg});"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end # Rubber
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rubber
|
2
|
+
|
3
|
+
class C_Float
|
4
|
+
define_members :name, :number, :parent
|
5
|
+
def code(io)
|
6
|
+
end
|
7
|
+
def declare(io)
|
8
|
+
#io.puts "static VALUE #{cname};"
|
9
|
+
end
|
10
|
+
include RegisterChildren
|
11
|
+
def default_cname
|
12
|
+
#"enum"+name
|
13
|
+
end
|
14
|
+
def doc_rd(io)
|
15
|
+
depth = (fullname.gsub(/[^:]/,'').size >> 1)
|
16
|
+
io.puts "=#{'=' * depth} #{fullname}"
|
17
|
+
end
|
18
|
+
def get_root(); is_root? ? self : parent.get_root; end; def is_root?()
|
19
|
+
not parent.respond_to?(:fullname)
|
20
|
+
end
|
21
|
+
def fullname()
|
22
|
+
if parent and parent.respond_to?(:fullname)
|
23
|
+
"#{parent.fullname}::#{name}"
|
24
|
+
else
|
25
|
+
name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def get_root(); is_root? ? self : parent.get_root; end;
|
29
|
+
def is_root?()
|
30
|
+
not parent.respond_to?(:fullname)
|
31
|
+
end
|
32
|
+
def register(io, already_defined=false)
|
33
|
+
if parent
|
34
|
+
io.puts " rb_define_const(#{parent.cname}, #{name.inspect}, rb_float_new(#{number}));"
|
35
|
+
else
|
36
|
+
raise "No parent for string constant #{name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Rubber
|
@@ -0,0 +1,268 @@
|
|
1
|
+
module Rubber
|
2
|
+
|
3
|
+
class C_Function
|
4
|
+
define_members(:name, :args, :text, :parent, {:autofree=>[]}, {:returntype=>'VALUE'}, :doc=>'')
|
5
|
+
attr_reader :multi, :block, :rest, :singleton
|
6
|
+
def check()
|
7
|
+
return if @checked
|
8
|
+
@block = @rest = @multi = false
|
9
|
+
@singleton = true if name.include?('.')
|
10
|
+
@arghash = {}
|
11
|
+
@min_args = 0
|
12
|
+
@opt_args = 0
|
13
|
+
args.each { |arg|
|
14
|
+
@arghash[arg.name] = arg
|
15
|
+
raise "Too many block parameters for #{parent.name}.#{name.gsub(/^self./,'')}" if @block and arg.block
|
16
|
+
raise "Too many rest parameters for #{parent.name}.#{name}" if @rest and arg.rest
|
17
|
+
@multi = true if arg.default or arg.rest
|
18
|
+
if @multi
|
19
|
+
@opt_args += 1 unless arg.block or arg.rest
|
20
|
+
else
|
21
|
+
@min_args += 1 unless arg.block
|
22
|
+
end
|
23
|
+
@block = arg if arg.block
|
24
|
+
@rest = arg if arg.rest
|
25
|
+
}
|
26
|
+
@scan_string = "#{@min_args}#{@opt_args}#{@rest ? "*" : ""}#{@block ? "&" : ""}"
|
27
|
+
@vars ||= {}
|
28
|
+
@checked = true
|
29
|
+
end
|
30
|
+
def rname()
|
31
|
+
name.split(/\./).last
|
32
|
+
end
|
33
|
+
#include RegisterChildren
|
34
|
+
def cname()
|
35
|
+
@cname ||= parent.name + ( @singleton ? '_CLASS' :'') + '_' + rname.gsub(/[?]/, '_query'). gsub(/[!]/, '_pling'). gsub(/[=]/, '_equals'). gsub(/[\[\]]/, '_brace')
|
36
|
+
end
|
37
|
+
def fullname()
|
38
|
+
check()
|
39
|
+
str = parent.fullname.dup
|
40
|
+
if name == 'initialize'
|
41
|
+
str << ".new"
|
42
|
+
else
|
43
|
+
str << ( @singleton ? (/^[a-zA-Z]/.match(rname) ? ".#{rname}" : rname) : "##{rname}")
|
44
|
+
end
|
45
|
+
str
|
46
|
+
end
|
47
|
+
def doc_rd(io)
|
48
|
+
io << "--- #{fullname}"
|
49
|
+
io << "(#{args.collect { |i| i.ruby_def }.join(', ')})\n" unless (fullname =~ /[!?]\z/ || !@singleton) and args.empty?
|
50
|
+
io.puts doc
|
51
|
+
io << "\n"
|
52
|
+
end
|
53
|
+
def prototype(io)
|
54
|
+
io.puts "static VALUE"
|
55
|
+
io.write "#{cname}("
|
56
|
+
if @multi
|
57
|
+
io.write "int __p_argc, VALUE *__p_argv, VALUE self"
|
58
|
+
else
|
59
|
+
io.write "VALUE self"
|
60
|
+
io.write(args.reject {|i| i.block }.collect { |i| ', VALUE ' + i.cname }.join(''))
|
61
|
+
#io.write ", " if args.size > 1 or (args.size > 0 and not @block)
|
62
|
+
end
|
63
|
+
io.write ")"
|
64
|
+
end
|
65
|
+
def declare(io)
|
66
|
+
check()
|
67
|
+
prototype(io)
|
68
|
+
io.puts ";"
|
69
|
+
end
|
70
|
+
def guess(name)
|
71
|
+
if name == 'self'
|
72
|
+
'VALUE'
|
73
|
+
elsif name == '_self' and parent.kind_of?(C_GObject)
|
74
|
+
'GObject*'
|
75
|
+
elsif @vars[name]
|
76
|
+
@vars[name]
|
77
|
+
else
|
78
|
+
if name =~ /^([A-Za-z0-9_]+)\[.*$/
|
79
|
+
if @vars[$1]
|
80
|
+
@vars[$1]
|
81
|
+
else
|
82
|
+
VALUE;
|
83
|
+
end
|
84
|
+
else
|
85
|
+
'VALUE'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
CAST_SAFER= /\<\{([a-z0-9A-Z* ]+)(>[a-z0-9A-Z* ]+)?:([^{};:]+)\}\>/
|
90
|
+
CAST= /\<([^:;{}]+):([a-z0-9A-Z* ]+)\>/
|
91
|
+
def code(io)
|
92
|
+
require 'stringio'
|
93
|
+
check()
|
94
|
+
prototype(io)
|
95
|
+
io.puts ""
|
96
|
+
io.puts "{"
|
97
|
+
oio = io
|
98
|
+
io = StringIO.new()
|
99
|
+
args.each { |arg|
|
100
|
+
arg.declare(io,self) unless not @multi and not arg.auto_convert? and not arg.block
|
101
|
+
}
|
102
|
+
parent.pre_func(io, self) if parent.respond_to?(:pre_func)
|
103
|
+
if @multi
|
104
|
+
io.puts ""
|
105
|
+
io.puts " /* Scan arguments */"
|
106
|
+
io.puts(" rb_scan_args(__p_argc, __p_argv, #{@scan_string.inspect},#{args.collect {|i| "&"+i.cname }.join(', ') });")
|
107
|
+
io.puts ""
|
108
|
+
|
109
|
+
io.puts " /* Set defaults */"
|
110
|
+
args.each_index { |i|
|
111
|
+
arg = args[i]
|
112
|
+
if arg.auto_convert?
|
113
|
+
io.write(" if (__p_argc > #{i})\n ") if arg.default
|
114
|
+
io.puts(" __orig_#{arg.name} = #{arg.name} = #{Rubber::explicit_cast(arg.cname, 'VALUE', arg.ctype)};")
|
115
|
+
io.puts(" else\n #{arg.name} = #{arg.default};") if arg.default
|
116
|
+
else
|
117
|
+
io.puts(" if (__p_argc <= #{i})\n #{arg.name} = #{arg.default};") if arg.default and not arg.block
|
118
|
+
io.puts(" else") if arg.default and arg.rtype
|
119
|
+
arg.check_type(io) if arg.rtype
|
120
|
+
end
|
121
|
+
io.puts "" if arg.default or arg.auto_convert?
|
122
|
+
}
|
123
|
+
#io.puts(" switch (argc) {")
|
124
|
+
#for i in @min_args .. @min_args + @opt_args
|
125
|
+
# io.puts " case #{i}:"
|
126
|
+
#end
|
127
|
+
#io.puts(" }")
|
128
|
+
else
|
129
|
+
args.each { |arg|
|
130
|
+
if arg.auto_convert?
|
131
|
+
io.puts(" __orig_#{arg.name} = #{arg.name} = #{Rubber::explicit_cast(arg.cname, 'VALUE', arg.ctype)};")
|
132
|
+
elsif arg.block
|
133
|
+
io.puts(" VALUE #{arg.name} = #{arg.init_value()};")
|
134
|
+
else
|
135
|
+
arg.check_type(io) if arg.rtype
|
136
|
+
end
|
137
|
+
}
|
138
|
+
end
|
139
|
+
io.puts ""
|
140
|
+
setupvars = io.string
|
141
|
+
io = oio
|
142
|
+
|
143
|
+
returned = false
|
144
|
+
oio =io
|
145
|
+
io = StringIO.new()
|
146
|
+
sc = StringScanner.new(text.strip)
|
147
|
+
io.write " " # Initial indent
|
148
|
+
until sc.empty?
|
149
|
+
if txt = sc.scan(CAST_SAFER)
|
150
|
+
from_type, to_type, cast = sc[1], sc[2], sc[3]
|
151
|
+
arg = @arghash[cast]
|
152
|
+
to_type = to_type[1..-1] unless to_type.nil? or to_type.empty?
|
153
|
+
to_type = (!(to_type.nil? or to_type.empty?) && to_type || (arg && arg.ctype || guess(cast)))
|
154
|
+
io.write(Rubber.explicit_cast(cast, from_type, to_type))
|
155
|
+
elsif txt = sc.scan(CAST)
|
156
|
+
warn("<TYPE:VALUE> is deprecated - please use <{FROM_TYPE>TO_TYPE:VALUE}> instead.")
|
157
|
+
name, cast = sc[1], sc[2]
|
158
|
+
arg = @arghash[name]
|
159
|
+
io.write(Rubber::explicit_cast(name, arg && arg.ctype || guess(name), cast))
|
160
|
+
elsif txt = sc.scan(/['"]/) #' Skip quoted string
|
161
|
+
txt += sc.scan_until(/(^|[^\\])#{txt}/) # Skip until unescaped quote
|
162
|
+
io.write(txt)
|
163
|
+
elsif c = sc.scan(/;/)
|
164
|
+
io.write ";\n "
|
165
|
+
elsif c = sc.scan(/return\s+/)
|
166
|
+
val = sc.scan_until(/;/)
|
167
|
+
val.strip! if val
|
168
|
+
if val and val.size > 1
|
169
|
+
val.chop! # Trim last char
|
170
|
+
io.write "do { __p_retval = "
|
171
|
+
# Scan returned bit for casts
|
172
|
+
retval = ""
|
173
|
+
mini_scanner = StringScanner.new(val)
|
174
|
+
until mini_scanner.eos?
|
175
|
+
if txt = mini_scanner.scan(CAST_SAFER)
|
176
|
+
from_type, to_type, cast = mini_scanner[1], mini_scanner[2], mini_scanner[3]
|
177
|
+
arg = @arghash[cast]
|
178
|
+
to_type = to_type[1..-1] unless to_type.nil? or to_type.empty?
|
179
|
+
to_type = (!(to_type.nil? or to_type.empty?) && to_type || (arg && arg.ctype || guess(cast)))
|
180
|
+
retval << (Rubber::explicit_cast(cast, from_type, to_type))
|
181
|
+
elsif txt = mini_scanner.scan(CAST)
|
182
|
+
warn("<TYPE:VALUE> is deprecated - please use <{TYPE>TO:VALUE}> instead.")
|
183
|
+
name, cast = mini_scanner[1], mini_scanner[2]
|
184
|
+
arg = @arghash[name]
|
185
|
+
retval << (Rubber::explicit_cast(name, arg && arg.ctype || guess(name), cast))
|
186
|
+
else
|
187
|
+
retval << (mini_scanner.get_byte)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
unless Rubber::native_type?(returntype)
|
191
|
+
io << Rubber::explicit_cast(retval, returntype, 'VALUE')
|
192
|
+
else
|
193
|
+
io << retval
|
194
|
+
end
|
195
|
+
#end of internal scan
|
196
|
+
io.write "; goto out; } while(0);"
|
197
|
+
returned = true
|
198
|
+
else
|
199
|
+
parent.post_func(io, self) if parent.respond_to?(:post_func)
|
200
|
+
io.write(";")
|
201
|
+
end
|
202
|
+
elsif c = sc.scan(/([a-z0-9A-Z_]+[ *]+)([a-zA-Z0-9]+)\s*([\[\]0-9]*)\s*([;=])/)
|
203
|
+
io.write "#{[sc[1], sc[2], sc[3], sc[4]].join(' ')}\n"
|
204
|
+
@vars ||= {}
|
205
|
+
base = sc[1].split(/\s/).first
|
206
|
+
p = 0
|
207
|
+
(sc[1]+sc[3]).each_byte { |i| p += 1 if i == ?[ or i == ?* }
|
208
|
+
@vars[sc[2]] = base.strip + ( p > 0 && (' ' + ('*' * p)) || '' )
|
209
|
+
elsif c = sc.get_byte
|
210
|
+
io.write(c)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
code = io.string
|
215
|
+
io = oio
|
216
|
+
|
217
|
+
|
218
|
+
io.puts " VALUE __p_retval = #{default()};" if returned
|
219
|
+
io.puts setupvars
|
220
|
+
io.puts "\n do {" if @vars and not @vars.empty?
|
221
|
+
io.puts code
|
222
|
+
io.puts "\n } while(0);\n\n" if @vars and not @vars.empty?
|
223
|
+
io.puts "out:" if returned
|
224
|
+
parent.post_func(io, self) if parent.respond_to?(:post_func)
|
225
|
+
|
226
|
+
args.each { |arg|
|
227
|
+
if arg.auto_convert? && $custom_frees[arg.ctype.gsub(/ /,'')]
|
228
|
+
io.puts($custom_frees[arg.ctype].gsub(/%%/,"__orig_#{arg.name}")+";")
|
229
|
+
end
|
230
|
+
}
|
231
|
+
|
232
|
+
if returned
|
233
|
+
io.puts " return __p_retval;"
|
234
|
+
else
|
235
|
+
io.puts " return #{default()};"
|
236
|
+
end
|
237
|
+
io.puts "}"
|
238
|
+
io.puts ""
|
239
|
+
end
|
240
|
+
def default
|
241
|
+
if rname =~ /=\z/ and args.size == 1
|
242
|
+
args.first.cname
|
243
|
+
elsif rname =~ /\Aset_/
|
244
|
+
"self"
|
245
|
+
else
|
246
|
+
"Qnil"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
def arity()
|
250
|
+
check()
|
251
|
+
return -1 if @multi
|
252
|
+
num = args.size
|
253
|
+
num -= 1 if @block
|
254
|
+
num
|
255
|
+
end
|
256
|
+
def alloc_func?
|
257
|
+
name.split(/\./,2).last == '__alloc__'
|
258
|
+
end
|
259
|
+
def register(io, already_defined=false)
|
260
|
+
if alloc_func?
|
261
|
+
io.puts " rb_define_alloc_func(#{parent.cname}, #{cname});"
|
262
|
+
else
|
263
|
+
io.puts " rb_define_#{@singleton ? "singleton_" : ""}method(#{parent.cname}, #{rname.inspect}, #{cname}, #{arity});"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
end # Rubber
|