aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-04-14 13:49:28 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-04-14 16:10:09 +0800
commit8729c41f44de3b164ad8d01bb3558c6400e27952 (patch)
tree9c611cef6c60a7522e9cbaf47d90a8c937f9a385
parent4b84b2e2aa3d7ab6a4e346c7439826700682f5f1 (diff)
downloadrneovim-8729c41f44de3b164ad8d01bb3558c6400e27952.tar.gz
rneovim-8729c41f44de3b164ad8d01bb3558c6400e27952.tar.bz2
rneovim-8729c41f44de3b164ad8d01bb3558c6400e27952.zip
vim-patch:8.2.1080: Vim9: no line break allowed in a for loop
Problem: Vim9: no line break allowed in a for loop. Solution: Skip line breaks in for command. https://github.com/vim/vim/commit/b7a78f7a6713f07d2fcad0b27dea22925c7b1cdf Omit *_break_count and skip_for_lines(): Vim9 script only. Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/api/vimscript.c2
-rw-r--r--src/nvim/debugger.c2
-rw-r--r--src/nvim/eval.c38
-rw-r--r--src/nvim/eval/userfunc.c1
-rw-r--r--src/nvim/ex_eval.c19
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/quickfix.c12
7 files changed, 51 insertions, 25 deletions
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index d2e18f08f3..208aa165c9 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -173,6 +173,7 @@ Object nvim_eval(String expr, Error *err)
TRY_WRAP(err, {
ok = eval0(expr.data, &rettv, NULL, &EVALARG_EVALUATE);
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
});
if (!ERROR_SET(err)) {
@@ -294,6 +295,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
api_set_error(err, kErrorTypeException,
"Failed to evaluate dict expression");
}
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
if (try_end(err)) {
return rv;
}
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 3c9a63f5a3..90723372a9 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -494,7 +494,7 @@ static typval_T *eval_expr_no_emsg(struct debuggy *const bp)
{
// Disable error messages, a bad expression would make Vim unusable.
emsg_off++;
- typval_T *const tv = eval_expr(bp->dbg_name);
+ typval_T *const tv = eval_expr(bp->dbg_name, NULL);
emsg_off--;
return tv;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index e5193cdfb8..0880fed71e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -849,6 +849,7 @@ char *eval_to_string_skip(char *arg, exarg_T *eap, const bool skip)
if (skip) {
emsg_skip--;
}
+ clear_evalarg(&EVALARG_EVALUATE, eap);
return retval;
}
@@ -910,6 +911,7 @@ char *eval_to_string(char *arg, bool convert)
}
tv_clear(&tv);
}
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
return retval;
}
@@ -964,12 +966,13 @@ varnumber_T eval_to_number(char *expr)
///
/// @return an allocated typval_T with the result or
/// NULL when there is an error.
-typval_T *eval_expr(char *arg)
+typval_T *eval_expr(char *arg, exarg_T *eap)
{
typval_T *tv = xmalloc(sizeof(*tv));
- if (eval0(arg, tv, NULL, &EVALARG_EVALUATE) == FAIL) {
+ if (eval0(arg, tv, eap, &EVALARG_EVALUATE) == FAIL) {
XFREE_CLEAR(tv);
}
+ clear_evalarg(&EVALARG_EVALUATE, eap);
return tv;
}
@@ -1215,6 +1218,7 @@ int eval_foldexpr(char *arg, int *cp)
sandbox--;
}
textlock--;
+ clear_evalarg(&EVALARG_EVALUATE, NULL);
return (int)retval;
}
@@ -1797,14 +1801,14 @@ notify:
/// @param[out] *errp set to true for an error, false otherwise;
///
/// @return a pointer that holds the info. Null when there is an error.
-void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
+void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, evalarg_T *const evalarg)
{
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
const char *expr;
typval_T tv;
list_T *l;
+ const bool skip = !(evalarg->eval_flags & EVAL_EVALUATE);
- evalarg_T evalarg = { .eval_flags = skip ? 0 : EVAL_EVALUATE };
*errp = true; // Default: there is an error.
expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
@@ -1813,7 +1817,8 @@ void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
}
expr = skipwhite(expr);
- if (expr[0] != 'i' || expr[1] != 'n' || !ascii_iswhite(expr[2])) {
+ if (expr[0] != 'i' || expr[1] != 'n'
+ || !(expr[2] == NUL || ascii_iswhite(expr[2]))) {
emsg(_("E690: Missing \"in\" after :for"));
return fi;
}
@@ -1821,7 +1826,8 @@ void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip)
if (skip) {
emsg_skip++;
}
- if (eval0(skipwhite(expr + 2), &tv, eap, &evalarg) == OK) {
+ expr = skipwhite(expr + 2);
+ if (eval0((char *)expr, &tv, eap, evalarg) == OK) {
*errp = false;
if (!skip) {
if (tv.v_type == VAR_LIST) {
@@ -2240,13 +2246,17 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
/// After using "evalarg" filled from "eap" free the memory.
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
{
- if (evalarg != NULL && eap != NULL && evalarg->eval_tofree != NULL) {
- // We may need to keep the original command line, e.g. for
- // ":let" it has the variable names. But we may also need the
- // new one, "nextcmd" points into it. Keep both.
- xfree(eap->cmdline_tofree);
- eap->cmdline_tofree = *eap->cmdlinep;
- *eap->cmdlinep = evalarg->eval_tofree;
+ if (evalarg != NULL && evalarg->eval_tofree != NULL) {
+ if (eap != NULL) {
+ // We may need to keep the original command line, e.g. for
+ // ":let" it has the variable names. But we may also need the
+ // new one, "nextcmd" points into it. Keep both.
+ xfree(eap->cmdline_tofree);
+ eap->cmdline_tofree = *eap->cmdlinep;
+ *eap->cmdlinep = evalarg->eval_tofree;
+ } else {
+ xfree(evalarg->eval_tofree);
+ }
evalarg->eval_tofree = NULL;
}
}
@@ -2301,8 +2311,6 @@ int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg)
eap->nextcmd = check_nextcmd(p);
}
- clear_evalarg(evalarg, eap);
-
return ret;
}
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index b1cb53fec2..1f25b7fb36 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -2996,6 +2996,7 @@ void ex_return(exarg_T *eap)
if (eap->skip) {
emsg_skip--;
}
+ clear_evalarg(&evalarg, eap);
}
/// ":1,25call func(arg1, arg2)" function call.
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 27f012a4ab..34015728b0 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -794,11 +794,17 @@ void ex_eval(exarg_T *eap)
typval_T tv;
evalarg_T evalarg = {
.eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
- .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL,
};
+ if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
+ evalarg.eval_getline = eap->getline;
+ evalarg.eval_cookie = eap->cookie;
+ }
+
if (eval0(eap->arg, &tv, eap, &evalarg) == OK) {
tv_clear(&tv);
}
+
+ clear_evalarg(&evalarg, eap);
}
/// Handle ":if".
@@ -961,6 +967,14 @@ void ex_while(exarg_T *eap)
} else {
void *fi;
+ evalarg_T evalarg = {
+ .eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
+ };
+ if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
+ evalarg.eval_getline = eap->getline;
+ evalarg.eval_cookie = eap->cookie;
+ }
+
// ":for var in list-expr"
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) {
// Jumping here from a ":continue" or ":endfor": use the
@@ -969,7 +983,7 @@ void ex_while(exarg_T *eap)
error = false;
} else {
// Evaluate the argument and get the info in a structure.
- fi = eval_for_line(eap->arg, &error, eap, skip);
+ fi = eval_for_line(eap->arg, &error, eap, &evalarg);
cstack->cs_forinfo[cstack->cs_idx] = fi;
}
@@ -984,6 +998,7 @@ void ex_while(exarg_T *eap)
free_for_info(fi);
cstack->cs_forinfo[cstack->cs_idx] = NULL;
}
+ clear_evalarg(&evalarg, eap);
}
// If this cstack entry was just initialised and is active, set the
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 386c6d88d9..6d4e7de1a3 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -5266,7 +5266,7 @@ int option_set_callback_func(char *optval, Callback *optcb)
|| (strncmp(optval, "function(", 9) == 0)
|| (strncmp(optval, "funcref(", 8) == 0)) {
// Lambda expression or a funcref
- tv = eval_expr(optval);
+ tv = eval_expr(optval, NULL);
if (tv == NULL) {
return FAIL;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index fdcdd71ceb..62eb14342c 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -6957,15 +6957,15 @@ void ex_cexpr(exarg_T *eap)
// Evaluate the expression. When the result is a string or a list we can
// use it to fill the errorlist.
- typval_T tv;
- if (eval0(eap->arg, &tv, eap, &EVALARG_EVALUATE) == FAIL) {
+ typval_T *tv = eval_expr(eap->arg, eap);
+ if (tv == NULL) {
return;
}
- if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
- || tv.v_type == VAR_LIST) {
+ if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
+ || tv->v_type == VAR_LIST) {
incr_quickfix_busy();
- int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
+ int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm,
(eap->cmdidx != CMD_caddexpr
&& eap->cmdidx != CMD_laddexpr),
(linenr_T)0, (linenr_T)0,
@@ -6996,7 +6996,7 @@ void ex_cexpr(exarg_T *eap)
emsg(_("E777: String or List expected"));
}
cleanup:
- tv_clear(&tv);
+ tv_free(tv);
}
// Get the location list for ":lhelpgrep"