diff options
-rw-r--r-- | src/nvim/digraph.c | 2 | ||||
-rw-r--r-- | src/nvim/eval.c | 52 | ||||
-rw-r--r-- | src/nvim/eval.h | 5 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 4 | ||||
-rw-r--r-- | src/nvim/eval/vars.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 3 | ||||
-rw-r--r-- | src/nvim/ex_eval.c | 15 | ||||
-rw-r--r-- | src/nvim/fold.c | 3 | ||||
-rw-r--r-- | src/nvim/mapping.c | 2 | ||||
-rw-r--r-- | src/nvim/ops.c | 2 | ||||
-rw-r--r-- | src/nvim/path.c | 4 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 2 | ||||
-rw-r--r-- | src/nvim/regexp.c | 2 | ||||
-rw-r--r-- | src/nvim/statusline.c | 4 |
15 files changed, 62 insertions, 41 deletions
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 7d6349e552..de3808e4f5 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -2203,7 +2203,7 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len) curwin = wp; STRCPY(buf, "b:keymap_name"); // must be writable emsg_skip++; - s = p = eval_to_string(buf, NULL, false); + s = p = eval_to_string(buf, false); emsg_skip--; curbuf = old_curbuf; curwin = old_curwin; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 4fe86c8399..a9c5ca46f3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -698,7 +698,7 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch /// @param skip only parse, don't execute /// /// @return true or false. -int eval_to_bool(char *arg, bool *error, char **nextcmd, int skip) +int eval_to_bool(char *arg, bool *error, exarg_T *eap, int skip) { typval_T tv; bool retval = false; @@ -706,7 +706,7 @@ int eval_to_bool(char *arg, bool *error, char **nextcmd, int skip) if (skip) { emsg_skip++; } - if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL) { + if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE) == FAIL) { *error = true; } else { *error = false; @@ -817,13 +817,12 @@ bool eval_expr_to_bool(const typval_T *expr, bool *error) /// Top level evaluation function, returning a string /// /// @param[in] arg String to evaluate. -/// @param nextcmd Pointer to the start of the next Ex command. /// @param[in] skip If true, only do parsing to nextcmd without reporting /// errors or actually evaluating anything. /// /// @return [allocated] string result of evaluation or NULL in case of error or /// when skipping. -char *eval_to_string_skip(const char *arg, const char **nextcmd, const bool skip) +char *eval_to_string_skip(char *arg, exarg_T *eap, const bool skip) FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT { typval_T tv; @@ -832,8 +831,7 @@ char *eval_to_string_skip(const char *arg, const char **nextcmd, const bool skip if (skip) { emsg_skip++; } - if (eval0((char *)arg, &tv, (char **)nextcmd, skip ? NULL : &EVALARG_EVALUATE) - == FAIL || skip) { + if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE) == FAIL || skip) { retval = NULL; } else { retval = xstrdup(tv_get_string(&tv)); @@ -863,13 +861,13 @@ int skip_expr(char **pp) /// a Float to a String. /// /// @return pointer to allocated memory, or NULL for failure. -char *eval_to_string(char *arg, char **nextcmd, bool convert) +char *eval_to_string(char *arg, bool convert) { typval_T tv; char *retval; garray_T ga; - if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL) { + if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) { retval = NULL; } else { if (convert && tv.v_type == VAR_LIST) { @@ -899,7 +897,7 @@ char *eval_to_string(char *arg, char **nextcmd, bool convert) /// textlock. /// /// @param use_sandbox when true, use the sandbox. -char *eval_to_string_safe(char *arg, char **nextcmd, int use_sandbox) +char *eval_to_string_safe(char *arg, int use_sandbox) { char *retval; funccal_entry_T funccal_entry; @@ -909,7 +907,7 @@ char *eval_to_string_safe(char *arg, char **nextcmd, int use_sandbox) sandbox++; } textlock++; - retval = eval_to_string(arg, nextcmd, false); + retval = eval_to_string(arg, false); if (use_sandbox) { sandbox--; } @@ -1778,7 +1776,7 @@ 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, char **nextcmdp, int skip) +void *eval_for_line(const char *arg, bool *errp, exarg_T *eap, int skip) { forinfo_T *fi = xcalloc(1, sizeof(forinfo_T)); const char *expr; @@ -1802,7 +1800,7 @@ void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip) if (skip) { emsg_skip++; } - if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK) { + if (eval0(skipwhite(expr + 2), &tv, eap, &evalarg) == OK) { *errp = false; if (!skip) { if (tv.v_type == VAR_LIST) { @@ -2230,7 +2228,7 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ /// @param evalarg can be NULL, &EVALARG_EVALUATE or a pointer. /// /// @return OK or FAIL. -int eval0(char *arg, typval_T *rettv, char **nextcmd, evalarg_T *const evalarg) +int eval0(char *arg, typval_T *rettv, exarg_T *eap, evalarg_T *const evalarg) { int ret; char *p; @@ -2238,6 +2236,9 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, evalarg_T *const evalarg) const int called_emsg_before = called_emsg; bool end_error = false; + if (evalarg != NULL) { + evalarg->eval_tofree = NULL; + } p = skipwhite(arg); ret = eval1(&p, rettv, evalarg); @@ -2263,8 +2264,24 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, evalarg_T *const evalarg) } ret = FAIL; } - if (nextcmd != NULL) { - *nextcmd = check_nextcmd(p); + + if (eap != NULL) { + eap->nextcmd = check_nextcmd(p); + } + + if (evalarg != NULL) { + if (eap != NULL) { + if (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; + } + } else { + xfree(evalarg->eval_tofree); + } } return ret; @@ -6537,15 +6554,14 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex } char *retval = NULL; - char *nextcmd = NULL; *expr_start = NUL; *expr_end = NUL; char c1 = *in_end; *in_end = NUL; - char *temp_result = eval_to_string(expr_start + 1, &nextcmd, false); - if (temp_result != NULL && nextcmd == NULL) { + char *temp_result = eval_to_string(expr_start + 1, false); + if (temp_result != NULL) { retval = xmalloc(strlen(temp_result) + (size_t)(expr_start - in_start) + (size_t)(in_end - expr_end) + 1); STRCPY(retval, in_start); diff --git a/src/nvim/eval.h b/src/nvim/eval.h index b29abe3d73..4f517551c6 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -273,6 +273,9 @@ typedef struct { /// copied from exarg_T when "getline" is "getsourceline". Can be NULL. void *eval_cookie; // argument for getline() + + /// pointer to the line obtained with getsourceline() + char *eval_tofree; } evalarg_T; /// Flag for expression evaluation. @@ -281,7 +284,7 @@ enum { }; /// Passed to an eval() function to enable evaluation. -EXTERN evalarg_T EVALARG_EVALUATE INIT(= { EVAL_EVALUATE, NULL }); +EXTERN evalarg_T EVALARG_EVALUATE INIT(= { EVAL_EVALUATE, NULL, NULL }); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.h.generated.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index d994a31039..fe0249ea3a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2957,7 +2957,7 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') - && eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL) { + && eval0(arg, &rettv, eap, &evalarg) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -3008,7 +3008,7 @@ void ex_call(exarg_T *eap) // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. emsg_skip++; - if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL) { + if (eval0(eap->arg, &rettv, eap, NULL) != FAIL) { tv_clear(&rettv); } emsg_skip--; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 02e526d7b6..bad676500b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -259,7 +259,7 @@ void ex_let(exarg_T *eap) .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, }; - i = eval0(expr, &rettv, &eap->nextcmd, &evalarg); + i = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) { emsg_skip--; } diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 629aaf14cf..7932649114 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -185,6 +185,7 @@ struct exarg { char *nextcmd; ///< next command (NULL if none) char *cmd; ///< the name of the command (except for :make) char **cmdlinep; ///< pointer to pointer of allocated cmdline + char *cmdline_tofree; ///< free later cmdidx_T cmdidx; ///< the index for the command uint32_t argt; ///< flags for the command int skip; ///< don't execute the command, only parse it diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index fbdb1bc2d7..e8ad472da8 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -2328,6 +2328,7 @@ doend: } ex_nesting_level--; + xfree(ea.cmdline_tofree); return ea.nextcmd; } @@ -4432,7 +4433,7 @@ static void ex_colorscheme(exarg_T *eap) char *expr = xstrdup("g:colors_name"); emsg_off++; - char *p = eval_to_string(expr, NULL, false); + char *p = eval_to_string(expr, false); emsg_off--; xfree(expr); diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 33b315c179..27f012a4ab 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -796,7 +796,7 @@ void ex_eval(exarg_T *eap) .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, }; - if (eval0(eap->arg, &tv, &eap->nextcmd, &evalarg) == OK) { + if (eval0(eap->arg, &tv, eap, &evalarg) == OK) { tv_clear(&tv); } } @@ -815,7 +815,7 @@ void ex_if(exarg_T *eap) int skip = CHECK_SKIP; bool error; - int result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + int result = eval_to_bool(eap->arg, &error, eap, skip); if (!skip && !error) { if (result) { @@ -910,7 +910,7 @@ void ex_else(exarg_T *eap) if (skip && *eap->arg != '"' && ends_excmd(*eap->arg)) { semsg(_(e_invexpr2), eap->arg); } else { - result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + result = eval_to_bool(eap->arg, &error, eap, skip); } // When throwing error exceptions, we want to throw always the first @@ -957,7 +957,7 @@ void ex_while(exarg_T *eap) int skip = CHECK_SKIP; if (eap->cmdidx == CMD_while) { // ":while bool-expr" - result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + result = eval_to_bool(eap->arg, &error, eap, skip); } else { void *fi; @@ -969,7 +969,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->nextcmd, skip); + fi = eval_for_line(eap->arg, &error, eap, skip); cstack->cs_forinfo[cstack->cs_idx] = fi; } @@ -1128,12 +1128,11 @@ void ex_endwhile(exarg_T *eap) /// Handle ":throw expr" void ex_throw(exarg_T *eap) { - const char *arg = eap->arg; + char *arg = eap->arg; char *value; if (*arg != NUL && *arg != '|' && *arg != '\n') { - value = eval_to_string_skip(arg, (const char **)&eap->nextcmd, - (bool)eap->skip); + value = eval_to_string_skip(arg, eap, eap->skip); } else { emsg(_(e_argreq)); value = NULL; diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 71984e806d..a0869b54c9 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1749,7 +1749,8 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo curbuf = wp->w_buffer; emsg_silent++; // handle exceptions, but don't display errors - text = eval_to_string_safe(wp->w_p_fdt, NULL, was_set_insecurely(wp, "foldtext", OPT_LOCAL)); + text = eval_to_string_safe(wp->w_p_fdt, + was_set_insecurely(wp, "foldtext", OPT_LOCAL)); emsg_silent--; if (text == NULL || did_emsg) { diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 19a2aca75e..c1565a84f5 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1632,7 +1632,7 @@ char *eval_map_expr(mapblock_T *mp, int c) api_clear_error(&err); } } else { - p = eval_to_string(expr, NULL, false); + p = eval_to_string(expr, false); xfree(expr); } expr_map_lock--; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 9aacfcad30..b2c0dd6c01 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -763,7 +763,7 @@ char *get_expr_line(void) } nested++; - rv = eval_to_string(expr_copy, NULL, true); + rv = eval_to_string(expr_copy, true); nested--; xfree(expr_copy); return rv; diff --git a/src/nvim/path.c b/src/nvim/path.c index 368f3feb27..8bd3303166 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1371,7 +1371,7 @@ static int expand_backtick(garray_T *gap, char *pat, int flags) char *cmd = xstrnsave(pat + 1, strlen(pat) - 2); if (*cmd == '=') { // `={expr}`: Expand expression - buffer = eval_to_string(cmd + 1, &p, true); + buffer = eval_to_string(cmd + 1, true); } else { buffer = get_cmd_output(cmd, NULL, (flags & EW_SILENT) ? kShellOptSilent : 0, NULL); } @@ -1662,7 +1662,7 @@ void simplify_filename(char *filename) static char *eval_includeexpr(const char *const ptr, const size_t len) { set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len); - char *res = eval_to_string_safe(curbuf->b_p_inex, NULL, + char *res = eval_to_string_safe(curbuf->b_p_inex, was_set_insecurely(curwin, "includeexpr", OPT_LOCAL)); set_vim_var_string(VV_FNAME, NULL, 0); return res; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 38e05f408e..fdcdd71ceb 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -6958,7 +6958,7 @@ 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->nextcmd, &EVALARG_EVALUATE) == FAIL) { + if (eval0(eap->arg, &tv, eap, &EVALARG_EVALUATE) == FAIL) { return; } diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 94796f0ed3..3ed32bf8af 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1812,7 +1812,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen } tv_clear(&rettv); } else { - eval_result[nested] = eval_to_string(source + 2, NULL, true); + eval_result[nested] = eval_to_string(source + 2, true); } nesting--; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6c698f45be..05649e9b7f 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -985,7 +985,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n }; set_var(S_LEN("g:statusline_winid"), &tv, false); - usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox); + usefmt = eval_to_string_safe(fmt + 2, use_sandbox); if (usefmt == NULL) { usefmt = fmt; } @@ -1457,7 +1457,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n } // Note: The result stored in `t` is unused. - str = eval_to_string_safe(out_p, &t, use_sandbox); + str = eval_to_string_safe(out_p, use_sandbox); curwin = save_curwin; curbuf = save_curbuf; |