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.
@@ -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