Patch 8.1.0281
Problem: Parsing command modifiers is not separated.
Solution: Move command modifier parsing to a separate function.
Files: src/ex_docmd.c, src/proto/ex_docmd.pro, src/ex_cmds.h,
src/globals.h, src/feature.h
*** ../vim-8.1.0280/src/ex_docmd.c 2018-08-10 23:13:07.934024645 +0200
--- src/ex_docmd.c 2018-08-13 23:27:03.980298529 +0200
***************
*** 1709,1721 ****
char_u *errormsg = NULL; /* error message */
char_u *after_modifier = NULL;
exarg_T ea; /* Ex command arguments */
- long verbose_save = -1;
int save_msg_scroll = msg_scroll;
- int save_msg_silent = -1;
- int did_esilent = 0;
- #ifdef HAVE_SANDBOX
- int did_sandbox = FALSE;
- #endif
cmdmod_T save_cmdmod;
int ni; /* set when Not
Implemented */
char_u *cmd;
--- 1709,1715 ----
***************
*** 1742,1748 ****
* recursive calls.
*/
save_cmdmod = cmdmod;
- vim_memset(&cmdmod, 0, sizeof(cmdmod));
/* "#!anything" is handled like a comment. */
if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!')
--- 1736,1741 ----
***************
*** 1750,1977 ****
/*
* Repeat until no more command modifiers are found.
*/
ea.cmd = *cmdlinep;
! for (;;)
! {
! /*
! * 1. Skip comment lines and leading white space and colons.
! */
! while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':')
! ++ea.cmd;
!
! /* in ex mode, an empty line works like :+ */
! if (*ea.cmd == NUL && exmode_active
! && (getline_equal(fgetline, cookie, getexmodeline)
! || getline_equal(fgetline, cookie, getexline))
! && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
! {
! ea.cmd = (char_u *)"+";
! ex_pressedreturn = TRUE;
! }
!
! /* ignore comment and empty lines */
! if (*ea.cmd == '"')
! goto doend;
! if (*ea.cmd == NUL)
! {
! ex_pressedreturn = TRUE;
! goto doend;
! }
!
! /*
! * 2. Handle command modifiers.
! */
! p = skip_range(ea.cmd, NULL);
! switch (*p)
! {
! /* When adding an entry, also modify cmd_exists(). */
! case 'a': if (!checkforcmd(&ea.cmd, "aboveleft", 3))
! break;
! cmdmod.split |= WSP_ABOVE;
! continue;
!
! case 'b': if (checkforcmd(&ea.cmd, "belowright", 3))
! {
! cmdmod.split |= WSP_BELOW;
! continue;
! }
! if (checkforcmd(&ea.cmd, "browse", 3))
! {
! #ifdef FEAT_BROWSE_CMD
! cmdmod.browse = TRUE;
! #endif
! continue;
! }
! if (!checkforcmd(&ea.cmd, "botright", 2))
! break;
! cmdmod.split |= WSP_BOT;
! continue;
!
! case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4))
! break;
! #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
! cmdmod.confirm = TRUE;
! #endif
! continue;
!
! case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3))
! {
! cmdmod.keepmarks = TRUE;
! continue;
! }
! if (checkforcmd(&ea.cmd, "keepalt", 5))
! {
! cmdmod.keepalt = TRUE;
! continue;
! }
! if (checkforcmd(&ea.cmd, "keeppatterns", 5))
! {
! cmdmod.keeppatterns = TRUE;
! continue;
! }
! if (!checkforcmd(&ea.cmd, "keepjumps", 5))
! break;
! cmdmod.keepjumps = TRUE;
! continue;
!
! case 'f': /* only accept ":filter {pat} cmd" */
! {
! char_u *reg_pat;
!
! if (!checkforcmd(&p, "filter", 4)
! || *p == NUL || ends_excmd(*p))
! break;
! if (*p == '!')
! {
! cmdmod.filter_force = TRUE;
! p = skipwhite(p + 1);
! if (*p == NUL || ends_excmd(*p))
! break;
! }
! p = skip_vimgrep_pat(p, ®_pat, NULL);
! if (p == NULL || *p == NUL)
! break;
! cmdmod.filter_regmatch.regprog =
! vim_regcomp(reg_pat, RE_MAGIC);
! if (cmdmod.filter_regmatch.regprog == NULL)
! break;
! ea.cmd = p;
! continue;
! }
!
! /* ":hide" and ":hide | cmd" are not modifiers */
! case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3)
! || *p == NUL || ends_excmd(*p))
! break;
! ea.cmd = p;
! cmdmod.hide = TRUE;
! continue;
!
! case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3))
! {
! cmdmod.lockmarks = TRUE;
! continue;
! }
!
! if (!checkforcmd(&ea.cmd, "leftabove", 5))
! break;
! cmdmod.split |= WSP_ABOVE;
! continue;
!
! case 'n': if (checkforcmd(&ea.cmd, "noautocmd", 3))
! {
! if (cmdmod.save_ei == NULL)
! {
! /* Set 'eventignore' to "all". Restore the
! * existing option value later. */
! cmdmod.save_ei = vim_strsave(p_ei);
! set_string_option_direct((char_u *)"ei", -1,
! (char_u *)"all", OPT_FREE, SID_NONE);
! }
! continue;
! }
! if (!checkforcmd(&ea.cmd, "noswapfile", 3))
! break;
! cmdmod.noswapfile = TRUE;
! continue;
!
! case 'r': if (!checkforcmd(&ea.cmd, "rightbelow", 6))
! break;
! cmdmod.split |= WSP_BELOW;
! continue;
!
! case 's': if (checkforcmd(&ea.cmd, "sandbox", 3))
! {
! #ifdef HAVE_SANDBOX
! if (!did_sandbox)
! ++sandbox;
! did_sandbox = TRUE;
#endif
! continue;
! }
! if (!checkforcmd(&ea.cmd, "silent", 3))
! break;
! if (save_msg_silent == -1)
! save_msg_silent = msg_silent;
! ++msg_silent;
! if (*ea.cmd == '!' && !VIM_ISWHITE(ea.cmd[-1]))
! {
! /* ":silent!", but not "silent !cmd" */
! ea.cmd = skipwhite(ea.cmd + 1);
! ++emsg_silent;
! ++did_esilent;
! }
! continue;
!
! case 't': if (checkforcmd(&p, "tab", 3))
! {
! long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS,
! ea.skip, FALSE, 1);
! if (tabnr == MAXLNUM)
! cmdmod.tab = tabpage_index(curtab) + 1;
! else
! {
! if (tabnr < 0 || tabnr > LAST_TAB_NR)
! {
! errormsg = (char_u *)_(e_invrange);
! goto doend;
! }
! cmdmod.tab = tabnr + 1;
! }
! ea.cmd = p;
! continue;
! }
! if (!checkforcmd(&ea.cmd, "topleft", 2))
! break;
! cmdmod.split |= WSP_TOP;
! continue;
!
! case 'u': if (!checkforcmd(&ea.cmd, "unsilent", 3))
! break;
! if (save_msg_silent == -1)
! save_msg_silent = msg_silent;
! msg_silent = 0;
! continue;
- case 'v': if (checkforcmd(&ea.cmd, "vertical", 4))
- {
- cmdmod.split |= WSP_VERT;
- continue;
- }
- if (!checkforcmd(&p, "verbose", 4))
- break;
- if (verbose_save < 0)
- verbose_save = p_verbose;
- if (vim_isdigit(*ea.cmd))
- p_verbose = atoi((char *)ea.cmd);
- else
- p_verbose = 1;
- ea.cmd = p;
- continue;
- }
- break;
- }
after_modifier = ea.cmd;
#ifdef FEAT_EVAL
--- 1743,1760 ----
/*
* Repeat until no more command modifiers are found.
+ * The "ea" structure holds the arguments that can be used.
*/
ea.cmd = *cmdlinep;
! ea.cmdlinep = cmdlinep;
! ea.getline = fgetline;
! ea.cookie = cookie;
! #ifdef FEAT_EVAL
! ea.cstack = cstack;
#endif
! if (parse_command_modifiers(&ea, &errormsg) == FAIL)
! goto doend;
after_modifier = ea.cmd;
#ifdef FEAT_EVAL
***************
*** 2688,2712 ****
/* The :try command saves the emsg_silent flag, reset it here when
* ":silent! try" was used, it should only apply to :try itself. */
! if (ea.cmdidx == CMD_try && did_esilent > 0)
{
! emsg_silent -= did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
! did_esilent = 0;
}
/*
* 7. Execute the command.
- *
- * The "ea" structure holds the arguments that can be used.
*/
- ea.cmdlinep = cmdlinep;
- ea.getline = fgetline;
- ea.cookie = cookie;
- #ifdef FEAT_EVAL
- ea.cstack = cstack;
- #endif
#ifdef FEAT_USR_CMDS
if (IS_USER_CMDIDX(ea.cmdidx))
--- 2471,2487 ----
/* The :try command saves the emsg_silent flag, reset it here when
* ":silent! try" was used, it should only apply to :try itself. */
! if (ea.cmdidx == CMD_try && ea.did_esilent > 0)
{
! emsg_silent -= ea.did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
! ea.did_esilent = 0;
}
/*
* 7. Execute the command.
*/
#ifdef FEAT_USR_CMDS
if (IS_USER_CMDIDX(ea.cmdidx))
***************
*** 2775,2782 ****
? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
#endif
! if (verbose_save >= 0)
! p_verbose = verbose_save;
if (cmdmod.save_ei != NULL)
{
--- 2550,2557 ----
? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
#endif
! if (ea.verbose_save >= 0)
! p_verbose = ea.verbose_save;
if (cmdmod.save_ei != NULL)
{
***************
*** 2791,2803 ****
cmdmod = save_cmdmod;
! if (save_msg_silent != -1)
{
/* messages could be enabled for a serious error, need to check if the
* counters don't become negative */
! if (!did_emsg || msg_silent > save_msg_silent)
! msg_silent = save_msg_silent;
! emsg_silent -= did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
/* Restore msg_scroll, it's set by file I/O commands, even when no
--- 2566,2578 ----
cmdmod = save_cmdmod;
! if (ea.save_msg_silent != -1)
{
/* messages could be enabled for a serious error, need to check if the
* counters don't become negative */
! if (!did_emsg || msg_silent > ea.save_msg_silent)
! msg_silent = ea.save_msg_silent;
! emsg_silent -= ea.did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
/* Restore msg_scroll, it's set by file I/O commands, even when no
***************
*** 2811,2817 ****
}
#ifdef HAVE_SANDBOX
! if (did_sandbox)
--sandbox;
#endif
--- 2586,2592 ----
}
#ifdef HAVE_SANDBOX
! if (ea.did_sandbox)
--sandbox;
#endif
***************
*** 2829,2834 ****
--- 2604,2853 ----
#endif
/*
+ * Parse and skip over command modifiers:
+ * - update eap->cmd
+ * - store flags in "cmdmod".
+ * - Set ex_pressedreturn for an empty command line.
+ * - set msg_silent for ":silent"
+ * - set p_verbose for ":verbose"
+ * - Increment "sandbox" for ":sandbox"
+ * Return FAIL when the command is not to be executed.
+ * May set "errormsg" to an error message.
+ */
+ int
+ parse_command_modifiers(exarg_T *eap, char_u **errormsg)
+ {
+ char_u *p;
+
+ vim_memset(&cmdmod, 0, sizeof(cmdmod));
+ eap->verbose_save = -1;
+ eap->save_msg_silent = -1;
+
+ for (;;)
+ {
+ /*
+ * 1. Skip comment lines and leading white space and colons.
+ */
+ while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':')
+ ++eap->cmd;
+
+ /* in ex mode, an empty line works like :+ */
+ if (*eap->cmd == NUL && exmode_active
+ && (getline_equal(eap->getline, eap->cookie, getexmodeline)
+ || getline_equal(eap->getline, eap->cookie, getexline))
+ && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+ {
+ eap->cmd = (char_u *)"+";
+ ex_pressedreturn = TRUE;
+ }
+
+ /* ignore comment and empty lines */
+ if (*eap->cmd == '"')
+ return FAIL;
+ if (*eap->cmd == NUL)
+ {
+ ex_pressedreturn = TRUE;
+ return FAIL;
+ }
+
+ /*
+ * 2. Handle command modifiers.
+ */
+ p = skip_range(eap->cmd, NULL);
+ switch (*p)
+ {
+ /* When adding an entry, also modify cmd_exists(). */
+ case 'a': if (!checkforcmd(&eap->cmd, "aboveleft", 3))
+ break;
+ cmdmod.split |= WSP_ABOVE;
+ continue;
+
+ case 'b': if (checkforcmd(&eap->cmd, "belowright", 3))
+ {
+ cmdmod.split |= WSP_BELOW;
+ continue;
+ }
+ if (checkforcmd(&eap->cmd, "browse", 3))
+ {
+ #ifdef FEAT_BROWSE_CMD
+ cmdmod.browse = TRUE;
+ #endif
+ continue;
+ }
+ if (!checkforcmd(&eap->cmd, "botright", 2))
+ break;
+ cmdmod.split |= WSP_BOT;
+ continue;
+
+ case 'c': if (!checkforcmd(&eap->cmd, "confirm", 4))
+ break;
+ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+ cmdmod.confirm = TRUE;
+ #endif
+ continue;
+
+ case 'k': if (checkforcmd(&eap->cmd, "keepmarks", 3))
+ {
+ cmdmod.keepmarks = TRUE;
+ continue;
+ }
+ if (checkforcmd(&eap->cmd, "keepalt", 5))
+ {
+ cmdmod.keepalt = TRUE;
+ continue;
+ }
+ if (checkforcmd(&eap->cmd, "keeppatterns", 5))
+ {
+ cmdmod.keeppatterns = TRUE;
+ continue;
+ }
+ if (!checkforcmd(&eap->cmd, "keepjumps", 5))
+ break;
+ cmdmod.keepjumps = TRUE;
+ continue;
+
+ case 'f': /* only accept ":filter {pat} cmd" */
+ {
+ char_u *reg_pat;
+
+ if (!checkforcmd(&p, "filter", 4)
+ || *p == NUL || ends_excmd(*p))
+ break;
+ if (*p == '!')
+ {
+ cmdmod.filter_force = TRUE;
+ p = skipwhite(p + 1);
+ if (*p == NUL || ends_excmd(*p))
+ break;
+ }
+ p = skip_vimgrep_pat(p, ®_pat, NULL);
+ if (p == NULL || *p == NUL)
+ break;
+ cmdmod.filter_regmatch.regprog =
+ vim_regcomp(reg_pat, RE_MAGIC);
+ if (cmdmod.filter_regmatch.regprog == NULL)
+ break;
+ eap->cmd = p;
+ continue;
+ }
+
+ /* ":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;
+ cmdmod.hide = TRUE;
+ continue;
+
+ case 'l': if (checkforcmd(&eap->cmd, "lockmarks", 3))
+ {
+ cmdmod.lockmarks = TRUE;
+ continue;
+ }
+
+ if (!checkforcmd(&eap->cmd, "leftabove", 5))
+ break;
+ cmdmod.split |= WSP_ABOVE;
+ continue;
+
+ case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3))
+ {
+ if (cmdmod.save_ei == NULL)
+ {
+ /* Set 'eventignore' to "all". Restore the
+ * existing option value later. */
+ cmdmod.save_ei = vim_strsave(p_ei);
+ set_string_option_direct((char_u *)"ei", -1,
+ (char_u *)"all", OPT_FREE, SID_NONE);
+ }
+ continue;
+ }
+ if (!checkforcmd(&eap->cmd, "noswapfile", 3))
+ break;
+ cmdmod.noswapfile = TRUE;
+ continue;
+
+ case 'r': if (!checkforcmd(&eap->cmd, "rightbelow", 6))
+ break;
+ cmdmod.split |= WSP_BELOW;
+ continue;
+
+ case 's': if (checkforcmd(&eap->cmd, "sandbox", 3))
+ {
+ #ifdef HAVE_SANDBOX
+ if (!eap->did_sandbox)
+ ++sandbox;
+ eap->did_sandbox = TRUE;
+ #endif
+ continue;
+ }
+ if (!checkforcmd(&eap->cmd, "silent", 3))
+ break;
+ if (eap->save_msg_silent == -1)
+ eap->save_msg_silent = msg_silent;
+ ++msg_silent;
+ if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
+ {
+ /* ":silent!", but not "silent !cmd" */
+ eap->cmd = skipwhite(eap->cmd + 1);
+ ++emsg_silent;
+ ++eap->did_esilent;
+ }
+ continue;
+
+ case 't': if (checkforcmd(&p, "tab", 3))
+ {
+ long tabnr = get_address(eap, &eap->cmd, ADDR_TABS,
+ eap->skip, FALSE,
1);
+ if (tabnr == MAXLNUM)
+ cmdmod.tab = tabpage_index(curtab) + 1;
+ else
+ {
+ if (tabnr < 0 || tabnr > LAST_TAB_NR)
+ {
+ *errormsg = (char_u *)_(e_invrange);
+ return FAIL;
+ }
+ cmdmod.tab = tabnr + 1;
+ }
+ eap->cmd = p;
+ continue;
+ }
+ if (!checkforcmd(&eap->cmd, "topleft", 2))
+ break;
+ cmdmod.split |= WSP_TOP;
+ continue;
+
+ case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3))
+ break;
+ if (eap->save_msg_silent == -1)
+ eap->save_msg_silent = msg_silent;
+ msg_silent = 0;
+ continue;
+
+ case 'v': if (checkforcmd(&eap->cmd, "vertical", 4))
+ {
+ cmdmod.split |= WSP_VERT;
+ continue;
+ }
+ if (!checkforcmd(&p, "verbose", 4))
+ break;
+ if (eap->verbose_save < 0)
+ eap->verbose_save = p_verbose;
+ if (vim_isdigit(*eap->cmd))
+ p_verbose = atoi((char *)eap->cmd);
+ else
+ p_verbose = 1;
+ eap->cmd = p;
+ continue;
+ }
+ break;
+ }
+
+ return OK;
+ }
+
+ /*
* Parse the address range, if any, in "eap".
* Return FAIL and set "errormsg" or return OK.
*/
*** ../vim-8.1.0280/src/proto/ex_docmd.pro 2018-08-10 23:13:07.934024645
+0200
--- src/proto/ex_docmd.pro 2018-08-13 23:24:18.797373050 +0200
***************
*** 4,9 ****
--- 4,10 ----
int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void
*cookie, int flags);
int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u
*(*func)(int, void *, int));
void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
+ int parse_command_modifiers(exarg_T *eap, char_u **errormsg);
int parse_cmd_address(exarg_T *eap, char_u **errormsg);
int checkforcmd(char_u **pp, char *cmd, int len);
int modifier_len(char_u *cmd);
*** ../vim-8.1.0280/src/ex_cmds.h 2018-07-10 19:39:14.994973018 +0200
--- src/ex_cmds.h 2018-08-13 23:25:36.236870329 +0200
***************
*** 1792,1797 ****
--- 1792,1803 ----
#ifdef FEAT_EVAL
struct condstack *cstack; /* condition stack for ":if" etc. */
#endif
+ long verbose_save; // saved value of p_verbose
+ int save_msg_silent; // saved value of msg_silent
+ int did_esilent; // how many times emsg_silent was
incremented
+ #ifdef HAVE_SANDBOX
+ int did_sandbox; // when TRUE did ++sandbox
+ #endif
};
#define FORCE_BIN 1 /* ":edit ++bin file" */
*** ../vim-8.1.0280/src/globals.h 2018-08-11 16:40:39.064311995 +0200
--- src/globals.h 2018-08-13 23:18:14.323704509 +0200
***************
*** 678,685 ****
* changed, no buffer can be deleted and
* current directory can't be changed.
* Used for SwapExists et al. */
! #ifdef FEAT_EVAL
! # define HAVE_SANDBOX
EXTERN int sandbox INIT(= 0);
/* Non-zero when evaluating an expression in a
* "sandbox". Several things are not allowed
--- 678,684 ----
* changed, no buffer can be deleted and
* current directory can't be changed.
* Used for SwapExists et al. */
! #ifdef HAVE_SANDBOX
EXTERN int sandbox INIT(= 0);
/* Non-zero when evaluating an expression in a
* "sandbox". Several things are not allowed
*** ../vim-8.1.0280/src/feature.h 2018-07-29 16:09:14.644945560 +0200
--- src/feature.h 2018-08-13 23:19:07.623368124 +0200
***************
*** 355,360 ****
--- 355,364 ----
# endif
#endif
+ #ifdef FEAT_EVAL
+ # define HAVE_SANDBOX
+ #endif
+
/*
* +profile Profiling for functions and scripts.
*/
*** ../vim-8.1.0280/src/version.c 2018-08-13 22:54:31.456665135 +0200
--- src/version.c 2018-08-13 23:04:38.032484283 +0200
***************
*** 796,797 ****
--- 796,799 ----
{ /* Add new patch number below this line */
+ /**/
+ 281,
/**/
--
Violators can be fined, arrested or jailed for making ugly faces at a dog.
[real standing law in Oklahoma, United States of America]
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.