|
diff --git a/gdb/Makefile.in b/gdb/Makefile.in |
|
index 17b71c6..03dd88f 100644 |
|
--- a/gdb/Makefile.in |
|
+++ b/gdb/Makefile.in |
|
@@ -412,6 +412,15 @@ SUBDIR_PYTHON_DEPS = |
|
SUBDIR_PYTHON_LDFLAGS = |
|
SUBDIR_PYTHON_CFLAGS = |
|
|
|
+SUBDIR_RUBY_SRCS = \ |
|
+ ruby/ruby.c |
|
+ |
|
+SUBDIR_RUBY_OBS = $(patsubst %.c,%.o,$(SUBDIR_RUBY_SRCS)) |
|
+ |
|
+SUBDIR_RUBY_DEPS = |
|
+SUBDIR_RUBY_LDFLAGS = |
|
+SUBDIR_RUBY_CFLAGS = |
|
+ |
|
SUBDIR_UNITTESTS_SRCS = \ |
|
unittests/array-view-selftests.c \ |
|
unittests/common-utils-selftests.c \ |
|
@@ -522,7 +531,7 @@ CONFIG_INSTALL = @CONFIG_INSTALL@ |
|
CONFIG_UNINSTALL = @CONFIG_UNINSTALL@ |
|
HAVE_NATIVE_GCORE_TARGET = @HAVE_NATIVE_GCORE_TARGET@ |
|
|
|
-CONFIG_SRC_SUBDIR = arch cli mi compile tui unittests guile python target |
|
+CONFIG_SRC_SUBDIR = arch cli mi compile tui unittests guile python target ruby |
|
CONFIG_DEP_SUBDIR = $(addsuffix /$(DEPDIR),$(CONFIG_SRC_SUBDIR)) |
|
|
|
# -I. for config files. |
|
@@ -552,7 +561,7 @@ CXXFLAGS = @CXXFLAGS@ |
|
# are sometimes a little generic, we think that the risk of collision |
|
# with other header files is high. If that happens, we try to mitigate |
|
# a bit the consequences by putting the Python includes last in the list. |
|
-INTERNAL_CPPFLAGS = @CPPFLAGS@ @GUILE_CPPFLAGS@ @PYTHON_CPPFLAGS@ |
|
+INTERNAL_CPPFLAGS = @CPPFLAGS@ @GUILE_CPPFLAGS@ @PYTHON_CPPFLAGS@ @RUBY_CPPFLAGS@ |
|
|
|
# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros. |
|
INTERNAL_CFLAGS_BASE = \ |
|
@@ -583,7 +592,7 @@ INTERNAL_LDFLAGS = \ |
|
# LIBIBERTY appears twice on purpose. |
|
CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(ZLIB) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \ |
|
$(XM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) \ |
|
- @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \ |
|
+ @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ @RUBY_LIBS@ \ |
|
$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \ |
|
$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) |
|
CDEPS = $(XM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \ |
|
@@ -1609,6 +1618,7 @@ generated_files = \ |
|
|
|
# Flags needed to compile Python code |
|
PYTHON_CFLAGS = @PYTHON_CFLAGS@ |
|
+RUBY_CFLAGS = |
|
|
|
all: gdb$(EXEEXT) $(CONFIG_ALL) |
|
@$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do |
|
@@ -1625,6 +1635,8 @@ $(CONFIG_DEP_SUBDIR): |
|
# Python files need special flags. |
|
python/%.o: INTERNAL_CFLAGS += $(PYTHON_CFLAGS) |
|
|
|
+ruby/%.o: INTERNAL_CFLAGS += $(RUBY_CFLAGS) |
|
+ |
|
# Rules for compiling .c files in the various source subdirectories. |
|
%.o: ${srcdir}/common/%.c |
|
$(COMPILE) $< |
|
diff --git a/gdb/configure b/gdb/configure |
|
index 092893d..183e5a9 100755 |
|
--- a/gdb/configure |
|
+++ b/gdb/configure |
|
@@ -681,6 +681,8 @@ HAVE_PYTHON_TRUE |
|
PYTHON_LIBS |
|
PYTHON_CPPFLAGS |
|
PYTHON_CFLAGS |
|
+RUBY_LIBS |
|
+RUBY_CPPFLAGS |
|
python_prog_path |
|
LTLIBMPFR |
|
LIBMPFR |
|
@@ -17591,8 +17593,13 @@ done |
|
ac_config_links="$ac_config_links $ac_config_links_1" |
|
|
|
|
|
- |
|
- |
|
+# add ruby stuffs |
|
+CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_RUBY_OBS)" |
|
+CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_RUBY_SRCS)" |
|
+CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_RUBY_DEPS)" |
|
+ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_RUBY_CFLAGS)" |
|
+RUBY_CPPFLAGS=`ruby ${srcdir}/ruby/config.rb --include` |
|
+RUBY_LIBS=`ruby ${srcdir}/ruby/config.rb --libs` |
|
|
|
$as_echo "#define GDB_DEFAULT_HOST_CHARSET \"UTF-8\"" >>confdefs.h |
|
|
|
diff --git a/gdb/python/python.c b/gdb/python/python.c |
|
index 4844c86..92cfa7d 100644 |
|
--- a/gdb/python/python.c |
|
+++ b/gdb/python/python.c |
|
@@ -37,6 +37,8 @@ |
|
#include "location.h" |
|
#include "ser-event.h" |
|
|
|
+extern void initialize_ruby(); |
|
+ |
|
/* Declared constants and enum for python stack printing. */ |
|
static const char python_excp_none[] = "none"; |
|
static const char python_excp_full[] = "full"; |
|
@@ -1893,6 +1895,8 @@ message == an error message without a stack will be printed."), |
|
if (!do_start_initialization () && PyErr_Occurred ()) |
|
gdbpy_print_stack (); |
|
#endif /* HAVE_PYTHON */ |
|
+ |
|
+ initialize_ruby(); |
|
} |
|
|
|
#ifdef HAVE_PYTHON |
|
diff --git a/gdb/ruby/config.rb b/gdb/ruby/config.rb |
|
new file mode 100644 |
|
index 0000000..a2bfa1a |
|
--- /dev/null |
|
+++ b/gdb/ruby/config.rb |
|
@@ -0,0 +1,13 @@ |
|
+#coding:utf-8 |
|
+require "mkmf" |
|
+ |
|
+if ARGV.length != 1 |
|
+ exit 1 |
|
+end |
|
+ |
|
+case ARGV[0] |
|
+when "--include" |
|
+ print RbConfig.expand("-I $(rubyarchhdrdir) -I $(rubyhdrdir)") |
|
+when "--libs" |
|
+ print RbConfig.expand(libpathflag + " -l$(RUBY_SO_NAME)") |
|
+end |
|
diff --git a/gdb/ruby/ruby.c b/gdb/ruby/ruby.c |
|
new file mode 100644 |
|
index 0000000..edf49f1 |
|
--- /dev/null |
|
+++ b/gdb/ruby/ruby.c |
|
@@ -0,0 +1,135 @@ |
|
+#include <stdio.h> |
|
+#include <build-gnulib/config.h> // to make gcc happy :P |
|
+#include <string.h> |
|
+#include <string> |
|
+#include "defs.h" |
|
+#include "gdbcmd.h" |
|
+#include <ruby.h> |
|
+ |
|
+static VALUE gdbruby_binding; |
|
+static VALUE rb_eGdbError; |
|
+ |
|
+static VALUE eval_ruby_internal(VALUE command){ |
|
+ RUBY_INIT_STACK; |
|
+ |
|
+ return rb_funcall(gdbruby_binding, rb_intern("eval"), 1, command); |
|
+} |
|
+ |
|
+static VALUE error_handler(VALUE args, VALUE exception_object){ |
|
+ unsigned long i, length; |
|
+ VALUE message; |
|
+ VALUE backtrace; |
|
+ VALUE item; |
|
+ RUBY_INIT_STACK; |
|
+ |
|
+ if(NIL_P(exception_object)){ |
|
+ puts("error"); |
|
+ return Qnil; |
|
+ } |
|
+ |
|
+ message = rb_funcall(exception_object, rb_intern("to_s"), 0); |
|
+ backtrace = rb_funcall(exception_object, rb_intern("backtrace"), 0); |
|
+ |
|
+ if(NIL_P(message)){ |
|
+ printf("%1$s: %1$s\n", rb_obj_classname(exception_object)); |
|
+ }else{ |
|
+ SafeStringValue(message); |
|
+ printf("%s: %s\n", rb_obj_classname(exception_object), RSTRING_PTR(message)); |
|
+ } |
|
+ |
|
+ if(NIL_P(backtrace)){ |
|
+ return Qnil; |
|
+ } |
|
+ |
|
+ length = NUM2LONG(rb_funcall(backtrace, rb_intern("length"), 0)); |
|
+ for(i = 0; length > 1 && i < length - 1; i++){ |
|
+ item = rb_ary_entry(backtrace, i); |
|
+ if(NIL_P(item)){ |
|
+ continue; |
|
+ } |
|
+ SafeStringValue(item); |
|
+ printf(" from %s\n", RSTRING_PTR(item)); |
|
+ } |
|
+ |
|
+ return Qnil; |
|
+} |
|
+ |
|
+static void eval_ruby(const char *script){ |
|
+ VALUE command; |
|
+ RUBY_INIT_STACK; |
|
+ |
|
+ if(script == NULL){ |
|
+ puts("no script given"); |
|
+ return; |
|
+ } |
|
+ |
|
+ command = rb_str_new2(script); |
|
+ rb_rescue((VALUE (*)(ANYARGS))eval_ruby_internal, command, (VALUE (*)(ANYARGS))error_handler, Qnil); |
|
+} |
|
+ |
|
+static VALUE gdb_execute(VALUE self, VALUE arg1){ |
|
+ char *code; |
|
+ std::string result; |
|
+ char *result_cstr; |
|
+ VALUE rb_result; |
|
+ RUBY_INIT_STACK; |
|
+ |
|
+ SafeStringValue(arg1); |
|
+ |
|
+ code = (char *)calloc(1, RSTRING_LEN(arg1) + 1); |
|
+ if(code == NULL){ |
|
+ rb_raise(rb_eRuntimeError, "error"); |
|
+ } |
|
+ memcpy(code, RSTRING_PTR(arg1), RSTRING_LEN(arg1)); |
|
+ |
|
+ TRY{ |
|
+ result = execute_command_to_string(code, 0); |
|
+ }CATCH(except, RETURN_MASK_ALL){ |
|
+ free(code); |
|
+ |
|
+ if(except.reason == RETURN_QUIT){ |
|
+ rb_raise(rb_eInterrupt, "Interrupt"); |
|
+ }else{ |
|
+ rb_raise(rb_eGdbError, "%s", except.message); |
|
+ } |
|
+ }END_CATCH |
|
+ |
|
+ free(code); |
|
+ |
|
+ result_cstr = strdup(result.c_str()); |
|
+ if(result_cstr == NULL){ |
|
+ rb_raise(rb_eRuntimeError, "error"); |
|
+ } |
|
+ |
|
+ rb_result = rb_str_new2(result_cstr); |
|
+ free(result_cstr); |
|
+ |
|
+ return rb_result; |
|
+} |
|
+ |
|
+void initialize_ruby(){ |
|
+ int a = 3; |
|
+ const char *args[] = {"ruby", "-e", "", NULL}; |
|
+ char **arg = (char **)args; |
|
+ int state; |
|
+ |
|
+ /* Initialize Ruby VM */ |
|
+ ruby_sysinit(&a, &arg); |
|
+ { |
|
+ RUBY_INIT_STACK; |
|
+ |
|
+ ruby_init(); |
|
+ ruby_options(a, arg); |
|
+ ruby_script("gdbruby"); |
|
+ |
|
+ rb_define_global_function("gdb_execute", (VALUE (*)(ANYARGS))gdb_execute, 1); |
|
+ |
|
+ gdbruby_binding = rb_funcall(Qnil, rb_intern("binding"), 0); |
|
+ rb_define_readonly_variable("gdbruby_binding", &gdbruby_binding); |
|
+ |
|
+ rb_eGdbError = rb_define_class("GdbError", rb_eStandardError); |
|
+ } |
|
+ |
|
+ /* Add ruby command to gdb */ |
|
+ add_com("ruby", no_class, (void (*)(char const *, int))eval_ruby, "Evaluate a Ruby command."); |
|
+} |
|
\ No newline at end of file |