To: vim_dev@googlegroups.com Subject: Patch 8.2.2652 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2652 Problem: Vim9: can use command modifier without an effect. Solution: Give an error for a misplaced command modifier. Fix error message number. Files: src/vim9compile.c, src/ex_docmd.c, src/proto/ex_docmd.pro, src/ex_eval.c, src/testdir/test_vim9_cmd.vim, src/testdir/test_vim9_builtin.vim, src/testdir/test_vim9_disassemble.vim *** ../vim-8.2.2651/src/vim9compile.c 2021-03-25 21:12:09.902618807 +0100 --- src/vim9compile.c 2021-03-25 22:09:16.377074112 +0100 *************** *** 2142,2152 **** { isn_T *isn; ! if (cmod->cmod_flags != 0 ! || cmod->cmod_split != 0 ! || cmod->cmod_verbose != 0 ! || cmod->cmod_tab != 0 ! || cmod->cmod_filter_regmatch.regprog != NULL) { cctx->ctx_has_cmdmod = TRUE; --- 2142,2148 ---- { isn_T *isn; ! if (has_cmdmod(cmod)) { cctx->ctx_has_cmdmod = TRUE; *************** *** 2172,2193 **** return OK; } ! /* ! * If an ISN_CMDMOD was just generated drop it. ! */ ! static void ! drop_cmdmod(cctx_T *cctx) { garray_T *instr = &cctx->ctx_instr; - // Drop any CMDMOD instruction if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD) { ! --instr->ga_len; ! cctx->ctx_has_cmdmod = FALSE; } } /* --- 2168,2186 ---- return OK; } ! static int ! misplaced_cmdmod(cctx_T *cctx) { garray_T *instr = &cctx->ctx_instr; if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD) { ! emsg(_(e_misplaced_command_modifier)); ! return TRUE; } + return FALSE; } /* *************** *** 7147,7153 **** garray_T *instr = &cctx->ctx_instr; isn_T *isn; ! drop_cmdmod(cctx); if (scope == NULL || scope->se_type != IF_SCOPE) { emsg(_(e_endif_without_if)); --- 7140,7148 ---- garray_T *instr = &cctx->ctx_instr; isn_T *isn; ! if (misplaced_cmdmod(cctx)) ! return NULL; ! if (scope == NULL || scope->se_type != IF_SCOPE) { emsg(_(e_endif_without_if)); *************** *** 7393,7399 **** forscope_T *forscope; isn_T *isn; ! drop_cmdmod(cctx); if (scope == NULL || scope->se_type != FOR_SCOPE) { --- 7388,7395 ---- forscope_T *forscope; isn_T *isn; ! if (misplaced_cmdmod(cctx)) ! return NULL; if (scope == NULL || scope->se_type != FOR_SCOPE) { *************** *** 7479,7485 **** scope_T *scope = cctx->ctx_scope; garray_T *instr = &cctx->ctx_instr; ! drop_cmdmod(cctx); if (scope == NULL || scope->se_type != WHILE_SCOPE) { emsg(_(e_while)); --- 7475,7482 ---- scope_T *scope = cctx->ctx_scope; garray_T *instr = &cctx->ctx_instr; ! if (misplaced_cmdmod(cctx)) ! return NULL; if (scope == NULL || scope->se_type != WHILE_SCOPE) { emsg(_(e_while)); *************** *** 7644,7649 **** --- 7641,7649 ---- scope_T *try_scope; scope_T *scope; + if (misplaced_cmdmod(cctx)) + return NULL; + // scope that holds the jumps that go to catch/finally/endtry try_scope = new_scope(cctx, TRY_SCOPE); if (try_scope == NULL) *************** *** 7684,7689 **** --- 7684,7692 ---- char_u *p; isn_T *isn; + if (misplaced_cmdmod(cctx)) + return NULL; + // end block scope from :try or :catch if (scope != NULL && scope->se_type == BLOCK_SCOPE) compile_endblock(cctx); *************** *** 7796,7801 **** --- 7799,7807 ---- isn_T *isn; int this_instr; + if (misplaced_cmdmod(cctx)) + return NULL; + // end block scope from :try or :catch if (scope != NULL && scope->se_type == BLOCK_SCOPE) compile_endblock(cctx); *************** *** 7854,7859 **** --- 7860,7868 ---- garray_T *instr = &cctx->ctx_instr; isn_T *try_isn; + if (misplaced_cmdmod(cctx)) + return NULL; + // end block scope from :catch or :finally if (scope != NULL && scope->se_type == BLOCK_SCOPE) compile_endblock(cctx); *** ../vim-8.2.2651/src/ex_docmd.c 2021-03-20 14:59:58.508414399 +0100 --- src/ex_docmd.c 2021-03-25 22:01:28.754365727 +0100 *************** *** 2970,2975 **** --- 2970,3002 ---- } /* + * Return TRUE if "cmod" has anything set. + */ + int + has_cmdmod(cmdmod_T *cmod) + { + return cmod->cmod_flags != 0 + || cmod->cmod_split != 0 + || cmod->cmod_verbose != 0 + || cmod->cmod_tab != 0 + || cmod->cmod_filter_regmatch.regprog != NULL; + } + + /* + * If Vim9 script and "cmdmod" has anything set give an error and return TRUE. + */ + int + cmdmod_error(void) + { + if (in_vim9script() && has_cmdmod(&cmdmod)) + { + emsg(_(e_misplaced_command_modifier)); + return TRUE; + } + return FALSE; + } + + /* * Apply the command modifiers. Saves current state in "cmdmod", call * undo_cmdmod() later. */ *** ../vim-8.2.2651/src/proto/ex_docmd.pro 2021-03-14 13:21:31.785065163 +0100 --- src/proto/ex_docmd.pro 2021-03-25 22:01:34.286350222 +0100 *************** *** 8,13 **** --- 8,15 ---- char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie); char *ex_errmsg(char *msg, char_u *arg); int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, int skip_only); + int has_cmdmod(cmdmod_T *cmod); + int cmdmod_error(void); void apply_cmdmod(cmdmod_T *cmod); void undo_cmdmod(cmdmod_T *cmod); int parse_cmd_address(exarg_T *eap, char **errormsg, int silent); *** ../vim-8.2.2651/src/ex_eval.c 2021-02-26 22:21:19.082675454 +0100 --- src/ex_eval.c 2021-03-25 22:08:59.889119166 +0100 *************** *** 1011,1016 **** --- 1011,1018 ---- { cstack_T *cstack = eap->cstack; + if (cmdmod_error()) + return; did_endif = TRUE; if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] *************** *** 1314,1319 **** --- 1316,1324 ---- int csf; int fl; + if (cmdmod_error()) + return; + if (eap->cmdidx == CMD_endwhile) { err = e_while; *************** *** 1539,1544 **** --- 1544,1552 ---- int skip; cstack_T *cstack = eap->cstack; + if (cmdmod_error()) + return; + if (cstack->cs_idx == CSTACK_LEN - 1) eap->errmsg = _("E601: :try nesting too deep"); else *************** *** 1617,1622 **** --- 1625,1633 ---- cstack_T *cstack = eap->cstack; char_u *pat; + if (cmdmod_error()) + return; + if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) { eap->errmsg = _(e_catch); *************** *** 1777,1782 **** --- 1788,1796 ---- int pending = CSTP_NONE; cstack_T *cstack = eap->cstack; + if (cmdmod_error()) + return; + if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) eap->errmsg = _(e_finally); else *************** *** 1906,1911 **** --- 1920,1928 ---- void *rettv = NULL; cstack_T *cstack = eap->cstack; + if (cmdmod_error()) + return; + if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0) eap->errmsg = _(e_no_endtry); else *** ../vim-8.2.2651/src/testdir/test_vim9_cmd.vim 2021-03-24 20:08:08.540745895 +0100 --- src/testdir/test_vim9_cmd.vim 2021-03-25 22:09:42.493002797 +0100 *************** *** 797,802 **** --- 797,851 ---- bwipe! enddef + def Test_useless_command_modifier() + g:maybe = true + var lines =<< trim END + if g:maybe + silent endif + END + CheckDefAndScriptFailure(lines, 'E1176:', 2) + + lines =<< trim END + for i in [0] + silent endfor + END + CheckDefAndScriptFailure(lines, 'E1176:', 2) + + lines =<< trim END + while g:maybe + silent endwhile + END + CheckDefAndScriptFailure(lines, 'E1176:', 2) + + lines =<< trim END + silent try + finally + endtry + END + CheckDefAndScriptFailure(lines, 'E1176:', 1) + + lines =<< trim END + try + silent catch + endtry + END + CheckDefAndScriptFailure(lines, 'E1176:', 2) + + lines =<< trim END + try + silent finally + endtry + END + CheckDefAndScriptFailure(lines, 'E1176:', 2) + + lines =<< trim END + try + finally + silent endtry + END + CheckDefAndScriptFailure(lines, 'E1176:', 3) + enddef + def Test_eval_command() var from = 3 var to = 5 *** ../vim-8.2.2651/src/testdir/test_vim9_builtin.vim 2021-03-22 22:21:22.781399262 +0100 --- src/testdir/test_vim9_builtin.vim 2021-03-25 22:12:34.912533393 +0100 *************** *** 247,253 **** def Test_exepath() CheckDefExecFailure(['echo exepath(true)'], 'E1174:') CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo exepath("")'], 'E1142:') enddef def Test_expand() --- 247,253 ---- def Test_exepath() CheckDefExecFailure(['echo exepath(true)'], 'E1174:') CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo exepath("")'], 'E1175:') enddef def Test_expand() *************** *** 406,418 **** def Test_finddir() CheckDefExecFailure(['echo finddir(true)'], 'E1174:') CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo finddir("")'], 'E1142:') enddef def Test_findfile() CheckDefExecFailure(['echo findfile(true)'], 'E1174:') CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo findfile("")'], 'E1142:') enddef def Test_flattennew() --- 406,418 ---- def Test_finddir() CheckDefExecFailure(['echo finddir(true)'], 'E1174:') CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo finddir("")'], 'E1175:') enddef def Test_findfile() CheckDefExecFailure(['echo findfile(true)'], 'E1174:') CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:') ! CheckDefExecFailure(['echo findfile("")'], 'E1175:') enddef def Test_flattennew() *** ../vim-8.2.2651/src/testdir/test_vim9_disassemble.vim 2021-03-25 21:12:09.902618807 +0100 --- src/testdir/test_vim9_disassemble.vim 2021-03-25 22:13:42.944348686 +0100 *************** *** 1903,1909 **** def s:SilentIf() silent if 4 == g:five silent elseif 4 == g:five ! silent endif enddef def Test_silent_if() --- 1903,1909 ---- def s:SilentIf() silent if 4 == g:five silent elseif 4 == g:five ! endif enddef def Test_silent_if() *************** *** 1924,1937 **** '\d\+ COMPAREANY ==\_s*' .. '\d\+ CMDMOD_REV\_s*' .. '\d\+ JUMP_IF_FALSE -> \d\+\_s*' .. ! 'silent endif\_s*' .. '\d\+ RETURN 0', res) enddef def s:SilentFor() silent for i in [0] ! silent endfor enddef def Test_silent_for() --- 1924,1937 ---- '\d\+ COMPAREANY ==\_s*' .. '\d\+ CMDMOD_REV\_s*' .. '\d\+ JUMP_IF_FALSE -> \d\+\_s*' .. ! 'endif\_s*' .. '\d\+ RETURN 0', res) enddef def s:SilentFor() silent for i in [0] ! endfor enddef def Test_silent_for() *************** *** 1945,1951 **** '\d CMDMOD_REV\_s*' .. '5 FOR $0 -> 8\_s*' .. '\d STORE $1\_s*' .. ! 'silent endfor\_s*' .. '\d JUMP -> 5\_s*' .. '8 DROP\_s*' .. '\d RETURN 0\_s*', --- 1945,1951 ---- '\d CMDMOD_REV\_s*' .. '5 FOR $0 -> 8\_s*' .. '\d STORE $1\_s*' .. ! 'endfor\_s*' .. '\d JUMP -> 5\_s*' .. '8 DROP\_s*' .. '\d RETURN 0\_s*', *************** *** 1954,1960 **** def s:SilentWhile() silent while g:not ! silent endwhile enddef def Test_silent_while() --- 1954,1960 ---- def s:SilentWhile() silent while g:not ! endwhile enddef def Test_silent_while() *************** *** 1967,1973 **** '\d CMDMOD_REV\_s*' .. '\d JUMP_IF_FALSE -> 6\_s*' .. ! 'silent endwhile\_s*' .. '\d JUMP -> 0\_s*' .. '6 RETURN 0\_s*', res) --- 1967,1973 ---- '\d CMDMOD_REV\_s*' .. '\d JUMP_IF_FALSE -> 6\_s*' .. ! 'endwhile\_s*' .. '\d JUMP -> 0\_s*' .. '6 RETURN 0\_s*', res) *** ../vim-8.2.2651/src/version.c 2021-03-25 21:12:09.902618807 +0100 --- src/version.c 2021-03-25 21:48:20.000683734 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2652, /**/ -- How To Keep A Healthy Level Of Insanity: 7. Finish all your sentences with "in accordance with the prophecy". /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///