diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | cmake/FindRuby.cmake | 25 | ||||
-rw-r--r-- | configure.in | 30 | ||||
-rw-r--r-- | src/plugins/scripts/ruby/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/plugins/scripts/ruby/weechat-ruby.c | 226 |
5 files changed, 206 insertions, 80 deletions
@@ -1,7 +1,7 @@ WeeChat ChangeLog ================= FlashCode <flashcode@flashtux.org> -v0.3.1-dev, 2009-11-24 +v0.3.1-dev, 2009-11-29 Version 0.3.1 (under dev!) @@ -35,6 +35,7 @@ Version 0.3.1 (under dev!) * irc: improve error management on socket error (recv/send) * irc: improve mask used by command /kickban * xfer: add missing charset decoding/encoding for IRC DCC chat (bug #27482) +* ruby: support of Ruby >= 1.9.1 (patch #6989) * gui: fix message "Day changed to", sometimes displayed at wrong time (bug #26959) * gui: fix bug with URL selection in some terminals (caused by horizontal lines) diff --git a/cmake/FindRuby.cmake b/cmake/FindRuby.cmake index 6f8da1c27..2e25e36dd 100644 --- a/cmake/FindRuby.cmake +++ b/cmake/FindRuby.cmake @@ -35,11 +35,16 @@ FIND_PROGRAM(RUBY_EXECUTABLE IF(RUBY_EXECUTABLE) EXECUTE_PROCESS( - COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['archdir']" + COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['rubyhdrdir'] || Config::CONFIG['archdir']" OUTPUT_VARIABLE RUBY_ARCH_DIR ) EXECUTE_PROCESS( + COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['arch']" + OUTPUT_VARIABLE RUBY_ARCH + ) + + EXECUTE_PROCESS( COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['libdir']" OUTPUT_VARIABLE RUBY_POSSIBLE_LIB_PATH ) @@ -48,17 +53,27 @@ IF(RUBY_EXECUTABLE) COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['rubylibdir']" OUTPUT_VARIABLE RUBY_RUBY_LIB_PATH ) + + EXECUTE_PROCESS( + COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts Config::CONFIG['ruby_version']" + OUTPUT_VARIABLE RUBY_VERSION + ) # remove the new lines from the output by replacing them with empty strings STRING(REPLACE "\n" "" RUBY_ARCH_DIR "${RUBY_ARCH_DIR}") STRING(REPLACE "\n" "" RUBY_POSSIBLE_LIB_PATH "${RUBY_POSSIBLE_LIB_PATH}") STRING(REPLACE "\n" "" RUBY_RUBY_LIB_PATH "${RUBY_RUBY_LIB_PATH}") + STRING(REPLACE "\n" "" RUBY_ARCH "${RUBY_ARCH}") + STRING(REPLACE "\n" "" RUBY_VERSION "${RUBY_VERSION}") FIND_PATH(RUBY_INCLUDE_PATH NAMES ruby.h PATHS ${RUBY_ARCH_DIR} ) + SET(RUBY_ARCH + "${RUBY_INCLUDE_PATH}/${RUBY_ARCH}") + FIND_LIBRARY(RUBY_LIBRARY NAMES ruby ruby1.6 ruby16 ruby1.8 ruby18 ruby1.9 ruby19 PATHS ${RUBY_POSSIBLE_LIB_PATH} ${RUBY_RUBY_LIB_PATH} @@ -67,11 +82,15 @@ IF(RUBY_EXECUTABLE) IF(RUBY_LIBRARY AND RUBY_INCLUDE_PATH) SET(RUBY_FOUND TRUE) ENDIF(RUBY_LIBRARY AND RUBY_INCLUDE_PATH) - + + IF(${RUBY_VERSION} STREQUAL "1.9.0") + SET(RUBY_FOUND FALSE) + ENDIF(${RUBY_VERSION} STREQUAL "1.9.0") + MARK_AS_ADVANCED( RUBY_EXECUTABLE RUBY_LIBRARY + RUBY_ARCH RUBY_INCLUDE_PATH ) - ENDIF(RUBY_EXECUTABLE) diff --git a/configure.in b/configure.in index 253c71572..b8b0f2d05 100644 --- a/configure.in +++ b/configure.in @@ -529,20 +529,32 @@ if test "x$enable_ruby" = "xyes" ; then not_found="$not_found ruby" else RUBY_VERSION=`$RUBY -rrbconfig -e "puts Config::CONFIG[['ruby_version']]"` - RUBY_INCLUDE=`$RUBY -rrbconfig -e "puts Config::CONFIG[['archdir']]"` - AC_MSG_CHECKING(for Ruby header files) - if test -r "$RUBY_INCLUDE/ruby.h"; then - RUBY_CFLAGS="-I$RUBY_INCLUDE" - else + if test "$RUBY_VERSION" = "1.9.0"; then AC_MSG_WARN([ -*** Ruby header files couldn't be found on your system. -*** Try to install them with your software package manager. +*** Ruby header files have been found, but they're of the version 1.9.0. +*** Ruby 1.9.0 is an unstable release and should not be used in production. +*** Please install Ruby >=1.8.6 or 1.9.1. *** WeeChat will be built without Ruby support.]) enable_ruby="no" not_found="$not_found ruby" + else + RUBY_INCLUDE=`$RUBY -rrbconfig -e "puts Config::CONFIG[['rubyhdrdir']] || Config::CONFIG[['archdir']]"` + RUBY_ARCH=`$RUBY -rrbconfig -e 'print Config::CONFIG[["arch"]]'` + AC_MSG_CHECKING(for Ruby header files) + if test -d "$RUBY_INCLUDE/"; then + M_RUBY_VERSION=`$RUBY -rrbconfig -e "puts Config::CONFIG[['ruby_version']].gsub(/\./, '')[[0,2]]"` + RUBY_CFLAGS="-I$RUBY_INCLUDE/ -I$RUBY_INCLUDE/$RUBY_ARCH -DRUBY_VERSION=$M_RUBY_VERSION" + else + AC_MSG_WARN([ +*** Ruby header files couldn't be found on your system. +*** Try to install them with your software package manager. +*** WeeChat will be built without Ruby support.]) + enable_ruby="no" + not_found="$not_found ruby" + fi + AC_MSG_RESULT(found) + RUBY_LFLAGS=`$RUBY -rrbconfig -e "puts Config::CONFIG[['LIBRUBYARG_SHARED']]"` fi - AC_MSG_RESULT(found) - RUBY_LFLAGS=`$RUBY -rrbconfig -e "puts Config::CONFIG[['LIBRUBYARG_SHARED']]"` fi else not_asked="$not_asked ruby" diff --git a/src/plugins/scripts/ruby/CMakeLists.txt b/src/plugins/scripts/ruby/CMakeLists.txt index cf977a254..98d948322 100644 --- a/src/plugins/scripts/ruby/CMakeLists.txt +++ b/src/plugins/scripts/ruby/CMakeLists.txt @@ -20,7 +20,7 @@ weechat-ruby-api.h) SET_TARGET_PROPERTIES(ruby PROPERTIES PREFIX "") IF(RUBY_FOUND) - INCLUDE_DIRECTORIES(${RUBY_INCLUDE_PATH}) + INCLUDE_DIRECTORIES(${RUBY_INCLUDE_PATH} ${RUBY_ARCH}) TARGET_LINK_LIBRARIES(ruby ${RUBY_LIBRARY} weechat_scripts) ENDIF(RUBY_FOUND) diff --git a/src/plugins/scripts/ruby/weechat-ruby.c b/src/plugins/scripts/ruby/weechat-ruby.c index b59b8b213..5cda87a08 100644 --- a/src/plugins/scripts/ruby/weechat-ruby.c +++ b/src/plugins/scripts/ruby/weechat-ruby.c @@ -22,6 +22,10 @@ #undef _ #include <ruby.h> +#if defined(RUBY_VERSION) && RUBY_VERSION >=19 +#include <ruby/encoding.h> +#endif + #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> @@ -31,6 +35,35 @@ #include "weechat-ruby.h" #include "weechat-ruby-api.h" +#ifndef StringValuePtr +#define StringValuePtr(s) STR2CSTR(s) +#endif +#ifndef RARRAY_LEN +#define RARRAY_LEN(s) RARRAY(s)->len +#endif +#ifndef RARRAY_PTR +#define RARRAY_PTR(s) RARRAY(s)->ptr +#endif +#ifndef RSTRING_LEN +#define RSTRING_LEN(s) RSTRING(s)->len +#endif +#ifndef RSTRING_PTR +#define RSTRING_PTR(s) RSTRING(s)->ptr +#endif + +#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 +#define rb_errinfo dll_rb_errinfo +#define ruby_errinfo dll_rb_errinfo +#else +#define ruby_errinfo (*dll_ruby_errinfo) +#endif + +#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 +static VALUE (*dll_rb_errinfo) (void); +#else +static VALUE *dll_ruby_errinfo; +#endif + WEECHAT_PLUGIN_NAME(RUBY_PLUGIN_NAME); WEECHAT_PLUGIN_DESCRIPTION("Ruby plugin for WeeChat"); @@ -80,12 +113,12 @@ typedef struct protect_call_arg { */ static VALUE -protect_funcall0(VALUE arg) +protect_funcall0 (VALUE arg) { - return rb_funcall2(((protect_call_arg_t *) arg)->recv, - ((protect_call_arg_t *) arg)->mid, - ((protect_call_arg_t *) arg)->argc, - ((protect_call_arg_t *) arg)->argv); + return rb_funcall2 (((protect_call_arg_t *)arg)->recv, + ((protect_call_arg_t *)arg)->mid, + ((protect_call_arg_t *)arg)->argc, + ((protect_call_arg_t *)arg)->argv); } /* @@ -118,7 +151,85 @@ rb_protect_funcall (VALUE recv, ID mid, int *state, int argc, ...) } /* - * weechat_ruby_exec: execute a Ruby script + * weechat_ruby_print_exception: display ruby exception + */ + +int +weechat_ruby_print_exception (VALUE err) +{ + VALUE backtrace; + int i; + int ruby_error; + char* line; + char* cline; + char* err_msg; + char* err_class; + + backtrace = rb_protect_funcall (err, rb_intern("backtrace"), + &ruby_error, 0); + err_msg = STR2CSTR(rb_protect_funcall(err, rb_intern("message"), + &ruby_error, 0)); + err_class = STR2CSTR(rb_protect_funcall(rb_protect_funcall(err, + rb_intern("class"), + &ruby_error, 0), + rb_intern("name"), &ruby_error, 0)); + + if (strcmp (err_class, "SyntaxError") == 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), RUBY_PLUGIN_NAME, + STR2CSTR(rb_inspect(err))); + } + else + { + for (i = 0; i < RARRAY_LEN(backtrace); i++) + { + line = STR2CSTR(RARRAY_PTR(backtrace)[i]); + cline = NULL; + if (i == 0) + { + cline = (char *)calloc (strlen (line) + 2 + strlen (err_msg) + + 3 + strlen (err_class) + 1, + sizeof (char)); + if (cline) + { + strcat (cline, line); + strcat (cline, ": "); + strcat (cline, err_msg); + strcat (cline, " ("); + strcat (cline, err_class); + strcat (cline, ")"); + } + } + else + { + cline = (char *)calloc(strlen (line) + strlen (" from ") + 1, + sizeof (char)); + if (cline) + { + strcat (cline, " from "); + strcat (cline, line); + } + } + if (cline) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), RUBY_PLUGIN_NAME, + cline); + } + + if (cline) + free (cline); + } + } + + return 0; +} + +/* + * weechat_ruby_exec: call a ruby command */ void * @@ -242,11 +353,8 @@ weechat_ruby_exec (struct t_plugin_script *script, weechat_gettext ("%s%s: unable to run function \"%s\""), weechat_prefix ("error"), RUBY_PLUGIN_NAME, function); - err = rb_inspect(rb_gv_get("$!")); - weechat_printf (NULL, - weechat_gettext ("%s%s: error: \"%s\""), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - STR2CSTR(err)); + err = rb_gv_get("$!"); + weechat_ruby_print_exception(err); return NULL; } @@ -392,18 +500,13 @@ weechat_ruby_load (const char *filename) if (ruby_retcode == Qnil) { - err = rb_inspect(rb_gv_get("$!")); - weechat_printf (NULL, - weechat_gettext ("%s%s: error: \"%s\""), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - STR2CSTR(err)); + err = rb_gv_get("$!"); + weechat_ruby_print_exception(err); return 0; } if (NUM2INT(ruby_retcode) != 0) { - VALUE ruby_eval_error; - switch (NUM2INT(ruby_retcode)) { case 1: @@ -432,14 +535,7 @@ weechat_ruby_load (const char *filename) if (NUM2INT(ruby_retcode) == 1 || NUM2INT(ruby_retcode) == 2) { - ruby_eval_error = rb_iv_get(curModule, "@load_eval_file_error"); - if (ruby_eval_error) - { - weechat_printf (NULL, - weechat_gettext ("%s%s: error: %s"), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - STR2CSTR(ruby_eval_error)); - } + weechat_ruby_print_exception(rb_iv_get(curModule, "@load_eval_file_error")); } return 0; @@ -455,11 +551,8 @@ weechat_ruby_load (const char *filename) "\"weechat_init\" in file \"%s\""), weechat_prefix ("error"), RUBY_PLUGIN_NAME, filename); - err = rb_inspect(rb_gv_get("$!")); - weechat_printf (NULL, - weechat_gettext ("%s%s: error: \"%s\""), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - STR2CSTR(err)); + err = rb_gv_get("$!"); + weechat_ruby_print_exception(err); if (ruby_current_script != NULL) { @@ -821,42 +914,39 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) "$stderr = WeechatOutputs\n" "\n" "class Module\n" - " @load_eval_file_error = ''\n" "\n" " def load_eval_file (file)\n" " lines = ''\n" - " begin\n" - " f = File.open(file, 'r')\n" - " lines = f.readlines.join\n" - " rescue => e\n" - " @load_eval_file_error = e\n" - " return 1\n" - " end\n" - "\n" - " begin\n" - " module_eval(lines)\n" - " rescue => e\n" - " @load_eval_file_error = e\n" - " return 2\n" - " end\n" - "\n" - " has_init = false\n" - "\n" - " instance_methods.each do |meth|\n" - " if meth == 'weechat_init'\n" - " has_init = true\n" - " end\n" - " module_eval('module_function :' + meth)\n" - " end\n" - "\n" - " unless has_init\n" - " return 3\n" - " end\n" - "\n" - " return 0\n" - " end\n" - "end\n" - }; + " begin\n" + " lines = File.read(file)\n" + " rescue => e\n" + " return 1\n" + " end\n" + "\n" + " begin\n" + " module_eval(lines)\n" + " rescue Exception => e\n" + " @load_eval_file_error = e\n" + " return 2\n" + " end\n" + "\n" + " has_init = false\n" + "\n" + " instance_methods.each do |meth|\n" + " if meth.to_s == 'weechat_init'\n" + " has_init = true\n" + " end\n" + " module_eval('module_function :' + meth)\n" + " end\n" + "\n" + " unless has_init\n" + " return 3\n" + " end\n" + "\n" + " return 0\n" + " end\n" + "end\n" + }; weechat_ruby_plugin = plugin; @@ -865,6 +955,10 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) /* init stdout/stderr buffer */ ruby_buffer_output[0] = '\0'; +#if defined(RUBY_VERSION) && RUBY_VERSION >= 19 + RUBY_INIT_STACK; +#endif + ruby_init (); ruby_init_loadpath (); ruby_script ("__weechat_plugin__"); @@ -886,7 +980,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) rb_eval_string_protect(weechat_ruby_code, &ruby_error); if (ruby_error) { - VALUE ruby_error_info = rb_inspect(ruby_errinfo); + VALUE ruby_error_info = rb_inspect((VALUE)ruby_errinfo); weechat_printf (NULL, weechat_gettext ("%s%s: unable to eval WeeChat ruby " "internal code"), @@ -934,7 +1028,7 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) /* unload all scripts */ weechat_ruby_unload_all (); - ruby_finalize(); + ruby_cleanup (0); return WEECHAT_RC_OK; } |