Patch 8.2.2668
Problem: Vim9: omitting "call" for "confirm()" does not give an error.
Solution: Do not recognize a modifier followed by "(".
Files: src/ex_docmd.c, src/testdir/test_vim9_builtin.vim
*** ../vim-8.2.2667/src/ex_docmd.c 2021-03-25 22:15:24.404073755 +0100
--- src/ex_docmd.c 2021-03-27 22:15:22.836193546 +0100
***************
*** 2685,2690 ****
--- 2685,2742 ----
}
/*
+ * Check for an Ex command with optional tail.
+ * If there is a match advance "pp" to the argument and return TRUE.
+ * If "noparen" is TRUE do not recognize the command followed by "(".
+ */
+ static int
+ checkforcmd_opt(
+ char_u **pp, // start of command
+ char *cmd, // name of command
+ int len, // required length
+ int noparen)
+ {
+ int i;
+
+ for (i = 0; cmd[i] != NUL; ++i)
+ if (((char_u *)cmd)[i] != (*pp)[i])
+ break;
+ if (i >= len && !isalpha((*pp)[i])
+ && (*pp)[i] != '_' && (!noparen || (*pp)[i] != '('))
+ {
+ *pp = skipwhite(*pp + i);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /*
+ * Check for an Ex command with optional tail.
+ * If there is a match advance "pp" to the argument and return TRUE.
+ */
+ int
+ checkforcmd(
+ char_u **pp, // start of command
+ char *cmd, // name of command
+ int len) // required length
+ {
+ return checkforcmd_opt(pp, cmd, len, FALSE);
+ }
+
+ /*
+ * Check for an Ex command with optional tail, not followed by "(".
+ * If there is a match advance "pp" to the argument and return TRUE.
+ */
+ static int
+ checkforcmd_noparen(
+ char_u **pp, // start of command
+ char *cmd, // name of command
+ int len) // required length
+ {
+ return checkforcmd_opt(pp, cmd, len, TRUE);
+ }
+
+ /*
* Parse and skip over command modifiers:
* - update eap->cmd
* - store flags in "cmod".
***************
*** 2770,2820 ****
switch (*p)
{
// When adding an entry, also modify cmd_exists().
! case 'a': if (!checkforcmd(&eap->cmd, "aboveleft", 3))
break;
cmod->cmod_split |= WSP_ABOVE;
continue;
! case 'b': if (checkforcmd(&eap->cmd, "belowright", 3))
{
cmod->cmod_split |= WSP_BELOW;
continue;
}
! if (checkforcmd(&eap->cmd, "browse", 3))
{
#ifdef FEAT_BROWSE_CMD
cmod->cmod_flags |= CMOD_BROWSE;
#endif
continue;
}
! if (!checkforcmd(&eap->cmd, "botright", 2))
break;
cmod->cmod_split |= WSP_BOT;
continue;
! case 'c': if (!checkforcmd(&eap->cmd, "confirm", 4))
break;
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
cmod->cmod_flags |= CMOD_CONFIRM;
#endif
continue;
! case 'k': if (checkforcmd(&eap->cmd, "keepmarks", 3))
{
cmod->cmod_flags |= CMOD_KEEPMARKS;
continue;
}
! if (checkforcmd(&eap->cmd, "keepalt", 5))
{
cmod->cmod_flags |= CMOD_KEEPALT;
continue;
}
! if (checkforcmd(&eap->cmd, "keeppatterns", 5))
{
cmod->cmod_flags |= CMOD_KEEPPATTERNS;
continue;
}
! if (!checkforcmd(&eap->cmd, "keepjumps", 5))
break;
cmod->cmod_flags |= CMOD_KEEPJUMPS;
continue;
--- 2822,2872 ----
switch (*p)
{
// When adding an entry, also modify cmd_exists().
! case 'a': if (!checkforcmd_noparen(&eap->cmd, "aboveleft", 3))
break;
cmod->cmod_split |= WSP_ABOVE;
continue;
! case 'b': if (checkforcmd_noparen(&eap->cmd, "belowright", 3))
{
cmod->cmod_split |= WSP_BELOW;
continue;
}
! if (checkforcmd_opt(&eap->cmd, "browse", 3, TRUE))
{
#ifdef FEAT_BROWSE_CMD
cmod->cmod_flags |= CMOD_BROWSE;
#endif
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "botright", 2))
break;
cmod->cmod_split |= WSP_BOT;
continue;
! case 'c': if (!checkforcmd_opt(&eap->cmd, "confirm", 4, TRUE))
break;
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
cmod->cmod_flags |= CMOD_CONFIRM;
#endif
continue;
! case 'k': if (checkforcmd_noparen(&eap->cmd, "keepmarks", 3))
{
cmod->cmod_flags |= CMOD_KEEPMARKS;
continue;
}
! if (checkforcmd_noparen(&eap->cmd, "keepalt", 5))
{
cmod->cmod_flags |= CMOD_KEEPALT;
continue;
}
! if (checkforcmd_noparen(&eap->cmd, "keeppatterns", 5))
{
cmod->cmod_flags |= CMOD_KEEPPATTERNS;
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "keepjumps", 5))
break;
cmod->cmod_flags |= CMOD_KEEPJUMPS;
continue;
***************
*** 2823,2829 ****
{
char_u *reg_pat;
! if (!checkforcmd(&p, "filter", 4)
|| *p == NUL || ends_excmd(*p))
break;
if (*p == '!')
--- 2875,2881 ----
{
char_u *reg_pat;
! if (!checkforcmd_noparen(&p, "filter", 4)
|| *p == NUL || ends_excmd(*p))
break;
if (*p == '!')
***************
*** 2857,2901 ****
}
// ":hide" and ":hide | cmd" are not modifiers
! case 'h': if (p != eap->cmd || !checkforcmd(&p, "hide", 3)
|| *p == NUL || ends_excmd(*p))
break;
eap->cmd = p;
cmod->cmod_flags |= CMOD_HIDE;
continue;
! case 'l': if (checkforcmd(&eap->cmd, "lockmarks", 3))
{
cmod->cmod_flags |= CMOD_LOCKMARKS;
continue;
}
! if (!checkforcmd(&eap->cmd, "leftabove", 5))
break;
cmod->cmod_split |= WSP_ABOVE;
continue;
! case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3))
{
cmod->cmod_flags |= CMOD_NOAUTOCMD;
continue;
}
! if (!checkforcmd(&eap->cmd, "noswapfile", 3))
break;
cmod->cmod_flags |= CMOD_NOSWAPFILE;
continue;
! case 'r': if (!checkforcmd(&eap->cmd, "rightbelow", 6))
break;
cmod->cmod_split |= WSP_BELOW;
continue;
! case 's': if (checkforcmd(&eap->cmd, "sandbox", 3))
{
cmod->cmod_flags |= CMOD_SANDBOX;
continue;
}
! if (!checkforcmd(&eap->cmd, "silent", 3))
break;
cmod->cmod_flags |= CMOD_SILENT;
if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
--- 2909,2953 ----
}
// ":hide" and ":hide | cmd" are not modifiers
! case 'h': if (p != eap->cmd || !checkforcmd_noparen(&p, "hide", 3)
|| *p == NUL || ends_excmd(*p))
break;
eap->cmd = p;
cmod->cmod_flags |= CMOD_HIDE;
continue;
! case 'l': if (checkforcmd_noparen(&eap->cmd, "lockmarks", 3))
{
cmod->cmod_flags |= CMOD_LOCKMARKS;
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "leftabove", 5))
break;
cmod->cmod_split |= WSP_ABOVE;
continue;
! case 'n': if (checkforcmd_noparen(&eap->cmd, "noautocmd", 3))
{
cmod->cmod_flags |= CMOD_NOAUTOCMD;
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "noswapfile", 3))
break;
cmod->cmod_flags |= CMOD_NOSWAPFILE;
continue;
! case 'r': if (!checkforcmd_noparen(&eap->cmd, "rightbelow", 6))
break;
cmod->cmod_split |= WSP_BELOW;
continue;
! case 's': if (checkforcmd_noparen(&eap->cmd, "sandbox", 3))
{
cmod->cmod_flags |= CMOD_SANDBOX;
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "silent", 3))
break;
cmod->cmod_flags |= CMOD_SILENT;
if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
***************
*** 2906,2912 ****
}
continue;
! case 't': if (checkforcmd(&p, "tab", 3))
{
if (!skip_only)
{
--- 2958,2964 ----
}
continue;
! case 't': if (checkforcmd_noparen(&p, "tab", 3))
{
if (!skip_only)
{
***************
*** 2928,2949 ****
eap->cmd = p;
continue;
}
! if (!checkforcmd(&eap->cmd, "topleft", 2))
break;
cmod->cmod_split |= WSP_TOP;
continue;
! case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3))
break;
cmod->cmod_flags |= CMOD_UNSILENT;
continue;
! case 'v': if (checkforcmd(&eap->cmd, "vertical", 4))
{
cmod->cmod_split |= WSP_VERT;
continue;
}
! if (checkforcmd(&eap->cmd, "vim9cmd", 4))
{
if (ends_excmd2(p, eap->cmd))
{
--- 2980,3001 ----
eap->cmd = p;
continue;
}
! if (!checkforcmd_noparen(&eap->cmd, "topleft", 2))
break;
cmod->cmod_split |= WSP_TOP;
continue;
! case 'u': if (!checkforcmd_noparen(&eap->cmd, "unsilent", 3))
break;
cmod->cmod_flags |= CMOD_UNSILENT;
continue;
! case 'v': if (checkforcmd_noparen(&eap->cmd, "vertical", 4))
{
cmod->cmod_split |= WSP_VERT;
continue;
}
! if (checkforcmd_noparen(&eap->cmd, "vim9cmd", 4))
{
if (ends_excmd2(p, eap->cmd))
{
***************
*** 2954,2960 ****
cmod->cmod_flags |= CMOD_VIM9CMD;
continue;
}
! if (!checkforcmd(&p, "verbose", 4))
break;
if (vim_isdigit(*eap->cmd))
cmod->cmod_verbose = atoi((char *)eap->cmd);
--- 3006,3012 ----
cmod->cmod_flags |= CMOD_VIM9CMD;
continue;
}
! if (!checkforcmd_noparen(&p, "verbose", 4))
break;
if (vim_isdigit(*eap->cmd))
cmod->cmod_verbose = atoi((char *)eap->cmd);
***************
*** 3252,3280 ****
}
/*
- * Check for an Ex command with optional tail.
- * If there is a match advance "pp" to the argument and return TRUE.
- */
- int
- checkforcmd(
- char_u **pp, // start of command
- char *cmd, // name of command
- int len) // required length
- {
- int i;
-
- for (i = 0; cmd[i] != NUL; ++i)
- if (((char_u *)cmd)[i] != (*pp)[i])
- break;
- if (i >= len && !isalpha((*pp)[i]) && (*pp)[i] != '_')
- {
- *pp = skipwhite(*pp + i);
- return TRUE;
- }
- return FALSE;
- }
-
- /*
* Append "cmd" to the error message in IObuff.
* Takes care of limiting the length and handling 0xa0, which would be
* invisible otherwise.
--- 3304,3309 ----
*** ../vim-8.2.2667/src/testdir/test_vim9_builtin.vim 2021-03-27 21:23:27.064153032 +0100
--- src/testdir/test_vim9_builtin.vim 2021-03-27 22:17:25.907777219 +0100
***************
*** 142,156 ****
CheckFeature browse
var lines =<< trim END
! call browse(1, 2, 3, 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 2')
lines =<< trim END
! call browse(1, 'title', 3, 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 3')
lines =<< trim END
! call browse(1, 'title', 'dir', 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 4')
enddef
--- 142,156 ----
CheckFeature browse
var lines =<< trim END
! browse(1, 2, 3, 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 2')
lines =<< trim END
! browse(1, 'title', 3, 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 3')
lines =<< trim END
! browse(1, 'title', 'dir', 4)
END
CheckDefExecAndScriptFailure(lines, 'E1174: String required for argument 4')
enddef
***************
*** 236,244 ****
CheckFeature dialog_con
endif
! assert_fails('call confirm(true)', 'E1174')
! assert_fails('call confirm("yes", true)', 'E1174')
! assert_fails('call confirm("yes", "maybe", 2, true)', 'E1174')
enddef
def Test_copy_return_type()
--- 236,244 ----
CheckFeature dialog_con
endif
! assert_fails('confirm(true)', 'E1174')
! assert_fails('confirm("yes", true)', 'E1174')
! assert_fails('confirm("yes", "maybe", 2, true)', 'E1174')
enddef
def Test_copy_return_type()
*** ../vim-8.2.2667/src/version.c 2021-03-27 22:07:21.529728904 +0100
--- src/version.c 2021-03-27 22:16:09.020035029 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2668,
/**/
--
What a wonderfully exciting cough! Do you mind if I join you?
-- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"
/// Bram Moolenaar -- Br...@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 ///