|
|
@ -11,8 +11,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include "tinythread.h"
|
|
|
|
#include "tinythread.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <ruby.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using namespace DFHack;
|
|
|
|
using namespace DFHack;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -20,6 +18,8 @@ using namespace DFHack;
|
|
|
|
// DFHack stuff
|
|
|
|
// DFHack stuff
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int df_loadruby(void);
|
|
|
|
|
|
|
|
static void df_unloadruby(void);
|
|
|
|
static void df_rubythread(void*);
|
|
|
|
static void df_rubythread(void*);
|
|
|
|
static command_result df_rubyload(color_ostream &out, std::vector <std::string> & parameters);
|
|
|
|
static command_result df_rubyload(color_ostream &out, std::vector <std::string> & parameters);
|
|
|
|
static command_result df_rubyeval(color_ostream &out, std::vector <std::string> & parameters);
|
|
|
|
static command_result df_rubyeval(color_ostream &out, std::vector <std::string> & parameters);
|
|
|
@ -45,6 +45,11 @@ DFHACK_PLUGIN("ruby")
|
|
|
|
|
|
|
|
|
|
|
|
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
|
|
|
|
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!df_loadruby()) {
|
|
|
|
|
|
|
|
Core::printerr("failed to load libruby\n");
|
|
|
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_irun = new tthread::mutex();
|
|
|
|
m_irun = new tthread::mutex();
|
|
|
|
m_mutex = new tthread::mutex();
|
|
|
|
m_mutex = new tthread::mutex();
|
|
|
|
r_type = RB_INIT;
|
|
|
|
r_type = RB_INIT;
|
|
|
@ -90,6 +95,8 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
|
|
|
|
m_mutex->unlock();
|
|
|
|
m_mutex->unlock();
|
|
|
|
delete m_mutex;
|
|
|
|
delete m_mutex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df_unloadruby();
|
|
|
|
|
|
|
|
|
|
|
|
return CR_OK;
|
|
|
|
return CR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -191,6 +198,111 @@ static command_result df_rubyeval(color_ostream &out, std::vector <std::string>
|
|
|
|
|
|
|
|
|
|
|
|
// ruby stuff
|
|
|
|
// 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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// these ruby definitions are invalid for windows 64bit
|
|
|
|
|
|
|
|
typedef unsigned long VALUE;
|
|
|
|
|
|
|
|
typedef unsigned long ID;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define Qfalse ((VALUE)0)
|
|
|
|
|
|
|
|
#define Qtrue ((VALUE)2)
|
|
|
|
|
|
|
|
#define Qnil ((VALUE)4)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define INT2FIX(i) ((VALUE)((((long)i) << 1) | 1))
|
|
|
|
|
|
|
|
#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);
|
|
|
|
|
|
|
|
VALUE (*rb_float_new)(double);
|
|
|
|
|
|
|
|
double (*rb_num2dbl)(VALUE);
|
|
|
|
|
|
|
|
VALUE (*rb_int2inum)(long);
|
|
|
|
|
|
|
|
VALUE (*rb_uint2inum)(unsigned long);
|
|
|
|
|
|
|
|
unsigned long (*rb_num2ulong)(VALUE);
|
|
|
|
|
|
|
|
// end of rip(ruby.h)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DFHack::DFLibrary *libruby_handle;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the ruby library, initialize function pointers
|
|
|
|
|
|
|
|
static int df_loadruby(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *libpath =
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
|
|
|
"msvcrt-ruby191.dll";
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
"libruby1.9.so.1.9.0";
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libruby_handle = OpenPlugin(libpath);
|
|
|
|
|
|
|
|
if (!libruby_handle)
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
rbloadsym(ruby_init);
|
|
|
|
|
|
|
|
rbloadsym(ruby_init_loadpath);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
rbloadsym(rb_float_new);
|
|
|
|
|
|
|
|
rbloadsym(rb_num2dbl);
|
|
|
|
|
|
|
|
rbloadsym(rb_int2inum);
|
|
|
|
|
|
|
|
rbloadsym(rb_uint2inum);
|
|
|
|
|
|
|
|
rbloadsym(rb_num2ulong);
|
|
|
|
|
|
|
|
#undef rbloadsym
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void df_unloadruby(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (libruby_handle) {
|
|
|
|
|
|
|
|
ClosePlugin(libruby_handle);
|
|
|
|
|
|
|
|
libruby_handle = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ruby thread code
|
|
|
|
// ruby thread code
|
|
|
|
static void dump_rb_error(void)
|
|
|
|
static void dump_rb_error(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -353,7 +465,7 @@ static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr)
|
|
|
|
static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
rb_raise(rb_eRuntimeError, "not implemented");
|
|
|
|
rb_raise(*rb_eRuntimeError, "not implemented");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VALUE rb_dfget_global_address(VALUE self, VALUE name)
|
|
|
|
static VALUE rb_dfget_global_address(VALUE self, VALUE name)
|
|
|
@ -402,7 +514,7 @@ static VALUE rb_dfmalloc(VALUE self, VALUE len)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char *ptr = (char*)malloc(FIX2INT(len));
|
|
|
|
char *ptr = (char*)malloc(FIX2INT(len));
|
|
|
|
if (!ptr)
|
|
|
|
if (!ptr)
|
|
|
|
rb_raise(rb_eRuntimeError, "no memory");
|
|
|
|
rb_raise(*rb_eRuntimeError, "no memory");
|
|
|
|
memset(ptr, 0, FIX2INT(len));
|
|
|
|
memset(ptr, 0, FIX2INT(len));
|
|
|
|
return rb_uint2inum((long)ptr);
|
|
|
|
return rb_uint2inum((long)ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|