summaryrefslogtreecommitdiff
path: root/src/if_ruby.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-08-01 18:42:13 +0200
committerBram Moolenaar <Bram@vim.org>2018-08-01 18:42:13 +0200
commitf711cb2f12458d32e082c0e3d4103e2b072947c3 (patch)
tree418bc15d4ed2c06169cbc8383276168ea31bc6f4 /src/if_ruby.c
parenta5bc38b8c16be93bac900137a5837585006cc8a4 (diff)
downloadvim-git-f711cb2f12458d32e082c0e3d4103e2b072947c3.tar.gz
patch 8.1.0232: Ruby error does not include backtracev8.1.0232
Problem: Ruby error does not include backtrace. Solution: Add an error backtrace. (Masataka Pocke Kuwabara, closes #3267)
Diffstat (limited to 'src/if_ruby.c')
-rw-r--r--src/if_ruby.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/src/if_ruby.c b/src/if_ruby.c
index 2e1f8d75a..bf83c8b96 100644
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -93,6 +93,11 @@
# define RUBY20_OR_LATER 1
#endif
+#if (defined(RUBY_VERSION) && RUBY_VERSION >= 21) \
+ || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 21)
+# define RUBY21_OR_LATER 1
+#endif
+
#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
/* Ruby 1.9 defines a number of static functions which use rb_num2long and
* rb_int2big */
@@ -238,11 +243,21 @@ static void ruby_vim_init(void);
# define rb_eRuntimeError (*dll_rb_eRuntimeError)
# define rb_eStandardError (*dll_rb_eStandardError)
# define rb_eval_string_protect dll_rb_eval_string_protect
+# ifdef RUBY21_OR_LATER
+# define rb_funcallv dll_rb_funcallv
+# else
+# define rb_funcall2 dll_rb_funcall2
+# endif
# define rb_global_variable dll_rb_global_variable
# define rb_hash_aset dll_rb_hash_aset
# define rb_hash_new dll_rb_hash_new
# define rb_inspect dll_rb_inspect
# define rb_int2inum dll_rb_int2inum
+# ifdef RUBY19_OR_LATER
+# define rb_intern2 dll_rb_intern2
+# else
+# define rb_intern dll_rb_intern
+# endif
# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18
# define rb_fix2int dll_rb_fix2int
@@ -367,11 +382,21 @@ static VALUE *dll_rb_eIndexError;
static VALUE *dll_rb_eRuntimeError;
static VALUE *dll_rb_eStandardError;
static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
+# ifdef RUBY21_OR_LATER
+static VALUE (*dll_rb_funcallv) (VALUE, ID, int, const VALUE*);
+# else
+static VALUE (*dll_rb_funcall2) (VALUE, ID, int, const VALUE*);
+# endif
static void (*dll_rb_global_variable) (VALUE*);
static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
static VALUE (*dll_rb_hash_new) (void);
static VALUE (*dll_rb_inspect) (VALUE);
static VALUE (*dll_rb_int2inum) (long);
+# ifdef RUBY19_OR_LATER
+static ID (*dll_rb_intern2) (const char*, long);
+# else
+static ID (*dll_rb_intern) (const char*);
+# endif
# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
static long (*dll_rb_fix2int) (VALUE);
static long (*dll_rb_num2int) (VALUE);
@@ -561,11 +586,21 @@ static struct
{"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
{"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
{"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
+# ifdef RUBY21_OR_LATER
+ {"rb_funcallv", (RUBY_PROC*)&dll_rb_funcallv},
+# else
+ {"rb_funcall2", (RUBY_PROC*)&dll_rb_funcall2},
+# endif
{"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
{"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
{"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
{"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
{"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
+# ifdef RUBY19_OR_LATER
+ {"rb_intern2", (RUBY_PROC*)&dll_rb_intern2},
+# else
+ {"rb_intern", (RUBY_PROC*)&dll_rb_intern},
+# endif
# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
{"rb_fix2int", (RUBY_PROC*)&dll_rb_fix2int},
{"rb_num2int", (RUBY_PROC*)&dll_rb_num2int},
@@ -926,9 +961,13 @@ static void error_print(int state)
RUBYEXTERN VALUE ruby_errinfo;
#endif
#endif
+ VALUE error;
VALUE eclass;
VALUE einfo;
+ VALUE bt;
+ int attr;
char buff[BUFSIZ];
+ long i;
#define TAG_RETURN 0x1
#define TAG_BREAK 0x2
@@ -960,12 +999,12 @@ static void error_print(int state)
case TAG_RAISE:
case TAG_FATAL:
#ifdef RUBY19_OR_LATER
- eclass = CLASS_OF(rb_errinfo());
- einfo = rb_obj_as_string(rb_errinfo());
+ error = rb_errinfo();
#else
- eclass = CLASS_OF(ruby_errinfo);
- einfo = rb_obj_as_string(ruby_errinfo);
+ error = ruby_errinfo;
#endif
+ eclass = CLASS_OF(error);
+ einfo = rb_obj_as_string(error);
if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0)
{
EMSG(_("E272: unhandled exception"));
@@ -982,6 +1021,17 @@ static void error_print(int state)
if (p) *p = '\0';
EMSG(buff);
}
+
+ attr = syn_name2attr((char_u *)"Error");
+# ifdef RUBY21_OR_LATER
+ bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
+ for (i = 0; i < RARRAY_LEN(bt); i++)
+ msg_attr((char_u *)RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
+# else
+ bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0);
+ for (i = 0; i < RARRAY_LEN(bt); i++)
+ msg_attr((char_u *)RSTRING_PTR(RARRAY_PTR(bt)[i]), attr);
+# endif
break;
default:
vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);