# Apply ruby 2.0 fix to ruby 1.9 as well.  Needed to allow
# vim to build with ruby 1.9.
# These changes were applied upstream to vim 7.4.224.  See
# https://groups.google.com/forum/#!msg/vim_dev/r8wzUVNYIfQ/m0DM8Wt97vkJ

# Also applies fixes for Ruby 2.1 
# from vim 7.4.570 
# https://github.com/vim/vim/commit/0c7485fdbb5023731b006572cc224cbf52e34288
# and Ruby 2.2, from fixes to vim 7.4.705
# https://github.com/vim/vim/commit/bbc1a592a0e0efd5101a58032e7e7cc9f3e9f417

--- src/if_ruby.c	2013-08-10 06:00:24.000000000 -0700
+++ src/if_ruby.c	2015-09-16 15:16:02.741823755 -0700
@@ -88,14 +88,24 @@
 # define rb_int2big rb_int2big_stub
 #endif
 
-#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 \
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
 	&& SIZEOF_INT < SIZEOF_LONG
-/* Ruby 2.0 defines a number of static functions which use rb_fix2int and
+/* Ruby 1.9 defines a number of static functions which use rb_fix2int and
  * rb_num2int if SIZEOF_INT < SIZEOF_LONG (64bit) */
 # define rb_fix2int rb_fix2int_stub
 # define rb_num2int rb_num2int_stub
 #endif
 
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
+/* Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses
+ * rb_gc_writebarrier_unprotect_promoted if USE_RGENGC  */
+# define rb_gc_writebarrier_unprotect_promoted rb_gc_writebarrier_unprotect_promoted_stub
+#endif
+#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
+# define rb_gc_writebarrier_unprotect rb_gc_writebarrier_unprotect_stub
+# define rb_check_type rb_check_type_stub
+#endif
+
 #include <ruby.h>
 #ifdef RUBY19_OR_LATER
 # include <ruby/encoding.h>
@@ -197,8 +207,10 @@ static void ruby_vim_init(void);
 # define rb_inspect			dll_rb_inspect
 # define rb_int2inum			dll_rb_int2inum
 # if SIZEOF_INT < SIZEOF_LONG /* 64 bits only */
+# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18
 #  define rb_fix2int			dll_rb_fix2int
 #  define rb_num2int			dll_rb_num2int
+# endif
 #  define rb_num2uint			dll_rb_num2uint
 # endif
 # define rb_lastline_get			dll_rb_lastline_get
@@ -373,8 +385,20 @@ static VALUE (*dll_rb_require) (const ch
 static void* (*ruby_process_options)(int, char**);
 # endif
 
+# if defined(USE_RGENGC) && USE_RGENGC
+#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
+static void (*dll_rb_gc_writebarrier_unprotect_promoted)(VALUE);
+#  else
+static void (*dll_rb_gc_writebarrier_unprotect)(VALUE obj);
+#  endif
+# endif
+
 # if defined(RUBY19_OR_LATER) && !defined(PROTO)
+#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
+long rb_num2long_stub(VALUE x)
+#  else
 SIGNED_VALUE rb_num2long_stub(VALUE x)
+#  endif
 {
     return dll_rb_num2long(x);
 }
@@ -382,7 +406,7 @@ VALUE rb_int2big_stub(SIGNED_VALUE x)
 {
     return dll_rb_int2big(x);
 }
-#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 \
+#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
 	&& SIZEOF_INT < SIZEOF_LONG
 long rb_fix2int_stub(VALUE x)
 {
@@ -399,13 +423,39 @@ rb_float_new_in_heap(double d)
 {
     return dll_rb_float_new(d);
 }
+#   if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
+unsigned long rb_num2ulong(VALUE x)
+#   else
 VALUE rb_num2ulong(VALUE x)
+#   endif
 {
     return (long)RSHIFT((SIGNED_VALUE)(x),1);
 }
 #  endif
 # endif
 
+   /* Do not generate a prototype here, VALUE isn't always defined. */
+# if defined(USE_RGENGC) && USE_RGENGC && !defined(PROTO)
+#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
+void rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj)
+{
+    dll_rb_gc_writebarrier_unprotect_promoted(obj);
+}
+#  else
+void rb_gc_writebarrier_unprotect_stub(VALUE obj)
+{
+    dll_rb_gc_writebarrier_unprotect(obj);
+}
+#  endif
+# endif
+
+# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
+void rb_check_type_stub(VALUE v, int i)
+{
+    dll_rb_check_type(v, i);
+}
+# endif
+
 static HINSTANCE hinstRuby = NULL; /* Instance of ruby.dll */
 
 /*
@@ -521,6 +571,13 @@ static struct
 #  endif
     {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
 # endif
+# if defined(USE_RGENGC) && USE_RGENGC
+#  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
+    {"rb_gc_writebarrier_unprotect_promoted", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect_promoted},
+#  else
+    {"rb_gc_writebarrier_unprotect", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect},
+#  endif
+# endif
     {"", NULL},
 };
 
