From 1af5ce01c333ed8be57f15dd7ba7846ac4760810 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 11:54:35 +0100 Subject: [PATCH 01/55] patch 8.2.0220: terminal test did pass on Mac Problem: Terminal test did pass on Mac. Solution: Remove the skip again. --- src/testdir/test_terminal.vim | 10 ++++------ src/version.c | 2 ++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index ae762fe670..605ac06fa8 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2359,12 +2359,10 @@ func Test_terminal_in_popup() call term_sendkeys(buf, "/edit\") call VerifyScreenDump(buf, 'Test_terminal_popup_3', {}) - " TODO: somehow this causes the job to keep running on Mac - if !has('mac') - call term_sendkeys(buf, "\:call HidePopup()\") - call VerifyScreenDump(buf, 'Test_terminal_popup_4', {}) - call term_sendkeys(buf, "\") - endif + call term_sendkeys(buf, "\:call HidePopup()\") + call VerifyScreenDump(buf, 'Test_terminal_popup_4', {}) + call term_sendkeys(buf, "\") + call term_wait(buf, 50) call term_sendkeys(buf, ":q\") call term_wait(buf, 100) " wait for terminal to vanish diff --git a/src/version.c b/src/version.c index e1c4a5e3fd..74f38b15ee 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 220, /**/ 219, /**/ From 6e587dcbf319ea898ef50f7e367c46586a6f408a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 13:15:52 +0100 Subject: [PATCH 02/55] patch 8.2.0221: no test for Vim9 += and ..= Problem: No test for Vim9 += and ..=. Solution: Add tests. --- src/testdir/test_vim9_script.vim | 25 +++++++++++++++++++++++-- src/version.c | 2 ++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 1cff3b61b2..10bbf9168b 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -27,6 +27,9 @@ func Test_def_basic() call assert_equal('yes', SomeFunc()) endfunc +let s:appendToMe = 'xxx' +let s:addToMe = 111 + def Test_assignment() let bool1: bool = true assert_equal(v:true, bool1) @@ -44,11 +47,16 @@ def Test_assignment() let dict2: dict = #{one: 1, two: 2} v:char = 'abc' - call assert_equal('abc', v:char) + assert_equal('abc', v:char) $ENVVAR = 'foobar' - call assert_equal('foobar', $ENVVAR) + assert_equal('foobar', $ENVVAR) $ENVVAR = '' + + appendToMe ..= 'yyy' + assert_equal('xxxyyy', appendToMe) + addToMe += 222 + assert_equal(333, addToMe) enddef func Test_assignment_failure() @@ -195,6 +203,7 @@ let s:export_script_lines =<< trim END export const CONST = 1234 export let exported = 9876 + export let exp_name = 'John' export def Exported(): string return 'Exported' enddef @@ -205,7 +214,14 @@ def Test_vim9script() vim9script import {exported, Exported} from './Xexport.vim' g:imported = exported + exported += 3 + g:imported_added = exported g:imported_func = Exported() + + import {exp_name} from './Xexport.vim' + g:imported_name = exp_name + exp_name ..= ' Doe' + g:imported_name_appended = exp_name END writefile(import_script_lines, 'Ximport.vim') @@ -216,13 +232,18 @@ def Test_vim9script() assert_equal('bobbie', g:result) assert_equal('bob', g:localname) assert_equal(9876, g:imported) + assert_equal(9879, g:imported_added) assert_equal('Exported', g:imported_func) + assert_equal('John', g:imported_name) + assert_equal('John Doe', g:imported_name_appended) assert_false(exists('g:name')) unlet g:result unlet g:localname unlet g:imported + unlet g:imported_added unlet g:imported_func + unlet g:imported_name g:imported_name_appended delete('Ximport.vim') delete('Xexport.vim') diff --git a/src/version.c b/src/version.c index 74f38b15ee..f302040e86 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 221, /**/ 220, /**/ From 170fcfcf250954d76fca86e3fed088ddfdb49383 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 17:51:35 +0100 Subject: [PATCH 03/55] patch 8.2.0222: Vim9: optional function arguments don't work yet Problem: Vim9: optional function arguments don't work yet. Solution: Implement optional function arguments. --- src/structs.h | 2 + src/testdir/test_vim9_script.vim | 52 ++++++++++------- src/userfunc.c | 1 + src/version.c | 2 + src/vim9compile.c | 51 +++++++++++++++-- src/vim9execute.c | 97 +++++++++++++++++++++++--------- 6 files changed, 154 insertions(+), 51 deletions(-) diff --git a/src/structs.h b/src/structs.h index bb3e72f635..7aff8af201 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1515,6 +1515,8 @@ typedef struct type_T **uf_arg_types; // argument types (count == uf_args.ga_len) type_T *uf_ret_type; // return type garray_T uf_type_list; // types used in arg and return types + int *uf_def_arg_idx; // instruction indexes for evaluating + // uf_def_args; length: uf_def_args.ga_len + 1 char_u *uf_va_name; // name from "...name" or NULL type_T *uf_va_type; // type from "...name: type" or NULL diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 10bbf9168b..d7b3b4c995 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -139,6 +139,39 @@ def Test_call_varargs() assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) enddef +def MyDefaultArgs(name = 'string'): string + return name +enddef + +def Test_call_default_args() + assert_equal('string', MyDefaultArgs()) + assert_equal('one', MyDefaultArgs('one')) + assert_fails('call MyDefaultArgs("one", "two")', 'E118:') +enddef + +func Test_call_default_args_from_func() + call assert_equal('string', MyDefaultArgs()) + call assert_equal('one', MyDefaultArgs('one')) + call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') +endfunc + +" Default arg and varargs +def MyDefVarargs(one: string, two = 'foo', ...rest: list): string + let res = one .. ',' .. two + for s in rest + res ..= ',' .. s + endfor + return res +enddef + +def Test_call_def_varargs() + call assert_fails('call MyDefVarargs()', 'E119:') + assert_equal('one,foo', MyDefVarargs('one')) + assert_equal('one,two', MyDefVarargs('one', 'two')) + assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) +enddef + + "def Test_call_func_defined_later() " call assert_equal('one', DefineLater('one')) " call assert_fails('call NotDefined("one")', 'E99:') @@ -148,25 +181,6 @@ func DefineLater(arg) return a:arg endfunc -def MyDefaultArgs(name = 'string'): string - return name -enddef - -func Test_call_default_args_from_func() - " TODO: implement using default value for optional argument - "call assert_equal('string', MyDefaultArgs()) - call assert_fails('call MyDefaultArgs()', 'optional arguments not implemented yet') - call assert_equal('one', MyDefaultArgs('one')) - call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') -endfunc - -def Test_call_default_args() - " TODO: implement using default value for optional argument - "assert_equal('string', MyDefaultArgs()) - assert_equal('one', MyDefaultArgs('one')) - assert_fails('call MyDefaultArgs("one", "two")', 'E118:') -enddef - def Test_return_type_wrong() CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') diff --git a/src/userfunc.c b/src/userfunc.c index ef1d42d12b..3c2673dde6 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -200,6 +200,7 @@ get_function_args( { typval_T rettv; + // find the end of the expression (doesn't evaluate it) any_default = TRUE; p = skipwhite(p) + 1; p = skipwhite(p); diff --git a/src/version.c b/src/version.c index f302040e86..09f9e9c3c6 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 222, /**/ 221, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 12400a35d5..a362fe8b48 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -956,11 +956,12 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount) * Return FAIL if the number of arguments is wrong. */ static int -generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int argcount) +generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) { isn_T *isn; garray_T *stack = &cctx->ctx_type_stack; int regular_args = ufunc->uf_args.ga_len; + int argcount = pushed_argcount; if (argcount > regular_args && !has_varargs(ufunc)) { @@ -978,9 +979,13 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int argcount) { int count = argcount - regular_args; - // TODO: add default values for optional arguments? - generate_NEWLIST(cctx, count < 0 ? 0 : count); - argcount = regular_args + 1; + // If count is negative an empty list will be added after evaluating + // default values for missing optional arguments. + if (count >= 0) + { + generate_NEWLIST(cctx, count); + argcount = regular_args + 1; + } } if ((isn = generate_instr(cctx, @@ -4600,6 +4605,44 @@ compile_def_function(ufunc_T *ufunc, int set_return_type) // Most modern script version. current_sctx.sc_version = SCRIPT_VERSION_VIM9; + if (ufunc->uf_def_args.ga_len > 0) + { + int count = ufunc->uf_def_args.ga_len; + int i; + char_u *arg; + int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); + + // Produce instructions for the default values of optional arguments. + // Store the instruction index in uf_def_arg_idx[] so that we know + // where to start when the function is called, depending on the number + // of arguments. + ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1); + if (ufunc->uf_def_arg_idx == NULL) + goto erret; + for (i = 0; i < count; ++i) + { + ufunc->uf_def_arg_idx[i] = instr->ga_len; + arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; + if (compile_expr1(&arg, &cctx) == FAIL + || generate_STORE(&cctx, ISN_STORE, + i - count - off, NULL) == FAIL) + goto erret; + } + + // If a varargs is following, push an empty list. + if (ufunc->uf_va_name != NULL) + { + if (generate_NEWLIST(&cctx, 0) == FAIL + || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL) + goto erret; + } + + ufunc->uf_def_arg_idx[count] = instr->ga_len; + } + + /* + * Loop over all the lines of the function and generate instructions. + */ for (;;) { if (line != NULL && *line == '|') diff --git a/src/vim9execute.c b/src/vim9execute.c index 093fbad8e3..d40320122e 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -70,7 +70,7 @@ typedef struct { #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx) /* - * Return the number of arguments, including any vararg. + * Return the number of arguments, including optional arguments and any vararg. */ static int ufunc_argcount(ufunc_T *ufunc) @@ -78,6 +78,35 @@ ufunc_argcount(ufunc_T *ufunc) return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); } +/* + * Set the instruction index, depending on omitted arguments, where the default + * values are to be computed. If all optional arguments are present, start + * with the function body. + * The expression evaluation is at the start of the instructions: + * 0 -> EVAL default1 + * STORE arg[-2] + * 1 -> EVAL default2 + * STORE arg[-1] + * 2 -> function body + */ + static void +init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) +{ + if (ufunc->uf_def_args.ga_len == 0) + ectx->ec_iidx = 0; + else + { + int defcount = ufunc->uf_args.ga_len - argcount; + + // If there is a varargs argument defcount can be negative, no defaults + // to evaluate then. + if (defcount < 0) + defcount = 0; + ectx->ec_iidx = ufunc->uf_def_arg_idx[ + ufunc->uf_def_args.ga_len - defcount]; + } +} + /* * Call compiled function "cdf_idx" from compiled code. * @@ -107,23 +136,15 @@ call_dfunc(int cdf_idx, int argcount, ectx_T *ectx) if (ga_grow(&ectx->ec_stack, optcount + 3 + dfunc->df_varcount) == FAIL) return FAIL; -// TODO: Put omitted argument default values on the stack. - if (optcount > 0) - { - emsg("optional arguments not implemented yet"); - return FAIL; - } if (optcount < 0) { emsg("argument count wrong?"); return FAIL; } -// for (idx = argcount - dfunc->df_minarg; -// idx < dfunc->df_maxarg; ++idx) -// { -// copy_tv(&dfunc->df_defarg[idx], STACK_TV_BOT(0)); -// ++ectx->ec_stack.ga_len; -// } + + // Reserve space for omitted optional arguments, filled in soon. + // Also any empty varargs argument. + ectx->ec_stack.ga_len += optcount; // Store current execution state in stack frame for ISN_RETURN. // TODO: If the actual number of arguments doesn't match what the called @@ -142,7 +163,9 @@ call_dfunc(int cdf_idx, int argcount, ectx_T *ectx) ectx->ec_dfunc_idx = cdf_idx; ectx->ec_instr = dfunc->df_instr; estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); - ectx->ec_iidx = 0; + + // Decide where to start execution, handles optional arguments. + init_instr_idx(ufunc, argcount, ectx); return OK; } @@ -156,9 +179,9 @@ call_dfunc(int cdf_idx, int argcount, ectx_T *ectx) static void func_return(ectx_T *ectx) { - int ret_idx = ectx->ec_stack.ga_len - 1; int idx; dfunc_T *dfunc; + int top; // execution context goes one level up estack_pop(); @@ -166,17 +189,27 @@ func_return(ectx_T *ectx) // Clear the local variables and temporary values, but not // the return value. for (idx = ectx->ec_frame + STACK_FRAME_SIZE; - idx < ectx->ec_stack.ga_len - 1; ++idx) + idx < ectx->ec_stack.ga_len - 1; ++idx) clear_tv(STACK_TV(idx)); + + // Clear the arguments. dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; - ectx->ec_stack.ga_len = ectx->ec_frame - - ufunc_argcount(dfunc->df_ufunc) + 1; + top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc); + for (idx = top; idx < ectx->ec_frame; ++idx) + clear_tv(STACK_TV(idx)); + + // Restore the previous frame. ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number; ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number; ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number; - *STACK_TV_BOT(-1) = *STACK_TV(ret_idx); dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; ectx->ec_instr = dfunc->df_instr; + + // Reset the stack to the position before the call, move the return value + // to the top of the stack. + idx = ectx->ec_stack.ga_len - 1; + ectx->ec_stack.ga_len = top + 1; + *STACK_TV_BOT(-1) = *STACK_TV(idx); } #undef STACK_TV @@ -362,7 +395,7 @@ call_def_function( int idx; int ret = FAIL; dfunc_T *dfunc; - int optcount = ufunc_argcount(ufunc) - argc; + int defcount = ufunc->uf_args.ga_len - argc; // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -388,17 +421,18 @@ call_def_function( copy_tv(&argv[idx], STACK_TV_BOT(0)); ++ectx.ec_stack.ga_len; } + // Make space for omitted arguments, will store default value below. + if (defcount > 0) + for (idx = 0; idx < defcount; ++idx) + { + STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; + ++ectx.ec_stack.ga_len; + } // Frame pointer points to just after arguments. ectx.ec_frame = ectx.ec_stack.ga_len; initial_frame_ptr = ectx.ec_frame; -// TODO: Put omitted argument default values on the stack. - if (optcount > 0) - { - emsg("optional arguments not implemented yet"); - return FAIL; - } // dummy frame entries for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) { @@ -413,7 +447,10 @@ call_def_function( ectx.ec_stack.ga_len += dfunc->df_varcount; ectx.ec_instr = dfunc->df_instr; - ectx.ec_iidx = 0; + + // Decide where to start execution, handles optional arguments. + init_instr_idx(ufunc, argc, &ectx); + for (;;) { isn_T *iptr; @@ -1657,7 +1694,11 @@ ex_disassemble(exarg_T *eap) break; case ISN_STORE: - smsg("%4d STORE $%lld", current, iptr->isn_arg.number); + if (iptr->isn_arg.number < 0) + smsg("%4d STORE arg[%lld]", current, + iptr->isn_arg.number + STACK_FRAME_SIZE); + else + smsg("%4d STORE $%lld", current, iptr->isn_arg.number); break; case ISN_STOREV: smsg("%4d STOREV v:%s", current, From 5cab73f8cca46d831fb9337b176493da2a55ed5d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 19:25:19 +0100 Subject: [PATCH 04/55] patch 8.2.0223: some instructions not yet tested Problem: Some instructions not yet tested. Solution: Disassemble more instructions. Move tests to a new file. Compile call to s:function(). --- src/proto/userfunc.pro | 2 +- src/testdir/Make_all.mak | 2 + src/testdir/test_vim9_disassemble.vim | 220 ++++++++++++++++++++++++++ src/testdir/test_vim9_script.vim | 210 ------------------------ src/userfunc.c | 4 +- src/version.c | 2 + src/vim.h | 3 + src/vim9compile.c | 43 +++-- 8 files changed, 256 insertions(+), 230 deletions(-) create mode 100644 src/testdir/test_vim9_disassemble.vim diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index 74bcabd8ce..165b04b5e4 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -6,6 +6,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate); char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload); void emsg_funcname(char *ermsg, char_u *name); int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe); +char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error); ufunc_T *find_func(char_u *name, cctx_T *cctx); int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict); void save_funccal(funccal_entry_T *entry); @@ -26,7 +27,6 @@ int has_varargs(ufunc_T *ufunc); int function_exists(char_u *name, int no_deref); char_u *get_expanded_name(char_u *name, int check); char_u *get_user_func_name(expand_T *xp, int idx); -void clean_script_functions(int sid); void ex_delfunction(exarg_T *eap); void func_unref(char_u *name); void func_ptr_unref(ufunc_T *fp); diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 350e58e571..40e56a290f 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -268,6 +268,7 @@ NEW_TESTS = \ test_utf8 \ test_utf8_comparisons \ test_vartabs \ + test_vim9_disassemble \ test_vim9_expr \ test_vim9_script \ test_viminfo \ @@ -470,6 +471,7 @@ NEW_TESTS_RES = \ test_user_func.res \ test_usercommands.res \ test_vartabs.res \ + test_vim9_disassemble.res \ test_vim9_expr.res \ test_vim9_script.res \ test_viminfo.res \ diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim new file mode 100644 index 0000000000..3345758032 --- /dev/null +++ b/src/testdir/test_vim9_disassemble.vim @@ -0,0 +1,220 @@ +" Test the :disassemble command, and compilation as a side effect + +func NotCompiled() + echo "not" +endfunc + +let s:scriptvar = 4 +let g:globalvar = 'g' + +def s:ScriptFuncLoad(arg: string) + let local = 1 + buffers + echo arg + echo local + echo v:version + echo s:scriptvar + echo g:globalvar + echo &tabstop + echo $ENVVAR + echo @z +enddef + +def Test_disassembleLoad() + assert_fails('disass NoFunc', 'E1061:') + assert_fails('disass NotCompiled', 'E1062:') + + let res = execute('disass s:ScriptFuncLoad') + assert_match('\d*_ScriptFuncLoad.*' + \ .. 'buffers.*' + \ .. ' EXEC \+buffers.*' + \ .. ' LOAD arg\[-1\].*' + \ .. ' LOAD $0.*' + \ .. ' LOADV v:version.*' + \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*' + \ .. ' LOADG g:globalvar.*' + \ .. ' LOADENV $ENVVAR.*' + \ .. ' LOADREG @z.*' + \, res) +enddef + +def s:ScriptFuncPush() + let localbool = true + let localspec = v:none + let localblob = 0z1234 + if has('float') + let localfloat = 1.234 + endif +enddef + +def Test_disassemblePush() + let res = execute('disass s:ScriptFuncPush') + assert_match('\d*_ScriptFuncPush.*' + \ .. 'localbool = true.*' + \ .. ' PUSH v:true.*' + \ .. 'localspec = v:none.*' + \ .. ' PUSH v:none.*' + \ .. 'localblob = 0z1234.*' + \ .. ' PUSHBLOB 0z1234.*' + \, res) + if has('float') + assert_match('\d*_ScriptFuncPush.*' + \ .. 'localfloat = 1.234.*' + \ .. ' PUSHF 1.234.*' + \, res) + endif +enddef + +def s:ScriptFuncStore() + let localnr = 1 + localnr = 2 + let localstr = 'abc' + localstr = 'xyz' + v:char = 'abc' + s:scriptvar = 'sv' + g:globalvar = 'gv' + &tabstop = 8 + $ENVVAR = 'ev' + @z = 'rv' +enddef + +def Test_disassembleStore() + let res = execute('disass s:ScriptFuncStore') + assert_match('\d*_ScriptFuncStore.*' + \ .. 'localnr = 2.*' + \ .. ' STORE 2 in $0.*' + \ .. 'localstr = ''xyz''.*' + \ .. ' STORE $1.*' + \ .. 'v:char = ''abc''.*' + \ .. 'STOREV v:char.*' + \ .. 's:scriptvar = ''sv''.*' + \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' + \ .. 'g:globalvar = ''gv''.*' + \ .. ' STOREG g:globalvar.*' + \ .. '&tabstop = 8.*' + \ .. ' STOREOPT &tabstop.*' + \ .. '$ENVVAR = ''ev''.*' + \ .. ' STOREENV $ENVVAR.*' + \ .. '@z = ''rv''.*' + \ .. ' STOREREG @z.*' + \, res) +enddef + +def s:ScriptFuncTry() + try + echo 'yes' + catch /fail/ + echo 'no' + finally + echo 'end' + endtry +enddef + +def Test_disassembleTry() + let res = execute('disass s:ScriptFuncTry') + assert_match('\d*_ScriptFuncTry.*' + \ .. 'try.*' + \ .. 'TRY catch -> \d\+, finally -> \d\+.*' + \ .. 'catch /fail/.*' + \ .. ' JUMP -> \d\+.*' + \ .. ' PUSH v:exception.*' + \ .. ' PUSHS "fail".*' + \ .. ' COMPARESTRING =\~.*' + \ .. ' JUMP_IF_FALSE -> \d\+.*' + \ .. ' CATCH.*' + \ .. 'finally.*' + \ .. ' PUSHS "end".*' + \ .. 'endtry.*' + \ .. ' ENDTRY.*' + \, res) +enddef + +def s:ScriptFuncNew() + let ll = [1, "two", 333] + let dd = #{one: 1, two: "val"} +enddef + +def Test_disassembleNew() + let res = execute('disass s:ScriptFuncNew') + assert_match('\d*_ScriptFuncNew.*' + \ .. 'let ll = \[1, "two", 333].*' + \ .. 'PUSHNR 1.*' + \ .. 'PUSHS "two".*' + \ .. 'PUSHNR 333.*' + \ .. 'NEWLIST size 3.*' + \ .. 'let dd = #{one: 1, two: "val"}.*' + \ .. 'PUSHS "one".*' + \ .. 'PUSHNR 1.*' + \ .. 'PUSHS "two".*' + \ .. 'PUSHS "val".*' + \ .. 'NEWDICT size 2.*' + \, res) +enddef + +def FuncWithArg(arg) + echo arg +enddef + +func UserFunc() + echo 'nothing' +endfunc + +func UserFuncWithArg(arg) + echo a:arg +endfunc + +def s:ScriptFuncCall(): string + changenr() + char2nr("abc") + Test_disassembleNew() + FuncWithArg(343) + ScriptFuncNew() + s:ScriptFuncNew() + UserFunc() + UserFuncWithArg("foo") + let FuncRef = function("UserFunc") + FuncRef() + let FuncRefWithArg = function("UserFuncWithArg") + FuncRefWithArg("bar") + return "yes" +enddef + +def Test_disassembleCall() + let res = execute('disass s:ScriptFuncCall') + assert_match('\d\+_ScriptFuncCall.*' + \ .. 'changenr().*' + \ .. ' BCALL changenr(argc 0).*' + \ .. 'char2nr("abc").*' + \ .. ' PUSHS "abc".*' + \ .. ' BCALL char2nr(argc 1).*' + \ .. 'Test_disassembleNew().*' + \ .. ' DCALL Test_disassembleNew(argc 0).*' + \ .. 'FuncWithArg(343).*' + \ .. ' PUSHNR 343.*' + \ .. ' DCALL FuncWithArg(argc 1).*' + \ .. 'ScriptFuncNew().*' + \ .. ' DCALL \d\+_ScriptFuncNew(argc 0).*' + \ .. 's:ScriptFuncNew().*' + \ .. ' DCALL \d\+_ScriptFuncNew(argc 0).*' + \ .. 'UserFunc().*' + \ .. ' UCALL UserFunc(argc 0).*' + \ .. 'UserFuncWithArg("foo").*' + \ .. ' PUSHS "foo".*' + \ .. ' UCALL UserFuncWithArg(argc 1).*' + \ .. 'let FuncRef = function("UserFunc").*' + \ .. 'FuncRef().*' + \ .. ' LOAD $\d.*' + \ .. ' PCALL (argc 0).*' + \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*' + \ .. 'FuncRefWithArg("bar").*' + \ .. ' PUSHS "bar".*' + \ .. ' LOAD $\d.*' + \ .. ' PCALL (argc 1).*' + \ .. 'return "yes".*' + \ .. ' PUSHS "yes".*' + \ .. ' RETURN.*' + \, res) +enddef + + +" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index d7b3b4c995..4b57bde0bd 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -489,215 +489,5 @@ def Test_compile_const_expr() assert_notmatch('JUMP', instr) enddef -func NotCompiled() - echo "not" -endfunc - -let s:scriptvar = 4 -let g:globalvar = 'g' - -def s:ScriptFuncLoad(arg: string) - let local = 1 - buffers - echo arg - echo local - echo v:version - echo s:scriptvar - echo g:globalvar - echo &tabstop - echo $ENVVAR - echo @z -enddef - -def Test_disassembleLoad() - assert_fails('disass NoFunc', 'E1061:') - assert_fails('disass NotCompiled', 'E1062:') - - let res = execute('disass s:ScriptFuncLoad') - assert_match('\d*_ScriptFuncLoad.*' - \ .. 'buffers.*' - \ .. ' EXEC \+buffers.*' - \ .. ' LOAD arg\[-1\].*' - \ .. ' LOAD $0.*' - \ .. ' LOADV v:version.*' - \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*' - \ .. ' LOADG g:globalvar.*' - \ .. ' LOADENV $ENVVAR.*' - \ .. ' LOADREG @z.*' - \, res) -enddef - -def s:ScriptFuncPush() - let localbool = true - let localspec = v:none - let localblob = 0z1234 - if has('float') - let localfloat = 1.234 - endif -enddef - -def Test_disassemblePush() - let res = execute('disass s:ScriptFuncPush') - assert_match('\d*_ScriptFuncPush.*' - \ .. 'localbool = true.*' - \ .. ' PUSH v:true.*' - \ .. 'localspec = v:none.*' - \ .. ' PUSH v:none.*' - \ .. 'localblob = 0z1234.*' - \ .. ' PUSHBLOB 0z1234.*' - \, res) - if has('float') - assert_match('\d*_ScriptFuncPush.*' - \ .. 'localfloat = 1.234.*' - \ .. ' PUSHF 1.234.*' - \, res) - endif -enddef - -def s:ScriptFuncStore() - let localnr = 1 - localnr = 2 - let localstr = 'abc' - localstr = 'xyz' - v:char = 'abc' - s:scriptvar = 'sv' - g:globalvar = 'gv' - &tabstop = 8 - $ENVVAR = 'ev' - @z = 'rv' -enddef - -def Test_disassembleStore() - let res = execute('disass s:ScriptFuncStore') - assert_match('\d*_ScriptFuncStore.*' - \ .. 'localnr = 2.*' - \ .. ' STORE 2 in $0.*' - \ .. 'localstr = ''xyz''.*' - \ .. ' STORE $1.*' - \ .. 'v:char = ''abc''.*' - \ .. 'STOREV v:char.*' - \ .. 's:scriptvar = ''sv''.*' - \ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*' - \ .. 'g:globalvar = ''gv''.*' - \ .. ' STOREG g:globalvar.*' - \ .. '&tabstop = 8.*' - \ .. ' STOREOPT &tabstop.*' - \ .. '$ENVVAR = ''ev''.*' - \ .. ' STOREENV $ENVVAR.*' - \ .. '@z = ''rv''.*' - \ .. ' STOREREG @z.*' - \, res) -enddef - -def s:ScriptFuncTry() - try - echo 'yes' - catch /fail/ - echo 'no' - finally - echo 'end' - endtry -enddef - -def Test_disassembleTry() - let res = execute('disass s:ScriptFuncTry') - assert_match('\d*_ScriptFuncTry.*' - \ .. 'try.*' - \ .. 'TRY catch -> \d\+, finally -> \d\+.*' - \ .. 'catch /fail/.*' - \ .. ' JUMP -> \d\+.*' - \ .. ' PUSH v:exception.*' - \ .. ' PUSHS "fail".*' - \ .. ' COMPARESTRING =\~.*' - \ .. ' JUMP_IF_FALSE -> \d\+.*' - \ .. ' CATCH.*' - \ .. 'finally.*' - \ .. ' PUSHS "end".*' - \ .. 'endtry.*' - \ .. ' ENDTRY.*' - \, res) -enddef - -def s:ScriptFuncNew() - let ll = [1, "two", 333] - let dd = #{one: 1, two: "val"} -enddef - -def Test_disassembleNew() - let res = execute('disass s:ScriptFuncNew') - assert_match('\d*_ScriptFuncNew.*' - \ .. 'let ll = \[1, "two", 333].*' - \ .. 'PUSHNR 1.*' - \ .. 'PUSHS "two".*' - \ .. 'PUSHNR 333.*' - \ .. 'NEWLIST size 3.*' - \ .. 'let dd = #{one: 1, two: "val"}.*' - \ .. 'PUSHS "one".*' - \ .. 'PUSHNR 1.*' - \ .. 'PUSHS "two".*' - \ .. 'PUSHS "val".*' - \ .. 'NEWDICT size 2.*' - \, res) -enddef - -def FuncWithArg(arg) - echo arg -enddef - -func UserFunc() - echo 'nothing' -endfunc - -func UserFuncWithArg(arg) - echo a:arg -endfunc - -def s:ScriptFuncCall(): string - changenr() - char2nr("abc") - Test_disassembleNew() - FuncWithArg(343) - UserFunc() - UserFuncWithArg("foo") - let FuncRef = function("UserFunc") - FuncRef() - let FuncRefWithArg = function("UserFuncWithArg") - FuncRefWithArg("bar") - return "yes" -enddef - -def Test_disassembleCall() - let res = execute('disass s:ScriptFuncCall') - assert_match('\d*_ScriptFuncCall.*' - \ .. 'changenr().*' - \ .. ' BCALL changenr(argc 0).*' - \ .. 'char2nr("abc").*' - \ .. ' PUSHS "abc".*' - \ .. ' BCALL char2nr(argc 1).*' - \ .. 'Test_disassembleNew().*' - \ .. ' DCALL Test_disassembleNew(argc 0).*' - \ .. 'FuncWithArg(343).*' - \ .. ' PUSHNR 343.*' - \ .. ' DCALL FuncWithArg(argc 1).*' - \ .. 'UserFunc().*' - \ .. ' UCALL UserFunc(argc 0).*' - \ .. 'UserFuncWithArg("foo").*' - \ .. ' PUSHS "foo".*' - \ .. ' UCALL UserFuncWithArg(argc 1).*' - \ .. 'let FuncRef = function("UserFunc").*' - \ .. 'FuncRef().*' - \ .. ' LOAD $\d.*' - \ .. ' PCALL (argc 0).*' - \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*' - \ .. 'FuncRefWithArg("bar").*' - \ .. ' PUSHS "bar".*' - \ .. ' LOAD $\d.*' - \ .. ' PCALL (argc 1).*' - \ .. 'return "yes".*' - \ .. ' PUSHS "yes".*' - \ .. ' RETURN.*' - \, res) -enddef - " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/userfunc.c b/src/userfunc.c index 3c2673dde6..1c25a62685 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -573,8 +573,6 @@ get_func_tv( return ret; } -#define FLEN_FIXED 40 - /* * Return TRUE if "p" starts with "" or "s:". * Only works if eval_fname_script() returned non-zero for "p"! @@ -591,7 +589,7 @@ eval_fname_sid(char_u *p) * Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory * (slow). */ - static char_u * + char_u * fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) { int llen; diff --git a/src/version.c b/src/version.c index 09f9e9c3c6..e76bdea773 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 223, /**/ 222, /**/ diff --git a/src/vim.h b/src/vim.h index 23e53747a4..12af8560c6 100644 --- a/src/vim.h +++ b/src/vim.h @@ -2574,6 +2574,9 @@ typedef enum { #define FCERR_DELETED 7 #define FCERR_NOTMETHOD 8 // function cannot be used as a method +// fixed buffer length for fname_trans_sid() +#define FLEN_FIXED 40 + // flags for find_name_end() #define FNE_INCL_BR 1 // include [] in name #define FNE_CHECK_START 2 // check name starts with valid character diff --git a/src/vim9compile.c b/src/vim9compile.c index a362fe8b48..922618b0a0 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1686,49 +1686,60 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init) char_u *p; int argcount = argcount_init; char_u namebuf[100]; + char_u fname_buf[FLEN_FIXED + 1]; + char_u *tofree = NULL; + int error = FCERR_NONE; ufunc_T *ufunc; + int res = FAIL; if (varlen >= sizeof(namebuf)) { semsg(_("E1011: name too long: %s"), name); return FAIL; } - vim_strncpy(namebuf, name, varlen); + vim_strncpy(namebuf, *arg, varlen); + name = fname_trans_sid(namebuf, fname_buf, &tofree, &error); *arg = skipwhite(*arg + varlen + 1); if (compile_arguments(arg, cctx, &argcount) == FAIL) - return FAIL; + goto theend; - if (ASCII_ISLOWER(*name)) + if (ASCII_ISLOWER(*name) && name[1] != ':') { int idx; // builtin function - idx = find_internal_func(namebuf); + idx = find_internal_func(name); if (idx >= 0) - return generate_BCALL(cctx, idx, argcount); + { + res = generate_BCALL(cctx, idx, argcount); + goto theend; + } semsg(_(e_unknownfunc), namebuf); } - // User defined function or variable must start with upper case. - if (!ASCII_ISUPPER(*name)) - { - semsg(_("E1012: Invalid function name: %s"), namebuf); - return FAIL; - } - // If we can find the function by name generate the right call. - ufunc = find_func(namebuf, cctx); + ufunc = find_func(name, cctx); if (ufunc != NULL) - return generate_CALL(cctx, ufunc, argcount); + { + res = generate_CALL(cctx, ufunc, argcount); + goto theend; + } // If the name is a variable, load it and use PCALL. p = namebuf; if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) - return generate_PCALL(cctx, argcount, FALSE); + { + res = generate_PCALL(cctx, argcount, FALSE); + goto theend; + } // The function may be defined only later. Need to figure out at runtime. - return generate_UCALL(cctx, namebuf, argcount); + res = generate_UCALL(cctx, name, argcount); + +theend: + vim_free(tofree); + return res; } // like NAMESPACE_CHAR but with 'a' and 'l'. From 158906cffc62bc82bc38198c2104967f2a70542c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 20:39:45 +0100 Subject: [PATCH 05/55] patch 8.2.0224: compiling :elseif not tested yet Problem: compiling :elseif not tested yet. Solution: Add test for :elseif. Fix generating jumps. --- src/testdir/test_vim9_disassemble.vim | 62 +++++++++++++++++++++++++++ src/testdir/test_vim9_script.vim | 36 ++++++---------- src/version.c | 2 + src/vim9compile.c | 5 ++- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 3345758032..b011342976 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -216,5 +216,67 @@ def Test_disassembleCall() \, res) enddef +def HasEval() + if has("eval") + echo "yes" + else + echo "no" + endif +enddef + +def HasNothing() + if has("nothing") + echo "yes" + else + echo "no" + endif +enddef + +def HasSomething() + if has("nothing") + echo "nothing" + elseif has("something") + echo "something" + elseif has("eval") + echo "eval" + elseif has("less") + echo "less" + endif +enddef + +def Test_compile_const_expr() + assert_equal("\nyes", execute('call HasEval()')) + let instr = execute('disassemble HasEval') + assert_match('HasEval.*' + \ .. 'if has("eval").*' + \ .. ' PUSHS "yes".*' + \, instr) + assert_notmatch('JUMP', instr) + + assert_equal("\nno", execute('call HasNothing()')) + instr = execute('disassemble HasNothing') + assert_match('HasNothing.*' + \ .. 'if has("nothing").*' + \ .. 'else.*' + \ .. ' PUSHS "no".*' + \, instr) + assert_notmatch('PUSHS "yes"', instr) + assert_notmatch('JUMP', instr) + + assert_equal("\neval", execute('call HasSomething()')) + instr = execute('disassemble HasSomething') + assert_match('HasSomething.*' + \ .. 'if has("nothing").*' + \ .. 'elseif has("something").*' + \ .. 'elseif has("eval").*' + \ .. ' PUSHS "eval".*' + \ .. 'elseif has("less").*' + \, instr) + assert_notmatch('PUSHS "nothing"', instr) + assert_notmatch('PUSHS "something"', instr) + assert_notmatch('PUSHS "less"', instr) + assert_notmatch('JUMP', instr) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 4b57bde0bd..892806f39a 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -459,34 +459,22 @@ def do_something(): EOF endfunc -def HasEval() - if has('eval') - echo 'yes' +def IfElse(what: number): string + let res = '' + if what == 1 + res = "one" + elseif what == 2 + res = "two" else - echo 'no' + res = "three" endif + return res enddef -def HasNothing() - if has('nothing') - echo 'yes' - else - echo 'no' - endif -enddef - -def Test_compile_const_expr() - assert_equal("\nyes", execute('call HasEval()')) - let instr = execute('disassemble HasEval') - assert_match('PUSHS "yes"', instr) - assert_notmatch('PUSHS "no"', instr) - assert_notmatch('JUMP', instr) - - assert_equal("\nno", execute('call HasNothing()')) - instr = execute('disassemble HasNothing') - assert_notmatch('PUSHS "yes"', instr) - assert_match('PUSHS "no"', instr) - assert_notmatch('JUMP', instr) +def Test_if_elseif_else() + assert_equal('one', IfElse(1)) + assert_equal('two', IfElse(2)) + assert_equal('three', IfElse(3)) enddef diff --git a/src/version.c b/src/version.c index e76bdea773..3cb8bc29fa 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 224, /**/ 223, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 922618b0a0..1c76c8adb2 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3891,7 +3891,7 @@ compile_elseif(char_u *arg, cctx_T *cctx) } cctx->ctx_locals.ga_len = scope->se_local_count; - if (cctx->ctx_skip != TRUE) + if (cctx->ctx_skip == MAYBE) { if (compile_jump_to_end(&scope->se_u.se_if.is_end_label, JUMP_ALWAYS, cctx) == FAIL) @@ -3947,13 +3947,14 @@ compile_else(char_u *arg, cctx_T *cctx) return NULL; } - if (cctx->ctx_skip != TRUE) + if (cctx->ctx_skip == MAYBE) { if (scope->se_u.se_if.is_if_label >= 0) { // previous "if" or "elseif" jumps here isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label; isn->isn_arg.jump.jump_where = instr->ga_len; + scope->se_u.se_if.is_if_label = -1; } } From 777770fbb0f3c091cbfa22572b953c0723355710 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 21:27:08 +0100 Subject: [PATCH 06/55] patch 8.2.0225: compiling lambda not tested yet Problem: compiling lambda not tested yet. Solution: Add test for lambda and funcref. Drop unused instruction arg. --- src/testdir/test_vim9_disassemble.vim | 47 +++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9.h | 1 - src/vim9execute.c | 12 ++----- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index b011342976..20ad602f41 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -278,5 +278,52 @@ def Test_compile_const_expr() assert_notmatch('JUMP', instr) enddef +def WithLambda(): string + let F = {a -> "X" .. a .. "X"} + return F("x") +enddef + +def Test_compile_lambda() + assert_equal("XxX", WithLambda()) + let instr = execute('disassemble WithLambda') + assert_match('WithLambda.*' + \ .. 'let F = {a -> "X" .. a .. "X"}.*' + \ .. ' FUNCREF \d\+.*' + \ .. 'PUSHS "x".*' + \ .. ' LOAD $0.*' + \ .. ' PCALL (argc 1).*' + \ .. ' CHECKTYPE string stack\[-1].*' + \, instr) +enddef + +def AndOr(arg): string + if arg == 1 && arg != 2 || arg == 4 + return 'yes' + endif + return 'no' +enddef + +def Test_compile_and_or() + assert_equal("yes", AndOr(1)) + assert_equal("no", AndOr(2)) + assert_equal("yes", AndOr(4)) + let instr = execute('disassemble AndOr') + assert_match('AndOr.*' + \ .. 'if arg == 1 && arg != 2 || arg == 4.*' + \ .. '\d LOAD arg\[-1].*' + \ .. '\d PUSHNR 1.*' + \ .. '\d COMPAREANY ==.*' + \ .. '\d JUMP_AND_KEEP_IF_FALSE -> \d\+.*' + \ .. '\d LOAD arg\[-1].*' + \ .. '\d PUSHNR 2.*' + \ .. '\d COMPAREANY !=.*' + \ .. '\d JUMP_AND_KEEP_IF_TRUE -> \d\+.*' + \ .. '\d LOAD arg\[-1].*' + \ .. '\d PUSHNR 4.*' + \ .. '\d COMPAREANY ==.*' + \ .. '\d JUMP_IF_FALSE -> \d\+.*' + \, instr) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 3cb8bc29fa..9b5682c1d1 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 225, /**/ 224, /**/ diff --git a/src/vim9.h b/src/vim9.h index a9f0710438..a97796505f 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -130,7 +130,6 @@ typedef struct { typedef enum { JUMP_ALWAYS, - JUMP_IF_TRUE, // pop and jump if true JUMP_IF_FALSE, // pop and jump if false JUMP_AND_KEEP_IF_TRUE, // jump if top of stack is true, drop if not JUMP_AND_KEEP_IF_FALSE, // jump if top of stack is false, drop if not diff --git a/src/vim9execute.c b/src/vim9execute.c index d40320122e..1b45bf9937 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1001,8 +1001,7 @@ call_def_function( if (when == JUMP_IF_FALSE || when == JUMP_AND_KEEP_IF_FALSE) jump = !jump; - if (when == JUMP_IF_FALSE || when == JUMP_IF_TRUE - || !jump) + if (when == JUMP_IF_FALSE || !jump) { // drop the value from the stack clear_tv(tv); @@ -1583,15 +1582,14 @@ failed: return ret; } -#define DISASSEMBLE 1 - /* * ":dissassemble". + * We don't really need this at runtime, but we do have tests that require it, + * so always include this. */ void ex_disassemble(exarg_T *eap) { -#ifdef DISASSEMBLE char_u *fname; ufunc_T *ufunc; dfunc_T *dfunc; @@ -1840,9 +1838,6 @@ ex_disassemble(exarg_T *eap) case JUMP_ALWAYS: when = "JUMP"; break; - case JUMP_IF_TRUE: - when = "JUMP_IF_TRUE"; - break; case JUMP_AND_KEEP_IF_TRUE: when = "JUMP_AND_KEEP_IF_TRUE"; break; @@ -1997,7 +1992,6 @@ ex_disassemble(exarg_T *eap) case ISN_DROP: smsg("%4d DROP", current); break; } } -#endif } /* From 04d0522046e79d0e13c1317ad34bf228722ec728 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 22:06:54 +0100 Subject: [PATCH 07/55] patch 8.2.0226: compiling for loop not tested Problem: Compiling for loop not tested. Solution: Add a test. Make variable initialization work for more types. --- src/testdir/test_vim9_disassemble.vim | 32 ++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 48 ++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 20ad602f41..d9a2ad455f 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -325,5 +325,37 @@ def Test_compile_and_or() \, instr) enddef +def ForLoop(): list + let res: list + for i in range(3) + res->add(i) + endfor + return res +enddef + +def Test_compile_for_loop() + assert_equal([0, 1, 2], ForLoop()) + let instr = execute('disassemble ForLoop') + assert_match('ForLoop.*' + \ .. 'let res: list.*' + \ .. ' NEWLIST size 0.*' + \ .. '\d STORE $0.*' + \ .. 'for i in range(3).*' + \ .. '\d STORE -1 in $1.*' + \ .. '\d PUSHNR 3.*' + \ .. '\d BCALL range(argc 1).*' + \ .. '\d FOR $1 -> \d\+.*' + \ .. '\d STORE $2.*' + \ .. 'res->add(i).*' + \ .. '\d LOAD $0.*' + \ .. '\d LOAD $2.*' + \ .. '\d BCALL add(argc 2).*' + \ .. '\d DROP.*' + \ .. 'endfor.*' + \ .. '\d JUMP -> \d\+.*' + \ .. '\d DROP.*' + \, instr) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 9b5682c1d1..4b03add2a9 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 226, /**/ 225, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 1c76c8adb2..0c72168f1b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3427,13 +3427,51 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) else { // variables are always initialized - // TODO: support more types if (ga_grow(instr, 1) == FAIL) goto theend; - if (type->tt_type == VAR_STRING) - generate_PUSHS(cctx, vim_strsave((char_u *)"")); - else - generate_PUSHNR(cctx, 0); + switch (type->tt_type) + { + case VAR_BOOL: + generate_PUSHBOOL(cctx, VVAL_FALSE); + break; + case VAR_SPECIAL: + generate_PUSHSPEC(cctx, VVAL_NONE); + break; + case VAR_FLOAT: +#ifdef FEAT_FLOAT + generate_PUSHF(cctx, 0.0); +#endif + break; + case VAR_STRING: + generate_PUSHS(cctx, NULL); + break; + case VAR_BLOB: + generate_PUSHBLOB(cctx, NULL); + break; + case VAR_FUNC: + // generate_PUSHS(cctx, NULL); TODO + break; + case VAR_PARTIAL: + // generate_PUSHS(cctx, NULL); TODO + break; + case VAR_LIST: + generate_NEWLIST(cctx, 0); + break; + case VAR_DICT: + generate_NEWDICT(cctx, 0); + break; + case VAR_JOB: + // generate_PUSHS(cctx, NULL); TODO + break; + case VAR_CHANNEL: + // generate_PUSHS(cctx, NULL); TODO + break; + case VAR_NUMBER: + case VAR_UNKNOWN: + case VAR_VOID: + generate_PUSHNR(cctx, 0); + break; + } } if (oplen > 0 && *op != '=') From c2a4b35b86fa8b28a34a9aea8ad16c87dbc6d834 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Feb 2020 22:41:16 +0100 Subject: [PATCH 08/55] patch 8.2.0227: compiling a few instructions not tested Problem: Compiling a few instructions not tested. Solution: Add more test cases. --- src/testdir/test_vim9_disassemble.vim | 79 ++++++++++++++++++++++++++- src/version.c | 2 + 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index d9a2ad455f..b6edb0d6c3 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -106,7 +106,7 @@ def s:ScriptFuncTry() catch /fail/ echo 'no' finally - echo 'end' + throw 'end' endtry enddef @@ -124,6 +124,7 @@ def Test_disassembleTry() \ .. ' CATCH.*' \ .. 'finally.*' \ .. ' PUSHS "end".*' + \ .. ' THROW.*' \ .. 'endtry.*' \ .. ' ENDTRY.*' \, res) @@ -357,5 +358,81 @@ def Test_compile_for_loop() \, instr) enddef +let g:number = 42 + +def Computing() + let nr = 3 + let nrres = nr + 7 + nrres = nr - 7 + nrres = nr * 7 + nrres = nr / 7 + nrres = nr % 7 + + let anyres = g:number + 7 + anyres = g:number - 7 + anyres = g:number * 7 + anyres = g:number / 7 + anyres = g:number % 7 + + if has('float') + let fl = 3.0 + let flres = fl + 7.0 + flres = fl - 7.0 + flres = fl * 7.0 + flres = fl / 7.0 + endif +enddef + +def Test_computing() + let instr = execute('disassemble Computing') + assert_match('Computing.*' + \ .. 'let nr = 3.*' + \ .. '\d STORE 3 in $0.*' + \ .. 'let nrres = nr + 7.*' + \ .. '\d LOAD $0.*' + \ .. '\d PUSHNR 7.*' + \ .. '\d OPNR +.*' + \ .. '\d STORE $1.*' + \ .. 'nrres = nr - 7.*' + \ .. '\d OPNR -.*' + \ .. 'nrres = nr \* 7.*' + \ .. '\d OPNR \*.*' + \ .. 'nrres = nr / 7.*' + \ .. '\d OPNR /.*' + \ .. 'nrres = nr % 7.*' + \ .. '\d OPNR %.*' + \ .. 'let anyres = g:number + 7.*' + \ .. '\d LOADG g:number.*' + \ .. '\d PUSHNR 7.*' + \ .. '\d OPANY +.*' + \ .. '\d STORE $2.*' + \ .. 'anyres = g:number - 7.*' + \ .. '\d OPANY -.*' + \ .. 'anyres = g:number \* 7.*' + \ .. '\d OPANY \*.*' + \ .. 'anyres = g:number / 7.*' + \ .. '\d OPANY /.*' + \ .. 'anyres = g:number % 7.*' + \ .. '\d OPANY %.*' + \, instr) + if has('float') + assert_match('Computing.*' + \ .. 'let fl = 3.0.*' + \ .. '\d PUSHF 3.0.*' + \ .. '\d STORE $3.*' + \ .. 'let flres = fl + 7.0.*' + \ .. '\d LOAD $3.*' + \ .. '\d PUSHF 7.0.*' + \ .. '\d OPFLOAT +.*' + \ .. '\d STORE $4.*' + \ .. 'flres = fl - 7.0.*' + \ .. '\d OPFLOAT -.*' + \ .. 'flres = fl \* 7.0.*' + \ .. '\d OPFLOAT \*.*' + \ .. 'flres = fl / 7.0.*' + \ .. '\d OPFLOAT /.*' + \, instr) + endif +enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 4b03add2a9..82f1003beb 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 227, /**/ 226, /**/ From 348808f7c000a49d435c15db68c814b026f8167d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Feb 2020 20:50:07 +0100 Subject: [PATCH 09/55] patch 8.2.0228: configure does not recognize gcc version on BSD Problem: Configure does not recognize gcc version on BSD. Solution: Do not use "\+" in the pattern matching the version number. (Ozaki Kiichi, closes #5590) --- src/auto/configure | 2 +- src/configure.ac | 2 +- src/version.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index 59f3e68d63..ff2739c86f 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -14762,7 +14762,7 @@ DEPEND_CFLAGS_FILTER= if test "$GCC" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC 3 or later" >&5 $as_echo_n "checking for GCC 3 or later... " >&6; } - gccmajor=`echo "$gccversion" | sed -e 's/^\([0-9]\+\)\..*$/\1/g'` + gccmajor=`echo "$gccversion" | sed -e 's/^\([1-9][0-9]*\)\..*$/\1/g'` if test "$gccmajor" -gt "2"; then DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 diff --git a/src/configure.ac b/src/configure.ac index bf10eac551..fe2022802b 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4447,7 +4447,7 @@ dnl the number before the version number. DEPEND_CFLAGS_FILTER= if test "$GCC" = yes; then AC_MSG_CHECKING(for GCC 3 or later) - gccmajor=`echo "$gccversion" | sed -e 's/^\([[0-9]]\+\)\..*$/\1/g'` + gccmajor=`echo "$gccversion" | sed -e 's/^\([[1-9]][[0-9]]*\)\..*$/\1/g'` if test "$gccmajor" -gt "2"; then DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'" AC_MSG_RESULT(yes) diff --git a/src/version.c b/src/version.c index 82f1003beb..29c1614784 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 228, /**/ 227, /**/ From f2460a3aec89e70d4bab8d2369ee3f78cc43f09a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Feb 2020 22:09:54 +0100 Subject: [PATCH 10/55] patch 8.2.0229: compare instructions not tested Problem: Compare instructions not tested. Solution: Add test cases. Fix disassemble with line continuation. --- src/testdir/test_vim9_disassemble.vim | 123 +++++++++++++++++++++++--- src/version.c | 2 + src/vim9compile.c | 2 +- src/vim9execute.c | 5 +- 4 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index b6edb0d6c3..d10e74148d 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -20,7 +20,7 @@ def s:ScriptFuncLoad(arg: string) echo @z enddef -def Test_disassembleLoad() +def Test_disassemble_load() assert_fails('disass NoFunc', 'E1061:') assert_fails('disass NotCompiled', 'E1062:') @@ -47,7 +47,7 @@ def s:ScriptFuncPush() endif enddef -def Test_disassemblePush() +def Test_disassemble_push() let res = execute('disass s:ScriptFuncPush') assert_match('\d*_ScriptFuncPush.*' \ .. 'localbool = true.*' @@ -78,7 +78,7 @@ def s:ScriptFuncStore() @z = 'rv' enddef -def Test_disassembleStore() +def Test_disassemble_store() let res = execute('disass s:ScriptFuncStore') assert_match('\d*_ScriptFuncStore.*' \ .. 'localnr = 2.*' @@ -110,7 +110,7 @@ def s:ScriptFuncTry() endtry enddef -def Test_disassembleTry() +def Test_disassemble_try() let res = execute('disass s:ScriptFuncTry') assert_match('\d*_ScriptFuncTry.*' \ .. 'try.*' @@ -135,7 +135,7 @@ def s:ScriptFuncNew() let dd = #{one: 1, two: "val"} enddef -def Test_disassembleNew() +def Test_disassemble_new() let res = execute('disass s:ScriptFuncNew') assert_match('\d*_ScriptFuncNew.*' \ .. 'let ll = \[1, "two", 333].*' @@ -167,7 +167,7 @@ endfunc def s:ScriptFuncCall(): string changenr() char2nr("abc") - Test_disassembleNew() + Test_disassemble_new() FuncWithArg(343) ScriptFuncNew() s:ScriptFuncNew() @@ -180,7 +180,7 @@ def s:ScriptFuncCall(): string return "yes" enddef -def Test_disassembleCall() +def Test_disassemble_call() let res = execute('disass s:ScriptFuncCall') assert_match('\d\+_ScriptFuncCall.*' \ .. 'changenr().*' @@ -188,8 +188,8 @@ def Test_disassembleCall() \ .. 'char2nr("abc").*' \ .. ' PUSHS "abc".*' \ .. ' BCALL char2nr(argc 1).*' - \ .. 'Test_disassembleNew().*' - \ .. ' DCALL Test_disassembleNew(argc 0).*' + \ .. 'Test_disassemble_new().*' + \ .. ' DCALL Test_disassemble_new(argc 0).*' \ .. 'FuncWithArg(343).*' \ .. ' PUSHNR 343.*' \ .. ' DCALL FuncWithArg(argc 1).*' @@ -245,7 +245,7 @@ def HasSomething() endif enddef -def Test_compile_const_expr() +def Test_disassemble_const_expr() assert_equal("\nyes", execute('call HasEval()')) let instr = execute('disassemble HasEval') assert_match('HasEval.*' @@ -284,7 +284,7 @@ def WithLambda(): string return F("x") enddef -def Test_compile_lambda() +def Test_disassemble_lambda() assert_equal("XxX", WithLambda()) let instr = execute('disassemble WithLambda') assert_match('WithLambda.*' @@ -304,7 +304,7 @@ def AndOr(arg): string return 'no' enddef -def Test_compile_and_or() +def Test_disassemble_and_or() assert_equal("yes", AndOr(1)) assert_equal("no", AndOr(2)) assert_equal("yes", AndOr(4)) @@ -334,7 +334,7 @@ def ForLoop(): list return res enddef -def Test_compile_for_loop() +def Test_disassemble_for_loop() assert_equal([0, 1, 2], ForLoop()) let instr = execute('disassemble ForLoop') assert_match('ForLoop.*' @@ -383,7 +383,7 @@ def Computing() endif enddef -def Test_computing() +def Test_disassemble_computing() let instr = execute('disassemble Computing') assert_match('Computing.*' \ .. 'let nr = 3.*' @@ -435,4 +435,99 @@ def Test_computing() endif enddef +def Test_disassemble_compare() + " TODO: COMPAREFUNC + let cases = [ + \ ['true == false', 'COMPAREBOOL =='], + \ ['true != false', 'COMPAREBOOL !='], + \ ['v:none == v:null', 'COMPARESPECIAL =='], + \ ['v:none != v:null', 'COMPARESPECIAL !='], + \ + \ ['111 == 222', 'COMPARENR =='], + \ ['111 != 222', 'COMPARENR !='], + \ ['111 > 222', 'COMPARENR >'], + \ ['111 < 222', 'COMPARENR <'], + \ ['111 >= 222', 'COMPARENR >='], + \ ['111 <= 222', 'COMPARENR <='], + \ ['111 =~ 222', 'COMPARENR =\~'], + \ ['111 !~ 222', 'COMPARENR !\~'], + \ + \ ['"xx" == "yy"', 'COMPARESTRING =='], + \ ['"xx" != "yy"', 'COMPARESTRING !='], + \ ['"xx" > "yy"', 'COMPARESTRING >'], + \ ['"xx" < "yy"', 'COMPARESTRING <'], + \ ['"xx" >= "yy"', 'COMPARESTRING >='], + \ ['"xx" <= "yy"', 'COMPARESTRING <='], + \ ['"xx" =~ "yy"', 'COMPARESTRING =\~'], + \ ['"xx" !~ "yy"', 'COMPARESTRING !\~'], + \ ['"xx" is "yy"', 'COMPARESTRING is'], + \ ['"xx" isnot "yy"', 'COMPARESTRING isnot'], + \ + \ ['0z11 == 0z22', 'COMPAREBLOB =='], + \ ['0z11 != 0z22', 'COMPAREBLOB !='], + \ ['0z11 is 0z22', 'COMPAREBLOB is'], + \ ['0z11 isnot 0z22', 'COMPAREBLOB isnot'], + \ + \ ['[1,2] == [3,4]', 'COMPARELIST =='], + \ ['[1,2] != [3,4]', 'COMPARELIST !='], + \ ['[1,2] is [3,4]', 'COMPARELIST is'], + \ ['[1,2] isnot [3,4]', 'COMPARELIST isnot'], + \ + \ ['#{a:1} == #{x:2}', 'COMPAREDICT =='], + \ ['#{a:1} != #{x:2}', 'COMPAREDICT !='], + \ ['#{a:1} is #{x:2}', 'COMPAREDICT is'], + \ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'], + \ + \ ['{->33} == {->44}', 'COMPAREPARTIAL =='], + \ ['{->33} != {->44}', 'COMPAREPARTIAL !='], + \ ['{->33} is {->44}', 'COMPAREPARTIAL is'], + \ ['{->33} isnot {->44}', 'COMPAREPARTIAL isnot'], + \ + \ ['77 == g:xx', 'COMPAREANY =='], + \ ['77 != g:xx', 'COMPAREANY !='], + \ ['77 > g:xx', 'COMPAREANY >'], + \ ['77 < g:xx', 'COMPAREANY <'], + \ ['77 >= g:xx', 'COMPAREANY >='], + \ ['77 <= g:xx', 'COMPAREANY <='], + \ ['77 =~ g:xx', 'COMPAREANY =\~'], + \ ['77 !~ g:xx', 'COMPAREANY !\~'], + \ ['77 is g:xx', 'COMPAREANY is'], + \ ['77 isnot g:xx', 'COMPAREANY isnot'], + \ ] + if has('float') + cases->extend([ + \ ['1.1 == 2.2', 'COMPAREFLOAT =='], + \ ['1.1 != 2.2', 'COMPAREFLOAT !='], + \ ['1.1 > 2.2', 'COMPAREFLOAT >'], + \ ['1.1 < 2.2', 'COMPAREFLOAT <'], + \ ['1.1 >= 2.2', 'COMPAREFLOAT >='], + \ ['1.1 <= 2.2', 'COMPAREFLOAT <='], + \ ['1.1 =~ 2.2', 'COMPAREFLOAT =\~'], + \ ['1.1 !~ 2.2', 'COMPAREFLOAT !\~'], + \ ]) + endif + + let nr = 1 + for case in cases + writefile(['def TestCase' .. nr .. '()', + \ ' if ' .. case[0], + \ ' echo 42' + \ ' endif', + \ 'enddef'], 'Xdisassemble') + source Xdisassemble + let instr = execute('disassemble TestCase' .. nr) + assert_match('TestCase' .. nr .. '.*' + \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' + \ .. '\d \(PUSH\|FUNCREF\).*' + \ .. '\d \(PUSH\|FUNCREF\|LOADG\).*' + \ .. '\d ' .. case[1] .. '.*' + \ .. '\d JUMP_IF_FALSE -> \d\+.*' + \, instr) + + nr += 1 + endfor + + " delete('Xdisassemble') +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 29c1614784..b08433c079 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 229, /**/ 228, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 0c72168f1b..96037d917f 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2342,7 +2342,7 @@ compile_subscript( emsg(_(e_missbrac)); return FAIL; } - *arg = skipwhite(*arg + 1); + *arg = *arg + 1; if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL) return FAIL; diff --git a/src/vim9execute.c b/src/vim9execute.c index 1b45bf9937..ed3a75b106 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1622,6 +1622,7 @@ ex_disassemble(exarg_T *eap) for (current = 0; current < dfunc->df_instr_count; ++current) { isn_T *iptr = &instr[current]; + char *line; while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) { @@ -1630,7 +1631,9 @@ ex_disassemble(exarg_T *eap) msg_puts("\n\n"); prev_current = current; } - msg(((char **)ufunc->uf_lines.ga_data)[line_idx++]); + line = ((char **)ufunc->uf_lines.ga_data)[line_idx++]; + if (line != NULL) + msg(line); } switch (iptr->isn_type) From 670218839aef105e83f8effaa1c83100c61c7bcf Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Feb 2020 22:20:53 +0100 Subject: [PATCH 11/55] patch 8.2.0230: terminal popup test is flaky Problem: Terminal popup test is flaky. Solution: Increase wait time a bit. --- src/testdir/test_terminal.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 605ac06fa8..0963405e83 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2362,7 +2362,7 @@ func Test_terminal_in_popup() call term_sendkeys(buf, "\:call HidePopup()\") call VerifyScreenDump(buf, 'Test_terminal_popup_4', {}) call term_sendkeys(buf, "\") - call term_wait(buf, 50) + call term_wait(buf, 100) call term_sendkeys(buf, ":q\") call term_wait(buf, 100) " wait for terminal to vanish diff --git a/src/version.c b/src/version.c index b08433c079..8bd7d10bfb 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 230, /**/ 229, /**/ From d02e508a18346ca1acb8c0c94c38e62a6ddeefe2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Feb 2020 14:22:53 +0100 Subject: [PATCH 12/55] patch 8.2.0231: silent system command may clear the screen Problem: Silent system command may clear the screen. Solution: Do not clear the screen in t_te. --- src/term.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/term.c b/src/term.c index 139928683c..b942b0f4b9 100644 --- a/src/term.c +++ b/src/term.c @@ -909,8 +909,8 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_KE, IF_EB("\033[?1l\033>", ESC_STR "[?1l" ESC_STR_nc ">")}, # ifdef FEAT_XTERM_SAVE {(int)KS_TI, IF_EB("\0337\033[?47h", ESC_STR "7" ESC_STR_nc "[?47h")}, - {(int)KS_TE, IF_EB("\033[2J\033[?47l\0338", - ESC_STR "[2J" ESC_STR_nc "[?47l" ESC_STR_nc "8")}, + {(int)KS_TE, IF_EB("\033[?47l\0338", + ESC_STR_nc "[?47l" ESC_STR_nc "8")}, # endif {(int)KS_CTI, IF_EB("\033[>4;2m", ESC_STR_nc "[>4;2m")}, {(int)KS_CTE, IF_EB("\033[>4;m", ESC_STR_nc "[>4;m")}, diff --git a/src/version.c b/src/version.c index 8bd7d10bfb..db1f9f77b7 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 231, /**/ 230, /**/ From 165315584d6587e287f54d6c8820e050114b5694 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Feb 2020 16:00:46 +0100 Subject: [PATCH 13/55] patch 8.2.0232: the :compiler command causes a crash Problem: The :compiler command causes a crash. (Daniel Steinberg) Solution: Do not use the script index if it isn't set. --- src/ex_docmd.c | 3 ++- src/testdir/test_compiler.vim | 10 ++++++++++ src/version.c | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 645ad0c93c..659af19111 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2495,7 +2495,8 @@ do_one_cmd( #ifdef FEAT_EVAL // Set flag that any command was executed, used by ex_vim9script(). - if (getline_equal(ea.getline, ea.cookie, getsourceline)) + if (getline_equal(ea.getline, ea.cookie, getsourceline) + && current_sctx.sc_sid > 0) SCRIPT_ITEM(current_sctx.sc_sid)->sn_had_command = TRUE; /* diff --git a/src/testdir/test_compiler.vim b/src/testdir/test_compiler.vim index 4f02cf1c2f..464dd9bcb5 100644 --- a/src/testdir/test_compiler.vim +++ b/src/testdir/test_compiler.vim @@ -1,6 +1,7 @@ " Test the :compiler command source check.vim +source shared.vim func Test_compiler() if !executable('perl') @@ -48,6 +49,15 @@ func Test_compiler_without_arg() call assert_match(runtime .. '/compiler/xmlwf.vim$', a[-1]) endfunc +" Test executing :compiler from the command line, not from a script +func Test_compiler_commandline() + call system(GetVimCommandClean() .. ' --not-a-term -c "compiler gcc" -c "call writefile([b:current_compiler], ''XcompilerOut'')" -c "quit"') + call assert_equal(0, v:shell_error) + call assert_equal(["gcc"], readfile('XcompilerOut')) + + call delete('XcompilerOut') +endfunc + func Test_compiler_completion() call feedkeys(":compiler \\\"\", 'tx') call assert_match('^"compiler ant bcc .* xmlwf$', @:) diff --git a/src/version.c b/src/version.c index db1f9f77b7..e1fde105f9 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 232, /**/ 231, /**/ From 4f645c54efe33d7a11e314676e503118761f08a7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Feb 2020 16:40:39 +0100 Subject: [PATCH 14/55] patch 8.2.0233: crash when using garbagecollect() in between rand() Problem: Crash when using garbagecollect() in between rand(). Solution: Redesign the rand() and srand() implementation. (Yasuhiro Matsumoto, closes #5587, closes #5588) --- runtime/doc/eval.txt | 1 + runtime/doc/testing.txt | 5 +- src/evalfunc.c | 254 ++++++++++++++++++++---------------- src/testdir/test_random.vim | 15 ++- src/version.c | 2 + 5 files changed, 163 insertions(+), 114 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 26e7d12de4..afbfd9f7e5 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2867,6 +2867,7 @@ test_refcount({expr}) Number get the reference count of {expr} test_scrollbar({which}, {value}, {dragging}) none scroll in the GUI for testing test_setmouse({row}, {col}) none set the mouse position for testing +test_srand_seed([seed]) none set seed for testing srand() test_settime({expr}) none set current time for testing timer_info([{id}]) List information about timers timer_pause({id}, {pause}) none pause or unpause a timer diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index 7fb24e6307..f2a7cf16c5 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -210,7 +210,6 @@ test_setmouse({row}, {col}) *test_setmouse()* call test_setmouse(4, 20) call feedkeys("\", "xt") - test_settime({expr}) *test_settime()* Set the time Vim uses internally. Currently only used for timestamps in the history, as they are used in viminfo, and @@ -223,6 +222,10 @@ test_settime({expr}) *test_settime()* Can also be used as a |method|: > GetTime()->test_settime() +test_srand_seed([seed]) *test_srand_seed()* + When [seed] is given this sets the seed value used by + `srand()`. When omitted the test seed is removed. + ============================================================================== 3. Assert functions *assert-functions-details* diff --git a/src/evalfunc.c b/src/evalfunc.c index aac8ee9058..66be42c241 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -168,6 +168,7 @@ static void f_pyeval(typval_T *argvars, typval_T *rettv); #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) static void f_pyxeval(typval_T *argvars, typval_T *rettv); #endif +static void f_test_srand_seed(typval_T *argvars, typval_T *rettv); static void f_rand(typval_T *argvars, typval_T *rettv); static void f_range(typval_T *argvars, typval_T *rettv); static void f_reg_executing(typval_T *argvars, typval_T *rettv); @@ -835,6 +836,7 @@ static funcentry_T global_functions[] = #endif {"test_setmouse", 2, 2, 0, &t_void, f_test_setmouse}, {"test_settime", 1, 1, FEARG_1, &t_void, f_test_settime}, + {"test_srand_seed", 0, 1, FEARG_1, &t_void, f_test_srand_seed}, #ifdef FEAT_TIMERS {"timer_info", 0, 1, FEARG_1, &t_list_dict_any, f_timer_info}, {"timer_pause", 2, 2, FEARG_1, &t_void, f_timer_pause}, @@ -5225,6 +5227,83 @@ f_pyxeval(typval_T *argvars, typval_T *rettv) } #endif +static UINT32_T srand_seed_for_testing = 0; +static int srand_seed_for_testing_is_used = FALSE; + + static void +f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED) +{ + if (argvars[0].v_type == VAR_UNKNOWN) + srand_seed_for_testing_is_used = FALSE; + else + { + srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]); + srand_seed_for_testing_is_used = TRUE; + } +} + + static void +init_srand(UINT32_T *x) +{ +#ifndef MSWIN + static int dev_urandom_state = NOTDONE; // FAIL or OK once tried +#endif + + if (srand_seed_for_testing_is_used) + { + *x = srand_seed_for_testing; + return; + } +#ifndef MSWIN + if (dev_urandom_state != FAIL) + { + int fd = open("/dev/urandom", O_RDONLY); + struct { + union { + UINT32_T number; + char bytes[sizeof(UINT32_T)]; + } contents; + } buf; + + // Attempt reading /dev/urandom. + if (fd == -1) + dev_urandom_state = FAIL; + else + { + buf.contents.number = 0; + if (read(fd, buf.contents.bytes, sizeof(UINT32_T)) + != sizeof(UINT32_T)) + dev_urandom_state = FAIL; + else + { + dev_urandom_state = OK; + *x = buf.contents.number; + } + close(fd); + } + } + if (dev_urandom_state != OK) + // Reading /dev/urandom doesn't work, fall back to time(). +#endif + *x = vim_time(); +} + +#define ROTL(x, k) ((x << k) | (x >> (32 - k))) +#define SPLITMIX32(x, z) ( \ + z = (x += 0x9e3779b9), \ + z = (z ^ (z >> 16)) * 0x85ebca6b, \ + z = (z ^ (z >> 13)) * 0xc2b2ae35, \ + z ^ (z >> 16) \ + ) +#define SHUFFLE_XOSHIRO128STARSTAR(x, y, z, w) \ + result = ROTL(y * 5, 7) * 9; \ + t = y << 9; \ + z ^= x; \ + w ^= y; \ + y ^= z, x ^= w; \ + z ^= t; \ + w = ROTL(w, 11); + /* * "rand()" function */ @@ -5232,66 +5311,57 @@ f_pyxeval(typval_T *argvars, typval_T *rettv) f_rand(typval_T *argvars, typval_T *rettv) { list_T *l = NULL; - static list_T *globl = NULL; - UINT32_T x, y, z, w, t, result; + static UINT32_T gx, gy, gz, gw; + static int initialized = FALSE; listitem_T *lx, *ly, *lz, *lw; + UINT32_T x, y, z, w, t, result; if (argvars[0].v_type == VAR_UNKNOWN) { // When no argument is given use the global seed list. - if (globl == NULL) + if (initialized == FALSE) { // Initialize the global seed list. - f_srand(argvars, rettv); - l = rettv->vval.v_list; - if (l == NULL || list_len(l) != 4) - { - clear_tv(rettv); - goto theend; - } - globl = l; + init_srand(&x); + + gx = SPLITMIX32(x, z); + gy = SPLITMIX32(x, z); + gz = SPLITMIX32(x, z); + gw = SPLITMIX32(x, z); + initialized = TRUE; } - else - l = globl; + + SHUFFLE_XOSHIRO128STARSTAR(gx, gy, gz, gw); } else if (argvars[0].v_type == VAR_LIST) { l = argvars[0].vval.v_list; if (l == NULL || list_len(l) != 4) goto theend; + + lx = list_find(l, 0L); + ly = list_find(l, 1L); + lz = list_find(l, 2L); + lw = list_find(l, 3L); + if (lx->li_tv.v_type != VAR_NUMBER) goto theend; + if (ly->li_tv.v_type != VAR_NUMBER) goto theend; + if (lz->li_tv.v_type != VAR_NUMBER) goto theend; + if (lw->li_tv.v_type != VAR_NUMBER) goto theend; + x = (UINT32_T)lx->li_tv.vval.v_number; + y = (UINT32_T)ly->li_tv.vval.v_number; + z = (UINT32_T)lz->li_tv.vval.v_number; + w = (UINT32_T)lw->li_tv.vval.v_number; + + SHUFFLE_XOSHIRO128STARSTAR(x, y, z, w); + + lx->li_tv.vval.v_number = (varnumber_T)x; + ly->li_tv.vval.v_number = (varnumber_T)y; + lz->li_tv.vval.v_number = (varnumber_T)z; + lw->li_tv.vval.v_number = (varnumber_T)w; } else goto theend; - lx = list_find(l, 0L); - ly = list_find(l, 1L); - lz = list_find(l, 2L); - lw = list_find(l, 3L); - if (lx->li_tv.v_type != VAR_NUMBER) goto theend; - if (ly->li_tv.v_type != VAR_NUMBER) goto theend; - if (lz->li_tv.v_type != VAR_NUMBER) goto theend; - if (lw->li_tv.v_type != VAR_NUMBER) goto theend; - x = (UINT32_T)lx->li_tv.vval.v_number; - y = (UINT32_T)ly->li_tv.vval.v_number; - z = (UINT32_T)lz->li_tv.vval.v_number; - w = (UINT32_T)lw->li_tv.vval.v_number; - - // SHUFFLE_XOSHIRO128STARSTAR -#define ROTL(x, k) ((x << k) | (x >> (32 - k))) - result = ROTL(y * 5, 7) * 9; - t = y << 9; - z ^= x; - w ^= y; - y ^= z, x ^= w; - z ^= t; - w = ROTL(w, 11); -#undef ROTL - - lx->li_tv.vval.v_number = (varnumber_T)x; - ly->li_tv.vval.v_number = (varnumber_T)y; - lz->li_tv.vval.v_number = (varnumber_T)z; - lw->li_tv.vval.v_number = (varnumber_T)w; - rettv->v_type = VAR_NUMBER; rettv->vval.v_number = (varnumber_T)result; return; @@ -5302,6 +5372,39 @@ theend: rettv->vval.v_number = -1; } +/* + * "srand()" function + */ + static void +f_srand(typval_T *argvars, typval_T *rettv) +{ + UINT32_T x = 0, z; + + if (rettv_list_alloc(rettv) == FAIL) + return; + if (argvars[0].v_type == VAR_UNKNOWN) + { + init_srand(&x); + } + else + { + int error = FALSE; + + x = (UINT32_T)tv_get_number_chk(&argvars[0], &error); + if (error) + return; + } + + list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z)); + list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z)); + list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z)); + list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32(x, z)); +} + +#undef ROTL +#undef SPLITMIX32 +#undef SHUFFLE_XOSHIRO128STARSTAR + /* * "range()" function */ @@ -7217,73 +7320,6 @@ f_sqrt(typval_T *argvars, typval_T *rettv) } #endif -/* - * "srand()" function - */ - static void -f_srand(typval_T *argvars, typval_T *rettv) -{ - static int dev_urandom_state = -1; // FAIL or OK once tried - UINT32_T x = 0, z; - - if (rettv_list_alloc(rettv) == FAIL) - return; - if (argvars[0].v_type == VAR_UNKNOWN) - { - if (dev_urandom_state != FAIL) - { - int fd = open("/dev/urandom", O_RDONLY); - struct { - union { - UINT32_T number; - char bytes[sizeof(UINT32_T)]; - } cont; - } buf; - - // Attempt reading /dev/urandom. - if (fd == -1) - dev_urandom_state = FAIL; - else - { - buf.cont.number = 0; - if (read(fd, buf.cont.bytes, sizeof(UINT32_T)) - != sizeof(UINT32_T)) - dev_urandom_state = FAIL; - else - { - dev_urandom_state = OK; - x = buf.cont.number; - } - close(fd); - } - - } - if (dev_urandom_state != OK) - // Reading /dev/urandom doesn't work, fall back to time(). - x = vim_time(); - } - else - { - int error = FALSE; - - x = (UINT32_T)tv_get_number_chk(&argvars[0], &error); - if (error) - return; - } - -#define SPLITMIX32 ( \ - z = (x += 0x9e3779b9), \ - z = (z ^ (z >> 16)) * 0x85ebca6b, \ - z = (z ^ (z >> 13)) * 0xc2b2ae35, \ - z ^ (z >> 16) \ - ) - - list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32); - list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32); - list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32); - list_append_number(rettv->vval.v_list, (varnumber_T)SPLITMIX32); -} - #ifdef FEAT_FLOAT /* * "str2float()" function diff --git a/src/testdir/test_random.vim b/src/testdir/test_random.vim index 747e438486..bdb7e1db0e 100644 --- a/src/testdir/test_random.vim +++ b/src/testdir/test_random.vim @@ -11,7 +11,7 @@ func Test_Rand() call test_settime(12341234) let s = srand() - if filereadable('/dev/urandom') + if !has('win32') && filereadable('/dev/urandom') " using /dev/urandom call assert_notequal(s, srand()) else @@ -21,9 +21,10 @@ func Test_Rand() call assert_notequal(s, srand()) endif - call srand() - let v = rand() - call assert_notequal(v, rand()) + call test_srand_seed(123456789) + call assert_equal(4284103975, rand()) + call assert_equal(1001954530, rand()) + call test_srand_seed() if has('float') call assert_fails('echo srand(1.2)', 'E805:') @@ -38,3 +39,9 @@ func Test_Rand() call test_settime(0) endfunc + +func Test_issue_5587() + call rand() + call garbagecollect() + call rand() +endfunc diff --git a/src/version.c b/src/version.c index e1fde105f9..99c63569d1 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 233, /**/ 232, /**/ From d5b991493816a2edba7cacdd06820cf3c0abc4dc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Feb 2020 17:14:46 +0100 Subject: [PATCH 15/55] patch 8.2.0234: message test fails on SunOS Problem: Message test fails on SunOS. Solution: Adjust expectation for printf "%p". (Ozaki Kiichi, closes #5595) --- src/message_test.c | 18 +++++++++++++++--- src/version.c | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/message_test.c b/src/message_test.c index 3397a9cb47..7f6540b310 100644 --- a/src/message_test.c +++ b/src/message_test.c @@ -240,14 +240,26 @@ test_vim_snprintf(void) // %p format is not tested in vim script tests Test_printf*() // as it only makes sense in C code. + // NOTE: SunOS libc doesn't use the prefix "0x" on %p. +#ifdef SUN_SYSTEM +# define PREFIX_LEN 0 +# define PREFIX_STR1 "" +# define PREFIX_STR2 "00" +#else +# define PREFIX_LEN 2 +# define PREFIX_STR1 "0x" +# define PREFIX_STR2 "0x" +#endif n = vim_snprintf(buf, bsize, "%p", ptr); - assert(n == 10); - assert(bsize == 0 || STRNCMP(buf, "0x87654321", bsize_int) == 0); + assert(n == 8 + PREFIX_LEN); + assert(bsize == 0 + || STRNCMP(buf, PREFIX_STR1 "87654321", bsize_int) == 0); assert(bsize == 0 || buf[MIN(n, bsize_int)] == '\0'); n = vim_snprintf(buf, bsize, fmt_012p, ptr); assert(n == 12); - assert(bsize == 0 || STRNCMP(buf, "0x0087654321", bsize_int) == 0); + assert(bsize == 0 + || STRNCMP(buf, PREFIX_STR2 "0087654321", bsize_int) == 0); assert(bsize == 0 || buf[MIN(n, bsize_int)] == '\0'); free(buf); diff --git a/src/version.c b/src/version.c index 99c63569d1..e1c6e319bf 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 234, /**/ 233, /**/ From dbe5d361feb65137099644329cf0ecfd4a945a14 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Feb 2020 18:35:31 +0100 Subject: [PATCH 16/55] patch 8.2.0235: draw error when an empty group is removed from 'statusline' Problem: Draw error when an empty group is removed from 'statusline'. Solution: Do not use highlighting from a removed group. --- src/buffer.c | 4 ++++ src/testdir/dumps/Test_statusline_1.dump | 10 ++++++++++ src/testdir/test_statusline.vim | 20 ++++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 36 insertions(+) create mode 100644 src/testdir/dumps/Test_statusline_1.dump diff --git a/src/buffer.c b/src/buffer.c index 7ff8097737..25620afb5d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -4216,6 +4216,10 @@ build_stl_str_hl( { p = t; l = 0; + // do not use the highlighting from the removed group + for (n = groupitem[groupdepth] + 1; n < curitem; n++) + if (item[n].type == Highlight) + item[n].type = Empty; } } if (l > item[groupitem[groupdepth]].maxwid) diff --git a/src/testdir/dumps/Test_statusline_1.dump b/src/testdir/dumps/Test_statusline_1.dump new file mode 100644 index 0000000000..f9816857af --- /dev/null +++ b/src/testdir/dumps/Test_statusline_1.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@49 +|~+0#4040ff13&| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +| +3#0000000&|Q|≡| @46 +| +0&&@49 diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim index 1f705b847f..ebfe8aac66 100644 --- a/src/testdir/test_statusline.vim +++ b/src/testdir/test_statusline.vim @@ -8,6 +8,7 @@ source view_util.vim source check.vim +source screendump.vim func s:get_statusline() return ScreenLines(&lines - 1, &columns)[0] @@ -393,3 +394,22 @@ func Test_statusline_visual() bwipe! x1 bwipe! x2 endfunc + +func Test_statusline_removed_group() + CheckScreendump + + let lines =<< trim END + scriptencoding utf-8 + set laststatus=2 + let &statusline = '%#StatColorHi2#%(✓%#StatColorHi2#%) Q≡' + END + call writefile(lines, 'XTest_statusline') + + let buf = RunVimInTerminal('-S XTest_statusline', {'rows': 10, 'cols': 50}) + call term_wait(buf, 100) + call VerifyScreenDump(buf, 'Test_statusline_1', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('XTest_statusline') +endfunc diff --git a/src/version.c b/src/version.c index e1c6e319bf..6a5f2e779c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 235, /**/ 234, /**/ From 57ea2924e5dd14aac716a1ee349bdb61f6429f59 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Feb 2020 14:27:20 +0100 Subject: [PATCH 17/55] patch 8.2.0236: MS-Windows unintall doesn't delete vimtutur.bat Problem: MS-Windows unintall doesn't delete vimtutur.bat. Solution: Change directory before deletion. (Ken Takata, closes #5603) --- src/uninstall.c | 6 ++++++ src/version.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/uninstall.c b/src/uninstall.c index b2a20cded8..ef0538a140 100644 --- a/src/uninstall.c +++ b/src/uninstall.c @@ -233,6 +233,10 @@ remove_batfiles(int doit) int i; int found = 0; + // avoid looking in the "installdir" by chdir to system root + mch_chdir(sysdrive); + mch_chdir("\\"); + for (i = 1; i < TARGET_COUNT; ++i) { batfile_path = searchpath_save(targets[i].batname); @@ -249,6 +253,8 @@ remove_batfiles(int doit) free(batfile_path); } } + + mch_chdir(installdir); return found; } diff --git a/src/version.c b/src/version.c index 6a5f2e779c..7ca6baacf1 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 236, /**/ 235, /**/ From 7ba3b91e0385c848c773e2f2d803db01730e7786 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Feb 2020 20:34:04 +0100 Subject: [PATCH 18/55] patch 8.2.0237: crash when setting 'wincolor' on finished terminal window Problem: Crash when setting 'wincolor' on finished terminal window. (Bakudankun) Solution: Check that the vterm is not NULL. (Yasuhiro Matsumoto, closes #5607, closes #5610) --- src/terminal.c | 2 ++ src/testdir/test_terminal.vim | 15 +++++++++++++++ src/version.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/terminal.c b/src/terminal.c index cbf8fe0799..10bfae8424 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -4276,6 +4276,8 @@ term_update_colors(void) { term_T *term = curwin->w_buffer->b_term; + if (term->tl_vterm == NULL) + return; init_default_colors(term, curwin); vterm_state_set_default_colors( vterm_obtain_state(term->tl_vterm), diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 0963405e83..8c1d3572a6 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2370,3 +2370,18 @@ func Test_terminal_in_popup() call StopVimInTerminal(buf) call delete('XtermPopup') endfunc + +func Test_issue_5607() + let wincount = winnr('$') + exe 'terminal' &shell &shellcmdflag 'exit' + let job = term_getjob(bufnr()) + call WaitForAssert({-> assert_equal("dead", job_status(job))}) + + let old_wincolor = &wincolor + try + set wincolor= + finally + let &wincolor = old_wincolor + bw! + endtry +endfunc diff --git a/src/version.c b/src/version.c index 7ca6baacf1..7c48e0bdc8 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 237, /**/ 236, /**/ From b3e195cca7b3201b188c1713b64012b1bef4f61f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Feb 2020 21:32:19 +0100 Subject: [PATCH 19/55] patch 8.2.0238: MS-Windows: job_stop() results in exit value zero Problem: MS-Windows: job_stop() results in exit value zero. Solution: Call TerminateJobObject() with -1 instead of 0. (Yasuhiro Matsumoto, closes #5150, closes #5614) --- src/os_win32.c | 4 ++-- src/testdir/test_channel.vim | 15 +++++++++++++++ src/version.c | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/os_win32.c b/src/os_win32.c index 7dc37a1114..2594aeea56 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -5384,9 +5384,9 @@ mch_signal_job(job_T *job, char_u *how) { if (job->jv_channel != NULL && job->jv_channel->ch_anonymous_pipe) job->jv_channel->ch_killing = TRUE; - return TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL; + return TerminateJobObject(job->jv_job_object, -1) ? OK : FAIL; } - return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL; + return terminate_all(job->jv_proc_info.hProcess, -1) ? OK : FAIL; } if (!AttachConsole(job->jv_proc_info.dwProcessId)) diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index c2068105bf..ebcd76e0ff 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -1991,3 +1991,18 @@ func Test_job_start_fails() " this was leaking memory call assert_fails("call job_start([''])", "E474:") endfunc + +func Test_issue_5150() + let g:job = job_start('grep foo', {}) + call job_stop(g:job) + sleep 10m + call assert_equal(-1, job_info(g:job).exitval) + let g:job = job_start('grep foo', {}) + call job_stop(g:job, 'term') + sleep 10m + call assert_equal(-1, job_info(g:job).exitval) + let g:job = job_start('grep foo', {}) + call job_stop(g:job, 'kill') + sleep 10m + call assert_equal(-1, job_info(g:job).exitval) +endfunc diff --git a/src/version.c b/src/version.c index 7c48e0bdc8..61a9f958a4 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 238, /**/ 237, /**/ From 355757aed6ae2ae5446882570d89f243e4805937 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Feb 2020 22:06:32 +0100 Subject: [PATCH 20/55] patch 8.2.0239: MS-Windows: 'env' job option does not override existing vars Problem: MS-Windows: 'env' job option does not override existing environment variables. (Tim Pope) Solution: Set the environment variables later. (Yasuhiro Matsumoto, closes #5485, closes #5608) --- src/os_win32.c | 36 ++++++++++++++++++------------------ src/testdir/test_channel.vim | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/os_win32.c b/src/os_win32.c index 2594aeea56..f394979d60 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -4948,24 +4948,6 @@ win32_build_env(dict_T *env, garray_T *gap, int is_terminal) if (ga_grow(gap, 1) == FAIL) return; - if (base) - { - WCHAR *p = (WCHAR*) base; - - // for last \0 - if (ga_grow(gap, 1) == FAIL) - return; - - while (*p != 0 || *(p + 1) != 0) - { - if (ga_grow(gap, 1) == OK) - *((WCHAR*)gap->ga_data + gap->ga_len++) = *p; - p++; - } - FreeEnvironmentStrings(base); - *((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0'; - } - if (env != NULL) { for (hi = env->dv_hashtab.ht_array; todo > 0; ++hi) @@ -4997,6 +4979,24 @@ win32_build_env(dict_T *env, garray_T *gap, int is_terminal) } } + if (base) + { + WCHAR *p = (WCHAR*) base; + + // for last \0 + if (ga_grow(gap, 1) == FAIL) + return; + + while (*p != 0 || *(p + 1) != 0) + { + if (ga_grow(gap, 1) == OK) + *((WCHAR*)gap->ga_data + gap->ga_len++) = *p; + p++; + } + FreeEnvironmentStrings(base); + *((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0'; + } + # if defined(FEAT_CLIENTSERVER) || defined(FEAT_TERMINAL) { # ifdef FEAT_CLIENTSERVER diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index ebcd76e0ff..16fe5c7829 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -2006,3 +2006,12 @@ func Test_issue_5150() sleep 10m call assert_equal(-1, job_info(g:job).exitval) endfunc + +func Test_issue_5485() + let $VAR1 = 'global' + let g:Ch_reply = "" + let l:job = job_start([&shell, &shellcmdflag, has('win32') ? 'echo %VAR1% %VAR2%' : 'echo $VAR1 $VAR2'], {'env': {'VAR1': 'local', 'VAR2': 'local'}, 'callback': 'Ch_handler'}) + let g:Ch_job = l:job + call WaitForAssert({-> assert_equal("local local", trim(g:Ch_reply))}) + unlet $VAR1 +endfunc diff --git a/src/version.c b/src/version.c index 61a9f958a4..cf96f40514 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 239, /**/ 238, /**/ From 408030e8d053fe1c871b2fc366363a30ed98c889 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Feb 2020 22:44:32 +0100 Subject: [PATCH 21/55] patch 8.2.0240: using memory after it was freed Problem: Using memory after it was freed. (Dominique Pelle) Solution: Do not mix converion buffer with other buffer. --- src/version.c | 2 ++ src/vim.h | 14 -------------- src/viminfo.c | 24 +++++++++++++++++++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/version.c b/src/version.c index cf96f40514..7eaf24bdd1 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 240, /**/ 239, /**/ diff --git a/src/vim.h b/src/vim.h index 12af8560c6..270109ace9 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1129,20 +1129,6 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define VIMINFO_VERSION_WITH_REGISTERS 3 #define VIMINFO_VERSION_WITH_MARKS 4 -typedef enum { - BVAL_NR, - BVAL_STRING, - BVAL_EMPTY -} btype_T; - -typedef struct { - btype_T bv_type; - long bv_nr; - char_u *bv_string; - int bv_len; // length of bv_string - int bv_allocated; // bv_string was allocated -} bval_T; - /* * Values for do_tag(). */ diff --git a/src/viminfo.c b/src/viminfo.c index b2b7ab28b0..897e864629 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -26,6 +26,21 @@ typedef struct garray_T vir_barlines; // lines starting with | } vir_T; +typedef enum { + BVAL_NR, + BVAL_STRING, + BVAL_EMPTY +} btype_T; + +typedef struct { + btype_T bv_type; + long bv_nr; + char_u *bv_string; + char_u *bv_tofree; // free later when not NULL + int bv_len; // length of bv_string + int bv_allocated; // bv_string was allocated +} bval_T; + #if defined(FEAT_VIMINFO) || defined(PROTO) static int viminfo_errcnt; @@ -1087,22 +1102,24 @@ barline_parse(vir_T *virp, char_u *text, garray_T *values) s[len] = NUL; converted = FALSE; + value->bv_tofree = NULL; if (virp->vir_conv.vc_type != CONV_NONE && *s != NUL) { sconv = string_convert(&virp->vir_conv, s, NULL); if (sconv != NULL) { if (s == buf) - vim_free(s); + // the converted string is stored in bv_string and + // freed later, also need to free "buf" later + value->bv_tofree = buf; s = sconv; - buf = s; converted = TRUE; } } // Need to copy in allocated memory if the string wasn't allocated // above and we did allocate before, thus vir_line may change. - if (s != buf && allocated) + if (s != buf && allocated && !converted) s = vim_strsave(s); value->bv_string = s; value->bv_type = BVAL_STRING; @@ -2747,6 +2764,7 @@ read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing) vp = (bval_T *)values.ga_data + i; if (vp->bv_type == BVAL_STRING && vp->bv_allocated) vim_free(vp->bv_string); + vim_free(vp->bv_tofree); } ga_clear(&values); } From 99234f29aa8767f2e71bb1f5db6ee0131bc8e64e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Feb 2020 22:56:54 +0100 Subject: [PATCH 22/55] patch 8.2.0241: crash when setting 'buftype' to "quickfix" Problem: Crash when setting 'buftype' to "quickfix". Solution: Check that error list is not NULL. (closes #5613) --- src/quickfix.c | 2 +- src/testdir/test_quickfix.vim | 7 +++++++ src/version.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/quickfix.c b/src/quickfix.c index 868b5d910a..00457e256d 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4520,7 +4520,7 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last) *dirname = NUL; // Add one line for each error - if (old_last == NULL) + if (old_last == NULL || old_last->qf_next == NULL) { qfp = qfl->qf_start; lnum = 0; diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 79ad82d2d6..3f4574a129 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -1628,6 +1628,13 @@ func Test_setqflist_invalid_nr() eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST}) endfunc +func Test_setqflist_user_sets_buftype() + call setqflist([{'text': 'foo'}, {'text': 'bar'}]) + set buftype=quickfix + call setqflist([], 'a') + enew +endfunc + func Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('c') call XquickfixSetListWithAct('l') diff --git a/src/version.c b/src/version.c index 7eaf24bdd1..f9ddda4044 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 241, /**/ 240, /**/ From 799439a5d85a7d45eff7485056f2798cea766300 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Feb 2020 21:44:17 +0100 Subject: [PATCH 23/55] patch 8.2.0242: preview popup window test fails with long directory name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Preview popup window test fails with long directory name. (Jakub Kądziołka) Solution: Use "silent cd". (closes #5615) --- src/testdir/test_popupwin.vim | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index ad5a808611..d331263e3f 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2821,9 +2821,9 @@ func Test_previewpopup() call term_sendkeys(buf, "/another\\}") call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_4', {}) - call term_sendkeys(buf, ":cd ..\:\") + call term_sendkeys(buf, ":silent cd ..\:\") call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_5', {}) - call term_sendkeys(buf, ":cd testdir\") + call term_sendkeys(buf, ":silent cd testdir\") call term_sendkeys(buf, ":pclose\") call term_sendkeys(buf, ":\") diff --git a/src/version.c b/src/version.c index f9ddda4044..9b9f412617 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 242, /**/ 241, /**/ From 9f6277bdde97b7767ded43a0b5a2023eb601b3b7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Feb 2020 22:04:02 +0100 Subject: [PATCH 24/55] patch 8.2.0243: insufficient code coverage for ex_docmd.c functions Problem: Insufficient code coverage for ex_docmd.c functions. Solution: Add more tests. (Yegappan Lakshmanan, closes #5618) --- src/testdir/Make_all.mak | 2 + src/testdir/test_arglist.vim | 17 +++++++ src/testdir/test_buffer.vim | 66 +++++++++++++++++++++++++ src/testdir/test_cd.vim | 16 ++++++ src/testdir/test_cmdline.vim | 9 ++++ src/testdir/test_ex_mode.vim | 22 +++++++++ src/testdir/test_excmd.vim | 38 +++++++++++++++ src/testdir/test_mapping.vim | 7 +++ src/testdir/test_quickfix.vim | 19 ++++++-- src/testdir/test_search.vim | 80 ++++++++++++++++++------------ src/testdir/test_sort.vim | 18 ++++++- src/testdir/test_source.vim | 10 ++++ src/testdir/test_substitute.vim | 37 ++++++++++---- src/testdir/test_undo.vim | 2 + src/testdir/test_vimscript.vim | 86 +++++++++++++++++++++++++++++++++ src/testdir/test_window_cmd.vim | 14 ++++++ src/version.c | 2 + 17 files changed, 399 insertions(+), 46 deletions(-) create mode 100644 src/testdir/test_buffer.vim diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 40e56a290f..3a4979bf33 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -60,6 +60,7 @@ NEW_TESTS = \ test_blob \ test_blockedit \ test_breakindent \ + test_buffer \ test_bufline \ test_bufwintabinfo \ test_cd \ @@ -305,6 +306,7 @@ NEW_TESTS_RES = \ test_blob.res \ test_blockedit.res \ test_breakindent.res \ + test_buffer.res \ test_bufline.res \ test_bufwintabinfo.res \ test_cd.res \ diff --git a/src/testdir/test_arglist.vim b/src/testdir/test_arglist.vim index c486b18e2f..9513ad334c 100644 --- a/src/testdir/test_arglist.vim +++ b/src/testdir/test_arglist.vim @@ -1,5 +1,8 @@ " Test argument list commands +source shared.vim +source term_util.vim + func Test_argidx() args a b c last @@ -505,3 +508,17 @@ func Test_argdo() call assert_equal(['Xa.c', 'Xb.c', 'Xc.c'], l) bwipe Xa.c Xb.c Xc.c endfunc + +" Test for quiting Vim with unedited files in the argument list +func Test_quit_with_arglist() + if !CanRunVimInTerminal() + throw 'Skipped: cannot run vim in terminal' + endif + let buf = RunVimInTerminal('', {'rows': 6}) + call term_sendkeys(buf, ":args a b c\n") + call term_sendkeys(buf, ":quit\n") + call WaitForAssert({-> assert_match('^E173:', term_getline(buf, 6))}) + call StopVimInTerminal(buf) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim new file mode 100644 index 0000000000..dc35bb4b83 --- /dev/null +++ b/src/testdir/test_buffer.vim @@ -0,0 +1,66 @@ +" Tests for Vim buffer + +" Test for the :bunload command with an offset +func Test_bunload_with_offset() + %bwipe! + call writefile(['B1'], 'b1') + call writefile(['B2'], 'b2') + call writefile(['B3'], 'b3') + call writefile(['B4'], 'b4') + + " Load four buffers. Unload the second and third buffers and then + " execute .+3bunload to unload the last buffer. + edit b1 + new b2 + new b3 + new b4 + + bunload b2 + bunload b3 + exe bufwinnr('b1') . 'wincmd w' + .+3bunload + call assert_equal(0, getbufinfo('b4')[0].loaded) + call assert_equal('b1', + \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) + + " Load four buffers. Unload the third and fourth buffers. Execute .+3bunload + " and check whether the second buffer is unloaded. + ball + bunload b3 + bunload b4 + exe bufwinnr('b1') . 'wincmd w' + .+3bunload + call assert_equal(0, getbufinfo('b2')[0].loaded) + call assert_equal('b1', + \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) + + " Load four buffers. Unload the second and third buffers and from the last + " buffer execute .-3bunload to unload the first buffer. + ball + bunload b2 + bunload b3 + exe bufwinnr('b4') . 'wincmd w' + .-3bunload + call assert_equal(0, getbufinfo('b1')[0].loaded) + call assert_equal('b4', + \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) + + " Load four buffers. Unload the first and second buffers. Execute .-3bunload + " from the last buffer and check whether the third buffer is unloaded. + ball + bunload b1 + bunload b2 + exe bufwinnr('b4') . 'wincmd w' + .-3bunload + call assert_equal(0, getbufinfo('b3')[0].loaded) + call assert_equal('b4', + \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) + + %bwipe! + call delete('b1') + call delete('b2') + call delete('b3') + call delete('b4') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cd.vim b/src/testdir/test_cd.vim index e44b25f0fa..e5c119e22e 100644 --- a/src/testdir/test_cd.vim +++ b/src/testdir/test_cd.vim @@ -1,5 +1,7 @@ " Test for :cd and chdir() +source shared.vim + func Test_cd_large_path() " This used to crash with a heap write overflow. call assert_fails('cd ' . repeat('x', 5000), 'E472:') @@ -40,6 +42,20 @@ func Test_cd_minus() call assert_equal(path_dotdot, getcwd()) cd - call assert_equal(path, getcwd()) + + " Test for :cd - without a previous directory + let lines =<< trim [SCRIPT] + call assert_fails('cd -', 'E186:') + call assert_fails('call chdir("-")', 'E186:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') endfunc func Test_cd_with_cpo_chdir() diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 36067d1d9f..a3d2d5a736 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -923,4 +923,13 @@ func Test_cmdlineclear_tabenter() call delete('XtestCmdlineClearTabenter') endfunc +" Test for failure in expanding special keywords in cmdline +func Test_cmdline_expand_special() + %bwipe! + call assert_fails('e #', 'E499:') + call assert_fails('e ', 'E495:') + call assert_fails('e ', 'E496:') + call assert_fails('e ', 'E497:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_ex_mode.vim b/src/testdir/test_ex_mode.vim index 5899571a97..7861477c74 100644 --- a/src/testdir/test_ex_mode.vim +++ b/src/testdir/test_ex_mode.vim @@ -84,4 +84,26 @@ func Test_Ex_substitute() call StopVimInTerminal(buf) endfunc +" Test for displaying lines from an empty buffer in Ex mode +func Test_Ex_emptybuf() + new + call assert_fails('call feedkeys("Q\", "xt")', 'E749:') + call setline(1, "abc") + call assert_fails('call feedkeys("Q\", "xt")', 'E501:') + call assert_fails('call feedkeys("Q%d\", "xt")', 'E749:') + close! +endfunc + +" Test for the :open command +func Test_open_command() + new + call setline(1, ['foo foo', 'foo bar', 'foo baz']) + call feedkeys("Qopen\j", 'xt') + call assert_equal('foo bar', getline('.')) + call feedkeys("Qopen /bar/\", 'xt') + call assert_equal(5, col('.')) + call assert_fails('call feedkeys("Qopen /baz/\", "xt")', 'E479:') + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim index 6174e660be..7ce32ca420 100644 --- a/src/testdir/test_excmd.vim +++ b/src/testdir/test_excmd.vim @@ -20,6 +20,7 @@ func Test_range_error() call assert_fails(':\/echo 1', 'E481:') normal vv call assert_fails(":'<,'>echo 1", 'E481:') + call assert_fails(":\\xcenter", 'E10:') endfunc func Test_buffers_lastused() @@ -241,4 +242,41 @@ func Test_confirm_cmd() call delete('bar') endfunc +" Test for the :print command +func Test_print_cmd() + call assert_fails('print', 'E749:') +endfunc + +" Test for the :winsize command +func Test_winsize_cmd() + call assert_fails('winsize 1', 'E465:') +endfunc + +" Test for the :redir command +func Test_redir_cmd() + call assert_fails('redir @@', 'E475:') + call assert_fails('redir abc', 'E475:') + if has('unix') + call mkdir('Xdir') + call assert_fails('redir > Xdir', 'E17:') + call delete('Xdir', 'd') + endif + if !has('bsd') + call writefile([], 'Xfile') + call setfperm('Xfile', 'r--r--r--') + call assert_fails('redir! > Xfile', 'E190:') + call delete('Xfile') + endif +endfunc + +" Test for the :filetype command +func Test_filetype_cmd() + call assert_fails('filetype abc', 'E475:') +endfunc + +" Test for the :mode command +func Test_mode_cmd() + call assert_fails('mode abc', 'E359:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 7aeb23c14d..00dfc5bbdd 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -552,6 +552,13 @@ func Test_map_error() map ,f abc call assert_fails('normal ,f', 'E121:') unmap ,f + + " Recursive use of :normal in a map + set maxmapdepth=100 + map gq :normal gq + call assert_fails('normal gq', 'E192:') + unmap gq + set maxmapdepth& endfunc " Test for key mapping diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 3f4574a129..cc5ee8066d 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -2725,10 +2725,6 @@ func XvimgrepTests(cchar) call assert_equal(0, getbufinfo('Xtestfile1')[0].loaded) call assert_equal([], getbufinfo('Xtestfile2')) - " Test with the last search pattern not set - call test_clear_search_pat() - call assert_fails('Xvimgrep // *', 'E35:') - call delete('Xtestfile1') call delete('Xtestfile2') endfunc @@ -2754,6 +2750,21 @@ func Test_vimgrep_incsearch() set noincsearch endfunc +" Test vimgrep with the last search pattern not set +func Test_vimgrep_with_no_last_search_pat() + let lines =<< trim [SCRIPT] + call assert_fails('vimgrep // *', 'E35:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') +endfunc + func XfreeTests(cchar) call s:setup_commands(a:cchar) diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index 69d007354e..9567aa468b 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -1457,42 +1457,62 @@ func Test_search_special() endfunc " Test for command failures when the last search pattern is not set. +" Need to run this in a new vim instance where last search pattern is not set. func Test_search_with_no_last_pat() - call test_clear_search_pat() - call assert_fails("normal i\/\e", 'E35:') - call assert_fails("exe '/'", 'E35:') - call assert_fails("exe '?'", 'E35:') - call assert_fails("/", 'E35:') - call assert_fails("?", 'E35:') - call assert_fails("normal n", 'E35:') - call assert_fails("normal N", 'E35:') - call assert_fails("normal gn", 'E35:') - call assert_fails("normal gN", 'E35:') - call assert_fails("normal cgn", 'E35:') - call assert_fails("normal cgN", 'E35:') - let p = [] - let p = @/ - call assert_equal('', p) - call assert_fails("normal :\/", 'E35:') - call assert_fails("//p", 'E35:') - call assert_fails(";//p", 'E35:') - call assert_fails("??p", 'E35:') - call assert_fails(";??p", 'E35:') - call assert_fails('g//p', 'E476:') - call assert_fails('v//p', 'E476:') + let lines =<< trim [SCRIPT] + call assert_fails("normal i\/\e", 'E35:') + call assert_fails("exe '/'", 'E35:') + call assert_fails("exe '?'", 'E35:') + call assert_fails("/", 'E35:') + call assert_fails("?", 'E35:') + call assert_fails("normal n", 'E35:') + call assert_fails("normal N", 'E35:') + call assert_fails("normal gn", 'E35:') + call assert_fails("normal gN", 'E35:') + call assert_fails("normal cgn", 'E35:') + call assert_fails("normal cgN", 'E35:') + let p = [] + let p = @/ + call assert_equal('', p) + call assert_fails("normal :\/", 'E35:') + call assert_fails("//p", 'E35:') + call assert_fails(";//p", 'E35:') + call assert_fails("??p", 'E35:') + call assert_fails(";??p", 'E35:') + call assert_fails('g//p', 'E476:') + call assert_fails('v//p', 'E476:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') endfunc " Test for using tilde (~) atom in search. This should use the last used " substitute pattern func Test_search_tilde_pat() - call test_clear_search_pat() - set regexpengine=1 - call assert_fails('exe "normal /~\"', 'E33:') - call assert_fails('exe "normal ?~\"', 'E33:') - set regexpengine=2 - call assert_fails('exe "normal /~\"', 'E383:') - call assert_fails('exe "normal ?~\"', 'E383:') - set regexpengine& + let lines =<< trim [SCRIPT] + set regexpengine=1 + call assert_fails('exe "normal /~\"', 'E33:') + call assert_fails('exe "normal ?~\"', 'E33:') + set regexpengine=2 + call assert_fails('exe "normal /~\"', 'E383:') + call assert_fails('exe "normal ?~\"', 'E383:') + set regexpengine& + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_sort.vim b/src/testdir/test_sort.vim index f6ad87af18..ce5592e2e9 100644 --- a/src/testdir/test_sort.vim +++ b/src/testdir/test_sort.vim @@ -1383,11 +1383,25 @@ func Test_sort_last_search_pat() call setline(1, ['3b', '1c', '2a']) sort // call assert_equal(['2a', '3b', '1c'], getline(1, '$')) - call test_clear_search_pat() - call assert_fails('sort //', 'E35:') close! endfunc +" Test for :sort with no last search pattern +func Test_sort_with_no_last_search_pat() + let lines =<< trim [SCRIPT] + call setline(1, ['3b', '1c', '2a']) + call assert_fails('sort //', 'E35:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') +endfunc + " Test for retaining marks across a :sort func Test_sort_with_marks() new diff --git a/src/testdir/test_source.vim b/src/testdir/test_source.vim index b8fe8422b3..e7f3fb1884 100644 --- a/src/testdir/test_source.vim +++ b/src/testdir/test_source.vim @@ -57,3 +57,13 @@ func Test_different_script() call assert_fails('source XtwoScript', 'E121:') call delete('XtwoScript') endfunc + +" When sourcing a vim script, shebang should be ignored. +func Test_source_ignore_shebang() + call writefile(['#!./xyzabc', 'let g:val=369'], 'Xfile.vim') + source Xfile.vim + call assert_equal(g:val, 369) + call delete('Xfile.vim') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim index acc59cf564..2ac6f45419 100644 --- a/src/testdir/test_substitute.vim +++ b/src/testdir/test_substitute.vim @@ -1,5 +1,7 @@ " Tests for multi-line regexps with ":s". +source shared.vim + func Test_multiline_subst() enew! call append(0, ["1 aa", @@ -805,17 +807,32 @@ endfunc " Test for command failures when the last substitute pattern is not set. func Test_sub_with_no_last_pat() - call test_clear_search_pat() - call assert_fails('~', 'E33:') - call assert_fails('s//abc/g', 'E476:') - call assert_fails('s\/bar', 'E476:') - call assert_fails('s\&bar&', 'E476:') + let lines =<< trim [SCRIPT] + call assert_fails('~', 'E33:') + call assert_fails('s//abc/g', 'E476:') + call assert_fails('s\/bar', 'E476:') + call assert_fails('s\&bar&', 'E476:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif - call test_clear_search_pat() - let save_cpo = &cpo - set cpo+=/ - call assert_fails('s/abc/%/', 'E33:') - let &cpo = save_cpo + let lines =<< trim [SCRIPT] + set cpo+=/ + call assert_fails('s/abc/%/', 'E33:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + + call delete('Xscript') + call delete('Xresult') endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index e858d72747..2ecc52082e 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -295,6 +295,8 @@ func Test_undo_write() close! call delete('Xtest') bwipe! Xtest + + call assert_fails('earlier xyz', 'E475:') endfunc func Test_insert_expr() diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index d7a3fe23f3..a422a6df88 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -1975,6 +1975,92 @@ func Test_function_defined_line() call delete('Xtest.vim') endfunc +" Test for missing :endif, :endfor, :endwhile and :endtry {{{1 +func Test_missing_end() + call writefile(['if 2 > 1', 'echo ">"'], 'Xscript') + call assert_fails('source Xscript', 'E171:') + call writefile(['for i in range(5)', 'echo i'], 'Xscript') + call assert_fails('source Xscript', 'E170:') + call writefile(['while v:true', 'echo "."'], 'Xscript') + call assert_fails('source Xscript', 'E170:') + call writefile(['try', 'echo "."'], 'Xscript') + call assert_fails('source Xscript', 'E600:') + call delete('Xscript') +endfunc + +" Test for deep nesting of if/for/while/try statements {{{1 +func Test_deep_nest() + if !CanRunVimInTerminal() + throw 'Skipped: cannot run vim in terminal' + endif + + let lines =<< trim [SCRIPT] + " Deep nesting of if ... endif + func Test1() + let @a = join(repeat(['if v:true'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endif'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of for ... endfor + func Test2() + let @a = join(repeat(['for i in [1]'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endfor'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of while ... endwhile + func Test3() + let @a = join(repeat(['while v:true'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endwhile'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of try ... endtry + func Test4() + let @a = join(repeat(['try'], 51), "\n") + let @a ..= "\necho v:true\n" + let @a ..= join(repeat(['endtry'], 51), "\n") + @a + let @a = '' + endfunc + [SCRIPT] + call writefile(lines, 'Xscript') + + let buf = RunVimInTerminal('-S Xscript', {'rows': 6}) + + " Deep nesting of if ... endif + call term_sendkeys(buf, ":call Test1()\n") + call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))}) + + " Deep nesting of for ... endfor + call term_sendkeys(buf, ":call Test2()\n") + call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) + + " Deep nesting of while ... endwhile + call term_sendkeys(buf, ":call Test3()\n") + call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) + + " Deep nesting of try ... endtry + call term_sendkeys(buf, ":call Test4()\n") + call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))}) + + "let l = '' + "for i in range(1, 6) + " let l ..= term_getline(buf, i) . "\n" + "endfor + "call assert_report(l) + + call StopVimInTerminal(buf) + call delete('Xscript') +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index cbd08c9741..24501e14c4 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -942,4 +942,18 @@ func Test_window_only() only! endfunc +" Test for errors with :wincmd +func Test_wincmd_errors() + call assert_fails('wincmd g', 'E474:') + call assert_fails('wincmd ab', 'E474:') +endfunc + +" Test for errors with :winpos +func Test_winpos_errors() + if !has("gui_running") && !has('win32') + call assert_fails('winpos', 'E188:') + endif + call assert_fails('winpos 10', 'E466:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 9b9f412617..71513f3b7d 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 243, /**/ 242, /**/ From 5f1d3ae8a8264292a53aad099e78a9b4a7bad375 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Feb 2020 22:37:35 +0100 Subject: [PATCH 25/55] patch 8.2.0244: compiler warning in Lua interface Problem: Compiler warning in Lua interface. Solution: Add type cast. (Ken Takata, closes #5621) --- src/if_lua.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/if_lua.c b/src/if_lua.c index 1eb7a77a14..8c1638a3a2 100644 --- a/src/if_lua.c +++ b/src/if_lua.c @@ -1148,7 +1148,7 @@ luaV_blob_add(lua_State *L) size_t i, l = 0; const char *s = lua_tolstring(L, 2, &l); - if (ga_grow(&b->bv_ga, l) == OK) + if (ga_grow(&b->bv_ga, (int)l) == OK) for (i = 0; i < l; ++i) ga_append(&b->bv_ga, s[i]); } @@ -1781,7 +1781,7 @@ luaV_blob(lua_State *L) size_t i, l = 0; const char *s = lua_tolstring(L, 1, &l); - if (ga_grow(&b->bv_ga, l) == OK) + if (ga_grow(&b->bv_ga, (int)l) == OK) for (i = 0; i < l; ++i) ga_append(&b->bv_ga, s[i]); } diff --git a/src/version.c b/src/version.c index 71513f3b7d..2c14352d87 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 244, /**/ 243, /**/ From 5489eab34528ba31054bc7c99af120b07f543b78 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Feb 2020 22:49:18 +0100 Subject: [PATCH 26/55] patch 8.2.0245: MSVC: error message if the auto directory already exists Problem: MSVC: error message if the auto directory already exists. Solution: Add "if not exists". (Ken Takata, closes #5620) --- src/Make_mvc.mak | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 3e8eae168f..c51f8045a7 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1584,7 +1584,7 @@ $(OUTDIR)/if_lua.obj: $(OUTDIR) if_lua.c $(INCL) $(CC) $(CFLAGS_OUTDIR) $(LUA_INC) if_lua.c auto/if_perl.c : if_perl.xs typemap - -mkdir auto + -if not exist auto/nul mkdir auto $(XSUBPP) -prototypes -typemap $(XSUBPP_TYPEMAP) \ -typemap typemap if_perl.xs -output $@ diff --git a/src/version.c b/src/version.c index 2c14352d87..8e3f20a483 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 245, /**/ 244, /**/ From 49c99fcca00740ae4feaba82bef4f9dc70b65318 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Feb 2020 23:01:39 +0100 Subject: [PATCH 27/55] patch 8.2.0246: MSVC: deprecation warnings with Ruby Problem: MSVC: deprecation warnings with Ruby. Solution: Move _CRT_SECURE_NO_DEPRECATE to build file. (Ken Takata, closes #5622) --- src/Make_mvc.mak | 2 ++ src/if_ruby.c | 12 ++++++------ src/os_win32.h | 6 ------ src/version.c | 2 ++ src/vim.h | 6 ------ src/vimio.h | 6 ------ 6 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index c51f8045a7..509708167e 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -657,6 +657,8 @@ OPTFLAG = /Ox ! if "$(OPTIMIZE)" != "SPACE" OPTFLAG = $(OPTFLAG) /GL ! endif +# Visual Studio 2005 has 'deprecated' many of the standard CRT functions +CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE ! endif # (/Wp64 is deprecated in VC9 and generates an obnoxious warning.) diff --git a/src/if_ruby.c b/src/if_ruby.c index 7f2a7d265e..f4e1e12394 100644 --- a/src/if_ruby.c +++ b/src/if_ruby.c @@ -21,7 +21,7 @@ #ifdef _WIN32 # if !defined(DYNAMIC_RUBY) || (RUBY_VERSION < 18) -# define NT +# define NT # endif # ifndef DYNAMIC_RUBY # define IMPORT // For static dll usage __declspec(dllimport) @@ -300,8 +300,8 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # define rb_float_new dll_rb_float_new # define rb_ary_new dll_rb_ary_new # ifdef rb_ary_new4 -# define RB_ARY_NEW4_MACRO 1 -# undef rb_ary_new4 +# define RB_ARY_NEW4_MACRO 1 +# undef rb_ary_new4 # endif # define rb_ary_new4 dll_rb_ary_new4 # define rb_ary_push dll_rb_ary_push @@ -1071,15 +1071,15 @@ error_print(int state) } attr = syn_name2attr((char_u *)"Error"); -# if RUBY_VERSION >= 21 +#if RUBY_VERSION >= 21 bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0); for (i = 0; i < RARRAY_LEN(bt); i++) msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr); -# else +#else bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0); for (i = 0; i < RARRAY_LEN(bt); i++) msg_attr(RSTRING_PTR(RARRAY_PTR(bt)[i]), attr); -# endif +#endif break; default: vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state); diff --git a/src/os_win32.h b/src/os_win32.h index f1be8c4411..abe95b5fe3 100644 --- a/src/os_win32.h +++ b/src/os_win32.h @@ -18,12 +18,6 @@ # endif #endif -// Stop the VC2005 compiler from nagging. -#if _MSC_VER >= 1400 -# define _CRT_SECURE_NO_DEPRECATE -# define _CRT_NONSTDC_NO_DEPRECATE -#endif - #define BINARY_FILE_IO #define USE_EXE_NAME // use argv[0] for $VIM #define USE_TERM_CONSOLE diff --git a/src/version.c b/src/version.c index 8e3f20a483..b3f95134c9 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 246, /**/ 245, /**/ diff --git a/src/vim.h b/src/vim.h index 270109ace9..ca0f6b1484 100644 --- a/src/vim.h +++ b/src/vim.h @@ -119,12 +119,6 @@ # endif #endif -// Visual Studio 2005 has 'deprecated' many of the standard CRT functions -#if _MSC_VER >= 1400 -# define _CRT_SECURE_NO_DEPRECATE -# define _CRT_NONSTDC_NO_DEPRECATE -#endif - /* * VIM_SIZEOF_INT is used in feature.h, and the system-specific included files * need items from feature.h. Therefore define VIM_SIZEOF_INT here. diff --git a/src/vimio.h b/src/vimio.h index 402b11381a..a07620ca71 100644 --- a/src/vimio.h +++ b/src/vimio.h @@ -7,12 +7,6 @@ * See README.txt for an overview of the Vim source code. */ -// Visual Studio 2005 has 'deprecated' many of the standard CRT functions -#if _MSC_VER >= 1400 -# define _CRT_SECURE_NO_DEPRECATE -# define _CRT_NONSTDC_NO_DEPRECATE -#endif - // cproto fails on missing include files #ifndef PROTO # include From 3b0ef8cfdbb6cb5a9cb2dc093132b78d7a52c667 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Feb 2020 21:03:32 +0100 Subject: [PATCH 28/55] patch 8.2.0247: misleading comment in NSIS installer script Problem: Misleading comment in NSIS installer script. Solution: Negate the meaning of the comment. (Ken Takata, closes #5627) --- nsis/gvim.nsi | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nsis/gvim.nsi b/nsis/gvim.nsi index d782e4397a..2b40e4b0db 100644 --- a/nsis/gvim.nsi +++ b/nsis/gvim.nsi @@ -39,7 +39,7 @@ Unicode true # Uncomment the next line if you want to include VisVim extension: #!define HAVE_VIS_VIM -# Comment the following line to create a multilanguage installer: +# Comment the following line to create an English-only installer: !define HAVE_MULTI_LANG # Uncomment the next line if you want to create a 64-bit installer. diff --git a/src/version.c b/src/version.c index b3f95134c9..1b22d6ffa2 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 247, /**/ 246, /**/ From 2f189750887636fecd440d7ef353d9224e48713f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Feb 2020 21:15:43 +0100 Subject: [PATCH 29/55] patch 8.2.0248: MS-Windows: dealing with deprecation is too complicated Problem: MS-Windows: dealing with deprecation is too complicated. Solution: Use io.h directly. Move _CRT_SECURE_NO_DEPRECATE to the build file. Suppress C4091 warning by setting "_WIN32_WINNT". (Ken Takata, closes #5626) --- Filelist | 1 - src/Make_mvc.mak | 9 ++++++--- src/dosinst.h | 8 +------- src/version.c | 2 ++ src/vim.h | 2 +- src/vimio.h | 13 ------------- src/winclip.c | 1 - 7 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 src/vimio.h diff --git a/Filelist b/Filelist index 25fefc1d12..91e6b04325 100644 --- a/Filelist +++ b/Filelist @@ -529,7 +529,6 @@ SRC_DOS = \ src/uninstall.c \ src/vim.def \ src/vim.rc \ - src/vimio.h \ src/gvim.exe.mnf \ src/vimrun.c \ src/xpm_w32.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 509708167e..b95e936f06 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -658,7 +658,8 @@ OPTFLAG = /Ox OPTFLAG = $(OPTFLAG) /GL ! endif # Visual Studio 2005 has 'deprecated' many of the standard CRT functions -CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE +CFLAGS_DEPR = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE +CFLAGS = $(CFLAGS) $(CFLAGS_DEPR) ! endif # (/Wp64 is deprecated in VC9 and generates an obnoxious warning.) @@ -1348,15 +1349,17 @@ $(VIM): $(VIM).exe $(OUTDIR): if not exist $(OUTDIR)/nul mkdir $(OUTDIR) +CFLAGS_INST = /nologo -DNDEBUG -DWIN32 -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) $(CFLAGS_DEPR) + install.exe: dosinst.c dosinst.h version.h - $(CC) /nologo -DNDEBUG -DWIN32 dosinst.c kernel32.lib shell32.lib \ + $(CC) $(CFLAGS_INST) dosinst.c kernel32.lib shell32.lib \ user32.lib ole32.lib advapi32.lib uuid.lib \ -link -subsystem:$(SUBSYSTEM_TOOLS) - if exist install.exe del install.exe ren dosinst.exe install.exe uninstall.exe: uninstall.c dosinst.h version.h - $(CC) /nologo -DNDEBUG -DWIN32 uninstall.c shell32.lib advapi32.lib \ + $(CC) $(CFLAGS_INST) uninstall.c shell32.lib advapi32.lib \ -link -subsystem:$(SUBSYSTEM_TOOLS) vimrun.exe: vimrun.c diff --git a/src/dosinst.h b/src/dosinst.h index c9d8c929bf..a849dad907 100644 --- a/src/dosinst.h +++ b/src/dosinst.h @@ -10,12 +10,6 @@ * dosinst.h: Common code for dosinst.c and uninstall.c */ -// Visual Studio 2005 has 'deprecated' many of the standard CRT functions -#if _MSC_VER >= 1400 -# define _CRT_SECURE_NO_DEPRECATE -# define _CRT_NONSTDC_NO_DEPRECATE -#endif - #include #include #include @@ -23,7 +17,7 @@ #include #ifndef UNIX_LINT -# include "vimio.h" +# include # include # include diff --git a/src/version.c b/src/version.c index 1b22d6ffa2..ba79618268 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 248, /**/ 247, /**/ diff --git a/src/vim.h b/src/vim.h index ca0f6b1484..62cc46cd03 100644 --- a/src/vim.h +++ b/src/vim.h @@ -18,7 +18,7 @@ #endif #ifdef MSWIN -# include "vimio.h" +# include #endif // ============ the header file puzzle: order matters ========= diff --git a/src/vimio.h b/src/vimio.h deleted file mode 100644 index a07620ca71..0000000000 --- a/src/vimio.h +++ /dev/null @@ -1,13 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4 noet: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -// cproto fails on missing include files -#ifndef PROTO -# include -#endif diff --git a/src/winclip.c b/src/winclip.c index d97f776ca8..767bf1c71e 100644 --- a/src/winclip.c +++ b/src/winclip.c @@ -14,7 +14,6 @@ * Also used by Cygwin, using os_unix.c. */ -#include "vimio.h" #include "vim.h" /* From 3fb377fa78131004138b22a87afe33eeb7649b94 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Feb 2020 21:52:32 +0100 Subject: [PATCH 30/55] patch 8.2.0249: MS-Windows: various warnings Problem: MS-Windows: various warnings. Solution: Set the charset to utf-8. Add _WIN32_WINNT and _USING_V110_SDK71_. (Ken Takata, closes #5625) --- src/GvimExt/Makefile | 10 ++++++++++ src/Make_mvc.mak | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 21 insertions(+) diff --git a/src/GvimExt/Makefile b/src/GvimExt/Makefile index 975ba11705..4b83f52dd5 100644 --- a/src/GvimExt/Makefile +++ b/src/GvimExt/Makefile @@ -10,6 +10,9 @@ TARGETOS = WINNT !ifndef APPVER APPVER = 5.01 !endif +!ifndef WINVER +WINVER = 0x0501 +!endif !if "$(DEBUG)" != "yes" NODEBUG = 1 @@ -53,6 +56,13 @@ olelibsdll = ole32.lib uuid.lib oleaut32.lib user32.lib gdi32.lib advapi32.lib # include CPUARG cflags = $(cflags) $(CPUARG) +# set WINVER and _WIN32_WINNT +cflags = $(cflags) -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) + +!if "$(CL)" == "/D_USING_V110_SDK71_" +rcflags = $(rcflags) /D_USING_V110_SDK71_ +!endif + SUBSYSTEM = console !if "$(SUBSYSTEM_VER)" != "" SUBSYSTEM = $(SUBSYSTEM),$(SUBSYSTEM_VER) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index b95e936f06..da9a911d0a 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -626,6 +626,12 @@ NODEFAULTLIB = NODEFAULTLIB = /nodefaultlib !endif +# Specify source code charset to suppress warning C4819 on non-English +# environment. Only available from MSVC 14. +!if $(MSVC_MAJOR) >= 14 +CFLAGS = $(CFLAGS) /source-charset:utf-8 +!endif + # Use multiprocess build on MSVC 10 !if ("$(USE_MP)" == "yes") && ($(MSVC_MAJOR) >= 10) CFLAGS = $(CFLAGS) /MP @@ -669,6 +675,9 @@ CFLAGS = $(CFLAGS) $(WP64CHECK) CFLAGS = $(CFLAGS) $(OPTFLAG) -DNDEBUG $(CPUARG) RCFLAGS = $(rcflags) $(rcvars) -DNDEBUG +! if "$(CL)" == "/D_USING_V110_SDK71_" +RCFLAGS = $(RCFLAGS) /D_USING_V110_SDK71_ +! endif ! ifdef USE_MSVCRT CFLAGS = $(CFLAGS) /MD LIBC = msvcrt.lib diff --git a/src/version.c b/src/version.c index ba79618268..7c31c195da 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 249, /**/ 248, /**/ From 4f5776c17cd86f904a7e2f92db297c73e28939b7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Feb 2020 22:15:19 +0100 Subject: [PATCH 31/55] patch 8.2.0250: test_clear_search_pat() is unused Problem: test_clear_search_pat() is unused. Solution: Remove the function. (Yegappan Lakshmanan, closes #5624) --- runtime/doc/eval.txt | 1 - runtime/doc/testing.txt | 5 ----- runtime/doc/usr_41.txt | 1 - src/evalfunc.c | 1 - src/proto/regexp.pro | 1 - src/proto/search.pro | 1 - src/proto/testing.pro | 1 - src/regexp.c | 9 --------- src/search.c | 6 ------ src/testdir/test_writefile.vim | 4 ++++ src/testing.c | 13 ------------- src/version.c | 2 ++ 12 files changed, 6 insertions(+), 39 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index afbfd9f7e5..d7c0dc3a8b 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2848,7 +2848,6 @@ term_wait({buf} [, {time}]) Number wait for screen to be updated test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail test_autochdir() none enable 'autochdir' during startup -test_clear_search_pat() none clears the last used search pattern test_feedinput({string}) none add key sequence to input buffer test_garbagecollect_now() none free memory right now for testing test_garbagecollect_soon() none free memory soon for testing diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index f2a7cf16c5..f343e86a6d 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -52,11 +52,6 @@ test_autochdir() *test_autochdir()* startup has finished. -test_clear_search_pat() *test_clear_search_pat()* - Clears the last used search pattern (|/|) and the substitute - pattern (|:s|). This is useful for testing conditions where - these patterns are not set previously. - test_feedinput({string}) *test_feedinput()* Characters in {string} are queued for processing as if they were typed by the user. This uses a low level input buffer. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 316eebcaea..1bed01f418 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -963,7 +963,6 @@ Testing: *test-functions* assert_report() report a test failure test_alloc_fail() make memory allocation fail test_autochdir() enable 'autochdir' during startup - test_clear_search_pat() clears the last used search pattern test_override() test with Vim internal overrides test_garbagecollect_now() free memory right now test_getvalue() get value of an internal variable diff --git a/src/evalfunc.c b/src/evalfunc.c index 66be42c241..58f1218f21 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -811,7 +811,6 @@ static funcentry_T global_functions[] = #endif {"test_alloc_fail", 3, 3, FEARG_1, &t_void, f_test_alloc_fail}, {"test_autochdir", 0, 0, 0, &t_void, f_test_autochdir}, - {"test_clear_search_pat", 0, 0, 0, &t_void, f_test_clear_search_pat}, {"test_feedinput", 1, 1, FEARG_1, &t_void, f_test_feedinput}, {"test_garbagecollect_now", 0, 0, 0, &t_void, f_test_garbagecollect_now}, {"test_garbagecollect_soon", 0, 0, 0, &t_void, f_test_garbagecollect_soon}, diff --git a/src/proto/regexp.pro b/src/proto/regexp.pro index 5e8e1a58a6..01f1fff0d7 100644 --- a/src/proto/regexp.pro +++ b/src/proto/regexp.pro @@ -12,7 +12,6 @@ int vim_regcomp_had_eol(void); regprog_T *vim_regcomp(char_u *expr_arg, int re_flags); void vim_regfree(regprog_T *prog); void free_regexp_stuff(void); -void free_regexp_prev_sub(void); int regprog_in_use(regprog_T *prog); int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col); int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col); diff --git a/src/proto/search.pro b/src/proto/search.pro index 3b46c0662c..e6ac11b2cb 100644 --- a/src/proto/search.pro +++ b/src/proto/search.pro @@ -9,7 +9,6 @@ void free_search_patterns(void); void save_last_search_pattern(void); void restore_last_search_pattern(void); char_u *last_search_pattern(void); -void free_last_pat(int idx); int ignorecase(char_u *pat); int ignorecase_opt(char_u *pat, int ic_in, int scs); int pat_has_uppercase(char_u *pat); diff --git a/src/proto/testing.pro b/src/proto/testing.pro index 209abf3486..2b001a543a 100644 --- a/src/proto/testing.pro +++ b/src/proto/testing.pro @@ -13,7 +13,6 @@ void f_assert_report(typval_T *argvars, typval_T *rettv); void f_assert_true(typval_T *argvars, typval_T *rettv); void f_test_alloc_fail(typval_T *argvars, typval_T *rettv); void f_test_autochdir(typval_T *argvars, typval_T *rettv); -void f_test_clear_search_pat(typval_T *argvars, typval_T *rettv); void f_test_feedinput(typval_T *argvars, typval_T *rettv); void f_test_getvalue(typval_T *argvars, typval_T *rettv); void f_test_option_not_set(typval_T *argvars, typval_T *rettv); diff --git a/src/regexp.c b/src/regexp.c index 7aeddb83cd..ef3896c0a4 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -2663,15 +2663,6 @@ free_regexp_stuff(void) } #endif -/* - * Free the previously used substitute search pattern. - */ - void -free_regexp_prev_sub(void) -{ - VIM_CLEAR(reg_prev_sub); -} - #ifdef FEAT_EVAL static void report_re_switch(char_u *pat) diff --git a/src/search.c b/src/search.c index 08915578fc..3b310dc2a9 100644 --- a/src/search.c +++ b/src/search.c @@ -380,12 +380,6 @@ last_search_pattern(void) } #endif - void -free_last_pat(int idx) -{ - VIM_CLEAR(spats[idx].pat); -} - /* * Return TRUE when case should be ignored for search pattern "pat". * Uses the 'ignorecase' and 'smartcase' options. diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim index 98a06eb011..f616980f35 100644 --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -214,6 +214,10 @@ func Test_write_errors() call assert_fails('1,2write', 'E140:') close! + call assert_fails('w > Xtest', 'E494:') + + call assert_fails('w > Xtest', 'E494:') + " Try to overwrite a directory if has('unix') call mkdir('Xdir1') diff --git a/src/testing.c b/src/testing.c index c2b382b8b6..5dacf073b3 100644 --- a/src/testing.c +++ b/src/testing.c @@ -631,19 +631,6 @@ f_test_autochdir(typval_T *argvars UNUSED, typval_T *rettv UNUSED) #endif } -/* - * "test_clear_search_pat()" - * Free the last search and substitute patterns - */ - void -f_test_clear_search_pat(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ - free_last_pat(RE_SUBST); - free_last_pat(RE_SEARCH); - set_old_sub(NULL); - free_regexp_prev_sub(); -} - /* * "test_feedinput()" */ diff --git a/src/version.c b/src/version.c index 7c31c195da..a28fc03858 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 250, /**/ 249, /**/ From 7306d6b1c9528dcfe89eb77aa7ef354ffa9605a8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Feb 2020 22:25:56 +0100 Subject: [PATCH 32/55] patch 8.2.0251: a couple of function return types can be more specific Problem: A couple of function return types can be more specific. Solution: Use a better return type. (Ken Takata, closes #5629) --- src/evalfunc.c | 4 ++-- src/globals.h | 4 ++-- src/version.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 58f1218f21..6e96d0d1b8 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -569,7 +569,7 @@ static funcentry_T global_functions[] = {"matcharg", 1, 1, FEARG_1, &t_list_string, f_matcharg}, {"matchdelete", 1, 2, FEARG_1, &t_number, f_matchdelete}, {"matchend", 2, 4, FEARG_1, &t_number, f_matchend}, - {"matchlist", 2, 4, FEARG_1, &t_list_any, f_matchlist}, + {"matchlist", 2, 4, FEARG_1, &t_list_string, f_matchlist}, {"matchstr", 2, 4, FEARG_1, &t_string, f_matchstr}, {"matchstrpos", 2, 4, FEARG_1, &t_list_any, f_matchstrpos}, {"max", 1, 1, FEARG_1, &t_any, f_max}, @@ -622,7 +622,7 @@ static funcentry_T global_functions[] = {"prop_add", 3, 3, FEARG_1, &t_void, f_prop_add}, {"prop_clear", 1, 3, FEARG_1, &t_void, f_prop_clear}, {"prop_find", 1, 2, FEARG_1, &t_dict_any, f_prop_find}, - {"prop_list", 1, 2, FEARG_1, &t_list_any, f_prop_list}, + {"prop_list", 1, 2, FEARG_1, &t_list_dict_any, f_prop_list}, {"prop_remove", 1, 3, FEARG_1, &t_number, f_prop_remove}, {"prop_type_add", 2, 2, FEARG_1, &t_void, f_prop_type_add}, {"prop_type_change", 2, 2, FEARG_1, &t_void, f_prop_type_change}, diff --git a/src/globals.h b/src/globals.h index 562d956eb1..bda75b486e 100644 --- a/src/globals.h +++ b/src/globals.h @@ -384,9 +384,9 @@ EXTERN type_T t_void INIT4(VAR_VOID, 0, NULL, NULL); EXTERN type_T t_bool INIT4(VAR_BOOL, 0, NULL, NULL); EXTERN type_T t_special INIT4(VAR_SPECIAL, 0, NULL, NULL); EXTERN type_T t_number INIT4(VAR_NUMBER, 0, NULL, NULL); -#ifdef FEAT_FLOAT +# ifdef FEAT_FLOAT EXTERN type_T t_float INIT4(VAR_FLOAT, 0, NULL, NULL); -#endif +# endif EXTERN type_T t_string INIT4(VAR_STRING, 0, NULL, NULL); EXTERN type_T t_blob INIT4(VAR_BLOB, 0, NULL, NULL); EXTERN type_T t_job INIT4(VAR_JOB, 0, NULL, NULL); diff --git a/src/version.c b/src/version.c index a28fc03858..8d43c79141 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 251, /**/ 250, /**/ From 3dd64608f6183a49c6854652017b928556224935 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 13 Feb 2020 20:31:28 +0100 Subject: [PATCH 33/55] patch 8.2.0252: Windows compiler warns for using size_t Problem: Windows compiler warns for using size_t. Solution: Change to int. (Mike Williams) --- src/version.c | 2 ++ src/vim9compile.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/version.c b/src/version.c index 8d43c79141..8ebbf491c5 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 252, /**/ 251, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 96037d917f..c6201be900 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4427,7 +4427,7 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED) char_u *end; char_u *pat; char_u *tofree = NULL; - size_t len; + int len; // Push v:exception, push {expr} and MATCH generate_instr_type(cctx, ISN_PUSHEXC, &t_string); @@ -4440,9 +4440,9 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED) return FAIL; } if (tofree == NULL) - len = end - (p + 1); + len = (int)(end - (p + 1)); else - len = end - (tofree + 1); + len = (int)(end - (tofree + 1)); pat = vim_strnsave(p + 1, len); vim_free(tofree); p += len + 2; From 21456cdccbdf9d222938139769f1abe95b8effdd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 13 Feb 2020 21:29:32 +0100 Subject: [PATCH 34/55] patch 8.2.0253: crash when using :disassamble without argument Problem: Crash when using :disassamble without argument. (Dhiraj Mishra) Solution: Check for missing argument. (Dominique Pelle, closes #5635, closes #5637) --- src/ex_cmds.h | 2 +- src/testdir/test_vim9_disassemble.vim | 4 ++++ src/version.c | 2 ++ src/vim9execute.c | 9 ++++++++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 10b9ed7233..f09fb3bffa 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -479,7 +479,7 @@ EXCMD(CMD_digraphs, "digraphs", ex_digraphs, EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, ADDR_NONE), EXCMD(CMD_disassemble, "disassemble", ex_disassemble, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_NEEDARG|EX_TRLBAR|EX_CMDWIN, ADDR_NONE), EXCMD(CMD_djump, "djump", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index d10e74148d..a873c86571 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -23,6 +23,10 @@ enddef def Test_disassemble_load() assert_fails('disass NoFunc', 'E1061:') assert_fails('disass NotCompiled', 'E1062:') + assert_fails('disass', 'E471:') + assert_fails('disass [', 'E475:') + assert_fails('disass 234', 'E475:') + assert_fails('disass foo', 'E475:') let res = execute('disass s:ScriptFuncLoad') assert_match('\d*_ScriptFuncLoad.*' diff --git a/src/version.c b/src/version.c index 8ebbf491c5..0499e5da19 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 253, /**/ 252, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index ed3a75b106..c31506a86d 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1590,6 +1590,7 @@ failed: void ex_disassemble(exarg_T *eap) { + char_u *arg = eap->arg; char_u *fname; ufunc_T *ufunc; dfunc_T *dfunc; @@ -1598,8 +1599,14 @@ ex_disassemble(exarg_T *eap) int line_idx = 0; int prev_current = 0; - fname = trans_function_name(&eap->arg, FALSE, + fname = trans_function_name(&arg, FALSE, TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL); + if (fname == NULL) + { + semsg(_(e_invarg2), eap->arg); + return; + } + ufunc = find_func(fname, NULL); vim_free(fname); if (ufunc == NULL) From ae8d2de3a9c0436a543c7d46071104af31ff6db7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 13 Feb 2020 21:42:24 +0100 Subject: [PATCH 35/55] patch 8.2.0254: compiler warning for checking size_t to be negative Problem: Compiler warning for checking size_t to be negative. Solution: Only check for zero. (Zoltan Arpadffy) --- src/version.c | 2 ++ src/vim9compile.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/version.c b/src/version.c index 0499e5da19..dc3d1634f0 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 254, /**/ 253, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index c6201be900..4413a514da 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -138,7 +138,7 @@ lookup_local(char_u *name, size_t len, cctx_T *cctx) { int idx; - if (len <= 0) + if (len == 0) return -1; for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx) { @@ -160,7 +160,7 @@ lookup_arg(char_u *name, size_t len, cctx_T *cctx) { int idx; - if (len <= 0) + if (len == 0) return -1; for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx) { From f2cecb6c10909184281e31a8f968200f3841562d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 13 Feb 2020 21:59:25 +0100 Subject: [PATCH 36/55] patch 8.2.0255: VMS: missing files in build Problem: VMS: missing files in build. Solution: Add the files. (Zoltan Arpadffy) --- src/Make_vms.mms | 18 ++++++++++++++++++ src/version.c | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/Make_vms.mms b/src/Make_vms.mms index 6d5db4b6e3..8a74d3eb0e 100644 --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -386,6 +386,9 @@ SRC = \ usercmd.c \ userfunc.c \ version.c \ + vim9compile.c \ + vim9execute.c \ + vim9script.c \ viminfo.c \ window.c \ $(GUI_SRC) \ @@ -489,6 +492,9 @@ OBJ = \ usercmd.obj \ userfunc.obj \ version.obj \ + vim9compile.obj \ + vim9execute.obj \ + vim9script.obj \ viminfo.obj \ window.obj \ $(GUI_OBJ) \ @@ -994,6 +1000,18 @@ viminfo.obj : viminfo.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h \ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ globals.h version.h +vim9compile.obj : vim9compile.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ + globals.h version.h +vim9execute.obj : vim9execute.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ + globals.h version.h +vim9script.obj : vim9script.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h \ + gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ + globals.h version.h window.obj : window.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h \ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \ diff --git a/src/version.c b/src/version.c index dc3d1634f0..49a4b08ea3 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 255, /**/ 254, /**/ From 0a8fed6231c84e4e1b3a7dd6c0d95d3f98207fe0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 14 Feb 2020 13:22:17 +0100 Subject: [PATCH 37/55] patch 8.2.0256: time and timer related code is spread out Problem: Time and timer related code is spread out. Solution: Move time and timer related code to a new file. (Yegappan Lakshmanan, closes #5604) --- Filelist | 2 + src/Make_cyg_ming.mak | 1 + src/Make_morph.mak | 1 + src/Make_mvc.mak | 4 + src/Make_vms.mms | 5 + src/Makefile | 10 + src/README.md | 1 + src/evalfunc.c | 226 --------- src/ex_cmds.c | 14 - src/ex_cmds2.c | 492 ------------------- src/main.c | 104 ---- src/memline.c | 88 ---- src/misc1.c | 31 -- src/misc2.c | 82 ---- src/proto.h | 1 + src/proto/ex_cmds.pro | 1 - src/proto/ex_cmds2.pro | 11 - src/proto/main.pro | 3 - src/proto/memline.pro | 2 - src/proto/misc1.pro | 1 - src/proto/misc2.pro | 3 - src/proto/time.pro | 28 ++ src/time.c | 1041 ++++++++++++++++++++++++++++++++++++++++ src/version.c | 2 + 24 files changed, 1096 insertions(+), 1058 deletions(-) create mode 100644 src/proto/time.pro create mode 100644 src/time.c diff --git a/Filelist b/Filelist index 91e6b04325..41eb53f5a3 100644 --- a/Filelist +++ b/Filelist @@ -127,6 +127,7 @@ SRC_ALL = \ src/termlib.c \ src/testing.c \ src/textprop.c \ + src/time.c \ src/ui.c \ src/undo.c \ src/usercmd.c \ @@ -275,6 +276,7 @@ SRC_ALL = \ src/proto/termlib.pro \ src/proto/testing.pro \ src/proto/textprop.pro \ + src/proto/time.pro \ src/proto/ui.pro \ src/proto/undo.pro \ src/proto/usercmd.pro \ diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 639f3e5dcb..99c004fc07 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -783,6 +783,7 @@ OBJ = \ $(OUTDIR)/term.o \ $(OUTDIR)/testing.o \ $(OUTDIR)/textprop.o \ + $(OUTDIR)/time.o \ $(OUTDIR)/ui.o \ $(OUTDIR)/undo.o \ $(OUTDIR)/usercmd.o \ diff --git a/src/Make_morph.mak b/src/Make_morph.mak index bb5805c4d2..2c226de298 100644 --- a/src/Make_morph.mak +++ b/src/Make_morph.mak @@ -102,6 +102,7 @@ SRC = arabic.c \ term.c \ testing.c \ textprop.c \ + time.c \ ui.c \ undo.c \ usercmd.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index da9a911d0a..fd7a6ab5c3 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -799,6 +799,7 @@ OBJ = \ $(OUTDIR)\term.obj \ $(OUTDIR)\testing.obj \ $(OUTDIR)\textprop.obj \ + $(OUTDIR)\time.obj \ $(OUTDIR)\ui.obj \ $(OUTDIR)\undo.obj \ $(OUTDIR)\usercmd.obj \ @@ -1733,6 +1734,8 @@ $(OUTDIR)/term.obj: $(OUTDIR) testing.c $(INCL) $(OUTDIR)/textprop.obj: $(OUTDIR) textprop.c $(INCL) +$(OUTDIR)/time.obj: $(OUTDIR) time.c $(INCL) + $(OUTDIR)/ui.obj: $(OUTDIR) ui.c $(INCL) $(OUTDIR)/undo.obj: $(OUTDIR) undo.c $(INCL) @@ -1926,6 +1929,7 @@ proto.h: \ proto/term.pro \ proto/testing.pro \ proto/textprop.pro \ + proto/time.pro \ proto/ui.pro \ proto/undo.pro \ proto/usercmd.pro \ diff --git a/src/Make_vms.mms b/src/Make_vms.mms index 8a74d3eb0e..32857decc1 100644 --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -381,6 +381,7 @@ SRC = \ termlib.c \ testing.c \ textprop.c \ + time.c \ ui.c \ undo.c \ usercmd.c \ @@ -487,6 +488,7 @@ OBJ = \ termlib.obj \ testing.obj \ textprop.obj \ + time.obj \ ui.obj \ undo.obj \ usercmd.obj \ @@ -978,6 +980,9 @@ testing.obj : testing.c vim.h [.auto]config.h feature.h os_unix.h \ textprop.obj : textprop.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h +time.obj : time.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ + [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h ui.obj : ui.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h diff --git a/src/Makefile b/src/Makefile index 912098f8b3..e284530164 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1661,6 +1661,7 @@ BASIC_SRC = \ terminal.c \ testing.c \ textprop.c \ + time.c \ ui.c \ undo.c \ usercmd.c \ @@ -1800,6 +1801,7 @@ OBJ_COMMON = \ objects/terminal.o \ objects/testing.o \ objects/textprop.o \ + objects/time.o \ objects/ui.o \ objects/undo.o \ objects/usercmd.o \ @@ -1971,6 +1973,7 @@ PRO_AUTO = \ termlib.pro \ testing.pro \ textprop.pro \ + time.pro \ ui.pro \ undo.pro \ usercmd.pro \ @@ -3433,6 +3436,9 @@ objects/testing.o: testing.c objects/textprop.o: textprop.c $(CCC) -o $@ textprop.c +objects/time.o: time.c + $(CCC) -o $@ time.c + objects/ui.o: ui.c $(CCC) -o $@ ui.c @@ -3959,6 +3965,10 @@ objects/textprop.o: textprop.c vim.h protodef.h auto/config.h feature.h os_unix. auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h +objects/time.o: time.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h objects/ui.o: ui.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/README.md b/src/README.md index 0262a7a5bd..4412d533ee 100644 --- a/src/README.md +++ b/src/README.md @@ -79,6 +79,7 @@ tag.c | tags term.c | terminal handling, termcap codes testing.c | testing: assert and test functions textprop.c | text properties +time.c | time and timer functions undo.c | undo and redo usercmd.c | user defined commands userfunc.c | user defined functions diff --git a/src/evalfunc.c b/src/evalfunc.c index 6e96d0d1b8..b4009f0aef 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -20,10 +20,6 @@ # include #endif -#if defined(MACOS_X) -# include // for time_t -#endif - #ifdef FEAT_FLOAT static void f_abs(typval_T *argvars, typval_T *rettv); static void f_acos(typval_T *argvars, typval_T *rettv); @@ -126,7 +122,6 @@ static void f_libcall(typval_T *argvars, typval_T *rettv); static void f_libcallnr(typval_T *argvars, typval_T *rettv); static void f_line(typval_T *argvars, typval_T *rettv); static void f_line2byte(typval_T *argvars, typval_T *rettv); -static void f_localtime(typval_T *argvars, typval_T *rettv); #ifdef FEAT_FLOAT static void f_log(typval_T *argvars, typval_T *rettv); static void f_log10(typval_T *argvars, typval_T *rettv); @@ -173,11 +168,6 @@ static void f_rand(typval_T *argvars, typval_T *rettv); static void f_range(typval_T *argvars, typval_T *rettv); static void f_reg_executing(typval_T *argvars, typval_T *rettv); static void f_reg_recording(typval_T *argvars, typval_T *rettv); -static void f_reltime(typval_T *argvars, typval_T *rettv); -#ifdef FEAT_FLOAT -static void f_reltimefloat(typval_T *argvars, typval_T *rettv); -#endif -static void f_reltimestr(typval_T *argvars, typval_T *rettv); static void f_remote_expr(typval_T *argvars, typval_T *rettv); static void f_remote_foreground(typval_T *argvars, typval_T *rettv); static void f_remote_peek(typval_T *argvars, typval_T *rettv); @@ -234,17 +224,11 @@ static void f_str2float(typval_T *argvars, typval_T *rettv); static void f_str2list(typval_T *argvars, typval_T *rettv); static void f_str2nr(typval_T *argvars, typval_T *rettv); static void f_strchars(typval_T *argvars, typval_T *rettv); -#ifdef HAVE_STRFTIME -static void f_strftime(typval_T *argvars, typval_T *rettv); -#endif static void f_strgetchar(typval_T *argvars, typval_T *rettv); static void f_stridx(typval_T *argvars, typval_T *rettv); static void f_strlen(typval_T *argvars, typval_T *rettv); static void f_strcharpart(typval_T *argvars, typval_T *rettv); static void f_strpart(typval_T *argvars, typval_T *rettv); -#ifdef HAVE_STRPTIME -static void f_strptime(typval_T *argvars, typval_T *rettv); -#endif static void f_strridx(typval_T *argvars, typval_T *rettv); static void f_strtrans(typval_T *argvars, typval_T *rettv); static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv); @@ -4512,15 +4496,6 @@ f_line2byte(typval_T *argvars UNUSED, typval_T *rettv) #endif } -/* - * "localtime()" function - */ - static void -f_localtime(typval_T *argvars UNUSED, typval_T *rettv) -{ - rettv->vval.v_number = (varnumber_T)time(NULL); -} - #ifdef FEAT_FLOAT /* * "log()" function @@ -5500,118 +5475,6 @@ f_reg_recording(typval_T *argvars UNUSED, typval_T *rettv) return_register(reg_recording, rettv); } -#if defined(FEAT_RELTIME) -/* - * Convert a List to proftime_T. - * Return FAIL when there is something wrong. - */ - static int -list2proftime(typval_T *arg, proftime_T *tm) -{ - long n1, n2; - int error = FALSE; - - if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL - || arg->vval.v_list->lv_len != 2) - return FAIL; - n1 = list_find_nr(arg->vval.v_list, 0L, &error); - n2 = list_find_nr(arg->vval.v_list, 1L, &error); -# ifdef MSWIN - tm->HighPart = n1; - tm->LowPart = n2; -# else - tm->tv_sec = n1; - tm->tv_usec = n2; -# endif - return error ? FAIL : OK; -} -#endif // FEAT_RELTIME - -/* - * "reltime()" function - */ - static void -f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ -#ifdef FEAT_RELTIME - proftime_T res; - proftime_T start; - - if (argvars[0].v_type == VAR_UNKNOWN) - { - // No arguments: get current time. - profile_start(&res); - } - else if (argvars[1].v_type == VAR_UNKNOWN) - { - if (list2proftime(&argvars[0], &res) == FAIL) - return; - profile_end(&res); - } - else - { - // Two arguments: compute the difference. - if (list2proftime(&argvars[0], &start) == FAIL - || list2proftime(&argvars[1], &res) == FAIL) - return; - profile_sub(&res, &start); - } - - if (rettv_list_alloc(rettv) == OK) - { - long n1, n2; - -# ifdef MSWIN - n1 = res.HighPart; - n2 = res.LowPart; -# else - n1 = res.tv_sec; - n2 = res.tv_usec; -# endif - list_append_number(rettv->vval.v_list, (varnumber_T)n1); - list_append_number(rettv->vval.v_list, (varnumber_T)n2); - } -#endif -} - -#ifdef FEAT_FLOAT -/* - * "reltimefloat()" function - */ - static void -f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv) -{ -# ifdef FEAT_RELTIME - proftime_T tm; -# endif - - rettv->v_type = VAR_FLOAT; - rettv->vval.v_float = 0; -# ifdef FEAT_RELTIME - if (list2proftime(&argvars[0], &tm) == OK) - rettv->vval.v_float = profile_float(&tm); -# endif -} -#endif - -/* - * "reltimestr()" function - */ - static void -f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv) -{ -#ifdef FEAT_RELTIME - proftime_T tm; -#endif - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; -#ifdef FEAT_RELTIME - if (list2proftime(&argvars[0], &tm) == OK) - rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm)); -#endif -} - #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) static void make_connection(void) @@ -7422,61 +7285,6 @@ f_str2nr(typval_T *argvars, typval_T *rettv) } -#ifdef HAVE_STRFTIME -/* - * "strftime({format}[, {time}])" function - */ - static void -f_strftime(typval_T *argvars, typval_T *rettv) -{ - char_u result_buf[256]; - struct tm tmval; - struct tm *curtime; - time_t seconds; - char_u *p; - - rettv->v_type = VAR_STRING; - - p = tv_get_string(&argvars[0]); - if (argvars[1].v_type == VAR_UNKNOWN) - seconds = time(NULL); - else - seconds = (time_t)tv_get_number(&argvars[1]); - curtime = vim_localtime(&seconds, &tmval); - // MSVC returns NULL for an invalid value of seconds. - if (curtime == NULL) - rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); - else - { - vimconv_T conv; - char_u *enc; - - conv.vc_type = CONV_NONE; - enc = enc_locale(); - convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) - p = string_convert(&conv, p, NULL); - if (p != NULL) - (void)strftime((char *)result_buf, sizeof(result_buf), - (char *)p, curtime); - else - result_buf[0] = NUL; - - if (conv.vc_type != CONV_NONE) - vim_free(p); - convert_setup(&conv, enc, p_enc); - if (conv.vc_type != CONV_NONE) - rettv->vval.v_string = string_convert(&conv, result_buf, NULL); - else - rettv->vval.v_string = vim_strsave(result_buf); - - // Release conversion descriptors - convert_setup(&conv, NULL, NULL); - vim_free(enc); - } -} -#endif - /* * "strgetchar()" function */ @@ -7734,40 +7542,6 @@ f_strpart(typval_T *argvars, typval_T *rettv) rettv->vval.v_string = vim_strnsave(p + n, len); } -#ifdef HAVE_STRPTIME -/* - * "strptime({format}, {timestring})" function - */ - static void -f_strptime(typval_T *argvars, typval_T *rettv) -{ - struct tm tmval; - char_u *fmt; - char_u *str; - vimconv_T conv; - char_u *enc; - - vim_memset(&tmval, NUL, sizeof(tmval)); - fmt = tv_get_string(&argvars[0]); - str = tv_get_string(&argvars[1]); - - conv.vc_type = CONV_NONE; - enc = enc_locale(); - convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) - fmt = string_convert(&conv, fmt, NULL); - if (fmt == NULL - || strptime((char *)str, (char *)fmt, &tmval) == NULL - || (rettv->vval.v_number = mktime(&tmval)) == -1) - rettv->vval.v_number = 0; - - if (conv.vc_type != CONV_NONE) - vim_free(fmt); - convert_setup(&conv, NULL, NULL); - vim_free(enc); -} -#endif - /* * "strridx()" function */ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 881e6f9265..0eeb3f3399 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -1678,20 +1678,6 @@ append_redir( (char *)opt, (char *)fname); } -/* - * Return the current time in seconds. Calls time(), unless test_settime() - * was used. - */ - time_T -vim_time(void) -{ -# ifdef FEAT_EVAL - return time_for_testing == 0 ? time(NULL) : time_for_testing; -# else - return time(NULL); -# endif -} - /* * Implementation of ":fixdel", also used by get_stty(). * resulting diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 4f8f7fbf65..bbaff391e4 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -14,498 +14,6 @@ #include "vim.h" #include "version.h" -#if defined(FEAT_EVAL) || defined(PROTO) -# if defined(FEAT_TIMERS) || defined(PROTO) -static timer_T *first_timer = NULL; -static long last_timer_id = 0; - -/* - * Return time left until "due". Negative if past "due". - */ - long -proftime_time_left(proftime_T *due, proftime_T *now) -{ -# ifdef MSWIN - LARGE_INTEGER fr; - - if (now->QuadPart > due->QuadPart) - return 0; - QueryPerformanceFrequency(&fr); - return (long)(((double)(due->QuadPart - now->QuadPart) - / (double)fr.QuadPart) * 1000); -# else - if (now->tv_sec > due->tv_sec) - return 0; - return (due->tv_sec - now->tv_sec) * 1000 - + (due->tv_usec - now->tv_usec) / 1000; -# endif -} - -/* - * Insert a timer in the list of timers. - */ - static void -insert_timer(timer_T *timer) -{ - timer->tr_next = first_timer; - timer->tr_prev = NULL; - if (first_timer != NULL) - first_timer->tr_prev = timer; - first_timer = timer; - did_add_timer = TRUE; -} - -/* - * Take a timer out of the list of timers. - */ - static void -remove_timer(timer_T *timer) -{ - if (timer->tr_prev == NULL) - first_timer = timer->tr_next; - else - timer->tr_prev->tr_next = timer->tr_next; - if (timer->tr_next != NULL) - timer->tr_next->tr_prev = timer->tr_prev; -} - - static void -free_timer(timer_T *timer) -{ - free_callback(&timer->tr_callback); - vim_free(timer); -} - -/* - * Create a timer and return it. NULL if out of memory. - * Caller should set the callback. - */ - timer_T * -create_timer(long msec, int repeat) -{ - timer_T *timer = ALLOC_CLEAR_ONE(timer_T); - long prev_id = last_timer_id; - - if (timer == NULL) - return NULL; - if (++last_timer_id <= prev_id) - // Overflow! Might cause duplicates... - last_timer_id = 0; - timer->tr_id = last_timer_id; - insert_timer(timer); - if (repeat != 0) - timer->tr_repeat = repeat - 1; - timer->tr_interval = msec; - - profile_setlimit(msec, &timer->tr_due); - return timer; -} - -/* - * Invoke the callback of "timer". - */ - static void -timer_callback(timer_T *timer) -{ - typval_T rettv; - typval_T argv[2]; - - argv[0].v_type = VAR_NUMBER; - argv[0].vval.v_number = (varnumber_T)timer->tr_id; - argv[1].v_type = VAR_UNKNOWN; - - call_callback(&timer->tr_callback, -1, &rettv, 1, argv); - clear_tv(&rettv); -} - -/* - * Call timers that are due. - * Return the time in msec until the next timer is due. - * Returns -1 if there are no pending timers. - */ - long -check_due_timer(void) -{ - timer_T *timer; - timer_T *timer_next; - long this_due; - long next_due = -1; - proftime_T now; - int did_one = FALSE; - int need_update_screen = FALSE; - long current_id = last_timer_id; - - // Don't run any timers while exiting or dealing with an error. - if (exiting || aborting()) - return next_due; - - profile_start(&now); - for (timer = first_timer; timer != NULL && !got_int; timer = timer_next) - { - timer_next = timer->tr_next; - - if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused) - continue; - this_due = proftime_time_left(&timer->tr_due, &now); - if (this_due <= 1) - { - // Save and restore a lot of flags, because the timer fires while - // waiting for a character, which might be halfway a command. - int save_timer_busy = timer_busy; - int save_vgetc_busy = vgetc_busy; - int save_did_emsg = did_emsg; - int save_called_emsg = called_emsg; - int save_must_redraw = must_redraw; - int save_trylevel = trylevel; - int save_did_throw = did_throw; - int save_ex_pressedreturn = get_pressedreturn(); - int save_may_garbage_collect = may_garbage_collect; - except_T *save_current_exception = current_exception; - vimvars_save_T vvsave; - - // Create a scope for running the timer callback, ignoring most of - // the current scope, such as being inside a try/catch. - timer_busy = timer_busy > 0 || vgetc_busy > 0; - vgetc_busy = 0; - called_emsg = 0; - did_emsg = FALSE; - did_uncaught_emsg = FALSE; - must_redraw = 0; - trylevel = 0; - did_throw = FALSE; - current_exception = NULL; - may_garbage_collect = FALSE; - save_vimvars(&vvsave); - - timer->tr_firing = TRUE; - timer_callback(timer); - timer->tr_firing = FALSE; - - timer_next = timer->tr_next; - did_one = TRUE; - timer_busy = save_timer_busy; - vgetc_busy = save_vgetc_busy; - if (did_uncaught_emsg) - ++timer->tr_emsg_count; - did_emsg = save_did_emsg; - called_emsg = save_called_emsg; - trylevel = save_trylevel; - did_throw = save_did_throw; - current_exception = save_current_exception; - restore_vimvars(&vvsave); - if (must_redraw != 0) - need_update_screen = TRUE; - must_redraw = must_redraw > save_must_redraw - ? must_redraw : save_must_redraw; - set_pressedreturn(save_ex_pressedreturn); - may_garbage_collect = save_may_garbage_collect; - - // Only fire the timer again if it repeats and stop_timer() wasn't - // called while inside the callback (tr_id == -1). - if (timer->tr_repeat != 0 && timer->tr_id != -1 - && timer->tr_emsg_count < 3) - { - profile_setlimit(timer->tr_interval, &timer->tr_due); - this_due = proftime_time_left(&timer->tr_due, &now); - if (this_due < 1) - this_due = 1; - if (timer->tr_repeat > 0) - --timer->tr_repeat; - } - else - { - this_due = -1; - remove_timer(timer); - free_timer(timer); - } - } - if (this_due > 0 && (next_due == -1 || next_due > this_due)) - next_due = this_due; - } - - if (did_one) - redraw_after_callback(need_update_screen); - -#ifdef FEAT_BEVAL_TERM - if (bevalexpr_due_set) - { - this_due = proftime_time_left(&bevalexpr_due, &now); - if (this_due <= 1) - { - bevalexpr_due_set = FALSE; - if (balloonEval == NULL) - { - balloonEval = ALLOC_CLEAR_ONE(BalloonEval); - balloonEvalForTerm = TRUE; - } - if (balloonEval != NULL) - { - general_beval_cb(balloonEval, 0); - setcursor(); - out_flush(); - } - } - else if (next_due == -1 || next_due > this_due) - next_due = this_due; - } -#endif -#ifdef FEAT_TERMINAL - // Some terminal windows may need their buffer updated. - next_due = term_check_timers(next_due, &now); -#endif - - return current_id != last_timer_id ? 1 : next_due; -} - -/* - * Find a timer by ID. Returns NULL if not found; - */ - static timer_T * -find_timer(long id) -{ - timer_T *timer; - - if (id >= 0) - { - for (timer = first_timer; timer != NULL; timer = timer->tr_next) - if (timer->tr_id == id) - return timer; - } - return NULL; -} - - -/* - * Stop a timer and delete it. - */ - void -stop_timer(timer_T *timer) -{ - if (timer->tr_firing) - // Free the timer after the callback returns. - timer->tr_id = -1; - else - { - remove_timer(timer); - free_timer(timer); - } -} - - static void -stop_all_timers(void) -{ - timer_T *timer; - timer_T *timer_next; - - for (timer = first_timer; timer != NULL; timer = timer_next) - { - timer_next = timer->tr_next; - stop_timer(timer); - } -} - - static void -add_timer_info(typval_T *rettv, timer_T *timer) -{ - list_T *list = rettv->vval.v_list; - dict_T *dict = dict_alloc(); - dictitem_T *di; - long remaining; - proftime_T now; - - if (dict == NULL) - return; - list_append_dict(list, dict); - - dict_add_number(dict, "id", timer->tr_id); - dict_add_number(dict, "time", (long)timer->tr_interval); - - profile_start(&now); - remaining = proftime_time_left(&timer->tr_due, &now); - dict_add_number(dict, "remaining", (long)remaining); - - dict_add_number(dict, "repeat", - (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1)); - dict_add_number(dict, "paused", (long)(timer->tr_paused)); - - di = dictitem_alloc((char_u *)"callback"); - if (di != NULL) - { - if (dict_add(dict, di) == FAIL) - vim_free(di); - else - put_callback(&timer->tr_callback, &di->di_tv); - } -} - - static void -add_timer_info_all(typval_T *rettv) -{ - timer_T *timer; - - for (timer = first_timer; timer != NULL; timer = timer->tr_next) - if (timer->tr_id != -1) - add_timer_info(rettv, timer); -} - -/* - * Mark references in partials of timers. - */ - int -set_ref_in_timer(int copyID) -{ - int abort = FALSE; - timer_T *timer; - typval_T tv; - - for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next) - { - if (timer->tr_callback.cb_partial != NULL) - { - tv.v_type = VAR_PARTIAL; - tv.vval.v_partial = timer->tr_callback.cb_partial; - } - else - { - tv.v_type = VAR_FUNC; - tv.vval.v_string = timer->tr_callback.cb_name; - } - abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); - } - return abort; -} - -# if defined(EXITFREE) || defined(PROTO) - void -timer_free_all() -{ - timer_T *timer; - - while (first_timer != NULL) - { - timer = first_timer; - remove_timer(timer); - free_timer(timer); - } -} -# endif - -/* - * "timer_info([timer])" function - */ - void -f_timer_info(typval_T *argvars, typval_T *rettv) -{ - timer_T *timer = NULL; - - if (rettv_list_alloc(rettv) != OK) - return; - if (argvars[0].v_type != VAR_UNKNOWN) - { - if (argvars[0].v_type != VAR_NUMBER) - emsg(_(e_number_exp)); - else - { - timer = find_timer((int)tv_get_number(&argvars[0])); - if (timer != NULL) - add_timer_info(rettv, timer); - } - } - else - add_timer_info_all(rettv); -} - -/* - * "timer_pause(timer, paused)" function - */ - void -f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED) -{ - timer_T *timer = NULL; - int paused = (int)tv_get_number(&argvars[1]); - - if (argvars[0].v_type != VAR_NUMBER) - emsg(_(e_number_exp)); - else - { - timer = find_timer((int)tv_get_number(&argvars[0])); - if (timer != NULL) - timer->tr_paused = paused; - } -} - -/* - * "timer_start(time, callback [, options])" function - */ - void -f_timer_start(typval_T *argvars, typval_T *rettv) -{ - long msec = (long)tv_get_number(&argvars[0]); - timer_T *timer; - int repeat = 0; - callback_T callback; - dict_T *dict; - - rettv->vval.v_number = -1; - if (check_secure()) - return; - if (argvars[2].v_type != VAR_UNKNOWN) - { - if (argvars[2].v_type != VAR_DICT - || (dict = argvars[2].vval.v_dict) == NULL) - { - semsg(_(e_invarg2), tv_get_string(&argvars[2])); - return; - } - if (dict_find(dict, (char_u *)"repeat", -1) != NULL) - repeat = dict_get_number(dict, (char_u *)"repeat"); - } - - callback = get_callback(&argvars[1]); - if (callback.cb_name == NULL) - return; - - timer = create_timer(msec, repeat); - if (timer == NULL) - free_callback(&callback); - else - { - set_callback(&timer->tr_callback, &callback); - rettv->vval.v_number = (varnumber_T)timer->tr_id; - } -} - -/* - * "timer_stop(timer)" function - */ - void -f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED) -{ - timer_T *timer; - - if (argvars[0].v_type != VAR_NUMBER) - { - emsg(_(e_number_exp)); - return; - } - timer = find_timer((int)tv_get_number(&argvars[0])); - if (timer != NULL) - stop_timer(timer); -} - -/* - * "timer_stopall()" function - */ - void -f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED) -{ - stop_all_timers(); -} - -# endif // FEAT_TIMERS - -#endif // FEAT_EVAL - /* * If 'autowrite' option set, try to write the file. * Careful: autocommands may make "buf" invalid! diff --git a/src/main.c b/src/main.c index c747aba3d1..2d61c0682e 100644 --- a/src/main.c +++ b/src/main.c @@ -3669,110 +3669,6 @@ check_swap_exists_action(void) #endif // NO_VIM_MAIN -#if defined(STARTUPTIME) || defined(PROTO) -static struct timeval prev_timeval; - -# ifdef MSWIN -/* - * Windows doesn't have gettimeofday(), although it does have struct timeval. - */ - static int -gettimeofday(struct timeval *tv, char *dummy UNUSED) -{ - long t = clock(); - tv->tv_sec = t / CLOCKS_PER_SEC; - tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC; - return 0; -} -# endif - -/* - * Save the previous time before doing something that could nest. - * set "*tv_rel" to the time elapsed so far. - */ - void -time_push(void *tv_rel, void *tv_start) -{ - *((struct timeval *)tv_rel) = prev_timeval; - gettimeofday(&prev_timeval, NULL); - ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec - - ((struct timeval *)tv_rel)->tv_usec; - ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec - - ((struct timeval *)tv_rel)->tv_sec; - if (((struct timeval *)tv_rel)->tv_usec < 0) - { - ((struct timeval *)tv_rel)->tv_usec += 1000000; - --((struct timeval *)tv_rel)->tv_sec; - } - *(struct timeval *)tv_start = prev_timeval; -} - -/* - * Compute the previous time after doing something that could nest. - * Subtract "*tp" from prev_timeval; - * Note: The arguments are (void *) to avoid trouble with systems that don't - * have struct timeval. - */ - void -time_pop( - void *tp) // actually (struct timeval *) -{ - prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec; - prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec; - if (prev_timeval.tv_usec < 0) - { - prev_timeval.tv_usec += 1000000; - --prev_timeval.tv_sec; - } -} - - static void -time_diff(struct timeval *then, struct timeval *now) -{ - long usec; - long msec; - - usec = now->tv_usec - then->tv_usec; - msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L, - usec = usec % 1000L; - fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L); -} - - void -time_msg( - char *mesg, - void *tv_start) // only for do_source: start time; actually - // (struct timeval *) -{ - static struct timeval start; - struct timeval now; - - if (time_fd != NULL) - { - if (strstr(mesg, "STARTING") != NULL) - { - gettimeofday(&start, NULL); - prev_timeval = start; - fprintf(time_fd, "\n\ntimes in msec\n"); - fprintf(time_fd, " clock self+sourced self: sourced script\n"); - fprintf(time_fd, " clock elapsed: other lines\n\n"); - } - gettimeofday(&now, NULL); - time_diff(&start, &now); - if (((struct timeval *)tv_start) != NULL) - { - fprintf(time_fd, " "); - time_diff(((struct timeval *)tv_start), &now); - } - fprintf(time_fd, " "); - time_diff(&prev_timeval, &now); - prev_timeval = now; - fprintf(time_fd, ": %s\n", mesg); - } -} - -#endif - #if !defined(NO_VIM_MAIN) && defined(FEAT_EVAL) static void set_progpath(char_u *argv0) diff --git a/src/memline.c b/src/memline.c index c6db9136fe..b409eb5553 100644 --- a/src/memline.c +++ b/src/memline.c @@ -2080,94 +2080,6 @@ get_b0_dict(char_u *fname, dict_T *d) } #endif -/* - * Cache of the current timezone name as retrieved from TZ, or an empty string - * where unset, up to 64 octets long including trailing null byte. - */ -#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET) -static char tz_cache[64]; -#endif - -/* - * Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the - * latter version preferred for reentrancy. - * - * If we use localtime_r(3) and we have tzset(3) available, check to see if the - * environment variable TZ has changed since the last run, and call tzset(3) to - * update the global timezone variables if it has. This is because the POSIX - * standard doesn't require localtime_r(3) implementations to do that as it - * does with localtime(3), and we don't want to call tzset(3) every time. - */ - struct tm * -vim_localtime( - const time_t *timep, // timestamp for local representation - struct tm *result UNUSED) // pointer to caller return buffer -{ -#ifdef HAVE_LOCALTIME_R -# ifdef HAVE_TZSET - char *tz; // pointer for TZ environment var - - tz = (char *)mch_getenv((char_u *)"TZ"); - if (tz == NULL) - tz = ""; - if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0) - { - tzset(); - vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1); - } -# endif // HAVE_TZSET - return localtime_r(timep, result); -#else - return localtime(timep); -#endif // HAVE_LOCALTIME_R -} - -/* - * Replacement for ctime(), which is not safe to use. - * Requires strftime(), otherwise returns "(unknown)". - * If "thetime" is invalid returns "(invalid)". Never returns NULL. - * When "add_newline" is TRUE add a newline like ctime() does. - * Uses a static buffer. - */ - char * -get_ctime(time_t thetime, int add_newline) -{ - static char buf[50]; -#ifdef HAVE_STRFTIME - struct tm tmval; - struct tm *curtime; - - curtime = vim_localtime(&thetime, &tmval); - // MSVC returns NULL for an invalid value of seconds. - if (curtime == NULL) - vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1); - else - { - (void)strftime(buf, sizeof(buf) - 1, _("%a %b %d %H:%M:%S %Y"), - curtime); -# ifdef MSWIN - if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) - { - char_u *to_free = NULL; - int len; - - acp_to_enc((char_u *)buf, (int)strlen(buf), &to_free, &len); - if (to_free != NULL) - { - STRCPY(buf, to_free); - vim_free(to_free); - } - } -# endif - } -#else - STRCPY(buf, "(unknown)"); -#endif - if (add_newline) - STRCAT(buf, "\n"); - return buf; -} - /* * Give information about an existing swap file. * Returns timestamp (0 when unknown). diff --git a/src/misc1.c b/src/misc1.c index bb7137dc3a..635b87be2a 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -2597,34 +2597,3 @@ path_with_url(char_u *fname) ; return path_is_url(p); } - -/* - * Put timestamp "tt" in "buf[buflen]" in a nice format. - */ - void -add_time(char_u *buf, size_t buflen, time_t tt) -{ -#ifdef HAVE_STRFTIME - struct tm tmval; - struct tm *curtime; - - if (vim_time() - tt >= 100) - { - curtime = vim_localtime(&tt, &tmval); - if (vim_time() - tt < (60L * 60L * 12L)) - // within 12 hours - (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime); - else - // longer ago - (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime); - } - else -#endif - { - long seconds = (long)(vim_time() - tt); - - vim_snprintf((char *)buf, buflen, - NGETTEXT("%ld second ago", "%ld seconds ago", seconds), - seconds); - } -} diff --git a/src/misc2.c b/src/misc2.c index c0208de26e..6ef420cabf 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -4126,26 +4126,6 @@ get4c(FILE *fd) return (int)n; } -/* - * Read 8 bytes from "fd" and turn them into a time_T, MSB first. - * Returns -1 when encountering EOF. - */ - time_T -get8ctime(FILE *fd) -{ - int c; - time_T n = 0; - int i; - - for (i = 0; i < 8; ++i) - { - c = getc(fd); - if (c == EOF) return -1; - n = (n << 8) + c; - } - return n; -} - /* * Read a string of length "cnt" from "fd" into allocated memory. * Returns NULL when out of memory or unable to read that many bytes. @@ -4191,68 +4171,6 @@ put_bytes(FILE *fd, long_u nr, int len) return OK; } -#ifdef _MSC_VER -# if (_MSC_VER <= 1200) -// This line is required for VC6 without the service pack. Also see the -// matching #pragma below. - # pragma optimize("", off) -# endif -#endif - -/* - * Write time_T to file "fd" in 8 bytes. - * Returns FAIL when the write failed. - */ - int -put_time(FILE *fd, time_T the_time) -{ - char_u buf[8]; - - time_to_bytes(the_time, buf); - return fwrite(buf, (size_t)8, (size_t)1, fd) == 1 ? OK : FAIL; -} - -/* - * Write time_T to "buf[8]". - */ - void -time_to_bytes(time_T the_time, char_u *buf) -{ - int c; - int i; - int bi = 0; - time_T wtime = the_time; - - // time_T can be up to 8 bytes in size, more than long_u, thus we - // can't use put_bytes() here. - // Another problem is that ">>" may do an arithmetic shift that keeps the - // sign. This happens for large values of wtime. A cast to long_u may - // truncate if time_T is 8 bytes. So only use a cast when it is 4 bytes, - // it's safe to assume that long_u is 4 bytes or more and when using 8 - // bytes the top bit won't be set. - for (i = 7; i >= 0; --i) - { - if (i + 1 > (int)sizeof(time_T)) - // ">>" doesn't work well when shifting more bits than avail - buf[bi++] = 0; - else - { -#if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4 - c = (int)(wtime >> (i * 8)); -#else - c = (int)((long_u)wtime >> (i * 8)); -#endif - buf[bi++] = c; - } - } -} - -#ifdef _MSC_VER -# if (_MSC_VER <= 1200) - # pragma optimize("", on) -# endif -#endif - #endif #if defined(FEAT_QUICKFIX) || defined(FEAT_SPELL) || defined(PROTO) diff --git a/src/proto.h b/src/proto.h index 7836c528e5..31f75cfd83 100644 --- a/src/proto.h +++ b/src/proto.h @@ -221,6 +221,7 @@ void mbyte_im_set_active(int active_arg); # include "textprop.pro" # endif # include "testing.pro" +# include "time.pro" # include "ui.pro" # include "undo.pro" # include "usercmd.pro" diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro index 3693cf4265..92887a6cf7 100644 --- a/src/proto/ex_cmds.pro +++ b/src/proto/ex_cmds.pro @@ -9,7 +9,6 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out); void do_shell(char_u *cmd, int flags); char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp); void append_redir(char_u *buf, int buflen, char_u *opt, char_u *fname); -time_T vim_time(void); void do_fixdel(exarg_T *eap); void print_line_no_prefix(linenr_T lnum, int use_number, int list); void print_line(linenr_T lnum, int use_number, int list); diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro index 9f694da93b..b9d1929f7d 100644 --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -1,15 +1,4 @@ /* ex_cmds2.c */ -long proftime_time_left(proftime_T *due, proftime_T *now); -timer_T *create_timer(long msec, int repeat); -long check_due_timer(void); -void stop_timer(timer_T *timer); -int set_ref_in_timer(int copyID); -void timer_free_all(void); -void f_timer_info(typval_T *argvars, typval_T *rettv); -void f_timer_pause(typval_T *argvars, typval_T *rettv); -void f_timer_start(typval_T *argvars, typval_T *rettv); -void f_timer_stop(typval_T *argvars, typval_T *rettv); -void f_timer_stopall(typval_T *argvars, typval_T *rettv); int autowrite(buf_T *buf, int forceit); void autowrite_all(void); int check_changed(buf_T *buf, int flags); diff --git a/src/proto/main.pro b/src/proto/main.pro index c663cd2b15..5fa96c3903 100644 --- a/src/proto/main.pro +++ b/src/proto/main.pro @@ -12,9 +12,6 @@ void getout_preserve_modified(int exitval); void getout(int exitval); int process_env(char_u *env, int is_viminit); void mainerr_arg_missing(char_u *str); -void time_push(void *tv_rel, void *tv_start); -void time_pop(void *tp); -void time_msg(char *mesg, void *tv_start); void server_to_input_buf(char_u *str); char_u *eval_client_expr_to_string(char_u *expr); int sendToLocalVim(char_u *cmd, int asExpr, char_u **result); diff --git a/src/proto/memline.pro b/src/proto/memline.pro index 663930dabd..113417042e 100644 --- a/src/proto/memline.pro +++ b/src/proto/memline.pro @@ -13,8 +13,6 @@ void ml_recover(int checkext); int recover_names(char_u *fname, int list, int nr, char_u **fname_out); char_u *make_percent_swname(char_u *dir, char_u *name); void get_b0_dict(char_u *fname, dict_T *d); -struct tm *vim_localtime(const time_t *timep, struct tm *result); -char *get_ctime(time_t thetime, int add_newline); void ml_sync_all(int check_file, int check_char); void ml_preserve(buf_T *buf, int message); char_u *ml_get(linenr_T lnum); diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index e4f2c3d8b6..1327701e0a 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -47,5 +47,4 @@ int goto_im(void); char_u *get_isolated_shell_name(void); int path_is_url(char_u *p); int path_with_url(char_u *fname); -void add_time(char_u *buf, size_t buflen, time_t tt); /* vim: set ft=c : */ diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index a52b462804..6c047f332d 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -94,11 +94,8 @@ int filewritable(char_u *fname); int get2c(FILE *fd); int get3c(FILE *fd); int get4c(FILE *fd); -time_T get8ctime(FILE *fd); char_u *read_string(FILE *fd, int cnt); int put_bytes(FILE *fd, long_u nr, int len); -int put_time(FILE *fd, time_T the_time); -void time_to_bytes(time_T the_time, char_u *buf); int has_non_ascii(char_u *s); int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc); int build_argv_from_string(char_u *cmd, char ***argv, int *argc); diff --git a/src/proto/time.pro b/src/proto/time.pro new file mode 100644 index 0000000000..becafea3b2 --- /dev/null +++ b/src/proto/time.pro @@ -0,0 +1,28 @@ +/* time.c */ +char *get_ctime(time_t thetime, int add_newline); +time_T vim_time(void); +void f_localtime(typval_T *argvars, typval_T *rettv); +void f_reltime(typval_T *argvars, typval_T *rettv); +void f_reltimefloat(typval_T *argvars, typval_T *rettv); +void f_reltimestr(typval_T *argvars, typval_T *rettv); +void f_strftime(typval_T *argvars, typval_T *rettv); +void f_strptime(typval_T *argvars, typval_T *rettv); +long proftime_time_left(proftime_T *due, proftime_T *now); +timer_T *create_timer(long msec, int repeat); +long check_due_timer(void); +void stop_timer(timer_T *timer); +int set_ref_in_timer(int copyID); +void timer_free_all(void); +void f_timer_info(typval_T *argvars, typval_T *rettv); +void f_timer_pause(typval_T *argvars, typval_T *rettv); +void f_timer_start(typval_T *argvars, typval_T *rettv); +void f_timer_stop(typval_T *argvars, typval_T *rettv); +void f_timer_stopall(typval_T *argvars, typval_T *rettv); +void time_push(void *tv_rel, void *tv_start); +void time_pop(void *tp); +void time_msg(char *mesg, void *tv_start); +time_T get8ctime(FILE *fd); +int put_time(FILE *fd, time_T the_time); +void time_to_bytes(time_T the_time, char_u *buf); +void add_time(char_u *buf, size_t buflen, time_t tt); +/* vim: set ft=c : */ diff --git a/src/time.c b/src/time.c new file mode 100644 index 0000000000..2706ac22da --- /dev/null +++ b/src/time.c @@ -0,0 +1,1041 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * time.c: functions related to time and timers + */ + +#include "vim.h" + +/* + * Cache of the current timezone name as retrieved from TZ, or an empty string + * where unset, up to 64 octets long including trailing null byte. + */ +#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET) +static char tz_cache[64]; +#endif + +/* + * Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the + * latter version preferred for reentrancy. + * + * If we use localtime_r(3) and we have tzset(3) available, check to see if the + * environment variable TZ has changed since the last run, and call tzset(3) to + * update the global timezone variables if it has. This is because the POSIX + * standard doesn't require localtime_r(3) implementations to do that as it + * does with localtime(3), and we don't want to call tzset(3) every time. + */ + static struct tm * +vim_localtime( + const time_t *timep, // timestamp for local representation + struct tm *result UNUSED) // pointer to caller return buffer +{ +#ifdef HAVE_LOCALTIME_R +# ifdef HAVE_TZSET + char *tz; // pointer for TZ environment var + + tz = (char *)mch_getenv((char_u *)"TZ"); + if (tz == NULL) + tz = ""; + if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0) + { + tzset(); + vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1); + } +# endif // HAVE_TZSET + return localtime_r(timep, result); +#else + return localtime(timep); +#endif // HAVE_LOCALTIME_R +} + +/* + * Return the current time in seconds. Calls time(), unless test_settime() + * was used. + */ + time_T +vim_time(void) +{ +# ifdef FEAT_EVAL + return time_for_testing == 0 ? time(NULL) : time_for_testing; +# else + return time(NULL); +# endif +} + +/* + * Replacement for ctime(), which is not safe to use. + * Requires strftime(), otherwise returns "(unknown)". + * If "thetime" is invalid returns "(invalid)". Never returns NULL. + * When "add_newline" is TRUE add a newline like ctime() does. + * Uses a static buffer. + */ + char * +get_ctime(time_t thetime, int add_newline) +{ + static char buf[50]; +#ifdef HAVE_STRFTIME + struct tm tmval; + struct tm *curtime; + + curtime = vim_localtime(&thetime, &tmval); + // MSVC returns NULL for an invalid value of seconds. + if (curtime == NULL) + vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1); + else + { + (void)strftime(buf, sizeof(buf) - 1, _("%a %b %d %H:%M:%S %Y"), + curtime); +# ifdef MSWIN + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + char_u *to_free = NULL; + int len; + + acp_to_enc((char_u *)buf, (int)strlen(buf), &to_free, &len); + if (to_free != NULL) + { + STRCPY(buf, to_free); + vim_free(to_free); + } + } +# endif + } +#else + STRCPY(buf, "(unknown)"); +#endif + if (add_newline) + STRCAT(buf, "\n"); + return buf; +} + +#if defined(FEAT_EVAL) || defined(PROTO) + +#if defined(MACOS_X) +# include // for time_t +#endif + +/* + * "localtime()" function + */ + void +f_localtime(typval_T *argvars UNUSED, typval_T *rettv) +{ + rettv->vval.v_number = (varnumber_T)time(NULL); +} + +# if defined(FEAT_RELTIME) +/* + * Convert a List to proftime_T. + * Return FAIL when there is something wrong. + */ + static int +list2proftime(typval_T *arg, proftime_T *tm) +{ + long n1, n2; + int error = FALSE; + + if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL + || arg->vval.v_list->lv_len != 2) + return FAIL; + n1 = list_find_nr(arg->vval.v_list, 0L, &error); + n2 = list_find_nr(arg->vval.v_list, 1L, &error); +# ifdef MSWIN + tm->HighPart = n1; + tm->LowPart = n2; +# else + tm->tv_sec = n1; + tm->tv_usec = n2; +# endif + return error ? FAIL : OK; +} +# endif // FEAT_RELTIME + +/* + * "reltime()" function + */ + void +f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +# ifdef FEAT_RELTIME + proftime_T res; + proftime_T start; + + if (argvars[0].v_type == VAR_UNKNOWN) + { + // No arguments: get current time. + profile_start(&res); + } + else if (argvars[1].v_type == VAR_UNKNOWN) + { + if (list2proftime(&argvars[0], &res) == FAIL) + return; + profile_end(&res); + } + else + { + // Two arguments: compute the difference. + if (list2proftime(&argvars[0], &start) == FAIL + || list2proftime(&argvars[1], &res) == FAIL) + return; + profile_sub(&res, &start); + } + + if (rettv_list_alloc(rettv) == OK) + { + long n1, n2; + +# ifdef MSWIN + n1 = res.HighPart; + n2 = res.LowPart; +# else + n1 = res.tv_sec; + n2 = res.tv_usec; +# endif + list_append_number(rettv->vval.v_list, (varnumber_T)n1); + list_append_number(rettv->vval.v_list, (varnumber_T)n2); + } +# endif +} + +# ifdef FEAT_FLOAT +/* + * "reltimefloat()" function + */ + void +f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv) +{ +# ifdef FEAT_RELTIME + proftime_T tm; +# endif + + rettv->v_type = VAR_FLOAT; + rettv->vval.v_float = 0; +# ifdef FEAT_RELTIME + if (list2proftime(&argvars[0], &tm) == OK) + rettv->vval.v_float = profile_float(&tm); +# endif +} +# endif + +/* + * "reltimestr()" function + */ + void +f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv) +{ +# ifdef FEAT_RELTIME + proftime_T tm; +# endif + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; +# ifdef FEAT_RELTIME + if (list2proftime(&argvars[0], &tm) == OK) + rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm)); +# endif +} + +# if defined(HAVE_STRFTIME) || defined(PROTO) +/* + * "strftime({format}[, {time}])" function + */ + void +f_strftime(typval_T *argvars, typval_T *rettv) +{ + char_u result_buf[256]; + struct tm tmval; + struct tm *curtime; + time_t seconds; + char_u *p; + + rettv->v_type = VAR_STRING; + + p = tv_get_string(&argvars[0]); + if (argvars[1].v_type == VAR_UNKNOWN) + seconds = time(NULL); + else + seconds = (time_t)tv_get_number(&argvars[1]); + curtime = vim_localtime(&seconds, &tmval); + // MSVC returns NULL for an invalid value of seconds. + if (curtime == NULL) + rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); + else + { + vimconv_T conv; + char_u *enc; + + conv.vc_type = CONV_NONE; + enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) + p = string_convert(&conv, p, NULL); + if (p != NULL) + (void)strftime((char *)result_buf, sizeof(result_buf), + (char *)p, curtime); + else + result_buf[0] = NUL; + + if (conv.vc_type != CONV_NONE) + vim_free(p); + convert_setup(&conv, enc, p_enc); + if (conv.vc_type != CONV_NONE) + rettv->vval.v_string = string_convert(&conv, result_buf, NULL); + else + rettv->vval.v_string = vim_strsave(result_buf); + + // Release conversion descriptors + convert_setup(&conv, NULL, NULL); + vim_free(enc); + } +} +# endif + +# if defined(HAVE_STRPTIME) || defined(PROTO) +/* + * "strptime({format}, {timestring})" function + */ + void +f_strptime(typval_T *argvars, typval_T *rettv) +{ + struct tm tmval; + char_u *fmt; + char_u *str; + vimconv_T conv; + char_u *enc; + + vim_memset(&tmval, NUL, sizeof(tmval)); + fmt = tv_get_string(&argvars[0]); + str = tv_get_string(&argvars[1]); + + conv.vc_type = CONV_NONE; + enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) + fmt = string_convert(&conv, fmt, NULL); + if (fmt == NULL + || strptime((char *)str, (char *)fmt, &tmval) == NULL + || (rettv->vval.v_number = mktime(&tmval)) == -1) + rettv->vval.v_number = 0; + + if (conv.vc_type != CONV_NONE) + vim_free(fmt); + convert_setup(&conv, NULL, NULL); + vim_free(enc); +} +# endif + +# if defined(FEAT_TIMERS) || defined(PROTO) +static timer_T *first_timer = NULL; +static long last_timer_id = 0; + +/* + * Return time left until "due". Negative if past "due". + */ + long +proftime_time_left(proftime_T *due, proftime_T *now) +{ +# ifdef MSWIN + LARGE_INTEGER fr; + + if (now->QuadPart > due->QuadPart) + return 0; + QueryPerformanceFrequency(&fr); + return (long)(((double)(due->QuadPart - now->QuadPart) + / (double)fr.QuadPart) * 1000); +# else + if (now->tv_sec > due->tv_sec) + return 0; + return (due->tv_sec - now->tv_sec) * 1000 + + (due->tv_usec - now->tv_usec) / 1000; +# endif +} + +/* + * Insert a timer in the list of timers. + */ + static void +insert_timer(timer_T *timer) +{ + timer->tr_next = first_timer; + timer->tr_prev = NULL; + if (first_timer != NULL) + first_timer->tr_prev = timer; + first_timer = timer; + did_add_timer = TRUE; +} + +/* + * Take a timer out of the list of timers. + */ + static void +remove_timer(timer_T *timer) +{ + if (timer->tr_prev == NULL) + first_timer = timer->tr_next; + else + timer->tr_prev->tr_next = timer->tr_next; + if (timer->tr_next != NULL) + timer->tr_next->tr_prev = timer->tr_prev; +} + + static void +free_timer(timer_T *timer) +{ + free_callback(&timer->tr_callback); + vim_free(timer); +} + +/* + * Create a timer and return it. NULL if out of memory. + * Caller should set the callback. + */ + timer_T * +create_timer(long msec, int repeat) +{ + timer_T *timer = ALLOC_CLEAR_ONE(timer_T); + long prev_id = last_timer_id; + + if (timer == NULL) + return NULL; + if (++last_timer_id <= prev_id) + // Overflow! Might cause duplicates... + last_timer_id = 0; + timer->tr_id = last_timer_id; + insert_timer(timer); + if (repeat != 0) + timer->tr_repeat = repeat - 1; + timer->tr_interval = msec; + + profile_setlimit(msec, &timer->tr_due); + return timer; +} + +/* + * Invoke the callback of "timer". + */ + static void +timer_callback(timer_T *timer) +{ + typval_T rettv; + typval_T argv[2]; + + argv[0].v_type = VAR_NUMBER; + argv[0].vval.v_number = (varnumber_T)timer->tr_id; + argv[1].v_type = VAR_UNKNOWN; + + call_callback(&timer->tr_callback, -1, &rettv, 1, argv); + clear_tv(&rettv); +} + +/* + * Call timers that are due. + * Return the time in msec until the next timer is due. + * Returns -1 if there are no pending timers. + */ + long +check_due_timer(void) +{ + timer_T *timer; + timer_T *timer_next; + long this_due; + long next_due = -1; + proftime_T now; + int did_one = FALSE; + int need_update_screen = FALSE; + long current_id = last_timer_id; + + // Don't run any timers while exiting or dealing with an error. + if (exiting || aborting()) + return next_due; + + profile_start(&now); + for (timer = first_timer; timer != NULL && !got_int; timer = timer_next) + { + timer_next = timer->tr_next; + + if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused) + continue; + this_due = proftime_time_left(&timer->tr_due, &now); + if (this_due <= 1) + { + // Save and restore a lot of flags, because the timer fires while + // waiting for a character, which might be halfway a command. + int save_timer_busy = timer_busy; + int save_vgetc_busy = vgetc_busy; + int save_did_emsg = did_emsg; + int save_called_emsg = called_emsg; + int save_must_redraw = must_redraw; + int save_trylevel = trylevel; + int save_did_throw = did_throw; + int save_ex_pressedreturn = get_pressedreturn(); + int save_may_garbage_collect = may_garbage_collect; + except_T *save_current_exception = current_exception; + vimvars_save_T vvsave; + + // Create a scope for running the timer callback, ignoring most of + // the current scope, such as being inside a try/catch. + timer_busy = timer_busy > 0 || vgetc_busy > 0; + vgetc_busy = 0; + called_emsg = 0; + did_emsg = FALSE; + did_uncaught_emsg = FALSE; + must_redraw = 0; + trylevel = 0; + did_throw = FALSE; + current_exception = NULL; + may_garbage_collect = FALSE; + save_vimvars(&vvsave); + + timer->tr_firing = TRUE; + timer_callback(timer); + timer->tr_firing = FALSE; + + timer_next = timer->tr_next; + did_one = TRUE; + timer_busy = save_timer_busy; + vgetc_busy = save_vgetc_busy; + if (did_uncaught_emsg) + ++timer->tr_emsg_count; + did_emsg = save_did_emsg; + called_emsg = save_called_emsg; + trylevel = save_trylevel; + did_throw = save_did_throw; + current_exception = save_current_exception; + restore_vimvars(&vvsave); + if (must_redraw != 0) + need_update_screen = TRUE; + must_redraw = must_redraw > save_must_redraw + ? must_redraw : save_must_redraw; + set_pressedreturn(save_ex_pressedreturn); + may_garbage_collect = save_may_garbage_collect; + + // Only fire the timer again if it repeats and stop_timer() wasn't + // called while inside the callback (tr_id == -1). + if (timer->tr_repeat != 0 && timer->tr_id != -1 + && timer->tr_emsg_count < 3) + { + profile_setlimit(timer->tr_interval, &timer->tr_due); + this_due = proftime_time_left(&timer->tr_due, &now); + if (this_due < 1) + this_due = 1; + if (timer->tr_repeat > 0) + --timer->tr_repeat; + } + else + { + this_due = -1; + remove_timer(timer); + free_timer(timer); + } + } + if (this_due > 0 && (next_due == -1 || next_due > this_due)) + next_due = this_due; + } + + if (did_one) + redraw_after_callback(need_update_screen); + +#ifdef FEAT_BEVAL_TERM + if (bevalexpr_due_set) + { + this_due = proftime_time_left(&bevalexpr_due, &now); + if (this_due <= 1) + { + bevalexpr_due_set = FALSE; + if (balloonEval == NULL) + { + balloonEval = ALLOC_CLEAR_ONE(BalloonEval); + balloonEvalForTerm = TRUE; + } + if (balloonEval != NULL) + { + general_beval_cb(balloonEval, 0); + setcursor(); + out_flush(); + } + } + else if (next_due == -1 || next_due > this_due) + next_due = this_due; + } +#endif +#ifdef FEAT_TERMINAL + // Some terminal windows may need their buffer updated. + next_due = term_check_timers(next_due, &now); +#endif + + return current_id != last_timer_id ? 1 : next_due; +} + +/* + * Find a timer by ID. Returns NULL if not found; + */ + static timer_T * +find_timer(long id) +{ + timer_T *timer; + + if (id >= 0) + { + for (timer = first_timer; timer != NULL; timer = timer->tr_next) + if (timer->tr_id == id) + return timer; + } + return NULL; +} + + +/* + * Stop a timer and delete it. + */ + void +stop_timer(timer_T *timer) +{ + if (timer->tr_firing) + // Free the timer after the callback returns. + timer->tr_id = -1; + else + { + remove_timer(timer); + free_timer(timer); + } +} + + static void +stop_all_timers(void) +{ + timer_T *timer; + timer_T *timer_next; + + for (timer = first_timer; timer != NULL; timer = timer_next) + { + timer_next = timer->tr_next; + stop_timer(timer); + } +} + + static void +add_timer_info(typval_T *rettv, timer_T *timer) +{ + list_T *list = rettv->vval.v_list; + dict_T *dict = dict_alloc(); + dictitem_T *di; + long remaining; + proftime_T now; + + if (dict == NULL) + return; + list_append_dict(list, dict); + + dict_add_number(dict, "id", timer->tr_id); + dict_add_number(dict, "time", (long)timer->tr_interval); + + profile_start(&now); + remaining = proftime_time_left(&timer->tr_due, &now); + dict_add_number(dict, "remaining", (long)remaining); + + dict_add_number(dict, "repeat", + (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1)); + dict_add_number(dict, "paused", (long)(timer->tr_paused)); + + di = dictitem_alloc((char_u *)"callback"); + if (di != NULL) + { + if (dict_add(dict, di) == FAIL) + vim_free(di); + else + put_callback(&timer->tr_callback, &di->di_tv); + } +} + + static void +add_timer_info_all(typval_T *rettv) +{ + timer_T *timer; + + for (timer = first_timer; timer != NULL; timer = timer->tr_next) + if (timer->tr_id != -1) + add_timer_info(rettv, timer); +} + +/* + * Mark references in partials of timers. + */ + int +set_ref_in_timer(int copyID) +{ + int abort = FALSE; + timer_T *timer; + typval_T tv; + + for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next) + { + if (timer->tr_callback.cb_partial != NULL) + { + tv.v_type = VAR_PARTIAL; + tv.vval.v_partial = timer->tr_callback.cb_partial; + } + else + { + tv.v_type = VAR_FUNC; + tv.vval.v_string = timer->tr_callback.cb_name; + } + abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); + } + return abort; +} + +# if defined(EXITFREE) || defined(PROTO) + void +timer_free_all() +{ + timer_T *timer; + + while (first_timer != NULL) + { + timer = first_timer; + remove_timer(timer); + free_timer(timer); + } +} +# endif + +/* + * "timer_info([timer])" function + */ + void +f_timer_info(typval_T *argvars, typval_T *rettv) +{ + timer_T *timer = NULL; + + if (rettv_list_alloc(rettv) != OK) + return; + if (argvars[0].v_type != VAR_UNKNOWN) + { + if (argvars[0].v_type != VAR_NUMBER) + emsg(_(e_number_exp)); + else + { + timer = find_timer((int)tv_get_number(&argvars[0])); + if (timer != NULL) + add_timer_info(rettv, timer); + } + } + else + add_timer_info_all(rettv); +} + +/* + * "timer_pause(timer, paused)" function + */ + void +f_timer_pause(typval_T *argvars, typval_T *rettv UNUSED) +{ + timer_T *timer = NULL; + int paused = (int)tv_get_number(&argvars[1]); + + if (argvars[0].v_type != VAR_NUMBER) + emsg(_(e_number_exp)); + else + { + timer = find_timer((int)tv_get_number(&argvars[0])); + if (timer != NULL) + timer->tr_paused = paused; + } +} + +/* + * "timer_start(time, callback [, options])" function + */ + void +f_timer_start(typval_T *argvars, typval_T *rettv) +{ + long msec = (long)tv_get_number(&argvars[0]); + timer_T *timer; + int repeat = 0; + callback_T callback; + dict_T *dict; + + rettv->vval.v_number = -1; + if (check_secure()) + return; + if (argvars[2].v_type != VAR_UNKNOWN) + { + if (argvars[2].v_type != VAR_DICT + || (dict = argvars[2].vval.v_dict) == NULL) + { + semsg(_(e_invarg2), tv_get_string(&argvars[2])); + return; + } + if (dict_find(dict, (char_u *)"repeat", -1) != NULL) + repeat = dict_get_number(dict, (char_u *)"repeat"); + } + + callback = get_callback(&argvars[1]); + if (callback.cb_name == NULL) + return; + + timer = create_timer(msec, repeat); + if (timer == NULL) + free_callback(&callback); + else + { + set_callback(&timer->tr_callback, &callback); + rettv->vval.v_number = (varnumber_T)timer->tr_id; + } +} + +/* + * "timer_stop(timer)" function + */ + void +f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED) +{ + timer_T *timer; + + if (argvars[0].v_type != VAR_NUMBER) + { + emsg(_(e_number_exp)); + return; + } + timer = find_timer((int)tv_get_number(&argvars[0])); + if (timer != NULL) + stop_timer(timer); +} + +/* + * "timer_stopall()" function + */ + void +f_timer_stopall(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + stop_all_timers(); +} + +# endif // FEAT_TIMERS + +# if defined(STARTUPTIME) || defined(PROTO) +static struct timeval prev_timeval; + +# ifdef MSWIN +/* + * Windows doesn't have gettimeofday(), although it does have struct timeval. + */ + static int +gettimeofday(struct timeval *tv, char *dummy UNUSED) +{ + long t = clock(); + tv->tv_sec = t / CLOCKS_PER_SEC; + tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC; + return 0; +} +# endif + +/* + * Save the previous time before doing something that could nest. + * set "*tv_rel" to the time elapsed so far. + */ + void +time_push(void *tv_rel, void *tv_start) +{ + *((struct timeval *)tv_rel) = prev_timeval; + gettimeofday(&prev_timeval, NULL); + ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec + - ((struct timeval *)tv_rel)->tv_usec; + ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec + - ((struct timeval *)tv_rel)->tv_sec; + if (((struct timeval *)tv_rel)->tv_usec < 0) + { + ((struct timeval *)tv_rel)->tv_usec += 1000000; + --((struct timeval *)tv_rel)->tv_sec; + } + *(struct timeval *)tv_start = prev_timeval; +} + +/* + * Compute the previous time after doing something that could nest. + * Subtract "*tp" from prev_timeval; + * Note: The arguments are (void *) to avoid trouble with systems that don't + * have struct timeval. + */ + void +time_pop( + void *tp) // actually (struct timeval *) +{ + prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec; + prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec; + if (prev_timeval.tv_usec < 0) + { + prev_timeval.tv_usec += 1000000; + --prev_timeval.tv_sec; + } +} + + static void +time_diff(struct timeval *then, struct timeval *now) +{ + long usec; + long msec; + + usec = now->tv_usec - then->tv_usec; + msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L, + usec = usec % 1000L; + fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L); +} + + void +time_msg( + char *mesg, + void *tv_start) // only for do_source: start time; actually + // (struct timeval *) +{ + static struct timeval start; + struct timeval now; + + if (time_fd != NULL) + { + if (strstr(mesg, "STARTING") != NULL) + { + gettimeofday(&start, NULL); + prev_timeval = start; + fprintf(time_fd, "\n\ntimes in msec\n"); + fprintf(time_fd, " clock self+sourced self: sourced script\n"); + fprintf(time_fd, " clock elapsed: other lines\n\n"); + } + gettimeofday(&now, NULL); + time_diff(&start, &now); + if (((struct timeval *)tv_start) != NULL) + { + fprintf(time_fd, " "); + time_diff(((struct timeval *)tv_start), &now); + } + fprintf(time_fd, " "); + time_diff(&prev_timeval, &now); + prev_timeval = now; + fprintf(time_fd, ": %s\n", mesg); + } +} +# endif // STARTUPTIME +#endif // FEAT_EVAL + +#if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO) +/* + * Read 8 bytes from "fd" and turn them into a time_T, MSB first. + * Returns -1 when encountering EOF. + */ + time_T +get8ctime(FILE *fd) +{ + int c; + time_T n = 0; + int i; + + for (i = 0; i < 8; ++i) + { + c = getc(fd); + if (c == EOF) return -1; + n = (n << 8) + c; + } + return n; +} + +#ifdef _MSC_VER +# if (_MSC_VER <= 1200) +// This line is required for VC6 without the service pack. Also see the +// matching #pragma below. + # pragma optimize("", off) +# endif +#endif + +/* + * Write time_T to file "fd" in 8 bytes. + * Returns FAIL when the write failed. + */ + int +put_time(FILE *fd, time_T the_time) +{ + char_u buf[8]; + + time_to_bytes(the_time, buf); + return fwrite(buf, (size_t)8, (size_t)1, fd) == 1 ? OK : FAIL; +} + +/* + * Write time_T to "buf[8]". + */ + void +time_to_bytes(time_T the_time, char_u *buf) +{ + int c; + int i; + int bi = 0; + time_T wtime = the_time; + + // time_T can be up to 8 bytes in size, more than long_u, thus we + // can't use put_bytes() here. + // Another problem is that ">>" may do an arithmetic shift that keeps the + // sign. This happens for large values of wtime. A cast to long_u may + // truncate if time_T is 8 bytes. So only use a cast when it is 4 bytes, + // it's safe to assume that long_u is 4 bytes or more and when using 8 + // bytes the top bit won't be set. + for (i = 7; i >= 0; --i) + { + if (i + 1 > (int)sizeof(time_T)) + // ">>" doesn't work well when shifting more bits than avail + buf[bi++] = 0; + else + { +#if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4 + c = (int)(wtime >> (i * 8)); +#else + c = (int)((long_u)wtime >> (i * 8)); +#endif + buf[bi++] = c; + } + } +} + +#ifdef _MSC_VER +# if (_MSC_VER <= 1200) + # pragma optimize("", on) +# endif +#endif + +#endif + +/* + * Put timestamp "tt" in "buf[buflen]" in a nice format. + */ + void +add_time(char_u *buf, size_t buflen, time_t tt) +{ +#ifdef HAVE_STRFTIME + struct tm tmval; + struct tm *curtime; + + if (vim_time() - tt >= 100) + { + curtime = vim_localtime(&tt, &tmval); + if (vim_time() - tt < (60L * 60L * 12L)) + // within 12 hours + (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime); + else + // longer ago + (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime); + } + else +#endif + { + long seconds = (long)(vim_time() - tt); + + vim_snprintf((char *)buf, buflen, + NGETTEXT("%ld second ago", "%ld seconds ago", seconds), + seconds); + } +} diff --git a/src/version.c b/src/version.c index 49a4b08ea3..73ea73690c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 256, /**/ 255, /**/ From 00f3b4e007af07870168bf044cecc9d544483953 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 14 Feb 2020 14:32:22 +0100 Subject: [PATCH 38/55] patch 8.2.0257: cannot recognize a terminal in a popup window Problem: Cannot recognize a terminal in a popup window. Solution: Add the win_gettype() function. --- runtime/doc/eval.txt | 17 +++++++ src/evalfunc.c | 20 +------- src/evalwindow.c | 48 ++++++++++++++++++++ src/proto/evalwindow.pro | 2 + src/testdir/dumps/Test_terminal_popup_1.dump | 4 +- src/testdir/test_cmdline.vim | 2 + src/testdir/test_terminal.vim | 4 ++ src/version.c | 2 + 8 files changed, 78 insertions(+), 21 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d7c0dc3a8b..765d836375 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -10328,6 +10328,23 @@ win_getid([{win} [, {tab}]]) *win_getid()* Can also be used as a |method|: > GetWinnr()->win_getid() + +win_gettype([{nr}]) *win_gettype()* + Return the type of the window: + "popup" popup window |popup| + "command" command-line window |cmdwin| + (empty) normal window + "unknown" window {nr} not found + + When {nr} is omitted return the type of the current window. + When {nr} is given return the type of this window by number or + |window-ID|. + + Also see the 'buftype' option. When running a terminal in a + popup window then 'buftype' is "terminal" and win_gettype() + returns "popup". + + win_gotoid({expr}) *win_gotoid()* Go to window with ID {expr}. This may also change the current tabpage. diff --git a/src/evalfunc.c b/src/evalfunc.c index b4009f0aef..a0f29943ec 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -86,7 +86,6 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv); static void f_get(typval_T *argvars, typval_T *rettv); static void f_getchangelist(typval_T *argvars, typval_T *rettv); static void f_getcharsearch(typval_T *argvars, typval_T *rettv); -static void f_getcmdwintype(typval_T *argvars, typval_T *rettv); static void f_getenv(typval_T *argvars, typval_T *rettv); static void f_getfontname(typval_T *argvars, typval_T *rettv); static void f_getjumplist(typval_T *argvars, typval_T *rettv); @@ -845,6 +844,7 @@ static funcentry_T global_functions[] = {"win_execute", 2, 3, FEARG_2, &t_string, f_win_execute}, {"win_findbuf", 1, 1, FEARG_1, &t_list_number, f_win_findbuf}, {"win_getid", 0, 2, FEARG_1, &t_number, f_win_getid}, + {"win_gettype", 0, 1, FEARG_1, &t_string, f_win_gettype}, {"win_gotoid", 1, 1, FEARG_1, &t_number, f_win_gotoid}, {"win_id2tabwin", 1, 1, FEARG_1, &t_list_number, f_win_id2tabwin}, {"win_id2win", 1, 1, FEARG_1, &t_number, f_win_id2win}, @@ -2919,24 +2919,6 @@ f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv) } } -/* - * "getcmdwintype()" function - */ - static void -f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; -#ifdef FEAT_CMDWIN - rettv->vval.v_string = alloc(2); - if (rettv->vval.v_string != NULL) - { - rettv->vval.v_string[0] = cmdwin_type; - rettv->vval.v_string[1] = NUL; - } -#endif -} - /* * "getenv()" function */ diff --git a/src/evalwindow.c b/src/evalwindow.c index be6762a5c6..c7a9f7960e 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -839,6 +839,54 @@ f_win_splitmove(typval_T *argvars, typval_T *rettv) win_move_into_split(wp, targetwin, size, flags); } +/* + * "win_gettype(nr)" function + */ + void +f_win_gettype(typval_T *argvars, typval_T *rettv) +{ + win_T *wp = curwin; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + if (argvars[0].v_type != VAR_UNKNOWN) + { + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) + { + rettv->vval.v_string = vim_strsave((char_u *)"unknown"); + return; + } + } +#ifdef FEAT_PROP_POPUP + if (WIN_IS_POPUP(wp)) + rettv->vval.v_string = vim_strsave((char_u *)"popup"); + else +#endif +#ifdef FEAT_CMDWIN + if (wp == curwin && cmdwin_type != 0) + rettv->vval.v_string = vim_strsave((char_u *)"command"); +#endif +} + +/* + * "getcmdwintype()" function + */ + void +f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; +#ifdef FEAT_CMDWIN + rettv->vval.v_string = alloc(2); + if (rettv->vval.v_string != NULL) + { + rettv->vval.v_string[0] = cmdwin_type; + rettv->vval.v_string[1] = NUL; + } +#endif +} + /* * "winbufnr(nr)" function */ diff --git a/src/proto/evalwindow.pro b/src/proto/evalwindow.pro index e3faa96eb5..4eb1ced8bc 100644 --- a/src/proto/evalwindow.pro +++ b/src/proto/evalwindow.pro @@ -20,6 +20,8 @@ void f_win_id2tabwin(typval_T *argvars, typval_T *rettv); void f_win_id2win(typval_T *argvars, typval_T *rettv); void f_win_screenpos(typval_T *argvars, typval_T *rettv); void f_win_splitmove(typval_T *argvars, typval_T *rettv); +void f_win_gettype(typval_T *argvars, typval_T *rettv); +void f_getcmdwintype(typval_T *argvars, typval_T *rettv); void f_winbufnr(typval_T *argvars, typval_T *rettv); void f_wincol(typval_T *argvars, typval_T *rettv); void f_winheight(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/dumps/Test_terminal_popup_1.dump b/src/testdir/dumps/Test_terminal_popup_1.dump index 0628eb08fe..8c2a54d848 100644 --- a/src/testdir/dumps/Test_terminal_popup_1.dump +++ b/src/testdir/dumps/Test_terminal_popup_1.dump @@ -8,8 +8,8 @@ |7| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |8| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |9| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 -|1|0| @11|║+0#0000001#ffd7ff255|"+0#0000000#ffffff0|X|t|e|x|t|"| |3|L|,| |3|6|C| @11|1|,|1| @10|A|l@1| |║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 +|1|0| @11|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26|1|,|1| @10|A|l@1| |║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |1@1| @11|╚+0#0000001#ffd7ff255|═@44|⇲| +0#0000000#ffffff0@13 |1|2| @72 |1|3| @72 -@57|0|,|0|-|1| @8|A|l@1| +|t|e|r|m|i|n|a|l| |p|o|p|u|p| @42|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index a3d2d5a736..27ebfbcda1 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -894,12 +894,14 @@ func Test_cmdwin_cedit() let g:cmd_wintype = '' func CmdWinType() let g:cmd_wintype = getcmdwintype() + let g:wintype = win_gettype() return '' endfunc call feedkeys("\a\=CmdWinType()\\") echo input('') call assert_equal('@', g:cmd_wintype) + call assert_equal('command', g:wintype) set cedit&vim delfunc CmdWinType diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 8c1d3572a6..993498cddd 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2333,6 +2333,7 @@ func Test_terminal_in_popup() call writefile(text, 'Xtext') let cmd = GetVimCommandCleanTerm() let lines = [ + \ 'set t_u7=', \ 'call setline(1, range(20))', \ 'hi PopTerm ctermbg=grey', \ 'func OpenTerm(setColor)', @@ -2346,6 +2347,9 @@ func Test_terminal_in_popup() \ 'func HidePopup()', \ ' call popup_hide(s:winid)', \ 'endfunc', + \ 'sleep 10m', + \ 'redraw', + \ 'echo getwinvar(s:winid, "&buftype") win_gettype(s:winid)', \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) diff --git a/src/version.c b/src/version.c index 73ea73690c..70ea449a35 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 257, /**/ 256, /**/ From 4132eb505c506f7a0710b03a275d1c5a247e4196 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 14 Feb 2020 16:53:00 +0100 Subject: [PATCH 39/55] patch 8.2.0258: modifyOtherKeys cannot be temporarily disabled Problem: ModifyOtherKeys cannot be temporarily disabled. Solution: Add echoraw() with an example for modifyOtherKeys. --- runtime/doc/eval.txt | 16 +++++++++++++++- src/evalfunc.c | 17 +++++++++++++++++ src/testdir/dumps/Test_functions_echoraw.dump | 5 +++++ src/testdir/test_functions.vim | 17 +++++++++++++++++ src/version.c | 2 ++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/testdir/dumps/Test_functions_echoraw.dump diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 765d836375..62a73048b7 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2020 Feb 03 +*eval.txt* For Vim version 8.2. Last change: 2020 Feb 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2414,6 +2414,7 @@ deletebufline({expr}, {first} [, {last}]) did_filetype() Number |TRUE| if FileType autocmd event used diff_filler({lnum}) Number diff filler lines about {lnum} diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col} +echoraw({expr}) none output {expr} as-is empty({expr}) Number |TRUE| if {expr} is empty environ() Dict return environment variables escape({string}, {chars}) String escape {chars} in {string} with '\' @@ -2899,6 +2900,7 @@ win_id2win({expr}) Number get window nr from window ID win_screenpos({nr}) List get screen position of window {nr} win_splitmove({nr}, {target} [, {options}]) Number move window {nr} to split of {target} +win_type([{nr}]) String type of window {nr} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} @@ -3944,6 +3946,17 @@ diff_hlID({lnum}, {col}) *diff_hlID()* Can also be used as a |method|: > GetLnum()->diff_hlID(col) + +echoraw({expr}) *echoraw()* + Output {expr} as-is, including unprintable characters. This + can be used to output a terminal code. For example, to disable + modifyOtherKeys: > + call echoraw(&t_TE) +< and to enable it again: > + call echoraw(&t_TI) +< Use with care, you can mess up the terminal this way. + + empty({expr}) *empty()* Return the Number 1 if {expr} is empty, zero otherwise. - A |List| or |Dictionary| is empty when it does not have any @@ -10402,6 +10415,7 @@ win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* Can also be used as a |method|: > GetWinid()->win_splitmove(target) < + *winbufnr()* winbufnr({nr}) The result is a Number, which is the number of the buffer associated with window {nr}. {nr} can be the window number or diff --git a/src/evalfunc.c b/src/evalfunc.c index a0f29943ec..3e1a462d19 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -60,6 +60,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv); #endif static void f_deepcopy(typval_T *argvars, typval_T *rettv); static void f_did_filetype(typval_T *argvars, typval_T *rettv); +static void f_echoraw(typval_T *argvars, typval_T *rettv); static void f_empty(typval_T *argvars, typval_T *rettv); static void f_environ(typval_T *argvars, typval_T *rettv); static void f_escape(typval_T *argvars, typval_T *rettv); @@ -394,6 +395,7 @@ static funcentry_T global_functions[] = {"did_filetype", 0, 0, 0, &t_number, f_did_filetype}, {"diff_filler", 1, 1, FEARG_1, &t_number, f_diff_filler}, {"diff_hlID", 2, 2, FEARG_1, &t_number, f_diff_hlID}, + {"echoraw", 1, 1, FEARG_1, &t_number, f_echoraw}, {"empty", 1, 1, FEARG_1, &t_number, f_empty}, {"environ", 0, 0, 0, &t_dict_string, f_environ}, {"escape", 2, 2, FEARG_1, &t_string, f_escape}, @@ -1813,6 +1815,21 @@ f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED) rettv->vval.v_number = did_filetype; } +/* + * "echoraw({expr})" function + */ + static void +f_echoraw(typval_T *argvars, typval_T *rettv UNUSED) +{ + char_u *str = tv_get_string_chk(&argvars[0]); + + if (str != NULL && *str != NUL) + { + out_str(str); + out_flush(); + } +} + /* * "empty({expr})" function */ diff --git a/src/testdir/dumps/Test_functions_echoraw.dump b/src/testdir/dumps/Test_functions_echoraw.dump new file mode 100644 index 0000000000..f27cd03257 --- /dev/null +++ b/src/testdir/dumps/Test_functions_echoraw.dump @@ -0,0 +1,5 @@ +>x+0&#ffffff0|e|l@1|o| @34 +|~+0#4040ff13&| @38 +|~| @38 +|~| @38 +| +0#0000000&@21|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 9173e8547c..c748854769 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2,6 +2,7 @@ source shared.vim source check.vim source term_util.vim +source screendump.vim " Must be done first, since the alternate buffer must be unset. func Test_00_bufexists() @@ -2017,3 +2018,19 @@ func Test_range() " uniq() call assert_equal([0, 1, 2, 3, 4], uniq(range(5))) endfunc + +func Test_echoraw() + CheckScreendump + + " Normally used for escape codes, but let's test with a CR. + let lines =<< trim END + call echoraw("hello\x") + END + call writefile(lines, 'XTest_echoraw') + let buf = RunVimInTerminal('-S XTest_echoraw', {'rows': 5, 'cols': 40}) + call VerifyScreenDump(buf, 'Test_functions_echoraw', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('XTest_echoraw') +endfunc diff --git a/src/version.c b/src/version.c index 70ea449a35..2720dc6528 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 258, /**/ 257, /**/ From c2adc00fa74530e7f9d2cd31ce39252e86465dd0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 14 Feb 2020 17:05:18 +0100 Subject: [PATCH 40/55] patch 8.2.0259: terminal in popup test sometimes fails Problem: Terminal in popup test sometimes fails. Solution: Clear the command line. --- src/testdir/dumps/Test_terminal_popup_1.dump | 2 +- src/testdir/test_terminal.vim | 1 + src/version.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/testdir/dumps/Test_terminal_popup_1.dump b/src/testdir/dumps/Test_terminal_popup_1.dump index 8c2a54d848..a03d589811 100644 --- a/src/testdir/dumps/Test_terminal_popup_1.dump +++ b/src/testdir/dumps/Test_terminal_popup_1.dump @@ -8,7 +8,7 @@ |7| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |8| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |9| @12|║+0#0000001#ffd7ff255|~+0#4040ff13#ffffff0| @43|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 -|1|0| @11|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@26|1|,|1| @10|A|l@1| |║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 +|1|0| @11|║+0#0000001#ffd7ff255|:+0#0000000#ffffff0| @25|1|,|1| @10|A|l@1| |║+0#0000001#ffd7ff255| +0#0000000#ffffff0@13 |1@1| @11|╚+0#0000001#ffd7ff255|═@44|⇲| +0#0000000#ffffff0@13 |1|2| @72 |1|3| @72 diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 993498cddd..5259454c82 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2353,6 +2353,7 @@ func Test_terminal_in_popup() \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) + call term_sendkeys(buf, ":\") call VerifyScreenDump(buf, 'Test_terminal_popup_1', {}) call term_sendkeys(buf, ":q\") diff --git a/src/version.c b/src/version.c index 2720dc6528..7dacf84a38 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 259, /**/ 258, /**/ From ebdf3c964a901fc00c9009689f7cfda478342c51 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 15 Feb 2020 21:41:42 +0100 Subject: [PATCH 41/55] Update runtime files. --- runtime/doc/change.txt | 6 ++-- runtime/doc/options.txt | 3 +- runtime/doc/popup.txt | 3 +- runtime/doc/starting.txt | 12 +++++--- runtime/doc/tabpage.txt | 4 +-- runtime/doc/tags | 6 ++++ runtime/doc/testing.txt | 2 +- runtime/doc/todo.txt | 48 ++++++++++++++++++----------- runtime/doc/vim9.txt | 13 ++++---- runtime/filetype.vim | 2 +- runtime/syntax/dockerfile.vim | 14 ++++----- runtime/syntax/spec.vim | 4 +-- runtime/syntax/sshconfig.vim | 57 +++++++++++++++++++++++------------ runtime/syntax/syncolor.vim | 8 +++-- 14 files changed, 113 insertions(+), 69 deletions(-) diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 1acb267c16..9e482c82ce 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 8.2. Last change: 2019 Sep 28 +*change.txt* For Vim version 8.2. Last change: 2020 Feb 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -636,6 +636,8 @@ For other systems the tmpnam() library function is used. |cmdline-ranges|. See |:s_flags| for [flags]. + The delimiter doesn't need to be /, see + |pattern-delimiter|. :[range]s[ubstitute] [flags] [count] :[range]&[&][flags] [count] *:&* @@ -775,7 +777,7 @@ This deletes "TESTING" from all lines, but only one per line. For compatibility with Vi these two exceptions are allowed: "\/{string}/" and "\?{string}?" do the same as "//{string}/r". "\&{string}&" does the same as "//{string}/". - *E146* + *pattern-delimiter* *E146* Instead of the '/' which surrounds the pattern and replacement string, you can use any other single-byte character, but not an alphanumeric character, '\', '"' or '|'. This is useful if you want to include a '/' in the search diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 847290e29f..a48e9ea4a5 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 8.2. Last change: 2020 Jan 24 +*options.txt* For Vim version 8.2. Last change: 2020 Feb 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1380,6 +1380,7 @@ A jump table for the options with a short description can be found at |Q_op|. This option is used together with 'bufhidden' and 'swapfile' to specify special kinds of buffers. See |special-buffers|. + Also see |win_gettype()|, which returns the type of the window. Be careful with changing this option, it can have many side effects! diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index 6372e4d80d..55565bc860 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -1,4 +1,4 @@ -*popup.txt* For Vim version 8.2. Last change: 2020 Feb 03 +*popup.txt* For Vim version 8.2. Last change: 2020 Feb 05 VIM REFERENCE MANUAL by Bram Moolenaar @@ -402,6 +402,7 @@ popup_hide({id}) *popup_hide()* hidden. If window {id} does not exist nothing happens. If window {id} exists but is not a popup window an error is given. *E993* + If popup window {id} contains a terminal an error is given. Can also be used as a |method|: > GetPopup()->popup_hide() diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index d542787612..b9a2370711 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 8.2. Last change: 2020 Jan 20 +*starting.txt* For Vim version 8.2. Last change: 2020 Feb 04 VIM REFERENCE MANUAL by Bram Moolenaar @@ -58,10 +58,12 @@ filename One or more file names. The first one will be the current that is read from stdin. The commands that would normally be read from stdin will now be read from stderr. Example: > find . -name "*.c" -print | vim - -< The buffer will not be marked as modified, so that it's easy - to exit. Be careful to mark it as modified if you don't want - to accidentally lose it. Example: > - ls | view - + +< The buffer will be marked as modified, so that you are + reminded to save the text when trying to exit. If you don't + like that, put this these lines in your vimrc: > + " Don't set 'modified' when reading from stdin + au StdinReadPost * set nomodified < Starting in Ex mode: > ex - diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 2f6d8e9aad..75070b5fe7 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -1,4 +1,4 @@ -*tabpage.txt* For Vim version 8.2. Last change: 2019 May 05 +*tabpage.txt* For Vim version 8.2. Last change: 2020 Feb 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -138,7 +138,7 @@ something else. :+tabclose " close the next tab page :1tabclose " close the first tab page :$tabclose " close the last tab page - :tabclose -2 " close the two previous tab page + :tabclose -2 " close the 2nd previous tab page :tabclose + " close the next tab page :tabclose 3 " close the third tab page :tabclose $ " close the last tab page diff --git a/runtime/doc/tags b/runtime/doc/tags index ed6dbef626..ac4ff94d13 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -2341,6 +2341,8 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* :diffupdate diff.txt /*:diffupdate* :dig digraph.txt /*:dig* :digraphs digraph.txt /*:digraphs* +:disa vim9.txt /*:disa* +:disassemble vim9.txt /*:disassemble* :display change.txt /*:display* :dj tagsrch.txt /*:dj* :djump tagsrch.txt /*:djump* @@ -6108,6 +6110,7 @@ dtd2vim insert.txt /*dtd2vim* dying-variable eval.txt /*dying-variable* e motion.txt /*e* easy starting.txt /*easy* +echoraw() eval.txt /*echoraw()* echospace-variable eval.txt /*echospace-variable* edit-a-file editing.txt /*edit-a-file* edit-binary editing.txt /*edit-binary* @@ -8244,6 +8247,7 @@ patches-8.2 version8.txt /*patches-8.2* pathshorten() eval.txt /*pathshorten()* pattern pattern.txt /*pattern* pattern-atoms pattern.txt /*pattern-atoms* +pattern-delimiter change.txt /*pattern-delimiter* pattern-multi-byte pattern.txt /*pattern-multi-byte* pattern-multi-items pattern.txt /*pattern-multi-items* pattern-overview pattern.txt /*pattern-overview* @@ -9485,6 +9489,7 @@ test_refcount() testing.txt /*test_refcount()* test_scrollbar() testing.txt /*test_scrollbar()* test_setmouse() testing.txt /*test_setmouse()* test_settime() testing.txt /*test_settime()* +test_srand_seed() testing.txt /*test_srand_seed()* testing testing.txt /*testing* testing-support testing.txt /*testing-support* testing-variable eval.txt /*testing-variable* @@ -10050,6 +10055,7 @@ win32s os_win32.txt /*win32s* win_execute() eval.txt /*win_execute()* win_findbuf() eval.txt /*win_findbuf()* win_getid() eval.txt /*win_getid()* +win_gettype() eval.txt /*win_gettype()* win_gotoid() eval.txt /*win_gotoid()* win_id2tabwin() eval.txt /*win_id2tabwin()* win_id2win() eval.txt /*win_id2win()* diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index f343e86a6d..f48984c9f2 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -1,4 +1,4 @@ -*testing.txt* For Vim version 8.2. Last change: 2019 Sep 08 +*testing.txt* For Vim version 8.2. Last change: 2020 Feb 08 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index ad3ac42c0f..e371e4c59d 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2020 Feb 04 +*todo.txt* For Vim version 8.2. Last change: 2020 Feb 15 VIM REFERENCE MANUAL by Bram Moolenaar @@ -40,15 +40,15 @@ browser use: https://github.com/vim/vim/issues/1234 Include ipv6 syntax changes? (DJ Lucas, #5360) -Add win_type(), which "popup" and "cmdline" as values? +Avoid modifyOtherKeys temporarily: + call modify_other_keys(v:false) " disable modifyOtherKeys +Should fix #5617. Vim9 script: -- test s:var += 'some' - test exported += 'some' -- implement default values for optional arguments - Generate instructions at start of function, skip over if argument provided? +- "echo Func()" is an error if Func() does not return anything. - Disallow unlet for local/script/imported vars - :func inside vim9script must still use a:arg +- Make "++nr" work. - Check that import in legacy script works and puts item in s: - Error in any command in "vim9script" aborts sourcing. - Find a way to test expressions in legacy and Vim9 script without duplication @@ -58,6 +58,7 @@ Vim9 script: Test return inside try/finally jumps to finally and then returns. - call autoload function. - Type checking arguments when calling :def function +- Implement more expressions, e.g. [a:b] - can use func as reference: def SomeFunc() ... map(list, SomeFunc) @@ -164,6 +165,10 @@ Patch to move duplicated code to a function. (Yegappan Lakshmanan, #5330) Patch to use more FOR_ALL_ macros and use them. (Yegappan Lakshmanan, #5339) +Patch to explain use of "%" in :!. (#5591) + +Patch to add "-d" to xxd. (#5616) + Running test_gui and test_gui_init with Motif sometimes kills the window manager. Problem with Motif? Now test_gui crashes in submenu_change(). Athena is OK. @@ -175,6 +180,8 @@ Flag in 'formatoptions' is not used in the tests. Patch to add 'vtp' option. (#5344) Needs better docs. Is there a better name? +Patch for Haiku support. (Emir Sarı, #5605) + undo result wrong: Masato Nishihata, #4798 When 'lazyredraw' is set sometimes the title is not updated. @@ -186,11 +193,21 @@ Patch to add function to return the text used in the quickfix window. Patch for Template string: #4491. New pull: #4634 Implementation is too inefficient, avoid using lambda. +Patch to add readdirex() (Ken Takata, #5619) + +Request to support in mappings, similar to how Neovim does this. +(Daniel Hahler, #4784) + Undo puts cursor in wrong line after "cG" undo. :unmap gives error but does remove the mapping. (Antony Scriven, 2019 Dec 19) +Dos uninstal may delete vim.bat from the wrong directory (e.g., when someone +makes his own wrapper). Add a magic string with the version number to the +.bat file and check for it in the uninstaller. E.g. + # uninstall key: vim8.1* + Patch to fix session file when using multiple tab pages. (Jason Franklin, 2019 May 20) Also put :argadd commands at the start for all buffers, so that their order @@ -216,6 +233,11 @@ ex_next() should pass flag to do_argfile(), then to do_ecmd(). Adding "10" to 'spellsuggest' causes spell suggestions to become very slow. (#4087) +FR: add search_status(), the current values displayed for search (current +match, total matches). (#5631) +Patch to provide search stats in a variable, so that it can be used in the +statusline. (Fujiwara Takuya, #4446) + ":helptags ALL" should skip directories where "tags" cannot be written. (Matěj Cepl, #5026) @@ -225,8 +247,7 @@ unlisted. (#4478) Patch to include reduce() function. (#5481) -Patch to provide search stats in a variable, so that it can be used in the -statusline. (Fujiwara Takuya, #4446) +Statusline highlighting error, off by one. (#5599) Enable 'termbidi' if $VTE_VERSION >= 5703 ? @@ -1109,11 +1130,9 @@ Make a function to check for function-like type? Screen updated delayed when using CTRL-O u in Insert mode. (Barlik, #1191) Perhaps because status message? -Implement optional arguments for functions. +Implement named arguments for functions: func Foo(start, count = 1 all = 1) - call Foo(12) call Foo(12, all = 0) - call Foo(12, 15, 0) Add a command to take a range of lines, filter them and put the output somewhere else. :{range}copy {dest} !cmd @@ -2758,11 +2777,6 @@ argument list or opening each file in a separate tab. Windows installer: licence text should not use indent, causes bad word wrap. (Benjamin Fritz, 2010 Aug 16) -Dos uninstal may delete vim.bat from the wrong directory (e.g., when someone -makes his own wrapper). Add a magic string with the version number to the -.bat file and check for it in the uninstaller. E.g. - # uninstall key: vim8.1* - Changes for Win32 makefile. (Mike Williams, 2007 Jan 22, Alexei Alexandrov, 2007 Feb 8) @@ -4491,8 +4505,6 @@ Vim script language: 8 Pass the command line arguments to Vim scripts in some way. As v:args List? Or extra parameter to argv()? 8 Add command arguments with three dashes, passed on to Vim scripts. -9 Add optional arguments to user functions: - :func myFunc(arg1, arg2, arg3 = "blah", arg4 = 17) 6 User functions: Functions local to buffer "b:func()"? 8 For Strings add ":let var[{expr}] = {expr}". When past the end of "var" just ignore. diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index dd2b1b2187..da4f1634b2 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1,4 +1,4 @@ -*vim9.txt* For Vim version 8.2. Last change: 2020 Jan 30 +*vim9.txt* For Vim version 8.2. Last change: 2020 Feb 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -231,11 +231,8 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE the function follows in the next lines, until the matching `:enddef`. - When {return-type} is omitted the return type will be - decided upon by the first encountered `return` - statement in the function. E.g., for: > - return 'message' -< The return type will be "string". + When {return-type} is omitted the function is not + expected to return anything. {arguments} is a sequence of zero or more argument declarations. There are three forms: @@ -257,6 +254,10 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE :enddef End of a function defined with `:def`. + *:disa* *:disassemble* +:disa[ssemble] {func} Show the instructions generated for {func}. + This is for debugging and testing. + ============================================================================== 4. Types *vim9-types* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index e2e48c9976..ddf5fd9c89 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2020 Jan 22 +" Last Change: 2020 Jan 31 " Listen very carefully, I will say this only once if exists("did_load_filetypes") diff --git a/runtime/syntax/dockerfile.vim b/runtime/syntax/dockerfile.vim index da3a3fc9d2..ce52e697cd 100644 --- a/runtime/syntax/dockerfile.vim +++ b/runtime/syntax/dockerfile.vim @@ -1,6 +1,6 @@ " dockerfile.vim - Syntax highlighting for Dockerfiles " Maintainer: Honza Pokorny -" Last Change: 2020 Jan 27 +" Last Change: 2020 Feb 11 " License: BSD " https://docs.docker.com/engine/reference/builder/ @@ -22,12 +22,12 @@ syntax region dockerfileFrom matchgroup=dockerfileKeyword start=/\v^\s*(FROM)\ze syntax keyword dockerfileKeyword contained ADD ARG CMD COPY ENTRYPOINT ENV EXPOSE HEALTHCHECK LABEL MAINTAINER ONBUILD RUN SHELL STOPSIGNAL USER VOLUME WORKDIR syntax match dockerfileOption contained /\v(^|\s)\zs--\S+/ -syntax match dockerfileInstruction contained /\v(\S+)(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileValue -syntax match dockerfileInstruction contained /\v(ADD|COPY)(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileJSON -syntax match dockerfileInstruction contained /\v(HEALTHCHECK)(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileInstruction -syntax match dockerfileInstruction contained /\v(CMD|ENTRYPOINT|RUN)/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileShell -syntax match dockerfileInstruction contained /\v(CMD|ENTRYPOINT|RUN)\ze\s+\[/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileJSON -syntax match dockerfileInstruction contained /\v(SHELL|VOLUME)/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileJSON +syntax match dockerfileInstruction contained /\v<(\S+)>(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileValue +syntax match dockerfileInstruction contained /\v<(ADD|COPY)>(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileJSON +syntax match dockerfileInstruction contained /\v<(HEALTHCHECK)>(\s+--\S+)*/ contains=dockerfileKeyword,dockerfileOption skipwhite nextgroup=dockerfileInstruction +syntax match dockerfileInstruction contained /\v<(CMD|ENTRYPOINT|RUN)>/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileShell +syntax match dockerfileInstruction contained /\v<(CMD|ENTRYPOINT|RUN)>\ze\s+\[/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileJSON +syntax match dockerfileInstruction contained /\v<(SHELL|VOLUME)>/ contains=dockerfileKeyword skipwhite nextgroup=dockerfileJSON syntax region dockerfileString contained start=/\v"/ skip=/\v\\./ end=/\v"/ syntax region dockerfileJSON contained keepend start=/\v\[/ skip=/\v\\\_./ end=/\v$/ contains=@JSON diff --git a/runtime/syntax/spec.vim b/runtime/syntax/spec.vim index f56a993ae5..4df549e677 100644 --- a/runtime/syntax/spec.vim +++ b/runtime/syntax/spec.vim @@ -3,7 +3,7 @@ " Language: SPEC: Build/install scripts for Linux RPM packages " Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com " Former Maintainer: Donovan Rebbechi elflord@panix.com (until March 2014) -" Last Change: 2019 Sep 27 +" Last Change: 2020 Feb 07 " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -111,7 +111,7 @@ syn region specDescriptionArea matchgroup=specSection start='^%description' end= syn region specPackageArea matchgroup=specSection start='^%package' end='^%'me=e-1 contains=specPackageOpts,specPreAmble,specComment "%% Scripts Section %% -syn region specScriptArea matchgroup=specSection start='^%\(prep\|build\|install\|clean\|pre\|postun\|preun\|post\|posttrans\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2 +syn region specScriptArea matchgroup=specSection start='^%\(prep\|build\|install\|clean\|check\|pre\|postun\|preun\|post\|posttrans\)\>' skip='^%{\|^%\(define\|patch\d*\|configure\|GNUconfigure\|setup\|autosetup\|autopatch\|find_lang\|make_build\|makeinstall\|make_install\)\>' end='^%'me=e-1 contains=specSpecialVariables,specVariables,@specCommands,specVariables,shDo,shFor,shCaseEsac,specNoNumberHilite,specCommandOpts,shComment,shIf,specSpecialChar,specMacroIdentifier,specSectionMacroArea,specSectionMacroBracketArea,shOperator,shQuote1,shQuote2 "%% Changelog Section %% syn region specChangelogArea matchgroup=specSection start='^%changelog' end='^%'me=e-1 contains=specEmail,specURL,specWeekday,specMonth,specNumber,specComment,specLicense diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim index 6c36f56af8..d0752aebcb 100644 --- a/runtime/syntax/sshconfig.vim +++ b/runtime/syntax/sshconfig.vim @@ -5,8 +5,9 @@ " Contributor: Leonard Ehrenfried " Contributor: Karsten Hopp " Contributor: Dean, Adam Kenneth -" Last Change: 2019 Sep 09 +" Last Change: 2020 Feb 12 " Added RemoteCommand from pull request #4809 +" Included additional keywords from Martin. " SSH Version: 7.4p1 " @@ -131,24 +132,25 @@ syn case ignore " Keywords syn keyword sshconfigHostSect Host -syn keyword sshconfigMatch canonical exec host originalhost user localuser all +syn keyword sshconfigMatch canonical final exec host originalhost user localuser all syn keyword sshconfigKeyword AddressFamily syn keyword sshconfigKeyword AddKeysToAgent syn keyword sshconfigKeyword BatchMode syn keyword sshconfigKeyword BindAddress +syn keyword sshconfigKeyword BindInterface syn keyword sshconfigKeyword CanonicalDomains syn keyword sshconfigKeyword CanonicalizeFallbackLocal syn keyword sshconfigKeyword CanonicalizeHostname syn keyword sshconfigKeyword CanonicalizeMaxDots +syn keyword sshconfigKeyword CanonicalizePermittedCNAMEs +syn keyword sshconfigKeyword CASignatureAlgorithms syn keyword sshconfigKeyword CertificateFile syn keyword sshconfigKeyword ChallengeResponseAuthentication syn keyword sshconfigKeyword CheckHostIP -syn keyword sshconfigKeyword Cipher syn keyword sshconfigKeyword Ciphers syn keyword sshconfigKeyword ClearAllForwardings syn keyword sshconfigKeyword Compression -syn keyword sshconfigKeyword CompressionLevel syn keyword sshconfigKeyword ConnectTimeout syn keyword sshconfigKeyword ConnectionAttempts syn keyword sshconfigKeyword ControlMaster @@ -158,18 +160,13 @@ syn keyword sshconfigKeyword DynamicForward syn keyword sshconfigKeyword EnableSSHKeysign syn keyword sshconfigKeyword EscapeChar syn keyword sshconfigKeyword ExitOnForwardFailure +syn keyword sshconfigKeyword FingerprintHash syn keyword sshconfigKeyword ForwardAgent syn keyword sshconfigKeyword ForwardX11 syn keyword sshconfigKeyword ForwardX11Timeout syn keyword sshconfigKeyword ForwardX11Trusted syn keyword sshconfigKeyword GSSAPIAuthentication -syn keyword sshconfigKeyword GSSAPIClientIdentity syn keyword sshconfigKeyword GSSAPIDelegateCredentials -syn keyword sshconfigKeyword GSSAPIKeyExchange -syn keyword sshconfigKeyword GSSAPIRenewalForcesRekey -syn keyword sshconfigKeyword GSSAPIServerIdentity -syn keyword sshconfigKeyword GSSAPITrustDNS -syn keyword sshconfigKeyword GSSAPITrustDns syn keyword sshconfigKeyword GatewayPorts syn keyword sshconfigKeyword GlobalKnownHostsFile syn keyword sshconfigKeyword HashKnownHosts @@ -180,6 +177,7 @@ syn keyword sshconfigKeyword HostbasedAuthentication syn keyword sshconfigKeyword HostbasedKeyTypes syn keyword sshconfigKeyword IPQoS syn keyword sshconfigKeyword IdentitiesOnly +syn keyword sshconfigKeyword IdentityAgent syn keyword sshconfigKeyword IdentityFile syn keyword sshconfigKeyword IgnoreUnknown syn keyword sshconfigKeyword Include @@ -199,35 +197,53 @@ syn keyword sshconfigKeyword PasswordAuthentication syn keyword sshconfigKeyword PermitLocalCommand syn keyword sshconfigKeyword Port syn keyword sshconfigKeyword PreferredAuthentications -syn keyword sshconfigKeyword Protocol syn keyword sshconfigKeyword ProxyCommand syn keyword sshconfigKeyword ProxyJump syn keyword sshconfigKeyword ProxyUseFDPass syn keyword sshconfigKeyword PubkeyAcceptedKeyTypes syn keyword sshconfigKeyword PubkeyAuthentication -syn keyword sshconfigKeyword RSAAuthentication syn keyword sshconfigKeyword RekeyLimit syn keyword sshconfigKeyword RemoteCommand syn keyword sshconfigKeyword RemoteForward syn keyword sshconfigKeyword RequestTTY -syn keyword sshconfigKeyword RhostsRSAAuthentication +syn keyword sshconfigKeyword RevokedHostKeys +syn keyword sshconfigKeyword SecurityKeyProvider syn keyword sshconfigKeyword SendEnv syn keyword sshconfigKeyword ServerAliveCountMax syn keyword sshconfigKeyword ServerAliveInterval syn keyword sshconfigKeyword SmartcardDevice +syn keyword sshconfigKeyword SetEnv +syn keyword sshconfigKeyword StreamLocalBindMask +syn keyword sshconfigKeyword StreamLocalBindUnlink syn keyword sshconfigKeyword StrictHostKeyChecking +syn keyword sshconfigKeyword SyslogFacility syn keyword sshconfigKeyword TCPKeepAlive syn keyword sshconfigKeyword Tunnel syn keyword sshconfigKeyword TunnelDevice syn keyword sshconfigKeyword UseBlacklistedKeys -syn keyword sshconfigKeyword UsePrivilegedPort +syn keyword sshconfigKeyword UpdateHostKeys syn keyword sshconfigKeyword User syn keyword sshconfigKeyword UserKnownHostsFile -syn keyword sshconfigKeyword UseRoaming syn keyword sshconfigKeyword VerifyHostKeyDNS syn keyword sshconfigKeyword VisualHostKey syn keyword sshconfigKeyword XAuthLocation +" Deprecated/ignored/remove/unsupported keywords + +syn keyword sshConfigDeprecated Cipher +syn keyword sshconfigDeprecated GSSAPIClientIdentity +syn keyword sshconfigDeprecated GSSAPIKeyExchange +syn keyword sshconfigDeprecated GSSAPIRenewalForcesRekey +syn keyword sshconfigDeprecated GSSAPIServerIdentity +syn keyword sshconfigDeprecated GSSAPITrustDNS +syn keyword sshconfigDeprecated GSSAPITrustDns +syn keyword sshconfigDeprecated Protocol +syn keyword sshconfigDeprecated RSAAuthentication +syn keyword sshconfigDeprecated RhostsRSAAuthentication +syn keyword sshconfigDeprecated CompressionLevel +syn keyword sshconfigDeprecated UseRoaming +syn keyword sshconfigDeprecated UsePrivilegedPort + " Define the default highlighting hi def link sshconfigComment Comment @@ -236,17 +252,17 @@ hi def link sshconfigHostPort sshconfigConstant hi def link sshconfigNumber sshconfigConstant hi def link sshconfigConstant Constant hi def link sshconfigYesNo sshconfigEnum -hi def link sshconfigCipher sshconfigEnum -hi def link sshconfigCiphers sshconfigEnum +hi def link sshconfigCipher sshconfigDeprecated +hi def link sshconfigCiphers sshconfigEnum hi def link sshconfigMAC sshconfigEnum hi def link sshconfigHostKeyAlgo sshconfigEnum hi def link sshconfigLogLevel sshconfigEnum hi def link sshconfigSysLogFacility sshconfigEnum hi def link sshconfigAddressFamily sshconfigEnum -hi def link sshconfigIPQoS sshconfigEnum +hi def link sshconfigIPQoS sshconfigEnum hi def link sshconfigKbdInteractive sshconfigEnum -hi def link sshconfigKexAlgo sshconfigEnum -hi def link sshconfigTunnel sshconfigEnum +hi def link sshconfigKexAlgo sshconfigEnum +hi def link sshconfigTunnel sshconfigEnum hi def link sshconfigPreferredAuth sshconfigEnum hi def link sshconfigVar sshconfigEnum hi def link sshconfigEnum Identifier @@ -254,6 +270,7 @@ hi def link sshconfigSpecial Special hi def link sshconfigKeyword Keyword hi def link sshconfigHostSect Type hi def link sshconfigMatch Type +hi def link sshconfigDeprecated Error let b:current_syntax = "sshconfig" diff --git a/runtime/syntax/syncolor.vim b/runtime/syntax/syncolor.vim index 8d0064db15..5b907a3b83 100644 --- a/runtime/syntax/syncolor.vim +++ b/runtime/syntax/syncolor.vim @@ -1,6 +1,6 @@ " Vim syntax support file " Maintainer: Bram Moolenaar -" Last Change: 2001 Sep 12 +" Last Change: 2020 Feb 13 " This file sets up the default methods for highlighting. " It is loaded from "synload.vim" and from Vim for ":syntax reset". @@ -43,10 +43,12 @@ if &background == "dark" else SynColor Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=Blue guibg=NONE SynColor Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE - SynColor Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=SlateBlue guibg=NONE + " #6a5acd is SlateBlue + SynColor Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a5acd guibg=NONE SynColor Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE SynColor Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE - SynColor PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=Purple guibg=NONE + " #6a0dad is Purple + SynColor PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a0dad guibg=NONE SynColor Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=bold guifg=SeaGreen guibg=NONE SynColor Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=SlateBlue SynColor Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=bg guibg=NONE From f4140488c72cad4dbf5449dba099cfa7de7bbb22 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 15 Feb 2020 23:06:45 +0100 Subject: [PATCH 42/55] patch 8.2.0260: several lines of code are duplicated Problem: Several lines of code are duplicated. Solution: Move duplicated code to a function. (Yegappan Lakshmanan, closes #5330) --- src/option.c | 136 ++++++++++++++++++++------------------------- src/os_unix.c | 24 +------- src/os_win32.c | 25 +-------- src/proto/term.pro | 1 + src/quickfix.c | 24 +++----- src/regexp.c | 22 ++++++++ src/regexp_bt.c | 12 +--- src/regexp_nfa.c | 12 +--- src/term.c | 31 +++++++++++ src/version.c | 2 + 10 files changed, 128 insertions(+), 161 deletions(-) diff --git a/src/option.c b/src/option.c index f02dd26a96..39ea7cbb4d 100644 --- a/src/option.c +++ b/src/option.c @@ -2498,6 +2498,61 @@ set_term_option_sctx_idx(char *name, int opt_idx) } #endif +#if defined(FEAT_EVAL) +/* + * Apply the OptionSet autocommand. + */ + static void +apply_optionset_autocmd( + int opt_idx, + long opt_flags, + long oldval, + long oldval_g, + long newval, + char *errmsg) +{ + char_u buf_old[12], buf_old_global[12], buf_new[12], buf_type[12]; + + // Don't do this while starting up, failure or recursively. + if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL) + return; + + vim_snprintf((char *)buf_old, sizeof(buf_old), "%ld", oldval); + vim_snprintf((char *)buf_old_global, sizeof(buf_old_global), "%ld", + oldval_g); + vim_snprintf((char *)buf_new, sizeof(buf_new), "%ld", newval); + vim_snprintf((char *)buf_type, sizeof(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_NEW, buf_new, -1); + set_vim_var_string(VV_OPTION_OLD, buf_old, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + if (opt_flags & OPT_LOCAL) + { + set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1); + set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); + } + if (opt_flags & OPT_GLOBAL) + { + set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1); + set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1); + } + if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) + { + set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1); + set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); + set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1); + } + if (opt_flags & OPT_MODELINE) + { + set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1); + set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); + } + apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, + NULL, FALSE, NULL); + reset_v_option_vars(); +} +#endif + /* * Set the value of a boolean option, and take care of side effects. * Returns NULL for success, or an error message for an error. @@ -3071,45 +3126,10 @@ set_bool_option( options[opt_idx].flags |= P_WAS_SET; #if defined(FEAT_EVAL) - // Don't do this while starting up or recursively. - if (!starting && *get_vim_var_str(VV_OPTION_TYPE) == NUL) - { - char_u buf_old[2], buf_old_global[2], buf_new[2], buf_type[7]; - - vim_snprintf((char *)buf_old, 2, "%d", old_value ? TRUE: FALSE); - vim_snprintf((char *)buf_old_global, 2, "%d", - old_global_value ? TRUE: FALSE); - vim_snprintf((char *)buf_new, 2, "%d", value ? TRUE: FALSE); - vim_snprintf((char *)buf_type, 7, "%s", - (opt_flags & OPT_LOCAL) ? "local" : "global"); - set_vim_var_string(VV_OPTION_NEW, buf_new, -1); - set_vim_var_string(VV_OPTION_OLD, buf_old, -1); - set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); - if (opt_flags & OPT_LOCAL) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - } - if (opt_flags & OPT_GLOBAL) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1); - } - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1); - } - if (opt_flags & OPT_MODELINE) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - } - apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, - NULL, FALSE, NULL); - reset_v_option_vars(); - } + apply_optionset_autocmd(opt_idx, opt_flags, + (long)(old_value ? TRUE : FALSE), + (long)(old_global_value ? TRUE : FALSE), + (long)(value ? TRUE : FALSE), NULL); #endif comp_col(); // in case 'ruler' or 'showcmd' changed @@ -3666,42 +3686,8 @@ set_num_option( options[opt_idx].flags |= P_WAS_SET; #if defined(FEAT_EVAL) - // Don't do this while starting up, failure or recursively. - if (!starting && errmsg == NULL && *get_vim_var_str(VV_OPTION_TYPE) == NUL) - { - char_u buf_old[11], buf_old_global[11], buf_new[11], buf_type[7]; - vim_snprintf((char *)buf_old, 10, "%ld", old_value); - vim_snprintf((char *)buf_old_global, 10, "%ld", old_global_value); - vim_snprintf((char *)buf_new, 10, "%ld", value); - vim_snprintf((char *)buf_type, 7, "%s", (opt_flags & OPT_LOCAL) ? "local" : "global"); - set_vim_var_string(VV_OPTION_NEW, buf_new, -1); - set_vim_var_string(VV_OPTION_OLD, buf_old, -1); - set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); - if (opt_flags & OPT_LOCAL) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - } - if (opt_flags & OPT_GLOBAL) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1); - } - if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1); - } - if (opt_flags & OPT_MODELINE) - { - set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1); - set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1); - } - apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname, - NULL, FALSE, NULL); - reset_v_option_vars(); - } + apply_optionset_autocmd(opt_idx, opt_flags, old_value, old_global_value, + value, errmsg); #endif comp_col(); // in case 'columns' or 'ls' changed diff --git a/src/os_unix.c b/src/os_unix.c index 15d88f9e15..654480d9ed 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4980,29 +4980,7 @@ mch_call_shell_fork( } } - // replace K_BS by and K_DEL by - for (i = ta_len; i < ta_len + len; ++i) - { - if (ta_buf[i] == CSI && len - i > 2) - { - c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); - if (c == K_DEL || c == K_KDEL || c == K_BS) - { - mch_memmove(ta_buf + i + 1, ta_buf + i + 3, - (size_t)(len - i - 2)); - if (c == K_DEL || c == K_KDEL) - ta_buf[i] = DEL; - else - ta_buf[i] = Ctrl_H; - len -= 2; - } - } - else if (ta_buf[i] == '\r') - ta_buf[i] = '\n'; - if (has_mbyte) - i += (*mb_ptr2len_len)(ta_buf + i, - ta_len + len - i) - 1; - } + term_replace_bs_del_keycode(ta_buf, ta_len, len); /* * For pipes: echo the typed characters. diff --git a/src/os_win32.c b/src/os_win32.c index f394979d60..df63fb7f3e 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -4173,7 +4173,6 @@ mch_system_piped(char *cmd, int options) int ta_len = 0; // valid bytes in ta_buf[] DWORD i; - int c; int noread_cnt = 0; garray_T ga; int delay = 1; @@ -4312,29 +4311,7 @@ mch_system_piped(char *cmd, int options) } } - // replace K_BS by and K_DEL by - for (i = ta_len; i < ta_len + len; ++i) - { - if (ta_buf[i] == CSI && len - i > 2) - { - c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); - if (c == K_DEL || c == K_KDEL || c == K_BS) - { - mch_memmove(ta_buf + i + 1, ta_buf + i + 3, - (size_t)(len - i - 2)); - if (c == K_DEL || c == K_KDEL) - ta_buf[i] = DEL; - else - ta_buf[i] = Ctrl_H; - len -= 2; - } - } - else if (ta_buf[i] == '\r') - ta_buf[i] = '\n'; - if (has_mbyte) - i += (*mb_ptr2len_len)(ta_buf + i, - ta_len + len - i) - 1; - } + term_replace_bs_del_keycode(ta_buf, ta_len, len); /* * For pipes: echo the typed characters. For a pty this diff --git a/src/proto/term.pro b/src/proto/term.pro index 4b9ee9ca24..2091cbfee8 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -77,4 +77,5 @@ void swap_tcap(void); guicolor_T gui_get_color_cmn(char_u *name); guicolor_T gui_get_rgb_color_cmn(int r, int g, int b); void cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx); +void term_replace_bs_del_keycode(char_u *ta_buf, int ta_len, int len); /* vim: set ft=c : */ diff --git a/src/quickfix.c b/src/quickfix.c index 00457e256d..f1df111212 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -980,11 +980,11 @@ qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields) } /* - * Parse the match for '%+' format pattern. The whole matching line is included - * in the error string. Return the matched line in "fields->errmsg". + * Copy a non-error line into the error string. Return the matched line in + * "fields->errmsg". */ static int -qf_parse_fmt_plus(char_u *linebuf, int linelen, qffields_T *fields) +copy_nonerror_line(char_u *linebuf, int linelen, qffields_T *fields) { char_u *p; @@ -996,7 +996,9 @@ qf_parse_fmt_plus(char_u *linebuf, int linelen, qffields_T *fields) fields->errmsg = p; fields->errmsglen = linelen + 1; } + // copy whole line to error message vim_strncpy(fields->errmsg, linebuf, linelen); + return QF_OK; } @@ -1180,7 +1182,7 @@ qf_parse_match( else if (i == 5) { if (fmt_ptr->flags == '+' && !qf_multiscan) // %+ - status = qf_parse_fmt_plus(linebuf, linelen, fields); + status = copy_nonerror_line(linebuf, linelen, fields); else if (midx > 0) // %m status = qf_parse_fmt_m(regmatch, midx, fields); } @@ -1307,23 +1309,11 @@ qf_parse_file_pfx( static int qf_parse_line_nomatch(char_u *linebuf, int linelen, qffields_T *fields) { - char_u *p; - fields->namebuf[0] = NUL; // no match found, remove file name fields->lnum = 0; // don't jump to this line fields->valid = FALSE; - if (linelen >= fields->errmsglen) - { - // linelen + null terminator - if ((p = vim_realloc(fields->errmsg, linelen + 1)) == NULL) - return QF_NOMEM; - fields->errmsg = p; - fields->errmsglen = linelen + 1; - } - // copy whole line to error message - vim_strncpy(fields->errmsg, linebuf, linelen); - return QF_OK; + return copy_nonerror_line(linebuf, linelen, fields); } /* diff --git a/src/regexp.c b/src/regexp.c index ef3896c0a4..4e21d44ccf 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -2511,6 +2511,28 @@ reg_submatch_list(int no) } #endif +/* + * Initialize the values used for matching against multiple lines + */ + static void +init_regexec_multi( + regmmatch_T *rmp, + win_T *win, // window in which to search or NULL + buf_T *buf, // buffer in which to search + linenr_T lnum) // nr of line to start looking for match +{ + rex.reg_match = NULL; + rex.reg_mmatch = rmp; + rex.reg_buf = buf; + rex.reg_win = win; + rex.reg_firstlnum = lnum; + rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; + rex.reg_line_lbr = FALSE; + rex.reg_ic = rmp->rmm_ic; + rex.reg_icombine = FALSE; + rex.reg_maxcol = rmp->rmm_maxcol; +} + #include "regexp_bt.c" static regengine_T bt_regengine = diff --git a/src/regexp_bt.c b/src/regexp_bt.c index 78be2b5f8d..0ed3711363 100644 --- a/src/regexp_bt.c +++ b/src/regexp_bt.c @@ -4854,17 +4854,7 @@ bt_regexec_multi( proftime_T *tm, // timeout limit or NULL int *timed_out) // flag set on timeout or NULL { - rex.reg_match = NULL; - rex.reg_mmatch = rmp; - rex.reg_buf = buf; - rex.reg_win = win; - rex.reg_firstlnum = lnum; - rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; - rex.reg_line_lbr = FALSE; - rex.reg_ic = rmp->rmm_ic; - rex.reg_icombine = FALSE; - rex.reg_maxcol = rmp->rmm_maxcol; - + init_regexec_multi(rmp, win, buf, lnum); return bt_regexec_both(NULL, col, tm, timed_out); } diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c index a288ea47c8..67d4af2f61 100644 --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -7409,17 +7409,7 @@ nfa_regexec_multi( proftime_T *tm, // timeout limit or NULL int *timed_out) // flag set on timeout or NULL { - rex.reg_match = NULL; - rex.reg_mmatch = rmp; - rex.reg_buf = buf; - rex.reg_win = win; - rex.reg_firstlnum = lnum; - rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; - rex.reg_line_lbr = FALSE; - rex.reg_ic = rmp->rmm_ic; - rex.reg_icombine = FALSE; - rex.reg_maxcol = rmp->rmm_maxcol; - + init_regexec_multi(rmp, win, buf, lnum); return nfa_regexec_both(NULL, col, tm, timed_out); } diff --git a/src/term.c b/src/term.c index b942b0f4b9..d269eb83c0 100644 --- a/src/term.c +++ b/src/term.c @@ -6390,3 +6390,34 @@ cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx) } #endif +/* + * Replace K_BS by and K_DEL by + */ + void +term_replace_bs_del_keycode(char_u *ta_buf, int ta_len, int len) +{ + int i; + int c; + + for (i = ta_len; i < ta_len + len; ++i) + { + if (ta_buf[i] == CSI && len - i > 2) + { + c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); + if (c == K_DEL || c == K_KDEL || c == K_BS) + { + mch_memmove(ta_buf + i + 1, ta_buf + i + 3, + (size_t)(len - i - 2)); + if (c == K_DEL || c == K_KDEL) + ta_buf[i] = DEL; + else + ta_buf[i] = Ctrl_H; + len -= 2; + } + } + else if (ta_buf[i] == '\r') + ta_buf[i] = '\n'; + if (has_mbyte) + i += (*mb_ptr2len_len)(ta_buf + i, ta_len + len - i) - 1; + } +} diff --git a/src/version.c b/src/version.c index 7dacf84a38..a77a7c8cae 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 260, /**/ 259, /**/ From f0cee1971f5258ce61f8a4e6a04d35c1e625bb01 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 13:33:56 +0100 Subject: [PATCH 43/55] patch 8.2.0261: some code not covered by tests Problem: Some code not covered by tests. Solution: Add test cases. (Yegappan Lakshmanan, closes #5645) --- src/testdir/test_buffer.vim | 91 ++++++++++++++++++++++++++++++ src/testdir/test_cmdline.vim | 43 ++++++++++++++ src/testdir/test_exists.vim | 4 ++ src/testdir/test_filechanged.vim | 15 +++++ src/testdir/test_fileformat.vim | 20 +++++++ src/testdir/test_mapping.vim | 1 + src/testdir/test_marks.vim | 9 +++ src/testdir/test_normal.vim | 16 ++++++ src/testdir/test_plus_arg_edit.vim | 13 +++++ src/testdir/test_quickfix.vim | 9 +++ src/version.c | 2 + 11 files changed, 223 insertions(+) diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim index dc35bb4b83..f2feca9fab 100644 --- a/src/testdir/test_buffer.vim +++ b/src/testdir/test_buffer.vim @@ -61,6 +61,97 @@ func Test_bunload_with_offset() call delete('b2') call delete('b3') call delete('b4') + + call assert_fails('1,4bunload', 'E16:') + call assert_fails(',100bunload', 'E16:') + + " Use a try-catch for this test. When assert_fails() is used for this + " test, the command fails with E515: instead of E90: + let caught_E90 = 0 + try + $bunload + catch /E90:/ + let caught_E90 = 1 + endtry + call assert_equal(1, caught_E90) + call assert_fails('$bunload', 'E515:') +endfunc + +" Test for :buffer, :bnext, :bprevious, :brewind, :blast and :bmodified +" commands +func Test_buflist_browse() + %bwipe! + call assert_fails('buffer 1000', 'E86:') + + call writefile(['foo1', 'foo2', 'foo3', 'foo4'], 'Xfile1') + call writefile(['bar1', 'bar2', 'bar3', 'bar4'], 'Xfile2') + call writefile(['baz1', 'baz2', 'baz3', 'baz4'], 'Xfile3') + edit Xfile1 + let b1 = bufnr() + edit Xfile2 + let b2 = bufnr() + edit +/baz4 Xfile3 + let b3 = bufnr() + + call assert_fails('buffer ' .. b1 .. ' abc', 'E488:') + call assert_equal(b3, bufnr()) + call assert_equal(4, line('.')) + exe 'buffer +/bar2 ' .. b2 + call assert_equal(b2, bufnr()) + call assert_equal(2, line('.')) + exe 'buffer +/bar1' + call assert_equal(b2, bufnr()) + call assert_equal(1, line('.')) + + brewind +/foo3 + call assert_equal(b1, bufnr()) + call assert_equal(3, line('.')) + + blast +/baz2 + call assert_equal(b3, bufnr()) + call assert_equal(2, line('.')) + + bprevious +/bar4 + call assert_equal(b2, bufnr()) + call assert_equal(4, line('.')) + + bnext +/baz3 + call assert_equal(b3, bufnr()) + call assert_equal(3, line('.')) + + call assert_fails('bmodified', 'E84:') + call setbufvar(b2, '&modified', 1) + exe 'bmodified +/bar3' + call assert_equal(b2, bufnr()) + call assert_equal(3, line('.')) + + " With no listed buffers in the list, :bnext and :bprev should fail + %bwipe! + set nobuflisted + call assert_fails('bnext', 'E85:') + call assert_fails('bprev', 'E85:') + set buflisted + + call assert_fails('sandbox bnext', 'E48:') + + call delete('Xfile1') + call delete('Xfile2') + call delete('Xfile3') + %bwipe! +endfunc + +" Test for :bdelete +func Test_bdelete_cmd() + %bwipe! + call assert_fails('bdelete 5', 'E516:') + + " Deleting a unlisted and unloaded buffer + edit Xfile1 + let bnr = bufnr() + set nobuflisted + enew + call assert_fails('bdelete ' .. bnr, 'E516:') + %bwipe! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 27ebfbcda1..ff15cbbe3b 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -632,9 +632,32 @@ func Test_cmdline_search_range() 1,\&s/b/B/ call assert_equal('B', getline(2)) + let @/ = 'apple' + call assert_fails('\/print', 'E486:') + bwipe! endfunc +" Test for the tick mark (') in an excmd range +func Test_tick_mark_in_range() + " If only the tick is passed as a range and no command is specified, there + " should not be an error + call feedkeys(":'\", 'xt') + call assert_equal("'", getreg(':')) + call assert_fails("',print", 'E78:') +endfunc + +" Test for using a line number followed by a search pattern as range +func Test_lnum_and_pattern_as_range() + new + call setline(1, ['foo 1', 'foo 2', 'foo 3']) + let @" = '' + 2/foo/yank + call assert_equal("foo 3\n", @") + call assert_equal(1, line('.')) + close! +endfunc + " Tests for getcmdline(), getcmdpos() and getcmdtype() func Check_cmdline(cmdtype) call assert_equal('MyCmd a', getcmdline()) @@ -934,4 +957,24 @@ func Test_cmdline_expand_special() call assert_fails('e ', 'E497:') endfunc +func Test_cmdwin_jump_to_win() + call assert_fails('call feedkeys("q:\\\", "xt")', 'E11:') + new + set modified + call assert_fails('call feedkeys("q/:qall\", "xt")', 'E162:') + close! + call feedkeys("q/:close\", "xt") + call assert_equal(1, winnr('$')) + call feedkeys("q/:exit\", "xt") + call assert_equal(1, winnr('$')) +endfunc + +" Test for backtick expression in the command line +func Test_cmd_backtick() + %argd + argadd `=['a', 'b', 'c']` + call assert_equal(['a', 'b', 'c'], argv()) + %argd +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_exists.vim b/src/testdir/test_exists.vim index fd34be83b0..471c77853d 100644 --- a/src/testdir/test_exists.vim +++ b/src/testdir/test_exists.vim @@ -94,8 +94,12 @@ func Test_exists() call assert_equal(0, exists(':edit/a')) " Valid internal command (partial match) call assert_equal(1, exists(':q')) + " Valid internal command with a digit + call assert_equal(2, exists(':2match')) " Non-existing internal command call assert_equal(0, exists(':invalidcmd')) + " Internal command with a count + call assert_equal(0, exists(':3buffer')) " User defined command (full match) command! MyCmd :echo 'My command' diff --git a/src/testdir/test_filechanged.vim b/src/testdir/test_filechanged.vim index 6d17d9586d..6192b9e66d 100644 --- a/src/testdir/test_filechanged.vim +++ b/src/testdir/test_filechanged.vim @@ -146,3 +146,18 @@ func Test_file_changed_dialog() bwipe! call delete('Xchanged_d') endfunc + +" Test for editing a new buffer from a FileChangedShell autocmd +func Test_FileChangedShell_newbuf() + call writefile(['one', 'two'], 'Xfile') + new Xfile + augroup testnewbuf + autocmd FileChangedShell * enew + augroup END + call writefile(['red'], 'Xfile') + call assert_fails('checktime', 'E811:') + au! testnewbuf + call delete('Xfile') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_fileformat.vim b/src/testdir/test_fileformat.vim index 394c274753..efc5a0dd17 100644 --- a/src/testdir/test_fileformat.vim +++ b/src/testdir/test_fileformat.vim @@ -276,3 +276,23 @@ func Test_fileformats() call delete('XXUxDsMc') call delete('Xtest') endfunc + +" Test for changing the fileformat using ++read +func Test_fileformat_plusplus_read() + new + call setline(1, ['one', 'two', 'three']) + w ++ff=dos Xfile1 + enew! + r ++fileformat=unix Xfile1 + call assert_equal('unix', &fileformat) + 3r ++edit Xfile1 + call assert_equal('dos', &fileformat) + close! + call delete('Xfile1') + set fileformat& + call assert_fails('e ++fileformat Xfile1', 'E474:') + call assert_fails('e ++ff=abc Xfile1', 'E474:') + call assert_fails('e ++abc1 Xfile1', 'E474:') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 00dfc5bbdd..71f254a780 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -38,6 +38,7 @@ func Test_abclear() abclear call assert_equal("\n\nNo abbreviation found", execute('abbrev')) + call assert_fails('%abclear', 'E481:') endfunc func Test_abclear_buffer() diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim index 829f40dcbd..24c8a41711 100644 --- a/src/testdir/test_marks.vim +++ b/src/testdir/test_marks.vim @@ -212,4 +212,13 @@ func Test_lockmarks_with_put() bwipe! endfunc +" Test for :k command to set a mark +func Test_marks_k_cmd() + new + call setline(1, ['foo', 'bar', 'baz', 'qux']) + 1,3kr + call assert_equal([0, 3, 1, 0], getpos("'r")) + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index d45cf41592..2115c76dd2 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -2705,3 +2705,19 @@ func Test_normal_gk() bw! set cpoptions& number& numberwidth& endfunc + +" Test for cursor movement with '-' in 'cpoptions' +func Test_normal_cpo_minus() + new + call setline(1, ['foo', 'bar', 'baz']) + let save_cpo = &cpo + set cpo+=- + call assert_beeps('normal 10j') + call assert_equal(1, line('.')) + normal G + call assert_beeps('normal 10k') + call assert_equal(3, line('.')) + call assert_fails(10, 'E16:') + let &cpo = save_cpo + close! +endfunc diff --git a/src/testdir/test_plus_arg_edit.vim b/src/testdir/test_plus_arg_edit.vim index e31680e7b6..64533e71cf 100644 --- a/src/testdir/test_plus_arg_edit.vim +++ b/src/testdir/test_plus_arg_edit.vim @@ -32,3 +32,16 @@ func Test_edit_bad() bw! call delete('Xfile') endfunc + +" Test for ++bin and ++nobin arguments +func Test_binary_arg() + new + edit ++bin Xfile1 + call assert_equal(1, &binary) + edit ++nobin Xfile2 + call assert_equal(0, &binary) + call assert_fails('edit ++binabc Xfile3', 'E474:') + close! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index cc5ee8066d..d3f2e3abd7 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -538,6 +538,15 @@ func Xtest_browse(cchar) 10Xcc call assert_equal(11, line('.')) call assert_equal('Xqftestfile2', bufname('%')) + Xopen + call cursor(2, 1) + if a:cchar == 'c' + .cc + else + .ll + endif + call assert_equal(6, line('.')) + call assert_equal('Xqftestfile1', bufname('%')) " Jumping to an error from the error window (when only the error window is " present) diff --git a/src/version.c b/src/version.c index a77a7c8cae..ba8343dd9c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 261, /**/ 260, /**/ From 50434bd74c7708e3e2a47449b6a3a8d9fa069f71 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 14:55:22 +0100 Subject: [PATCH 44/55] patch 8.2.0262: fileformat test fails on MS-Windows Problem: Fileformat test fails on MS-Windows. Solution: Set fileformat of buffer. --- src/testdir/test_fileformat.vim | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/testdir/test_fileformat.vim b/src/testdir/test_fileformat.vim index efc5a0dd17..9f90debd7f 100644 --- a/src/testdir/test_fileformat.vim +++ b/src/testdir/test_fileformat.vim @@ -281,10 +281,13 @@ endfunc func Test_fileformat_plusplus_read() new call setline(1, ['one', 'two', 'three']) + set ff=unix w ++ff=dos Xfile1 enew! + " A :read doesn't change the fileformat, but does apply to the read lines. r ++fileformat=unix Xfile1 call assert_equal('unix', &fileformat) + call assert_equal("three\r", getline('$')) 3r ++edit Xfile1 call assert_equal('dos', &fileformat) close! diff --git a/src/version.c b/src/version.c index ba8343dd9c..95d4cd8438 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 262, /**/ 261, /**/ From df2ecddf9d0acc325c8290fbcff44de25b0c1e75 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 15:03:48 +0100 Subject: [PATCH 45/55] patch 8.2.0263: a few new Vim9 messages are not localized Problem: A few new Vim9 messages are not localized. Solution: Add the gettext wrapper. (Dominique Pelle, closes #5647) --- src/version.c | 2 ++ src/vim9compile.c | 6 +++--- src/vim9execute.c | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/version.c b/src/version.c index 95d4cd8438..780330ca27 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 263, /**/ 262, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 4413a514da..a4b5a92f0f 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3312,7 +3312,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) if (oplen == 3 && !heredoc && dest != dest_global && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN) { - emsg("E1019: Can only concatenate to string"); + emsg(_("E1019: Can only concatenate to string")); goto theend; } @@ -4735,7 +4735,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type) } else { - emsg("E1025: using } outside of a block scope"); + emsg(_("E1025: using } outside of a block scope")); goto erret; } if (line != NULL) @@ -4995,7 +4995,7 @@ erret: if (errormsg != NULL) emsg(errormsg); else if (called_emsg == called_emsg_before) - emsg("E1028: compile_def_function failed"); + emsg(_("E1028: compile_def_function failed")); // don't execute this function body ufunc->uf_lines.ga_len = 0; diff --git a/src/vim9execute.c b/src/vim9execute.c index c31506a86d..4555748110 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1611,12 +1611,12 @@ ex_disassemble(exarg_T *eap) vim_free(fname); if (ufunc == NULL) { - semsg("E1061: Cannot find function %s", eap->arg); + semsg(_("E1061: Cannot find function %s"), eap->arg); return; } if (ufunc->uf_dfunc_idx < 0) { - semsg("E1062: Function %s is not compiled", eap->arg); + semsg(_("E1062: Function %s is not compiled"), eap->arg); return; } if (ufunc->uf_name_exp != NULL) From a36c830a32f439b862ffb85d4c4b4799ee5ea2f9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 15:08:28 +0100 Subject: [PATCH 46/55] patch 8.2.0264: fileformat test still fails on MS-Windows Problem: Fileformat test still fails on MS-Windows. Solution: Set fileformat of buffer in the right place. --- src/testdir/test_fileformat.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_fileformat.vim b/src/testdir/test_fileformat.vim index 9f90debd7f..efc3b2252e 100644 --- a/src/testdir/test_fileformat.vim +++ b/src/testdir/test_fileformat.vim @@ -281,9 +281,9 @@ endfunc func Test_fileformat_plusplus_read() new call setline(1, ['one', 'two', 'three']) - set ff=unix w ++ff=dos Xfile1 enew! + set ff=unix " A :read doesn't change the fileformat, but does apply to the read lines. r ++fileformat=unix Xfile1 call assert_equal('unix', &fileformat) diff --git a/src/version.c b/src/version.c index 780330ca27..dc849eb45e 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 264, /**/ 263, /**/ From a76b31542e1d83b7d2fe7378439912e800a4d0f6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 16:20:21 +0100 Subject: [PATCH 47/55] patch 8.2.0265: "eval" after "if 0" doesn't check for following command Problem: "eval" after "if 0" doesn't check for following command. Solution: Add "eval" to list of commands that check for a following command. (closes #5640) --- src/ex_docmd.c | 1 + src/testdir/test_expr.vim | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 659af19111..a819f64888 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2375,6 +2375,7 @@ do_one_cmd( case CMD_echoerr: case CMD_echomsg: case CMD_echon: + case CMD_eval: case CMD_execute: case CMD_filter: case CMD_help: diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index bd9cacafa2..1281ae72f8 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -530,3 +530,12 @@ func Test_broken_number() call assert_equal(2, str2nr('2a')) call assert_fails('inoremap b', 'E474:') endfunc + +func Test_eval_after_if() + let s:val = '' + func SetVal(x) + let s:val ..= a:x + endfunc + if 0 | eval SetVal('a') | endif | call SetVal('b') + call assert_equal('b', s:val) +endfunc diff --git a/src/version.c b/src/version.c index dc849eb45e..da0b2f61c0 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 265, /**/ 264, /**/ From a28be85ccde03ee0a0dc984dfd7396c50713b593 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 17:04:09 +0100 Subject: [PATCH 48/55] patch 8.2.0266: terminal in popup test sometimes fails on Mac Problem: Terminal in popup test sometimes fails on Mac. Solution: Add a short delay. --- src/testdir/test_terminal.vim | 1 + src/version.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 5259454c82..e0761c4bdf 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2353,6 +2353,7 @@ func Test_terminal_in_popup() \ ] call writefile(lines, 'XtermPopup') let buf = RunVimInTerminal('-S XtermPopup', #{rows: 15}) + call term_wait(buf, 100) call term_sendkeys(buf, ":\") call VerifyScreenDump(buf, 'Test_terminal_popup_1', {}) diff --git a/src/version.c b/src/version.c index da0b2f61c0..67e23d52c4 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 266, /**/ 265, /**/ From e51bb17dd0d51384375830ee2a1df30c08121443 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 16 Feb 2020 19:42:23 +0100 Subject: [PATCH 49/55] patch 8.2.0267: no check for a following cmd when calling a function fails Problem: No check for a following command when calling a function fails. Solution: Also check for a following command when inside a try block. (closes #5642) --- src/testdir/test_user_func.vim | 4 ++++ src/userfunc.c | 3 ++- src/version.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim index d10a110848..872b87343d 100644 --- a/src/testdir/test_user_func.vim +++ b/src/testdir/test_user_func.vim @@ -162,3 +162,7 @@ endfunc func Test_user_method() eval 'bar'->s:addFoo()->assert_equal('barfoo') endfunc + +func Test_failed_call_in_try() + try | call UnknownFunc() | catch | endtry +endfunc diff --git a/src/userfunc.c b/src/userfunc.c index 1c25a62685..d1d497d690 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3554,7 +3554,8 @@ ex_call(exarg_T *eap) if (eap->skip) --emsg_skip; - if (!failed) + // When inside :try we need to check for following "| catch". + if (!failed || eap->cstack->cs_trylevel > 0) { // Check for trailing illegal characters and a following command. if (!ends_excmd(*arg)) diff --git a/src/version.c b/src/version.c index 67e23d52c4..73a70cdf2c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 267, /**/ 266, /**/ From 40d9da2a4395025169ebaf53a63618adfa737e96 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 10:01:24 +0100 Subject: [PATCH 50/55] patch 8.2.0268: trycatch test fails Problem: Trycatch test fails. Solution: When calling function fails only check for following command, do not give another error. --- src/userfunc.c | 7 +++++-- src/version.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/userfunc.c b/src/userfunc.c index d1d497d690..fc2161f51d 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3560,8 +3560,11 @@ ex_call(exarg_T *eap) // Check for trailing illegal characters and a following command. if (!ends_excmd(*arg)) { - emsg_severe = TRUE; - emsg(_(e_trailing)); + if (!failed) + { + emsg_severe = TRUE; + emsg(_(e_trailing)); + } } else eap->nextcmd = check_nextcmd(arg); diff --git a/src/version.c b/src/version.c index 73a70cdf2c..afac47d7e9 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 268, /**/ 267, /**/ From b13af50f73dd89503c915f76fcf92be58789521a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 21:12:08 +0100 Subject: [PATCH 51/55] patch 8.2.0269: Vim9: operator after list index does not work Problem: Vim9: operator after list index does not work. (Yasuhiro Matsumoto) Solution: After indexing a list change the type to the list member type. (closes #5651) --- src/testdir/test_vim9_expr.vim | 15 +++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 11 +++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 1ff713126b..c0767f517b 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -478,6 +478,17 @@ def Test_expr6() assert_equal(2, g:anint % g:alsoint) assert_equal(4, 6 * 4 / 6) + + let x = [2] + let y = [3] + assert_equal(5, x[0] + y[0]) + assert_equal(6, x[0] * y[0]) + if has('float') + let xf = [2.0] + let yf = [3.0] + assert_equal(5.0, xf[0] + yf[0]) + assert_equal(6.0, xf[0] * yf[0]) + endif enddef def Test_expr6_float() @@ -538,6 +549,10 @@ func Test_expr6_fails() call CheckDefFailure("let x = #{one: 1} / #{two: 2}", 'E1036:') call CheckDefFailure("let x = #{one: 1} % #{two: 2}", 'E1035:') + call CheckDefFailure("let x = 0xff[1]", 'E714:') + if has('float') + call CheckDefFailure("let x = 0.7[1]", 'E714:') + endif endfunc func Test_expr6_float_fails() diff --git a/src/version.c b/src/version.c index afac47d7e9..4ea0367441 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 269, /**/ 268, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index a4b5a92f0f..adfcbcc8ff 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2330,6 +2330,9 @@ compile_subscript( } else if (**arg == '[') { + garray_T *stack; + type_T **typep; + // list index: list[123] // TODO: more arguments // TODO: dict member dict['name'] @@ -2346,6 +2349,14 @@ compile_subscript( if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL) return FAIL; + stack = &cctx->ctx_type_stack; + typep = ((type_T **)stack->ga_data) + stack->ga_len - 1; + if ((*typep)->tt_type != VAR_LIST && *typep != &t_any) + { + emsg(_(e_listreq)); + return FAIL; + } + *typep = (*typep)->tt_member; } else if (**arg == '.' && (*arg)[1] != '.') { From bc2b71d44a0b90b6aeb3534a76912fccbe5577df Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 21:33:30 +0100 Subject: [PATCH 52/55] patch 8.2.0270: some code not covered by tests Problem: Some code not covered by tests. Solution: Add test cases. (Yegappan Lakshmanan, closes #5649) --- src/testdir/test_autocmd.vim | 2 + src/testdir/test_buffer.vim | 4 +- src/testdir/test_edit.vim | 18 +++ src/testdir/test_ex_mode.vim | 7 +- src/testdir/test_excmd.vim | 56 +++++++++ src/testdir/test_expand.vim | 29 +++++ src/testdir/test_filetype.vim | 22 ++++ src/testdir/test_findfile.vim | 40 +++++++ src/testdir/test_join.vim | 6 + src/testdir/test_move.vim | 1 + src/testdir/test_normal.vim | 2 +- src/testdir/test_registers.vim | 11 ++ src/testdir/test_source.vim | 21 ++++ src/testdir/test_tabpage.vim | 14 +++ src/testdir/test_tagjump.vim | 201 ++++++++++++++++++++++++++++++++ src/testdir/test_vimscript.vim | 10 ++ src/testdir/test_visual.vim | 14 +++ src/testdir/test_window_cmd.vim | 9 ++ src/testdir/test_writefile.vim | 4 +- src/version.c | 2 + 20 files changed, 466 insertions(+), 7 deletions(-) diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 23deec6c30..3b071049c2 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2357,3 +2357,5 @@ func Test_FileType_spell() au! crash setglobal spellfile= endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim index f2feca9fab..3266adc275 100644 --- a/src/testdir/test_buffer.vim +++ b/src/testdir/test_buffer.vim @@ -103,9 +103,9 @@ func Test_buflist_browse() call assert_equal(b2, bufnr()) call assert_equal(1, line('.')) - brewind +/foo3 + brewind + call assert_equal(b1, bufnr()) - call assert_equal(3, line('.')) + call assert_equal(4, line('.')) blast +/baz2 call assert_equal(b3, bufnr()) diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim index 1a37146cee..eef22d49c2 100644 --- a/src/testdir/test_edit.vim +++ b/src/testdir/test_edit.vim @@ -1500,6 +1500,22 @@ func Test_edit_startinsert() bwipe! endfunc +" Test for :startreplace and :startgreplace +func Test_edit_startreplace() + new + call setline(1, 'abc') + call feedkeys("l:startreplace\xyz\e", 'xt') + call assert_equal('axyz', getline(1)) + call feedkeys("0:startreplace!\abc\e", 'xt') + call assert_equal('axyzabc', getline(1)) + call setline(1, "a\tb") + call feedkeys("0l:startgreplace\xyz\e", 'xt') + call assert_equal("axyz\tb", getline(1)) + call feedkeys("0i\=execute('startreplace')\12\e", 'xt') + call assert_equal("12axyz\tb", getline(1)) + close! +endfunc + func Test_edit_noesckeys() CheckNotGui new @@ -1519,3 +1535,5 @@ func Test_edit_noesckeys() bwipe! set esckeys endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_ex_mode.vim b/src/testdir/test_ex_mode.vim index 7861477c74..bf10104984 100644 --- a/src/testdir/test_ex_mode.vim +++ b/src/testdir/test_ex_mode.vim @@ -55,7 +55,7 @@ func Test_ex_mode() let &encoding = encoding_save endfunc -" Test subsittute confirmation prompt :%s/pat/str/c in Ex mode +" Test substitute confirmation prompt :%s/pat/str/c in Ex mode func Test_Ex_substitute() CheckRunVimInTerminal let buf = RunVimInTerminal('', {'rows': 6}) @@ -77,6 +77,11 @@ func Test_Ex_substitute() call term_sendkeys(buf, "q\") call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000) + " Pressing enter in ex mode should print the current line + call term_sendkeys(buf, "\") + call WaitForAssert({-> assert_match(' 3 foo foo', + \ term_getline(buf, 5))}, 1000) + call term_sendkeys(buf, ":vi\") call WaitForAssert({-> assert_match('foo bar', term_getline(buf, 1))}, 1000) diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim index 7ce32ca420..2407f8eb1e 100644 --- a/src/testdir/test_excmd.vim +++ b/src/testdir/test_excmd.vim @@ -267,6 +267,16 @@ func Test_redir_cmd() call assert_fails('redir! > Xfile', 'E190:') call delete('Xfile') endif + + " Test for redirecting to a register + redir @q> | echon 'clean ' | redir END + redir @q>> | echon 'water' | redir END + call assert_equal('clean water', @q) + + " Test for redirecting to a variable + redir => color | echon 'blue ' | redir END + redir =>> color | echon 'sky' | redir END + call assert_equal('blue sky', color) endfunc " Test for the :filetype command @@ -279,4 +289,50 @@ func Test_mode_cmd() call assert_fails('mode abc', 'E359:') endfunc +" Test for the :sleep command +func Test_sleep_cmd() + call assert_fails('sleep x', 'E475:') +endfunc + +" Test for the :read command +func Test_read_cmd() + call writefile(['one'], 'Xfile') + new + call assert_fails('read', 'E32:') + edit Xfile + read + call assert_equal(['one', 'one'], getline(1, '$')) + close! + new + read Xfile + call assert_equal(['', 'one'], getline(1, '$')) + call deletebufline('', 1, '$') + call feedkeys("Qr Xfile\visual\", 'xt') + call assert_equal(['one'], getline(1, '$')) + close! + call delete('Xfile') +endfunc + +" Test for running Ex commands when text is locked. +" e in the command line is used to lock the text +func Test_run_excmd_with_text_locked() + " :quit + let cmd = ":\eexecute('quit')\\" + call assert_fails("call feedkeys(cmd, 'xt')", 'E523:') + + " :qall + let cmd = ":\eexecute('qall')\\" + call assert_fails("call feedkeys(cmd, 'xt')", 'E523:') + + " :exit + let cmd = ":\eexecute('exit')\\" + call assert_fails("call feedkeys(cmd, 'xt')", 'E523:') + + " :close - should be ignored + new + let cmd = ":\eexecute('close')\\" + call assert_equal(2, winnr('$')) + close +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_expand.vim b/src/testdir/test_expand.vim index 48dce25bb3..5a51903712 100644 --- a/src/testdir/test_expand.vim +++ b/src/testdir/test_expand.vim @@ -1,5 +1,7 @@ " Test for expanding file names +source shared.vim + func Test_with_directories() call mkdir('Xdir1') call mkdir('Xdir2') @@ -81,3 +83,30 @@ func Test_expandcmd() call assert_fails('call expandcmd("make %")', 'E499:') close endfunc + +" Test for expanding , and outside of sourcing a script +func Test_source_sfile() + let lines =<< trim [SCRIPT] + :call assert_fails('echo expandcmd("")', 'E498:') + :call assert_fails('echo expandcmd("")', 'E842:') + :call assert_fails('echo expandcmd("")', 'E961:') + :call assert_fails('call expandcmd("edit ")', 'E446:') + :call assert_fails('call expandcmd("edit #")', 'E194:') + :call assert_fails('call expandcmd("edit #<2")', 'E684:') + :call assert_fails('call expandcmd("edit ")', 'E348:') + :call assert_fails('call expandcmd("edit ")', 'E348:') + :call assert_fails('autocmd User MyCmd echo ""', 'E498:') + :call writefile(v:errors, 'Xresult') + :qall! + + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -s Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 3868e73c5d..213f2de1c9 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -621,3 +621,25 @@ func Test_setfiletype_completion() call feedkeys(":setfiletype java\\\"\", 'tx') call assert_equal('"setfiletype java javacc javascript javascriptreact', @:) endfunc + +" Test for ':filetype detect' command for a buffer without a file +func Test_emptybuf_ftdetect() + new + call setline(1, '#!/bin/sh') + call assert_equal('', &filetype) + filetype detect + call assert_equal('sh', &filetype) + close! +endfunc + +" Test for ':filetype indent on' and ':filetype indent off' commands +func Test_filetype_indent_off() + new Xtest.vim + filetype indent on + call assert_equal(1, g:did_indent_on) + filetype indent off + call assert_equal(0, exists('g:did_indent_on')) + close +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim index 2e6f888896..ac6d8637b8 100644 --- a/src/testdir/test_findfile.vim +++ b/src/testdir/test_findfile.vim @@ -183,3 +183,43 @@ func Test_finddir_error() call assert_fails('call finddir("x", "**x")', 'E343:') call assert_fails('call finddir("x", repeat("x", 5000))', 'E854:') endfunc + +" Test for the :find, :sfind and :tabfind commands +func Test_find_cmd() + new + let save_path = &path + let save_dir = getcwd() + set path=.,./**/* + call CreateFiles() + cd Xdir1 + + " Test for :find + find foo + call assert_equal('foo', expand('%:.')) + 2find foo + call assert_equal('Xdir2/foo', expand('%:.')) + call assert_fails('3find foo', 'E347:') + + " Test for :sfind + enew + sfind barfoo + call assert_equal('Xdir2/Xdir3/barfoo', expand('%:.')) + call assert_equal(3, winnr('$')) + close + call assert_fails('sfind baz', 'E345:') + call assert_equal(2, winnr('$')) + + " Test for :tabfind + enew + tabfind foobar + call assert_equal('Xdir2/foobar', expand('%:.')) + call assert_equal(2, tabpagenr('$')) + tabclose + call assert_fails('tabfind baz', 'E345:') + call assert_equal(1, tabpagenr('$')) + + call chdir(save_dir) + call CleanFiles() + let &path = save_path + close +endfunc diff --git a/src/testdir/test_join.vim b/src/testdir/test_join.vim index 377edab1e9..fdd9e05ebc 100644 --- a/src/testdir/test_join.vim +++ b/src/testdir/test_join.vim @@ -436,5 +436,11 @@ func Test_join_lines() call setline(1, ['a', 'b', '', 'c', 'd']) normal 5J call assert_equal('a b c d', getline(1)) + call setline(1, ['a', 'b', 'c']) + 2,2join + call assert_equal(['a', 'b', 'c'], getline(1, '$')) + call assert_equal(2, line('.')) + 2join + call assert_equal(['a', 'b c'], getline(1, '$')) bwipe! endfunc diff --git a/src/testdir/test_move.vim b/src/testdir/test_move.vim index f666a904b0..8c40369dbd 100644 --- a/src/testdir/test_move.vim +++ b/src/testdir/test_move.vim @@ -38,6 +38,7 @@ func Test_move() call assert_fails("move -100", 'E16:') call assert_fails("move +100", 'E16:') call assert_fails('move', 'E16:') + call assert_fails("move 'r", 'E20:') %bwipeout! endfunc diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 2115c76dd2..843374d26e 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -2006,7 +2006,7 @@ fun! Test_normal37_g_cmd6() tabclose endfor " clean up - call assert_fails(':tabclose', 'E784') + call assert_fails(':tabclose', 'E784:') endfunc fun! Test_normal38_nvhome() diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index 45cf02a59c..b8f0a1012f 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -386,4 +386,15 @@ func Test_put_reg_restart_mode() bwipe! endfunc +" Test for executing a register using :@ command +func Test_execute_register() + call setreg('r', []) + call assert_beeps('@r') + let i = 1 + let @q = 'let i+= 1' + @q + @ + call assert_equal(3, i) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_source.vim b/src/testdir/test_source.vim index e7f3fb1884..ba6fd5ad95 100644 --- a/src/testdir/test_source.vim +++ b/src/testdir/test_source.vim @@ -66,4 +66,25 @@ func Test_source_ignore_shebang() call delete('Xfile.vim') endfunc +" Test for expanding in a autocmd and for and +func Test_source_autocmd_sfile() + let code =<< trim [CODE] + let g:SfileName = '' + augroup sfiletest + au! + autocmd User UserAutoCmd let g:Sfile = ':t' + augroup END + doautocmd User UserAutoCmd + let g:Slnum = expand('') + let g:Sflnum = expand('') + augroup! sfiletest + [CODE] + call writefile(code, 'Xscript.vim') + source Xscript.vim + call assert_equal('Xscript.vim', g:Sfile) + call assert_equal('7', g:Slnum) + call assert_equal('8', g:Sflnum) + call delete('Xscript.vim') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index bf721a0b61..35c9fd0eab 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -139,7 +139,11 @@ function Test_tabpage() call assert_fails("tabmove -99", 'E474:') call assert_fails("tabmove -3+", 'E474:') call assert_fails("tabmove $3", 'E474:') + call assert_fails("%tabonly", 'E16:') 1tabonly! + tabnew + call assert_fails("-2tabmove", 'E474:') + tabonly! endfunc " Test autocommands @@ -609,4 +613,14 @@ func Test_tabpage_cmdheight() call delete('XTest_tabpage_cmdheight') endfunc +" Test for closing the tab page from a command window +func Test_tabpage_close_cmdwin() + tabnew + call feedkeys("q/:tabclose\\", 'xt') + call assert_equal(2, tabpagenr('$')) + call feedkeys("q/:tabonly\\", 'xt') + call assert_equal(2, tabpagenr('$')) + tabonly +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 47b9ffb459..29c3840597 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -893,6 +893,11 @@ func Test_tag_multimatch() tag FIRST tnext call assert_equal(2, line('.')) + tlast + tprev + call assert_equal(2, line('.')) + tNext + call assert_equal(1, line('.')) set ignorecase& call delete('Xtags') @@ -1035,4 +1040,200 @@ Type number and (empty cancels): %bwipe endfunc +" Test for :isearch, :ilist, :ijump and :isplit commands +" Test for [i, ]i, [I, ]I, [ CTRL-I, ] CTRL-I and CTRL-W i commands +func Test_inc_search() + new + call setline(1, ['1:foo', '2:foo', 'foo', '3:foo', '4:foo']) + call cursor(3, 1) + + " Test for [i and ]i + call assert_equal('1:foo', execute('normal [i')) + call assert_equal('2:foo', execute('normal 2[i')) + call assert_fails('normal 3[i', 'E387:') + call assert_equal('3:foo', execute('normal ]i')) + call assert_equal('4:foo', execute('normal 2]i')) + call assert_fails('normal 3]i', 'E389:') + + " Test for :isearch + call assert_equal('1:foo', execute('isearch foo')) + call assert_equal('3:foo', execute('isearch 4 /foo/')) + call assert_fails('isearch 3 foo', 'E387:') + call assert_equal('3:foo', execute('+1,$isearch foo')) + call assert_fails('1,.-1isearch 3 foo', 'E389:') + call assert_fails('isearch bar', 'E389:') + call assert_fails('isearch /foo/3', 'E488:') + + " Test for [I and ]I + call assert_equal([ + \ ' 1: 1 1:foo', + \ ' 2: 2 2:foo', + \ ' 3: 3 foo', + \ ' 4: 4 3:foo', + \ ' 5: 5 4:foo'], split(execute('normal [I'), "\n")) + call assert_equal([ + \ ' 1: 4 3:foo', + \ ' 2: 5 4:foo'], split(execute('normal ]I'), "\n")) + + " Test for :ilist + call assert_equal([ + \ ' 1: 1 1:foo', + \ ' 2: 2 2:foo', + \ ' 3: 3 foo', + \ ' 4: 4 3:foo', + \ ' 5: 5 4:foo'], split(execute('ilist foo'), "\n")) + call assert_equal([ + \ ' 1: 4 3:foo', + \ ' 2: 5 4:foo'], split(execute('+1,$ilist /foo/'), "\n")) + call assert_fails('ilist bar', 'E389:') + + " Test for [ CTRL-I and ] CTRL-I + exe "normal [\t" + call assert_equal([1, 3], [line('.'), col('.')]) + exe "normal 2j4[\t" + call assert_equal([4, 3], [line('.'), col('.')]) + call assert_fails("normal k3[\t", 'E387:') + call assert_fails("normal 6[\t", 'E389:') + exe "normal ]\t" + call assert_equal([4, 3], [line('.'), col('.')]) + exe "normal k2]\t" + call assert_equal([5, 3], [line('.'), col('.')]) + call assert_fails("normal 2k3]\t", 'E389:') + + " Test for :ijump + call cursor(3, 1) + ijump foo + call assert_equal([1, 3], [line('.'), col('.')]) + call cursor(3, 1) + ijump 4 /foo/ + call assert_equal([4, 3], [line('.'), col('.')]) + call cursor(3, 1) + call assert_fails('ijump 3 foo', 'E387:') + +,$ijump 2 foo + call assert_equal([5, 3], [line('.'), col('.')]) + call assert_fails('ijump bar', 'E389:') + + " Test for CTRL-W i + call cursor(3, 1) + wincmd i + call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')]) + close + 5wincmd i + call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')]) + close + call assert_fails('3wincmd i', 'E387:') + call assert_fails('6wincmd i', 'E389:') + + " Test for :isplit + isplit foo + call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')]) + close + isplit 5 /foo/ + call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')]) + close + call assert_fails('isplit 3 foo', 'E387:') + call assert_fails('isplit 6 foo', 'E389:') + call assert_fails('isplit bar', 'E389:') + + close! +endfunc + +" Test for :dsearch, :dlist, :djump and :dsplit commands +" Test for [d, ]d, [D, ]D, [ CTRL-D, ] CTRL-D and CTRL-W d commands +func Test_def_search() + new + call setline(1, ['#define FOO 1', '#define FOO 2', '#define FOO 3', + \ '#define FOO 4', '#define FOO 5']) + call cursor(3, 9) + + " Test for [d and ]d + call assert_equal('#define FOO 1', execute('normal [d')) + call assert_equal('#define FOO 2', execute('normal 2[d')) + call assert_fails('normal 3[d', 'E387:') + call assert_equal('#define FOO 4', execute('normal ]d')) + call assert_equal('#define FOO 5', execute('normal 2]d')) + call assert_fails('normal 3]d', 'E388:') + + " Test for :dsearch + call assert_equal('#define FOO 1', execute('dsearch FOO')) + call assert_equal('#define FOO 5', execute('dsearch 5 /FOO/')) + call assert_fails('dsearch 3 FOO', 'E387:') + call assert_equal('#define FOO 4', execute('+1,$dsearch FOO')) + call assert_fails('1,.-1dsearch 3 FOO', 'E388:') + call assert_fails('dsearch BAR', 'E388:') + + " Test for [D and ]D + call assert_equal([ + \ ' 1: 1 #define FOO 1', + \ ' 2: 2 #define FOO 2', + \ ' 3: 3 #define FOO 3', + \ ' 4: 4 #define FOO 4', + \ ' 5: 5 #define FOO 5'], split(execute('normal [D'), "\n")) + call assert_equal([ + \ ' 1: 4 #define FOO 4', + \ ' 2: 5 #define FOO 5'], split(execute('normal ]D'), "\n")) + + " Test for :dlist + call assert_equal([ + \ ' 1: 1 #define FOO 1', + \ ' 2: 2 #define FOO 2', + \ ' 3: 3 #define FOO 3', + \ ' 4: 4 #define FOO 4', + \ ' 5: 5 #define FOO 5'], split(execute('dlist FOO'), "\n")) + call assert_equal([ + \ ' 1: 4 #define FOO 4', + \ ' 2: 5 #define FOO 5'], split(execute('+1,$dlist /FOO/'), "\n")) + call assert_fails('dlist BAR', 'E388:') + + " Test for [ CTRL-D and ] CTRL-D + exe "normal [\" + call assert_equal([1, 9], [line('.'), col('.')]) + exe "normal 2j4[\" + call assert_equal([4, 9], [line('.'), col('.')]) + call assert_fails("normal k3[\", 'E387:') + call assert_fails("normal 6[\", 'E388:') + exe "normal ]\" + call assert_equal([4, 9], [line('.'), col('.')]) + exe "normal k2]\" + call assert_equal([5, 9], [line('.'), col('.')]) + call assert_fails("normal 2k3]\", 'E388:') + + " Test for :djump + call cursor(3, 9) + djump FOO + call assert_equal([1, 9], [line('.'), col('.')]) + call cursor(3, 9) + djump 4 /FOO/ + call assert_equal([4, 9], [line('.'), col('.')]) + call cursor(3, 9) + call assert_fails('djump 3 FOO', 'E387:') + +,$djump 2 FOO + call assert_equal([5, 9], [line('.'), col('.')]) + call assert_fails('djump BAR', 'E388:') + + " Test for CTRL-W d + call cursor(3, 9) + wincmd d + call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')]) + close + 5wincmd d + call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')]) + close + call assert_fails('3wincmd d', 'E387:') + call assert_fails('6wincmd d', 'E388:') + + " Test for :dsplit + dsplit FOO + call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')]) + close + dsplit 5 /FOO/ + call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')]) + close + call assert_fails('dsplit 3 FOO', 'E387:') + call assert_fails('dsplit 6 FOO', 'E388:') + call assert_fails('dsplit BAR', 'E388:') + + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index a422a6df88..a75e5f6f2b 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -2061,6 +2061,16 @@ func Test_deep_nest() call delete('Xscript') endfunc +" Test for , in a function {{{1 +func Test_sfile_in_function() + func Xfunc() + call assert_match('..Test_sfile_in_function\[5]..Xfunc', expand('')) + call assert_equal('2', expand('')) + endfunc + call Xfunc() + delfunc Xfunc +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index ae281238e9..601ad0fbe2 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -894,4 +894,18 @@ func Test_block_insert_replace_tabs() bwipe! endfunc +" Test for * register in : +func Test_star_register() + call assert_fails('*bfirst', 'E16:') + new + call setline(1, ['foo', 'bar', 'baz', 'qux']) + exe "normal jVj\" + *yank r + call assert_equal("bar\nbaz\n", @r) + + delmarks < > + call assert_fails('*yank', 'E20:') + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 24501e14c4..362b0eb02a 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -940,6 +940,15 @@ func Test_window_only() new call assert_fails('only', 'E445:') only! + " Test for :only with a count + let wid = win_getid() + new + new + 3only + call assert_equal(1, winnr('$')) + call assert_equal(wid, win_getid()) + call assert_fails('close', 'E444:') + call assert_fails('%close', 'E16:') endfunc " Test for errors with :wincmd diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim index f616980f35..5449071229 100644 --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -215,9 +215,7 @@ func Test_write_errors() close! call assert_fails('w > Xtest', 'E494:') - - call assert_fails('w > Xtest', 'E494:') - + " Try to overwrite a directory if has('unix') call mkdir('Xdir1') diff --git a/src/version.c b/src/version.c index 4ea0367441..e27ac71521 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 270, /**/ 269, /**/ From 82f654e092ac5b86316bc1b30c0b07a849813186 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 22:12:50 +0100 Subject: [PATCH 53/55] patch 8.2.0271: the "num64" feature is available everywhere Problem: The "num64" feature is available everywhere and building without it causes problems. Solution: Graduage the "num64" feature. (James McCoy, closes #5650) --- src/evalfunc.c | 2 -- src/feature.h | 4 --- src/message.c | 36 ++++++-------------------- src/structs.h | 47 ++++++++++++++-------------------- src/testdir/test_expr.vim | 12 +++------ src/testdir/test_largefile.vim | 7 +---- src/testdir/test_sort.vim | 36 ++++++++++++-------------- src/testdir/test_vimscript.vim | 22 +++------------- src/version.c | 6 ++--- 9 files changed, 53 insertions(+), 119 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 3e1a462d19..f1a06caaac 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3545,9 +3545,7 @@ f_has(typval_T *argvars, typval_T *rettv) "mzscheme", #endif #endif -#ifdef FEAT_NUM64 "num64", -#endif #ifdef FEAT_OLE "ole", #endif diff --git a/src/feature.h b/src/feature.h index 7e1e982ed6..b25837e1f6 100644 --- a/src/feature.h +++ b/src/feature.h @@ -285,16 +285,12 @@ * +eval Built-in script language and expression evaluation, * ":let", ":if", etc. * +float Floating point variables. - * +num64 64-bit Number. */ #ifdef FEAT_NORMAL # define FEAT_EVAL # if defined(HAVE_FLOAT_FUNCS) || defined(MSWIN) || defined(MACOS_X) # define FEAT_FLOAT # endif -# if defined(HAVE_STDINT_H) || defined(MSWIN) || (VIM_SIZEOF_LONG >= 8) -# define FEAT_NUM64 -# endif #endif #ifdef FEAT_EVAL diff --git a/src/message.c b/src/message.c index 935fd8c447..9ab0eaefeb 100644 --- a/src/message.c +++ b/src/message.c @@ -4246,10 +4246,8 @@ vim_vsnprintf_typval( # define TMP_LEN 350 // On my system 1e308 is the biggest number possible. // That sounds reasonable to use as the maximum // printable. -# elif defined(FEAT_NUM64) -# define TMP_LEN 66 # else -# define TMP_LEN 34 +# define TMP_LEN 66 # endif char tmp[TMP_LEN]; @@ -4374,11 +4372,7 @@ vim_vsnprintf_typval( if (length_modifier == 'l' && *p == 'l') { // double l = long long -# ifdef FEAT_NUM64 length_modifier = 'L'; -# else - length_modifier = 'l'; // treat it as a single 'l' -# endif p++; } } @@ -4394,7 +4388,7 @@ vim_vsnprintf_typval( default: break; } -# if defined(FEAT_EVAL) && defined(FEAT_NUM64) +# if defined(FEAT_EVAL) switch (fmt_spec) { case 'd': case 'u': case 'o': case 'x': case 'X': @@ -4516,11 +4510,9 @@ vim_vsnprintf_typval( long int long_arg = 0; unsigned long int ulong_arg = 0; -# ifdef FEAT_NUM64 // only defined for length modifier ll varnumber_T llong_arg = 0; uvarnumber_T ullong_arg = 0; -# endif // only defined for b conversion uvarnumber_T bin_arg = 0; @@ -4581,19 +4573,17 @@ vim_vsnprintf_typval( else if (long_arg < 0) arg_sign = -1; break; -# ifdef FEAT_NUM64 case 'L': llong_arg = -# if defined(FEAT_EVAL) +# if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : -# endif +# endif va_arg(ap, varnumber_T); if (llong_arg > 0) arg_sign = 1; else if (llong_arg < 0) arg_sign = -1; break; -# endif } } else @@ -4622,18 +4612,16 @@ vim_vsnprintf_typval( if (ulong_arg != 0) arg_sign = 1; break; -# ifdef FEAT_NUM64 case 'L': ullong_arg = -# if defined(FEAT_EVAL) +# if defined(FEAT_EVAL) tvs != NULL ? (uvarnumber_T) tv_nr(tvs, &arg_idx) : -# endif +# endif va_arg(ap, uvarnumber_T); if (ullong_arg != 0) arg_sign = 1; break; -# endif } } @@ -4687,17 +4675,13 @@ vim_vsnprintf_typval( ; else if (length_modifier == 'L') { -# ifdef FEAT_NUM64 -# ifdef MSWIN +# ifdef MSWIN f[f_l++] = 'I'; f[f_l++] = '6'; f[f_l++] = '4'; -# else - f[f_l++] = 'l'; - f[f_l++] = 'l'; -# endif # else f[f_l++] = 'l'; + f[f_l++] = 'l'; # endif } else @@ -4735,11 +4719,9 @@ vim_vsnprintf_typval( case 'l': str_arg_l += sprintf( tmp + str_arg_l, f, long_arg); break; -# ifdef FEAT_NUM64 case 'L': str_arg_l += sprintf( tmp + str_arg_l, f, llong_arg); break; -# endif } } else @@ -4754,11 +4736,9 @@ vim_vsnprintf_typval( case 'l': str_arg_l += sprintf( tmp + str_arg_l, f, ulong_arg); break; -# ifdef FEAT_NUM64 case 'L': str_arg_l += sprintf( tmp + str_arg_l, f, ullong_arg); break; -# endif } } diff --git a/src/structs.h b/src/structs.h index 7aff8af201..823dfda3ca 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1245,42 +1245,33 @@ typedef struct hashtable_S typedef long_u hash_T; // Type for hi_hash -#ifdef FEAT_NUM64 // Use 64-bit Number. -# ifdef MSWIN -# ifdef PROTO -typedef long varnumber_T; -typedef unsigned long uvarnumber_T; -# define VARNUM_MIN LONG_MIN -# define VARNUM_MAX LONG_MAX -# define UVARNUM_MAX ULONG_MAX -# else -typedef __int64 varnumber_T; -typedef unsigned __int64 uvarnumber_T; -# define VARNUM_MIN _I64_MIN -# define VARNUM_MAX _I64_MAX -# define UVARNUM_MAX _UI64_MAX -# endif -# elif defined(HAVE_STDINT_H) -typedef int64_t varnumber_T; -typedef uint64_t uvarnumber_T; -# define VARNUM_MIN INT64_MIN -# define VARNUM_MAX INT64_MAX -# define UVARNUM_MAX UINT64_MAX -# else +#ifdef MSWIN +# ifdef PROTO typedef long varnumber_T; typedef unsigned long uvarnumber_T; # define VARNUM_MIN LONG_MIN # define VARNUM_MAX LONG_MAX # define UVARNUM_MAX ULONG_MAX +# else +typedef __int64 varnumber_T; +typedef unsigned __int64 uvarnumber_T; +# define VARNUM_MIN _I64_MIN +# define VARNUM_MAX _I64_MAX +# define UVARNUM_MAX _UI64_MAX # endif +#elif defined(HAVE_STDINT_H) +typedef int64_t varnumber_T; +typedef uint64_t uvarnumber_T; +# define VARNUM_MIN INT64_MIN +# define VARNUM_MAX INT64_MAX +# define UVARNUM_MAX UINT64_MAX #else -// Use 32-bit Number. -typedef int varnumber_T; -typedef unsigned int uvarnumber_T; -# define VARNUM_MIN INT_MIN -# define VARNUM_MAX INT_MAX -# define UVARNUM_MAX UINT_MAX +typedef long varnumber_T; +typedef unsigned long uvarnumber_T; +# define VARNUM_MIN LONG_MIN +# define VARNUM_MAX LONG_MAX +# define UVARNUM_MAX ULONG_MAX #endif typedef double float_T; diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index 1281ae72f8..7601c4fa71 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -382,9 +382,7 @@ function Test_max_min_errors() endfunc function Test_printf_64bit() - if has('num64') - call assert_equal("123456789012345", printf('%d', 123456789012345)) - endif + call assert_equal("123456789012345", printf('%d', 123456789012345)) endfunc function Test_printf_spec_s() @@ -423,12 +421,8 @@ function Test_printf_spec_b() call assert_equal(" 0b1111011", printf('%#10b', 123)) call assert_equal("0B01111011", printf('%#010B', 123)) call assert_equal("1001001100101100000001011010010", printf('%b', 1234567890)) - if has('num64') - call assert_equal("11100000100100010000110000011011101111101111001", printf('%b', 123456789012345)) - call assert_equal("1111111111111111111111111111111111111111111111111111111111111111", printf('%b', -1)) - else - call assert_equal("11111111111111111111111111111111", printf('%b', -1)) - endif + call assert_equal("11100000100100010000110000011011101111101111001", printf('%b', 123456789012345)) + call assert_equal("1111111111111111111111111111111111111111111111111111111111111111", printf('%b', -1)) endfunc func Test_substitute_expr() diff --git a/src/testdir/test_largefile.vim b/src/testdir/test_largefile.vim index 1b3e02a0c8..68d6ec9eb0 100644 --- a/src/testdir/test_largefile.vim +++ b/src/testdir/test_largefile.vim @@ -24,11 +24,6 @@ func Test_largefile() w " Check if the file size is 4,000,000,000 bytes. let fsize=getfsize(fname) - if has('num64') - call assert_true(fsize == 4000000000) - else - " getfsize() returns -2 if a Number is 32 bits. - call assert_true(fsize == -2) - endif + call assert_true(fsize == 4000000000) call delete(fname) endfunc diff --git a/src/testdir/test_sort.vim b/src/testdir/test_sort.vim index ce5592e2e9..8299db4ef8 100644 --- a/src/testdir/test_sort.vim +++ b/src/testdir/test_sort.vim @@ -1295,9 +1295,8 @@ abc \ '2147483647'], getline(1, '$')) bwipe! - if has('num64') - new - a + new + a -9223372036854775808 -9223372036854775807 @@ -1312,22 +1311,21 @@ abc abc . - sort n - call assert_equal(['', - \ 'abc', - \ '', - \ '-9223372036854775808', - \ '-9223372036854775808', - \ '-9223372036854775807', - \ '-9223372036854775806', - \ '-1', - \ '0', - \ '1', - \ '9223372036854775806', - \ '9223372036854775807', - \ '9223372036854775807'], getline(1, '$')) - bwipe! - endif + sort n + call assert_equal(['', + \ 'abc', + \ '', + \ '-9223372036854775808', + \ '-9223372036854775808', + \ '-9223372036854775807', + \ '-9223372036854775806', + \ '-1', + \ '0', + \ '1', + \ '9223372036854775806', + \ '9223372036854775807', + \ '9223372036854775807'], getline(1, '$')) + bwipe! endfunc diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index a75e5f6f2b..b16b05b02c 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -1416,10 +1416,6 @@ endfunc "------------------------------------------------------------------------------- func Test_num64() - if !has('num64') - return - endif - call assert_notequal( 4294967296, 0) call assert_notequal(-4294967296, 0) call assert_equal( 4294967296, 0xFFFFffff + 1) @@ -1692,27 +1688,15 @@ func Test_compound_assignment_operators() " Test special cases: division or modulus with 0. let x = 1 let x /= 0 - if has('num64') - call assert_equal(0x7FFFFFFFFFFFFFFF, x) - else - call assert_equal(0x7fffffff, x) - endif + call assert_equal(0x7FFFFFFFFFFFFFFF, x) let x = -1 let x /= 0 - if has('num64') - call assert_equal(-0x7FFFFFFFFFFFFFFF, x) - else - call assert_equal(-0x7fffffff, x) - endif + call assert_equal(-0x7FFFFFFFFFFFFFFF, x) let x = 0 let x /= 0 - if has('num64') - call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x) - else - call assert_equal(-0x7FFFFFFF - 1, x) - endif + call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x) let x = 1 let x %= 0 diff --git a/src/version.c b/src/version.c index e27ac71521..ad70c4dd0b 100644 --- a/src/version.c +++ b/src/version.c @@ -436,11 +436,7 @@ static char *(features[]) = #else "-netbeans_intg", #endif -#ifdef FEAT_NUM64 "+num64", -#else - "-num64", -#endif #ifdef FEAT_GUI_MSWIN # ifdef FEAT_OLE "+ole", @@ -742,6 +738,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 271, /**/ 270, /**/ From 414b79662786762256e756ece8ab4aaecbbf9bd1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 22:39:35 +0100 Subject: [PATCH 54/55] patch 8.2.0272: ":helptags ALL" gives error for some directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ":helptags ALL" gives error for directories without write permission. (Matěj Cepl) Solution: Ignore errors for ":helptags ALL". (Ken Takata, closes #5026, closes #5652) --- src/ex_cmds.c | 17 ++++++++++------- src/testdir/test_help.vim | 16 ++++++++++++---- src/version.c | 2 ++ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 0eeb3f3399..f92537862f 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -5920,7 +5920,8 @@ helptags_one( char_u *dir, // doc directory char_u *ext, // suffix, ".txt", ".itx", ".frx", etc. char_u *tagfname, // "tags" for English, "tags-fr" for French. - int add_help_tags) // add "help-tags" tag + int add_help_tags, // add "help-tags" tag + int ignore_writeerr) // ignore write error { FILE *fd_tags; FILE *fd; @@ -5964,7 +5965,8 @@ helptags_one( fd_tags = mch_fopen((char *)NameBuff, "w"); if (fd_tags == NULL) { - semsg(_("E152: Cannot open %s for writing"), NameBuff); + if (!ignore_writeerr) + semsg(_("E152: Cannot open %s for writing"), NameBuff); FreeWild(filecount, files); return; } @@ -6165,7 +6167,7 @@ helptags_one( * Generate tags in one help directory, taking care of translations. */ static void -do_helptags(char_u *dirname, int add_help_tags) +do_helptags(char_u *dirname, int add_help_tags, int ignore_writeerr) { #ifdef FEAT_MULTI_LANG int len; @@ -6251,7 +6253,7 @@ do_helptags(char_u *dirname, int add_help_tags) ext[1] = fname[5]; ext[2] = fname[6]; } - helptags_one(dirname, ext, fname, add_help_tags); + helptags_one(dirname, ext, fname, add_help_tags, ignore_writeerr); } ga_clear(&ga); @@ -6259,14 +6261,15 @@ do_helptags(char_u *dirname, int add_help_tags) #else // No language support, just use "*.txt" and "tags". - helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags); + helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags, + ignore_writeerr); #endif } static void helptags_cb(char_u *fname, void *cookie) { - do_helptags(fname, *(int *)cookie); + do_helptags(fname, *(int *)cookie, TRUE); } /* @@ -6300,7 +6303,7 @@ ex_helptags(exarg_T *eap) if (dirname == NULL || !mch_isdir(dirname)) semsg(_("E150: Not a directory: %s"), eap->arg); else - do_helptags(dirname, add_help_tags); + do_helptags(dirname, add_help_tags, FALSE); vim_free(dirname); } } diff --git a/src/testdir/test_help.vim b/src/testdir/test_help.vim index 3b6ad3923b..219689bde5 100644 --- a/src/testdir/test_help.vim +++ b/src/testdir/test_help.vim @@ -90,10 +90,18 @@ func Test_helptag_cmd() " The following tests fail on FreeBSD for some reason if has('unix') && !has('bsd') " Read-only tags file - call writefile([''], 'Xdir/tags') - call setfperm('Xdir/tags', 'r-xr--r--') - call assert_fails('helptags Xdir', 'E152:', getfperm('Xdir/tags')) - call delete('Xdir/tags') + call mkdir('Xdir/doc', 'p') + call writefile([''], 'Xdir/doc/tags') + call writefile([], 'Xdir/doc/sample.txt') + call setfperm('Xdir/doc/tags', 'r-xr--r--') + call assert_fails('helptags Xdir/doc', 'E152:', getfperm('Xdir/doc/tags')) + + let rtp = &rtp + let &rtp = 'Xdir' + helptags ALL + let &rtp = rtp + + call delete('Xdir/doc/tags') " No permission to read the help file call setfperm('Xdir/a/doc/sample.txt', '-w-------') diff --git a/src/version.c b/src/version.c index ad70c4dd0b..1008eaf1e6 100644 --- a/src/version.c +++ b/src/version.c @@ -738,6 +738,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 272, /**/ 271, /**/ From 1fa8d2c33d7290eda7dc2a94d4ec6a599a2d61dd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 17 Feb 2020 22:53:14 +0100 Subject: [PATCH 55/55] patch 8.2.0273: MS-Windows uninstall may delete wrong batch file Problem: MS-Windows uninstall may delete wrong batch file. Solution: Add specific marker in the generated batch file. (Ken Takata, closes #5654) --- src/Make_mvc.mak | 2 +- src/dosinst.c | 1 + src/dosinst.h | 3 +++ src/uninstall.c | 17 +++++------------ src/version.c | 2 ++ 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index fd7a6ab5c3..6076dc172e 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1359,7 +1359,7 @@ $(VIM): $(VIM).exe $(OUTDIR): if not exist $(OUTDIR)/nul mkdir $(OUTDIR) -CFLAGS_INST = /nologo -DNDEBUG -DWIN32 -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) $(CFLAGS_DEPR) +CFLAGS_INST = /nologo /O2 -DNDEBUG -DWIN32 -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) $(CFLAGS_DEPR) install.exe: dosinst.c dosinst.h version.h $(CC) $(CFLAGS_INST) dosinst.c kernel32.lib shell32.lib \ diff --git a/src/dosinst.c b/src/dosinst.c index 2ded88ef3b..6ce40439a0 100644 --- a/src/dosinst.c +++ b/src/dosinst.c @@ -841,6 +841,7 @@ install_bat_choice(int idx) fprintf(fd, "@echo off\n"); fprintf(fd, "rem -- Run Vim --\n"); + fprintf(fd, VIMBAT_UNINSTKEY "\n"); fprintf(fd, "\n"); fprintf(fd, "setlocal\n"); diff --git a/src/dosinst.h b/src/dosinst.h index a849dad907..c262c4224b 100644 --- a/src/dosinst.h +++ b/src/dosinst.h @@ -354,6 +354,9 @@ struct "vimtutor.bat", "vimtutor.bat", ""}, }; +/* Uninstall key for vim.bat, etc. */ +#define VIMBAT_UNINSTKEY "rem # uninstall key: " VIM_VERSION_NODOT " #" + #define ICON_COUNT 3 char *(icon_names[ICON_COUNT]) = {"gVim " VIM_VERSION_SHORT, diff --git a/src/uninstall.c b/src/uninstall.c index ef0538a140..e9a9aac327 100644 --- a/src/uninstall.c +++ b/src/uninstall.c @@ -200,8 +200,7 @@ batfile_thisversion(char *path) { FILE *fd; char line[BUFSIZE]; - char *p; - int ver_len = strlen(VIM_VERSION_NODOT); + int key_len = strlen(VIMBAT_UNINSTKEY); int found = FALSE; fd = fopen(path, "r"); @@ -209,17 +208,11 @@ batfile_thisversion(char *path) { while (fgets(line, sizeof(line), fd) != NULL) { - for (p = line; *p != 0; ++p) - // don't accept "vim60an" when looking for "vim60". - if (strnicmp(p, VIM_VERSION_NODOT, ver_len) == 0 - && !isdigit(p[ver_len]) - && !isalpha(p[ver_len])) - { - found = TRUE; - break; - } - if (found) + if (strncmp(line, VIMBAT_UNINSTKEY, key_len) == 0) + { + found = TRUE; break; + } } fclose(fd); } diff --git a/src/version.c b/src/version.c index 1008eaf1e6..2fbccd29a2 100644 --- a/src/version.c +++ b/src/version.c @@ -738,6 +738,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 273, /**/ 272, /**/