1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * MzScheme interface by Sergey Khorev <[email protected]> 4 * Based on work by Brent Fulgham <[email protected]> 5 * (Based on lots of help from Matthew Flatt) 6 * 7 * This consists of six parts: 8 * 1. MzScheme interpreter main program 9 * 2. Routines that handle the external interface between MzScheme and 10 * Vim. 11 * 3. MzScheme input/output handlers: writes output via [e]msg(). 12 * 4. Implementation of the Vim Features for MzScheme 13 * 5. Vim Window-related Manipulation Functions. 14 * 6. Vim Buffer-related Manipulation Functions 15 * 16 * NOTES 17 * 1. Memory, allocated with scheme_malloc*, need not to be freed explicitly, 18 * garbage collector will do it self 19 * 2. Requires at least NORMAL features. I can't imagine why one may want 20 * to build with SMALL or TINY features but with MzScheme interface. 21 * 3. I don't use K&R-style functions. Anyways, MzScheme headers are ANSI. 22 */ 23 24 #include "vim.h" 25 26 #include "if_mzsch.h" 27 28 /* Only do the following when the feature is enabled. Needed for "make 29 * depend". */ 30 #if defined(FEAT_MZSCHEME) || defined(PROTO) 31 32 #ifdef PROTO 33 typedef int Scheme_Object; 34 typedef int Scheme_Closed_Prim; 35 typedef int Scheme_Env; 36 typedef int Scheme_Hash_Table; 37 typedef int Scheme_Type; 38 typedef int Scheme_Thread; 39 typedef int Scheme_Closed_Prim; 40 typedef int mzshort; 41 typedef int Scheme_Prim; 42 typedef int HINSTANCE; 43 #endif 44 45 /* 46 * scheme_register_tls_space is only available on 32-bit Windows until 47 * racket-6.3. See 48 * http://docs.racket-lang.org/inside/im_memoryalloc.html?q=scheme_register_tls_space 49 */ 50 #if MZSCHEME_VERSION_MAJOR >= 500 && defined(WIN32) \ 51 && defined(USE_THREAD_LOCAL) \ 52 && (!defined(_WIN64) || MZSCHEME_VERSION_MAJOR >= 603) 53 # define HAVE_TLS_SPACE 1 54 #endif 55 56 /* 57 * Since version 4.x precise GC requires trampolined startup. 58 * Futures and places in version 5.x need it too. 59 */ 60 #if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR >= 400 \ 61 || MZSCHEME_VERSION_MAJOR >= 500 \ 62 && (defined(MZ_USE_FUTURES) || defined(MZ_USE_PLACES)) 63 # define TRAMPOLINED_MZVIM_STARTUP 64 #endif 65 66 /* Base data structures */ 67 #define SCHEME_VIMBUFFERP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_buffer_type) 68 #define SCHEME_VIMWINDOWP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_window_type) 69 70 typedef struct 71 { 72 Scheme_Object so; 73 buf_T *buf; 74 } vim_mz_buffer; 75 76 #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) 77 78 typedef struct 79 { 80 Scheme_Object so; 81 win_T *win; 82 } vim_mz_window; 83 84 #define INVALID_WINDOW_VALUE ((win_T *)(-1)) 85 86 /* 87 * Prims that form MzScheme Vim interface 88 */ 89 typedef struct 90 { 91 Scheme_Closed_Prim *prim; 92 char *name; 93 int mina; /* arity information */ 94 int maxa; 95 } Vim_Prim; 96 97 typedef struct 98 { 99 char *name; 100 Scheme_Object *port; 101 } Port_Info; 102 103 /* 104 *======================================================================== 105 * Vim-Control Commands 106 *======================================================================== 107 */ 108 /* 109 *======================================================================== 110 * Utility functions for the vim/mzscheme interface 111 *======================================================================== 112 */ 113 #ifdef HAVE_SANDBOX 114 static Scheme_Object *sandbox_file_guard(int, Scheme_Object **); 115 static Scheme_Object *sandbox_network_guard(int, Scheme_Object **); 116 static void sandbox_check(void); 117 #endif 118 /* Buffer-related commands */ 119 static Scheme_Object *buffer_new(buf_T *buf); 120 static Scheme_Object *get_buffer_by_num(void *, int, Scheme_Object **); 121 static vim_mz_buffer *get_vim_curr_buffer(void); 122 123 /* Window-related commands */ 124 static Scheme_Object *window_new(win_T *win); 125 static vim_mz_window *get_vim_curr_window(void); 126 127 /* 128 *======================================================================== 129 * Internal Function Prototypes 130 *======================================================================== 131 */ 132 static int vim_error_check(void); 133 static int do_mzscheme_command(exarg_T *, void *, Scheme_Closed_Prim *what); 134 static int startup_mzscheme(void); 135 static char *string_to_line(Scheme_Object *obj); 136 #if MZSCHEME_VERSION_MAJOR >= 501 137 # define OUTPUT_LEN_TYPE intptr_t 138 #else 139 # define OUTPUT_LEN_TYPE long 140 #endif 141 static void do_output(char *mesg, OUTPUT_LEN_TYPE len); 142 static void do_printf(char *format, ...); 143 static void do_flush(void); 144 static Scheme_Object *_apply_thunk_catch_exceptions( 145 Scheme_Object *, Scheme_Object **); 146 static Scheme_Object *extract_exn_message(Scheme_Object *v); 147 static Scheme_Object *do_eval(void *, int noargc, Scheme_Object **noargv); 148 static Scheme_Object *do_load(void *, int noargc, Scheme_Object **noargv); 149 static void register_vim_exn(void); 150 static vim_mz_buffer *get_buffer_arg(const char *fname, int argnum, 151 int argc, Scheme_Object **argv); 152 static vim_mz_window *get_window_arg(const char *fname, int argnum, 153 int argc, Scheme_Object **argv); 154 static int line_in_range(linenr_T, buf_T *); 155 static void check_line_range(linenr_T, buf_T *); 156 static void mz_fix_cursor(int lo, int hi, int extra); 157 158 static int eval_with_exn_handling(void *, Scheme_Closed_Prim *, 159 Scheme_Object **ret); 160 static void make_modules(void); 161 static void init_exn_catching_apply(void); 162 static int mzscheme_env_main(Scheme_Env *env, int argc, char **argv); 163 static int mzscheme_init(void); 164 #ifdef FEAT_EVAL 165 static Scheme_Object *vim_to_mzscheme(typval_T *vim_value); 166 static Scheme_Object *vim_to_mzscheme_impl(typval_T *vim_value, int depth, 167 Scheme_Hash_Table *visited); 168 static int mzscheme_to_vim(Scheme_Object *obj, typval_T *tv); 169 static int mzscheme_to_vim_impl(Scheme_Object *obj, typval_T *tv, int depth, 170 Scheme_Hash_Table *visited); 171 static Scheme_Object *vim_funcref(void *data, int argc, Scheme_Object **argv); 172 #endif 173 174 #ifdef MZ_PRECISE_GC 175 static int buffer_size_proc(void *obj UNUSED) 176 { 177 return gcBYTES_TO_WORDS(sizeof(vim_mz_buffer)); 178 } 179 static int buffer_mark_proc(void *obj) 180 { 181 return buffer_size_proc(obj); 182 } 183 static int buffer_fixup_proc(void *obj) 184 { 185 /* apparently not needed as the object will be uncollectable while 186 * the buffer is alive 187 */ 188 /* 189 vim_mz_buffer* buf = (vim_mz_buffer*) obj; 190 buf->buf->b_mzscheme_ref = GC_fixup_self(obj); 191 */ 192 return buffer_size_proc(obj); 193 } 194 static int window_size_proc(void *obj UNUSED) 195 { 196 return gcBYTES_TO_WORDS(sizeof(vim_mz_window)); 197 } 198 static int window_mark_proc(void *obj) 199 { 200 return window_size_proc(obj); 201 } 202 static int window_fixup_proc(void *obj) 203 { 204 /* apparently not needed as the object will be uncollectable while 205 * the window is alive 206 */ 207 /* 208 vim_mz_window* win = (vim_mz_window*) obj; 209 win->win->w_mzscheme_ref = GC_fixup_self(obj); 210 */ 211 return window_size_proc(obj); 212 } 213 /* with precise GC, w_mzscheme_ref and b_mzscheme_ref are immobile boxes 214 * containing pointers to a window/buffer 215 * with conservative GC these are simply pointers*/ 216 # define WINDOW_REF(win) *(vim_mz_window **)((win)->w_mzscheme_ref) 217 # define BUFFER_REF(buf) *(vim_mz_buffer **)((buf)->b_mzscheme_ref) 218 #else 219 # define WINDOW_REF(win) (vim_mz_window *)((win)->w_mzscheme_ref) 220 # define BUFFER_REF(buf) (vim_mz_buffer *)((buf)->b_mzscheme_ref) 221 #endif 222 223 #if defined(DYNAMIC_MZSCHEME) || defined(PROTO) 224 static Scheme_Object *dll_scheme_eof; 225 static Scheme_Object *dll_scheme_false; 226 static Scheme_Object *dll_scheme_void; 227 static Scheme_Object *dll_scheme_null; 228 static Scheme_Object *dll_scheme_true; 229 230 static Scheme_Thread **dll_scheme_current_thread_ptr; 231 232 static void (**dll_scheme_console_printf_ptr)(char *str, ...); 233 static void (**dll_scheme_console_output_ptr)(char *str, OUTPUT_LEN_TYPE len); 234 static void (**dll_scheme_notify_multithread_ptr)(int on); 235 236 static void *(*dll_GC_malloc)(size_t size_in_bytes); 237 static void *(*dll_GC_malloc_atomic)(size_t size_in_bytes); 238 static Scheme_Env *(*dll_scheme_basic_env)(void); 239 static void (*dll_scheme_check_threads)(void); 240 static void (*dll_scheme_register_static)(void *ptr, long size); 241 static void (*dll_scheme_set_stack_base)(void *base, int no_auto_statics); 242 static void (*dll_scheme_add_global)(const char *name, Scheme_Object *val, 243 Scheme_Env *env); 244 static void (*dll_scheme_add_global_symbol)(Scheme_Object *name, 245 Scheme_Object *val, Scheme_Env *env); 246 static Scheme_Object *(*dll_scheme_apply)(Scheme_Object *rator, int num_rands, 247 Scheme_Object **rands); 248 static Scheme_Object *(*dll_scheme_builtin_value)(const char *name); 249 # if MZSCHEME_VERSION_MAJOR >= 299 250 static Scheme_Object *(*dll_scheme_byte_string_to_char_string)(Scheme_Object *s); 251 static Scheme_Object *(*dll_scheme_make_path)(const char *chars); 252 # endif 253 static void (*dll_scheme_close_input_port)(Scheme_Object *port); 254 static void (*dll_scheme_count_lines)(Scheme_Object *port); 255 #if MZSCHEME_VERSION_MAJOR < 360 256 static Scheme_Object *(*dll_scheme_current_continuation_marks)(void); 257 #else 258 static Scheme_Object *(*dll_scheme_current_continuation_marks)(Scheme_Object *prompt_tag); 259 #endif 260 static void (*dll_scheme_display)(Scheme_Object *obj, Scheme_Object *port); 261 static char *(*dll_scheme_display_to_string)(Scheme_Object *obj, OUTPUT_LEN_TYPE *len); 262 static int (*dll_scheme_eq)(Scheme_Object *obj1, Scheme_Object *obj2); 263 static Scheme_Object *(*dll_scheme_do_eval)(Scheme_Object *obj, 264 int _num_rands, Scheme_Object **rands, int val); 265 static void (*dll_scheme_dont_gc_ptr)(void *p); 266 static Scheme_Object *(*dll_scheme_eval)(Scheme_Object *obj, Scheme_Env *env); 267 static Scheme_Object *(*dll_scheme_eval_string)(const char *str, 268 Scheme_Env *env); 269 static Scheme_Object *(*dll_scheme_eval_string_all)(const char *str, 270 Scheme_Env *env, int all); 271 static void (*dll_scheme_finish_primitive_module)(Scheme_Env *env); 272 # if MZSCHEME_VERSION_MAJOR < 299 273 static char *(*dll_scheme_format)(char *format, int flen, int argc, 274 Scheme_Object **argv, long *rlen); 275 # else 276 static char *(*dll_scheme_format_utf8)(char *format, int flen, int argc, 277 Scheme_Object **argv, OUTPUT_LEN_TYPE *rlen); 278 static Scheme_Object *(*dll_scheme_get_param)(Scheme_Config *c, int pos); 279 # endif 280 static void (*dll_scheme_gc_ptr_ok)(void *p); 281 # if MZSCHEME_VERSION_MAJOR < 299 282 static char *(*dll_scheme_get_sized_string_output)(Scheme_Object *, 283 long *len); 284 # else 285 static char *(*dll_scheme_get_sized_byte_string_output)(Scheme_Object *, 286 OUTPUT_LEN_TYPE *len); 287 # endif 288 static Scheme_Object *(*dll_scheme_intern_symbol)(const char *name); 289 static Scheme_Object *(*dll_scheme_lookup_global)(Scheme_Object *symbol, 290 Scheme_Env *env); 291 static Scheme_Object *(*dll_scheme_make_closed_prim_w_arity) 292 (Scheme_Closed_Prim *prim, void *data, const char *name, mzshort mina, 293 mzshort maxa); 294 static Scheme_Object *(*dll_scheme_make_integer_value)(long i); 295 static Scheme_Object *(*dll_scheme_make_pair)(Scheme_Object *car, 296 Scheme_Object *cdr); 297 static Scheme_Object *(*dll_scheme_make_prim_w_arity)(Scheme_Prim *prim, 298 const char *name, mzshort mina, mzshort maxa); 299 # if MZSCHEME_VERSION_MAJOR < 299 300 static Scheme_Object *(*dll_scheme_make_string)(const char *chars); 301 static Scheme_Object *(*dll_scheme_make_string_output_port)(); 302 # else 303 static Scheme_Object *(*dll_scheme_make_byte_string)(const char *chars); 304 static Scheme_Object *(*dll_scheme_make_byte_string_output_port)(); 305 # endif 306 static Scheme_Object *(*dll_scheme_make_struct_instance)(Scheme_Object *stype, 307 int argc, Scheme_Object **argv); 308 static Scheme_Object **(*dll_scheme_make_struct_names)(Scheme_Object *base, 309 Scheme_Object *field_names, int flags, int *count_out); 310 static Scheme_Object *(*dll_scheme_make_struct_type)(Scheme_Object *base, 311 Scheme_Object *parent, Scheme_Object *inspector, int num_fields, 312 int num_uninit_fields, Scheme_Object *uninit_val, 313 Scheme_Object *properties 314 # if MZSCHEME_VERSION_MAJOR >= 299 315 , Scheme_Object *guard 316 # endif 317 ); 318 static Scheme_Object **(*dll_scheme_make_struct_values)( 319 Scheme_Object *struct_type, Scheme_Object **names, int count, 320 int flags); 321 static Scheme_Type (*dll_scheme_make_type)(const char *name); 322 static Scheme_Object *(*dll_scheme_make_vector)(int size, 323 Scheme_Object *fill); 324 static void *(*dll_scheme_malloc_fail_ok)(void *(*f)(size_t), size_t); 325 static Scheme_Object *(*dll_scheme_open_input_file)(const char *name, 326 const char *who); 327 static Scheme_Env *(*dll_scheme_primitive_module)(Scheme_Object *name, 328 Scheme_Env *for_env); 329 static int (*dll_scheme_proper_list_length)(Scheme_Object *list); 330 static void (*dll_scheme_raise)(Scheme_Object *exn); 331 static Scheme_Object *(*dll_scheme_read)(Scheme_Object *port); 332 static void (*dll_scheme_signal_error)(const char *msg, ...); 333 static void (*dll_scheme_wrong_type)(const char *name, const char *expected, 334 int which, int argc, Scheme_Object **argv); 335 # if MZSCHEME_VERSION_MAJOR >= 299 336 static void (*dll_scheme_set_param)(Scheme_Config *c, int pos, 337 Scheme_Object *o); 338 static Scheme_Config *(*dll_scheme_current_config)(void); 339 static Scheme_Object *(*dll_scheme_char_string_to_byte_string) 340 (Scheme_Object *s); 341 static Scheme_Object *(*dll_scheme_char_string_to_path) 342 (Scheme_Object *s); 343 static void *(*dll_scheme_set_collects_path)(Scheme_Object *p); 344 # endif 345 static Scheme_Hash_Table *(*dll_scheme_make_hash_table)(int type); 346 static void (*dll_scheme_hash_set)(Scheme_Hash_Table *table, 347 Scheme_Object *key, Scheme_Object *value); 348 static Scheme_Object *(*dll_scheme_hash_get)(Scheme_Hash_Table *table, 349 Scheme_Object *key); 350 static Scheme_Object *(*dll_scheme_make_double)(double d); 351 static Scheme_Object *(*dll_scheme_make_sized_byte_string)(char *chars, 352 long len, int copy); 353 static Scheme_Object *(*dll_scheme_namespace_require)(Scheme_Object *req); 354 static Scheme_Object *(*dll_scheme_dynamic_wind)(void (*pre)(void *), Scheme_Object *(* volatile act)(void *), void (* volatile post)(void *), Scheme_Object *(*jmp_handler)(void *), void * volatile data); 355 # ifdef MZ_PRECISE_GC 356 static void *(*dll_GC_malloc_one_tagged)(size_t size_in_bytes); 357 static void (*dll_GC_register_traversers)(short tag, Size_Proc size, Mark_Proc mark, Fixup_Proc fixup, int is_constant_size, int is_atomic); 358 # endif 359 # if MZSCHEME_VERSION_MAJOR >= 400 360 static void (*dll_scheme_init_collection_paths)(Scheme_Env *global_env, Scheme_Object *extra_dirs); 361 static void **(*dll_scheme_malloc_immobile_box)(void *p); 362 static void (*dll_scheme_free_immobile_box)(void **b); 363 # endif 364 # if MZSCHEME_VERSION_MAJOR >= 500 365 # ifdef TRAMPOLINED_MZVIM_STARTUP 366 static int (*dll_scheme_main_setup)(int no_auto_statics, Scheme_Env_Main _main, int argc, char **argv); 367 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || MZSCHEME_VERSION_MAJOR >= 603 368 static void (*dll_scheme_register_tls_space)(void *tls_space, int _tls_index); 369 # endif 370 # endif 371 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || defined(IMPLEMENT_THREAD_LOCAL_EXTERNALLY_VIA_PROC) 372 static Thread_Local_Variables *(*dll_scheme_external_get_thread_local_variables)(void); 373 # endif 374 # endif 375 # if MZSCHEME_VERSION_MAJOR >= 600 376 static void (*dll_scheme_embedded_load)(intptr_t len, const char *s, int predefined); 377 static void (*dll_scheme_register_embedded_load)(intptr_t len, const char *s); 378 static void (*dll_scheme_set_config_path)(Scheme_Object *p); 379 # endif 380 381 #if defined(DYNAMIC_MZSCHEME) /* not when defined(PROTO) */ 382 383 /* arrays are imported directly */ 384 # define scheme_eof dll_scheme_eof 385 # define scheme_false dll_scheme_false 386 # define scheme_void dll_scheme_void 387 # define scheme_null dll_scheme_null 388 # define scheme_true dll_scheme_true 389 390 /* pointers are GetProceAddress'ed as pointers to pointer */ 391 #if !defined(USE_THREAD_LOCAL) && !defined(LINK_EXTENSIONS_BY_TABLE) 392 # define scheme_current_thread (*dll_scheme_current_thread_ptr) 393 # endif 394 # define scheme_console_printf (*dll_scheme_console_printf_ptr) 395 # define scheme_console_output (*dll_scheme_console_output_ptr) 396 # define scheme_notify_multithread (*dll_scheme_notify_multithread_ptr) 397 398 /* and functions in a usual way */ 399 # define GC_malloc dll_GC_malloc 400 # define GC_malloc_atomic dll_GC_malloc_atomic 401 402 # define scheme_add_global dll_scheme_add_global 403 # define scheme_add_global_symbol dll_scheme_add_global_symbol 404 # define scheme_apply dll_scheme_apply 405 # define scheme_basic_env dll_scheme_basic_env 406 # define scheme_builtin_value dll_scheme_builtin_value 407 # if MZSCHEME_VERSION_MAJOR >= 299 408 # define scheme_byte_string_to_char_string dll_scheme_byte_string_to_char_string 409 # define scheme_make_path dll_scheme_make_path 410 # endif 411 # define scheme_check_threads dll_scheme_check_threads 412 # define scheme_close_input_port dll_scheme_close_input_port 413 # define scheme_count_lines dll_scheme_count_lines 414 # define scheme_current_continuation_marks \ 415 dll_scheme_current_continuation_marks 416 # define scheme_display dll_scheme_display 417 # define scheme_display_to_string dll_scheme_display_to_string 418 # define scheme_do_eval dll_scheme_do_eval 419 # define scheme_dont_gc_ptr dll_scheme_dont_gc_ptr 420 # define scheme_eq dll_scheme_eq 421 # define scheme_eval dll_scheme_eval 422 # define scheme_eval_string dll_scheme_eval_string 423 # define scheme_eval_string_all dll_scheme_eval_string_all 424 # define scheme_finish_primitive_module dll_scheme_finish_primitive_module 425 # if MZSCHEME_VERSION_MAJOR < 299 426 # define scheme_format dll_scheme_format 427 # else 428 # define scheme_format_utf8 dll_scheme_format_utf8 429 # endif 430 # define scheme_gc_ptr_ok dll_scheme_gc_ptr_ok 431 # if MZSCHEME_VERSION_MAJOR < 299 432 # define scheme_get_sized_byte_string_output dll_scheme_get_sized_string_output 433 # else 434 # define scheme_get_sized_byte_string_output \ 435 dll_scheme_get_sized_byte_string_output 436 # define scheme_get_param dll_scheme_get_param 437 # endif 438 # define scheme_intern_symbol dll_scheme_intern_symbol 439 # define scheme_lookup_global dll_scheme_lookup_global 440 # define scheme_make_closed_prim_w_arity dll_scheme_make_closed_prim_w_arity 441 # define scheme_make_integer_value dll_scheme_make_integer_value 442 # define scheme_make_pair dll_scheme_make_pair 443 # define scheme_make_prim_w_arity dll_scheme_make_prim_w_arity 444 # if MZSCHEME_VERSION_MAJOR < 299 445 # define scheme_make_byte_string dll_scheme_make_string 446 # define scheme_make_byte_string_output_port dll_scheme_make_string_output_port 447 # else 448 # define scheme_make_byte_string dll_scheme_make_byte_string 449 # define scheme_make_byte_string_output_port \ 450 dll_scheme_make_byte_string_output_port 451 # endif 452 # define scheme_make_struct_instance dll_scheme_make_struct_instance 453 # define scheme_make_struct_names dll_scheme_make_struct_names 454 # define scheme_make_struct_type dll_scheme_make_struct_type 455 # define scheme_make_struct_values dll_scheme_make_struct_values 456 # define scheme_make_type dll_scheme_make_type 457 # define scheme_make_vector dll_scheme_make_vector 458 # define scheme_malloc_fail_ok dll_scheme_malloc_fail_ok 459 # define scheme_open_input_file dll_scheme_open_input_file 460 # define scheme_primitive_module dll_scheme_primitive_module 461 # define scheme_proper_list_length dll_scheme_proper_list_length 462 # define scheme_raise dll_scheme_raise 463 # define scheme_read dll_scheme_read 464 # define scheme_register_static dll_scheme_register_static 465 # define scheme_set_stack_base dll_scheme_set_stack_base 466 # define scheme_signal_error dll_scheme_signal_error 467 # define scheme_wrong_type dll_scheme_wrong_type 468 # if MZSCHEME_VERSION_MAJOR >= 299 469 # define scheme_set_param dll_scheme_set_param 470 # define scheme_current_config dll_scheme_current_config 471 # define scheme_char_string_to_byte_string \ 472 dll_scheme_char_string_to_byte_string 473 # define scheme_char_string_to_path \ 474 dll_scheme_char_string_to_path 475 # define scheme_set_collects_path dll_scheme_set_collects_path 476 # endif 477 # define scheme_make_hash_table dll_scheme_make_hash_table 478 # define scheme_hash_set dll_scheme_hash_set 479 # define scheme_hash_get dll_scheme_hash_get 480 # define scheme_make_double dll_scheme_make_double 481 # define scheme_make_sized_byte_string dll_scheme_make_sized_byte_string 482 # define scheme_namespace_require dll_scheme_namespace_require 483 # define scheme_dynamic_wind dll_scheme_dynamic_wind 484 # ifdef MZ_PRECISE_GC 485 # define GC_malloc_one_tagged dll_GC_malloc_one_tagged 486 # define GC_register_traversers dll_GC_register_traversers 487 # endif 488 # if MZSCHEME_VERSION_MAJOR >= 400 489 # ifdef TRAMPOLINED_MZVIM_STARTUP 490 # define scheme_main_setup dll_scheme_main_setup 491 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || MZSCHEME_VERSION_MAJOR >= 603 492 # define scheme_register_tls_space dll_scheme_register_tls_space 493 # endif 494 # endif 495 # define scheme_init_collection_paths dll_scheme_init_collection_paths 496 # define scheme_malloc_immobile_box dll_scheme_malloc_immobile_box 497 # define scheme_free_immobile_box dll_scheme_free_immobile_box 498 # endif 499 # if MZSCHEME_VERSION_MAJOR >= 600 500 # define scheme_embedded_load dll_scheme_embedded_load 501 # define scheme_register_embedded_load dll_scheme_register_embedded_load 502 # define scheme_set_config_path dll_scheme_set_config_path 503 # endif 504 505 # if MZSCHEME_VERSION_MAJOR >= 500 506 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || defined(IMPLEMENT_THREAD_LOCAL_EXTERNALLY_VIA_PROC) 507 /* define as function for macro in schthread.h */ 508 Thread_Local_Variables * 509 scheme_external_get_thread_local_variables(void) 510 { 511 return dll_scheme_external_get_thread_local_variables(); 512 } 513 # endif 514 # endif 515 516 #endif 517 518 typedef struct 519 { 520 char *name; 521 void **ptr; 522 } Thunk_Info; 523 524 static Thunk_Info mzgc_imports[] = { 525 {"GC_malloc", (void **)&dll_GC_malloc}, 526 {"GC_malloc_atomic", (void **)&dll_GC_malloc_atomic}, 527 {NULL, NULL}}; 528 529 static Thunk_Info mzsch_imports[] = { 530 {"scheme_eof", (void **)&dll_scheme_eof}, 531 {"scheme_false", (void **)&dll_scheme_false}, 532 {"scheme_void", (void **)&dll_scheme_void}, 533 {"scheme_null", (void **)&dll_scheme_null}, 534 {"scheme_true", (void **)&dll_scheme_true}, 535 #if !defined(USE_THREAD_LOCAL) && !defined(LINK_EXTENSIONS_BY_TABLE) 536 {"scheme_current_thread", (void **)&dll_scheme_current_thread_ptr}, 537 #endif 538 {"scheme_console_printf", (void **)&dll_scheme_console_printf_ptr}, 539 {"scheme_console_output", (void **)&dll_scheme_console_output_ptr}, 540 {"scheme_notify_multithread", 541 (void **)&dll_scheme_notify_multithread_ptr}, 542 {"scheme_add_global", (void **)&dll_scheme_add_global}, 543 {"scheme_add_global_symbol", (void **)&dll_scheme_add_global_symbol}, 544 {"scheme_apply", (void **)&dll_scheme_apply}, 545 {"scheme_basic_env", (void **)&dll_scheme_basic_env}, 546 # if MZSCHEME_VERSION_MAJOR >= 299 547 {"scheme_byte_string_to_char_string", (void **)&dll_scheme_byte_string_to_char_string}, 548 {"scheme_make_path", (void **)&dll_scheme_make_path}, 549 # endif 550 {"scheme_builtin_value", (void **)&dll_scheme_builtin_value}, 551 {"scheme_check_threads", (void **)&dll_scheme_check_threads}, 552 {"scheme_close_input_port", (void **)&dll_scheme_close_input_port}, 553 {"scheme_count_lines", (void **)&dll_scheme_count_lines}, 554 {"scheme_current_continuation_marks", 555 (void **)&dll_scheme_current_continuation_marks}, 556 {"scheme_display", (void **)&dll_scheme_display}, 557 {"scheme_display_to_string", (void **)&dll_scheme_display_to_string}, 558 {"scheme_do_eval", (void **)&dll_scheme_do_eval}, 559 {"scheme_dont_gc_ptr", (void **)&dll_scheme_dont_gc_ptr}, 560 {"scheme_eq", (void **)&dll_scheme_eq}, 561 {"scheme_eval", (void **)&dll_scheme_eval}, 562 {"scheme_eval_string", (void **)&dll_scheme_eval_string}, 563 {"scheme_eval_string_all", (void **)&dll_scheme_eval_string_all}, 564 {"scheme_finish_primitive_module", 565 (void **)&dll_scheme_finish_primitive_module}, 566 # if MZSCHEME_VERSION_MAJOR < 299 567 {"scheme_format", (void **)&dll_scheme_format}, 568 # else 569 {"scheme_format_utf8", (void **)&dll_scheme_format_utf8}, 570 {"scheme_get_param", (void **)&dll_scheme_get_param}, 571 #endif 572 {"scheme_gc_ptr_ok", (void **)&dll_scheme_gc_ptr_ok}, 573 # if MZSCHEME_VERSION_MAJOR < 299 574 {"scheme_get_sized_string_output", 575 (void **)&dll_scheme_get_sized_string_output}, 576 # else 577 {"scheme_get_sized_byte_string_output", 578 (void **)&dll_scheme_get_sized_byte_string_output}, 579 #endif 580 {"scheme_intern_symbol", (void **)&dll_scheme_intern_symbol}, 581 {"scheme_lookup_global", (void **)&dll_scheme_lookup_global}, 582 {"scheme_make_closed_prim_w_arity", 583 (void **)&dll_scheme_make_closed_prim_w_arity}, 584 {"scheme_make_integer_value", (void **)&dll_scheme_make_integer_value}, 585 {"scheme_make_pair", (void **)&dll_scheme_make_pair}, 586 {"scheme_make_prim_w_arity", (void **)&dll_scheme_make_prim_w_arity}, 587 # if MZSCHEME_VERSION_MAJOR < 299 588 {"scheme_make_string", (void **)&dll_scheme_make_string}, 589 {"scheme_make_string_output_port", 590 (void **)&dll_scheme_make_string_output_port}, 591 # else 592 {"scheme_make_byte_string", (void **)&dll_scheme_make_byte_string}, 593 {"scheme_make_byte_string_output_port", 594 (void **)&dll_scheme_make_byte_string_output_port}, 595 # endif 596 {"scheme_make_struct_instance", 597 (void **)&dll_scheme_make_struct_instance}, 598 {"scheme_make_struct_names", (void **)&dll_scheme_make_struct_names}, 599 {"scheme_make_struct_type", (void **)&dll_scheme_make_struct_type}, 600 {"scheme_make_struct_values", (void **)&dll_scheme_make_struct_values}, 601 {"scheme_make_type", (void **)&dll_scheme_make_type}, 602 {"scheme_make_vector", (void **)&dll_scheme_make_vector}, 603 {"scheme_malloc_fail_ok", (void **)&dll_scheme_malloc_fail_ok}, 604 {"scheme_open_input_file", (void **)&dll_scheme_open_input_file}, 605 {"scheme_primitive_module", (void **)&dll_scheme_primitive_module}, 606 {"scheme_proper_list_length", (void **)&dll_scheme_proper_list_length}, 607 {"scheme_raise", (void **)&dll_scheme_raise}, 608 {"scheme_read", (void **)&dll_scheme_read}, 609 {"scheme_register_static", (void **)&dll_scheme_register_static}, 610 {"scheme_set_stack_base", (void **)&dll_scheme_set_stack_base}, 611 {"scheme_signal_error", (void **)&dll_scheme_signal_error}, 612 {"scheme_wrong_type", (void **)&dll_scheme_wrong_type}, 613 # if MZSCHEME_VERSION_MAJOR >= 299 614 {"scheme_set_param", (void **)&dll_scheme_set_param}, 615 {"scheme_current_config", (void **)&dll_scheme_current_config}, 616 {"scheme_char_string_to_byte_string", 617 (void **)&dll_scheme_char_string_to_byte_string}, 618 {"scheme_char_string_to_path", (void **)&dll_scheme_char_string_to_path}, 619 {"scheme_set_collects_path", (void **)&dll_scheme_set_collects_path}, 620 # endif 621 {"scheme_make_hash_table", (void **)&dll_scheme_make_hash_table}, 622 {"scheme_hash_set", (void **)&dll_scheme_hash_set}, 623 {"scheme_hash_get", (void **)&dll_scheme_hash_get}, 624 {"scheme_make_double", (void **)&dll_scheme_make_double}, 625 {"scheme_make_sized_byte_string", (void **)&dll_scheme_make_sized_byte_string}, 626 {"scheme_namespace_require", (void **)&dll_scheme_namespace_require}, 627 {"scheme_dynamic_wind", (void **)&dll_scheme_dynamic_wind}, 628 # ifdef MZ_PRECISE_GC 629 {"GC_malloc_one_tagged", (void **)&dll_GC_malloc_one_tagged}, 630 {"GC_register_traversers", (void **)&dll_GC_register_traversers}, 631 # endif 632 # if MZSCHEME_VERSION_MAJOR >= 400 633 # ifdef TRAMPOLINED_MZVIM_STARTUP 634 {"scheme_main_setup", (void **)&dll_scheme_main_setup}, 635 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || MZSCHEME_VERSION_MAJOR >= 603 636 {"scheme_register_tls_space", (void **)&dll_scheme_register_tls_space}, 637 # endif 638 # endif 639 {"scheme_init_collection_paths", (void **)&dll_scheme_init_collection_paths}, 640 {"scheme_malloc_immobile_box", (void **)&dll_scheme_malloc_immobile_box}, 641 {"scheme_free_immobile_box", (void **)&dll_scheme_free_immobile_box}, 642 # endif 643 # if MZSCHEME_VERSION_MAJOR >= 500 644 # if defined(IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS) || defined(IMPLEMENT_THREAD_LOCAL_EXTERNALLY_VIA_PROC) 645 {"scheme_external_get_thread_local_variables", (void **)&dll_scheme_external_get_thread_local_variables}, 646 # endif 647 # endif 648 # if MZSCHEME_VERSION_MAJOR >= 600 649 {"scheme_embedded_load", (void **)&dll_scheme_embedded_load}, 650 {"scheme_register_embedded_load", (void **)&dll_scheme_register_embedded_load}, 651 {"scheme_set_config_path", (void **)&dll_scheme_set_config_path}, 652 # endif 653 {NULL, NULL}}; 654 655 static HINSTANCE hMzGC = 0; 656 static HINSTANCE hMzSch = 0; 657 658 static void dynamic_mzscheme_end(void); 659 static int mzscheme_runtime_link_init(char *sch_dll, char *gc_dll, 660 int verbose); 661 662 static int 663 mzscheme_runtime_link_init(char *sch_dll, char *gc_dll, int verbose) 664 { 665 Thunk_Info *thunk = NULL; 666 667 if (hMzGC && hMzSch) 668 return OK; 669 hMzSch = vimLoadLib(sch_dll); 670 hMzGC = vimLoadLib(gc_dll); 671 672 if (!hMzGC) 673 { 674 if (verbose) 675 semsg(_(e_loadlib), gc_dll); 676 return FAIL; 677 } 678 679 if (!hMzSch) 680 { 681 if (verbose) 682 semsg(_(e_loadlib), sch_dll); 683 return FAIL; 684 } 685 686 for (thunk = mzsch_imports; thunk->name; thunk++) 687 { 688 if ((*thunk->ptr = 689 (void *)GetProcAddress(hMzSch, thunk->name)) == NULL) 690 { 691 FreeLibrary(hMzSch); 692 hMzSch = 0; 693 FreeLibrary(hMzGC); 694 hMzGC = 0; 695 if (verbose) 696 semsg(_(e_loadfunc), thunk->name); 697 return FAIL; 698 } 699 } 700 for (thunk = mzgc_imports; thunk->name; thunk++) 701 { 702 if ((*thunk->ptr = 703 (void *)GetProcAddress(hMzGC, thunk->name)) == NULL) 704 { 705 FreeLibrary(hMzSch); 706 hMzSch = 0; 707 FreeLibrary(hMzGC); 708 hMzGC = 0; 709 if (verbose) 710 semsg(_(e_loadfunc), thunk->name); 711 return FAIL; 712 } 713 } 714 return OK; 715 } 716 717 int 718 mzscheme_enabled(int verbose) 719 { 720 return mzscheme_runtime_link_init( 721 (char *)p_mzschemedll, (char *)p_mzschemegcdll, verbose) == OK; 722 } 723 724 static void 725 dynamic_mzscheme_end(void) 726 { 727 if (hMzSch) 728 { 729 FreeLibrary(hMzSch); 730 hMzSch = 0; 731 } 732 if (hMzGC) 733 { 734 FreeLibrary(hMzGC); 735 hMzGC = 0; 736 } 737 } 738 #endif /* DYNAMIC_MZSCHEME */ 739 740 #if MZSCHEME_VERSION_MAJOR < 299 741 # define GUARANTEED_STRING_ARG(proc, num) GUARANTEE_STRING(proc, num) 742 #else 743 static Scheme_Object * 744 guaranteed_byte_string_arg(char *proc, int num, int argc, Scheme_Object **argv) 745 { 746 if (SCHEME_BYTE_STRINGP(argv[num])) 747 { 748 return argv[num]; 749 } 750 else if (SCHEME_CHAR_STRINGP(argv[num])) 751 { 752 Scheme_Object *tmp = NULL; 753 MZ_GC_DECL_REG(2); 754 MZ_GC_VAR_IN_REG(0, argv[num]); 755 MZ_GC_VAR_IN_REG(1, tmp); 756 MZ_GC_REG(); 757 tmp = scheme_char_string_to_byte_string(argv[num]); 758 MZ_GC_UNREG(); 759 return tmp; 760 } 761 else 762 scheme_wrong_type(proc, "string", num, argc, argv); 763 /* unreachable */ 764 return scheme_void; 765 } 766 # define GUARANTEED_STRING_ARG(proc, num) guaranteed_byte_string_arg(proc, num, argc, argv) 767 #endif 768 769 /* need to put it here for dynamic stuff to work */ 770 #if defined(INCLUDE_MZSCHEME_BASE) 771 # include "mzscheme_base.c" 772 #endif 773 774 /* 775 *======================================================================== 776 * 1. MzScheme interpreter startup 777 *======================================================================== 778 */ 779 780 static Scheme_Type mz_buffer_type; 781 static Scheme_Type mz_window_type; 782 783 static int initialized = FALSE; 784 #ifdef DYNAMIC_MZSCHEME 785 static int disabled = FALSE; 786 #endif 787 static int load_base_module_failed = FALSE; 788 789 /* global environment */ 790 static Scheme_Env *environment = NULL; 791 /* output/error handlers */ 792 static Scheme_Object *curout = NULL; 793 static Scheme_Object *curerr = NULL; 794 /* exn:vim exception */ 795 static Scheme_Object *exn_catching_apply = NULL; 796 static Scheme_Object *exn_p = NULL; 797 static Scheme_Object *exn_message = NULL; 798 static Scheme_Object *vim_exn = NULL; /* Vim Error exception */ 799 800 #if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 801 static void *stack_base = NULL; 802 #endif 803 804 static long range_start; 805 static long range_end; 806 807 /* MzScheme threads scheduling stuff */ 808 static int mz_threads_allow = 0; 809 810 #if defined(FEAT_GUI_W32) 811 static void CALLBACK timer_proc(HWND, UINT, UINT_PTR, DWORD); 812 static UINT timer_id = 0; 813 #elif defined(FEAT_GUI_GTK) 814 static gboolean timer_proc(gpointer); 815 static guint timer_id = 0; 816 #elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) 817 static void timer_proc(XtPointer, XtIntervalId *); 818 static XtIntervalId timer_id = (XtIntervalId)0; 819 #elif defined(FEAT_GUI_MAC) 820 pascal void timer_proc(EventLoopTimerRef, void *); 821 static EventLoopTimerRef timer_id = NULL; 822 static EventLoopTimerUPP timerUPP; 823 #endif 824 825 #ifndef FEAT_GUI_W32 /* Win32 console and Unix */ 826 void 827 mzvim_check_threads(void) 828 { 829 /* Last time MzScheme threads were scheduled */ 830 static time_t mz_last_time = 0; 831 832 if (mz_threads_allow && p_mzq > 0) 833 { 834 time_t now = time(NULL); 835 836 if ((now - mz_last_time) * 1000 > p_mzq) 837 { 838 mz_last_time = now; 839 scheme_check_threads(); 840 } 841 } 842 } 843 #endif 844 845 #if defined(MZSCHEME_GUI_THREADS) || defined(PROTO) 846 static void setup_timer(void); 847 static void remove_timer(void); 848 849 /* timers are presented in GUI only */ 850 # if defined(FEAT_GUI_W32) 851 static void CALLBACK 852 timer_proc(HWND hwnd UNUSED, UINT uMsg UNUSED, UINT_PTR idEvent UNUSED, DWORD dwTime UNUSED) 853 # elif defined(FEAT_GUI_GTK) 854 static gboolean 855 timer_proc(gpointer data UNUSED) 856 # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) 857 static void 858 timer_proc(XtPointer timed_out UNUSED, XtIntervalId *interval_id UNUSED) 859 # elif defined(FEAT_GUI_MAC) 860 pascal void 861 timer_proc(EventLoopTimerRef theTimer UNUSED, void *userData UNUSED) 862 # endif 863 { 864 scheme_check_threads(); 865 # if defined(FEAT_GUI_GTK) 866 return TRUE; /* continue receiving notifications */ 867 # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) 868 /* renew timeout */ 869 if (mz_threads_allow && p_mzq > 0) 870 timer_id = XtAppAddTimeOut(app_context, p_mzq, 871 timer_proc, NULL); 872 # endif 873 } 874 875 static void 876 setup_timer(void) 877 { 878 # if defined(FEAT_GUI_W32) 879 timer_id = SetTimer(NULL, 0, p_mzq, timer_proc); 880 # elif defined(FEAT_GUI_GTK) 881 timer_id = g_timeout_add((guint)p_mzq, (GSourceFunc)timer_proc, NULL); 882 # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) 883 timer_id = XtAppAddTimeOut(app_context, p_mzq, timer_proc, NULL); 884 # elif defined(FEAT_GUI_MAC) 885 timerUPP = NewEventLoopTimerUPP(timer_proc); 886 InstallEventLoopTimer(GetMainEventLoop(), p_mzq * kEventDurationMillisecond, 887 p_mzq * kEventDurationMillisecond, timerUPP, NULL, &timer_id); 888 # endif 889 } 890 891 static void 892 remove_timer(void) 893 { 894 # if defined(FEAT_GUI_W32) 895 KillTimer(NULL, timer_id); 896 # elif defined(FEAT_GUI_GTK) 897 g_source_remove(timer_id); 898 # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) 899 XtRemoveTimeOut(timer_id); 900 # elif defined(FEAT_GUI_MAC) 901 RemoveEventLoopTimer(timer_id); 902 DisposeEventLoopTimerUPP(timerUPP); 903 # endif 904 timer_id = 0; 905 } 906 907 void 908 mzvim_reset_timer(void) 909 { 910 if (timer_id != 0) 911 remove_timer(); 912 if (mz_threads_allow && p_mzq > 0 && gui.in_use) 913 setup_timer(); 914 } 915 916 #endif /* MZSCHEME_GUI_THREADS */ 917 918 static void 919 notify_multithread(int on) 920 { 921 mz_threads_allow = on; 922 #ifdef MZSCHEME_GUI_THREADS 923 if (on && timer_id == 0 && p_mzq > 0 && gui.in_use) 924 setup_timer(); 925 if (!on && timer_id != 0) 926 remove_timer(); 927 #endif 928 } 929 930 void 931 mzscheme_end(void) 932 { 933 /* We can not unload the DLL. Racket's thread might be still alive. */ 934 #if 0 935 #ifdef DYNAMIC_MZSCHEME 936 dynamic_mzscheme_end(); 937 #endif 938 #endif 939 } 940 941 #if HAVE_TLS_SPACE 942 # if defined(_MSC_VER) 943 static __declspec(thread) void *tls_space; 944 extern intptr_t _tls_index; 945 # elif defined(__MINGW32__) 946 static __thread void *tls_space; 947 extern intptr_t _tls_index; 948 # else 949 static THREAD_LOCAL void *tls_space; 950 static intptr_t _tls_index = 0; 951 # endif 952 #endif 953 954 /* 955 * mzscheme_main() is called early in main(). 956 * We may call scheme_main_setup() which calls mzscheme_env_main() which then 957 * trampolines into vim_main2(), which never returns. 958 */ 959 int 960 mzscheme_main(void) 961 { 962 int argc = 0; 963 char *argv = NULL; 964 965 #ifdef DYNAMIC_MZSCHEME 966 /* 967 * Racket requires trampolined startup. We can not load it later. 968 * If dynamic dll loading is failed, disable it. 969 */ 970 if (!mzscheme_enabled(FALSE)) 971 { 972 disabled = TRUE; 973 return vim_main2(); 974 } 975 #endif 976 #ifdef HAVE_TLS_SPACE 977 scheme_register_tls_space(&tls_space, _tls_index); 978 #endif 979 #ifdef TRAMPOLINED_MZVIM_STARTUP 980 return scheme_main_setup(TRUE, mzscheme_env_main, argc, &argv); 981 #else 982 return mzscheme_env_main(NULL, argc, &argv); 983 #endif 984 } 985 986 static int 987 mzscheme_env_main(Scheme_Env *env, int argc UNUSED, char **argv UNUSED) 988 { 989 #ifdef TRAMPOLINED_MZVIM_STARTUP 990 /* Scheme has created the environment for us */ 991 environment = env; 992 #else 993 # ifdef MZ_PRECISE_GC 994 Scheme_Object *dummy = NULL; 995 MZ_GC_DECL_REG(1); 996 MZ_GC_VAR_IN_REG(0, dummy); 997 998 stack_base = &__gc_var_stack__; 999 # else 1000 int dummy = 0; 1001 stack_base = (void *)&dummy; 1002 # endif 1003 #endif 1004 1005 vim_main2(); 1006 /* not reached, vim_main2() will loop until exit() */ 1007 1008 return 0; 1009 } 1010 1011 static Scheme_Object* 1012 load_base_module(void *data) 1013 { 1014 scheme_namespace_require(scheme_intern_symbol((char *)data)); 1015 return scheme_null; 1016 } 1017 1018 static Scheme_Object * 1019 load_base_module_on_error(void *data UNUSED) 1020 { 1021 load_base_module_failed = TRUE; 1022 return scheme_null; 1023 } 1024 1025 static int 1026 startup_mzscheme(void) 1027 { 1028 #ifndef TRAMPOLINED_MZVIM_STARTUP 1029 scheme_set_stack_base(stack_base, 1); 1030 #endif 1031 1032 #ifndef TRAMPOLINED_MZVIM_STARTUP 1033 /* in newer versions of precise GC the initial env has been created */ 1034 environment = scheme_basic_env(); 1035 #endif 1036 1037 MZ_REGISTER_STATIC(environment); 1038 MZ_REGISTER_STATIC(curout); 1039 MZ_REGISTER_STATIC(curerr); 1040 MZ_REGISTER_STATIC(exn_catching_apply); 1041 MZ_REGISTER_STATIC(exn_p); 1042 MZ_REGISTER_STATIC(exn_message); 1043 MZ_REGISTER_STATIC(vim_exn); 1044 1045 MZ_GC_CHECK(); 1046 1047 #ifdef INCLUDE_MZSCHEME_BASE 1048 /* invoke function from generated and included mzscheme_base.c */ 1049 declare_modules(environment); 1050 #endif 1051 1052 /* setup 'current-library-collection-paths' parameter */ 1053 # if MZSCHEME_VERSION_MAJOR >= 299 1054 { 1055 Scheme_Object *coll_path = NULL; 1056 int mustfree = FALSE; 1057 char_u *s; 1058 1059 MZ_GC_DECL_REG(1); 1060 MZ_GC_VAR_IN_REG(0, coll_path); 1061 MZ_GC_REG(); 1062 /* workaround for dynamic loading on windows */ 1063 s = vim_getenv((char_u *)"PLTCOLLECTS", &mustfree); 1064 if (s != NULL) 1065 { 1066 coll_path = scheme_make_path((char *)s); 1067 MZ_GC_CHECK(); 1068 if (mustfree) 1069 vim_free(s); 1070 } 1071 # ifdef MZSCHEME_COLLECTS 1072 if (coll_path == NULL) 1073 { 1074 coll_path = scheme_make_path(MZSCHEME_COLLECTS); 1075 MZ_GC_CHECK(); 1076 } 1077 # endif 1078 if (coll_path != NULL) 1079 { 1080 scheme_set_collects_path(coll_path); 1081 MZ_GC_CHECK(); 1082 } 1083 MZ_GC_UNREG(); 1084 } 1085 # else 1086 # ifdef MZSCHEME_COLLECTS 1087 { 1088 Scheme_Object *coll_string = NULL; 1089 Scheme_Object *coll_pair = NULL; 1090 Scheme_Config *config = NULL; 1091 1092 MZ_GC_DECL_REG(3); 1093 MZ_GC_VAR_IN_REG(0, coll_string); 1094 MZ_GC_VAR_IN_REG(1, coll_pair); 1095 MZ_GC_VAR_IN_REG(2, config); 1096 MZ_GC_REG(); 1097 coll_string = scheme_make_byte_string(MZSCHEME_COLLECTS); 1098 MZ_GC_CHECK(); 1099 coll_pair = scheme_make_pair(coll_string, scheme_null); 1100 MZ_GC_CHECK(); 1101 config = scheme_current_config(); 1102 MZ_GC_CHECK(); 1103 scheme_set_param(config, MZCONFIG_COLLECTION_PATHS, coll_pair); 1104 MZ_GC_CHECK(); 1105 MZ_GC_UNREG(); 1106 } 1107 # endif 1108 #endif 1109 1110 # if MZSCHEME_VERSION_MAJOR >= 600 1111 { 1112 Scheme_Object *config_path = NULL; 1113 int mustfree = FALSE; 1114 char_u *s; 1115 1116 MZ_GC_DECL_REG(1); 1117 MZ_GC_VAR_IN_REG(0, config_path); 1118 MZ_GC_REG(); 1119 /* workaround for dynamic loading on windows */ 1120 s = vim_getenv((char_u *)"PLTCONFIGDIR", &mustfree); 1121 if (s != NULL) 1122 { 1123 config_path = scheme_make_path((char *)s); 1124 MZ_GC_CHECK(); 1125 if (mustfree) 1126 vim_free(s); 1127 } 1128 #ifdef MZSCHEME_CONFIGDIR 1129 if (config_path == NULL) 1130 { 1131 config_path = scheme_make_path(MZSCHEME_CONFIGDIR); 1132 MZ_GC_CHECK(); 1133 } 1134 #endif 1135 if (config_path != NULL) 1136 { 1137 scheme_set_config_path(config_path); 1138 MZ_GC_CHECK(); 1139 } 1140 MZ_GC_UNREG(); 1141 } 1142 # endif 1143 1144 #if MZSCHEME_VERSION_MAJOR >= 400 1145 scheme_init_collection_paths(environment, scheme_null); 1146 #endif 1147 1148 /* 1149 * versions 4.x do not provide Scheme bindings by default 1150 * we need to add them explicitly 1151 */ 1152 { 1153 /* use error handler to avoid abort */ 1154 scheme_dynamic_wind(NULL, load_base_module, NULL, 1155 load_base_module_on_error, "racket/base"); 1156 if (load_base_module_failed) 1157 { 1158 load_base_module_failed = FALSE; 1159 scheme_dynamic_wind(NULL, load_base_module, NULL, 1160 load_base_module_on_error, "scheme/base"); 1161 if (load_base_module_failed) 1162 return -1; 1163 } 1164 } 1165 1166 register_vim_exn(); 1167 /* use new environment to initialise exception handling */ 1168 init_exn_catching_apply(); 1169 1170 /* redirect output */ 1171 scheme_console_output = do_output; 1172 scheme_console_printf = do_printf; 1173 1174 #ifdef HAVE_SANDBOX 1175 { 1176 Scheme_Object *make_security_guard = NULL; 1177 MZ_GC_DECL_REG(1); 1178 MZ_GC_VAR_IN_REG(0, make_security_guard); 1179 MZ_GC_REG(); 1180 1181 #if MZSCHEME_VERSION_MAJOR < 400 1182 { 1183 Scheme_Object *make_security_guard_symbol = NULL; 1184 MZ_GC_DECL_REG(1); 1185 MZ_GC_VAR_IN_REG(0, make_security_guard_symbol); 1186 MZ_GC_REG(); 1187 make_security_guard_symbol = scheme_intern_symbol("make-security-guard"); 1188 MZ_GC_CHECK(); 1189 make_security_guard = scheme_lookup_global( 1190 make_security_guard_symbol, environment); 1191 MZ_GC_UNREG(); 1192 } 1193 #else 1194 make_security_guard = scheme_builtin_value("make-security-guard"); 1195 MZ_GC_CHECK(); 1196 #endif 1197 1198 /* setup sandbox guards */ 1199 if (make_security_guard != NULL) 1200 { 1201 Scheme_Object *args[3] = {NULL, NULL, NULL}; 1202 Scheme_Object *guard = NULL; 1203 Scheme_Config *config = NULL; 1204 MZ_GC_DECL_REG(5); 1205 MZ_GC_ARRAY_VAR_IN_REG(0, args, 3); 1206 MZ_GC_VAR_IN_REG(3, guard); 1207 MZ_GC_VAR_IN_REG(4, config); 1208 MZ_GC_REG(); 1209 config = scheme_current_config(); 1210 MZ_GC_CHECK(); 1211 args[0] = scheme_get_param(config, MZCONFIG_SECURITY_GUARD); 1212 MZ_GC_CHECK(); 1213 args[1] = scheme_make_prim_w_arity(sandbox_file_guard, 1214 "sandbox-file-guard", 3, 3); 1215 args[2] = scheme_make_prim_w_arity(sandbox_network_guard, 1216 "sandbox-network-guard", 4, 4); 1217 guard = scheme_apply(make_security_guard, 3, args); 1218 MZ_GC_CHECK(); 1219 scheme_set_param(config, MZCONFIG_SECURITY_GUARD, guard); 1220 MZ_GC_CHECK(); 1221 MZ_GC_UNREG(); 1222 } 1223 MZ_GC_UNREG(); 1224 } 1225 #endif 1226 /* Create buffer and window types for use in Scheme code */ 1227 mz_buffer_type = scheme_make_type("<vim-buffer>"); 1228 MZ_GC_CHECK(); 1229 mz_window_type = scheme_make_type("<vim-window>"); 1230 MZ_GC_CHECK(); 1231 #ifdef MZ_PRECISE_GC 1232 GC_register_traversers(mz_buffer_type, 1233 buffer_size_proc, buffer_mark_proc, buffer_fixup_proc, 1234 TRUE, TRUE); 1235 GC_register_traversers(mz_window_type, 1236 window_size_proc, window_mark_proc, window_fixup_proc, 1237 TRUE, TRUE); 1238 #endif 1239 1240 make_modules(); 1241 1242 /* 1243 * setup callback to receive notifications 1244 * whether thread scheduling is (or not) required 1245 */ 1246 scheme_notify_multithread = notify_multithread; 1247 1248 return 0; 1249 } 1250 1251 /* 1252 * This routine is called for each new invocation of MzScheme 1253 * to make sure things are properly initialized. 1254 */ 1255 static int 1256 mzscheme_init(void) 1257 { 1258 if (!initialized) 1259 { 1260 #ifdef DYNAMIC_MZSCHEME 1261 if (disabled || !mzscheme_enabled(TRUE)) 1262 { 1263 emsg(_("E815: Sorry, this command is disabled, the MzScheme libraries could not be loaded.")); 1264 return -1; 1265 } 1266 #endif 1267 if (load_base_module_failed || startup_mzscheme()) 1268 { 1269 emsg(_("E895: Sorry, this command is disabled, the MzScheme's racket/base module could not be loaded.")); 1270 return -1; 1271 } 1272 initialized = TRUE; 1273 } 1274 { 1275 Scheme_Config *config = NULL; 1276 MZ_GC_DECL_REG(1); 1277 MZ_GC_VAR_IN_REG(0, config); 1278 MZ_GC_REG(); 1279 config = scheme_current_config(); 1280 MZ_GC_CHECK(); 1281 /* recreate ports each call effectively clearing these ones */ 1282 curout = scheme_make_byte_string_output_port(); 1283 MZ_GC_CHECK(); 1284 curerr = scheme_make_byte_string_output_port(); 1285 MZ_GC_CHECK(); 1286 scheme_set_param(config, MZCONFIG_OUTPUT_PORT, curout); 1287 MZ_GC_CHECK(); 1288 scheme_set_param(config, MZCONFIG_ERROR_PORT, curerr); 1289 MZ_GC_CHECK(); 1290 MZ_GC_UNREG(); 1291 } 1292 1293 return 0; 1294 } 1295 1296 /* 1297 *======================================================================== 1298 * 2. External Interface 1299 *======================================================================== 1300 */ 1301 1302 /* 1303 * Evaluate command with exception handling 1304 */ 1305 static int 1306 eval_with_exn_handling(void *data, Scheme_Closed_Prim *what, Scheme_Object **ret) 1307 { 1308 Scheme_Object *value = NULL; 1309 Scheme_Object *exn = NULL; 1310 Scheme_Object *prim = NULL; 1311 1312 MZ_GC_DECL_REG(3); 1313 MZ_GC_VAR_IN_REG(0, value); 1314 MZ_GC_VAR_IN_REG(1, exn); 1315 MZ_GC_VAR_IN_REG(2, prim); 1316 MZ_GC_REG(); 1317 1318 prim = scheme_make_closed_prim_w_arity(what, data, "mzvim", 0, 0); 1319 MZ_GC_CHECK(); 1320 value = _apply_thunk_catch_exceptions(prim, &exn); 1321 MZ_GC_CHECK(); 1322 1323 if (!value) 1324 { 1325 value = extract_exn_message(exn); 1326 /* Got an exn? */ 1327 if (value) 1328 { 1329 scheme_display(value, curerr); /* Send to stderr-vim */ 1330 MZ_GC_CHECK(); 1331 do_flush(); 1332 } 1333 MZ_GC_UNREG(); 1334 /* `raise' was called on some arbitrary value */ 1335 return FAIL; 1336 } 1337 1338 if (ret != NULL) /* if pointer to retval supported give it up */ 1339 *ret = value; 1340 /* Print any result, as long as it's not a void */ 1341 else if (!SCHEME_VOIDP(value)) 1342 { 1343 scheme_display(value, curout); /* Send to stdout-vim */ 1344 MZ_GC_CHECK(); 1345 } 1346 1347 do_flush(); 1348 MZ_GC_UNREG(); 1349 return OK; 1350 } 1351 1352 /* :mzscheme */ 1353 static int 1354 do_mzscheme_command(exarg_T *eap, void *data, Scheme_Closed_Prim *what) 1355 { 1356 if (mzscheme_init()) 1357 return FAIL; 1358 1359 range_start = eap->line1; 1360 range_end = eap->line2; 1361 1362 return eval_with_exn_handling(data, what, NULL); 1363 } 1364 1365 /* 1366 * Routine called by VIM when deleting a buffer 1367 */ 1368 void 1369 mzscheme_buffer_free(buf_T *buf) 1370 { 1371 if (buf->b_mzscheme_ref) 1372 { 1373 vim_mz_buffer *bp = NULL; 1374 MZ_GC_DECL_REG(1); 1375 MZ_GC_VAR_IN_REG(0, bp); 1376 MZ_GC_REG(); 1377 1378 bp = BUFFER_REF(buf); 1379 bp->buf = INVALID_BUFFER_VALUE; 1380 #ifndef MZ_PRECISE_GC 1381 scheme_gc_ptr_ok(bp); 1382 #else 1383 scheme_free_immobile_box(buf->b_mzscheme_ref); 1384 #endif 1385 buf->b_mzscheme_ref = NULL; 1386 MZ_GC_CHECK(); 1387 MZ_GC_UNREG(); 1388 } 1389 } 1390 1391 /* 1392 * Routine called by VIM when deleting a Window 1393 */ 1394 void 1395 mzscheme_window_free(win_T *win) 1396 { 1397 if (win->w_mzscheme_ref) 1398 { 1399 vim_mz_window *wp = NULL; 1400 MZ_GC_DECL_REG(1); 1401 MZ_GC_VAR_IN_REG(0, wp); 1402 MZ_GC_REG(); 1403 wp = WINDOW_REF(win); 1404 wp->win = INVALID_WINDOW_VALUE; 1405 #ifndef MZ_PRECISE_GC 1406 scheme_gc_ptr_ok(wp); 1407 #else 1408 scheme_free_immobile_box(win->w_mzscheme_ref); 1409 #endif 1410 win->w_mzscheme_ref = NULL; 1411 MZ_GC_CHECK(); 1412 MZ_GC_UNREG(); 1413 } 1414 } 1415 1416 /* 1417 * ":mzscheme" (or ":mz") 1418 */ 1419 void 1420 ex_mzscheme(exarg_T *eap) 1421 { 1422 char_u *script; 1423 1424 script = script_get(eap, eap->arg); 1425 if (!eap->skip) 1426 { 1427 if (script == NULL) 1428 do_mzscheme_command(eap, eap->arg, do_eval); 1429 else 1430 { 1431 do_mzscheme_command(eap, script, do_eval); 1432 vim_free(script); 1433 } 1434 } 1435 } 1436 1437 static Scheme_Object * 1438 do_load(void *data, int noargc UNUSED, Scheme_Object **noargv UNUSED) 1439 { 1440 Scheme_Object *expr = NULL; 1441 Scheme_Object *result = NULL; 1442 char *file = NULL; 1443 Port_Info *pinfo = (Port_Info *)data; 1444 1445 MZ_GC_DECL_REG(3); 1446 MZ_GC_VAR_IN_REG(0, expr); 1447 MZ_GC_VAR_IN_REG(1, result); 1448 MZ_GC_VAR_IN_REG(2, file); 1449 MZ_GC_REG(); 1450 1451 file = (char *)scheme_malloc_fail_ok(scheme_malloc_atomic, MAXPATHL + 1); 1452 MZ_GC_CHECK(); 1453 1454 /* make Vim expansion */ 1455 expand_env((char_u *)pinfo->name, (char_u *)file, MAXPATHL); 1456 pinfo->port = scheme_open_input_file(file, "mzfile"); 1457 MZ_GC_CHECK(); 1458 scheme_count_lines(pinfo->port); /* to get accurate read error location*/ 1459 MZ_GC_CHECK(); 1460 1461 /* Like REPL but print only last result */ 1462 while (!SCHEME_EOFP(expr = scheme_read(pinfo->port))) 1463 { 1464 result = scheme_eval(expr, environment); 1465 MZ_GC_CHECK(); 1466 } 1467 1468 /* errors will be caught in do_mzscheme_command and ex_mzfile */ 1469 scheme_close_input_port(pinfo->port); 1470 MZ_GC_CHECK(); 1471 pinfo->port = NULL; 1472 MZ_GC_UNREG(); 1473 return result; 1474 } 1475 1476 /* :mzfile */ 1477 void 1478 ex_mzfile(exarg_T *eap) 1479 { 1480 Port_Info pinfo = {NULL, NULL}; 1481 1482 MZ_GC_DECL_REG(1); 1483 MZ_GC_VAR_IN_REG(0, pinfo.port); 1484 MZ_GC_REG(); 1485 1486 pinfo.name = (char *)eap->arg; 1487 if (do_mzscheme_command(eap, &pinfo, do_load) != OK 1488 && pinfo.port != NULL) /* looks like port was not closed */ 1489 { 1490 scheme_close_input_port(pinfo.port); 1491 MZ_GC_CHECK(); 1492 } 1493 MZ_GC_UNREG(); 1494 } 1495 1496 1497 /* 1498 *======================================================================== 1499 * Exception handling code -- cribbed form the MzScheme sources and 1500 * Matthew Flatt's "Inside PLT MzScheme" document. 1501 *======================================================================== 1502 */ 1503 static void 1504 init_exn_catching_apply(void) 1505 { 1506 if (!exn_catching_apply) 1507 { 1508 char *e = 1509 "(lambda (thunk) " 1510 "(with-handlers ([void (lambda (exn) (cons #f exn))]) " 1511 "(cons #t (thunk))))"; 1512 1513 exn_catching_apply = scheme_eval_string(e, environment); 1514 MZ_GC_CHECK(); 1515 exn_p = scheme_builtin_value("exn?"); 1516 MZ_GC_CHECK(); 1517 exn_message = scheme_builtin_value("exn-message"); 1518 MZ_GC_CHECK(); 1519 } 1520 } 1521 1522 /* 1523 * This function applies a thunk, returning the Scheme value if there's 1524 * no exception, otherwise returning NULL and setting *exn to the raised 1525 * value (usually an exn structure). 1526 */ 1527 static Scheme_Object * 1528 _apply_thunk_catch_exceptions(Scheme_Object *f, Scheme_Object **exn) 1529 { 1530 Scheme_Object *v; 1531 1532 v = _scheme_apply(exn_catching_apply, 1, &f); 1533 /* v is a pair: (cons #t value) or (cons #f exn) */ 1534 1535 if (SCHEME_TRUEP(SCHEME_CAR(v))) 1536 return SCHEME_CDR(v); 1537 else 1538 { 1539 *exn = SCHEME_CDR(v); 1540 return NULL; 1541 } 1542 } 1543 1544 static Scheme_Object * 1545 extract_exn_message(Scheme_Object *v) 1546 { 1547 if (SCHEME_TRUEP(_scheme_apply(exn_p, 1, &v))) 1548 return _scheme_apply(exn_message, 1, &v); 1549 else 1550 return NULL; /* Not an exn structure */ 1551 } 1552 1553 static Scheme_Object * 1554 do_eval(void *s, int noargc UNUSED, Scheme_Object **noargv UNUSED) 1555 { 1556 return scheme_eval_string_all((char *)s, environment, TRUE); 1557 } 1558 1559 /* 1560 *======================================================================== 1561 * 3. MzScheme I/O Handlers 1562 *======================================================================== 1563 */ 1564 static void 1565 do_intrnl_output(char *mesg, int error) 1566 { 1567 char *p, *prev; 1568 1569 prev = mesg; 1570 p = strchr(prev, '\n'); 1571 while (p) 1572 { 1573 *p = '\0'; 1574 if (error) 1575 emsg(prev); 1576 else 1577 msg(prev); 1578 prev = p + 1; 1579 p = strchr(prev, '\n'); 1580 } 1581 1582 if (error) 1583 emsg(prev); 1584 else 1585 msg(prev); 1586 } 1587 1588 static void 1589 do_output(char *mesg, OUTPUT_LEN_TYPE len UNUSED) 1590 { 1591 /* TODO: use len, the string may not be NUL terminated */ 1592 do_intrnl_output(mesg, 0); 1593 } 1594 1595 static void 1596 do_err_output(char *mesg) 1597 { 1598 do_intrnl_output(mesg, 1); 1599 } 1600 1601 static void 1602 do_printf(char *format, ...) 1603 { 1604 do_intrnl_output(format, 1); 1605 } 1606 1607 static void 1608 do_flush(void) 1609 { 1610 char *buff; 1611 OUTPUT_LEN_TYPE length; 1612 1613 buff = scheme_get_sized_byte_string_output(curerr, &length); 1614 MZ_GC_CHECK(); 1615 if (length) 1616 { 1617 do_err_output(buff); 1618 return; 1619 } 1620 1621 buff = scheme_get_sized_byte_string_output(curout, &length); 1622 MZ_GC_CHECK(); 1623 if (length) 1624 do_output(buff, length); 1625 } 1626 1627 /* 1628 *======================================================================== 1629 * 4. Implementation of the Vim Features for MzScheme 1630 *======================================================================== 1631 */ 1632 1633 /* (command {command-string}) */ 1634 static Scheme_Object * 1635 vim_command(void *data, int argc, Scheme_Object **argv) 1636 { 1637 Vim_Prim *prim = (Vim_Prim *)data; 1638 Scheme_Object *cmd = NULL; 1639 MZ_GC_DECL_REG(1); 1640 MZ_GC_VAR_IN_REG(0, cmd); 1641 MZ_GC_REG(); 1642 cmd = GUARANTEED_STRING_ARG(prim->name, 0); 1643 1644 /* may be use do_cmdline_cmd? */ 1645 do_cmdline(BYTE_STRING_VALUE(cmd), NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE); 1646 update_screen(VALID); 1647 1648 MZ_GC_UNREG(); 1649 raise_if_error(); 1650 return scheme_void; 1651 } 1652 1653 /* (eval {expr-string}) */ 1654 static Scheme_Object * 1655 vim_eval(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1656 { 1657 #ifdef FEAT_EVAL 1658 Vim_Prim *prim = (Vim_Prim *)data; 1659 Scheme_Object *result = NULL; 1660 typval_T *vim_result; 1661 Scheme_Object *expr = NULL; 1662 MZ_GC_DECL_REG(2); 1663 MZ_GC_VAR_IN_REG(0, result); 1664 MZ_GC_VAR_IN_REG(1, expr); 1665 MZ_GC_REG(); 1666 expr = GUARANTEED_STRING_ARG(prim->name, 0); 1667 1668 vim_result = eval_expr(BYTE_STRING_VALUE(expr), NULL); 1669 1670 if (vim_result == NULL) 1671 raise_vim_exn(_("invalid expression")); 1672 1673 result = vim_to_mzscheme(vim_result); 1674 MZ_GC_CHECK(); 1675 free_tv(vim_result); 1676 1677 MZ_GC_UNREG(); 1678 return result; 1679 #else 1680 raise_vim_exn(_("expressions disabled at compile time")); 1681 /* unreachable */ 1682 return scheme_false; 1683 #endif 1684 } 1685 1686 /* (range-start) */ 1687 static Scheme_Object * 1688 get_range_start(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1689 { 1690 return scheme_make_integer(range_start); 1691 } 1692 1693 /* (range-end) */ 1694 static Scheme_Object * 1695 get_range_end(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1696 { 1697 return scheme_make_integer(range_end); 1698 } 1699 1700 /* (beep) */ 1701 static Scheme_Object * 1702 mzscheme_beep(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1703 { 1704 vim_beep(BO_LANG); 1705 return scheme_void; 1706 } 1707 1708 static Scheme_Object *M_global = NULL; 1709 1710 /* (get-option {option-name}) [buffer/window] */ 1711 static Scheme_Object * 1712 get_option(void *data, int argc, Scheme_Object **argv) 1713 { 1714 Vim_Prim *prim = (Vim_Prim *)data; 1715 long value; 1716 char *strval; 1717 int rc; 1718 Scheme_Object *rval = NULL; 1719 Scheme_Object *name = NULL; 1720 int opt_flags = 0; 1721 buf_T *save_curb = curbuf; 1722 win_T *save_curw = curwin; 1723 1724 MZ_GC_DECL_REG(2); 1725 MZ_GC_VAR_IN_REG(0, rval); 1726 MZ_GC_VAR_IN_REG(1, name); 1727 MZ_GC_REG(); 1728 1729 name = GUARANTEED_STRING_ARG(prim->name, 0); 1730 1731 if (argc > 1) 1732 { 1733 if (M_global == NULL) 1734 { 1735 MZ_REGISTER_STATIC(M_global); 1736 M_global = scheme_intern_symbol("global"); 1737 MZ_GC_CHECK(); 1738 } 1739 1740 if (argv[1] == M_global) 1741 opt_flags = OPT_GLOBAL; 1742 else if (SCHEME_VIMBUFFERP(argv[1])) 1743 { 1744 curbuf = get_valid_buffer(argv[1]); 1745 opt_flags = OPT_LOCAL; 1746 } 1747 else if (SCHEME_VIMWINDOWP(argv[1])) 1748 { 1749 win_T *win = get_valid_window(argv[1]); 1750 1751 curwin = win; 1752 curbuf = win->w_buffer; 1753 opt_flags = OPT_LOCAL; 1754 } 1755 else 1756 scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv); 1757 } 1758 1759 rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval, opt_flags); 1760 curbuf = save_curb; 1761 curwin = save_curw; 1762 1763 switch (rc) 1764 { 1765 case 1: 1766 MZ_GC_UNREG(); 1767 return scheme_make_integer_value(value); 1768 case 0: 1769 rval = scheme_make_byte_string(strval); 1770 MZ_GC_CHECK(); 1771 vim_free(strval); 1772 MZ_GC_UNREG(); 1773 return rval; 1774 case -1: 1775 case -2: 1776 MZ_GC_UNREG(); 1777 raise_vim_exn(_("hidden option")); 1778 case -3: 1779 MZ_GC_UNREG(); 1780 raise_vim_exn(_("unknown option")); 1781 } 1782 /* unreachable */ 1783 return scheme_void; 1784 } 1785 1786 /* (set-option {option-changing-string} [buffer/window]) */ 1787 static Scheme_Object * 1788 set_option(void *data, int argc, Scheme_Object **argv) 1789 { 1790 char_u *command = NULL; 1791 int opt_flags = 0; 1792 buf_T *save_curb = curbuf; 1793 win_T *save_curw = curwin; 1794 Vim_Prim *prim = (Vim_Prim *)data; 1795 Scheme_Object *cmd = NULL; 1796 1797 MZ_GC_DECL_REG(1); 1798 MZ_GC_VAR_IN_REG(0, cmd); 1799 MZ_GC_REG(); 1800 cmd = GUARANTEED_STRING_ARG(prim->name, 0); 1801 1802 if (argc > 1) 1803 { 1804 if (M_global == NULL) 1805 { 1806 MZ_REGISTER_STATIC(M_global); 1807 M_global = scheme_intern_symbol("global"); 1808 MZ_GC_CHECK(); 1809 } 1810 1811 if (argv[1] == M_global) 1812 opt_flags = OPT_GLOBAL; 1813 else if (SCHEME_VIMBUFFERP(argv[1])) 1814 { 1815 curbuf = get_valid_buffer(argv[1]); 1816 opt_flags = OPT_LOCAL; 1817 } 1818 else if (SCHEME_VIMWINDOWP(argv[1])) 1819 { 1820 win_T *win = get_valid_window(argv[1]); 1821 curwin = win; 1822 curbuf = win->w_buffer; 1823 opt_flags = OPT_LOCAL; 1824 } 1825 else 1826 scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv); 1827 } 1828 1829 /* do_set can modify cmd, make copy */ 1830 command = vim_strsave(BYTE_STRING_VALUE(cmd)); 1831 MZ_GC_UNREG(); 1832 do_set(command, opt_flags); 1833 vim_free(command); 1834 update_screen(NOT_VALID); 1835 curbuf = save_curb; 1836 curwin = save_curw; 1837 raise_if_error(); 1838 return scheme_void; 1839 } 1840 1841 /* 1842 *=========================================================================== 1843 * 5. Vim Window-related Manipulation Functions 1844 *=========================================================================== 1845 */ 1846 1847 /* (curr-win) */ 1848 static Scheme_Object * 1849 get_curr_win(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1850 { 1851 return (Scheme_Object *)get_vim_curr_window(); 1852 } 1853 1854 /* (win-count) */ 1855 static Scheme_Object * 1856 get_window_count(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1857 { 1858 int n = 0; 1859 win_T *w; 1860 1861 FOR_ALL_WINDOWS(w) 1862 ++n; 1863 return scheme_make_integer(n); 1864 } 1865 1866 /* (get-win-list [buffer]) */ 1867 static Scheme_Object * 1868 get_window_list(void *data, int argc, Scheme_Object **argv) 1869 { 1870 Vim_Prim *prim = (Vim_Prim *)data; 1871 vim_mz_buffer *buf; 1872 Scheme_Object *list; 1873 win_T *w = firstwin; 1874 1875 buf = get_buffer_arg(prim->name, 0, argc, argv); 1876 list = scheme_null; 1877 1878 for ( ; w != NULL; w = w->w_next) 1879 if (w->w_buffer == buf->buf) 1880 { 1881 list = scheme_make_pair(window_new(w), list); 1882 MZ_GC_CHECK(); 1883 } 1884 1885 return list; 1886 } 1887 1888 static Scheme_Object * 1889 window_new(win_T *win) 1890 { 1891 vim_mz_window *self = NULL; 1892 1893 MZ_GC_DECL_REG(1); 1894 MZ_GC_VAR_IN_REG(0, self); 1895 1896 /* We need to handle deletion of windows underneath us. 1897 * If we add a "w_mzscheme_ref" field to the win_T structure, 1898 * then we can get at it in win_free() in vim. 1899 * 1900 * On a win_free() we set the Scheme object's win_T *field 1901 * to an invalid value. We trap all uses of a window 1902 * object, and reject them if the win_T *field is invalid. 1903 */ 1904 if (win->w_mzscheme_ref != NULL) 1905 return (Scheme_Object *)WINDOW_REF(win); 1906 1907 MZ_GC_REG(); 1908 self = scheme_malloc_fail_ok(scheme_malloc_tagged, sizeof(vim_mz_window)); 1909 vim_memset(self, 0, sizeof(vim_mz_window)); 1910 #ifndef MZ_PRECISE_GC 1911 scheme_dont_gc_ptr(self); /* because win isn't visible to GC */ 1912 #else 1913 win->w_mzscheme_ref = scheme_malloc_immobile_box(NULL); 1914 #endif 1915 MZ_GC_CHECK(); 1916 WINDOW_REF(win) = self; 1917 MZ_GC_CHECK(); 1918 self->win = win; 1919 self->so.type = mz_window_type; 1920 1921 MZ_GC_UNREG(); 1922 return (Scheme_Object *)self; 1923 } 1924 1925 /* (get-win-num [window]) */ 1926 static Scheme_Object * 1927 get_window_num(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 1928 { 1929 int nr = 1; 1930 Vim_Prim *prim = (Vim_Prim *)data; 1931 win_T *win = get_window_arg(prim->name, 0, argc, argv)->win; 1932 win_T *wp; 1933 1934 for (wp = firstwin; wp != win; wp = wp->w_next) 1935 ++nr; 1936 1937 return scheme_make_integer(nr); 1938 } 1939 1940 /* (get-win-by-num {windownum}) */ 1941 static Scheme_Object * 1942 get_window_by_num(void *data, int argc, Scheme_Object **argv) 1943 { 1944 Vim_Prim *prim = (Vim_Prim *)data; 1945 win_T *win = firstwin; 1946 int fnum; 1947 1948 fnum = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 1949 if (fnum < 1) 1950 scheme_signal_error(_("window index is out of range")); 1951 1952 for ( ; win != NULL; win = win->w_next, --fnum) 1953 if (fnum == 1) /* to be 1-based */ 1954 return window_new(win); 1955 1956 return scheme_false; 1957 } 1958 1959 /* (get-win-buffer [window]) */ 1960 static Scheme_Object * 1961 get_window_buffer(void *data, int argc, Scheme_Object **argv) 1962 { 1963 Vim_Prim *prim = (Vim_Prim *)data; 1964 vim_mz_window *win = get_window_arg(prim->name, 0, argc, argv); 1965 1966 return buffer_new(win->win->w_buffer); 1967 } 1968 1969 /* (get-win-height [window]) */ 1970 static Scheme_Object * 1971 get_window_height(void *data, int argc, Scheme_Object **argv) 1972 { 1973 Vim_Prim *prim = (Vim_Prim *)data; 1974 vim_mz_window *win = get_window_arg(prim->name, 0, argc, argv); 1975 1976 return scheme_make_integer(win->win->w_height); 1977 } 1978 1979 /* (set-win-height {height} [window]) */ 1980 static Scheme_Object * 1981 set_window_height(void *data, int argc, Scheme_Object **argv) 1982 { 1983 Vim_Prim *prim = (Vim_Prim *)data; 1984 vim_mz_window *win; 1985 win_T *savewin; 1986 int height; 1987 1988 win = get_window_arg(prim->name, 1, argc, argv); 1989 height = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 1990 1991 #ifdef FEAT_GUI 1992 need_mouse_correct = TRUE; 1993 #endif 1994 1995 savewin = curwin; 1996 curwin = win->win; 1997 win_setheight(height); 1998 curwin = savewin; 1999 2000 raise_if_error(); 2001 return scheme_void; 2002 } 2003 2004 /* (get-win-width [window]) */ 2005 static Scheme_Object * 2006 get_window_width(void *data, int argc, Scheme_Object **argv) 2007 { 2008 Vim_Prim *prim = (Vim_Prim *)data; 2009 vim_mz_window *win = get_window_arg(prim->name, 0, argc, argv); 2010 2011 return scheme_make_integer(win->win->w_width); 2012 } 2013 2014 /* (set-win-width {width} [window]) */ 2015 static Scheme_Object * 2016 set_window_width(void *data, int argc, Scheme_Object **argv) 2017 { 2018 Vim_Prim *prim = (Vim_Prim *)data; 2019 vim_mz_window *win; 2020 win_T *savewin; 2021 int width = 0; 2022 2023 win = get_window_arg(prim->name, 1, argc, argv); 2024 width = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2025 2026 # ifdef FEAT_GUI 2027 need_mouse_correct = TRUE; 2028 # endif 2029 2030 savewin = curwin; 2031 curwin = win->win; 2032 win_setwidth(width); 2033 curwin = savewin; 2034 2035 raise_if_error(); 2036 return scheme_void; 2037 } 2038 2039 /* (get-cursor [window]) -> (line . col) */ 2040 static Scheme_Object * 2041 get_cursor(void *data, int argc, Scheme_Object **argv) 2042 { 2043 Vim_Prim *prim = (Vim_Prim *)data; 2044 vim_mz_window *win; 2045 pos_T pos; 2046 2047 win = get_window_arg(prim->name, 0, argc, argv); 2048 pos = win->win->w_cursor; 2049 return scheme_make_pair(scheme_make_integer_value((long)pos.lnum), 2050 scheme_make_integer_value((long)pos.col + 1)); 2051 } 2052 2053 /* (set-cursor (line . col) [window]) */ 2054 static Scheme_Object * 2055 set_cursor(void *data, int argc, Scheme_Object **argv) 2056 { 2057 Vim_Prim *prim = (Vim_Prim *)data; 2058 vim_mz_window *win; 2059 long lnum = 0; 2060 long col = 0; 2061 2062 #ifdef HAVE_SANDBOX 2063 sandbox_check(); 2064 #endif 2065 win = get_window_arg(prim->name, 1, argc, argv); 2066 GUARANTEE_PAIR(prim->name, 0); 2067 2068 if (!SCHEME_INTP(SCHEME_CAR(argv[0])) 2069 || !SCHEME_INTP(SCHEME_CDR(argv[0]))) 2070 scheme_wrong_type(prim->name, "integer pair", 0, argc, argv); 2071 2072 lnum = SCHEME_INT_VAL(SCHEME_CAR(argv[0])); 2073 col = SCHEME_INT_VAL(SCHEME_CDR(argv[0])) - 1; 2074 2075 check_line_range(lnum, win->win->w_buffer); 2076 /* don't know how to catch invalid column value */ 2077 2078 win->win->w_cursor.lnum = lnum; 2079 win->win->w_cursor.col = col; 2080 win->win->w_set_curswant = TRUE; 2081 update_screen(VALID); 2082 2083 raise_if_error(); 2084 return scheme_void; 2085 } 2086 /* 2087 *=========================================================================== 2088 * 6. Vim Buffer-related Manipulation Functions 2089 *=========================================================================== 2090 */ 2091 2092 /* (open-buff {filename}) */ 2093 static Scheme_Object * 2094 mzscheme_open_buffer(void *data, int argc, Scheme_Object **argv) 2095 { 2096 Vim_Prim *prim = (Vim_Prim *)data; 2097 int num = 0; 2098 Scheme_Object *onum = NULL; 2099 Scheme_Object *buf = NULL; 2100 Scheme_Object *fname; 2101 2102 MZ_GC_DECL_REG(3); 2103 MZ_GC_VAR_IN_REG(0, onum); 2104 MZ_GC_VAR_IN_REG(1, buf); 2105 MZ_GC_VAR_IN_REG(2, fname); 2106 MZ_GC_REG(); 2107 fname = GUARANTEED_STRING_ARG(prim->name, 0); 2108 2109 #ifdef HAVE_SANDBOX 2110 sandbox_check(); 2111 #endif 2112 /* TODO make open existing file */ 2113 num = buflist_add(BYTE_STRING_VALUE(fname), BLN_LISTED | BLN_CURBUF); 2114 2115 if (num == 0) 2116 raise_vim_exn(_("couldn't open buffer")); 2117 2118 onum = scheme_make_integer(num); 2119 buf = get_buffer_by_num(data, 1, &onum); 2120 MZ_GC_UNREG(); 2121 return buf; 2122 } 2123 2124 /* (get-buff-by-num {buffernum}) */ 2125 static Scheme_Object * 2126 get_buffer_by_num(void *data, int argc, Scheme_Object **argv) 2127 { 2128 Vim_Prim *prim = (Vim_Prim *)data; 2129 buf_T *buf; 2130 int fnum; 2131 2132 fnum = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2133 2134 FOR_ALL_BUFFERS(buf) 2135 if (buf->b_fnum == fnum) 2136 return buffer_new(buf); 2137 2138 return scheme_false; 2139 } 2140 2141 /* (get-buff-by-name {buffername}) */ 2142 static Scheme_Object * 2143 get_buffer_by_name(void *data, int argc, Scheme_Object **argv) 2144 { 2145 Vim_Prim *prim = (Vim_Prim *)data; 2146 buf_T *buf; 2147 Scheme_Object *buffer = NULL; 2148 Scheme_Object *fname = NULL; 2149 2150 MZ_GC_DECL_REG(2); 2151 MZ_GC_VAR_IN_REG(0, buffer); 2152 MZ_GC_VAR_IN_REG(1, fname); 2153 MZ_GC_REG(); 2154 fname = GUARANTEED_STRING_ARG(prim->name, 0); 2155 buffer = scheme_false; 2156 2157 FOR_ALL_BUFFERS(buf) 2158 { 2159 if (buf->b_ffname == NULL || buf->b_sfname == NULL) 2160 /* empty string */ 2161 { 2162 if (BYTE_STRING_VALUE(fname)[0] == NUL) 2163 buffer = buffer_new(buf); 2164 } 2165 else if (!fnamecmp(buf->b_ffname, BYTE_STRING_VALUE(fname)) 2166 || !fnamecmp(buf->b_sfname, BYTE_STRING_VALUE(fname))) 2167 { 2168 /* either short or long filename matches */ 2169 buffer = buffer_new(buf); 2170 } 2171 } 2172 2173 MZ_GC_UNREG(); 2174 return buffer; 2175 } 2176 2177 /* (get-next-buff [buffer]) */ 2178 static Scheme_Object * 2179 get_next_buffer(void *data, int argc, Scheme_Object **argv) 2180 { 2181 Vim_Prim *prim = (Vim_Prim *)data; 2182 buf_T *buf = get_buffer_arg(prim->name, 0, argc, argv)->buf; 2183 2184 if (buf->b_next == NULL) 2185 return scheme_false; 2186 else 2187 return buffer_new(buf->b_next); 2188 } 2189 2190 /* (get-prev-buff [buffer]) */ 2191 static Scheme_Object * 2192 get_prev_buffer(void *data, int argc, Scheme_Object **argv) 2193 { 2194 Vim_Prim *prim = (Vim_Prim *)data; 2195 buf_T *buf = get_buffer_arg(prim->name, 0, argc, argv)->buf; 2196 2197 if (buf->b_prev == NULL) 2198 return scheme_false; 2199 else 2200 return buffer_new(buf->b_prev); 2201 } 2202 2203 /* (get-buff-num [buffer]) */ 2204 static Scheme_Object * 2205 get_buffer_num(void *data, int argc, Scheme_Object **argv) 2206 { 2207 Vim_Prim *prim = (Vim_Prim *)data; 2208 vim_mz_buffer *buf = get_buffer_arg(prim->name, 0, argc, argv); 2209 2210 return scheme_make_integer(buf->buf->b_fnum); 2211 } 2212 2213 /* (buff-count) */ 2214 static Scheme_Object * 2215 get_buffer_count(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 2216 { 2217 buf_T *b; 2218 int n = 0; 2219 2220 FOR_ALL_BUFFERS(b) ++n; 2221 return scheme_make_integer(n); 2222 } 2223 2224 /* (get-buff-name [buffer]) */ 2225 static Scheme_Object * 2226 get_buffer_name(void *data, int argc, Scheme_Object **argv) 2227 { 2228 Vim_Prim *prim = (Vim_Prim *)data; 2229 vim_mz_buffer *buf = get_buffer_arg(prim->name, 0, argc, argv); 2230 2231 return scheme_make_byte_string((char *)buf->buf->b_ffname); 2232 } 2233 2234 /* (curr-buff) */ 2235 static Scheme_Object * 2236 get_curr_buffer(void *data UNUSED, int argc UNUSED, Scheme_Object **argv UNUSED) 2237 { 2238 return (Scheme_Object *)get_vim_curr_buffer(); 2239 } 2240 2241 static Scheme_Object * 2242 buffer_new(buf_T *buf) 2243 { 2244 vim_mz_buffer *self = NULL; 2245 2246 MZ_GC_DECL_REG(1); 2247 MZ_GC_VAR_IN_REG(0, self); 2248 2249 /* We need to handle deletion of buffers underneath us. 2250 * If we add a "b_mzscheme_ref" field to the buf_T structure, 2251 * then we can get at it in buf_freeall() in vim. 2252 */ 2253 if (buf->b_mzscheme_ref) 2254 return (Scheme_Object *)BUFFER_REF(buf); 2255 2256 MZ_GC_REG(); 2257 self = scheme_malloc_fail_ok(scheme_malloc_tagged, sizeof(vim_mz_buffer)); 2258 vim_memset(self, 0, sizeof(vim_mz_buffer)); 2259 #ifndef MZ_PRECISE_GC 2260 scheme_dont_gc_ptr(self); /* because buf isn't visible to GC */ 2261 #else 2262 buf->b_mzscheme_ref = scheme_malloc_immobile_box(NULL); 2263 #endif 2264 MZ_GC_CHECK(); 2265 BUFFER_REF(buf) = self; 2266 MZ_GC_CHECK(); 2267 self->buf = buf; 2268 self->so.type = mz_buffer_type; 2269 2270 MZ_GC_UNREG(); 2271 return (Scheme_Object *)self; 2272 } 2273 2274 /* 2275 * (get-buff-size [buffer]) 2276 * 2277 * Get the size (number of lines) in the current buffer. 2278 */ 2279 static Scheme_Object * 2280 get_buffer_size(void *data, int argc, Scheme_Object **argv) 2281 { 2282 Vim_Prim *prim = (Vim_Prim *)data; 2283 vim_mz_buffer *buf = get_buffer_arg(prim->name, 0, argc, argv); 2284 2285 return scheme_make_integer(buf->buf->b_ml.ml_line_count); 2286 } 2287 2288 /* 2289 * (get-buff-line {linenr} [buffer]) 2290 * 2291 * Get a line from the specified buffer. The line number is 2292 * in Vim format (1-based). The line is returned as a MzScheme 2293 * string object. 2294 */ 2295 static Scheme_Object * 2296 get_buffer_line(void *data, int argc, Scheme_Object **argv) 2297 { 2298 Vim_Prim *prim = (Vim_Prim *)data; 2299 vim_mz_buffer *buf; 2300 int linenr; 2301 char_u *line; 2302 2303 buf = get_buffer_arg(prim->name, 1, argc, argv); 2304 linenr = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2305 line = ml_get_buf(buf->buf, (linenr_T)linenr, FALSE); 2306 2307 raise_if_error(); 2308 return scheme_make_byte_string((char *)line); 2309 } 2310 2311 2312 /* 2313 * (get-buff-line-list {start} {end} [buffer]) 2314 * 2315 * Get a list of lines from the specified buffer. The line numbers 2316 * are in Vim format (1-based). The range is from lo up to, but not 2317 * including, hi. The list is returned as a list of string objects. 2318 */ 2319 static Scheme_Object * 2320 get_buffer_line_list(void *data, int argc, Scheme_Object **argv) 2321 { 2322 Vim_Prim *prim = (Vim_Prim *)data; 2323 vim_mz_buffer *buf; 2324 int i, hi, lo, n; 2325 Scheme_Object *list = NULL; 2326 2327 MZ_GC_DECL_REG(1); 2328 MZ_GC_VAR_IN_REG(0, list); 2329 MZ_GC_REG(); 2330 2331 buf = get_buffer_arg(prim->name, 2, argc, argv); 2332 list = scheme_null; 2333 hi = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 1)); 2334 lo = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2335 2336 /* 2337 * Handle some error conditions 2338 */ 2339 if (lo < 0) 2340 lo = 0; 2341 2342 if (hi < 0) 2343 hi = 0; 2344 if (hi < lo) 2345 hi = lo; 2346 2347 n = hi - lo; 2348 2349 for (i = n; i >= 0; --i) 2350 { 2351 Scheme_Object *str = scheme_make_byte_string( 2352 (char *)ml_get_buf(buf->buf, (linenr_T)(lo+i), FALSE)); 2353 raise_if_error(); 2354 2355 /* Set the list item */ 2356 list = scheme_make_pair(str, list); 2357 MZ_GC_CHECK(); 2358 } 2359 MZ_GC_UNREG(); 2360 return list; 2361 } 2362 2363 /* 2364 * (set-buff-line {linenr} {string/#f} [buffer]) 2365 * 2366 * Replace a line in the specified buffer. The line number is 2367 * in Vim format (1-based). The replacement line is given as 2368 * an MzScheme string object. The object is checked for validity 2369 * and correct format. An exception is thrown if the values are not 2370 * the correct format. 2371 * 2372 * It returns a Scheme Object that indicates the length of the 2373 * string changed. 2374 */ 2375 static Scheme_Object * 2376 set_buffer_line(void *data, int argc, Scheme_Object **argv) 2377 { 2378 /* First of all, we check the value of the supplied MzScheme object. 2379 * There are three cases: 2380 * 1. #f - this is a deletion. 2381 * 2. A string - this is a replacement. 2382 * 3. Anything else - this is an error. 2383 */ 2384 Vim_Prim *prim = (Vim_Prim *)data; 2385 vim_mz_buffer *buf; 2386 Scheme_Object *line = NULL; 2387 char *save; 2388 int n; 2389 2390 MZ_GC_DECL_REG(1); 2391 MZ_GC_VAR_IN_REG(0, line); 2392 MZ_GC_REG(); 2393 2394 #ifdef HAVE_SANDBOX 2395 sandbox_check(); 2396 #endif 2397 n = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2398 if (!SCHEME_STRINGP(argv[1]) && !SCHEME_FALSEP(argv[1])) 2399 scheme_wrong_type(prim->name, "string or #f", 1, argc, argv); 2400 line = argv[1]; 2401 buf = get_buffer_arg(prim->name, 2, argc, argv); 2402 2403 check_line_range(n, buf->buf); 2404 2405 if (SCHEME_FALSEP(line)) 2406 { 2407 buf_T *savebuf = curbuf; 2408 2409 curbuf = buf->buf; 2410 2411 if (u_savedel((linenr_T)n, 1L) == FAIL) 2412 { 2413 curbuf = savebuf; 2414 raise_vim_exn(_("cannot save undo information")); 2415 } 2416 else if (ml_delete((linenr_T)n, FALSE) == FAIL) 2417 { 2418 curbuf = savebuf; 2419 raise_vim_exn(_("cannot delete line")); 2420 } 2421 if (buf->buf == curwin->w_buffer) 2422 mz_fix_cursor(n, n + 1, -1); 2423 deleted_lines_mark((linenr_T)n, 1L); 2424 2425 curbuf = savebuf; 2426 2427 MZ_GC_UNREG(); 2428 raise_if_error(); 2429 return scheme_void; 2430 } 2431 else 2432 { 2433 /* Otherwise it's a line */ 2434 buf_T *savebuf = curbuf; 2435 2436 save = string_to_line(line); 2437 2438 curbuf = buf->buf; 2439 2440 if (u_savesub((linenr_T)n) == FAIL) 2441 { 2442 curbuf = savebuf; 2443 vim_free(save); 2444 raise_vim_exn(_("cannot save undo information")); 2445 } 2446 else if (ml_replace((linenr_T)n, (char_u *)save, TRUE) == FAIL) 2447 { 2448 curbuf = savebuf; 2449 vim_free(save); 2450 raise_vim_exn(_("cannot replace line")); 2451 } 2452 else 2453 { 2454 vim_free(save); 2455 changed_bytes((linenr_T)n, 0); 2456 } 2457 2458 curbuf = savebuf; 2459 2460 /* Check that the cursor is not beyond the end of the line now. */ 2461 if (buf->buf == curwin->w_buffer) 2462 check_cursor_col(); 2463 2464 MZ_GC_UNREG(); 2465 raise_if_error(); 2466 return scheme_void; 2467 } 2468 } 2469 2470 static void 2471 free_array(char **array) 2472 { 2473 char **curr = array; 2474 while (*curr != NULL) 2475 vim_free(*curr++); 2476 vim_free(array); 2477 } 2478 2479 /* 2480 * (set-buff-line-list {start} {end} {string-list/#f/null} [buffer]) 2481 * 2482 * Replace a range of lines in the specified buffer. The line numbers are in 2483 * Vim format (1-based). The range is from lo up to, but not including, hi. 2484 * The replacement lines are given as a Scheme list of string objects. The 2485 * list is checked for validity and correct format. 2486 * 2487 * Errors are returned as a value of FAIL. The return value is OK on success. 2488 * If OK is returned and len_change is not NULL, *len_change is set to the 2489 * change in the buffer length. 2490 */ 2491 static Scheme_Object * 2492 set_buffer_line_list(void *data, int argc, Scheme_Object **argv) 2493 { 2494 /* First of all, we check the type of the supplied MzScheme object. 2495 * There are three cases: 2496 * 1. #f - this is a deletion. 2497 * 2. A list - this is a replacement. 2498 * 3. Anything else - this is an error. 2499 */ 2500 Vim_Prim *prim = (Vim_Prim *)data; 2501 vim_mz_buffer *buf = NULL; 2502 Scheme_Object *line_list = NULL; 2503 int i, old_len, new_len, hi, lo; 2504 long extra; 2505 2506 MZ_GC_DECL_REG(1); 2507 MZ_GC_VAR_IN_REG(0, line_list); 2508 MZ_GC_REG(); 2509 2510 #ifdef HAVE_SANDBOX 2511 sandbox_check(); 2512 #endif 2513 lo = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2514 hi = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 1)); 2515 if (!SCHEME_PAIRP(argv[2]) 2516 && !SCHEME_FALSEP(argv[2]) && !SCHEME_NULLP(argv[2])) 2517 scheme_wrong_type(prim->name, "list or #f", 2, argc, argv); 2518 line_list = argv[2]; 2519 buf = get_buffer_arg(prim->name, 3, argc, argv); 2520 old_len = hi - lo; 2521 if (old_len < 0) /* process inverse values wisely */ 2522 { 2523 i = lo; 2524 lo = hi; 2525 hi = i; 2526 old_len = -old_len; 2527 } 2528 extra = 0; 2529 2530 check_line_range(lo, buf->buf); /* inclusive */ 2531 check_line_range(hi - 1, buf->buf); /* exclusive */ 2532 2533 if (SCHEME_FALSEP(line_list) || SCHEME_NULLP(line_list)) 2534 { 2535 buf_T *savebuf = curbuf; 2536 curbuf = buf->buf; 2537 2538 if (u_savedel((linenr_T)lo, (long)old_len) == FAIL) 2539 { 2540 curbuf = savebuf; 2541 raise_vim_exn(_("cannot save undo information")); 2542 } 2543 else 2544 { 2545 for (i = 0; i < old_len; i++) 2546 if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2547 { 2548 curbuf = savebuf; 2549 raise_vim_exn(_("cannot delete line")); 2550 } 2551 if (buf->buf == curwin->w_buffer) 2552 mz_fix_cursor(lo, hi, -old_len); 2553 deleted_lines_mark((linenr_T)lo, (long)old_len); 2554 } 2555 2556 curbuf = savebuf; 2557 2558 MZ_GC_UNREG(); 2559 raise_if_error(); 2560 return scheme_void; 2561 } 2562 else 2563 { 2564 buf_T *savebuf = curbuf; 2565 2566 /* List */ 2567 new_len = scheme_proper_list_length(line_list); 2568 MZ_GC_CHECK(); 2569 if (new_len < 0) /* improper or cyclic list */ 2570 scheme_wrong_type(prim->name, "proper list", 2571 2, argc, argv); 2572 else 2573 { 2574 char **array = NULL; 2575 Scheme_Object *line = NULL; 2576 Scheme_Object *rest = NULL; 2577 2578 MZ_GC_DECL_REG(2); 2579 MZ_GC_VAR_IN_REG(0, line); 2580 MZ_GC_VAR_IN_REG(1, rest); 2581 MZ_GC_REG(); 2582 2583 array = (char **)alloc((new_len+1)* sizeof(char *)); 2584 vim_memset(array, 0, (new_len+1) * sizeof(char *)); 2585 2586 rest = line_list; 2587 for (i = 0; i < new_len; ++i) 2588 { 2589 line = SCHEME_CAR(rest); 2590 rest = SCHEME_CDR(rest); 2591 if (!SCHEME_STRINGP(line)) 2592 { 2593 free_array(array); 2594 scheme_wrong_type(prim->name, "string-list", 2, argc, argv); 2595 } 2596 array[i] = string_to_line(line); 2597 } 2598 2599 curbuf = buf->buf; 2600 2601 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) 2602 { 2603 curbuf = savebuf; 2604 free_array(array); 2605 raise_vim_exn(_("cannot save undo information")); 2606 } 2607 2608 /* 2609 * If the size of the range is reducing (ie, new_len < old_len) we 2610 * need to delete some old_len. We do this at the start, by 2611 * repeatedly deleting line "lo". 2612 */ 2613 for (i = 0; i < old_len - new_len; ++i) 2614 { 2615 if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2616 { 2617 curbuf = savebuf; 2618 free_array(array); 2619 raise_vim_exn(_("cannot delete line")); 2620 } 2621 extra--; 2622 } 2623 2624 /* 2625 * For as long as possible, replace the existing old_len with the 2626 * new old_len. This is a more efficient operation, as it requires 2627 * less memory allocation and freeing. 2628 */ 2629 for (i = 0; i < old_len && i < new_len; i++) 2630 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], TRUE) == FAIL) 2631 { 2632 curbuf = savebuf; 2633 free_array(array); 2634 raise_vim_exn(_("cannot replace line")); 2635 } 2636 2637 /* 2638 * Now we may need to insert the remaining new_len. We don't need to 2639 * free the string passed back because MzScheme has control of that 2640 * memory. 2641 */ 2642 while (i < new_len) 2643 { 2644 if (ml_append((linenr_T)(lo + i - 1), 2645 (char_u *)array[i], 0, FALSE) == FAIL) 2646 { 2647 curbuf = savebuf; 2648 free_array(array); 2649 raise_vim_exn(_("cannot insert line")); 2650 } 2651 ++i; 2652 ++extra; 2653 } 2654 MZ_GC_UNREG(); 2655 free_array(array); 2656 } 2657 2658 /* 2659 * Adjust marks. Invalidate any which lie in the 2660 * changed range, and move any in the remainder of the buffer. 2661 */ 2662 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), 2663 (long)MAXLNUM, (long)extra); 2664 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); 2665 2666 if (buf->buf == curwin->w_buffer) 2667 mz_fix_cursor(lo, hi, extra); 2668 curbuf = savebuf; 2669 2670 MZ_GC_UNREG(); 2671 raise_if_error(); 2672 return scheme_void; 2673 } 2674 } 2675 2676 /* 2677 * (insert-buff-line-list {linenr} {string/string-list} [buffer]) 2678 * 2679 * Insert a number of lines into the specified buffer after the specified line. 2680 * The line number is in Vim format (1-based). The lines to be inserted are 2681 * given as an MzScheme list of string objects or as a single string. The lines 2682 * to be added are checked for validity and correct format. Errors are 2683 * returned as a value of FAIL. The return value is OK on success. 2684 * If OK is returned and len_change is not NULL, *len_change 2685 * is set to the change in the buffer length. 2686 */ 2687 static Scheme_Object * 2688 insert_buffer_line_list(void *data, int argc, Scheme_Object **argv) 2689 { 2690 Vim_Prim *prim = (Vim_Prim *)data; 2691 vim_mz_buffer *buf = NULL; 2692 Scheme_Object *list = NULL; 2693 char *str = NULL; 2694 int i, n, size; 2695 2696 MZ_GC_DECL_REG(1); 2697 MZ_GC_VAR_IN_REG(0, list); 2698 MZ_GC_REG(); 2699 2700 #ifdef HAVE_SANDBOX 2701 sandbox_check(); 2702 #endif 2703 /* 2704 * First of all, we check the type of the supplied MzScheme object. 2705 * It must be a string or a list, or the call is in error. 2706 */ 2707 n = SCHEME_INT_VAL(GUARANTEE_INTEGER(prim->name, 0)); 2708 list = argv[1]; 2709 2710 if (!SCHEME_STRINGP(list) && !SCHEME_PAIRP(list)) 2711 scheme_wrong_type(prim->name, "string or list", 1, argc, argv); 2712 buf = get_buffer_arg(prim->name, 2, argc, argv); 2713 2714 if (n != 0) /* 0 can be used in insert */ 2715 check_line_range(n, buf->buf); 2716 if (SCHEME_STRINGP(list)) 2717 { 2718 buf_T *savebuf = curbuf; 2719 2720 str = string_to_line(list); 2721 curbuf = buf->buf; 2722 2723 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL) 2724 { 2725 curbuf = savebuf; 2726 vim_free(str); 2727 raise_vim_exn(_("cannot save undo information")); 2728 } 2729 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL) 2730 { 2731 curbuf = savebuf; 2732 vim_free(str); 2733 raise_vim_exn(_("cannot insert line")); 2734 } 2735 else 2736 { 2737 vim_free(str); 2738 appended_lines_mark((linenr_T)n, 1L); 2739 } 2740 2741 curbuf = savebuf; 2742 update_screen(VALID); 2743 2744 MZ_GC_UNREG(); 2745 raise_if_error(); 2746 return scheme_void; 2747 } 2748 2749 /* List */ 2750 size = scheme_proper_list_length(list); 2751 MZ_GC_CHECK(); 2752 if (size < 0) /* improper or cyclic list */ 2753 scheme_wrong_type(prim->name, "proper list", 2754 2, argc, argv); 2755 else 2756 { 2757 Scheme_Object *line = NULL; 2758 Scheme_Object *rest = NULL; 2759 char **array; 2760 buf_T *savebuf = curbuf; 2761 2762 MZ_GC_DECL_REG(2); 2763 MZ_GC_VAR_IN_REG(0, line); 2764 MZ_GC_VAR_IN_REG(1, rest); 2765 MZ_GC_REG(); 2766 2767 array = (char **)alloc((size+1) * sizeof(char *)); 2768 vim_memset(array, 0, (size+1) * sizeof(char *)); 2769 2770 rest = list; 2771 for (i = 0; i < size; ++i) 2772 { 2773 line = SCHEME_CAR(rest); 2774 rest = SCHEME_CDR(rest); 2775 array[i] = string_to_line(line); 2776 } 2777 2778 curbuf = buf->buf; 2779 2780 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) 2781 { 2782 curbuf = savebuf; 2783 free_array(array); 2784 raise_vim_exn(_("cannot save undo information")); 2785 } 2786 else 2787 { 2788 for (i = 0; i < size; ++i) 2789 if (ml_append((linenr_T)(n + i), (char_u *)array[i], 2790 0, FALSE) == FAIL) 2791 { 2792 curbuf = savebuf; 2793 free_array(array); 2794 raise_vim_exn(_("cannot insert line")); 2795 } 2796 2797 if (i > 0) 2798 appended_lines_mark((linenr_T)n, (long)i); 2799 } 2800 free_array(array); 2801 MZ_GC_UNREG(); 2802 curbuf = savebuf; 2803 update_screen(VALID); 2804 } 2805 2806 MZ_GC_UNREG(); 2807 raise_if_error(); 2808 return scheme_void; 2809 } 2810 2811 /* 2812 * Predicates 2813 */ 2814 /* (buff? obj) */ 2815 static Scheme_Object * 2816 vim_bufferp(void *data UNUSED, int argc UNUSED, Scheme_Object **argv) 2817 { 2818 if (SCHEME_VIMBUFFERP(argv[0])) 2819 return scheme_true; 2820 else 2821 return scheme_false; 2822 } 2823 2824 /* (win? obj) */ 2825 static Scheme_Object * 2826 vim_windowp(void *data UNUSED, int argc UNUSED, Scheme_Object **argv) 2827 { 2828 if (SCHEME_VIMWINDOWP(argv[0])) 2829 return scheme_true; 2830 else 2831 return scheme_false; 2832 } 2833 2834 /* (buff-valid? obj) */ 2835 static Scheme_Object * 2836 vim_buffer_validp(void *data UNUSED, int argc UNUSED, Scheme_Object **argv) 2837 { 2838 if (SCHEME_VIMBUFFERP(argv[0]) 2839 && ((vim_mz_buffer *)argv[0])->buf != INVALID_BUFFER_VALUE) 2840 return scheme_true; 2841 else 2842 return scheme_false; 2843 } 2844 2845 /* (win-valid? obj) */ 2846 static Scheme_Object * 2847 vim_window_validp(void *data UNUSED, int argc UNUSED, Scheme_Object **argv) 2848 { 2849 if (SCHEME_VIMWINDOWP(argv[0]) 2850 && ((vim_mz_window *)argv[0])->win != INVALID_WINDOW_VALUE) 2851 return scheme_true; 2852 else 2853 return scheme_false; 2854 } 2855 2856 /* 2857 *=========================================================================== 2858 * Utilities 2859 *=========================================================================== 2860 */ 2861 2862 /* 2863 * Convert an MzScheme string into a Vim line. 2864 * 2865 * All internal nulls are replaced by newline characters. 2866 * It is an error for the string to contain newline characters. 2867 * 2868 * Returns pointer to Vim allocated memory 2869 */ 2870 static char * 2871 string_to_line(Scheme_Object *obj) 2872 { 2873 char *scheme_str = NULL; 2874 char *vim_str = NULL; 2875 OUTPUT_LEN_TYPE len; 2876 int i; 2877 2878 scheme_str = scheme_display_to_string(obj, &len); 2879 2880 /* Error checking: String must not contain newlines, as we 2881 * are replacing a single line, and we must replace it with 2882 * a single line. 2883 */ 2884 if (memchr(scheme_str, '\n', len)) 2885 scheme_signal_error(_("string cannot contain newlines")); 2886 2887 vim_str = (char *)alloc(len + 1); 2888 2889 /* Create a copy of the string, with internal nulls replaced by 2890 * newline characters, as is the vim convention. 2891 */ 2892 for (i = 0; i < len; ++i) 2893 { 2894 if (scheme_str[i] == '\0') 2895 vim_str[i] = '\n'; 2896 else 2897 vim_str[i] = scheme_str[i]; 2898 } 2899 2900 vim_str[i] = '\0'; 2901 2902 MZ_GC_CHECK(); 2903 return vim_str; 2904 } 2905 2906 #ifdef FEAT_EVAL 2907 /* 2908 * Convert Vim value into MzScheme, adopted from if_python.c 2909 */ 2910 static Scheme_Object * 2911 vim_to_mzscheme(typval_T *vim_value) 2912 { 2913 Scheme_Object *result = NULL; 2914 /* hash table to store visited values to avoid infinite loops */ 2915 Scheme_Hash_Table *visited = NULL; 2916 2917 MZ_GC_DECL_REG(2); 2918 MZ_GC_VAR_IN_REG(0, result); 2919 MZ_GC_VAR_IN_REG(1, visited); 2920 MZ_GC_REG(); 2921 2922 visited = scheme_make_hash_table(SCHEME_hash_ptr); 2923 MZ_GC_CHECK(); 2924 2925 result = vim_to_mzscheme_impl(vim_value, 1, visited); 2926 2927 MZ_GC_UNREG(); 2928 return result; 2929 } 2930 2931 static Scheme_Object * 2932 vim_to_mzscheme_impl(typval_T *vim_value, int depth, Scheme_Hash_Table *visited) 2933 { 2934 Scheme_Object *result = NULL; 2935 int new_value = TRUE; 2936 2937 MZ_GC_DECL_REG(2); 2938 MZ_GC_VAR_IN_REG(0, result); 2939 MZ_GC_VAR_IN_REG(1, visited); 2940 MZ_GC_REG(); 2941 2942 /* Avoid infinite recursion */ 2943 if (depth > 100) 2944 { 2945 MZ_GC_UNREG(); 2946 return scheme_void; 2947 } 2948 2949 /* Check if we run into a recursive loop. The item must be in visited 2950 * then and we can use it again. 2951 */ 2952 result = scheme_hash_get(visited, (Scheme_Object *)vim_value); 2953 MZ_GC_CHECK(); 2954 if (result != NULL) /* found, do nothing */ 2955 new_value = FALSE; 2956 else if (vim_value->v_type == VAR_STRING) 2957 { 2958 result = scheme_make_byte_string((char *)vim_value->vval.v_string); 2959 MZ_GC_CHECK(); 2960 } 2961 else if (vim_value->v_type == VAR_NUMBER) 2962 { 2963 result = scheme_make_integer((long)vim_value->vval.v_number); 2964 MZ_GC_CHECK(); 2965 } 2966 # ifdef FEAT_FLOAT 2967 else if (vim_value->v_type == VAR_FLOAT) 2968 { 2969 result = scheme_make_double((double)vim_value->vval.v_float); 2970 MZ_GC_CHECK(); 2971 } 2972 # endif 2973 else if (vim_value->v_type == VAR_LIST) 2974 { 2975 list_T *list = vim_value->vval.v_list; 2976 listitem_T *curr; 2977 2978 if (list == NULL || list->lv_first == NULL) 2979 result = scheme_null; 2980 else 2981 { 2982 Scheme_Object *obj = NULL; 2983 2984 MZ_GC_DECL_REG(1); 2985 MZ_GC_VAR_IN_REG(0, obj); 2986 MZ_GC_REG(); 2987 2988 curr = list->lv_last; 2989 obj = vim_to_mzscheme_impl(&curr->li_tv, depth + 1, visited); 2990 result = scheme_make_pair(obj, scheme_null); 2991 MZ_GC_CHECK(); 2992 2993 while (curr != list->lv_first) 2994 { 2995 curr = curr->li_prev; 2996 obj = vim_to_mzscheme_impl(&curr->li_tv, depth + 1, visited); 2997 result = scheme_make_pair(obj, result); 2998 MZ_GC_CHECK(); 2999 } 3000 } 3001 MZ_GC_UNREG(); 3002 } 3003 else if (vim_value->v_type == VAR_DICT) 3004 { 3005 Scheme_Object *key = NULL; 3006 Scheme_Object *obj = NULL; 3007 3008 MZ_GC_DECL_REG(2); 3009 MZ_GC_VAR_IN_REG(0, key); 3010 MZ_GC_VAR_IN_REG(1, obj); 3011 MZ_GC_REG(); 3012 3013 result = (Scheme_Object *)scheme_make_hash_table(SCHEME_hash_ptr); 3014 MZ_GC_CHECK(); 3015 if (vim_value->vval.v_dict != NULL) 3016 { 3017 hashtab_T *ht = &vim_value->vval.v_dict->dv_hashtab; 3018 long_u todo = ht->ht_used; 3019 hashitem_T *hi; 3020 dictitem_T *di; 3021 3022 for (hi = ht->ht_array; todo > 0; ++hi) 3023 { 3024 if (!HASHITEM_EMPTY(hi)) 3025 { 3026 --todo; 3027 3028 di = dict_lookup(hi); 3029 obj = vim_to_mzscheme_impl(&di->di_tv, depth + 1, visited); 3030 key = scheme_make_byte_string((char *)hi->hi_key); 3031 MZ_GC_CHECK(); 3032 scheme_hash_set((Scheme_Hash_Table *)result, key, obj); 3033 MZ_GC_CHECK(); 3034 } 3035 } 3036 } 3037 MZ_GC_UNREG(); 3038 } 3039 else if (vim_value->v_type == VAR_FUNC) 3040 { 3041 Scheme_Object *funcname = NULL; 3042 3043 MZ_GC_DECL_REG(1); 3044 MZ_GC_VAR_IN_REG(0, funcname); 3045 MZ_GC_REG(); 3046 3047 /* FIXME: func_ref() and func_unref() are needed. */ 3048 funcname = scheme_make_byte_string((char *)vim_value->vval.v_string); 3049 MZ_GC_CHECK(); 3050 result = scheme_make_closed_prim_w_arity(vim_funcref, funcname, 3051 (const char *)BYTE_STRING_VALUE(funcname), 0, -1); 3052 MZ_GC_CHECK(); 3053 3054 MZ_GC_UNREG(); 3055 } 3056 else if (vim_value->v_type == VAR_PARTIAL) 3057 { 3058 if (vim_value->vval.v_partial == NULL) 3059 result = scheme_null; 3060 else 3061 { 3062 Scheme_Object *funcname = NULL; 3063 3064 MZ_GC_DECL_REG(1); 3065 MZ_GC_VAR_IN_REG(0, funcname); 3066 MZ_GC_REG(); 3067 3068 /* FIXME: func_ref() and func_unref() are needed. */ 3069 /* TODO: Support pt_dict and pt_argv. */ 3070 funcname = scheme_make_byte_string( 3071 (char *)partial_name(vim_value->vval.v_partial)); 3072 MZ_GC_CHECK(); 3073 result = scheme_make_closed_prim_w_arity(vim_funcref, funcname, 3074 (const char *)BYTE_STRING_VALUE(funcname), 0, -1); 3075 MZ_GC_CHECK(); 3076 3077 MZ_GC_UNREG(); 3078 } 3079 } 3080 else if (vim_value->v_type == VAR_SPECIAL) 3081 { 3082 if (vim_value->vval.v_number <= VVAL_TRUE) 3083 result = scheme_make_integer((long)vim_value->vval.v_number); 3084 else 3085 result = scheme_null; 3086 MZ_GC_CHECK(); 3087 } 3088 else 3089 { 3090 result = scheme_void; 3091 new_value = FALSE; 3092 } 3093 if (new_value) 3094 { 3095 scheme_hash_set(visited, (Scheme_Object *)vim_value, result); 3096 MZ_GC_CHECK(); 3097 } 3098 MZ_GC_UNREG(); 3099 return result; 3100 } 3101 3102 static int 3103 mzscheme_to_vim(Scheme_Object *obj, typval_T *tv) 3104 { 3105 int i, status; 3106 Scheme_Hash_Table *visited = NULL; 3107 3108 MZ_GC_DECL_REG(2); 3109 MZ_GC_VAR_IN_REG(0, obj); 3110 MZ_GC_VAR_IN_REG(1, visited); 3111 MZ_GC_REG(); 3112 3113 visited = scheme_make_hash_table(SCHEME_hash_ptr); 3114 MZ_GC_CHECK(); 3115 3116 status = mzscheme_to_vim_impl(obj, tv, 1, visited); 3117 for (i = 0; i < visited->size; ++i) 3118 { 3119 /* free up remembered objects */ 3120 if (visited->vals[i] != NULL) 3121 free_tv((typval_T *)visited->vals[i]); 3122 } 3123 3124 MZ_GC_UNREG(); 3125 return status; 3126 } 3127 static int 3128 mzscheme_to_vim_impl(Scheme_Object *obj, typval_T *tv, int depth, 3129 Scheme_Hash_Table *visited) 3130 { 3131 int status = OK; 3132 typval_T *found; 3133 3134 MZ_GC_DECL_REG(2); 3135 MZ_GC_VAR_IN_REG(0, obj); 3136 MZ_GC_VAR_IN_REG(1, visited); 3137 MZ_GC_REG(); 3138 3139 MZ_GC_CHECK(); 3140 if (depth > 100) /* limit the deepest recursion level */ 3141 { 3142 tv->v_type = VAR_NUMBER; 3143 tv->vval.v_number = 0; 3144 return FAIL; 3145 } 3146 3147 found = (typval_T *)scheme_hash_get(visited, obj); 3148 if (found != NULL) 3149 copy_tv(found, tv); 3150 else if (SCHEME_VOIDP(obj)) 3151 { 3152 tv->v_type = VAR_SPECIAL; 3153 tv->vval.v_number = VVAL_NULL; 3154 } 3155 else if (SCHEME_INTP(obj)) 3156 { 3157 tv->v_type = VAR_NUMBER; 3158 tv->vval.v_number = SCHEME_INT_VAL(obj); 3159 } 3160 else if (SCHEME_BOOLP(obj)) 3161 { 3162 tv->v_type = VAR_SPECIAL; 3163 tv->vval.v_number = SCHEME_TRUEP(obj); 3164 } 3165 # ifdef FEAT_FLOAT 3166 else if (SCHEME_DBLP(obj)) 3167 { 3168 tv->v_type = VAR_FLOAT; 3169 tv->vval.v_float = SCHEME_DBL_VAL(obj); 3170 } 3171 # endif 3172 else if (SCHEME_BYTE_STRINGP(obj)) 3173 { 3174 tv->v_type = VAR_STRING; 3175 tv->vval.v_string = vim_strsave(BYTE_STRING_VALUE(obj)); 3176 } 3177 # if MZSCHEME_VERSION_MAJOR >= 299 3178 else if (SCHEME_CHAR_STRINGP(obj)) 3179 { 3180 Scheme_Object *tmp = NULL; 3181 MZ_GC_DECL_REG(1); 3182 MZ_GC_VAR_IN_REG(0, tmp); 3183 MZ_GC_REG(); 3184 3185 tmp = scheme_char_string_to_byte_string(obj); 3186 tv->v_type = VAR_STRING; 3187 tv->vval.v_string = vim_strsave(BYTE_STRING_VALUE(tmp)); 3188 MZ_GC_UNREG(); 3189 } 3190 #endif 3191 else if (SCHEME_VECTORP(obj) || SCHEME_NULLP(obj) 3192 || SCHEME_PAIRP(obj) || SCHEME_MUTABLE_PAIRP(obj)) 3193 { 3194 list_T *list = list_alloc(); 3195 if (list == NULL) 3196 status = FAIL; 3197 else 3198 { 3199 int i; 3200 Scheme_Object *curr = NULL; 3201 Scheme_Object *cval = NULL; 3202 /* temporary var to hold current element of vectors and pairs */ 3203 typval_T *v; 3204 3205 MZ_GC_DECL_REG(2); 3206 MZ_GC_VAR_IN_REG(0, curr); 3207 MZ_GC_VAR_IN_REG(1, cval); 3208 MZ_GC_REG(); 3209 3210 tv->v_type = VAR_LIST; 3211 tv->vval.v_list = list; 3212 ++list->lv_refcount; 3213 3214 v = (typval_T *)alloc(sizeof(typval_T)); 3215 if (v == NULL) 3216 status = FAIL; 3217 else 3218 { 3219 /* add the value in advance to allow handling of self-referential 3220 * data structures */ 3221 typval_T *visited_tv = (typval_T *)alloc(sizeof(typval_T)); 3222 copy_tv(tv, visited_tv); 3223 scheme_hash_set(visited, obj, (Scheme_Object *)visited_tv); 3224 3225 if (SCHEME_VECTORP(obj)) 3226 { 3227 for (i = 0; i < SCHEME_VEC_SIZE(obj); ++i) 3228 { 3229 cval = SCHEME_VEC_ELS(obj)[i]; 3230 status = mzscheme_to_vim_impl(cval, v, depth + 1, visited); 3231 if (status == FAIL) 3232 break; 3233 status = list_append_tv(list, v); 3234 clear_tv(v); 3235 if (status == FAIL) 3236 break; 3237 } 3238 } 3239 else if (SCHEME_PAIRP(obj) || SCHEME_MUTABLE_PAIRP(obj)) 3240 { 3241 for (curr = obj; 3242 SCHEME_PAIRP(curr) || SCHEME_MUTABLE_PAIRP(curr); 3243 curr = SCHEME_CDR(curr)) 3244 { 3245 cval = SCHEME_CAR(curr); 3246 status = mzscheme_to_vim_impl(cval, v, depth + 1, visited); 3247 if (status == FAIL) 3248 break; 3249 status = list_append_tv(list, v); 3250 clear_tv(v); 3251 if (status == FAIL) 3252 break; 3253 } 3254 /* improper list not terminated with null 3255 * need to handle the last element */ 3256 if (status == OK && !SCHEME_NULLP(curr)) 3257 { 3258 status = mzscheme_to_vim_impl(cval, v, depth + 1, visited); 3259 if (status == OK) 3260 { 3261 status = list_append_tv(list, v); 3262 clear_tv(v); 3263 } 3264 } 3265 } 3266 /* nothing to do for scheme_null */ 3267 vim_free(v); 3268 } 3269 MZ_GC_UNREG(); 3270 } 3271 } 3272 else if (SCHEME_HASHTP(obj)) 3273 { 3274 int i; 3275 dict_T *dict; 3276 Scheme_Object *key = NULL; 3277 Scheme_Object *val = NULL; 3278 3279 MZ_GC_DECL_REG(2); 3280 MZ_GC_VAR_IN_REG(0, key); 3281 MZ_GC_VAR_IN_REG(1, val); 3282 MZ_GC_REG(); 3283 3284 dict = dict_alloc(); 3285 if (dict == NULL) 3286 status = FAIL; 3287 else 3288 { 3289 typval_T *visited_tv = (typval_T *)alloc(sizeof(typval_T)); 3290 3291 tv->v_type = VAR_DICT; 3292 tv->vval.v_dict = dict; 3293 ++dict->dv_refcount; 3294 3295 copy_tv(tv, visited_tv); 3296 scheme_hash_set(visited, obj, (Scheme_Object *)visited_tv); 3297 3298 for (i = 0; i < ((Scheme_Hash_Table *)obj)->size; ++i) 3299 { 3300 if (((Scheme_Hash_Table *) obj)->vals[i] != NULL) 3301 { 3302 /* generate item for `display'ed Scheme key */ 3303 dictitem_T *item = dictitem_alloc((char_u *)string_to_line( 3304 ((Scheme_Hash_Table *) obj)->keys[i])); 3305 /* convert Scheme val to Vim and add it to the dict */ 3306 if (mzscheme_to_vim_impl(((Scheme_Hash_Table *) obj)->vals[i], 3307 &item->di_tv, depth + 1, visited) == FAIL 3308 || dict_add(dict, item) == FAIL) 3309 { 3310 dictitem_free(item); 3311 status = FAIL; 3312 break; 3313 } 3314 } 3315 3316 } 3317 } 3318 MZ_GC_UNREG(); 3319 } 3320 else 3321 { 3322 /* `display' any other value to string */ 3323 tv->v_type = VAR_STRING; 3324 tv->vval.v_string = (char_u *)string_to_line(obj); 3325 } 3326 MZ_GC_UNREG(); 3327 return status; 3328 } 3329 3330 /* Scheme prim procedure wrapping Vim funcref */ 3331 static Scheme_Object * 3332 vim_funcref(void *name, int argc, Scheme_Object **argv) 3333 { 3334 int i; 3335 typval_T args; 3336 int status = OK; 3337 Scheme_Object *result = NULL; 3338 list_T *list = list_alloc(); 3339 3340 MZ_GC_DECL_REG(1); 3341 MZ_GC_VAR_IN_REG(0, result); 3342 MZ_GC_REG(); 3343 3344 result = scheme_void; 3345 if (list == NULL) 3346 status = FAIL; 3347 else 3348 { 3349 args.v_type = VAR_LIST; 3350 args.vval.v_list = list; 3351 ++list->lv_refcount; 3352 for (i = 0; status == OK && i < argc; ++i) 3353 { 3354 typval_T *v = (typval_T *)alloc(sizeof(typval_T)); 3355 if (v == NULL) 3356 status = FAIL; 3357 else 3358 { 3359 status = mzscheme_to_vim(argv[i], v); 3360 if (status == OK) 3361 { 3362 status = list_append_tv(list, v); 3363 clear_tv(v); 3364 } 3365 vim_free(v); 3366 } 3367 } 3368 if (status == OK) 3369 { 3370 typval_T ret; 3371 ret.v_type = VAR_UNKNOWN; 3372 3373 mzscheme_call_vim(BYTE_STRING_VALUE((Scheme_Object *)name), &args, &ret); 3374 MZ_GC_CHECK(); 3375 result = vim_to_mzscheme(&ret); 3376 clear_tv(&ret); 3377 MZ_GC_CHECK(); 3378 } 3379 } 3380 clear_tv(&args); 3381 MZ_GC_UNREG(); 3382 if (status != OK) 3383 raise_vim_exn(_("error converting Scheme values to Vim")); 3384 else 3385 raise_if_error(); 3386 return result; 3387 } 3388 3389 void 3390 do_mzeval(char_u *str, typval_T *rettv) 3391 { 3392 Scheme_Object *ret = NULL; 3393 3394 MZ_GC_DECL_REG(1); 3395 MZ_GC_VAR_IN_REG(0, ret); 3396 MZ_GC_REG(); 3397 3398 if (mzscheme_init()) 3399 { 3400 MZ_GC_UNREG(); 3401 return; 3402 } 3403 3404 MZ_GC_CHECK(); 3405 if (eval_with_exn_handling(str, do_eval, &ret) == OK) 3406 mzscheme_to_vim(ret, rettv); 3407 3408 MZ_GC_UNREG(); 3409 } 3410 #endif 3411 3412 /* 3413 * Check to see whether a Vim error has been reported, or a keyboard 3414 * interrupt (from vim --> got_int) has been detected. 3415 */ 3416 static int 3417 vim_error_check(void) 3418 { 3419 return (got_int || did_emsg); 3420 } 3421 3422 /* 3423 * register Scheme exn:vim 3424 */ 3425 static void 3426 register_vim_exn(void) 3427 { 3428 int nc = 0; 3429 int i; 3430 Scheme_Object *struct_exn = NULL; 3431 Scheme_Object *exn_name = NULL; 3432 3433 MZ_GC_DECL_REG(2); 3434 MZ_GC_VAR_IN_REG(0, struct_exn); 3435 MZ_GC_VAR_IN_REG(1, exn_name); 3436 MZ_GC_REG(); 3437 3438 exn_name = scheme_intern_symbol("exn:vim"); 3439 MZ_GC_CHECK(); 3440 struct_exn = scheme_builtin_value("struct:exn"); 3441 MZ_GC_CHECK(); 3442 3443 if (vim_exn == NULL) 3444 vim_exn = scheme_make_struct_type(exn_name, 3445 struct_exn, NULL, 0, 0, NULL, NULL 3446 #if MZSCHEME_VERSION_MAJOR >= 299 3447 , NULL 3448 #endif 3449 ); 3450 3451 3452 { 3453 Scheme_Object **tmp = NULL; 3454 Scheme_Object *exn_names[5] = {NULL, NULL, NULL, NULL, NULL}; 3455 Scheme_Object *exn_values[5] = {NULL, NULL, NULL, NULL, NULL}; 3456 MZ_GC_DECL_REG(6); 3457 MZ_GC_ARRAY_VAR_IN_REG(0, exn_names, 5); 3458 MZ_GC_ARRAY_VAR_IN_REG(3, exn_values, 5); 3459 MZ_GC_REG(); 3460 3461 tmp = scheme_make_struct_names(exn_name, scheme_null, 0, &nc); 3462 mch_memmove(exn_names, tmp, nc * sizeof(Scheme_Object *)); 3463 MZ_GC_CHECK(); 3464 3465 tmp = scheme_make_struct_values(vim_exn, exn_names, nc, 0); 3466 mch_memmove(exn_values, tmp, nc * sizeof(Scheme_Object *)); 3467 MZ_GC_CHECK(); 3468 3469 for (i = 0; i < nc; i++) 3470 { 3471 scheme_add_global_symbol(exn_names[i], 3472 exn_values[i], environment); 3473 MZ_GC_CHECK(); 3474 } 3475 MZ_GC_UNREG(); 3476 } 3477 MZ_GC_UNREG(); 3478 } 3479 3480 /* 3481 * raise exn:vim, may be with additional info string 3482 */ 3483 void 3484 raise_vim_exn(const char *add_info) 3485 { 3486 char *fmt = _("Vim error: ~a"); 3487 Scheme_Object *argv[2] = {NULL, NULL}; 3488 Scheme_Object *exn = NULL; 3489 Scheme_Object *byte_string = NULL; 3490 3491 MZ_GC_DECL_REG(5); 3492 MZ_GC_ARRAY_VAR_IN_REG(0, argv, 2); 3493 MZ_GC_VAR_IN_REG(3, exn); 3494 MZ_GC_VAR_IN_REG(4, byte_string); 3495 MZ_GC_REG(); 3496 3497 if (add_info != NULL) 3498 { 3499 char *c_string = NULL; 3500 Scheme_Object *info = NULL; 3501 3502 MZ_GC_DECL_REG(3); 3503 MZ_GC_VAR_IN_REG(0, c_string); 3504 MZ_GC_VAR_IN_REG(2, info); 3505 MZ_GC_REG(); 3506 3507 info = scheme_make_byte_string(add_info); 3508 MZ_GC_CHECK(); 3509 c_string = scheme_format_utf8(fmt, (int)STRLEN(fmt), 1, &info, NULL); 3510 MZ_GC_CHECK(); 3511 byte_string = scheme_make_byte_string(c_string); 3512 MZ_GC_CHECK(); 3513 argv[0] = scheme_byte_string_to_char_string(byte_string); 3514 SCHEME_SET_IMMUTABLE(argv[0]); 3515 MZ_GC_UNREG(); 3516 } 3517 else 3518 { 3519 byte_string = scheme_make_byte_string(_("Vim error")); 3520 MZ_GC_CHECK(); 3521 argv[0] = scheme_byte_string_to_char_string(byte_string); 3522 MZ_GC_CHECK(); 3523 } 3524 MZ_GC_CHECK(); 3525 3526 #if MZSCHEME_VERSION_MAJOR < 360 3527 argv[1] = scheme_current_continuation_marks(); 3528 MZ_GC_CHECK(); 3529 #else 3530 argv[1] = scheme_current_continuation_marks(NULL); 3531 MZ_GC_CHECK(); 3532 #endif 3533 3534 exn = scheme_make_struct_instance(vim_exn, 2, argv); 3535 MZ_GC_CHECK(); 3536 scheme_raise(exn); 3537 MZ_GC_UNREG(); 3538 } 3539 3540 void 3541 raise_if_error(void) 3542 { 3543 if (vim_error_check()) 3544 raise_vim_exn(NULL); 3545 } 3546 3547 /* get buffer: 3548 * either current 3549 * or passed as argv[argnum] with checks 3550 */ 3551 static vim_mz_buffer * 3552 get_buffer_arg(const char *fname, int argnum, int argc, Scheme_Object **argv) 3553 { 3554 vim_mz_buffer *b; 3555 3556 if (argc < argnum + 1) 3557 return get_vim_curr_buffer(); 3558 if (!SCHEME_VIMBUFFERP(argv[argnum])) 3559 scheme_wrong_type(fname, "vim-buffer", argnum, argc, argv); 3560 b = (vim_mz_buffer *)argv[argnum]; 3561 (void)get_valid_buffer(argv[argnum]); 3562 return b; 3563 } 3564 3565 /* get window: 3566 * either current 3567 * or passed as argv[argnum] with checks 3568 */ 3569 static vim_mz_window * 3570 get_window_arg(const char *fname, int argnum, int argc, Scheme_Object **argv) 3571 { 3572 vim_mz_window *w; 3573 3574 if (argc < argnum + 1) 3575 return get_vim_curr_window(); 3576 w = (vim_mz_window *)argv[argnum]; 3577 if (!SCHEME_VIMWINDOWP(argv[argnum])) 3578 scheme_wrong_type(fname, "vim-window", argnum, argc, argv); 3579 (void)get_valid_window(argv[argnum]); 3580 return w; 3581 } 3582 3583 /* get valid Vim buffer from Scheme_Object* */ 3584 buf_T *get_valid_buffer(void *obj) 3585 { 3586 buf_T *buf = ((vim_mz_buffer *)obj)->buf; 3587 3588 if (buf == INVALID_BUFFER_VALUE) 3589 scheme_signal_error(_("buffer is invalid")); 3590 return buf; 3591 } 3592 3593 /* get valid Vim window from Scheme_Object* */ 3594 win_T *get_valid_window(void *obj) 3595 { 3596 win_T *win = ((vim_mz_window *)obj)->win; 3597 if (win == INVALID_WINDOW_VALUE) 3598 scheme_signal_error(_("window is invalid")); 3599 return win; 3600 } 3601 3602 int 3603 mzthreads_allowed(void) 3604 { 3605 return mz_threads_allow; 3606 } 3607 3608 static int 3609 line_in_range(linenr_T lnum, buf_T *buf) 3610 { 3611 return (lnum > 0 && lnum <= buf->b_ml.ml_line_count); 3612 } 3613 3614 static void 3615 check_line_range(linenr_T lnum, buf_T *buf) 3616 { 3617 if (!line_in_range(lnum, buf)) 3618 scheme_signal_error(_("linenr out of range")); 3619 } 3620 3621 /* 3622 * Check if deleting lines made the cursor position invalid 3623 * (or you'll get msg from Vim about invalid linenr). 3624 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if 3625 * deleted). Got from if_python.c 3626 */ 3627 static void 3628 mz_fix_cursor(int lo, int hi, int extra) 3629 { 3630 if (curwin->w_cursor.lnum >= lo) 3631 { 3632 /* Adjust the cursor position if it's in/after the changed 3633 * lines. */ 3634 if (curwin->w_cursor.lnum >= hi) 3635 { 3636 curwin->w_cursor.lnum += extra; 3637 check_cursor_col(); 3638 } 3639 else if (extra < 0) 3640 { 3641 curwin->w_cursor.lnum = lo; 3642 check_cursor(); 3643 } 3644 else 3645 check_cursor_col(); 3646 changed_cline_bef_curs(); 3647 } 3648 invalidate_botline(); 3649 } 3650 3651 static Vim_Prim prims[]= 3652 { 3653 /* 3654 * Buffer-related commands 3655 */ 3656 {get_buffer_line, "get-buff-line", 1, 2}, 3657 {set_buffer_line, "set-buff-line", 2, 3}, 3658 {get_buffer_line_list, "get-buff-line-list", 2, 3}, 3659 {get_buffer_name, "get-buff-name", 0, 1}, 3660 {get_buffer_num, "get-buff-num", 0, 1}, 3661 {get_buffer_size, "get-buff-size", 0, 1}, 3662 {set_buffer_line_list, "set-buff-line-list", 3, 4}, 3663 {insert_buffer_line_list, "insert-buff-line-list", 2, 3}, 3664 {get_curr_buffer, "curr-buff", 0, 0}, 3665 {get_buffer_count, "buff-count", 0, 0}, 3666 {get_next_buffer, "get-next-buff", 0, 1}, 3667 {get_prev_buffer, "get-prev-buff", 0, 1}, 3668 {mzscheme_open_buffer, "open-buff", 1, 1}, 3669 {get_buffer_by_name, "get-buff-by-name", 1, 1}, 3670 {get_buffer_by_num, "get-buff-by-num", 1, 1}, 3671 /* 3672 * Window-related commands 3673 */ 3674 {get_curr_win, "curr-win", 0, 0}, 3675 {get_window_count, "win-count", 0, 0}, 3676 {get_window_by_num, "get-win-by-num", 1, 1}, 3677 {get_window_num, "get-win-num", 0, 1}, 3678 {get_window_buffer, "get-win-buffer", 0, 1}, 3679 {get_window_height, "get-win-height", 0, 1}, 3680 {set_window_height, "set-win-height", 1, 2}, 3681 {get_window_width, "get-win-width", 0, 1}, 3682 {set_window_width, "set-win-width", 1, 2}, 3683 {get_cursor, "get-cursor", 0, 1}, 3684 {set_cursor, "set-cursor", 1, 2}, 3685 {get_window_list, "get-win-list", 0, 1}, 3686 /* 3687 * Vim-related commands 3688 */ 3689 {vim_command, "command", 1, 1}, 3690 {vim_eval, "eval", 1, 1}, 3691 {get_range_start, "range-start", 0, 0}, 3692 {get_range_end, "range-end", 0, 0}, 3693 {mzscheme_beep, "beep", 0, 0}, 3694 {get_option, "get-option", 1, 2}, 3695 {set_option, "set-option", 1, 2}, 3696 /* 3697 * small utilities 3698 */ 3699 {vim_bufferp, "buff?", 1, 1}, 3700 {vim_windowp, "win?", 1, 1}, 3701 {vim_buffer_validp, "buff-valid?", 1, 1}, 3702 {vim_window_validp, "win-valid?", 1, 1} 3703 }; 3704 3705 /* return MzScheme wrapper for curbuf */ 3706 static vim_mz_buffer * 3707 get_vim_curr_buffer(void) 3708 { 3709 if (curbuf->b_mzscheme_ref == NULL) 3710 return (vim_mz_buffer *)buffer_new(curbuf); 3711 else 3712 return BUFFER_REF(curbuf); 3713 } 3714 3715 /* return MzScheme wrapper for curwin */ 3716 static vim_mz_window * 3717 get_vim_curr_window(void) 3718 { 3719 if (curwin->w_mzscheme_ref == NULL) 3720 return (vim_mz_window *)window_new(curwin); 3721 else 3722 return WINDOW_REF(curwin); 3723 } 3724 3725 static void 3726 make_modules(void) 3727 { 3728 int i; 3729 Scheme_Env *mod = NULL; 3730 Scheme_Object *vimext_symbol = NULL; 3731 Scheme_Object *closed_prim = NULL; 3732 3733 MZ_GC_DECL_REG(3); 3734 MZ_GC_VAR_IN_REG(0, mod); 3735 MZ_GC_VAR_IN_REG(1, vimext_symbol); 3736 MZ_GC_VAR_IN_REG(2, closed_prim); 3737 MZ_GC_REG(); 3738 3739 vimext_symbol = scheme_intern_symbol("vimext"); 3740 MZ_GC_CHECK(); 3741 mod = scheme_primitive_module(vimext_symbol, environment); 3742 MZ_GC_CHECK(); 3743 /* all prims made closed so they can access their own names */ 3744 for (i = 0; i < (int)(sizeof(prims)/sizeof(prims[0])); i++) 3745 { 3746 Vim_Prim *prim = prims + i; 3747 closed_prim = scheme_make_closed_prim_w_arity(prim->prim, prim, prim->name, 3748 prim->mina, prim->maxa); 3749 scheme_add_global(prim->name, closed_prim, mod); 3750 MZ_GC_CHECK(); 3751 } 3752 scheme_finish_primitive_module(mod); 3753 MZ_GC_CHECK(); 3754 MZ_GC_UNREG(); 3755 } 3756 3757 #ifdef HAVE_SANDBOX 3758 static Scheme_Object *M_write = NULL; 3759 static Scheme_Object *M_read = NULL; 3760 static Scheme_Object *M_execute = NULL; 3761 static Scheme_Object *M_delete = NULL; 3762 3763 static void 3764 sandbox_check(void) 3765 { 3766 if (sandbox) 3767 raise_vim_exn(_("not allowed in the Vim sandbox")); 3768 } 3769 3770 /* security guards to force Vim's sandbox restrictions on MzScheme level */ 3771 static Scheme_Object * 3772 sandbox_file_guard(int argc UNUSED, Scheme_Object **argv) 3773 { 3774 if (sandbox) 3775 { 3776 Scheme_Object *requested_access = argv[2]; 3777 3778 if (M_write == NULL) 3779 { 3780 MZ_REGISTER_STATIC(M_write); 3781 M_write = scheme_intern_symbol("write"); 3782 MZ_GC_CHECK(); 3783 } 3784 if (M_read == NULL) 3785 { 3786 MZ_REGISTER_STATIC(M_read); 3787 M_read = scheme_intern_symbol("read"); 3788 MZ_GC_CHECK(); 3789 } 3790 if (M_execute == NULL) 3791 { 3792 MZ_REGISTER_STATIC(M_execute); 3793 M_execute = scheme_intern_symbol("execute"); 3794 MZ_GC_CHECK(); 3795 } 3796 if (M_delete == NULL) 3797 { 3798 MZ_REGISTER_STATIC(M_delete); 3799 M_delete = scheme_intern_symbol("delete"); 3800 MZ_GC_CHECK(); 3801 } 3802 3803 while (!SCHEME_NULLP(requested_access)) 3804 { 3805 Scheme_Object *item = SCHEME_CAR(requested_access); 3806 if (scheme_eq(item, M_write) || scheme_eq(item, M_read) 3807 || scheme_eq(item, M_execute) || scheme_eq(item, M_delete)) 3808 { 3809 raise_vim_exn(_("not allowed in the Vim sandbox")); 3810 } 3811 requested_access = SCHEME_CDR(requested_access); 3812 } 3813 } 3814 return scheme_void; 3815 } 3816 3817 static Scheme_Object * 3818 sandbox_network_guard(int argc UNUSED, Scheme_Object **argv UNUSED) 3819 { 3820 return scheme_void; 3821 } 3822 #endif 3823 3824 #endif 3825