blob: b769adfa2f41a752a64bcd3bb0870fdfed83aed0 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00004 *
5 * Ruby interface by Shugo Maeda
6 * with improvements by SegPhault (Ryan Paul)
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +02007 * with improvements by Jon Maken
Bram Moolenaar071d4272004-06-13 20:20:40 +00008 *
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
Bram Moolenaar32d19c12018-09-13 17:26:54 +020014#include "protodef.h"
Bram Moolenaar2d73ff42010-10-27 17:40:59 +020015#ifdef HAVE_CONFIG_H
16# include "auto/config.h"
17#endif
Bram Moolenaar3ca71f12010-10-27 16:49:47 +020018
Bram Moolenaare2793352011-01-17 19:53:27 +010019#include <stdio.h>
20#include <string.h>
21
Bram Moolenaar071d4272004-06-13 20:20:40 +000022#ifdef _WIN32
Bram Moolenaar071d4272004-06-13 20:20:40 +000023# ifndef DYNAMIC_RUBY
K.Takata236ccbf2022-09-22 16:12:06 +010024# define NT
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010025# define IMPORT // For static dll usage __declspec(dllimport)
Bram Moolenaar071d4272004-06-13 20:20:40 +000026# define RUBYEXTERN __declspec(dllimport)
27# endif
28#endif
29#ifndef RUBYEXTERN
30# define RUBYEXTERN extern
31#endif
32
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +020033#ifdef DYNAMIC_RUBY
Bram Moolenaar071d4272004-06-13 20:20:40 +000034/*
35 * This is tricky. In ruby.h there is (inline) function rb_class_of()
36 * definition. This function use these variables. But we want function to
37 * use dll_* variables.
38 */
Bram Moolenaardace9f72020-12-28 15:07:45 +010039# if RUBY_VERSION >= 24
40# define USE_RUBY_INTEGER
41# endif
42
Bram Moolenaar071d4272004-06-13 20:20:40 +000043# define rb_cFalseClass (*dll_rb_cFalseClass)
44# define rb_cFixnum (*dll_rb_cFixnum)
Bram Moolenaar2016ae52016-06-13 20:08:43 +020045# if defined(USE_RUBY_INTEGER)
46# define rb_cInteger (*dll_rb_cInteger)
Bram Moolenaar06469e92016-06-11 22:26:53 +020047# endif
Bram Moolenaar41a41412020-01-07 21:32:19 +010048# if RUBY_VERSION >= 20
Bram Moolenaardb3fbe52013-03-07 15:16:21 +010049# define rb_cFloat (*dll_rb_cFloat)
50# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000051# define rb_cNilClass (*dll_rb_cNilClass)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +010052# define rb_cString (*dll_rb_cString)
Bram Moolenaar071d4272004-06-13 20:20:40 +000053# define rb_cSymbol (*dll_rb_cSymbol)
54# define rb_cTrueClass (*dll_rb_cTrueClass)
Bram Moolenaardace9f72020-12-28 15:07:45 +010055
Bram Moolenaar071d4272004-06-13 20:20:40 +000056/*
K.Takata236ccbf2022-09-22 16:12:06 +010057 * All Ruby functions are exported with "__declspec(dllimport)" in ruby.h.
58 * But it causes trouble for these variables, because it is defined in this
59 * file. When defined this RUBY_EXPORT it modified to "extern" and be able
60 * to avoid this problem.
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 */
K.Takata236ccbf2022-09-22 16:12:06 +010062# define RUBY_EXPORT
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +020063
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010064// Ruby 1.9 defines a number of static functions which use rb_num2long and
65// rb_int2big
K.Takata236ccbf2022-09-22 16:12:06 +010066# define rb_num2long rb_num2long_stub
67# define rb_int2big rb_int2big_stub
Bram Moolenaar42d57f02010-03-10 12:47:00 +010068
K.Takata236ccbf2022-09-22 16:12:06 +010069# if RUBY_VERSION >= 30 || VIM_SIZEOF_INT < VIM_SIZEOF_LONG
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010070// Ruby 1.9 defines a number of static functions which use rb_fix2int and
71// rb_num2int if VIM_SIZEOF_INT < VIM_SIZEOF_LONG (64bit)
K.Takata236ccbf2022-09-22 16:12:06 +010072# define rb_fix2int rb_fix2int_stub
73# define rb_num2int rb_num2int_stub
Bram Moolenaardace9f72020-12-28 15:07:45 +010074# endif
Bram Moolenaar0bcdd6e2013-04-14 16:19:03 +020075
Bram Moolenaardace9f72020-12-28 15:07:45 +010076# if RUBY_VERSION == 21
Bram Moolenaar2ab2e862019-12-04 21:24:53 +010077// Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses
78// rb_gc_writebarrier_unprotect_promoted if USE_RGENGC
ichizok8bb3fe42021-12-28 15:51:45 +000079# define rb_gc_writebarrier_unprotect_promoted rb_gc_writebarrier_unprotect_promoted_stub
Bram Moolenaardace9f72020-12-28 15:07:45 +010080# endif
Bram Moolenaara1a118b2014-02-05 22:41:15 +010081
Bram Moolenaardace9f72020-12-28 15:07:45 +010082# if RUBY_VERSION >= 22
ichizok8bb3fe42021-12-28 15:51:45 +000083# define rb_gc_writebarrier_unprotect rb_gc_writebarrier_unprotect_stub
Bram Moolenaardace9f72020-12-28 15:07:45 +010084# endif
85
Isao Sato443657b2024-01-03 19:31:05 +010086# if RUBY_VERSION >= 26 && RUBY_VERSION <= 32
ichizok8bb3fe42021-12-28 15:51:45 +000087# define rb_ary_detransient rb_ary_detransient_stub
Bram Moolenaardace9f72020-12-28 15:07:45 +010088# endif
89
90# if RUBY_VERSION >= 30
ichizok8bb3fe42021-12-28 15:51:45 +000091# define rb_check_type rb_check_type_stub
92# define rb_num2uint rb_num2uint_stub
93# define ruby_malloc_size_overflow ruby_malloc_size_overflow_stub
94# endif
95
96# if RUBY_VERSION >= 31
97# define rb_debug_rstring_null_ptr rb_debug_rstring_null_ptr_stub
98# define rb_unexpected_type rb_unexpected_type_stub
Bram Moolenaardace9f72020-12-28 15:07:45 +010099# endif
100
101#endif // ifdef DYNAMIC_RUBY
Bram Moolenaarb09c6842018-12-27 22:11:01 +0100102
Bram Moolenaar81ea1df2020-04-11 18:01:41 +0200103// On macOS pre-installed Ruby defines "SIZEOF_TIME_T" as "SIZEOF_LONG" so it
Bram Moolenaar92c098d2020-05-26 20:09:11 +0200104// conflicts with the definition in config.h then causes a macro-redefined
105// warning.
Bram Moolenaar81ea1df2020-04-11 18:01:41 +0200106#ifdef SIZEOF_TIME_T
107# undef SIZEOF_TIME_T
108#endif
109
Philip H.411730e2025-05-11 15:01:31 +0200110#pragma GCC diagnostic push
111#pragma GCC diagnostic ignored "-Wunused-parameter"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112#include <ruby.h>
Philip H.411730e2025-05-11 15:01:31 +0200113#pragma GCC diagnostic pop
K.Takata236ccbf2022-09-22 16:12:06 +0100114#include <ruby/encoding.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000115
Bram Moolenaar92c098d2020-05-26 20:09:11 +0200116// See above.
117#ifdef SIZEOF_TIME_T
118# undef SIZEOF_TIME_T
119#endif
120
Bram Moolenaar8dc4c722019-04-14 19:42:13 +0200121#undef off_t // ruby defines off_t as _int64, Mingw uses long
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122#undef EXTERN
123#undef _
124
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100125// T_DATA defined both by Ruby and Mac header files, hack around it...
Bram Moolenaard0573012017-10-28 21:11:06 +0200126#if defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000127# define __OPENTRANSPORT__
128# define __OPENTRANSPORTPROTOCOL__
129# define __OPENTRANSPORTPROVIDERS__
130#endif
131
Bram Moolenaar165641d2010-02-17 16:23:09 +0100132/*
Bram Moolenaar0d27f642015-12-28 22:05:28 +0100133 * The TypedData_XXX macro family can be used since Ruby 1.9.2 but
134 * rb_data_type_t changed in 1.9.3, therefore require at least 2.0.
135 * The old Data_XXX macro family was deprecated on Ruby 2.2.
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100136 * Use TypedData_XXX if available.
137 */
Bram Moolenaar41a41412020-01-07 21:32:19 +0100138#if defined(TypedData_Wrap_Struct) && (RUBY_VERSION >= 20)
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100139# define USE_TYPEDDATA 1
140#endif
141
142/*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +0200143 * Backward compatibility for Ruby 1.8 and earlier.
Bram Moolenaar165641d2010-02-17 16:23:09 +0100144 * Ruby 1.9 does not provide STR2CSTR, instead StringValuePtr is provided.
145 * Ruby 1.9 does not provide RXXX(s)->len and RXXX(s)->ptr, instead
146 * RXXX_LEN(s) and RXXX_PTR(s) are provided.
147 */
148#ifndef StringValuePtr
149# define StringValuePtr(s) STR2CSTR(s)
150#endif
151#ifndef RARRAY_LEN
152# define RARRAY_LEN(s) RARRAY(s)->len
153#endif
154#ifndef RARRAY_PTR
155# define RARRAY_PTR(s) RARRAY(s)->ptr
156#endif
157#ifndef RSTRING_LEN
158# define RSTRING_LEN(s) RSTRING(s)->len
159#endif
160#ifndef RSTRING_PTR
161# define RSTRING_PTR(s) RSTRING(s)->ptr
162#endif
163
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100164#ifdef HAVE_DUP
165# undef HAVE_DUP
166#endif
167
ichizok8bb3fe42021-12-28 15:51:45 +0000168// Avoid redefining TRUE/FALSE in vterm.h.
169#ifdef TRUE
170# undef TRUE
171#endif
172#ifdef FALSE
173# undef FALSE
174#endif
175
Bram Moolenaar071d4272004-06-13 20:20:40 +0000176#include "vim.h"
177#include "version.h"
178
Bram Moolenaar7dca2eb2019-02-18 20:42:50 +0100179#ifdef DYNAMIC_RUBY
Ken Takatac97b3fe2023-10-11 21:27:06 +0200180# ifdef MSWIN // must come after including vim.h, where it is defined
181# define RUBY_PROC FARPROC
182# define load_dll vimLoadLib
183# define symbol_from_dll GetProcAddress
184# define close_dll FreeLibrary
185# define load_dll_error GetWin32Error
186# else
Bram Moolenaar7dca2eb2019-02-18 20:42:50 +0100187# include <dlfcn.h>
188# define HINSTANCE void*
189# define RUBY_PROC void*
190# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
191# define symbol_from_dll dlsym
192# define close_dll dlclose
Martin Tournoij1a3e5742021-07-24 13:57:29 +0200193# define load_dll_error dlerror
Bram Moolenaar7dca2eb2019-02-18 20:42:50 +0100194# endif
195#endif
196
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197#if defined(PROTO) && !defined(FEAT_RUBY)
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100198// Define these to be able to generate the function prototypes.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199# define VALUE int
200# define RUBY_DATA_FUNC int
201#endif
202
203static int ruby_initialized = 0;
Bram Moolenaar99685e62013-05-11 13:56:18 +0200204static void *ruby_stack_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205static VALUE objtbl;
206
207static VALUE mVIM;
208static VALUE cBuffer;
209static VALUE cVimWindow;
210static VALUE eDeletedBufferError;
211static VALUE eDeletedWindowError;
212
213static int ensure_ruby_initialized(void);
214static void error_print(int);
215static void ruby_io_init(void);
216static void ruby_vim_init(void);
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100217static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218
K.Takata236ccbf2022-09-22 16:12:06 +0100219#if defined(__ia64) && !defined(ruby_init_stack)
220# define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221#endif
222
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200223#if defined(DYNAMIC_RUBY) || defined(PROTO)
Bram Moolenaaref269542016-01-19 13:22:12 +0100224# if defined(PROTO) && !defined(HINSTANCE)
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100225# define HINSTANCE int // for generating prototypes
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200226# endif
227
Bram Moolenaar071d4272004-06-13 20:20:40 +0000228/*
229 * Wrapper defines
230 */
Bram Moolenaar8b430b42020-02-22 15:01:00 +0100231// Ruby 2.7 actually expands the following symbols as macro.
232# if RUBY_VERSION >= 27
233# undef rb_define_global_function
234# undef rb_define_method
235# undef rb_define_module_function
236# undef rb_define_singleton_method
237# endif
238
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200239# define rb_assoc_new dll_rb_assoc_new
240# define rb_cObject (*dll_rb_cObject)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100241# define rb_class_new_instance dll_rb_class_new_instance
Bram Moolenaardace9f72020-12-28 15:07:45 +0100242# if RUBY_VERSION < 30
243# define rb_check_type dll_rb_check_type
244# endif
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100245# ifdef USE_TYPEDDATA
246# define rb_check_typeddata dll_rb_check_typeddata
Bram Moolenaar0c7485f2015-01-14 14:04:10 +0100247# endif
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200248# define rb_class_path dll_rb_class_path
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100249# ifdef USE_TYPEDDATA
Bram Moolenaar41a41412020-01-07 21:32:19 +0100250# if RUBY_VERSION >= 23
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100251# define rb_data_typed_object_wrap dll_rb_data_typed_object_wrap
252# else
253# define rb_data_typed_object_alloc dll_rb_data_typed_object_alloc
254# endif
255# else
256# define rb_data_object_alloc dll_rb_data_object_alloc
257# endif
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200258# define rb_define_class_under dll_rb_define_class_under
259# define rb_define_const dll_rb_define_const
260# define rb_define_global_function dll_rb_define_global_function
261# define rb_define_method dll_rb_define_method
262# define rb_define_module dll_rb_define_module
263# define rb_define_module_function dll_rb_define_module_function
264# define rb_define_singleton_method dll_rb_define_singleton_method
265# define rb_define_virtual_variable dll_rb_define_virtual_variable
266# define rb_stdout (*dll_rb_stdout)
Bram Moolenaarb6c8cd82018-07-24 05:41:30 +0200267# define rb_stderr (*dll_rb_stderr)
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200268# define rb_eArgError (*dll_rb_eArgError)
269# define rb_eIndexError (*dll_rb_eIndexError)
270# define rb_eRuntimeError (*dll_rb_eRuntimeError)
271# define rb_eStandardError (*dll_rb_eStandardError)
272# define rb_eval_string_protect dll_rb_eval_string_protect
Bram Moolenaar41a41412020-01-07 21:32:19 +0100273# if RUBY_VERSION >= 21
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200274# define rb_funcallv dll_rb_funcallv
275# else
276# define rb_funcall2 dll_rb_funcall2
277# endif
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200278# define rb_global_variable dll_rb_global_variable
279# define rb_hash_aset dll_rb_hash_aset
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100280# define rb_hash_foreach dll_rb_hash_foreach
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200281# define rb_hash_new dll_rb_hash_new
282# define rb_inspect dll_rb_inspect
283# define rb_int2inum dll_rb_int2inum
Bram Moolenaar218beb32018-08-04 17:24:44 +0200284
285// ruby.h may redefine rb_intern to use RUBY_CONST_ID_CACHE(), but that won't
286// work. Not using the cache appears to be the best solution.
287# undef rb_intern
288# define rb_intern dll_rb_intern
289
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100290# if VIM_SIZEOF_INT < VIM_SIZEOF_LONG // 64 bits only
Bram Moolenaardace9f72020-12-28 15:07:45 +0100291# if RUBY_VERSION < 30
292# define rb_num2uint dll_rb_num2uint
293# endif
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200294# endif
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100295# define rb_num2dbl dll_rb_num2dbl
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200296# define rb_lastline_get dll_rb_lastline_get
297# define rb_lastline_set dll_rb_lastline_set
Bram Moolenaard0573012017-10-28 21:11:06 +0200298# define rb_protect dll_rb_protect
299# define rb_load dll_rb_load
K.Takata236ccbf2022-09-22 16:12:06 +0100300# if RUBY_VERSION < 20
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200301# define rb_num2ulong dll_rb_num2ulong
302# endif
303# define rb_obj_alloc dll_rb_obj_alloc
304# define rb_obj_as_string dll_rb_obj_as_string
305# define rb_obj_id dll_rb_obj_id
306# define rb_raise dll_rb_raise
307# define rb_str_cat dll_rb_str_cat
308# define rb_str_concat dll_rb_str_concat
Bram Moolenaar6aa2cd42016-02-16 15:06:59 +0100309# undef rb_str_new
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200310# define rb_str_new dll_rb_str_new
311# ifdef rb_str_new2
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100312// Ruby may #define rb_str_new2 to use rb_str_new_cstr.
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200313# define need_rb_str_new_cstr 1
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100314// Ruby's headers #define rb_str_new_cstr to make use of GCC's
315// __builtin_constant_p extension.
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200316# undef rb_str_new_cstr
317# define rb_str_new_cstr dll_rb_str_new_cstr
Bram Moolenaar76a86062013-05-11 17:45:48 +0200318# else
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200319# define rb_str_new2 dll_rb_str_new2
Bram Moolenaar76a86062013-05-11 17:45:48 +0200320# endif
K.Takata236ccbf2022-09-22 16:12:06 +0100321# define rb_string_value dll_rb_string_value
322# define rb_string_value_ptr dll_rb_string_value_ptr
323# define rb_float_new dll_rb_float_new
324# define rb_ary_new dll_rb_ary_new
325# ifdef rb_ary_new4
326# define RB_ARY_NEW4_MACRO 1
327# undef rb_ary_new4
Bram Moolenaar3ca71f12010-10-27 16:49:47 +0200328# endif
K.Takata236ccbf2022-09-22 16:12:06 +0100329# define rb_ary_new4 dll_rb_ary_new4
330# define rb_ary_push dll_rb_ary_push
331# ifdef __ia64
332# define rb_ia64_bsp dll_rb_ia64_bsp
333# undef ruby_init_stack
334# define ruby_init_stack(addr) dll_ruby_init_stack((addr), rb_ia64_bsp())
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200335# else
K.Takata236ccbf2022-09-22 16:12:06 +0100336# define ruby_init_stack dll_ruby_init_stack
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200337# endif
K.Takata236ccbf2022-09-22 16:12:06 +0100338# define rb_errinfo dll_rb_errinfo
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200339# define ruby_init dll_ruby_init
340# define ruby_init_loadpath dll_ruby_init_loadpath
Bram Moolenaar4f974752019-02-17 17:44:42 +0100341# ifdef MSWIN
K.Takata236ccbf2022-09-22 16:12:06 +0100342# define ruby_sysinit dll_ruby_sysinit
343# define rb_w32_snprintf dll_rb_w32_snprintf
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200344# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000345
K.Takata236ccbf2022-09-22 16:12:06 +0100346# define ruby_script dll_ruby_script
347# define rb_enc_find_index dll_rb_enc_find_index
348# define rb_enc_find dll_rb_enc_find
349# undef rb_enc_str_new
350# define rb_enc_str_new dll_rb_enc_str_new
351# define rb_sprintf dll_rb_sprintf
352# define rb_require dll_rb_require
353# define ruby_options dll_ruby_options
Bram Moolenaar165641d2010-02-17 16:23:09 +0100354
Bram Moolenaar071d4272004-06-13 20:20:40 +0000355/*
356 * Pointers for dynamic link
357 */
358static VALUE (*dll_rb_assoc_new) (VALUE, VALUE);
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200359VALUE *dll_rb_cFalseClass;
360VALUE *dll_rb_cFixnum;
Bram Moolenaar2016ae52016-06-13 20:08:43 +0200361# if defined(USE_RUBY_INTEGER)
Bram Moolenaar06469e92016-06-11 22:26:53 +0200362VALUE *dll_rb_cInteger;
363# endif
Bram Moolenaar41a41412020-01-07 21:32:19 +0100364# if RUBY_VERSION >= 20
Bram Moolenaardb3fbe52013-03-07 15:16:21 +0100365VALUE *dll_rb_cFloat;
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200366# endif
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200367VALUE *dll_rb_cNilClass;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368static VALUE *dll_rb_cObject;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100369VALUE *dll_rb_cString;
Bram Moolenaarba52cde2010-06-25 04:29:11 +0200370VALUE *dll_rb_cSymbol;
371VALUE *dll_rb_cTrueClass;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100372static VALUE (*dll_rb_class_new_instance) (int,VALUE*,VALUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000373static void (*dll_rb_check_type) (VALUE,int);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100374# ifdef USE_TYPEDDATA
375static void *(*dll_rb_check_typeddata) (VALUE,const rb_data_type_t *);
376# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377static VALUE (*dll_rb_class_path) (VALUE);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100378# ifdef USE_TYPEDDATA
Bram Moolenaar41a41412020-01-07 21:32:19 +0100379# if RUBY_VERSION >= 23
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100380static VALUE (*dll_rb_data_typed_object_wrap) (VALUE, void*, const rb_data_type_t *);
381# else
382static VALUE (*dll_rb_data_typed_object_alloc) (VALUE, void*, const rb_data_type_t *);
383# endif
384# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000385static VALUE (*dll_rb_data_object_alloc) (VALUE, void*, RUBY_DATA_FUNC, RUBY_DATA_FUNC);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100386# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000387# if RUBY_VERSION >= 31
388static void (*dll_rb_debug_rstring_null_ptr) (const char*);
389# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000390static VALUE (*dll_rb_define_class_under) (VALUE, const char*, VALUE);
391static void (*dll_rb_define_const) (VALUE,const char*,VALUE);
lilydjwg7292c0c2025-05-02 15:17:14 +0200392static void (*dll_rb_define_global_function) (const char*,VALUE(*)(int,VALUE*,VALUE),int);
393static void (*dll_rb_define_method) (VALUE,const char*,VALUE(*)(ANYARGS),int);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394static VALUE (*dll_rb_define_module) (const char*);
lilydjwg7292c0c2025-05-02 15:17:14 +0200395static void (*dll_rb_define_module_function) (VALUE,const char*,VALUE(*)(VALUE,VALUE),int);
396static void (*dll_rb_define_singleton_method) (VALUE,const char*,VALUE(*)(ANYARGS),int);
397static void (*dll_rb_define_virtual_variable) (const char*,VALUE(*)(ID,VALUE*),void(*)());
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398static VALUE *dll_rb_stdout;
Bram Moolenaarb6c8cd82018-07-24 05:41:30 +0200399static VALUE *dll_rb_stderr;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000400static VALUE *dll_rb_eArgError;
401static VALUE *dll_rb_eIndexError;
402static VALUE *dll_rb_eRuntimeError;
403static VALUE *dll_rb_eStandardError;
404static VALUE (*dll_rb_eval_string_protect) (const char*, int*);
Bram Moolenaar41a41412020-01-07 21:32:19 +0100405# if RUBY_VERSION >= 21
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200406static VALUE (*dll_rb_funcallv) (VALUE, ID, int, const VALUE*);
407# else
408static VALUE (*dll_rb_funcall2) (VALUE, ID, int, const VALUE*);
409# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410static void (*dll_rb_global_variable) (VALUE*);
411static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE);
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100412static VALUE (*dll_rb_hash_foreach) (VALUE, int (*)(VALUE, VALUE, VALUE), VALUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413static VALUE (*dll_rb_hash_new) (void);
414static VALUE (*dll_rb_inspect) (VALUE);
415static VALUE (*dll_rb_int2inum) (long);
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200416static ID (*dll_rb_intern) (const char*);
Bram Moolenaar9d20daf2021-02-01 19:31:47 +0100417# if RUBY_VERSION >= 30 || VIM_SIZEOF_INT < VIM_SIZEOF_LONG
Bram Moolenaar2623b4f2012-09-18 16:36:32 +0200418static long (*dll_rb_fix2int) (VALUE);
419static long (*dll_rb_num2int) (VALUE);
420static unsigned long (*dll_rb_num2uint) (VALUE);
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200421# endif
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100422static double (*dll_rb_num2dbl) (VALUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000423static VALUE (*dll_rb_lastline_get) (void);
424static void (*dll_rb_lastline_set) (VALUE);
Bram Moolenaar37badc82018-01-31 20:15:30 +0100425static VALUE (*dll_rb_protect) (VALUE (*)(VALUE), VALUE, int*);
Bram Moolenaard0573012017-10-28 21:11:06 +0200426static void (*dll_rb_load) (VALUE, int);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000427static long (*dll_rb_num2long) (VALUE);
428static unsigned long (*dll_rb_num2ulong) (VALUE);
429static VALUE (*dll_rb_obj_alloc) (VALUE);
430static VALUE (*dll_rb_obj_as_string) (VALUE);
431static VALUE (*dll_rb_obj_id) (VALUE);
432static void (*dll_rb_raise) (VALUE, const char*, ...);
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +0200433static VALUE (*dll_rb_string_value) (volatile VALUE*);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000434static VALUE (*dll_rb_str_cat) (VALUE, const char*, long);
435static VALUE (*dll_rb_str_concat) (VALUE, VALUE);
436static VALUE (*dll_rb_str_new) (const char*, long);
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200437# ifdef need_rb_str_new_cstr
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100438// Ruby may #define rb_str_new2 to use rb_str_new_cstr.
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200439static VALUE (*dll_rb_str_new_cstr) (const char*);
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200440# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441static VALUE (*dll_rb_str_new2) (const char*);
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200442# endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100443static VALUE (*dll_rb_errinfo) (void);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000444static void (*dll_ruby_init) (void);
445static void (*dll_ruby_init_loadpath) (void);
Bram Moolenaar4f974752019-02-17 17:44:42 +0100446# ifdef MSWIN
Bram Moolenaar4f391792017-01-15 16:59:07 +0100447static void (*dll_ruby_sysinit) (int*, char***);
Bram Moolenaar3ca71f12010-10-27 16:49:47 +0200448static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...);
449# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000450# if RUBY_VERSION >= 31
ichizoke1240652022-01-07 20:01:07 +0000451# ifdef _MSC_VER
452static void (*dll_rb_unexpected_type) (VALUE, int);
453# else
454NORETURN(static void (*dll_rb_unexpected_type) (VALUE, int));
455# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000456# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100457static char * (*dll_rb_string_value_ptr) (volatile VALUE*);
458static VALUE (*dll_rb_float_new) (double);
459static VALUE (*dll_rb_ary_new) (void);
Bram Moolenaar51e9fbf2018-08-11 14:24:11 +0200460static VALUE (*dll_rb_ary_new4) (long n, const VALUE *elts);
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100461static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
Isao Sato443657b2024-01-03 19:31:05 +0100462# if RUBY_VERSION >= 26 && RUBY_VERSION <= 32
Bram Moolenaarb09c6842018-12-27 22:11:01 +0100463static void (*dll_rb_ary_detransient) (VALUE);
K.Takata236ccbf2022-09-22 16:12:06 +0100464# endif
465# ifdef __ia64
Bram Moolenaar76a86062013-05-11 17:45:48 +0200466static void * (*dll_rb_ia64_bsp) (void);
467static void (*dll_ruby_init_stack)(VALUE*, void*);
K.Takata236ccbf2022-09-22 16:12:06 +0100468# else
Bram Moolenaar76a86062013-05-11 17:45:48 +0200469static void (*dll_ruby_init_stack)(VALUE*);
470# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100471static VALUE (*dll_rb_int2big)(SIGNED_VALUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000472
Bram Moolenaar165641d2010-02-17 16:23:09 +0100473static void (*dll_ruby_script) (const char*);
474static int (*dll_rb_enc_find_index) (const char*);
475static rb_encoding* (*dll_rb_enc_find) (const char*);
476static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*);
477static VALUE (*dll_rb_sprintf) (const char*, ...);
Bram Moolenaar7a8ef142010-12-24 13:39:35 +0100478static VALUE (*dll_rb_require) (const char*);
Bram Moolenaardace9f72020-12-28 15:07:45 +0100479static void* (*dll_ruby_options)(int, char**);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100480
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100481# if defined(USE_RGENGC) && USE_RGENGC
Bram Moolenaar41a41412020-01-07 21:32:19 +0100482# if RUBY_VERSION == 21
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100483static void (*dll_rb_gc_writebarrier_unprotect_promoted)(VALUE);
Bram Moolenaar0c7485f2015-01-14 14:04:10 +0100484# else
485static void (*dll_rb_gc_writebarrier_unprotect)(VALUE obj);
486# endif
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100487# endif
488
Bram Moolenaardace9f72020-12-28 15:07:45 +0100489# if RUBY_VERSION >= 30
Bram Moolenaar9d20daf2021-02-01 19:31:47 +0100490# ifdef _MSC_VER
491static void (*dll_ruby_malloc_size_overflow)(size_t, size_t);
492# else
Bram Moolenaardace9f72020-12-28 15:07:45 +0100493NORETURN(static void (*dll_ruby_malloc_size_overflow)(size_t, size_t));
Bram Moolenaar9d20daf2021-02-01 19:31:47 +0100494# endif
Bram Moolenaardace9f72020-12-28 15:07:45 +0100495# endif
496
Isao Sato443657b2024-01-03 19:31:05 +0100497# if RUBY_VERSION >= 26 && RUBY_VERSION <= 32
Bram Moolenaar0e121402020-12-10 20:50:34 +0100498void rb_ary_detransient_stub(VALUE x);
499# endif
500
Bram Moolenaardace9f72020-12-28 15:07:45 +0100501// Do not generate a prototype here, VALUE isn't always defined.
502# ifndef PROTO
K.Takata236ccbf2022-09-22 16:12:06 +0100503# if RUBY_VERSION >= 22
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100504 long
505rb_num2long_stub(VALUE x)
K.Takata236ccbf2022-09-22 16:12:06 +0100506# else
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100507 SIGNED_VALUE
508rb_num2long_stub(VALUE x)
K.Takata236ccbf2022-09-22 16:12:06 +0100509# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100510{
511 return dll_rb_num2long(x);
512}
K.Takata236ccbf2022-09-22 16:12:06 +0100513# if RUBY_VERSION >= 26
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100514 VALUE
515rb_int2big_stub(intptr_t x)
K.Takata236ccbf2022-09-22 16:12:06 +0100516# else
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100517 VALUE
518rb_int2big_stub(SIGNED_VALUE x)
K.Takata236ccbf2022-09-22 16:12:06 +0100519# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100520{
521 return dll_rb_int2big(x);
522}
K.Takata236ccbf2022-09-22 16:12:06 +0100523# if RUBY_VERSION >= 30 || VIM_SIZEOF_INT < VIM_SIZEOF_LONG
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100524 long
525rb_fix2int_stub(VALUE x)
Bram Moolenaar0bcdd6e2013-04-14 16:19:03 +0200526{
527 return dll_rb_fix2int(x);
528}
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100529 long
530rb_num2int_stub(VALUE x)
Bram Moolenaar0bcdd6e2013-04-14 16:19:03 +0200531{
532 return dll_rb_num2int(x);
533}
K.Takata236ccbf2022-09-22 16:12:06 +0100534# endif
535# if RUBY_VERSION >= 20
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100536 VALUE
Bram Moolenaar886ed692013-02-26 13:41:35 +0100537rb_float_new_in_heap(double d)
538{
539 return dll_rb_float_new(d);
540}
K.Takata236ccbf2022-09-22 16:12:06 +0100541# if RUBY_VERSION >= 22
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100542 unsigned long
543rb_num2ulong(VALUE x)
K.Takata236ccbf2022-09-22 16:12:06 +0100544# else
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100545 VALUE
546rb_num2ulong(VALUE x)
K.Takata236ccbf2022-09-22 16:12:06 +0100547# endif
Bram Moolenaar886ed692013-02-26 13:41:35 +0100548{
549 return (long)RSHIFT((SIGNED_VALUE)(x),1);
550}
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200551# endif
Bram Moolenaardace9f72020-12-28 15:07:45 +0100552# if defined(USE_RGENGC) && USE_RGENGC
553# if RUBY_VERSION == 21
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100554 void
555rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj)
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100556{
Bram Moolenaar90140742014-11-27 17:44:08 +0100557 dll_rb_gc_writebarrier_unprotect_promoted(obj);
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100558}
Bram Moolenaardace9f72020-12-28 15:07:45 +0100559# else
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100560 void
561rb_gc_writebarrier_unprotect_stub(VALUE obj)
Bram Moolenaar0c7485f2015-01-14 14:04:10 +0100562{
563 dll_rb_gc_writebarrier_unprotect(obj);
564}
Bram Moolenaardace9f72020-12-28 15:07:45 +0100565# endif
Bram Moolenaar0c7485f2015-01-14 14:04:10 +0100566# endif
Isao Sato443657b2024-01-03 19:31:05 +0100567# if RUBY_VERSION >= 26 && RUBY_VERSION <= 32
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100568 void
569rb_ary_detransient_stub(VALUE x)
Bram Moolenaarf62fc312019-01-08 20:29:32 +0100570{
571 dll_rb_ary_detransient(x);
572}
Bram Moolenaardace9f72020-12-28 15:07:45 +0100573# endif
574# if RUBY_VERSION >= 30
575 void
576rb_check_type_stub(VALUE obj, int t)
577{
578 dll_rb_check_type(obj, t);
579}
580 unsigned long
581rb_num2uint_stub(VALUE x)
582{
583 return dll_rb_num2uint(x);
584}
585 void
586ruby_malloc_size_overflow_stub(size_t x, size_t y)
587{
588 dll_ruby_malloc_size_overflow(x, y);
589}
590# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000591# if RUBY_VERSION >= 31
592 void
593rb_debug_rstring_null_ptr_stub(const char *func)
594{
595 dll_rb_debug_rstring_null_ptr(func);
596}
597 void
598rb_unexpected_type_stub(VALUE self, int t)
599{
600 dll_rb_unexpected_type(self, t);
601}
602# endif
Bram Moolenaardace9f72020-12-28 15:07:45 +0100603# endif // ifndef PROTO
Bram Moolenaarf62fc312019-01-08 20:29:32 +0100604
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100605static HINSTANCE hinstRuby = NULL; // Instance of ruby.dll
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606
607/*
Bram Moolenaarda2303d2005-08-30 21:55:26 +0000608 * Table of name to function pointer of ruby.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000610static struct
611{
612 char *name;
613 RUBY_PROC *ptr;
614} ruby_funcname_table[] =
615{
616 {"rb_assoc_new", (RUBY_PROC*)&dll_rb_assoc_new},
617 {"rb_cFalseClass", (RUBY_PROC*)&dll_rb_cFalseClass},
Bram Moolenaar2016ae52016-06-13 20:08:43 +0200618# if defined(USE_RUBY_INTEGER)
Bram Moolenaar06469e92016-06-11 22:26:53 +0200619 {"rb_cInteger", (RUBY_PROC*)&dll_rb_cInteger},
Bram Moolenaar6abda992017-01-09 21:10:31 +0100620# else
621 {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum},
Bram Moolenaar06469e92016-06-11 22:26:53 +0200622# endif
Bram Moolenaar41a41412020-01-07 21:32:19 +0100623# if RUBY_VERSION >= 20
Bram Moolenaardb3fbe52013-03-07 15:16:21 +0100624 {"rb_cFloat", (RUBY_PROC*)&dll_rb_cFloat},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200625# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass},
627 {"rb_cObject", (RUBY_PROC*)&dll_rb_cObject},
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100628 {"rb_cString", (RUBY_PROC*)&dll_rb_cString},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000629 {"rb_cSymbol", (RUBY_PROC*)&dll_rb_cSymbol},
630 {"rb_cTrueClass", (RUBY_PROC*)&dll_rb_cTrueClass},
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100631 {"rb_class_new_instance", (RUBY_PROC*)&dll_rb_class_new_instance},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000632 {"rb_check_type", (RUBY_PROC*)&dll_rb_check_type},
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100633# ifdef USE_TYPEDDATA
634 {"rb_check_typeddata", (RUBY_PROC*)&dll_rb_check_typeddata},
635# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path},
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100637# ifdef USE_TYPEDDATA
Bram Moolenaar41a41412020-01-07 21:32:19 +0100638# if RUBY_VERSION >= 23
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100639 {"rb_data_typed_object_wrap", (RUBY_PROC*)&dll_rb_data_typed_object_wrap},
640# else
641 {"rb_data_typed_object_alloc", (RUBY_PROC*)&dll_rb_data_typed_object_alloc},
642# endif
643# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000644 {"rb_data_object_alloc", (RUBY_PROC*)&dll_rb_data_object_alloc},
Bram Moolenaarf2f6d292015-12-28 20:57:10 +0100645# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000646# if RUBY_VERSION >= 31
647 {"rb_debug_rstring_null_ptr", (RUBY_PROC*)&dll_rb_debug_rstring_null_ptr},
648# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649 {"rb_define_class_under", (RUBY_PROC*)&dll_rb_define_class_under},
650 {"rb_define_const", (RUBY_PROC*)&dll_rb_define_const},
651 {"rb_define_global_function", (RUBY_PROC*)&dll_rb_define_global_function},
652 {"rb_define_method", (RUBY_PROC*)&dll_rb_define_method},
653 {"rb_define_module", (RUBY_PROC*)&dll_rb_define_module},
654 {"rb_define_module_function", (RUBY_PROC*)&dll_rb_define_module_function},
655 {"rb_define_singleton_method", (RUBY_PROC*)&dll_rb_define_singleton_method},
656 {"rb_define_virtual_variable", (RUBY_PROC*)&dll_rb_define_virtual_variable},
657 {"rb_stdout", (RUBY_PROC*)&dll_rb_stdout},
Bram Moolenaarb6c8cd82018-07-24 05:41:30 +0200658 {"rb_stderr", (RUBY_PROC*)&dll_rb_stderr},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 {"rb_eArgError", (RUBY_PROC*)&dll_rb_eArgError},
660 {"rb_eIndexError", (RUBY_PROC*)&dll_rb_eIndexError},
661 {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError},
662 {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError},
663 {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect},
Bram Moolenaar41a41412020-01-07 21:32:19 +0100664# if RUBY_VERSION >= 21
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200665 {"rb_funcallv", (RUBY_PROC*)&dll_rb_funcallv},
666# else
667 {"rb_funcall2", (RUBY_PROC*)&dll_rb_funcall2},
668# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000669 {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable},
670 {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset},
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100671 {"rb_hash_foreach", (RUBY_PROC*)&dll_rb_hash_foreach},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new},
673 {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect},
674 {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum},
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200675 {"rb_intern", (RUBY_PROC*)&dll_rb_intern},
Bram Moolenaar9d20daf2021-02-01 19:31:47 +0100676# if RUBY_VERSION >= 30 || VIM_SIZEOF_INT < VIM_SIZEOF_LONG
Bram Moolenaar2623b4f2012-09-18 16:36:32 +0200677 {"rb_fix2int", (RUBY_PROC*)&dll_rb_fix2int},
678 {"rb_num2int", (RUBY_PROC*)&dll_rb_num2int},
679 {"rb_num2uint", (RUBY_PROC*)&dll_rb_num2uint},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200680# endif
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100681 {"rb_num2dbl", (RUBY_PROC*)&dll_rb_num2dbl},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get},
683 {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set},
Bram Moolenaard0573012017-10-28 21:11:06 +0200684 {"rb_protect", (RUBY_PROC*)&dll_rb_protect},
685 {"rb_load", (RUBY_PROC*)&dll_rb_load},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 {"rb_num2long", (RUBY_PROC*)&dll_rb_num2long},
687 {"rb_num2ulong", (RUBY_PROC*)&dll_rb_num2ulong},
688 {"rb_obj_alloc", (RUBY_PROC*)&dll_rb_obj_alloc},
689 {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string},
690 {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id},
691 {"rb_raise", (RUBY_PROC*)&dll_rb_raise},
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +0200692 {"rb_string_value", (RUBY_PROC*)&dll_rb_string_value},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000693 {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat},
694 {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat},
695 {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200696# ifdef need_rb_str_new_cstr
Bram Moolenaar1d2beae2010-05-22 21:56:55 +0200697 {"rb_str_new_cstr", (RUBY_PROC*)&dll_rb_str_new_cstr},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200698# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000699 {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200700# endif
Bram Moolenaar165641d2010-02-17 16:23:09 +0100701 {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 {"ruby_init", (RUBY_PROC*)&dll_ruby_init},
703 {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath},
Bram Moolenaar4f974752019-02-17 17:44:42 +0100704# ifdef MSWIN
Bram Moolenaar4f391792017-01-15 16:59:07 +0100705 {"ruby_sysinit", (RUBY_PROC*)&dll_ruby_sysinit},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf},
Bram Moolenaar3ca71f12010-10-27 16:49:47 +0200707# endif
ichizok8bb3fe42021-12-28 15:51:45 +0000708# if RUBY_VERSION >= 31
709 {"rb_unexpected_type", (RUBY_PROC*)&dll_rb_unexpected_type},
710# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100711 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
K.Takata236ccbf2022-09-22 16:12:06 +0100712# if RUBY_VERSION >= 20
Bram Moolenaar886ed692013-02-26 13:41:35 +0100713 {"rb_float_new_in_heap", (RUBY_PROC*)&dll_rb_float_new},
K.Takata236ccbf2022-09-22 16:12:06 +0100714# else
715 {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
Bram Moolenaar3b9abb62013-05-12 14:11:17 +0200716# endif
K.Takata236ccbf2022-09-22 16:12:06 +0100717 {"rb_ary_new", (RUBY_PROC*)&dll_rb_ary_new},
718# ifdef RB_ARY_NEW4_MACRO
719 {"rb_ary_new_from_values", (RUBY_PROC*)&dll_rb_ary_new4},
720# else
721 {"rb_ary_new4", (RUBY_PROC*)&dll_rb_ary_new4},
722# endif
723 {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push},
Isao Sato443657b2024-01-03 19:31:05 +0100724# if RUBY_VERSION >= 26 && RUBY_VERSION <= 32
K.Takata236ccbf2022-09-22 16:12:06 +0100725 {"rb_ary_detransient", (RUBY_PROC*)&dll_rb_ary_detransient},
726# endif
Bram Moolenaar42d57f02010-03-10 12:47:00 +0100727 {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big},
Bram Moolenaar165641d2010-02-17 16:23:09 +0100728 {"ruby_script", (RUBY_PROC*)&dll_ruby_script},
729 {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index},
730 {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find},
731 {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new},
732 {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf},
Bram Moolenaar7a8ef142010-12-24 13:39:35 +0100733 {"rb_require", (RUBY_PROC*)&dll_rb_require},
Bram Moolenaar9b1067e2015-11-19 19:33:15 +0100734 {"ruby_options", (RUBY_PROC*)&dll_ruby_options},
K.Takata236ccbf2022-09-22 16:12:06 +0100735# ifdef __ia64
Bram Moolenaar10f3a792013-05-20 12:52:29 +0200736 {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp},
Bram Moolenaar10f3a792013-05-20 12:52:29 +0200737# endif
K.Takata236ccbf2022-09-22 16:12:06 +0100738 {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100739# if defined(USE_RGENGC) && USE_RGENGC
Bram Moolenaar41a41412020-01-07 21:32:19 +0100740# if RUBY_VERSION == 21
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100741 {"rb_gc_writebarrier_unprotect_promoted", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect_promoted},
Bram Moolenaar0c7485f2015-01-14 14:04:10 +0100742# else
743 {"rb_gc_writebarrier_unprotect", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect},
744# endif
Bram Moolenaara1a118b2014-02-05 22:41:15 +0100745# endif
Bram Moolenaardace9f72020-12-28 15:07:45 +0100746# if RUBY_VERSION >= 30
747 {"ruby_malloc_size_overflow", (RUBY_PROC*)&dll_ruby_malloc_size_overflow},
748# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749 {"", NULL},
750};
751
752/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753 * Load library and get all pointers.
754 * Parameter 'libname' provides name of DLL.
755 * Return OK or FAIL.
756 */
757 static int
758ruby_runtime_link_init(char *libname, int verbose)
759{
760 int i;
761
762 if (hinstRuby)
763 return OK;
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +0200764 hinstRuby = load_dll(libname);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765 if (!hinstRuby)
766 {
767 if (verbose)
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000768 semsg(_(e_could_not_load_library_str_str), libname, load_dll_error());
Bram Moolenaar071d4272004-06-13 20:20:40 +0000769 return FAIL;
770 }
771
772 for (i = 0; ruby_funcname_table[i].ptr; ++i)
773 {
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +0200774 if (!(*ruby_funcname_table[i].ptr = symbol_from_dll(hinstRuby,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775 ruby_funcname_table[i].name)))
776 {
Bram Moolenaarf9b5ef82010-09-29 13:02:53 +0200777 close_dll(hinstRuby);
Bram Moolenaar3ca71f12010-10-27 16:49:47 +0200778 hinstRuby = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 if (verbose)
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000780 semsg(_(e_could_not_load_library_function_str), ruby_funcname_table[i].name);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781 return FAIL;
782 }
783 }
784 return OK;
785}
786
787/*
788 * If ruby is enabled (there is installed ruby on Windows system) return TRUE,
789 * else FALSE.
790 */
791 int
Bram Moolenaar68c2f632016-01-30 17:24:07 +0100792ruby_enabled(int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793{
Bram Moolenaar25e4fcd2016-01-09 14:57:47 +0100794 return ruby_runtime_link_init((char *)p_rubydll, verbose) == OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000795}
Bram Moolenaar2ab2e862019-12-04 21:24:53 +0100796#endif // defined(DYNAMIC_RUBY) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797
798 void
Bram Moolenaar68c2f632016-01-30 17:24:07 +0100799ruby_end(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000801}
802
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100803 void
804ex_ruby(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805{
806 int state;
807 char *script = NULL;
808
Bram Moolenaar35a2e192006-03-13 22:07:11 +0000809 script = (char *)script_get(eap, eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 if (!eap->skip && ensure_ruby_initialized())
811 {
812 if (script == NULL)
813 rb_eval_string_protect((char *)eap->arg, &state);
814 else
815 rb_eval_string_protect(script, &state);
816 if (state)
817 error_print(state);
818 }
819 vim_free(script);
820}
821
Bram Moolenaar165641d2010-02-17 16:23:09 +0100822/*
823 * In Ruby 1.9 or later, ruby String object has encoding.
824 * conversion buffer string of vim to ruby String object using
825 * VIM encoding option.
826 */
827 static VALUE
828vim_str2rb_enc_str(const char *s)
829{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100830 long lval;
831 char_u *sval;
832 rb_encoding *enc;
833
Yegappan Lakshmanan64095532021-12-06 11:03:55 +0000834 if (get_option_value((char_u *)"enc", &lval, &sval, NULL, 0) == gov_string)
Bram Moolenaar165641d2010-02-17 16:23:09 +0100835 {
836 enc = rb_enc_find((char *)sval);
837 vim_free(sval);
Bram Moolenaar758535a2016-03-30 22:06:16 +0200838 if (enc)
Bram Moolenaar9b0ac222016-06-01 20:31:43 +0200839 return rb_enc_str_new(s, (long)strlen(s), enc);
Bram Moolenaar165641d2010-02-17 16:23:09 +0100840 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100841 return rb_str_new2(s);
842}
843
844 static VALUE
845eval_enc_string_protect(const char *str, int *state)
846{
Bram Moolenaar165641d2010-02-17 16:23:09 +0100847 long lval;
848 char_u *sval;
849 rb_encoding *enc;
850 VALUE v;
851
Yegappan Lakshmanan64095532021-12-06 11:03:55 +0000852 if (get_option_value((char_u *)"enc", &lval, &sval, NULL, 0) == gov_string)
Bram Moolenaar165641d2010-02-17 16:23:09 +0100853 {
854 enc = rb_enc_find((char *)sval);
855 vim_free(sval);
856 if (enc)
857 {
858 v = rb_sprintf("#-*- coding:%s -*-\n%s", rb_enc_name(enc), str);
859 return rb_eval_string_protect(StringValuePtr(v), state);
860 }
861 }
Bram Moolenaar165641d2010-02-17 16:23:09 +0100862 return rb_eval_string_protect(str, state);
863}
864
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100865 void
866ex_rubydo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867{
868 int state;
869 linenr_T i;
Bram Moolenaarc593fee2017-01-29 23:11:25 +0100870 buf_T *was_curbuf = curbuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000872 if (!ensure_ruby_initialized())
873 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000875 if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
876 return;
877 for (i = eap->line1; i <= eap->line2; i++)
878 {
879 VALUE line;
880
881 if (i > curbuf->b_ml.ml_line_count)
882 break;
883 line = vim_str2rb_enc_str((char *)ml_get(i));
884 rb_lastline_set(line);
885 eval_enc_string_protect((char *) eap->arg, &state);
886 if (state)
887 {
888 error_print(state);
889 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890 }
zeertzjqe99f0682024-01-29 19:32:39 +0100891 if (was_curbuf != curbuf || i > curbuf->b_ml.ml_line_count)
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000892 break;
893 line = rb_lastline_get();
894 if (!NIL_P(line))
895 {
896 if (TYPE(line) != T_STRING)
897 {
898 emsg(_(e_dollar_must_be_an_instance_of_string));
899 return;
900 }
901 ml_replace(i, (char_u *) StringValuePtr(line), 1);
902 changed();
903#ifdef SYNTAX_HL
904 syn_changed(i); // recompute syntax hl. for this line
905#endif
906 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000907 }
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000908 check_cursor();
909 update_curbuf(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000910}
911
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100912 static VALUE
913rb_load_wrap(VALUE file_to_load)
Bram Moolenaar37badc82018-01-31 20:15:30 +0100914{
915 rb_load(file_to_load, 0);
916 return Qnil;
917}
918
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100919 void
920ex_rubyfile(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921{
922 int state;
923
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000924 if (!ensure_ruby_initialized())
925 return;
926
927 VALUE file_to_load = rb_str_new2((const char *)eap->arg);
928 rb_protect(rb_load_wrap, file_to_load, &state);
929 if (state)
930 error_print(state);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931}
932
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100933 void
934ruby_buffer_free(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935{
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000936 if (buf->b_ruby_ref == NULL)
937 return;
938
939 rb_hash_aset(objtbl, rb_obj_id((VALUE) buf->b_ruby_ref), Qnil);
940 RDATA(buf->b_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941}
942
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100943 void
944ruby_window_free(win_T *win)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945{
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000946 if (win->w_ruby_ref == NULL)
947 return;
948
949 rb_hash_aset(objtbl, rb_obj_id((VALUE) win->w_ruby_ref), Qnil);
950 RDATA(win->w_ruby_ref)->data = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951}
952
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100953 static int
954ensure_ruby_initialized(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000955{
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000956 if (ruby_initialized)
957 return ruby_initialized;
958
959#ifdef DYNAMIC_RUBY
960 if (ruby_enabled(TRUE))
961#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000962 {
Bram Moolenaar4f974752019-02-17 17:44:42 +0100963#ifdef MSWIN
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000964 // suggested by Ariya Mizutani
965 int argc = 1;
966 char *argv[] = {"gvim.exe"};
967 char **argvp = argv;
968 ruby_sysinit(&argc, &argvp);
Bram Moolenaar0b69c732010-02-17 15:11:50 +0100969#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 {
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000971 ruby_init_stack(ruby_stack_start);
972 ruby_init();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 }
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000974 {
975 int dummy_argc = 2;
976 char *dummy_argv[] = {"vim-ruby", "-e_=0"};
977 ruby_options(dummy_argc, dummy_argv);
978 }
979 ruby_script("vim-ruby");
980 ruby_io_init();
981 ruby_vim_init();
982 ruby_initialized = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 }
Yegappan Lakshmanan0233bdf2023-01-12 12:33:30 +0000984#ifdef DYNAMIC_RUBY
985 else
986 {
987 emsg(_(e_sorry_this_command_is_disabled_the_ruby_library_could_not_be_loaded));
988 return 0;
989 }
990#endif
991
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992 return ruby_initialized;
993}
994
Bram Moolenaare99be0e2019-03-26 22:51:09 +0100995 static void
996error_print(int state)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997{
Bram Moolenaarf711cb22018-08-01 18:42:13 +0200998 VALUE error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 VALUE eclass;
1000 VALUE einfo;
Bram Moolenaarf711cb22018-08-01 18:42:13 +02001001 VALUE bt;
1002 int attr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 char buff[BUFSIZ];
Bram Moolenaarf711cb22018-08-01 18:42:13 +02001004 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001005
1006#define TAG_RETURN 0x1
1007#define TAG_BREAK 0x2
1008#define TAG_NEXT 0x3
1009#define TAG_RETRY 0x4
1010#define TAG_REDO 0x5
1011#define TAG_RAISE 0x6
1012#define TAG_THROW 0x7
1013#define TAG_FATAL 0x8
1014#define TAG_MASK 0xf
1015
Bram Moolenaar758535a2016-03-30 22:06:16 +02001016 switch (state)
1017 {
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001018 case TAG_RETURN:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001019 emsg(_(e_unexpected_return));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001020 break;
1021 case TAG_NEXT:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001022 emsg(_(e_unexpected_next));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001023 break;
1024 case TAG_BREAK:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001025 emsg(_(e_unexpected_break));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001026 break;
1027 case TAG_REDO:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001028 emsg(_(e_unexpected_redo));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001029 break;
1030 case TAG_RETRY:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001031 emsg(_(e_retry_outside_of_rescue_clause));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001032 break;
1033 case TAG_RAISE:
1034 case TAG_FATAL:
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001035 error = rb_errinfo();
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001036 eclass = CLASS_OF(error);
1037 einfo = rb_obj_as_string(error);
1038 if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0)
1039 {
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001040 emsg(_(e_unhandled_exception));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001041 }
1042 else
1043 {
1044 VALUE epath;
1045 char *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001046
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001047 epath = rb_class_path(eclass);
1048 vim_snprintf(buff, BUFSIZ, "%s: %s",
1049 RSTRING_PTR(epath), RSTRING_PTR(einfo));
1050 p = strchr(buff, '\n');
1051 if (p) *p = '\0';
1052 emsg(buff);
1053 }
Bram Moolenaarf711cb22018-08-01 18:42:13 +02001054
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001055 attr = syn_name2attr((char_u *)"Error");
Bram Moolenaar49c99fc2020-02-11 23:01:39 +01001056#if RUBY_VERSION >= 21
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001057 bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
1058 for (i = 0; i < RARRAY_LEN(bt); i++)
1059 msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
Bram Moolenaar49c99fc2020-02-11 23:01:39 +01001060#else
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001061 bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0);
1062 for (i = 0; i < RARRAY_LEN(bt); i++)
1063 msg_attr(RSTRING_PTR(RARRAY_PTR(bt)[i]), attr);
Bram Moolenaar49c99fc2020-02-11 23:01:39 +01001064#endif
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001065 break;
1066 default:
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00001067 vim_snprintf(buff, BUFSIZ, _(e_unknown_longjmp_status_nr), state);
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001068 emsg(buff);
1069 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070 }
1071}
1072
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001073 static VALUE
1074vim_message(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075{
1076 char *buff, *p;
1077
1078 str = rb_obj_as_string(str);
Bram Moolenaar3f5f7952011-08-04 19:34:59 +02001079 if (RSTRING_LEN(str) > 0)
1080 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001081 // Only do this when the string isn't empty, alloc(0) causes trouble.
Bram Moolenaar00ccf542017-09-03 15:17:48 +02001082 buff = ALLOCA_N(char, RSTRING_LEN(str) + 1);
Bram Moolenaar3f5f7952011-08-04 19:34:59 +02001083 strcpy(buff, RSTRING_PTR(str));
1084 p = strchr(buff, '\n');
1085 if (p) *p = '\0';
Bram Moolenaar32526b32019-01-19 17:43:09 +01001086 msg(buff);
Bram Moolenaar3f5f7952011-08-04 19:34:59 +02001087 }
1088 else
1089 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01001090 msg("");
Bram Moolenaar3f5f7952011-08-04 19:34:59 +02001091 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001092 return Qnil;
1093}
1094
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001095 static VALUE
1096vim_set_option(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097{
Bram Moolenaar165641d2010-02-17 16:23:09 +01001098 do_set((char_u *)StringValuePtr(str), 0);
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001099 update_screen(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100 return Qnil;
1101}
1102
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001103 static VALUE
1104vim_command(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001105{
Bram Moolenaar165641d2010-02-17 16:23:09 +01001106 do_cmdline_cmd((char_u *)StringValuePtr(str));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001107 return Qnil;
1108}
1109
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001110#ifdef FEAT_EVAL
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001111 static VALUE
1112vim_to_ruby(typval_T *tv)
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001113{
1114 VALUE result = Qnil;
1115
1116 if (tv->v_type == VAR_STRING)
1117 {
Bram Moolenaar94127e42010-03-19 23:08:48 +01001118 result = rb_str_new2(tv->vval.v_string == NULL
1119 ? "" : (char *)(tv->vval.v_string));
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001120 }
1121 else if (tv->v_type == VAR_NUMBER)
1122 {
Bram Moolenaar639a2552010-03-17 18:15:23 +01001123 result = INT2NUM(tv->vval.v_number);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001124 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001125 else if (tv->v_type == VAR_FLOAT)
1126 {
Bram Moolenaar639a2552010-03-17 18:15:23 +01001127 result = rb_float_new(tv->vval.v_float);
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001128 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001129 else if (tv->v_type == VAR_LIST)
1130 {
Bram Moolenaar639a2552010-03-17 18:15:23 +01001131 list_T *list = tv->vval.v_list;
1132 listitem_T *curr;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001133
Bram Moolenaar639a2552010-03-17 18:15:23 +01001134 result = rb_ary_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001135
Bram Moolenaar639a2552010-03-17 18:15:23 +01001136 if (list != NULL)
1137 {
Bram Moolenaaraeea7212020-04-02 18:50:46 +02001138 FOR_ALL_LIST_ITEMS(list, curr)
Bram Moolenaar639a2552010-03-17 18:15:23 +01001139 rb_ary_push(result, vim_to_ruby(&curr->li_tv));
Bram Moolenaar639a2552010-03-17 18:15:23 +01001140 }
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001141 }
1142 else if (tv->v_type == VAR_DICT)
1143 {
Bram Moolenaar639a2552010-03-17 18:15:23 +01001144 result = rb_hash_new();
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001145
Bram Moolenaar639a2552010-03-17 18:15:23 +01001146 if (tv->vval.v_dict != NULL)
1147 {
1148 hashtab_T *ht = &tv->vval.v_dict->dv_hashtab;
1149 long_u todo = ht->ht_used;
1150 hashitem_T *hi;
1151 dictitem_T *di;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001152
Yegappan Lakshmanan14113fd2023-03-07 17:13:51 +00001153 FOR_ALL_HASHTAB_ITEMS(ht, hi, todo)
Bram Moolenaar639a2552010-03-17 18:15:23 +01001154 {
1155 if (!HASHITEM_EMPTY(hi))
1156 {
1157 --todo;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001158
Bram Moolenaar639a2552010-03-17 18:15:23 +01001159 di = dict_lookup(hi);
1160 rb_hash_aset(result, rb_str_new2((char *)hi->hi_key),
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001161 vim_to_ruby(&di->di_tv));
Bram Moolenaar639a2552010-03-17 18:15:23 +01001162 }
1163 }
1164 }
Bram Moolenaar520e1e42016-01-23 19:46:28 +01001165 }
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001166 else if (tv->v_type == VAR_BOOL || tv->v_type == VAR_SPECIAL)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01001167 {
Bram Moolenaard84b26a2018-07-28 17:18:09 +02001168 if (tv->vval.v_number == VVAL_TRUE)
1169 result = Qtrue;
1170 else if (tv->vval.v_number == VVAL_FALSE)
1171 result = Qfalse;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01001172 }
1173 else if (tv->v_type == VAR_BLOB)
1174 {
1175 result = rb_str_new(tv->vval.v_blob->bv_ga.ga_data,
1176 tv->vval.v_blob->bv_ga.ga_len);
1177 }
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001178 // else return Qnil;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001179
1180 return result;
1181}
1182#endif
1183
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001184 static VALUE
1185vim_evaluate(VALUE self UNUSED, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001186{
1187#ifdef FEAT_EVAL
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001188 typval_T *tv;
1189 VALUE result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001190
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001191 tv = eval_expr((char_u *)StringValuePtr(str), NULL);
1192 if (tv == NULL)
Bram Moolenaar639a2552010-03-17 18:15:23 +01001193 return Qnil;
Bram Moolenaar3fac56e2010-02-24 15:48:04 +01001194 result = vim_to_ruby(tv);
1195
1196 free_tv(tv);
1197
1198 return result;
1199#else
1200 return Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001201#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202}
1203
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001204#ifdef USE_TYPEDDATA
1205static size_t buffer_dsize(const void *buf);
1206
1207static const rb_data_type_t buffer_type = {
1208 "vim_buffer",
Bram Moolenaar41a41412020-01-07 21:32:19 +01001209 {0, 0, buffer_dsize,
1210# if RUBY_VERSION >= 27
Bram Moolenaar8b430b42020-02-22 15:01:00 +01001211 0, {0}
Bram Moolenaar41a41412020-01-07 21:32:19 +01001212# else
1213 {0, 0}
1214# endif
1215 },
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001216 0, 0,
1217# ifdef RUBY_TYPED_FREE_IMMEDIATELY
1218 0,
1219# endif
1220};
1221
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001222 static size_t
1223buffer_dsize(const void *buf UNUSED)
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001224{
1225 return sizeof(buf_T);
1226}
1227#endif
1228
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001229 static VALUE
1230buffer_new(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001231{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001232 if (buf->b_ruby_ref)
1233 {
1234 return (VALUE) buf->b_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001235 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001236 else
1237 {
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001238#ifdef USE_TYPEDDATA
1239 VALUE obj = TypedData_Wrap_Struct(cBuffer, &buffer_type, buf);
1240#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241 VALUE obj = Data_Wrap_Struct(cBuffer, 0, 0, buf);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001242#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00001243 buf->b_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1245 return obj;
1246 }
1247}
1248
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001249 static buf_T *
1250get_buf(VALUE obj)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251{
1252 buf_T *buf;
1253
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001254#ifdef USE_TYPEDDATA
1255 TypedData_Get_Struct(obj, buf_T, &buffer_type, buf);
1256#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001257 Data_Get_Struct(obj, buf_T, buf);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001258#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 if (buf == NULL)
1260 rb_raise(eDeletedBufferError, "attempt to refer to deleted buffer");
1261 return buf;
1262}
1263
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001264 static VALUE
1265vim_blob(VALUE self UNUSED, VALUE str)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01001266{
1267 VALUE result = rb_str_new("0z", 2);
1268 char buf[4];
1269 int i;
1270 for (i = 0; i < RSTRING_LEN(str); i++)
1271 {
Bram Moolenaar0d13cce2019-02-23 14:23:03 +01001272 sprintf(buf, "%02X", (unsigned char)(RSTRING_PTR(str)[i]));
Bram Moolenaarb191be22019-01-30 21:00:12 +01001273 rb_str_concat(result, rb_str_new2(buf));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01001274 }
1275 return result;
1276}
1277
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001278 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001279buffer_s_current(VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280{
1281 return buffer_new(curbuf);
1282}
1283
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001284 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001285buffer_s_current_getter(ID id UNUSED, VALUE *x UNUSED)
1286{
1287 return buffer_new(curbuf);
1288}
1289
1290 static VALUE
1291buffer_s_count(VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001292{
1293 buf_T *b;
1294 int n = 0;
1295
Bram Moolenaar29323592016-07-24 22:04:11 +02001296 FOR_ALL_BUFFERS(b)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001297 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001298 // Deleted buffers should not be counted
1299 // SegPhault - 01/07/05
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001300 if (b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001301 n++;
1302 }
1303
Bram Moolenaar071d4272004-06-13 20:20:40 +00001304 return INT2NUM(n);
1305}
1306
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001307 static VALUE
1308buffer_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001309{
1310 buf_T *b;
1311 int n = NUM2INT(num);
1312
Bram Moolenaar29323592016-07-24 22:04:11 +02001313 FOR_ALL_BUFFERS(b)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001314 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001315 // Deleted buffers should not be counted
1316 // SegPhault - 01/07/05
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001317 if (!b->b_p_bl)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001318 continue;
1319
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001320 if (n == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321 return buffer_new(b);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001322
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001323 n--;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001324 }
1325 return Qnil;
1326}
1327
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001328 static VALUE
1329buffer_name(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330{
1331 buf_T *buf = get_buf(self);
1332
Bram Moolenaar35a2e192006-03-13 22:07:11 +00001333 return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001334}
1335
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001336 static VALUE
1337buffer_number(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001338{
1339 buf_T *buf = get_buf(self);
1340
1341 return INT2NUM(buf->b_fnum);
1342}
1343
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001344 static VALUE
1345buffer_count(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001346{
1347 buf_T *buf = get_buf(self);
1348
1349 return INT2NUM(buf->b_ml.ml_line_count);
1350}
1351
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001352 static VALUE
1353get_buffer_line(buf_T *buf, linenr_T n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354{
Bram Moolenaar3c531602010-11-16 14:46:19 +01001355 if (n <= 0 || n > buf->b_ml.ml_line_count)
1356 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
1357 return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001358}
1359
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001360 static VALUE
1361buffer_aref(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001362{
1363 buf_T *buf = get_buf(self);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001364
1365 if (buf != NULL)
1366 return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001367 return Qnil; // For stop warning
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001368}
1369
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001370 static VALUE
1371set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001372{
Bram Moolenaar165641d2010-02-17 16:23:09 +01001373 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001374 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001375
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001376 if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
1377 {
Bram Moolenaare76062c2022-11-28 18:51:43 +00001378 // Set curwin/curbuf for "buf" and save some things.
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001379 aucmd_prepbuf(&aco, buf);
Bram Moolenaare76062c2022-11-28 18:51:43 +00001380 if (curbuf == buf)
Bram Moolenaar758535a2016-03-30 22:06:16 +02001381 {
Bram Moolenaare76062c2022-11-28 18:51:43 +00001382 // Only when it worked to set "curbuf".
1383 if (u_savesub(n) == OK)
1384 {
1385 ml_replace(n, (char_u *)line, TRUE);
1386 changed();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001387#ifdef SYNTAX_HL
Bram Moolenaare76062c2022-11-28 18:51:43 +00001388 syn_changed(n); // recompute syntax hl. for this line
Bram Moolenaar071d4272004-06-13 20:20:40 +00001389#endif
Bram Moolenaare76062c2022-11-28 18:51:43 +00001390 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001391
Bram Moolenaare76062c2022-11-28 18:51:43 +00001392 // restore curwin/curbuf and a few other things
1393 aucmd_restbuf(&aco);
1394 // Careful: autocommands may have made "buf" invalid!
1395 }
Bram Moolenaarf30e74c2006-08-16 17:35:00 +00001396
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001397 update_curbuf(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001398 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001399 else
1400 {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001401 rb_raise(rb_eIndexError, "line number %ld out of range", (long)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001402 }
1403 return str;
1404}
1405
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001406 static VALUE
1407buffer_aset(VALUE self, VALUE num, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001408{
1409 buf_T *buf = get_buf(self);
1410
1411 if (buf != NULL)
1412 return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
1413 return str;
1414}
1415
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001416 static VALUE
1417buffer_delete(VALUE self, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001418{
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001419 buf_T *buf = get_buf(self);
1420 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001421 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001422
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001423 if (n > 0 && n <= buf->b_ml.ml_line_count)
1424 {
Bram Moolenaare76062c2022-11-28 18:51:43 +00001425 // Set curwin/curbuf for "buf" and save some things.
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001426 aucmd_prepbuf(&aco, buf);
Bram Moolenaare76062c2022-11-28 18:51:43 +00001427 if (curbuf == buf)
Bram Moolenaar758535a2016-03-30 22:06:16 +02001428 {
Bram Moolenaare76062c2022-11-28 18:51:43 +00001429 // Only when it worked to set "curbuf".
1430 if (u_savedel(n, 1) == OK)
1431 {
1432 ml_delete(n);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001433
Bram Moolenaare76062c2022-11-28 18:51:43 +00001434 // Changes to non-active buffers should properly refresh
1435 // SegPhault - 01/09/05
1436 deleted_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001437
Bram Moolenaare76062c2022-11-28 18:51:43 +00001438 changed();
1439 }
1440
1441 // restore curwin/curbuf and a few other things
1442 aucmd_restbuf(&aco);
1443 // Careful: autocommands may have made "buf" invalid!
Bram Moolenaar071d4272004-06-13 20:20:40 +00001444 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001445
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001446 update_curbuf(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001447 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001448 else
1449 {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001450 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001451 }
1452 return Qnil;
1453}
1454
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001455 static VALUE
1456buffer_append(VALUE self, VALUE num, VALUE str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001457{
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001458 buf_T *buf = get_buf(self);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001459 char *line = StringValuePtr(str);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001460 long n = NUM2LONG(num);
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001461 aco_save_T aco;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001462
Bram Moolenaar3c531602010-11-16 14:46:19 +01001463 if (line == NULL)
1464 {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001465 rb_raise(rb_eIndexError, "NULL line");
1466 }
1467 else if (n >= 0 && n <= buf->b_ml.ml_line_count)
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001468 {
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001469 // set curwin/curbuf for "buf" and save some things
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001470 aucmd_prepbuf(&aco, buf);
Bram Moolenaare76062c2022-11-28 18:51:43 +00001471 if (curbuf == buf)
Bram Moolenaar758535a2016-03-30 22:06:16 +02001472 {
Bram Moolenaare76062c2022-11-28 18:51:43 +00001473 // Only when it worked to set "curbuf".
1474 if (u_inssub(n + 1) == OK)
1475 {
1476 ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001477
Bram Moolenaare76062c2022-11-28 18:51:43 +00001478 // Changes to non-active buffers should properly refresh screen
1479 // SegPhault - 12/20/04
1480 appended_lines_mark(n, 1L);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001481
Bram Moolenaare76062c2022-11-28 18:51:43 +00001482 changed();
1483 }
1484
1485 // restore curwin/curbuf and a few other things
1486 aucmd_restbuf(&aco);
1487 // Careful: autocommands may have made "buf" invalid!
Bram Moolenaar071d4272004-06-13 20:20:40 +00001488 }
Bram Moolenaar20ff7922006-06-20 19:10:43 +00001489
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001490 update_curbuf(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491 }
Bram Moolenaar3c531602010-11-16 14:46:19 +01001492 else
1493 {
Bram Moolenaar165641d2010-02-17 16:23:09 +01001494 rb_raise(rb_eIndexError, "line number %ld out of range", n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001495 }
1496 return str;
1497}
1498
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001499#ifdef USE_TYPEDDATA
1500static size_t window_dsize(const void *buf);
1501
1502static const rb_data_type_t window_type = {
1503 "vim_window",
Bram Moolenaar41a41412020-01-07 21:32:19 +01001504 {0, 0, window_dsize,
1505# if RUBY_VERSION >= 27
Bram Moolenaar8b430b42020-02-22 15:01:00 +01001506 0, {0}
Bram Moolenaar41a41412020-01-07 21:32:19 +01001507# else
1508 {0, 0}
1509# endif
1510 },
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001511 0, 0,
1512# ifdef RUBY_TYPED_FREE_IMMEDIATELY
1513 0,
1514# endif
1515};
1516
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001517 static size_t
1518window_dsize(const void *win UNUSED)
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001519{
1520 return sizeof(win_T);
1521}
1522#endif
1523
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001524 static VALUE
1525window_new(win_T *win)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001526{
Bram Moolenaare344bea2005-09-01 20:46:49 +00001527 if (win->w_ruby_ref)
1528 {
1529 return (VALUE) win->w_ruby_ref;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001530 }
Bram Moolenaare344bea2005-09-01 20:46:49 +00001531 else
1532 {
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001533#ifdef USE_TYPEDDATA
1534 VALUE obj = TypedData_Wrap_Struct(cVimWindow, &window_type, win);
1535#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001536 VALUE obj = Data_Wrap_Struct(cVimWindow, 0, 0, win);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001537#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00001538 win->w_ruby_ref = (void *) obj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001539 rb_hash_aset(objtbl, rb_obj_id(obj), obj);
1540 return obj;
1541 }
1542}
1543
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001544 static win_T *
1545get_win(VALUE obj)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001546{
1547 win_T *win;
1548
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001549#ifdef USE_TYPEDDATA
1550 TypedData_Get_Struct(obj, win_T, &window_type, win);
1551#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001552 Data_Get_Struct(obj, win_T, win);
Bram Moolenaarf2f6d292015-12-28 20:57:10 +01001553#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001554 if (win == NULL)
1555 rb_raise(eDeletedWindowError, "attempt to refer to deleted window");
1556 return win;
1557}
1558
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001559 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001560window_s_current(VALUE self UNUSED)
1561{
1562 return window_new(curwin);
1563}
1564
1565 static VALUE
1566window_s_current_getter(ID id UNUSED, VALUE *x UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001567{
1568 return window_new(curwin);
1569}
1570
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001571/*
1572 * Added line manipulation functions
1573 * SegPhault - 03/07/05
1574 */
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001575 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001576line_s_current(VALUE self UNUSED)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001577{
1578 return get_buffer_line(curbuf, curwin->w_cursor.lnum);
1579}
1580
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001581 static VALUE
1582set_current_line(VALUE self UNUSED, VALUE str)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001583{
1584 return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
1585}
1586
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001587 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001588current_line_number(VALUE self UNUSED)
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001589{
1590 return INT2FIX((int)curwin->w_cursor.lnum);
1591}
1592
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001593 static VALUE
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001594window_s_count(VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001595{
Bram Moolenaar071d4272004-06-13 20:20:40 +00001596 win_T *w;
1597 int n = 0;
1598
Bram Moolenaar29323592016-07-24 22:04:11 +02001599 FOR_ALL_WINDOWS(w)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001600 n++;
1601 return INT2NUM(n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001602}
1603
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001604 static VALUE
1605window_s_aref(VALUE self UNUSED, VALUE num)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001606{
1607 win_T *w;
1608 int n = NUM2INT(num);
1609
Bram Moolenaar071d4272004-06-13 20:20:40 +00001610 for (w = firstwin; w != NULL; w = w->w_next, --n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001611 if (n == 0)
1612 return window_new(w);
1613 return Qnil;
1614}
1615
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001616 static VALUE
1617window_buffer(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001618{
1619 win_T *win = get_win(self);
1620
1621 return buffer_new(win->w_buffer);
1622}
1623
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001624 static VALUE
1625window_height(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001626{
1627 win_T *win = get_win(self);
1628
1629 return INT2NUM(win->w_height);
1630}
1631
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001632 static VALUE
1633window_set_height(VALUE self, VALUE height)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001634{
1635 win_T *win = get_win(self);
1636 win_T *savewin = curwin;
1637
1638 curwin = win;
1639 win_setheight(NUM2INT(height));
1640 curwin = savewin;
1641 return height;
1642}
1643
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001644 static VALUE
1645window_width(VALUE self UNUSED)
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001646{
Bram Moolenaare745d752017-09-22 16:56:22 +02001647 return INT2NUM(get_win(self)->w_width);
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001648}
1649
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001650 static VALUE
1651window_set_width(VALUE self UNUSED, VALUE width)
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001652{
1653 win_T *win = get_win(self);
1654 win_T *savewin = curwin;
1655
1656 curwin = win;
1657 win_setwidth(NUM2INT(width));
1658 curwin = savewin;
1659 return width;
1660}
1661
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001662 static VALUE
1663window_cursor(VALUE self)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001664{
1665 win_T *win = get_win(self);
1666
1667 return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col));
1668}
1669
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001670 static VALUE
1671window_set_cursor(VALUE self, VALUE pos)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001672{
1673 VALUE lnum, col;
1674 win_T *win = get_win(self);
1675
1676 Check_Type(pos, T_ARRAY);
Bram Moolenaar165641d2010-02-17 16:23:09 +01001677 if (RARRAY_LEN(pos) != 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001678 rb_raise(rb_eArgError, "array length must be 2");
Bram Moolenaar165641d2010-02-17 16:23:09 +01001679 lnum = RARRAY_PTR(pos)[0];
1680 col = RARRAY_PTR(pos)[1];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001681 win->w_cursor.lnum = NUM2LONG(lnum);
1682 win->w_cursor.col = NUM2UINT(col);
Bram Moolenaar53901442018-07-25 22:02:36 +02001683 win->w_set_curswant = TRUE;
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001684 check_cursor(); // put cursor on an existing line
Bram Moolenaara4d158b2022-08-14 14:17:45 +01001685 update_screen(UPD_NOT_VALID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001686 return Qnil;
1687}
1688
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001689 static VALUE
1690f_nop(VALUE self UNUSED)
Bram Moolenaar35df7d22012-04-20 18:05:47 +02001691{
1692 return Qnil;
1693}
1694
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001695 static VALUE
1696f_p(int argc, VALUE *argv, VALUE self UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001697{
1698 int i;
1699 VALUE str = rb_str_new("", 0);
Bram Moolenaar51e9fbf2018-08-11 14:24:11 +02001700 VALUE ret = Qnil;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001701
Bram Moolenaar758535a2016-03-30 22:06:16 +02001702 for (i = 0; i < argc; i++)
1703 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001704 if (i > 0) rb_str_cat(str, ", ", 2);
1705 rb_str_concat(str, rb_inspect(argv[i]));
1706 }
Bram Moolenaar32526b32019-01-19 17:43:09 +01001707 msg(RSTRING_PTR(str));
Bram Moolenaar51e9fbf2018-08-11 14:24:11 +02001708
1709 if (argc == 1)
1710 ret = argv[0];
1711 else if (argc > 1)
1712 ret = rb_ary_new4(argc, argv);
1713 return ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001714}
1715
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001716 static void
1717ruby_io_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001718{
1719#ifndef DYNAMIC_RUBY
1720 RUBYEXTERN VALUE rb_stdout;
Bram Moolenaarb6c8cd82018-07-24 05:41:30 +02001721 RUBYEXTERN VALUE rb_stderr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001722#endif
1723
1724 rb_stdout = rb_obj_alloc(rb_cObject);
Bram Moolenaarb6c8cd82018-07-24 05:41:30 +02001725 rb_stderr = rb_obj_alloc(rb_cObject);
lilydjwg7292c0c2025-05-02 15:17:14 +02001726 rb_define_singleton_method(rb_stdout, "write", (void*)vim_message, 1);
1727 rb_define_singleton_method(rb_stdout, "flush", (void*)f_nop, 0);
1728 rb_define_singleton_method(rb_stderr, "write", (void*)vim_message, 1);
1729 rb_define_singleton_method(rb_stderr, "flush", (void*)f_nop, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001730 rb_define_global_function("p", f_p, -1);
1731}
1732
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001733 static void
1734ruby_vim_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001735{
1736 objtbl = rb_hash_new();
1737 rb_global_variable(&objtbl);
1738
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001739 // The Vim module used to be called "VIM", but "Vim" is better. Make an
1740 // alias "VIM" for backwards compatibility.
Bram Moolenaarf711faf2007-05-10 16:48:19 +00001741 mVIM = rb_define_module("Vim");
1742 rb_define_const(rb_cObject, "VIM", mVIM);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001743 rb_define_const(mVIM, "VERSION_MAJOR", INT2NUM(VIM_VERSION_MAJOR));
1744 rb_define_const(mVIM, "VERSION_MINOR", INT2NUM(VIM_VERSION_MINOR));
1745 rb_define_const(mVIM, "VERSION_BUILD", INT2NUM(VIM_VERSION_BUILD));
1746 rb_define_const(mVIM, "VERSION_PATCHLEVEL", INT2NUM(VIM_VERSION_PATCHLEVEL));
1747 rb_define_const(mVIM, "VERSION_SHORT", rb_str_new2(VIM_VERSION_SHORT));
1748 rb_define_const(mVIM, "VERSION_MEDIUM", rb_str_new2(VIM_VERSION_MEDIUM));
1749 rb_define_const(mVIM, "VERSION_LONG", rb_str_new2(VIM_VERSION_LONG));
1750 rb_define_const(mVIM, "VERSION_LONG_DATE", rb_str_new2(VIM_VERSION_LONG_DATE));
1751 rb_define_module_function(mVIM, "message", vim_message, 1);
1752 rb_define_module_function(mVIM, "set_option", vim_set_option, 1);
1753 rb_define_module_function(mVIM, "command", vim_command, 1);
1754 rb_define_module_function(mVIM, "evaluate", vim_evaluate, 1);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01001755 rb_define_module_function(mVIM, "blob", vim_blob, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001756
1757 eDeletedBufferError = rb_define_class_under(mVIM, "DeletedBufferError",
1758 rb_eStandardError);
1759 eDeletedWindowError = rb_define_class_under(mVIM, "DeletedWindowError",
1760 rb_eStandardError);
1761
1762 cBuffer = rb_define_class_under(mVIM, "Buffer", rb_cObject);
lilydjwg7292c0c2025-05-02 15:17:14 +02001763 rb_define_singleton_method(cBuffer, "current", (void*)buffer_s_current, 0);
1764 rb_define_singleton_method(cBuffer, "count", (void*)buffer_s_count, 0);
1765 rb_define_singleton_method(cBuffer, "[]", (void*)buffer_s_aref, 1);
1766 rb_define_method(cBuffer, "name", (void*)buffer_name, 0);
1767 rb_define_method(cBuffer, "number", (void*)buffer_number, 0);
1768 rb_define_method(cBuffer, "count", (void*)buffer_count, 0);
1769 rb_define_method(cBuffer, "length", (void*)buffer_count, 0);
1770 rb_define_method(cBuffer, "[]", (void*)buffer_aref, 1);
1771 rb_define_method(cBuffer, "[]=", (void*)buffer_aset, 2);
1772 rb_define_method(cBuffer, "delete", (void*)buffer_delete, 1);
1773 rb_define_method(cBuffer, "append", (void*)buffer_append, 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001774
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001775 // Added line manipulation functions
1776 // SegPhault - 03/07/05
lilydjwg7292c0c2025-05-02 15:17:14 +02001777 rb_define_method(cBuffer, "line_number", (void*)current_line_number, 0);
1778 rb_define_method(cBuffer, "line", (void*)line_s_current, 0);
1779 rb_define_method(cBuffer, "line=", (void*)set_current_line, 1);
Bram Moolenaarbe4d5062006-03-18 21:30:13 +00001780
1781
Bram Moolenaar071d4272004-06-13 20:20:40 +00001782 cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
lilydjwg7292c0c2025-05-02 15:17:14 +02001783 rb_define_singleton_method(cVimWindow, "current", (void*)window_s_current, 0);
1784 rb_define_singleton_method(cVimWindow, "count", (void*)window_s_count, 0);
1785 rb_define_singleton_method(cVimWindow, "[]", (void*)window_s_aref, 1);
1786 rb_define_method(cVimWindow, "buffer", (void*)window_buffer, 0);
1787 rb_define_method(cVimWindow, "height", (void*)window_height, 0);
1788 rb_define_method(cVimWindow, "height=", (void*)window_set_height, 1);
1789 rb_define_method(cVimWindow, "width", (void*)window_width, 0);
1790 rb_define_method(cVimWindow, "width=", (void*)window_set_width, 1);
1791 rb_define_method(cVimWindow, "cursor", (void*)window_cursor, 0);
1792 rb_define_method(cVimWindow, "cursor=", (void*)window_set_cursor, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001793
Bram Moolenaard5a986f2020-12-06 21:11:31 +01001794 rb_define_virtual_variable("$curbuf", buffer_s_current_getter, 0);
1795 rb_define_virtual_variable("$curwin", window_s_current_getter, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001796}
Bram Moolenaar99685e62013-05-11 13:56:18 +02001797
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001798 void
1799vim_ruby_init(void *stack_start)
Bram Moolenaar99685e62013-05-11 13:56:18 +02001800{
Bram Moolenaar2ab2e862019-12-04 21:24:53 +01001801 // should get machine stack start address early in main function
Bram Moolenaar99685e62013-05-11 13:56:18 +02001802 ruby_stack_start = stack_start;
1803}
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001804
1805 static int
1806convert_hash2dict(VALUE key, VALUE val, VALUE arg)
1807{
1808 dict_T *d = (dict_T *)arg;
1809 dictitem_T *di;
1810
Bram Moolenaardace9f72020-12-28 15:07:45 +01001811 di = dictitem_alloc((char_u *)RSTRING_PTR(rb_obj_as_string(key)));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001812 if (di == NULL || ruby_convert_to_vim_value(val, &di->di_tv) != OK
1813 || dict_add(d, di) != OK)
1814 {
Bram Moolenaaref2c3252022-11-25 16:31:51 +00001815 d->dv_hashtab.ht_flags |= HTFLAGS_ERROR;
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001816 return ST_STOP;
1817 }
1818 return ST_CONTINUE;
1819}
1820
1821 static int
1822ruby_convert_to_vim_value(VALUE val, typval_T *rettv)
1823{
1824 switch (TYPE(val))
1825 {
1826 case T_NIL:
1827 rettv->v_type = VAR_SPECIAL;
1828 rettv->vval.v_number = VVAL_NULL;
1829 break;
1830 case T_TRUE:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001831 rettv->v_type = VAR_BOOL;
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001832 rettv->vval.v_number = VVAL_TRUE;
1833 break;
1834 case T_FALSE:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001835 rettv->v_type = VAR_BOOL;
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001836 rettv->vval.v_number = VVAL_FALSE;
1837 break;
1838 case T_BIGNUM:
1839 case T_FIXNUM:
1840 rettv->v_type = VAR_NUMBER;
1841 rettv->vval.v_number = (varnumber_T)NUM2LONG(val);
1842 break;
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001843 case T_FLOAT:
1844 rettv->v_type = VAR_FLOAT;
1845 rettv->vval.v_float = (float_T)NUM2DBL(val);
1846 break;
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001847 default:
1848 val = rb_obj_as_string(val);
1849 // FALLTHROUGH
1850 case T_STRING:
1851 {
1852 VALUE str = (VALUE)RSTRING(val);
1853
1854 rettv->v_type = VAR_STRING;
1855 rettv->vval.v_string = vim_strnsave((char_u *)RSTRING_PTR(str),
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001856 RSTRING_LEN(str));
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001857 }
1858 break;
1859 case T_ARRAY:
1860 {
1861 list_T *l;
1862 long i;
1863 typval_T v;
1864
1865 l = list_alloc();
1866 if (l == NULL)
1867 return FAIL;
1868
1869 for (i = 0; i < RARRAY_LEN(val); ++i)
1870 {
1871 if (ruby_convert_to_vim_value((VALUE)RARRAY_PTR(val)[i],
1872 &v) != OK)
1873 {
1874 list_unref(l);
1875 return FAIL;
1876 }
1877 list_append_tv(l, &v);
1878 clear_tv(&v);
1879 }
1880
1881 rettv->v_type = VAR_LIST;
1882 rettv->vval.v_list = l;
1883 ++l->lv_refcount;
1884 }
1885 break;
1886 case T_HASH:
1887 {
1888 dict_T *d;
1889
1890 d = dict_alloc();
1891 if (d == NULL)
1892 return FAIL;
1893
1894 rb_hash_foreach(val, convert_hash2dict, (VALUE)d);
Bram Moolenaaref2c3252022-11-25 16:31:51 +00001895 if (d->dv_hashtab.ht_flags & HTFLAGS_ERROR)
Bram Moolenaare99be0e2019-03-26 22:51:09 +01001896 {
1897 dict_unref(d);
1898 return FAIL;
1899 }
1900
1901 rettv->v_type = VAR_DICT;
1902 rettv->vval.v_dict = d;
1903 ++d->dv_refcount;
1904 }
1905 break;
1906 }
1907 return OK;
1908}
1909
1910 void
1911do_rubyeval(char_u *str, typval_T *rettv)
1912{
1913 int retval = FAIL;
1914
1915 if (ensure_ruby_initialized())
1916 {
1917 int state;
1918 VALUE obj;
1919
1920 obj = rb_eval_string_protect((const char *)str, &state);
1921 if (state)
1922 error_print(state);
1923 else
1924 retval = ruby_convert_to_vim_value(obj, rettv);
1925 }
1926 if (retval == FAIL)
1927 {
1928 rettv->v_type = VAR_NUMBER;
1929 rettv->vval.v_number = 0;
1930 }
1931}