# HG changeset patch # User Christian Brabandt # Date 1533141905 -7200 # Node ID ceb9b6bf0f4aec5a74568d0c4445e3b1336759b9 # Parent c5b4768f5224a71201e6bd3f9c6de892969aa775 patch 8.1.0232: Ruby error does not include backtrace commit https://github.com/vim/vim/commit/f711cb2f12458d32e082c0e3d4103e2b072947c3 Author: Bram Moolenaar Date: Wed Aug 1 18:42:13 2018 +0200 patch 8.1.0232: Ruby error does not include backtrace Problem: Ruby error does not include backtrace. Solution: Add an error backtrace. (Masataka Pocke Kuwabara, closes https://github.com/vim/vim/issues/3267) diff --git a/src/if_ruby.c b/src/if_ruby.c --- 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); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -795,6 +795,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 232, +/**/ 231, /**/ 230,