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