Patch 8.2.3716
Problem: Vim9: range without a command is not compiled.
Solution: Add the ISN_EXECRANGE byte code.
Files: src/ex_docmd.c, src/proto/
ex_docmd.pro, src/vim9compile.c,
src/vim9execute.c, src/vim9.h,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.3715/src/ex_docmd.c 2021-11-29 20:39:06.674101624 +0000
--- src/ex_docmd.c 2021-12-01 14:50:35.384211034 +0000
***************
*** 1977,2019 ****
*/
if (ea.skip) // skip this if inside :if
goto doend;
! if ((*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2))
! #ifdef FEAT_EVAL
! && !vim9script
! #endif
! )
! {
! ea.cmdidx = CMD_print;
! ea.argt = EX_RANGE+EX_COUNT+EX_TRLBAR;
! if ((errormsg = invalid_range(&ea)) == NULL)
! {
! correct_range(&ea);
! ex_print(&ea);
! }
! }
! else if (ea.addr_count != 0)
! {
! if (ea.line2 > curbuf->b_ml.ml_line_count)
! {
! // With '-' in 'cpoptions' a line number past the file is an
! // error, otherwise put it at the end of the file.
! if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
! ea.line2 = -1;
! else
! ea.line2 = curbuf->b_ml.ml_line_count;
! }
!
! if (ea.line2 < 0)
! errormsg = _(e_invalid_range);
! else
! {
! if (ea.line2 == 0)
! curwin->w_cursor.lnum = 1;
! else
! curwin->w_cursor.lnum = ea.line2;
! beginline(BL_SOL | BL_FIX);
! }
! }
goto doend;
}
--- 1977,1983 ----
*/
if (ea.skip) // skip this if inside :if
goto doend;
! errormsg = ex_range_without_command(&ea);
goto doend;
}
***************
*** 2708,2713 ****
--- 2672,2726 ----
}
/*
+ * Handle a range without a command.
+ * Returns an error message on failure.
+ */
+ char *
+ ex_range_without_command(exarg_T *eap)
+ {
+ char *errormsg = NULL;
+
+ if ((*eap->cmd == '|' || (exmode_active && eap->line1 != eap->line2))
+ #ifdef FEAT_EVAL
+ && !in_vim9script()
+ #endif
+ )
+ {
+ eap->cmdidx = CMD_print;
+ eap->argt = EX_RANGE+EX_COUNT+EX_TRLBAR;
+ if ((errormsg = invalid_range(eap)) == NULL)
+ {
+ correct_range(eap);
+ ex_print(eap);
+ }
+ }
+ else if (eap->addr_count != 0)
+ {
+ if (eap->line2 > curbuf->b_ml.ml_line_count)
+ {
+ // With '-' in 'cpoptions' a line number past the file is an
+ // error, otherwise put it at the end of the file.
+ if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
+ eap->line2 = -1;
+ else
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ }
+
+ if (eap->line2 < 0)
+ errormsg = _(e_invalid_range);
+ else
+ {
+ if (eap->line2 == 0)
+ curwin->w_cursor.lnum = 1;
+ else
+ curwin->w_cursor.lnum = eap->line2;
+ beginline(BL_SOL | BL_FIX);
+ }
+ }
+ return errormsg;
+ }
+
+ /*
* 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 "(".
*** ../vim-8.2.3715/src/proto/
ex_docmd.pro 2021-08-10 18:52:57.474235537 +0100
--- src/proto/
ex_docmd.pro 2021-12-01 14:50:06.320314008 +0000
***************
*** 7,12 ****
--- 7,13 ----
void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char *ex_errmsg(char *msg, char_u *arg);
+ char *ex_range_without_command(exarg_T *eap);
int checkforcmd(char_u **pp, char *cmd, int len);
int checkforcmd_noparen(char_u **pp, char *cmd, int len);
int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, int skip_only);
***************
*** 22,28 ****
void f_fullcommand(typval_T *argvars, typval_T *rettv);
cmdidx_T excmd_get_cmdidx(char_u *cmd, int len);
long excmd_get_argt(cmdidx_T idx);
! char_u *skip_range(char_u *cmd, int skip_star, int *ctx);
void ex_ni(exarg_T *eap);
int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
void separate_nextcmd(exarg_T *eap);
--- 23,29 ----
void f_fullcommand(typval_T *argvars, typval_T *rettv);
cmdidx_T excmd_get_cmdidx(char_u *cmd, int len);
long excmd_get_argt(cmdidx_T idx);
! char_u *skip_range(char_u *cmd_start, int skip_star, int *ctx);
void ex_ni(exarg_T *eap);
int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
void separate_nextcmd(exarg_T *eap);
*** ../vim-8.2.3715/src/vim9compile.c 2021-12-01 10:09:12.404191464 +0000
--- src/vim9compile.c 2021-12-01 15:08:01.185162896 +0000
***************
*** 2275,2282 ****
return OK;
}
static int
! generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *line)
{
isn_T *isn;
--- 2275,2286 ----
return OK;
}
+ /*
+ * Generate an EXEC instruction that takes a string argument.
+ * A copy is made of "line".
+ */
static int
! generate_EXEC_copy(cctx_T *cctx, isntype_T isntype, char_u *line)
{
isn_T *isn;
***************
*** 2287,2292 ****
--- 2291,2319 ----
return OK;
}
+ /*
+ * Generate an EXEC instruction that takes a string argument.
+ * "str" must be allocated, it is consumed.
+ */
+ static int
+ generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *str)
+ {
+ isn_T *isn;
+
+ if (cctx->ctx_skip == SKIP_YES)
+ {
+ vim_free(str);
+ return OK;
+ }
+ if ((isn = generate_instr(cctx, isntype)) == NULL)
+ {
+ vim_free(str);
+ return FAIL;
+ }
+ isn->isn_arg.string = str;
+ return OK;
+ }
+
static int
generate_LEGACY_EVAL(cctx_T *cctx, char_u *line)
{
***************
*** 7552,7558 ****
vim_snprintf((char *)buf, len, "%s %s",
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
p);
! ret = generate_EXEC(cctx, isn, buf);
vim_free(buf);
*name_end = cc;
--- 7579,7585 ----
vim_snprintf((char *)buf, len, "%s %s",
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
p);
! ret = generate_EXEC_copy(cctx, isn, buf);
vim_free(buf);
*name_end = cc;
***************
*** 9248,9254 ****
generate_EXECCONCAT(cctx, count);
}
else
! generate_EXEC(cctx, ISN_EXEC, line);
theend:
if (*nextcmd != NUL)
--- 9275,9281 ----
generate_EXECCONCAT(cctx, count);
}
else
! generate_EXEC_copy(cctx, ISN_EXEC, line);
theend:
if (*nextcmd != NUL)
***************
*** 9874,9883 ****
if (ends_excmd2(line, ea.cmd))
{
// A range without a command: jump to the line.
! // TODO: compile to a more efficient command, possibly
! // calling parse_cmd_address().
! ea.cmdidx = CMD_SIZE;
! line = compile_exec(line, &ea, &cctx);
goto nextline;
}
}
--- 9901,9912 ----
if (ends_excmd2(line, ea.cmd))
{
// A range without a command: jump to the line.
! line = skipwhite(line);
! while (*line == ':')
! ++line;
! generate_EXEC(&cctx, ISN_EXECRANGE,
! vim_strnsave(line, ea.cmd - line));
! line = ea.cmd;
goto nextline;
}
}
***************
*** 10350,10355 ****
--- 10379,10385 ----
{
case ISN_DEF:
case ISN_EXEC:
+ case ISN_EXECRANGE:
case ISN_EXEC_SPLIT:
case ISN_LEGACY_EVAL:
case ISN_LOADAUTO:
*** ../vim-8.2.3715/src/vim9execute.c 2021-11-29 10:36:15.916827518 +0000
--- src/vim9execute.c 2021-12-01 14:58:01.438798689 +0000
***************
*** 1774,1779 ****
--- 1774,1801 ----
}
break;
+ // execute Ex command line that is only a range
+ case ISN_EXECRANGE:
+ {
+ exarg_T ea;
+ char *error = NULL;
+
+ CLEAR_FIELD(ea);
+ ea.cmdidx = CMD_SIZE;
+ ea.addr_type = ADDR_LINES;
+ ea.cmd = iptr->isn_arg.string;
+ parse_cmd_address(&ea, &error, FALSE);
+ if (error == NULL)
+ error = ex_range_without_command(&ea);
+ if (error != NULL)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(error);
+ goto on_error;
+ }
+ }
+ break;
+
// Evaluate an expression with legacy syntax, push it onto the
// stack.
case ISN_LEGACY_EVAL:
***************
*** 5068,5073 ****
--- 5090,5098 ----
case ISN_EXEC_SPLIT:
smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
break;
+ case ISN_EXECRANGE:
+ smsg("%s%4d EXECRANGE %s", pfx, current, iptr->isn_arg.string);
+ break;
case ISN_LEGACY_EVAL:
smsg("%s%4d EVAL legacy %s", pfx, current,
iptr->isn_arg.string);
*** ../vim-8.2.3715/src/vim9.h 2021-11-28 22:00:08.148081412 +0000
--- src/vim9.h 2021-12-01 14:37:00.840311433 +0000
***************
*** 15,20 ****
--- 15,21 ----
ISN_EXEC, // execute Ex command line isn_arg.string
ISN_EXECCONCAT, // execute Ex command from isn_arg.number items on stack
ISN_EXEC_SPLIT, // execute Ex command from isn_arg.string split at NL
+ ISN_EXECRANGE, // execute EX command that is only a range
ISN_LEGACY_EVAL, // evaluate expression isn_arg.string with legacy syntax.
ISN_ECHO, // :echo with isn_arg.echo.echo_count items on top of stack
ISN_EXECUTE, // :execute with isn_arg.number items on top of stack
*** ../vim-8.2.3715/src/testdir/test_vim9_disassemble.vim 2021-11-30 20:57:34.561305257 +0000
--- src/testdir/test_vim9_disassemble.vim 2021-12-01 15:20:31.675255283 +0000
***************
*** 1999,2004 ****
--- 1999,2023 ----
res)
enddef
+ def s:OnlyRange()
+ :$
+ :123
+ :'m
+ enddef
+
+ def Test_disassemble_range_only()
+ var res = execute('disass s:OnlyRange')
+ assert_match('\<SNR>\d*_OnlyRange\_s*' ..
+ ':$\_s*' ..
+ '\d EXECRANGE $\_s*' ..
+ ':123\_s*' ..
+ '\d EXECRANGE 123\_s*' ..
+ ':''m\_s*' ..
+ '\d EXECRANGE ''m\_s*' ..
+ '\d\+ RETURN void',
+ res)
+ enddef
+
def s:Echomsg()
echomsg 'some' 'message'
echoconsole 'nothing'
*** ../vim-8.2.3715/src/version.c 2021-12-01 12:41:25.079773508 +0000
--- src/version.c 2021-12-01 14:35:56.672820240 +0000
***************
*** 755,756 ****
--- 755,758 ----
{ /* Add new patch number below this line */
+ /**/
+ 3716,
/**/
--
DENNIS: Look, strange women lying on their backs in ponds handing out
swords ... that's no basis for a system of government. Supreme
executive power derives from a mandate from the masses, not from some
farcical aquatic ceremony.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// 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 ///