From e1784b557dfeae0f85559a65610d1280c7396a71 Mon Sep 17 00:00:00 2001
From: Dominik Honnef <dominikho@gmx.net>
Date: Wed, 25 Nov 2009 18:36:21 +0100
Subject: [PATCH] patched ruby plugin to support both ruby 1.8 and 1.9

---
 cmake/FindRuby.cmake                    |   13 +++-
 configure.in                            |    8 +-
 src/plugins/scripts/ruby/CMakeLists.txt |    2 +-
 src/plugins/scripts/ruby/weechat-ruby.c |  131 +++++++++++++++++++++++--------
 4 files changed, 116 insertions(+), 38 deletions(-)

diff --git a/cmake/FindRuby.cmake b/cmake/FindRuby.cmake
index 6f8da1c..be07011 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
     )
@@ -53,12 +58,16 @@ IF(RUBY_EXECUTABLE)
   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}")
   
   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}
@@ -71,7 +80,7 @@ IF(RUBY_EXECUTABLE)
   MARK_AS_ADVANCED(
     RUBY_EXECUTABLE
     RUBY_LIBRARY
+    RUBY_ARCH
     RUBY_INCLUDE_PATH
     )
-  
 ENDIF(RUBY_EXECUTABLE)
diff --git a/configure.in b/configure.in
index 253c715..085bee7 100644
--- a/configure.in
+++ b/configure.in
@@ -529,10 +529,12 @@ 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']]"`
+        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 -r "$RUBY_INCLUDE/ruby.h"; then
-            RUBY_CFLAGS="-I$RUBY_INCLUDE"
+        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.
diff --git a/src/plugins/scripts/ruby/CMakeLists.txt b/src/plugins/scripts/ruby/CMakeLists.txt
index cf977a2..98d9483 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 b59b8b2..dfec8d4 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");
@@ -117,8 +150,58 @@ rb_protect_funcall (VALUE recv, ID mid, int *state, int argc, ...)
     return rb_protect(protect_funcall0, (VALUE) &arg, state);
 }
 
+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)));
+    rb_ivar_set(err, "mesg", Qnil);
+  } 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));
+        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));
+        strcat(cline, "     from ");
+        strcat(cline, line);
+      }
+      weechat_printf (NULL,
+                      weechat_gettext ("%s%s: error: %s"),
+                      weechat_prefix ("error"), RUBY_PLUGIN_NAME,
+                      cline);
+
+      free(cline);
+    }
+  }
+  return 0;
+}
+
 /*
- * weechat_ruby_exec: execute a Ruby script
+ * weechat_ruby_exec: call a ruby command
  */
 
 void *
@@ -242,11 +325,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,11 +472,8 @@ 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;
     }
     
@@ -432,14 +509,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 +525,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,21 +888,18 @@ 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"
+      "      lines = File.read(file)\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"
+      "    rescue Exception => e\n"
 	    "      @load_eval_file_error = e\n"
 	    "      return 2\n"
 	    "    end\n"
@@ -843,7 +907,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
 	    "    has_init = false\n"
 	    "\n"
 	    "    instance_methods.each do |meth|\n"
-	    "      if meth == 'weechat_init'\n"
+      "      if meth.to_s == 'weechat_init'\n"
 	    "        has_init = true\n"
 	    "      end\n"
 	    "      module_eval('module_function :' + meth)\n"
@@ -865,6 +929,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__");
@@ -933,8 +1001,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;
 }
-- 
1.6.5.3

