2008-08-30 12:55:34 -04:00
|
|
|
$out = open("callback.h", "w")
|
|
|
|
|
2005-02-04 08:35:37 -05:00
|
|
|
$dl_h = ARGV[0] || "dl.h"
|
|
|
|
|
|
|
|
# import DLSTACK_SIZE, DLSTACK_ARGS and so on
|
|
|
|
File.open($dl_h){|f|
|
|
|
|
pre = ""
|
|
|
|
f.each{|line|
|
|
|
|
line.chop!
|
2008-08-30 01:48:09 -04:00
|
|
|
if( line[-1] == ?\\ )
|
2005-02-04 08:35:37 -05:00
|
|
|
line.chop!
|
|
|
|
line.concat(" ")
|
|
|
|
pre += line
|
|
|
|
next
|
|
|
|
end
|
|
|
|
if( pre.size > 0 )
|
|
|
|
line = pre + line
|
|
|
|
pre = ""
|
|
|
|
end
|
|
|
|
case line
|
|
|
|
when /#define\s+DLSTACK_SIZE\s+\(?(\d+)\)?/
|
|
|
|
DLSTACK_SIZE = $1.to_i
|
|
|
|
when /#define\s+DLSTACK_ARGS\s+(.+)/
|
|
|
|
DLSTACK_ARGS = $1.to_i
|
|
|
|
when /#define\s+DLTYPE_([A-Z_]+)\s+\(?(\d+)\)?/
|
|
|
|
eval("#{$1} = #{$2}")
|
|
|
|
when /#define\s+MAX_DLTYPE\s+\(?(\d+)\)?/
|
|
|
|
MAX_DLTYPE = $1.to_i
|
|
|
|
when /#define\s+MAX_CALLBACK\s+\(?(\d+)\)?/
|
|
|
|
MAX_CALLBACK = $1.to_i
|
|
|
|
end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CDECL = "cdecl"
|
|
|
|
STDCALL = "stdcall"
|
|
|
|
|
|
|
|
CALLTYPES = [CDECL, STDCALL]
|
|
|
|
|
|
|
|
DLTYPE = {
|
|
|
|
VOID => {
|
|
|
|
:name => 'void',
|
|
|
|
:type => 'void',
|
|
|
|
:conv => nil,
|
|
|
|
},
|
|
|
|
CHAR => {
|
|
|
|
:name => 'char',
|
|
|
|
:type => 'char',
|
|
|
|
:conv => 'NUM2CHR(%s)'
|
|
|
|
},
|
|
|
|
SHORT => {
|
|
|
|
:name => 'short',
|
|
|
|
:type => 'short',
|
|
|
|
:conv => 'NUM2INT(%s)',
|
|
|
|
},
|
|
|
|
INT => {
|
|
|
|
:name => 'int',
|
|
|
|
:type => 'int',
|
|
|
|
:conv => 'NUM2INT(%s)',
|
|
|
|
},
|
|
|
|
LONG => {
|
|
|
|
:name => 'long',
|
|
|
|
:type => 'long',
|
|
|
|
:conv => 'NUM2LONG(%s)',
|
|
|
|
},
|
|
|
|
LONG_LONG => {
|
|
|
|
:name => 'long_long',
|
|
|
|
:type => 'LONG_LONG',
|
|
|
|
:conv => 'NUM2LL(%s)',
|
|
|
|
},
|
|
|
|
FLOAT => {
|
|
|
|
:name => 'float',
|
|
|
|
:type => 'float',
|
* include/ruby/ruby.h: introduce 2 macros:
RFLOAT_VALUE(v), DOUBLE2NUM(dbl).
Rename RFloat#value -> RFloat#double_value.
Do not touch RFloat#double_value directly.
* bignum.c, insns.def, marshal.c, math.c, numeric.c, object.c,
pack.c, parse.y, process.c, random.c, sprintf.c, string.c,
time.c: apply above changes.
* ext/dl/mkcallback.rb, ext/json/ext/generator/generator.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13913 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-13 11:00:53 -05:00
|
|
|
:conv => 'RFLOAT_VALUE(%s)',
|
2005-02-04 08:35:37 -05:00
|
|
|
},
|
|
|
|
DOUBLE => {
|
|
|
|
:name => 'double',
|
|
|
|
:type => 'double',
|
* include/ruby/ruby.h: introduce 2 macros:
RFLOAT_VALUE(v), DOUBLE2NUM(dbl).
Rename RFloat#value -> RFloat#double_value.
Do not touch RFloat#double_value directly.
* bignum.c, insns.def, marshal.c, math.c, numeric.c, object.c,
pack.c, parse.y, process.c, random.c, sprintf.c, string.c,
time.c: apply above changes.
* ext/dl/mkcallback.rb, ext/json/ext/generator/generator.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13913 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-13 11:00:53 -05:00
|
|
|
:conv => 'RFLOAT_VALUE(%s)',
|
2005-02-04 08:35:37 -05:00
|
|
|
},
|
|
|
|
VOIDP => {
|
|
|
|
:name => 'ptr',
|
|
|
|
:type => 'void *',
|
|
|
|
:conv => 'NUM2PTR(%s)',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def func_name(ty, argc, n, calltype)
|
|
|
|
"rb_dl_callback_#{DLTYPE[ty][:name]}_#{argc}_#{n}_#{calltype}"
|
|
|
|
end
|
|
|
|
|
|
|
|
$out << (<<EOS)
|
|
|
|
VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
|
|
|
|
VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
|
|
|
|
/*static void *cdecl_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
|
|
|
|
/*static void *stdcall_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
|
2008-08-30 12:55:34 -04:00
|
|
|
ID rb_dl_cb_call;
|
2005-02-04 08:35:37 -05:00
|
|
|
EOS
|
|
|
|
|
2008-08-30 12:29:03 -04:00
|
|
|
def foreach_proc_entry
|
|
|
|
for calltype in CALLTYPES
|
|
|
|
case calltype
|
|
|
|
when CDECL
|
|
|
|
proc_entry = "rb_DLCdeclCallbackProcs"
|
|
|
|
when STDCALL
|
|
|
|
proc_entry = "rb_DLStdcallCallbackProcs"
|
|
|
|
else
|
|
|
|
raise "unknown calltype: #{calltype}"
|
|
|
|
end
|
|
|
|
yield calltype, proc_entry
|
2005-02-04 08:35:37 -05:00
|
|
|
end
|
2008-08-30 12:29:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def gencallback(ty, calltype, proc_entry, argc, n)
|
|
|
|
<<-EOS
|
2005-02-04 08:35:37 -05:00
|
|
|
|
2006-07-06 15:59:31 -04:00
|
|
|
static #{DLTYPE[ty][:type]}
|
|
|
|
FUNC_#{calltype.upcase}(#{func_name(ty,argc,n,calltype)})(#{(0...argc).collect{|i| "DLSTACK_TYPE stack" + i.to_s}.join(", ")})
|
2005-02-04 08:35:37 -05:00
|
|
|
{
|
2005-02-06 13:07:10 -05:00
|
|
|
VALUE ret, cb#{argc > 0 ? ", args[#{argc}]" : ""};
|
2005-02-04 08:35:37 -05:00
|
|
|
#{
|
|
|
|
(0...argc).collect{|i|
|
|
|
|
" args[%d] = LONG2NUM(stack%d);" % [i,i]
|
|
|
|
}.join("\n")
|
|
|
|
}
|
|
|
|
cb = rb_ary_entry(rb_ary_entry(#{proc_entry}, #{ty}), #{(n * DLSTACK_SIZE) + argc});
|
2008-08-30 12:55:34 -04:00
|
|
|
ret = rb_funcall2(cb, rb_dl_cb_call, #{argc}, #{argc > 0 ? 'args' : 'NULL'});
|
2005-02-04 08:35:37 -05:00
|
|
|
return #{DLTYPE[ty][:conv] ? DLTYPE[ty][:conv] % "ret" : ""};
|
|
|
|
}
|
|
|
|
|
2008-08-30 12:29:03 -04:00
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
|
|
|
def gen_push_proc_ary(ty, aryname)
|
|
|
|
sprintf(" rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
|
|
|
|
MAX_CALLBACK * DLSTACK_SIZE,
|
|
|
|
(0...MAX_CALLBACK).collect{
|
|
|
|
(0...DLSTACK_SIZE).collect{ "Qnil" }.join(",")
|
|
|
|
}.join(","))
|
|
|
|
end
|
|
|
|
|
|
|
|
def gen_push_addr_ary(ty, aryname, calltype)
|
|
|
|
sprintf(" rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
|
|
|
|
MAX_CALLBACK * DLSTACK_SIZE,
|
|
|
|
(0...MAX_CALLBACK).collect{|i|
|
|
|
|
(0...DLSTACK_SIZE).collect{|argc|
|
|
|
|
"PTR2NUM(%s)" % func_name(ty,argc,i,calltype)
|
|
|
|
}.join(",")
|
|
|
|
}.join(","))
|
|
|
|
end
|
|
|
|
|
2008-08-30 12:55:34 -04:00
|
|
|
def gen_callback_file(ty)
|
|
|
|
filename = "callback-#{ty}.c"
|
|
|
|
initname = "rb_dl_init_callbacks_#{ty}"
|
|
|
|
open(filename, "w") {|f|
|
|
|
|
f.puts <<-EOS
|
|
|
|
#include "dl.h"
|
|
|
|
extern VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
|
|
|
|
extern VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
|
|
|
|
extern ID rb_dl_cb_call;
|
|
|
|
EOS
|
|
|
|
yield f
|
|
|
|
f.puts <<-EOS
|
|
|
|
void
|
|
|
|
#{initname}()
|
|
|
|
{
|
|
|
|
#{gen_push_proc_ary(ty, "rb_DLCdeclCallbackProcs")}
|
|
|
|
#{gen_push_addr_ary(ty, "rb_DLCdeclCallbackAddrs", CDECL)}
|
|
|
|
#{gen_push_proc_ary(ty, "rb_DLStdcallCallbackProcs")}
|
|
|
|
#{gen_push_addr_ary(ty, "rb_DLStdcallCallbackAddrs", STDCALL)}
|
|
|
|
}
|
|
|
|
EOS
|
|
|
|
}
|
|
|
|
initname
|
|
|
|
end
|
|
|
|
|
|
|
|
for ty in 0...MAX_DLTYPE
|
|
|
|
initname = gen_callback_file(ty) {|f|
|
|
|
|
foreach_proc_entry do |calltype, proc_entry|
|
|
|
|
for argc in 0...DLSTACK_SIZE
|
|
|
|
for n in 0...MAX_CALLBACK
|
|
|
|
f << gencallback(ty, calltype, proc_entry, argc, n)
|
|
|
|
end
|
2005-02-04 08:35:37 -05:00
|
|
|
end
|
|
|
|
end
|
2008-08-30 12:55:34 -04:00
|
|
|
}
|
|
|
|
$out << "void #{initname}();\n"
|
2005-02-04 08:35:37 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
$out << (<<EOS)
|
|
|
|
static void
|
|
|
|
rb_dl_init_callbacks()
|
|
|
|
{
|
2008-08-30 01:42:06 -04:00
|
|
|
VALUE tmp;
|
2008-08-30 12:55:34 -04:00
|
|
|
rb_dl_cb_call = rb_intern("call");
|
2005-02-04 08:35:37 -05:00
|
|
|
|
2008-08-30 01:42:06 -04:00
|
|
|
tmp = rb_DLCdeclCallbackProcs = rb_ary_new();
|
|
|
|
rb_define_const(rb_mDL, "CdeclCallbackProcs", tmp);
|
|
|
|
|
|
|
|
tmp = rb_DLCdeclCallbackAddrs = rb_ary_new();
|
|
|
|
rb_define_const(rb_mDL, "CdeclCallbackAddrs", tmp);
|
|
|
|
|
|
|
|
tmp = rb_DLStdcallCallbackProcs = rb_ary_new();
|
|
|
|
rb_define_const(rb_mDL, "StdcallCallbackProcs", tmp);
|
|
|
|
|
|
|
|
tmp = rb_DLStdcallCallbackAddrs = rb_ary_new();
|
|
|
|
rb_define_const(rb_mDL, "StdcallCallbackAddrs", tmp);
|
|
|
|
|
2005-02-04 08:35:37 -05:00
|
|
|
#{
|
|
|
|
(0...MAX_DLTYPE).collect{|ty|
|
2008-08-30 23:56:30 -04:00
|
|
|
" rb_dl_init_callbacks_#{ty}();\n"
|
2008-08-30 12:55:34 -04:00
|
|
|
}.join("")
|
2005-02-04 08:35:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
EOS
|