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