ruby: add df_array, pointer_ary, move generated classes in DFHack

develop
jj 2012-04-20 01:29:52 +02:00
parent a450e9ddeb
commit 0952b76173
3 changed files with 115 additions and 53 deletions

@ -51,8 +51,7 @@ sub render_global_enum {
my ($name, $type) = @_;
my $rbname = rb_ucase($name);
# store constants in DFHack::EnumName and not in DFHack::MemHack::EnumName
push @lines_rb, "class ::DFHack::$rbname";
push @lines_rb, "class $rbname";
%seen_enum_name = ();
indent_rb {
render_enum_fields($type);
@ -81,7 +80,7 @@ sub render_global_bitfield {
my ($name, $type) = @_;
my $rbname = rb_ucase($name);
push @lines_rb, "class $rbname < Compound";
push @lines_rb, "class $rbname < MemHack::Compound";
indent_rb {
render_bitfield_fields($type);
};
@ -142,7 +141,7 @@ sub render_global_class {
}
}
my $rbparent = ($parent ? rb_ucase($parent) : 'Compound');
my $rbparent = ($parent ? rb_ucase($parent) : 'MemHack::Compound');
my $cppvar = "v_$cpp_var_counter";
$cpp_var_counter++;
@ -191,7 +190,7 @@ sub render_global_objects {
push @lines_cpp, "void cpp_$sname(FILE *fout) {";
push @include_cpp, $sname;
push @lines_rb, "class $rbname < Compound";
push @lines_rb, "class $rbname < MemHack::Compound";
indent_rb {
for my $obj (@objects) {
my $oname = $obj->getAttribute('name');
@ -208,7 +207,6 @@ sub render_global_objects {
};
push @lines_rb, "end";
push @lines_rb, "module ::DFHack";
indent_rb {
push @lines_rb, "Global = GlobalObjects.new._at(0)";
for my $obj (@global_objects) {
@ -216,7 +214,6 @@ sub render_global_objects {
push @lines_rb, "def self.$obj=(v) ; Global.$obj = v ; end";
}
};
push @lines_rb, "end";
}
@ -325,8 +322,13 @@ sub render_item_pointer {
my ($item, $cppvar) = @_;
my $tg = $item->findnodes('child::ld:item')->[0];
my $tglen = get_tglen($tg, $cppvar);
push @lines_rb, "pointer($tglen) {";
my $ary = $item->getAttribute('is-array');
if ($ary and $ary eq 'true') {
my $tglen = get_tglen($tg, $cppvar);
push @lines_rb, "pointer_ary($tglen) {";
} else {
push @lines_rb, "pointer {";
}
indent_rb {
render_item($tg, "${cppvar}[0]");
};
@ -468,15 +470,13 @@ if ($output =~ /\.cpp$/) {
print FH "}\n";
} else {
print FH "module DFHack\n";
print FH "module MemHack\n";
if ($memstruct) {
open MH, "<$memstruct";
print FH "$_" while(<MH>);
close MH;
}
print FH "module DFHack\n";
print FH "$_\n" for @lines_rb;
print FH "end\n";
print FH "end\n";
}
close FH;

@ -1,6 +1,8 @@
module DFHack
module MemHack
class MemStruct
attr_accessor :_memaddr
def _at(addr) ; @_memaddr = addr ; self ; end
def _at(addr) ; @_memaddr = addr ; dup ; end
def _get ; self ; end
end
@ -27,8 +29,11 @@ class Compound < MemStruct
def bits(shift, len)
BitField.new(shift, len)
end
def pointer(tglen=nil)
Pointer.new(tglen, (yield if tglen))
def pointer
Pointer.new((yield if block_given?))
end
def pointer_ary(tglen)
PointerAry.new(tglen, yield)
end
def static_array(len, tglen)
StaticArray.new(tglen, len, yield)
@ -80,6 +85,7 @@ class Compound < MemStruct
end
def _set(h) ; h.each { |k, v| send("_#{k}=", v) } ; end
end
class Number < MemStruct
attr_accessor :_bits, :_signed
def initialize(bits, signed)
@ -149,6 +155,23 @@ class BitField < MemStruct
end
class Pointer < MemStruct
attr_accessor :_tg
def initialize(tg)
@_tg = tg
end
def _getp
DFHack.memory_read_int32(@_memaddr) & 0xffffffff
end
# the pointer is invisible, forward all methods to the pointed object
def method_missing(*a)
addr = _getp
tg = (addr == 0 ? nil : @_tg._at(addr)._get)
tg.send(*a)
end
end
class PointerAry < MemStruct
attr_accessor :_tglen, :_tg
def initialize(tglen, tg)
@_tglen = tglen
@ -159,10 +182,6 @@ class Pointer < MemStruct
delta = (i != 0 ? i*@_tglen : 0)
(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + delta
end
def _setp(v)
DFHack.memory_write_int32(@_memaddr, v)
end
def _get ; self ; end
def [](i)
addr = _getp(i)
@ -174,11 +193,6 @@ class Pointer < MemStruct
raise 'null pointer' if addr == 0
@_tg._at(addr)._set(v)
end
# the pointer is invisible, forward all methods to the pointed object
def method_missing(*a)
self[0].send(*a)
end
end
class StaticArray < MemStruct
attr_accessor :_tglen, :_length, :_tg
@ -205,7 +219,7 @@ class StaticArray < MemStruct
end
include Enumerable
def each; (0...length).each { |i| yield self[i] }; end
def each ; (0...length).each { |i| yield self[i] } ; end
end
class StaticString < MemStruct
attr_accessor :_length
@ -274,8 +288,9 @@ class StlVector32 < MemStruct
end
v
end
include Enumerable
def each; (0...length).each { |i| yield self[i] }; end
def each ; (0...length).each { |i| yield self[i] } ; end
end
class StlVector16 < StlVector32
def length
@ -346,19 +361,41 @@ class StlDeque < MemStruct
@_tglen = tglen
@_tg = tg
end
# TODO
end
class DfFlagarray < MemStruct
# TODO
end
class DfArray < MemStruct
class DfArray < Compound
attr_accessor :_tglen, :_tg
def initialize(tglen, tg)
@_tglen = tglen
@_tg = tg
end
# TODO
field(:_length, 0) { number 32, false }
field(:_ptr, 4) { number 32, false }
def length ; _length ; end
def size ; _length ; end
def _tgat(i)
@_tg._at(_ptr + i*@_tglen) if i >= 0 and i < _length
end
def [](i)
i += _length if i < 0
_tgat(i)._get
end
def []=(i, v)
i += _length if i < 0
_tgat(i)._set(v)
end
def _set(a)
a.each_with_index { |v, i| self[i] = v }
end
include Enumerable
def each ; (0...length).each { |i| yield self[i] } ; end
end
class DfLinkedList < MemStruct
attr_accessor :_tg
@ -373,33 +410,60 @@ class Global < MemStruct
@_glob = glob
end
def _at(addr)
g = DFHack::MemHack.const_get(@_glob)
g = DFHack.rtti_getclass(g, addr)
g = DFHack.const_get(@_glob)
g = DFHack.rtti_getclassat(g, addr)
g.new._at(addr)
end
end
end # module MemHack
module ::DFHack
def self.rtti_register(cname, cls)
@rtti_n2c ||= {}
@rtti_class ||= {}
@rtti_n2c[cname] = cls
@rtti_class[cls] = true
end
# return the ruby class to use for a given address if rtti info is available
def self.rtti_getclass(cls, addr)
@rtti_n2c ||= {}
@rtti_class ||= {}
if addr != 0 and @rtti_class[cls]
@rtti_n2c[rtti_readclassname(get_vtable_ptr(addr))] || cls
else
cls
end
# cpp rtti name -> rb class
@rtti_n2c = {}
@rtti_c2n = {}
# vtableptr -> cpp rtti name (cache)
@rtti_n2v = {}
@rtti_v2n = {}
def self.rtti_n2c ; @rtti_n2c ; end
def self.rtti_c2n ; @rtti_c2n ; end
# register a ruby class with a cpp rtti class name
def self.rtti_register(cname, cls)
@rtti_n2c[cname] = cls
@rtti_c2n[cls] = cname
end
# return the ruby class to use for the cpp object at address if rtti info is available
def self.rtti_getclassat(cls, addr)
if addr != 0 and @rtti_c2n[cls]
# rtti info exist for class => cpp object has a vtable
@rtti_n2c[rtti_readclassname(get_vtable_ptr(addr))] || cls
else
cls
end
end
def self.rtti_readclassname(vptr)
@rtti_v2n ||= {}
@rtti_v2n[vptr] ||= get_rtti_classname(vptr)
# try to read the rtti classname from an object vtable pointer
def self.rtti_readclassname(vptr)
unless n = @rtti_v2n[vptr]
n = @rtti_v2n[vptr] = get_rtti_classname(vptr)
@rtti_n2v[n] = vptr
end
n
end
# return the vtable pointer from the cpp rtti name
def self.rtti_getvtable(cname)
unless v = @rtti_n2v[cname]
v = get_vtable(cname)
@rtti_n2v[cname] = v
@rtti_v2n[v] = cname if v != 0
end
v if v != 0
end
end

@ -370,14 +370,12 @@ static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr)
static VALUE rb_dfget_global_address(VALUE self, VALUE name)
{
uint32_t addr = Core::getInstance().vinfo->getAddress(rb_string_value_ptr(&name));
return rb_uint2inum(addr);
return rb_uint2inum(Core::getInstance().vinfo->getAddress(rb_string_value_ptr(&name)));
}
static VALUE rb_dfget_vtable(VALUE self, VALUE name)
{
uint32_t addr = (uint32_t)Core::getInstance().vinfo->getVTable(rb_string_value_ptr(&name));
return rb_uint2inum(addr);
return rb_uint2inum((uint32_t)Core::getInstance().vinfo->getVTable(rb_string_value_ptr(&name)));
}
// read the c++ class name from a vtable pointer, inspired from doReadClassName