From 4c2d4d4b86355063d0eef3c93dc6b686448123b3 Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 24 Jun 2012 16:09:31 +0200 Subject: [PATCH] ruby: clean stuff up, install ruby modules in df/hack/ruby/ --- plugins/ruby/CMakeLists.txt | 7 +- plugins/ruby/{plugins => }/building.rb | 0 plugins/ruby/{plugins => }/plant.rb | 0 plugins/ruby/ruby.cpp | 105 +++---------------------- plugins/ruby/ruby.rb | 54 ++++++------- plugins/ruby/{plugins => }/unit.rb | 0 6 files changed, 43 insertions(+), 123 deletions(-) rename plugins/ruby/{plugins => }/building.rb (100%) rename plugins/ruby/{plugins => }/plant.rb (100%) rename plugins/ruby/{plugins => }/unit.rb (100%) diff --git a/plugins/ruby/CMakeLists.txt b/plugins/ruby/CMakeLists.txt index e69632e61..f33e41740 100644 --- a/plugins/ruby/CMakeLists.txt +++ b/plugins/ruby/CMakeLists.txt @@ -30,4 +30,9 @@ INCLUDE_DIRECTORIES("${dfhack_SOURCE_DIR}/depends/tthread") DFHACK_PLUGIN(ruby ruby.cpp LINK_LIBRARIES dfhack-tinythread) ADD_DEPENDENCIES(ruby ruby-autogen-rb) -INSTALL(FILES ruby.rb ruby-autogen.rb ${RUBYLIB} DESTINATION ${DFHACK_LIBRARY_DESTINATION}) +INSTALL(FILES ${RUBYLIB} DESTINATION ${DFHACK_LIBRARY_DESTINATION}) + +INSTALL(DIRECTORY . + DESTINATION hack/ruby + FILES_MATCHING PATTERN "*.rb") + diff --git a/plugins/ruby/plugins/building.rb b/plugins/ruby/building.rb similarity index 100% rename from plugins/ruby/plugins/building.rb rename to plugins/ruby/building.rb diff --git a/plugins/ruby/plugins/plant.rb b/plugins/ruby/plant.rb similarity index 100% rename from plugins/ruby/plugins/plant.rb rename to plugins/ruby/plant.rb diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index 630cca0e6..e3bed78b7 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -21,7 +21,6 @@ using namespace DFHack; static int df_loadruby(void); static void df_unloadruby(void); static void df_rubythread(void*); -static command_result df_rubyload(color_ostream &out, std::vector & parameters); static command_result df_rubyeval(color_ostream &out, std::vector & parameters); static void ruby_bind_dfhack(void); @@ -31,7 +30,6 @@ enum RB_command { RB_INIT, RB_DIE, RB_EVAL, - RB_CUSTOM, }; tthread::mutex *m_irun; tthread::mutex *m_mutex; @@ -66,10 +64,6 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector & parameters) -{ - if (parameters.size() == 1 && (parameters[0] == "help" || parameters[0] == "?")) - { - out.print("This command loads the ruby script whose path is given as parameter, and run it.\n"); - return CR_OK; - } - - std::string cmd = "load '"; - cmd += parameters[0]; // TODO escape singlequotes - cmd += "'"; - - return plugin_eval_rb(cmd); -} - static command_result df_rubyeval(color_ostream &out, std::vector & parameters) { command_result ret; @@ -206,13 +185,14 @@ static command_result df_rubyeval(color_ostream &out, std::vector // ruby stuff -// ruby-dev on windows is messy -// ruby.h on linux 64 is broken -// so we dynamically load libruby instead of linking it at compile time -// lib path can be set in dfhack.ini to use the system libruby, but by -// default we'll embed our own (downloaded by cmake) +// - ruby-dev on windows is messy +// - ruby.h with gcc -m32 on linux 64 is broken +// so we dynamically load libruby with dlopen/LoadLibrary +// lib path is hardcoded here, and by default downloaded by cmake +// this code should work with ruby1.9, but ruby1.9 doesn't like running +// in a dedicated non-main thread, so use ruby1.8 binaries only for now -// these ruby definitions are invalid for windows 64bit +// these ruby definitions are invalid for windows 64bit (need long long) typedef unsigned long VALUE; typedef unsigned long ID; @@ -224,23 +204,17 @@ typedef unsigned long ID; #define FIX2INT(i) (((long)i) >> 1) #define RUBY_METHOD_FUNC(func) ((VALUE(*)(...))func) -VALUE *rb_eRuntimeError; - void (*ruby_sysinit)(int *, const char ***); void (*ruby_init)(void); void (*ruby_init_loadpath)(void); void (*ruby_script)(const char*); void (*ruby_finalize)(void); ID (*rb_intern)(const char*); -VALUE (*rb_raise)(VALUE, const char*, ...); VALUE (*rb_funcall)(VALUE, ID, int, ...); VALUE (*rb_define_module)(const char*); void (*rb_define_singleton_method)(VALUE, const char*, VALUE(*)(...), int); -void (*rb_define_const)(VALUE, const char*, VALUE); -void (*rb_load_protect)(VALUE, int, int*); VALUE (*rb_gv_get)(const char*); VALUE (*rb_str_new)(const char*, long); -VALUE (*rb_str_new2)(const char*); char* (*rb_string_value_ptr)(VALUE*); VALUE (*rb_eval_string_protect)(const char*, int*); VALUE (*rb_ary_shift)(VALUE); @@ -269,11 +243,6 @@ static int df_loadruby(void) return 0; } - if (!(rb_eRuntimeError = (VALUE*)LookupPlugin(libruby_handle, "rb_eRuntimeError"))) - return 0; - - // XXX does msvc support decltype ? might need a #define decltype typeof - // or just assign to *(void**)(&s) = ... // ruby_sysinit is optional (ruby1.9 only) ruby_sysinit = (decltype(ruby_sysinit))LookupPlugin(libruby_handle, "ruby_sysinit"); #define rbloadsym(s) if (!(s = (decltype(s))LookupPlugin(libruby_handle, #s))) return 0 @@ -282,15 +251,11 @@ static int df_loadruby(void) rbloadsym(ruby_script); rbloadsym(ruby_finalize); rbloadsym(rb_intern); - rbloadsym(rb_raise); rbloadsym(rb_funcall); rbloadsym(rb_define_module); rbloadsym(rb_define_singleton_method); - rbloadsym(rb_define_const); - rbloadsym(rb_load_protect); rbloadsym(rb_gv_get); rbloadsym(rb_str_new); - rbloadsym(rb_str_new2); rbloadsym(rb_string_value_ptr); rbloadsym(rb_eval_string_protect); rbloadsym(rb_ary_shift); @@ -382,10 +347,6 @@ static void df_rubythread(void *p) if (state) dump_rb_error(); break; - - case RB_CUSTOM: - // TODO handle ruby custom commands - break; } r_result = CR_OK; @@ -431,30 +392,6 @@ static VALUE rb_dfsuspend(VALUE self) return Qtrue; } -// returns the delta to apply to dfhack xml addrs wrt actual memory addresses -// usage: real_addr = addr_from_xml + this_delta; -static VALUE rb_dfrebase_delta(void) -{ - uint32_t expected_base_address; - uint32_t actual_base_address = 0; -#ifdef WIN32 - expected_base_address = 0x00400000; - actual_base_address = (uint32_t)GetModuleHandle(0); -#else - expected_base_address = 0x08048000; - FILE *f = fopen("/proc/self/maps", "r"); - char line[256]; - while (fgets(line, sizeof(line), f)) { - if (strstr(line, "libs/Dwarf_Fortress")) { - actual_base_address = strtoul(line, 0, 16); - break; - } - } -#endif - - return rb_int2inum(actual_base_address - expected_base_address); -} - static VALUE rb_dfprint_str(VALUE self, VALUE s) { console_proxy->print("%s", rb_string_value_ptr(&s)); @@ -467,25 +404,6 @@ static VALUE rb_dfprint_err(VALUE self, VALUE s) return Qnil; } -/* TODO needs main dfhack support - this needs a custom DFHack::Plugin subclass to pass the cmdname to invoke(), to match the ruby callback -// register a ruby method as dfhack console command -// usage: DFHack.register("moo", "this commands prints moo on the console") { DFHack.puts "moo !" } -static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) -{ - commands.push_back(PluginCommand(rb_string_value_ptr(&name), - rb_string_value_ptr(&descr), - df_rubycustom)); - - return Qtrue; -} -*/ -static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) -{ - rb_raise(*rb_eRuntimeError, "not implemented"); - return Qnil; -} - static VALUE rb_dfget_global_address(VALUE self, VALUE name) { return rb_uint2inum(Core::getInstance().vinfo->getAddress(rb_string_value_ptr(&name))); @@ -511,7 +429,7 @@ static VALUE rb_dfget_rtti_classname(VALUE self, VALUE vptr) char *typestring = *(char**)(typeinfo + 0x4); while (*typestring >= '0' && *typestring <= '9') typestring++; - return rb_str_new2(typestring); + return rb_str_new(typestring, strlen(typestring)); #endif } @@ -532,7 +450,7 @@ static VALUE rb_dfmalloc(VALUE self, VALUE len) { char *ptr = (char*)malloc(FIX2INT(len)); if (!ptr) - rb_raise(*rb_eRuntimeError, "no memory"); + return Qnil; memset(ptr, 0, FIX2INT(len)); return rb_uint2inum((long)ptr); } @@ -821,13 +739,11 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "get_vtable", RUBY_METHOD_FUNC(rb_dfget_vtable), 1); rb_define_singleton_method(rb_cDFHack, "get_rtti_classname", RUBY_METHOD_FUNC(rb_dfget_rtti_classname), 1); rb_define_singleton_method(rb_cDFHack, "get_vtable_ptr", RUBY_METHOD_FUNC(rb_dfget_vtable_ptr), 1); - rb_define_singleton_method(rb_cDFHack, "register_dfcommand", RUBY_METHOD_FUNC(rb_dfregister), 2); rb_define_singleton_method(rb_cDFHack, "print_str", RUBY_METHOD_FUNC(rb_dfprint_str), 1); rb_define_singleton_method(rb_cDFHack, "print_err", RUBY_METHOD_FUNC(rb_dfprint_err), 1); rb_define_singleton_method(rb_cDFHack, "malloc", RUBY_METHOD_FUNC(rb_dfmalloc), 1); rb_define_singleton_method(rb_cDFHack, "free", RUBY_METHOD_FUNC(rb_dffree), 1); rb_define_singleton_method(rb_cDFHack, "vmethod_do_call", RUBY_METHOD_FUNC(rb_dfvcall), 6); - rb_define_const(rb_cDFHack, "REBASE_DELTA", rb_dfrebase_delta()); rb_define_singleton_method(rb_cDFHack, "memory_read", RUBY_METHOD_FUNC(rb_dfmemory_read), 2); rb_define_singleton_method(rb_cDFHack, "memory_read_int8", RUBY_METHOD_FUNC(rb_dfmemory_read_int8), 1); @@ -869,8 +785,7 @@ static void ruby_bind_dfhack(void) { // load the default ruby-level definitions int state=0; - // windows cmake installs files in df/, linux installs files in df/hack/ - rb_eval_string_protect("File.exist?('hack/ruby.rb') ? load('hack/ruby.rb') : load('ruby.rb')", &state); + rb_eval_string_protect("require './hack/ruby/ruby'", &state); if (state) dump_rb_error(); } diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index 9c11144c0..3a7d20a27 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -1,3 +1,26 @@ +module Kernel + def puts(*a) + a.flatten.each { |l| + DFHack.print_str(l.to_s.chomp + "\n") + } + nil + end + + def puts_err(*a) + a.flatten.each { |l| + DFHack.print_err(l.to_s.chomp + "\n") + } + nil + end + + def p(*a) + a.each { |e| + puts_err e.inspect + } + nil + end +end + module DFHack class << self # update the ruby.cpp version to accept a block @@ -14,28 +37,6 @@ module DFHack end end - module ::Kernel - def puts(*a) - a.flatten.each { |l| - DFHack.print_str(l.to_s.chomp + "\n") - } - nil - end - - def puts_err(*a) - a.flatten.each { |l| - DFHack.print_err(l.to_s.chomp + "\n") - } - nil - end - - def p(*a) - a.each { |e| - puts_err e.inspect - } - end - end - # register a callback to be called every gframe or more # ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 } def onupdate_register(&b) @@ -1047,8 +1048,7 @@ end end -# load autogen'd file -File.exist?('hack/ruby-autogen.rb') ? require('hack/ruby-autogen') : require('ruby-autogen') - -# load optional user-specified startup file -load 'ruby_custom.rb' if File.exist?('ruby_custom.rb') +# load autogenned file +require './hack/ruby/ruby-autogen' +# load all modules +Dir['./hack/ruby/*.rb'].each { |m| require m.chomp('.rb') } diff --git a/plugins/ruby/plugins/unit.rb b/plugins/ruby/unit.rb similarity index 100% rename from plugins/ruby/plugins/unit.rb rename to plugins/ruby/unit.rb