To: vim_dev@googlegroups.com Subject: Patch 8.2.3215 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3215 Problem: Vim9: argument types are not checked at compile time. Solution: Add several more type checks. Sort the argument lists. (Yegappan Lakshmanan, closes #8626) Files: src/change.c, src/evalfunc.c, src/filepath.c, src/sound.c, src/testdir/test_gui.vim, src/testdir/test_vim9_builtin.vim, src/testing.c *** ../vim-8.2.3214/src/change.c 2021-07-13 22:21:39.581467722 +0200 --- src/change.c 2021-07-24 21:30:48.348129172 +0200 *************** *** 241,246 **** --- 241,249 ---- listener_T *lnr; buf_T *buf = curbuf; + if (in_vim9script() && check_for_opt_buffer_arg(argvars, 1) == FAIL) + return; + callback = get_callback(&argvars[0]); if (callback.cb_name == NULL) return; *** ../vim-8.2.3214/src/evalfunc.c 2021-07-24 16:16:11.542239515 +0200 --- src/evalfunc.c 2021-07-24 21:30:48.348129172 +0200 *************** *** 644,726 **** /* * Lists of functions that check the argument types of a builtin function. */ - static argcheck_T arg1_string[] = {arg_string}; - static argcheck_T arg1_number[] = {arg_number}; static argcheck_T arg1_bool[] = {arg_bool}; ! static argcheck_T arg1_list_any[] = {arg_list_any}; static argcheck_T arg1_dict_any[] = {arg_dict_any}; static argcheck_T arg1_job[] = {arg_job}; ! static argcheck_T arg1_buffer[] = {arg_buffer}; ! static argcheck_T arg1_lnum[] = {arg_lnum}; static argcheck_T arg1_list_number[] = {arg_list_number}; static argcheck_T arg1_list_string[] = {arg_list_string}; ! static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; ! static argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; static argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any}; static argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string}; ! static argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; ! static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict}; ! static argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; ! static argcheck_T arg1_dict_or_string[] = {arg_dict_any_or_string}; ! static argcheck_T arg1_buffer_or_dict_any[] = {arg_buffer_or_dict_any}; static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; ! static argcheck_T arg2_number[] = {arg_number, arg_number}; ! static argcheck_T arg2_string[] = {arg_string, arg_string}; ! static argcheck_T arg2_string_number[] = {arg_string, arg_number}; ! static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; ! static argcheck_T arg2_string_list_nr[] = {arg_string, arg_list_number}; ! static argcheck_T arg2_string_bool[] = {arg_string, arg_bool}; ! static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; ! static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr}; ! static argcheck_T arg2_string_chan_or_job[] = {arg_string, arg_chan_or_job}; static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number}; static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool}; ! static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string}; ! static argcheck_T arg2_list_any_number[] = {arg_list_any, arg_number}; ! static argcheck_T arg2_number_string[] = {arg_number, arg_string}; static argcheck_T arg2_number_bool[] = {arg_number, arg_bool}; - static argcheck_T arg2_number_list[] = {arg_number, arg_list_any}; static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any}; static argcheck_T arg2_number_string_or_list[] = {arg_number, arg_string_or_list_any}; - static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string}; - static argcheck_T arg2_dict_any_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; - static argcheck_T arg2_job_dict[] = {arg_job, arg_dict_any}; - static argcheck_T arg2_job_string_or_number[] = {arg_job, arg_string_or_nr}; - static argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; ! static argcheck_T arg2_lnum[] = {arg_lnum, arg_lnum}; ! static argcheck_T arg2_lnum_number[] = {arg_lnum, arg_number}; ! static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any}; ! static argcheck_T arg2_chan_or_job_string[] = {arg_chan_or_job, arg_string}; ! static argcheck_T arg2_buffer_string[] = {arg_buffer, arg_string}; ! static argcheck_T arg2_buffer_number[] = {arg_buffer, arg_number}; ! static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool}; ! static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum}; ! static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any}; ! static argcheck_T arg2_buffer_any[] = {arg_buffer, NULL}; ! static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any}; - static argcheck_T arg3_number_string_string[] = {arg_number, arg_string, arg_string}; static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL}; static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer}; ! static argcheck_T arg3_number_any_dict[] = {arg_number, NULL, arg_dict_any}; ! static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; ! static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; ! static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; ! static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool}; static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool}; static argcheck_T arg3_string_bool_dict[] = {arg_string, arg_bool, arg_dict_any}; ! static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any}; ! static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number}; ! static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool}; ! static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum}; ! static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number}; ! static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any}; ! static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, NULL}; static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL}; static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string}; static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number, arg_number, arg_number}; static argcheck_T arg4_browse[] = {arg_bool, arg_string, arg_string, arg_string}; static argcheck_T arg23_chanexpr[] = {arg_chan_or_job, NULL, arg_dict_any}; static argcheck_T arg23_chanraw[] = {arg_chan_or_job, arg_string_or_blob, arg_dict_any}; --- 644,734 ---- /* * Lists of functions that check the argument types of a builtin function. */ static argcheck_T arg1_bool[] = {arg_bool}; ! static argcheck_T arg1_buffer[] = {arg_buffer}; ! static argcheck_T arg1_buffer_or_dict_any[] = {arg_buffer_or_dict_any}; ! static argcheck_T arg1_chan_or_job[] = {arg_chan_or_job}; static argcheck_T arg1_dict_any[] = {arg_dict_any}; + static argcheck_T arg1_dict_or_string[] = {arg_dict_any_or_string}; + static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; static argcheck_T arg1_job[] = {arg_job}; ! static argcheck_T arg1_list_any[] = {arg_list_any}; static argcheck_T arg1_list_number[] = {arg_list_number}; + static argcheck_T arg1_list_or_blob[] = {arg_list_or_blob}; + static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict}; static argcheck_T arg1_list_string[] = {arg_list_string}; ! static argcheck_T arg1_lnum[] = {arg_lnum}; ! static argcheck_T arg1_number[] = {arg_number}; ! static argcheck_T arg1_string[] = {arg_string}; static argcheck_T arg1_string_or_list_any[] = {arg_string_or_list_any}; static argcheck_T arg1_string_or_list_string[] = {arg_string_or_list_string}; ! static argcheck_T arg1_string_or_nr[] = {arg_string_or_nr}; ! static argcheck_T arg2_any_buffer[] = {NULL, arg_buffer}; ! static argcheck_T arg2_buffer_any[] = {arg_buffer, NULL}; ! static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool}; ! static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any}; ! static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum}; ! static argcheck_T arg2_buffer_number[] = {arg_buffer, arg_number}; ! static argcheck_T arg2_buffer_string[] = {arg_buffer, arg_string}; ! static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any}; ! static argcheck_T arg2_chan_or_job_string[] = {arg_chan_or_job, arg_string}; ! static argcheck_T arg2_dict_any_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; ! static argcheck_T arg2_dict_string[] = {arg_dict_any, arg_string}; static argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr}; ! static argcheck_T arg2_job_dict[] = {arg_job, arg_dict_any}; ! static argcheck_T arg2_job_string_or_number[] = {arg_job, arg_string_or_nr}; ! static argcheck_T arg2_list_any_number[] = {arg_list_any, arg_number}; ! static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string}; static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number}; static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool}; ! static argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; ! static argcheck_T arg2_lnum[] = {arg_lnum, arg_lnum}; ! static argcheck_T arg2_lnum_number[] = {arg_lnum, arg_number}; ! static argcheck_T arg2_number[] = {arg_number, arg_number}; static argcheck_T arg2_number_bool[] = {arg_number, arg_bool}; static argcheck_T arg2_number_dict_any[] = {arg_number, arg_dict_any}; + static argcheck_T arg2_number_list[] = {arg_number, arg_list_any}; + static argcheck_T arg2_number_string[] = {arg_number, arg_string}; static argcheck_T arg2_number_string_or_list[] = {arg_number, arg_string_or_list_any}; static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; ! static argcheck_T arg2_string[] = {arg_string, arg_string}; ! static argcheck_T arg2_string_any[] = {arg_string, NULL}; ! static argcheck_T arg2_string_bool[] = {arg_string, arg_bool}; ! static argcheck_T arg2_string_chan_or_job[] = {arg_string, arg_chan_or_job}; ! static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; ! static argcheck_T arg2_string_list_number[] = {arg_string, arg_list_number}; ! static argcheck_T arg2_string_number[] = {arg_string, arg_number}; ! static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; ! static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr}; ! static argcheck_T arg3_any_list_dict[] = {NULL, arg_list_any, arg_dict_any}; ! static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum}; ! static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number}; ! static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, NULL}; ! static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any}; ! static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number}; ! static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any}; ! static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool}; static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; + static argcheck_T arg3_number_any_dict[] = {arg_number, NULL, arg_dict_any}; static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any}; static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL}; static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer}; ! static argcheck_T arg3_number_string_string[] = {arg_number, arg_string, arg_string}; ! static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; ! static argcheck_T arg3_string_any_dict[] = {arg_string, NULL, arg_dict_any}; static argcheck_T arg3_string_bool_bool[] = {arg_string, arg_bool, arg_bool}; static argcheck_T arg3_string_bool_dict[] = {arg_string, arg_bool, arg_dict_any}; ! static argcheck_T arg3_string_number_bool[] = {arg_string, arg_number, arg_bool}; ! static argcheck_T arg3_string_number_number[] = {arg_string, arg_number, arg_number}; ! static argcheck_T arg3_string_string_bool[] = {arg_string, arg_string, arg_bool}; ! static argcheck_T arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; ! static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; ! static argcheck_T arg4_list_number_number_number[] = {arg_list_string, arg_number, arg_number, arg_number}; static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL}; + static argcheck_T arg4_string_string_any_string[] = {arg_string, arg_string, NULL, arg_string}; static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string}; static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number, arg_number, arg_number}; + /* Function specific argument types (not covered by the above) */ static argcheck_T arg4_browse[] = {arg_bool, arg_string, arg_string, arg_string}; static argcheck_T arg23_chanexpr[] = {arg_chan_or_job, NULL, arg_dict_any}; static argcheck_T arg23_chanraw[] = {arg_chan_or_job, arg_string_or_blob, arg_dict_any}; *************** *** 734,741 **** static argcheck_T arg25_globpath[] = {arg_string, arg_string, arg_bool, arg_bool, arg_bool}; static argcheck_T arg24_index[] = {arg_list_or_blob, arg_item_of_prev, arg_number, arg_bool}; static argcheck_T arg23_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; ! static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL}; static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool}; static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any}; static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any}; static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL}; --- 742,750 ---- static argcheck_T arg25_globpath[] = {arg_string, arg_string, arg_bool, arg_bool, arg_bool}; static argcheck_T arg24_index[] = {arg_list_or_blob, arg_item_of_prev, arg_number, arg_bool}; static argcheck_T arg23_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; ! static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr}; static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool}; + static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL}; static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any}; static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any}; static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL}; *************** *** 1138,1144 **** ret_number, f_byteidx}, {"byteidxcomp", 2, 2, FEARG_1, arg2_string_number, ret_number, f_byteidxcomp}, ! {"call", 2, 3, FEARG_1, NULL, ret_any, f_call}, {"ceil", 1, 1, FEARG_1, arg1_float_or_nr, ret_float, FLOAT_FUNC(f_ceil)}, --- 1147,1153 ---- ret_number, f_byteidx}, {"byteidxcomp", 2, 2, FEARG_1, arg2_string_number, ret_number, f_byteidxcomp}, ! {"call", 2, 3, FEARG_1, arg3_any_list_dict, ret_any, f_call}, {"ceil", 1, 1, FEARG_1, arg1_float_or_nr, ret_float, FLOAT_FUNC(f_ceil)}, *************** *** 1186,1192 **** ret_number, f_charclass}, {"charcol", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_charcol}, ! {"charidx", 2, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_charidx}, {"chdir", 1, 1, FEARG_1, arg1_string, ret_string, f_chdir}, --- 1195,1201 ---- ret_number, f_charclass}, {"charcol", 1, 1, FEARG_1, arg1_string_or_list_any, ret_number, f_charcol}, ! {"charidx", 2, 3, FEARG_1, arg3_string_number_bool, ret_number, f_charidx}, {"chdir", 1, 1, FEARG_1, arg1_string, ret_string, f_chdir}, *************** *** 1310,1318 **** ret_void, f_foreground}, {"fullcommand", 1, 1, FEARG_1, arg1_string, ret_string, f_fullcommand}, ! {"funcref", 1, 3, FEARG_1, NULL, ret_func_any, f_funcref}, ! {"function", 1, 3, FEARG_1, NULL, ret_f_function, f_function}, {"garbagecollect", 0, 1, 0, arg1_bool, ret_void, f_garbagecollect}, --- 1319,1327 ---- ret_void, f_foreground}, {"fullcommand", 1, 1, FEARG_1, arg1_string, ret_string, f_fullcommand}, ! {"funcref", 1, 3, FEARG_1, arg3_any_list_dict, ret_func_any, f_funcref}, ! {"function", 1, 3, FEARG_1, arg3_any_list_dict, ret_f_function, f_function}, {"garbagecollect", 0, 1, 0, arg1_bool, ret_void, f_garbagecollect}, *************** *** 1508,1516 **** ret_number, f_last_buffer_nr}, {"len", 1, 1, FEARG_1, NULL, ret_number, f_len}, ! {"libcall", 3, 3, FEARG_3, NULL, ret_string, f_libcall}, ! {"libcallnr", 3, 3, FEARG_3, NULL, ret_number, f_libcallnr}, {"line", 1, 2, FEARG_1, arg2_string_number, ret_number, f_line}, --- 1517,1525 ---- ret_number, f_last_buffer_nr}, {"len", 1, 1, FEARG_1, NULL, ret_number, f_len}, ! {"libcall", 3, 3, FEARG_3, arg3_libcall, ret_string, f_libcall}, ! {"libcallnr", 3, 3, FEARG_3, arg3_libcall, ret_number, f_libcallnr}, {"line", 1, 2, FEARG_1, arg2_string_number, ret_number, f_line}, *************** *** 1520,1526 **** ret_number, f_lispindent}, {"list2str", 1, 2, FEARG_1, arg2_list_number_bool, ret_string, f_list2str}, ! {"listener_add", 1, 2, FEARG_2, NULL, ret_number, f_listener_add}, {"listener_flush", 0, 1, FEARG_1, arg1_buffer, ret_void, f_listener_flush}, --- 1529,1535 ---- ret_number, f_lispindent}, {"list2str", 1, 2, FEARG_1, arg2_list_number_bool, ret_string, f_list2str}, ! {"listener_add", 1, 2, FEARG_2, arg2_any_buffer, ret_number, f_listener_add}, {"listener_flush", 0, 1, FEARG_1, arg1_buffer, ret_void, f_listener_flush}, *************** *** 1722,1730 **** ret_list_number, f_range}, {"readblob", 1, 1, FEARG_1, arg1_string, ret_blob, f_readblob}, ! {"readdir", 1, 3, FEARG_1, NULL, ret_list_string, f_readdir}, ! {"readdirex", 1, 3, FEARG_1, NULL, ret_list_dict_any, f_readdirex}, {"readfile", 1, 3, FEARG_1, arg3_string_string_nr, ret_list_string, f_readfile}, --- 1731,1739 ---- ret_list_number, f_range}, {"readblob", 1, 1, FEARG_1, arg1_string, ret_blob, f_readblob}, ! {"readdir", 1, 3, FEARG_1, arg3_string_any_dict, ret_list_string, f_readdir}, ! {"readdirex", 1, 3, FEARG_1, arg3_string_any_dict, ret_list_dict_any, f_readdirex}, {"readfile", 1, 3, FEARG_1, arg3_string_string_nr, ret_list_string, f_readfile}, *************** *** 1808,1814 **** ret_void, f_setbufvar}, {"setcellwidths", 1, 1, FEARG_1, arg1_list_any, ret_void, f_setcellwidths}, ! {"setcharpos", 2, 2, FEARG_2, arg2_string_list_nr, ret_number_bool, f_setcharpos}, {"setcharsearch", 1, 1, FEARG_1, arg1_dict_any, ret_void, f_setcharsearch}, --- 1817,1823 ---- ret_void, f_setbufvar}, {"setcellwidths", 1, 1, FEARG_1, arg1_list_any, ret_void, f_setcellwidths}, ! {"setcharpos", 2, 2, FEARG_2, arg2_string_list_number, ret_number_bool, f_setcharpos}, {"setcharsearch", 1, 1, FEARG_1, arg1_dict_any, ret_void, f_setcharsearch}, *************** *** 1830,1836 **** ret_number_bool, f_setloclist}, {"setmatches", 1, 2, FEARG_1, arg2_list_any_number, ret_number_bool, f_setmatches}, ! {"setpos", 2, 2, FEARG_2, arg2_string_list_nr, ret_number_bool, f_setpos}, {"setqflist", 1, 3, FEARG_1, arg13_setqflist, ret_number_bool, f_setqflist}, --- 1839,1845 ---- ret_number_bool, f_setloclist}, {"setmatches", 1, 2, FEARG_1, arg2_list_any_number, ret_number_bool, f_setmatches}, ! {"setpos", 2, 2, FEARG_2, arg2_string_list_number, ret_number_bool, f_setpos}, {"setqflist", 1, 3, FEARG_1, arg13_setqflist, ret_number_bool, f_setqflist}, *************** *** 1886,1894 **** ret_first_arg, f_sort}, {"sound_clear", 0, 0, 0, NULL, ret_void, SOUND_FUNC(f_sound_clear)}, ! {"sound_playevent", 1, 2, FEARG_1, NULL, ret_number, SOUND_FUNC(f_sound_playevent)}, ! {"sound_playfile", 1, 2, FEARG_1, NULL, ret_number, SOUND_FUNC(f_sound_playfile)}, {"sound_stop", 1, 1, FEARG_1, arg1_number, ret_void, SOUND_FUNC(f_sound_stop)}, --- 1895,1903 ---- ret_first_arg, f_sort}, {"sound_clear", 0, 0, 0, NULL, ret_void, SOUND_FUNC(f_sound_clear)}, ! {"sound_playevent", 1, 2, FEARG_1, arg2_string_any, ret_number, SOUND_FUNC(f_sound_playevent)}, ! {"sound_playfile", 1, 2, FEARG_1, arg2_string_any, ret_number, SOUND_FUNC(f_sound_playfile)}, {"sound_stop", 1, 1, FEARG_1, arg1_number, ret_void, SOUND_FUNC(f_sound_stop)}, *************** *** 1896,1902 **** ret_string, f_soundfold}, {"spellbadword", 0, 1, FEARG_1, arg1_string, ret_list_string, f_spellbadword}, ! {"spellsuggest", 1, 3, FEARG_1, arg3_string_nr_bool, ret_list_string, f_spellsuggest}, {"split", 1, 3, FEARG_1, arg3_string_string_bool, ret_list_string, f_split}, --- 1905,1911 ---- ret_string, f_soundfold}, {"spellbadword", 0, 1, FEARG_1, arg1_string, ret_list_string, f_spellbadword}, ! {"spellsuggest", 1, 3, FEARG_1, arg3_string_number_bool, ret_list_string, f_spellsuggest}, {"split", 1, 3, FEARG_1, arg3_string_string_bool, ret_list_string, f_split}, *************** *** 1910,1916 **** ret_float, FLOAT_FUNC(f_str2float)}, {"str2list", 1, 2, FEARG_1, arg2_string_bool, ret_list_number, f_str2list}, ! {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, {"strcharlen", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_strcharlen}, --- 1919,1925 ---- ret_float, FLOAT_FUNC(f_str2float)}, {"str2list", 1, 2, FEARG_1, arg2_string_bool, ret_list_number, f_str2list}, ! {"str2nr", 1, 3, FEARG_1, arg3_string_number_bool, ret_number, f_str2nr}, {"strcharlen", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_strcharlen}, *************** *** 1954,1960 **** ret_number, f_strwidth}, {"submatch", 1, 2, FEARG_1, arg2_number_bool, ret_string, f_submatch}, ! {"substitute", 4, 4, FEARG_1, NULL, ret_string, f_substitute}, {"swapinfo", 1, 1, FEARG_1, arg1_string, ret_dict_any, f_swapinfo}, --- 1963,1969 ---- ret_number, f_strwidth}, {"submatch", 1, 2, FEARG_1, arg2_number_bool, ret_string, f_submatch}, ! {"substitute", 4, 4, FEARG_1, arg4_string_string_any_string, ret_string, f_substitute}, {"swapinfo", 1, 1, FEARG_1, arg1_string, ret_dict_any, f_swapinfo}, *************** *** 2064,2070 **** ret_void, f_test_garbagecollect_soon}, {"test_getvalue", 1, 1, FEARG_1, arg1_string, ret_number, f_test_getvalue}, ! {"test_gui_drop_files", 4, 4, 0, NULL, ret_void, f_test_gui_drop_files}, {"test_gui_mouse_event", 5, 5, 0, arg5_number, ret_void, f_test_gui_mouse_event}, --- 2073,2079 ---- ret_void, f_test_garbagecollect_soon}, {"test_getvalue", 1, 1, FEARG_1, arg1_string, ret_number, f_test_getvalue}, ! {"test_gui_drop_files", 4, 4, 0, arg4_list_number_number_number, ret_void, f_test_gui_drop_files}, {"test_gui_mouse_event", 5, 5, 0, arg5_number, ret_void, f_test_gui_mouse_event}, *************** *** 2092,2098 **** ret_void, f_test_override}, {"test_refcount", 1, 1, FEARG_1, NULL, ret_number, f_test_refcount}, ! {"test_scrollbar", 3, 3, FEARG_2, NULL, ret_void, #ifdef FEAT_GUI f_test_scrollbar --- 2101,2107 ---- ret_void, f_test_override}, {"test_refcount", 1, 1, FEARG_1, NULL, ret_number, f_test_refcount}, ! {"test_scrollbar", 3, 3, FEARG_2, arg3_string_number_number, ret_void, #ifdef FEAT_GUI f_test_scrollbar *************** *** 2682,2687 **** --- 2691,2701 ---- partial_T *partial = NULL; dict_T *selfdict = NULL; + if (in_vim9script() + && (check_for_list_arg(argvars, 1) == FAIL + || check_for_opt_dict_arg(argvars, 2) == FAIL)) + return; + if (argvars[1].v_type != VAR_LIST) { emsg(_(e_listreq)); *************** *** 3734,3739 **** --- 3748,3759 ---- char_u *trans_name = NULL; int is_global = FALSE; + if (in_vim9script() + && (check_for_opt_list_arg(argvars, 1) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_opt_dict_arg(argvars, 2) == FAIL))) + return; + if (argvars[0].v_type == VAR_FUNC) { // function(MyFunc, [arg], dict) *************** *** 6417,6422 **** --- 6437,6448 ---- if (check_restricted() || check_secure()) return; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL + || check_for_string_or_number_arg(argvars, 2) == FAIL)) + return; + #ifdef FEAT_LIBCALL // The first two args must be strings, otherwise it's meaningless if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING) *************** *** 9177,9188 **** char_u patbuf[NUMBUFLEN]; char_u subbuf[NUMBUFLEN]; char_u flagsbuf[NUMBUFLEN]; ! ! char_u *str = tv_get_string_chk(&argvars[0]); ! char_u *pat = tv_get_string_buf_chk(&argvars[1], patbuf); char_u *sub = NULL; typval_T *expr = NULL; ! char_u *flg = tv_get_string_buf_chk(&argvars[3], flagsbuf); if (argvars[2].v_type == VAR_FUNC || argvars[2].v_type == VAR_PARTIAL) expr = &argvars[2]; --- 9203,9223 ---- char_u patbuf[NUMBUFLEN]; char_u subbuf[NUMBUFLEN]; char_u flagsbuf[NUMBUFLEN]; ! char_u *str; ! char_u *pat; char_u *sub = NULL; typval_T *expr = NULL; ! char_u *flg; ! ! if (in_vim9script() ! && (check_for_string_arg(argvars, 0) == FAIL ! || check_for_string_arg(argvars, 1) == FAIL ! || check_for_string_arg(argvars, 3) == FAIL)) ! return; ! ! str = tv_get_string_chk(&argvars[0]); ! pat = tv_get_string_buf_chk(&argvars[1], patbuf); ! flg = tv_get_string_buf_chk(&argvars[3], flagsbuf); if (argvars[2].v_type == VAR_FUNC || argvars[2].v_type == VAR_PARTIAL) expr = &argvars[2]; *** ../vim-8.2.3214/src/filepath.c 2021-07-23 20:37:52.018322443 +0200 --- src/filepath.c 2021-07-24 21:30:48.348129172 +0200 *************** *** 1602,1607 **** --- 1602,1614 ---- if (rettv_list_alloc(rettv) == FAIL) return; + + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_opt_dict_arg(argvars, 2) == FAIL))) + return; + path = tv_get_string(&argvars[0]); expr = &argvars[1]; *************** *** 1648,1653 **** --- 1655,1667 ---- if (rettv_list_alloc(rettv) == FAIL) return; + + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_opt_dict_arg(argvars, 2) == FAIL))) + return; + path = tv_get_string(&argvars[0]); expr = &argvars[1]; *** ../vim-8.2.3214/src/sound.c 2021-06-07 20:28:41.881591603 +0200 --- src/sound.c 2021-07-24 21:30:48.348129172 +0200 *************** *** 179,184 **** --- 179,187 ---- static void sound_play_common(typval_T *argvars, typval_T *rettv, int playfile) { + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + if (context == NULL) ca_context_create(&context); if (context != NULL) *************** *** 351,356 **** --- 354,362 ---- { WCHAR *wp; + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + wp = enc_to_utf16(tv_get_string(&argvars[0]), NULL); if (wp == NULL) return; *************** *** 371,376 **** --- 377,385 ---- char buf[32]; MCIERROR err; + if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) + return; + esc = vim_strsave_shellescape(tv_get_string(&argvars[0]), FALSE, FALSE); len = STRLEN(esc) + 5 + 18 + 1; *** ../vim-8.2.3214/src/testdir/test_gui.vim 2021-07-20 17:51:48.247744104 +0200 --- src/testdir/test_gui.vim 2021-07-24 21:30:48.348129172 +0200 *************** *** 1172,1181 **** func Test_gui_drop_files() CheckFeature drop_file ! call assert_fails('call test_gui_drop_files(1, 1, 1, 0)', 'E474:') ! call assert_fails('call test_gui_drop_files(["x"], "", 1, 0)', 'E474:') ! call assert_fails('call test_gui_drop_files(["x"], 1, "", 0)', 'E474:') ! call assert_fails('call test_gui_drop_files(["x"], 1, 1, "")', 'E474:') %bw! %argdelete --- 1172,1181 ---- func Test_gui_drop_files() CheckFeature drop_file ! call assert_fails('call test_gui_drop_files(1, 1, 1, 0)', 'E1211:') ! call assert_fails('call test_gui_drop_files(["x"], "", 1, 0)', 'E1210:') ! call assert_fails('call test_gui_drop_files(["x"], 1, "", 0)', 'E1210:') ! call assert_fails('call test_gui_drop_files(["x"], 1, 1, "")', 'E1210:') %bw! %argdelete *** ../vim-8.2.3214/src/testdir/test_vim9_builtin.vim 2021-07-24 16:16:11.542239515 +0200 --- src/testdir/test_vim9_builtin.vim 2021-07-24 21:30:48.348129172 +0200 *************** *** 373,378 **** --- 373,380 ---- var l = [3, 2, 1] call('reverse', [l]) l->assert_equal([1, 2, 3]) + CheckDefAndScriptFailure2(['call("reverse", 2)'], 'E1013: Argument 2: type mismatch, expected list but got number', 'E1211: List required for argument 2') + CheckDefAndScriptFailure2(['call("reverse", [2], [1])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') enddef def Test_ch_canread() *************** *** 1126,1131 **** --- 1128,1143 ---- assert_equal('', fullcommand('scg')) enddef + def Test_funcref() + CheckDefAndScriptFailure2(['funcref("reverse", 2)'], 'E1013: Argument 2: type mismatch, expected list but got number', 'E1211: List required for argument 2') + CheckDefAndScriptFailure2(['funcref("reverse", [2], [1])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') + enddef + + def Test_function() + CheckDefAndScriptFailure2(['function("reverse", 2)'], 'E1013: Argument 2: type mismatch, expected list but got number', 'E1211: List required for argument 2') + CheckDefAndScriptFailure2(['function("reverse", [2], [1])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') + enddef + def Test_garbagecollect() garbagecollect(true) CheckDefAndScriptFailure2(['garbagecollect("1")'], 'E1013: Argument 1: type mismatch, expected bool but got string', 'E1135: Using a String as a Bool') *************** *** 1691,1696 **** --- 1703,1722 ---- var->assert_equal(['a', 'b']) enddef + def Test_libcall() + CheckFeature libcall + CheckDefAndScriptFailure2(['libcall(1, "b", 3)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['libcall("a", 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['libcall("a", "b", 1.1)'], 'E1013: Argument 3: type mismatch, expected string but got float', 'E1174: String required for argument 3') + enddef + + def Test_libcallnr() + CheckFeature libcall + CheckDefAndScriptFailure2(['libcallnr(1, "b", 3)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['libcallnr("a", 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['libcallnr("a", "b", 1.1)'], 'E1013: Argument 3: type mismatch, expected string but got float', 'E1174: String required for argument 3') + enddef + def Test_line() assert_fails('line(true)', 'E1174:') CheckDefAndScriptFailure2(['line(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') *************** *** 1726,1731 **** --- 1752,1761 ---- ->str2nr() enddef + def Test_listener_add() + CheckDefAndScriptFailure2(['listener_add("1", true)'], 'E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2') + enddef + def Test_listener_flush() CheckDefAndScriptFailure2(['listener_flush([1])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E730: Using a List as a String') enddef *************** *** 2285,2292 **** enddef def Test_readdir() ! eval expand('sautest')->readdir((e) => e[0] !=# '.') ! eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') enddef def Test_readblob() --- 2315,2329 ---- enddef def Test_readdir() ! eval expand('sautest')->readdir((e) => e[0] !=# '.') ! eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') ! CheckDefAndScriptFailure2(['readdir(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') ! CheckDefAndScriptFailure2(['readdir("a", "1", [3])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') ! enddef ! ! def Test_readdirex() ! CheckDefAndScriptFailure2(['readdirex(["a"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') ! CheckDefAndScriptFailure2(['readdirex("a", "1", [3])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') enddef def Test_readblob() *************** *** 2604,2631 **** CheckScriptSuccess(lines) assert_equal('yes', g:caught) unlet g:caught lines =<< trim END echo searchpair("a", "b", "c", "d", "f", 33) END CheckDefAndScriptFailure2(lines, 'E1001: Variable not found: f', 'E475: Invalid argument: d') - lines =<< trim END - def TestPair() - echo searchpair("a", "b", "c", "d", "1", 99) - enddef - defcompile - END - CheckScriptSuccess(lines) - - bwipe! CheckDefAndScriptFailure2(['searchpair(1, "b", "c")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') CheckDefAndScriptFailure2(['searchpair("a", 2, "c")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') CheckDefAndScriptFailure2(['searchpair("a", "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3') CheckDefAndScriptFailure2(['searchpair("a", "b", "c", 4)'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') ! # BUG: Vim crashes with the following test ! #CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", "f")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') ! #CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", 3, "g")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') enddef def Test_searchpos() --- 2641,2659 ---- CheckScriptSuccess(lines) assert_equal('yes', g:caught) unlet g:caught + bwipe! lines =<< trim END echo searchpair("a", "b", "c", "d", "f", 33) END CheckDefAndScriptFailure2(lines, 'E1001: Variable not found: f', 'E475: Invalid argument: d') CheckDefAndScriptFailure2(['searchpair(1, "b", "c")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') CheckDefAndScriptFailure2(['searchpair("a", 2, "c")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') CheckDefAndScriptFailure2(['searchpair("a", "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3') CheckDefAndScriptFailure2(['searchpair("a", "b", "c", 4)'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') ! CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "r", "1", "f")'], 'E1013: Argument 6: type mismatch, expected number but got string', 'E1210: Number required for argument 6') ! CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "r", "1", 3, "g")'], 'E1013: Argument 7: type mismatch, expected number but got string', 'E1210: Number required for argument 7') enddef def Test_searchpos() *************** *** 2951,2956 **** --- 2979,2994 ---- CheckDefAndScriptFailure2(['spellsuggest("a", 1, 0z01)'], 'E1013: Argument 3: type mismatch, expected bool but got blob', 'E1212: Bool required for argument 3') enddef + def Test_sound_playevent() + CheckFeature sound + CheckDefAndScriptFailure2(['sound_playevent(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + enddef + + def Test_sound_playfile() + CheckFeature sound + CheckDefAndScriptFailure2(['sound_playfile(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + enddef + def Test_sound_stop() CheckFeature sound CheckDefFailure(['sound_stop("x")'], 'E1013: Argument 1: type mismatch, expected number but got string') *************** *** 3137,3142 **** --- 3175,3183 ---- assert_fails('"text"->substitute(".*", () => job_start(":"), "")', 'E908: using an invalid value as a String: job') assert_fails('"text"->substitute(".*", () => job_start(":")->job_getchannel(), "")', 'E908: using an invalid value as a String: channel') endif + CheckDefAndScriptFailure2(['substitute(1, "b", "1", "d")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['substitute("a", 2, "1", "d")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['substitute("a", "b", "1", 4)'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') enddef def Test_swapinfo() *************** *** 3376,3381 **** --- 3417,3430 ---- CheckDefAndScriptFailure2(['test_getvalue(1.1)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E474: Invalid argument') enddef + def Test_test_gui_drop_files() + CheckGui + CheckDefAndScriptFailure2(['test_gui_drop_files("a", 1, 1, 0)'], 'E1013: Argument 1: type mismatch, expected list but got string', 'E1211: List required for argument 1') + CheckDefAndScriptFailure2(['test_gui_drop_files(["x"], "", 1, 0)'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + CheckDefAndScriptFailure2(['test_gui_drop_files(["x"], 1, "", 0)'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['test_gui_drop_files(["x"], 1, 1, "")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + enddef + def Test_test_gui_mouse_event() CheckGui CheckDefAndScriptFailure2(['test_gui_mouse_event(1.1, 1, 1, 1, 1)'], 'E1013: Argument 1: type mismatch, expected number but got float', 'E1210: Number required for argument 1') *************** *** 3399,3404 **** --- 3448,3460 ---- CheckDefAndScriptFailure2(['test_override("a", "x")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') enddef + def Test_test_scrollbar() + CheckGui + CheckDefAndScriptFailure2(['test_scrollbar(1, 2, 3)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['test_scrollbar("a", "b", 3)'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + CheckDefAndScriptFailure2(['test_scrollbar("a", 2, "c")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + enddef + def Test_test_setmouse() CheckDefAndScriptFailure2(['test_setmouse("a", 10)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E474: Invalid argument') CheckDefAndScriptFailure2(['test_setmouse(10, "b")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E474: Invalid argument') *** ../vim-8.2.3214/src/testing.c 2021-07-20 17:51:48.251744105 +0200 --- src/testing.c 2021-07-24 21:30:48.348129172 +0200 *************** *** 1193,1198 **** --- 1193,1203 ---- int dragging; scrollbar_T *sb = NULL; + if (check_for_string_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL + || check_for_number_arg(argvars, 2) == FAIL) + return; + if (argvars[0].v_type != VAR_STRING || (argvars[1].v_type) != VAR_NUMBER || (argvars[2].v_type) != VAR_NUMBER) *************** *** 1281,1294 **** list_T *l; listitem_T *li; ! if (argvars[0].v_type != VAR_LIST ! || (argvars[1].v_type) != VAR_NUMBER ! || (argvars[2].v_type) != VAR_NUMBER ! || (argvars[3].v_type) != VAR_NUMBER) ! { ! emsg(_(e_invarg)); return; - } row = tv_get_number(&argvars[1]); col = tv_get_number(&argvars[2]); --- 1286,1296 ---- list_T *l; listitem_T *li; ! if (check_for_list_arg(argvars, 0) == FAIL ! || check_for_number_arg(argvars, 1) == FAIL ! || check_for_number_arg(argvars, 2) == FAIL ! || check_for_number_arg(argvars, 3) == FAIL) return; row = tv_get_number(&argvars[1]); col = tv_get_number(&argvars[2]); *** ../vim-8.2.3214/src/version.c 2021-07-24 21:19:38.946094111 +0200 --- src/version.c 2021-07-24 21:32:15.527875904 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3215, /**/ -- A computer without Windows is like a fish without a bicycle. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///