xref: /vim-8.2.3635/src/if_ruby.c (revision 7dca2ebb)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Ruby interface by Shugo Maeda
6  *   with improvements by SegPhault (Ryan Paul)
7  *   with improvements by Jon Maken
8  *
9  * Do ":help uganda"  in Vim to read copying and usage conditions.
10  * Do ":help credits" in Vim to see a list of people who contributed.
11  * See README.txt for an overview of the Vim source code.
12  */
13 
14 #include "protodef.h"
15 #ifdef HAVE_CONFIG_H
16 # include "auto/config.h"
17 #endif
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #ifdef _WIN32
23 # if !defined(DYNAMIC_RUBY_VER) || (DYNAMIC_RUBY_VER < 18)
24 #   define NT
25 # endif
26 # ifndef DYNAMIC_RUBY
27 #  define IMPORT /* For static dll usage __declspec(dllimport) */
28 #  define RUBYEXTERN __declspec(dllimport)
29 # endif
30 #endif
31 #ifndef RUBYEXTERN
32 # define RUBYEXTERN extern
33 #endif
34 
35 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 24
36 # define USE_RUBY_INTEGER
37 #endif
38 
39 #ifdef DYNAMIC_RUBY
40 /*
41  * This is tricky.  In ruby.h there is (inline) function rb_class_of()
42  * definition.  This function use these variables.  But we want function to
43  * use dll_* variables.
44  */
45 # define rb_cFalseClass		(*dll_rb_cFalseClass)
46 # define rb_cFixnum		(*dll_rb_cFixnum)
47 # if defined(USE_RUBY_INTEGER)
48 #  define rb_cInteger		(*dll_rb_cInteger)
49 # endif
50 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
51 #  define rb_cFloat		(*dll_rb_cFloat)
52 # endif
53 # define rb_cNilClass		(*dll_rb_cNilClass)
54 # define rb_cString		(*dll_rb_cString)
55 # define rb_cSymbol		(*dll_rb_cSymbol)
56 # define rb_cTrueClass		(*dll_rb_cTrueClass)
57 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
58 /*
59  * On ver 1.8, all Ruby functions are exported with "__declspec(dllimport)"
60  * in ruby.h.  But it causes trouble for these variables, because it is
61  * defined in this file.  When defined this RUBY_EXPORT it modified to
62  * "extern" and be able to avoid this problem.
63  */
64 #  define RUBY_EXPORT
65 # endif
66 
67 #endif  // ifdef DYNAMIC_RUBY
68 
69 // suggested by Ariya Mizutani
70 #if (_MSC_VER == 1200)
71 # undef _WIN32_WINNT
72 #endif
73 
74 #if (defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
75     || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19)
76 # define RUBY19_OR_LATER 1
77 #endif
78 
79 #if (defined(RUBY_VERSION) && RUBY_VERSION >= 20) \
80     || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20)
81 # define RUBY20_OR_LATER 1
82 #endif
83 
84 #if (defined(RUBY_VERSION) && RUBY_VERSION >= 21) \
85     || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 21)
86 # define RUBY21_OR_LATER 1
87 #endif
88 
89 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19
90 /* Ruby 1.9 defines a number of static functions which use rb_num2long and
91  * rb_int2big */
92 # define rb_num2long rb_num2long_stub
93 # define rb_int2big rb_int2big_stub
94 #endif
95 
96 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
97 	&& VIM_SIZEOF_INT < VIM_SIZEOF_LONG
98 /* Ruby 1.9 defines a number of static functions which use rb_fix2int and
99  * rb_num2int if VIM_SIZEOF_INT < VIM_SIZEOF_LONG (64bit) */
100 # define rb_fix2int rb_fix2int_stub
101 # define rb_num2int rb_num2int_stub
102 #endif
103 
104 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
105 /* Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses
106  * rb_gc_writebarrier_unprotect_promoted if USE_RGENGC  */
107 # define rb_gc_writebarrier_unprotect_promoted rb_gc_writebarrier_unprotect_promoted_stub
108 #endif
109 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
110 # define rb_gc_writebarrier_unprotect rb_gc_writebarrier_unprotect_stub
111 #endif
112 
113 #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26
114 # define rb_ary_detransient rb_ary_detransient_stub
115 #endif
116 
117 #include <ruby.h>
118 #ifdef RUBY19_OR_LATER
119 # include <ruby/encoding.h>
120 #endif
121 
122 #undef off_t	/* ruby defines off_t as _int64, Mingw uses long */
123 #undef EXTERN
124 #undef _
125 
126 /* T_DATA defined both by Ruby and Mac header files, hack around it... */
127 #if defined(MACOS_X)
128 # define __OPENTRANSPORT__
129 # define __OPENTRANSPORTPROTOCOL__
130 # define __OPENTRANSPORTPROVIDERS__
131 #endif
132 
133 /*
134  * The TypedData_XXX macro family can be used since Ruby 1.9.2 but
135  * rb_data_type_t changed in 1.9.3, therefore require at least 2.0.
136  * The old Data_XXX macro family was deprecated on Ruby 2.2.
137  * Use TypedData_XXX if available.
138  */
139 #if defined(TypedData_Wrap_Struct) && defined(RUBY20_OR_LATER)
140 # define USE_TYPEDDATA	1
141 #endif
142 
143 /*
144  * Backward compatibility for Ruby 1.8 and earlier.
145  * Ruby 1.9 does not provide STR2CSTR, instead StringValuePtr is provided.
146  * Ruby 1.9 does not provide RXXX(s)->len and RXXX(s)->ptr, instead
147  * RXXX_LEN(s) and RXXX_PTR(s) are provided.
148  */
149 #ifndef StringValuePtr
150 # define StringValuePtr(s) STR2CSTR(s)
151 #endif
152 #ifndef RARRAY_LEN
153 # define RARRAY_LEN(s) RARRAY(s)->len
154 #endif
155 #ifndef RARRAY_PTR
156 # define RARRAY_PTR(s) RARRAY(s)->ptr
157 #endif
158 #ifndef RSTRING_LEN
159 # define RSTRING_LEN(s) RSTRING(s)->len
160 #endif
161 #ifndef RSTRING_PTR
162 # define RSTRING_PTR(s) RSTRING(s)->ptr
163 #endif
164 
165 #ifdef HAVE_DUP
166 # undef HAVE_DUP
167 #endif
168 
169 #include "vim.h"
170 #include "version.h"
171 
172 #ifdef DYNAMIC_RUBY
173 # if !defined(MSWIN)  // must come after including vim.h, where it is defined
174 #  include <dlfcn.h>
175 #  define HINSTANCE void*
176 #  define RUBY_PROC void*
177 #  define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
178 #  define symbol_from_dll dlsym
179 #  define close_dll dlclose
180 # else
181 #  define RUBY_PROC FARPROC
182 #  define load_dll vimLoadLib
183 #  define symbol_from_dll GetProcAddress
184 #  define close_dll FreeLibrary
185 # endif
186 #endif
187 
188 #if defined(PROTO) && !defined(FEAT_RUBY)
189 /* Define these to be able to generate the function prototypes. */
190 # define VALUE int
191 # define RUBY_DATA_FUNC int
192 #endif
193 
194 static int ruby_initialized = 0;
195 static void *ruby_stack_start;
196 static VALUE objtbl;
197 
198 static VALUE mVIM;
199 static VALUE cBuffer;
200 static VALUE cVimWindow;
201 static VALUE eDeletedBufferError;
202 static VALUE eDeletedWindowError;
203 
204 static int ensure_ruby_initialized(void);
205 static void error_print(int);
206 static void ruby_io_init(void);
207 static void ruby_vim_init(void);
208 
209 #if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
210 # if defined(__ia64) && !defined(ruby_init_stack)
211 #  define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
212 # endif
213 #endif
214 
215 #if defined(DYNAMIC_RUBY) || defined(PROTO)
216 # if defined(PROTO) && !defined(HINSTANCE)
217 #  define HINSTANCE int		/* for generating prototypes */
218 # endif
219 
220 /*
221  * Wrapper defines
222  */
223 # define rb_assoc_new			dll_rb_assoc_new
224 # define rb_cObject			(*dll_rb_cObject)
225 # define rb_class_new_instance		dll_rb_class_new_instance
226 # define rb_check_type			dll_rb_check_type
227 # ifdef USE_TYPEDDATA
228 #  define rb_check_typeddata		dll_rb_check_typeddata
229 # endif
230 # define rb_class_path			dll_rb_class_path
231 # ifdef USE_TYPEDDATA
232 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23
233 #   define rb_data_typed_object_wrap	dll_rb_data_typed_object_wrap
234 #  else
235 #   define rb_data_typed_object_alloc	dll_rb_data_typed_object_alloc
236 #  endif
237 # else
238 #  define rb_data_object_alloc		dll_rb_data_object_alloc
239 # endif
240 # define rb_define_class_under		dll_rb_define_class_under
241 # define rb_define_const			dll_rb_define_const
242 # define rb_define_global_function	dll_rb_define_global_function
243 # define rb_define_method		dll_rb_define_method
244 # define rb_define_module		dll_rb_define_module
245 # define rb_define_module_function	dll_rb_define_module_function
246 # define rb_define_singleton_method	dll_rb_define_singleton_method
247 # define rb_define_virtual_variable	dll_rb_define_virtual_variable
248 # define rb_stdout			(*dll_rb_stdout)
249 # define rb_stderr			(*dll_rb_stderr)
250 # define rb_eArgError			(*dll_rb_eArgError)
251 # define rb_eIndexError			(*dll_rb_eIndexError)
252 # define rb_eRuntimeError		(*dll_rb_eRuntimeError)
253 # define rb_eStandardError		(*dll_rb_eStandardError)
254 # define rb_eval_string_protect		dll_rb_eval_string_protect
255 # ifdef RUBY21_OR_LATER
256 #  define rb_funcallv			dll_rb_funcallv
257 # else
258 #  define rb_funcall2			dll_rb_funcall2
259 # endif
260 # define rb_global_variable		dll_rb_global_variable
261 # define rb_hash_aset			dll_rb_hash_aset
262 # define rb_hash_new			dll_rb_hash_new
263 # define rb_inspect			dll_rb_inspect
264 # define rb_int2inum			dll_rb_int2inum
265 
266 // ruby.h may redefine rb_intern to use RUBY_CONST_ID_CACHE(), but that won't
267 // work.  Not using the cache appears to be the best solution.
268 # undef rb_intern
269 # define rb_intern			dll_rb_intern
270 
271 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
272 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18
273 #   define rb_fix2int			dll_rb_fix2int
274 #   define rb_num2int			dll_rb_num2int
275 #  endif
276 #  define rb_num2uint			dll_rb_num2uint
277 # endif
278 # define rb_lastline_get			dll_rb_lastline_get
279 # define rb_lastline_set			dll_rb_lastline_set
280 # define rb_protect			dll_rb_protect
281 # define rb_load			dll_rb_load
282 # ifndef RUBY19_OR_LATER
283 #  define rb_num2long			dll_rb_num2long
284 # endif
285 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 19
286 #  define rb_num2ulong			dll_rb_num2ulong
287 # endif
288 # define rb_obj_alloc			dll_rb_obj_alloc
289 # define rb_obj_as_string		dll_rb_obj_as_string
290 # define rb_obj_id			dll_rb_obj_id
291 # define rb_raise			dll_rb_raise
292 # define rb_str_cat			dll_rb_str_cat
293 # define rb_str_concat			dll_rb_str_concat
294 # undef rb_str_new
295 # define rb_str_new			dll_rb_str_new
296 # ifdef rb_str_new2
297 /* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
298 #  define need_rb_str_new_cstr 1
299 /* Ruby's headers #define rb_str_new_cstr to make use of GCC's
300  * __builtin_constant_p extension. */
301 #  undef rb_str_new_cstr
302 #  define rb_str_new_cstr		dll_rb_str_new_cstr
303 # else
304 #  define rb_str_new2			dll_rb_str_new2
305 # endif
306 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
307 #  define rb_string_value		dll_rb_string_value
308 #  define rb_string_value_ptr		dll_rb_string_value_ptr
309 #  define rb_float_new			dll_rb_float_new
310 #  define rb_ary_new			dll_rb_ary_new
311 #  ifdef rb_ary_new4
312 #    define RB_ARY_NEW4_MACRO 1
313 #    undef rb_ary_new4
314 #  endif
315 #  define rb_ary_new4			dll_rb_ary_new4
316 #  define rb_ary_push			dll_rb_ary_push
317 #  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
318 #   ifdef __ia64
319 #    define rb_ia64_bsp			dll_rb_ia64_bsp
320 #    undef ruby_init_stack
321 #    define ruby_init_stack(addr)	dll_ruby_init_stack((addr), rb_ia64_bsp())
322 #   else
323 #    define ruby_init_stack		dll_ruby_init_stack
324 #   endif
325 #  endif
326 # else
327 #  define rb_str2cstr			dll_rb_str2cstr
328 # endif
329 # ifdef RUBY19_OR_LATER
330 #  define rb_errinfo			dll_rb_errinfo
331 # else
332 #  define ruby_errinfo			(*dll_ruby_errinfo)
333 # endif
334 # define ruby_init			dll_ruby_init
335 # define ruby_init_loadpath		dll_ruby_init_loadpath
336 # ifdef MSWIN
337 #  ifdef RUBY19_OR_LATER
338 #   define ruby_sysinit			dll_ruby_sysinit
339 #  else
340 #   define NtInitialize			dll_NtInitialize
341 #  endif
342 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
343 #   define rb_w32_snprintf		dll_rb_w32_snprintf
344 #  endif
345 # endif
346 
347 # ifdef RUBY19_OR_LATER
348 #  define ruby_script			dll_ruby_script
349 #  define rb_enc_find_index		dll_rb_enc_find_index
350 #  define rb_enc_find			dll_rb_enc_find
351 #  undef rb_enc_str_new
352 #  define rb_enc_str_new		dll_rb_enc_str_new
353 #  define rb_sprintf			dll_rb_sprintf
354 #  define rb_require			dll_rb_require
355 #  define ruby_options			dll_ruby_options
356 # endif
357 
358 /*
359  * Pointers for dynamic link
360  */
361 static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
362 VALUE *dll_rb_cFalseClass;
363 VALUE *dll_rb_cFixnum;
364 # if defined(USE_RUBY_INTEGER)
365 VALUE *dll_rb_cInteger;
366 # endif
367 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
368 VALUE *dll_rb_cFloat;
369 # endif
370 VALUE *dll_rb_cNilClass;
371 static VALUE *dll_rb_cObject;
372 VALUE *dll_rb_cString;
373 VALUE *dll_rb_cSymbol;
374 VALUE *dll_rb_cTrueClass;
375 static VALUE (*dll_rb_class_new_instance) (int,VALUE*,VALUE);
376 static void (*dll_rb_check_type) (VALUE,int);
377 # ifdef USE_TYPEDDATA
378 static void *(*dll_rb_check_typeddata) (VALUE,const rb_data_type_t *);
379 # endif
380 static VALUE (*dll_rb_class_path) (VALUE);
381 # ifdef USE_TYPEDDATA
382 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23
383 static VALUE (*dll_rb_data_typed_object_wrap) (VALUE, void*, const rb_data_type_t *);
384 #  else
385 static VALUE (*dll_rb_data_typed_object_alloc) (VALUE, void*, const rb_data_type_t *);
386 #  endif
387 # else
388 static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
389 # endif
390 static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
391 static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
392 static void (*dll_rb_define_global_function) (const char*,VALUE(*)(),int);
393 static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(),int);
394 static VALUE (*dll_rb_define_module) (const char*);
395 static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(),int);
396 static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(),int);
397 static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(),void(*)());
398 static VALUE *dll_rb_stdout;
399 static VALUE *dll_rb_stderr;
400 static VALUE *dll_rb_eArgError;
401 static VALUE *dll_rb_eIndexError;
402 static VALUE *dll_rb_eRuntimeError;
403 static VALUE *dll_rb_eStandardError;
404 static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
405 # ifdef RUBY21_OR_LATER
406 static VALUE (*dll_rb_funcallv) (VALUE, ID, int, const VALUE*);
407 # else
408 static VALUE (*dll_rb_funcall2) (VALUE, ID, int, const VALUE*);
409 # endif
410 static void (*dll_rb_global_variable) (VALUE*);
411 static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
412 static VALUE (*dll_rb_hash_new) (void);
413 static VALUE (*dll_rb_inspect) (VALUE);
414 static VALUE (*dll_rb_int2inum) (long);
415 static ID (*dll_rb_intern) (const char*);
416 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
417 static long (*dll_rb_fix2int) (VALUE);
418 static long (*dll_rb_num2int) (VALUE);
419 static unsigned long (*dll_rb_num2uint) (VALUE);
420 # endif
421 static VALUE (*dll_rb_lastline_get) (void);
422 static void (*dll_rb_lastline_set) (VALUE);
423 static VALUE (*dll_rb_protect) (VALUE (*)(VALUE), VALUE, int*);
424 static void (*dll_rb_load) (VALUE, int);
425 static long (*dll_rb_num2long) (VALUE);
426 static unsigned long (*dll_rb_num2ulong) (VALUE);
427 static VALUE (*dll_rb_obj_alloc) (VALUE);
428 static VALUE (*dll_rb_obj_as_string) (VALUE);
429 static VALUE (*dll_rb_obj_id) (VALUE);
430 static void (*dll_rb_raise) (VALUE, const char*, ...);
431 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
432 static VALUE (*dll_rb_string_value) (volatile VALUE*);
433 # else
434 static char *(*dll_rb_str2cstr) (VALUE,int*);
435 # endif
436 static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
437 static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
438 static VALUE (*dll_rb_str_new) (const char*, long);
439 # ifdef need_rb_str_new_cstr
440 /* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */
441 static VALUE (*dll_rb_str_new_cstr) (const char*);
442 # else
443 static VALUE (*dll_rb_str_new2) (const char*);
444 # endif
445 # ifdef RUBY19_OR_LATER
446 static VALUE (*dll_rb_errinfo) (void);
447 # else
448 static VALUE *dll_ruby_errinfo;
449 # endif
450 static void (*dll_ruby_init) (void);
451 static void (*dll_ruby_init_loadpath) (void);
452 # ifdef MSWIN
453 #  ifdef RUBY19_OR_LATER
454 static void (*dll_ruby_sysinit) (int*, char***);
455 #  else
456 static void (*dll_NtInitialize) (int*, char***);
457 #  endif
458 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
459 static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
460 #  endif
461 # endif
462 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
463 static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
464 static VALUE (*dll_rb_float_new) (double);
465 static VALUE (*dll_rb_ary_new) (void);
466 static VALUE (*dll_rb_ary_new4) (long n, const VALUE *elts);
467 static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
468 #  if DYNAMIC_RUBY_VER >= 26
469 static void (*dll_rb_ary_detransient) (VALUE);
470 #  endif
471 #  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
472 #   ifdef __ia64
473 static void * (*dll_rb_ia64_bsp) (void);
474 static void (*dll_ruby_init_stack)(VALUE*, void*);
475 #   else
476 static void (*dll_ruby_init_stack)(VALUE*);
477 #   endif
478 #  endif
479 # endif
480 # ifdef RUBY19_OR_LATER
481 static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
482 # endif
483 
484 # ifdef RUBY19_OR_LATER
485 static void (*dll_ruby_script) (const char*);
486 static int (*dll_rb_enc_find_index) (const char*);
487 static rb_encoding* (*dll_rb_enc_find) (const char*);
488 static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
489 static VALUE (*dll_rb_sprintf) (const char*, ...);
490 static VALUE (*dll_rb_require) (const char*);
491 static void* (*ruby_options)(int, char**);
492 # endif
493 
494 # if defined(USE_RGENGC) && USE_RGENGC
495 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
496 static void (*dll_rb_gc_writebarrier_unprotect_promoted)(VALUE);
497 #  else
498 static void (*dll_rb_gc_writebarrier_unprotect)(VALUE obj);
499 #  endif
500 # endif
501 
502 # if defined(RUBY19_OR_LATER) && !defined(PROTO)
503 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
504 long rb_num2long_stub(VALUE x)
505 #  else
506 SIGNED_VALUE rb_num2long_stub(VALUE x)
507 #  endif
508 {
509     return dll_rb_num2long(x);
510 }
511 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26
512 VALUE rb_int2big_stub(intptr_t x)
513 #  else
514 VALUE rb_int2big_stub(SIGNED_VALUE x)
515 #  endif
516 {
517     return dll_rb_int2big(x);
518 }
519 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \
520 	&& VIM_SIZEOF_INT < VIM_SIZEOF_LONG
521 long rb_fix2int_stub(VALUE x)
522 {
523     return dll_rb_fix2int(x);
524 }
525 long rb_num2int_stub(VALUE x)
526 {
527     return dll_rb_num2int(x);
528 }
529 #  endif
530 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
531 VALUE
532 rb_float_new_in_heap(double d)
533 {
534     return dll_rb_float_new(d);
535 }
536 #   if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22
537 unsigned long rb_num2ulong(VALUE x)
538 #   else
539 VALUE rb_num2ulong(VALUE x)
540 #   endif
541 {
542     return (long)RSHIFT((SIGNED_VALUE)(x),1);
543 }
544 #  endif
545 # endif
546 
547    /* Do not generate a prototype here, VALUE isn't always defined. */
548 # if defined(USE_RGENGC) && USE_RGENGC && !defined(PROTO)
549 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
550 void rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj)
551 {
552     dll_rb_gc_writebarrier_unprotect_promoted(obj);
553 }
554 #  else
555 void rb_gc_writebarrier_unprotect_stub(VALUE obj)
556 {
557     dll_rb_gc_writebarrier_unprotect(obj);
558 }
559 #  endif
560 # endif
561 
562 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26
563 void rb_ary_detransient_stub(VALUE x)
564 {
565     dll_rb_ary_detransient(x);
566 }
567 # endif
568 
569 static HINSTANCE hinstRuby = NULL; /* Instance of ruby.dll */
570 
571 /*
572  * Table of name to function pointer of ruby.
573  */
574 static struct
575 {
576     char *name;
577     RUBY_PROC *ptr;
578 } ruby_funcname_table[] =
579 {
580     {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
581     {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
582 # if defined(USE_RUBY_INTEGER)
583     {"rb_cInteger", (RUBY_PROC*)&dll_rb_cInteger},
584 # else
585     {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
586 # endif
587 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20
588     {"rb_cFloat", (RUBY_PROC*)&dll_rb_cFloat},
589 # endif
590     {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
591     {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
592     {"rb_cString", (RUBY_PROC*)&dll_rb_cString},
593     {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
594     {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
595     {"rb_class_new_instance", (RUBY_PROC*)&dll_rb_class_new_instance},
596     {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
597 # ifdef USE_TYPEDDATA
598     {"rb_check_typeddata", (RUBY_PROC*)&dll_rb_check_typeddata},
599 # endif
600     {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
601 # ifdef USE_TYPEDDATA
602 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23
603     {"rb_data_typed_object_wrap", (RUBY_PROC*)&dll_rb_data_typed_object_wrap},
604 #  else
605     {"rb_data_typed_object_alloc", (RUBY_PROC*)&dll_rb_data_typed_object_alloc},
606 #  endif
607 # else
608     {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
609 # endif
610     {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
611     {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
612     {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
613     {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
614     {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
615     {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
616     {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
617     {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
618     {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
619     {"rb_stderr", (RUBY_PROC*)&dll_rb_stderr},
620     {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
621     {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
622     {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
623     {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
624     {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
625 # ifdef RUBY21_OR_LATER
626     {"rb_funcallv", (RUBY_PROC*)&dll_rb_funcallv},
627 # else
628     {"rb_funcall2", (RUBY_PROC*)&dll_rb_funcall2},
629 # endif
630     {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
631     {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
632     {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
633     {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
634     {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
635     {"rb_intern", (RUBY_PROC*)&dll_rb_intern},
636 # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG /* 64 bits only */
637     {"rb_fix2int", (RUBY_PROC*)&dll_rb_fix2int},
638     {"rb_num2int", (RUBY_PROC*)&dll_rb_num2int},
639     {"rb_num2uint", (RUBY_PROC*)&dll_rb_num2uint},
640 # endif
641     {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
642     {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
643     {"rb_protect", (RUBY_PROC*)&dll_rb_protect},
644     {"rb_load", (RUBY_PROC*)&dll_rb_load},
645     {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
646     {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
647     {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
648     {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
649     {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
650     {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
651 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
652     {"rb_string_value", (RUBY_PROC*)&dll_rb_string_value},
653 # else
654     {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr},
655 # endif
656     {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
657     {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
658     {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
659 # ifdef need_rb_str_new_cstr
660     {"rb_str_new_cstr", (RUBY_PROC*)&dll_rb_str_new_cstr},
661 # else
662     {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
663 # endif
664 # ifdef RUBY19_OR_LATER
665     {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
666 # else
667     {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo},
668 # endif
669     {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
670     {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
671 # ifdef MSWIN
672 #  ifdef RUBY19_OR_LATER
673     {"ruby_sysinit", (RUBY_PROC*)&dll_ruby_sysinit},
674 #  else
675     {"NtInitialize", (RUBY_PROC*)&dll_NtInitialize},
676 #  endif
677 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
678     {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
679 #  endif
680 # endif
681 # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
682     {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
683 #  if DYNAMIC_RUBY_VER <= 19
684     {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
685 #  else
686     {"rb_float_new_in_heap", (RUBY_PROC*)&dll_rb_float_new},
687 #  endif
688     {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
689 #  ifdef RB_ARY_NEW4_MACRO
690     {"rb_ary_new_from_values", (RUBY_PROC*)&dll_rb_ary_new4},
691 #  else
692     {"rb_ary_new4", (RUBY_PROC*)&dll_rb_ary_new4},
693 #  endif
694     {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
695 #  if DYNAMIC_RUBY_VER >= 26
696     {"rb_ary_detransient", (RUBY_PROC*)&dll_rb_ary_detransient},
697 #  endif
698 # endif
699 # ifdef RUBY19_OR_LATER
700     {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
701     {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
702     {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
703     {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
704     {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
705     {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
706     {"rb_require", (RUBY_PROC*)&dll_rb_require},
707     {"ruby_options", (RUBY_PROC*)&dll_ruby_options},
708 # endif
709 # if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
710 #  ifdef __ia64
711     {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp},
712 #  endif
713     {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
714 # endif
715 # if defined(USE_RGENGC) && USE_RGENGC
716 #  if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21
717     {"rb_gc_writebarrier_unprotect_promoted", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect_promoted},
718 #  else
719     {"rb_gc_writebarrier_unprotect", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect},
720 #  endif
721 # endif
722     {"", NULL},
723 };
724 
725 /*
726  * Free ruby.dll
727  */
728     static void
729 end_dynamic_ruby(void)
730 {
731     if (hinstRuby)
732     {
733 	close_dll(hinstRuby);
734 	hinstRuby = NULL;
735     }
736 }
737 
738 /*
739  * Load library and get all pointers.
740  * Parameter 'libname' provides name of DLL.
741  * Return OK or FAIL.
742  */
743     static int
744 ruby_runtime_link_init(char *libname, int verbose)
745 {
746     int i;
747 
748     if (hinstRuby)
749 	return OK;
750     hinstRuby = load_dll(libname);
751     if (!hinstRuby)
752     {
753 	if (verbose)
754 	    semsg(_(e_loadlib), libname);
755 	return FAIL;
756     }
757 
758     for (i = 0; ruby_funcname_table[i].ptr; ++i)
759     {
760 	if (!(*ruby_funcname_table[i].ptr = symbol_from_dll(hinstRuby,
761 			ruby_funcname_table[i].name)))
762 	{
763 	    close_dll(hinstRuby);
764 	    hinstRuby = NULL;
765 	    if (verbose)
766 		semsg(_(e_loadfunc), ruby_funcname_table[i].name);
767 	    return FAIL;
768 	}
769     }
770     return OK;
771 }
772 
773 /*
774  * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
775  * else FALSE.
776  */
777     int
778 ruby_enabled(int verbose)
779 {
780     return ruby_runtime_link_init((char *)p_rubydll, verbose) == OK;
781 }
782 #endif /* defined(DYNAMIC_RUBY) || defined(PROTO) */
783 
784     void
785 ruby_end(void)
786 {
787 #ifdef DYNAMIC_RUBY
788     end_dynamic_ruby();
789 #endif
790 }
791 
792 void ex_ruby(exarg_T *eap)
793 {
794     int state;
795     char *script = NULL;
796 
797     script = (char *)script_get(eap, eap->arg);
798     if (!eap->skip && ensure_ruby_initialized())
799     {
800 	if (script == NULL)
801 	    rb_eval_string_protect((char *)eap->arg, &state);
802 	else
803 	    rb_eval_string_protect(script, &state);
804 	if (state)
805 	    error_print(state);
806     }
807     vim_free(script);
808 }
809 
810 /*
811  *  In Ruby 1.9 or later, ruby String object has encoding.
812  *  conversion buffer string of vim to ruby String object using
813  *  VIM encoding option.
814  */
815     static VALUE
816 vim_str2rb_enc_str(const char *s)
817 {
818 #ifdef RUBY19_OR_LATER
819     int isnum;
820     long lval;
821     char_u *sval;
822     rb_encoding *enc;
823 
824     isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
825     if (isnum == 0)
826     {
827 	enc = rb_enc_find((char *)sval);
828 	vim_free(sval);
829 	if (enc)
830 	{
831 	    return rb_enc_str_new(s, (long)strlen(s), enc);
832 	}
833     }
834 #endif
835     return rb_str_new2(s);
836 }
837 
838     static VALUE
839 eval_enc_string_protect(const char *str, int *state)
840 {
841 #ifdef RUBY19_OR_LATER
842     int isnum;
843     long lval;
844     char_u *sval;
845     rb_encoding *enc;
846     VALUE v;
847 
848     isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
849     if (isnum == 0)
850     {
851 	enc = rb_enc_find((char *)sval);
852 	vim_free(sval);
853 	if (enc)
854 	{
855 	    v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
856 	    return rb_eval_string_protect(StringValuePtr(v), state);
857 	}
858     }
859 #endif
860     return rb_eval_string_protect(str, state);
861 }
862 
863 void ex_rubydo(exarg_T *eap)
864 {
865     int state;
866     linenr_T i;
867     buf_T   *was_curbuf = curbuf;
868 
869     if (ensure_ruby_initialized())
870     {
871 	if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
872 	    return;
873 	for (i = eap->line1; i <= eap->line2; i++)
874 	{
875 	    VALUE line;
876 
877 	    if (i > curbuf->b_ml.ml_line_count)
878 		break;
879 	    line = vim_str2rb_enc_str((char *)ml_get(i));
880 	    rb_lastline_set(line);
881 	    eval_enc_string_protect((char *) eap->arg, &state);
882 	    if (state)
883 	    {
884 		error_print(state);
885 		break;
886 	    }
887 	    if (was_curbuf != curbuf)
888 		break;
889 	    line = rb_lastline_get();
890 	    if (!NIL_P(line))
891 	    {
892 		if (TYPE(line) != T_STRING)
893 		{
894 		    emsg(_("E265: $_ must be an instance of String"));
895 		    return;
896 		}
897 		ml_replace(i, (char_u *) StringValuePtr(line), 1);
898 		changed();
899 #ifdef SYNTAX_HL
900 		syn_changed(i); /* recompute syntax hl. for this line */
901 #endif
902 	    }
903 	}
904 	check_cursor();
905 	update_curbuf(NOT_VALID);
906     }
907 }
908 
909 static VALUE rb_load_wrap(VALUE file_to_load)
910 {
911     rb_load(file_to_load, 0);
912     return Qnil;
913 }
914 
915 void ex_rubyfile(exarg_T *eap)
916 {
917     int state;
918 
919     if (ensure_ruby_initialized())
920     {
921 	VALUE file_to_load = rb_str_new2((const char *)eap->arg);
922 	rb_protect(rb_load_wrap, file_to_load, &state);
923 	if (state)
924 	    error_print(state);
925     }
926 }
927 
928 void ruby_buffer_free(buf_T *buf)
929 {
930     if (buf->b_ruby_ref)
931     {
932 	rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
933 	RDATA(buf->b_ruby_ref)->data = NULL;
934     }
935 }
936 
937 void ruby_window_free(win_T *win)
938 {
939     if (win->w_ruby_ref)
940     {
941 	rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
942 	RDATA(win->w_ruby_ref)->data = NULL;
943     }
944 }
945 
946 static int ensure_ruby_initialized(void)
947 {
948     if (!ruby_initialized)
949     {
950 #ifdef DYNAMIC_RUBY
951 	if (ruby_enabled(TRUE))
952 	{
953 #endif
954 #ifdef MSWIN
955 	    /* suggested by Ariya Mizutani */
956 	    int argc = 1;
957 	    char *argv[] = {"gvim.exe"};
958 	    char **argvp = argv;
959 # ifdef RUBY19_OR_LATER
960 	    ruby_sysinit(&argc, &argvp);
961 # else
962 	    NtInitialize(&argc, &argvp);
963 # endif
964 #endif
965 	    {
966 #if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
967 		ruby_init_stack(ruby_stack_start);
968 #endif
969 		ruby_init();
970 	    }
971 #ifdef RUBY19_OR_LATER
972 	    {
973 		int dummy_argc = 2;
974 		char *dummy_argv[] = {"vim-ruby", "-e_=0"};
975 		ruby_options(dummy_argc, dummy_argv);
976 	    }
977 	    ruby_script("vim-ruby");
978 #else
979 	    ruby_init_loadpath();
980 #endif
981 	    ruby_io_init();
982 	    ruby_vim_init();
983 	    ruby_initialized = 1;
984 #ifdef DYNAMIC_RUBY
985 	}
986 	else
987 	{
988 	    emsg(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
989 	    return 0;
990 	}
991 #endif
992     }
993     return ruby_initialized;
994 }
995 
996 static void error_print(int state)
997 {
998 #if !defined(DYNAMIC_RUBY) && !defined(RUBY19_OR_LATER)
999     RUBYEXTERN VALUE ruby_errinfo;
1000 #endif
1001     VALUE error;
1002     VALUE eclass;
1003     VALUE einfo;
1004     VALUE bt;
1005     int attr;
1006     char buff[BUFSIZ];
1007     long i;
1008 
1009 #define TAG_RETURN	0x1
1010 #define TAG_BREAK	0x2
1011 #define TAG_NEXT	0x3
1012 #define TAG_RETRY	0x4
1013 #define TAG_REDO	0x5
1014 #define TAG_RAISE	0x6
1015 #define TAG_THROW	0x7
1016 #define TAG_FATAL	0x8
1017 #define TAG_MASK	0xf
1018 
1019     switch (state)
1020     {
1021     case TAG_RETURN:
1022 	emsg(_("E267: unexpected return"));
1023 	break;
1024     case TAG_NEXT:
1025 	emsg(_("E268: unexpected next"));
1026 	break;
1027     case TAG_BREAK:
1028 	emsg(_("E269: unexpected break"));
1029 	break;
1030     case TAG_REDO:
1031 	emsg(_("E270: unexpected redo"));
1032 	break;
1033     case TAG_RETRY:
1034 	emsg(_("E271: retry outside of rescue clause"));
1035 	break;
1036     case TAG_RAISE:
1037     case TAG_FATAL:
1038 #ifdef RUBY19_OR_LATER
1039 	error = rb_errinfo();
1040 #else
1041 	error = ruby_errinfo;
1042 #endif
1043 	eclass = CLASS_OF(error);
1044 	einfo = rb_obj_as_string(error);
1045 	if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0)
1046 	{
1047 	    emsg(_("E272: unhandled exception"));
1048 	}
1049 	else
1050 	{
1051 	    VALUE epath;
1052 	    char *p;
1053 
1054 	    epath = rb_class_path(eclass);
1055 	    vim_snprintf(buff, BUFSIZ, "%s: %s",
1056 		     RSTRING_PTR(epath), RSTRING_PTR(einfo));
1057 	    p = strchr(buff, '\n');
1058 	    if (p) *p = '\0';
1059 	    emsg(buff);
1060 	}
1061 
1062 	attr = syn_name2attr((char_u *)"Error");
1063 # ifdef RUBY21_OR_LATER
1064 	bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
1065 	for (i = 0; i < RARRAY_LEN(bt); i++)
1066 	    msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
1067 # else
1068 	bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0);
1069 	for (i = 0; i < RARRAY_LEN(bt); i++)
1070 	    msg_attr(RSTRING_PTR(RARRAY_PTR(bt)[i]), attr);
1071 # endif
1072 	break;
1073     default:
1074 	vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state);
1075 	emsg(buff);
1076 	break;
1077     }
1078 }
1079 
1080 static VALUE vim_message(VALUE self UNUSED, VALUE str)
1081 {
1082     char *buff, *p;
1083 
1084     str = rb_obj_as_string(str);
1085     if (RSTRING_LEN(str) > 0)
1086     {
1087 	/* Only do this when the string isn't empty, alloc(0) causes trouble. */
1088 	buff = ALLOCA_N(char, RSTRING_LEN(str) + 1);
1089 	strcpy(buff, RSTRING_PTR(str));
1090 	p = strchr(buff, '\n');
1091 	if (p) *p = '\0';
1092 	msg(buff);
1093     }
1094     else
1095     {
1096 	msg("");
1097     }
1098     return Qnil;
1099 }
1100 
1101 static VALUE vim_set_option(VALUE self UNUSED, VALUE str)
1102 {
1103     do_set((char_u *)StringValuePtr(str), 0);
1104     update_screen(NOT_VALID);
1105     return Qnil;
1106 }
1107 
1108 static VALUE vim_command(VALUE self UNUSED, VALUE str)
1109 {
1110     do_cmdline_cmd((char_u *)StringValuePtr(str));
1111     return Qnil;
1112 }
1113 
1114 #ifdef FEAT_EVAL
1115 static VALUE vim_to_ruby(typval_T *tv)
1116 {
1117     VALUE result = Qnil;
1118 
1119     if (tv->v_type == VAR_STRING)
1120     {
1121 	result = rb_str_new2(tv->vval.v_string == NULL
1122 					  ? "" : (char *)(tv->vval.v_string));
1123     }
1124     else if (tv->v_type == VAR_NUMBER)
1125     {
1126 	result = INT2NUM(tv->vval.v_number);
1127     }
1128 # ifdef FEAT_FLOAT
1129     else if (tv->v_type == VAR_FLOAT)
1130     {
1131 	result = rb_float_new(tv->vval.v_float);
1132     }
1133 # endif
1134     else if (tv->v_type == VAR_LIST)
1135     {
1136 	list_T      *list = tv->vval.v_list;
1137 	listitem_T  *curr;
1138 
1139 	result = rb_ary_new();
1140 
1141 	if (list != NULL)
1142 	{
1143 	    for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
1144 	    {
1145 		rb_ary_push(result, vim_to_ruby(&curr->li_tv));
1146 	    }
1147 	}
1148     }
1149     else if (tv->v_type == VAR_DICT)
1150     {
1151 	result = rb_hash_new();
1152 
1153 	if (tv->vval.v_dict != NULL)
1154 	{
1155 	    hashtab_T   *ht = &tv->vval.v_dict->dv_hashtab;
1156 	    long_u      todo = ht->ht_used;
1157 	    hashitem_T  *hi;
1158 	    dictitem_T  *di;
1159 
1160 	    for (hi = ht->ht_array; todo > 0; ++hi)
1161 	    {
1162 		if (!HASHITEM_EMPTY(hi))
1163 		{
1164 		    --todo;
1165 
1166 		    di = dict_lookup(hi);
1167 		    rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
1168 						     vim_to_ruby(&di->di_tv));
1169 		}
1170 	    }
1171 	}
1172     }
1173     else if (tv->v_type == VAR_SPECIAL)
1174     {
1175 	if (tv->vval.v_number == VVAL_TRUE)
1176 	    result = Qtrue;
1177 	else if (tv->vval.v_number == VVAL_FALSE)
1178 	    result = Qfalse;
1179     }
1180     else if (tv->v_type == VAR_BLOB)
1181     {
1182 	result = rb_str_new(tv->vval.v_blob->bv_ga.ga_data,
1183 		tv->vval.v_blob->bv_ga.ga_len);
1184     }
1185     /* else return Qnil; */
1186 
1187     return result;
1188 }
1189 #endif
1190 
1191 static VALUE vim_evaluate(VALUE self UNUSED, VALUE str)
1192 {
1193 #ifdef FEAT_EVAL
1194     typval_T    *tv;
1195     VALUE       result;
1196 
1197     tv = eval_expr((char_u *)StringValuePtr(str), NULL);
1198     if (tv == NULL)
1199     {
1200 	return Qnil;
1201     }
1202     result = vim_to_ruby(tv);
1203 
1204     free_tv(tv);
1205 
1206     return result;
1207 #else
1208     return Qnil;
1209 #endif
1210 }
1211 
1212 #ifdef USE_TYPEDDATA
1213 static size_t buffer_dsize(const void *buf);
1214 
1215 static const rb_data_type_t buffer_type = {
1216     "vim_buffer",
1217     {0, 0, buffer_dsize, {0, 0}},
1218     0, 0,
1219 # ifdef RUBY_TYPED_FREE_IMMEDIATELY
1220     0,
1221 # endif
1222 };
1223 
1224 static size_t buffer_dsize(const void *buf UNUSED)
1225 {
1226     return sizeof(buf_T);
1227 }
1228 #endif
1229 
1230 static VALUE buffer_new(buf_T *buf)
1231 {
1232     if (buf->b_ruby_ref)
1233     {
1234 	return (VALUE) buf->b_ruby_ref;
1235     }
1236     else
1237     {
1238 #ifdef USE_TYPEDDATA
1239 	VALUE obj = TypedData_Wrap_Struct(cBuffer, &buffer_type, buf);
1240 #else
1241 	VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
1242 #endif
1243 	buf->b_ruby_ref = (void *) obj;
1244 	rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1245 	return obj;
1246     }
1247 }
1248 
1249 static buf_T *get_buf(VALUE obj)
1250 {
1251     buf_T *buf;
1252 
1253 #ifdef USE_TYPEDDATA
1254     TypedData_Get_Struct(obj, buf_T, &buffer_type, buf);
1255 #else
1256     Data_Get_Struct(obj, buf_T, buf);
1257 #endif
1258     if (buf == NULL)
1259 	rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
1260     return buf;
1261 }
1262 
1263 static VALUE vim_blob(VALUE self UNUSED, VALUE str)
1264 {
1265     VALUE result = rb_str_new("0z", 2);
1266     char    buf[4];
1267     int	i;
1268     for (i = 0; i < RSTRING_LEN(str); i++)
1269     {
1270 	sprintf(buf, "%02X", RSTRING_PTR(str)[i]);
1271 	rb_str_concat(result, rb_str_new2(buf));
1272     }
1273     return result;
1274 }
1275 
1276 static VALUE buffer_s_current(void)
1277 {
1278     return buffer_new(curbuf);
1279 }
1280 
1281 static VALUE buffer_s_count(void)
1282 {
1283     buf_T *b;
1284     int n = 0;
1285 
1286     FOR_ALL_BUFFERS(b)
1287     {
1288 	/*  Deleted buffers should not be counted
1289 	 *    SegPhault - 01/07/05 */
1290 	if (b->b_p_bl)
1291 	    n++;
1292     }
1293 
1294     return INT2NUM(n);
1295 }
1296 
1297 static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num)
1298 {
1299     buf_T *b;
1300     int n = NUM2INT(num);
1301 
1302     FOR_ALL_BUFFERS(b)
1303     {
1304 	/*  Deleted buffers should not be counted
1305 	 *    SegPhault - 01/07/05 */
1306 	if (!b->b_p_bl)
1307 	    continue;
1308 
1309 	if (n == 0)
1310 	    return buffer_new(b);
1311 
1312 	n--;
1313     }
1314     return Qnil;
1315 }
1316 
1317 static VALUE buffer_name(VALUE self)
1318 {
1319     buf_T *buf = get_buf(self);
1320 
1321     return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
1322 }
1323 
1324 static VALUE buffer_number(VALUE self)
1325 {
1326     buf_T *buf = get_buf(self);
1327 
1328     return INT2NUM(buf->b_fnum);
1329 }
1330 
1331 static VALUE buffer_count(VALUE self)
1332 {
1333     buf_T *buf = get_buf(self);
1334 
1335     return INT2NUM(buf->b_ml.ml_line_count);
1336 }
1337 
1338 static VALUE get_buffer_line(buf_T *buf, linenr_T n)
1339 {
1340     if (n <= 0 || n > buf->b_ml.ml_line_count)
1341 	rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
1342     return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE));
1343 }
1344 
1345 static VALUE buffer_aref(VALUE self, VALUE num)
1346 {
1347     buf_T *buf = get_buf(self);
1348 
1349     if (buf != NULL)
1350 	return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
1351     return Qnil; /* For stop warning */
1352 }
1353 
1354 static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
1355 {
1356     char	*line = StringValuePtr(str);
1357     aco_save_T	aco;
1358 
1359     if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
1360     {
1361 	/* set curwin/curbuf for "buf" and save some things */
1362 	aucmd_prepbuf(&aco, buf);
1363 
1364 	if (u_savesub(n) == OK)
1365 	{
1366 	    ml_replace(n, (char_u *)line, TRUE);
1367 	    changed();
1368 #ifdef SYNTAX_HL
1369 	    syn_changed(n); /* recompute syntax hl. for this line */
1370 #endif
1371 	}
1372 
1373 	/* restore curwin/curbuf and a few other things */
1374 	aucmd_restbuf(&aco);
1375 	/* Careful: autocommands may have made "buf" invalid! */
1376 
1377 	update_curbuf(NOT_VALID);
1378     }
1379     else
1380     {
1381 	rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
1382     }
1383     return str;
1384 }
1385 
1386 static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
1387 {
1388     buf_T *buf = get_buf(self);
1389 
1390     if (buf != NULL)
1391 	return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
1392     return str;
1393 }
1394 
1395 static VALUE buffer_delete(VALUE self, VALUE num)
1396 {
1397     buf_T	*buf = get_buf(self);
1398     long	n = NUM2LONG(num);
1399     aco_save_T	aco;
1400 
1401     if (n > 0 && n <= buf->b_ml.ml_line_count)
1402     {
1403 	/* set curwin/curbuf for "buf" and save some things */
1404 	aucmd_prepbuf(&aco, buf);
1405 
1406 	if (u_savedel(n, 1) == OK)
1407 	{
1408 	    ml_delete(n, 0);
1409 
1410 	    /* Changes to non-active buffers should properly refresh
1411 	     *   SegPhault - 01/09/05 */
1412 	    deleted_lines_mark(n, 1L);
1413 
1414 	    changed();
1415 	}
1416 
1417 	/* restore curwin/curbuf and a few other things */
1418 	aucmd_restbuf(&aco);
1419 	/* Careful: autocommands may have made "buf" invalid! */
1420 
1421 	update_curbuf(NOT_VALID);
1422     }
1423     else
1424     {
1425 	rb_raise(rb_eIndexError, "line number %ld out of range", n);
1426     }
1427     return Qnil;
1428 }
1429 
1430 static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
1431 {
1432     buf_T	*buf = get_buf(self);
1433     char	*line = StringValuePtr(str);
1434     long	n = NUM2LONG(num);
1435     aco_save_T	aco;
1436 
1437     if (line == NULL)
1438     {
1439 	rb_raise(rb_eIndexError, "NULL line");
1440     }
1441     else if (n >= 0 && n <= buf->b_ml.ml_line_count)
1442     {
1443 	/* set curwin/curbuf for "buf" and save some things */
1444 	aucmd_prepbuf(&aco, buf);
1445 
1446 	if (u_inssub(n + 1) == OK)
1447 	{
1448 	    ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
1449 
1450 	    /*  Changes to non-active buffers should properly refresh screen
1451 	     *    SegPhault - 12/20/04 */
1452 	    appended_lines_mark(n, 1L);
1453 
1454 	    changed();
1455 	}
1456 
1457 	/* restore curwin/curbuf and a few other things */
1458 	aucmd_restbuf(&aco);
1459 	/* Careful: autocommands may have made "buf" invalid! */
1460 
1461 	update_curbuf(NOT_VALID);
1462     }
1463     else
1464     {
1465 	rb_raise(rb_eIndexError, "line number %ld out of range", n);
1466     }
1467     return str;
1468 }
1469 
1470 #ifdef USE_TYPEDDATA
1471 static size_t window_dsize(const void *buf);
1472 
1473 static const rb_data_type_t window_type = {
1474     "vim_window",
1475     {0, 0, window_dsize, {0, 0}},
1476     0, 0,
1477 # ifdef RUBY_TYPED_FREE_IMMEDIATELY
1478     0,
1479 # endif
1480 };
1481 
1482 static size_t window_dsize(const void *win UNUSED)
1483 {
1484     return sizeof(win_T);
1485 }
1486 #endif
1487 
1488 static VALUE window_new(win_T *win)
1489 {
1490     if (win->w_ruby_ref)
1491     {
1492 	return (VALUE) win->w_ruby_ref;
1493     }
1494     else
1495     {
1496 #ifdef USE_TYPEDDATA
1497 	VALUE obj = TypedData_Wrap_Struct(cVimWindow, &window_type, win);
1498 #else
1499 	VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
1500 #endif
1501 	win->w_ruby_ref = (void *) obj;
1502 	rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1503 	return obj;
1504     }
1505 }
1506 
1507 static win_T *get_win(VALUE obj)
1508 {
1509     win_T *win;
1510 
1511 #ifdef USE_TYPEDDATA
1512     TypedData_Get_Struct(obj, win_T, &window_type, win);
1513 #else
1514     Data_Get_Struct(obj, win_T, win);
1515 #endif
1516     if (win == NULL)
1517 	rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1518     return win;
1519 }
1520 
1521 static VALUE window_s_current(void)
1522 {
1523     return window_new(curwin);
1524 }
1525 
1526 /*
1527  * Added line manipulation functions
1528  *    SegPhault - 03/07/05
1529  */
1530 static VALUE line_s_current(void)
1531 {
1532     return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1533 }
1534 
1535 static VALUE set_current_line(VALUE self UNUSED, VALUE str)
1536 {
1537     return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1538 }
1539 
1540 static VALUE current_line_number(void)
1541 {
1542     return INT2FIX((int)curwin->w_cursor.lnum);
1543 }
1544 
1545 
1546 
1547 static VALUE window_s_count(void)
1548 {
1549     win_T	*w;
1550     int n = 0;
1551 
1552     FOR_ALL_WINDOWS(w)
1553 	n++;
1554     return INT2NUM(n);
1555 }
1556 
1557 static VALUE window_s_aref(VALUE self UNUSED, VALUE num)
1558 {
1559     win_T *w;
1560     int n = NUM2INT(num);
1561 
1562     for (w = firstwin; w != NULL; w = w->w_next, --n)
1563 	if (n == 0)
1564 	    return window_new(w);
1565     return Qnil;
1566 }
1567 
1568 static VALUE window_buffer(VALUE self)
1569 {
1570     win_T *win = get_win(self);
1571 
1572     return buffer_new(win->w_buffer);
1573 }
1574 
1575 static VALUE window_height(VALUE self)
1576 {
1577     win_T *win = get_win(self);
1578 
1579     return INT2NUM(win->w_height);
1580 }
1581 
1582 static VALUE window_set_height(VALUE self, VALUE height)
1583 {
1584     win_T *win = get_win(self);
1585     win_T *savewin = curwin;
1586 
1587     curwin = win;
1588     win_setheight(NUM2INT(height));
1589     curwin = savewin;
1590     return height;
1591 }
1592 
1593 static VALUE window_width(VALUE self UNUSED)
1594 {
1595     return INT2NUM(get_win(self)->w_width);
1596 }
1597 
1598 static VALUE window_set_width(VALUE self UNUSED, VALUE width)
1599 {
1600     win_T *win = get_win(self);
1601     win_T *savewin = curwin;
1602 
1603     curwin = win;
1604     win_setwidth(NUM2INT(width));
1605     curwin = savewin;
1606     return width;
1607 }
1608 
1609 static VALUE window_cursor(VALUE self)
1610 {
1611     win_T *win = get_win(self);
1612 
1613     return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1614 }
1615 
1616 static VALUE window_set_cursor(VALUE self, VALUE pos)
1617 {
1618     VALUE lnum, col;
1619     win_T *win = get_win(self);
1620 
1621     Check_Type(pos, T_ARRAY);
1622     if (RARRAY_LEN(pos) != 2)
1623 	rb_raise(rb_eArgError, "array length must be 2");
1624     lnum = RARRAY_PTR(pos)[0];
1625     col = RARRAY_PTR(pos)[1];
1626     win->w_cursor.lnum = NUM2LONG(lnum);
1627     win->w_cursor.col = NUM2UINT(col);
1628     win->w_set_curswant = TRUE;
1629     check_cursor();		    /* put cursor on an existing line */
1630     update_screen(NOT_VALID);
1631     return Qnil;
1632 }
1633 
1634 static VALUE f_nop(VALUE self UNUSED)
1635 {
1636     return Qnil;
1637 }
1638 
1639 static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED)
1640 {
1641     int i;
1642     VALUE str = rb_str_new("", 0);
1643     VALUE ret = Qnil;
1644 
1645     for (i = 0; i < argc; i++)
1646     {
1647 	if (i > 0) rb_str_cat(str, ", ", 2);
1648 	rb_str_concat(str, rb_inspect(argv[i]));
1649     }
1650     msg(RSTRING_PTR(str));
1651 
1652     if (argc == 1)
1653 	ret = argv[0];
1654     else if (argc > 1)
1655 	ret = rb_ary_new4(argc, argv);
1656     return ret;
1657 }
1658 
1659 static void ruby_io_init(void)
1660 {
1661 #ifndef DYNAMIC_RUBY
1662     RUBYEXTERN VALUE rb_stdout;
1663     RUBYEXTERN VALUE rb_stderr;
1664 #endif
1665 
1666     rb_stdout = rb_obj_alloc(rb_cObject);
1667     rb_stderr = rb_obj_alloc(rb_cObject);
1668     rb_define_singleton_method(rb_stdout, "write", vim_message, 1);
1669     rb_define_singleton_method(rb_stdout, "flush", f_nop, 0);
1670     rb_define_singleton_method(rb_stderr, "write", vim_message, 1);
1671     rb_define_singleton_method(rb_stderr, "flush", f_nop, 0);
1672     rb_define_global_function("p", f_p, -1);
1673 }
1674 
1675 static void ruby_vim_init(void)
1676 {
1677     objtbl = rb_hash_new();
1678     rb_global_variable(&objtbl);
1679 
1680     /* The Vim module used to be called "VIM", but "Vim" is better.  Make an
1681      * alias "VIM" for backwards compatibility. */
1682     mVIM = rb_define_module("Vim");
1683     rb_define_const(rb_cObject, "VIM", mVIM);
1684     rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1685     rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1686     rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1687     rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1688     rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1689     rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1690     rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1691     rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1692     rb_define_module_function(mVIM, "message", vim_message, 1);
1693     rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1694     rb_define_module_function(mVIM, "command", vim_command, 1);
1695     rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
1696     rb_define_module_function(mVIM, "blob", vim_blob, 1);
1697 
1698     eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1699 						rb_eStandardError);
1700     eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1701 						rb_eStandardError);
1702 
1703     cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
1704     rb_define_singleton_method(cBuffer, "current", buffer_s_current, 0);
1705     rb_define_singleton_method(cBuffer, "count", buffer_s_count, 0);
1706     rb_define_singleton_method(cBuffer, "[]", buffer_s_aref, 1);
1707     rb_define_method(cBuffer, "name", buffer_name, 0);
1708     rb_define_method(cBuffer, "number", buffer_number, 0);
1709     rb_define_method(cBuffer, "count", buffer_count, 0);
1710     rb_define_method(cBuffer, "length", buffer_count, 0);
1711     rb_define_method(cBuffer, "[]", buffer_aref, 1);
1712     rb_define_method(cBuffer, "[]=", buffer_aset, 2);
1713     rb_define_method(cBuffer, "delete", buffer_delete, 1);
1714     rb_define_method(cBuffer, "append", buffer_append, 2);
1715 
1716     /* Added line manipulation functions
1717      *   SegPhault - 03/07/05 */
1718     rb_define_method(cBuffer, "line_number", current_line_number, 0);
1719     rb_define_method(cBuffer, "line", line_s_current, 0);
1720     rb_define_method(cBuffer, "line=", set_current_line, 1);
1721 
1722 
1723     cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
1724     rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
1725     rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
1726     rb_define_singleton_method(cVimWindow, "[]", window_s_aref, 1);
1727     rb_define_method(cVimWindow, "buffer", window_buffer, 0);
1728     rb_define_method(cVimWindow, "height", window_height, 0);
1729     rb_define_method(cVimWindow, "height=", window_set_height, 1);
1730     rb_define_method(cVimWindow, "width", window_width, 0);
1731     rb_define_method(cVimWindow, "width=", window_set_width, 1);
1732     rb_define_method(cVimWindow, "cursor", window_cursor, 0);
1733     rb_define_method(cVimWindow, "cursor=", window_set_cursor, 1);
1734 
1735     rb_define_virtual_variable("$curbuf", buffer_s_current, 0);
1736     rb_define_virtual_variable("$curwin", window_s_current, 0);
1737 }
1738 
1739 void vim_ruby_init(void *stack_start)
1740 {
1741     /* should get machine stack start address early in main function */
1742     ruby_stack_start = stack_start;
1743 }
1744