blob: fabe9643c3b06dcedd7c320b9a1ebf12c34b6279 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * eval.c: Expression evaluation.
12 */
Bram Moolenaarfefecb02016-02-27 21:27:20 +010013#define USING_FLOAT_STUFF
Bram Moolenaar071d4272004-06-13 20:20:40 +000014
15#include "vim.h"
16
Bram Moolenaar8c8de832008-06-24 22:58:06 +000017#if defined(FEAT_EVAL) || defined(PROTO)
18
Bram Moolenaar314f11d2010-08-09 22:07:08 +020019#ifdef VMS
20# include <float.h>
21#endif
22
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +010023#define NAMESPACE_CHAR (char_u *)"abglstvw"
24
Bram Moolenaar5409f5d2020-06-24 18:37:35 +020025static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
26static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
27static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
28static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +010029static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +020030static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +010031static int eval8(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
32static int eval9(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
33static int eval9_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp);
Bram Moolenaara40058a2005-07-11 22:42:07 +000034
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020035static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
Bram Moolenaar2c704a72010-06-03 21:17:25 +020036
Bram Moolenaare21c1582019-03-02 11:57:09 +010037/*
38 * Return "n1" divided by "n2", taking care of dividing by zero.
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010039 * If "failed" is not NULL set it to TRUE when dividing by zero fails.
Bram Moolenaare21c1582019-03-02 11:57:09 +010040 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +020041 varnumber_T
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010042num_divide(varnumber_T n1, varnumber_T n2, int *failed)
Bram Moolenaare21c1582019-03-02 11:57:09 +010043{
44 varnumber_T result;
45
Bram Moolenaar99880f92021-01-20 21:23:14 +010046 if (n2 == 0)
Bram Moolenaare21c1582019-03-02 11:57:09 +010047 {
Bram Moolenaar99880f92021-01-20 21:23:14 +010048 if (in_vim9script())
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010049 {
Bram Moolenaar99880f92021-01-20 21:23:14 +010050 emsg(_(e_divide_by_zero));
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010051 if (failed != NULL)
52 *failed = TRUE;
53 }
Bram Moolenaare21c1582019-03-02 11:57:09 +010054 if (n1 == 0)
55 result = VARNUM_MIN; // similar to NaN
56 else if (n1 < 0)
57 result = -VARNUM_MAX;
58 else
59 result = VARNUM_MAX;
60 }
Bram Moolenaarcdef1ce2022-10-20 14:17:18 +010061 else if (n1 == VARNUM_MIN && n2 == -1)
62 {
63 // specific case: trying to do VARNUM_MIN / -1 results in a positive
64 // number that doesn't fit in varnumber_T and causes an FPE
65 result = VARNUM_MAX;
66 }
Bram Moolenaare21c1582019-03-02 11:57:09 +010067 else
68 result = n1 / n2;
69
70 return result;
71}
72
73/*
74 * Return "n1" modulus "n2", taking care of dividing by zero.
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010075 * If "failed" is not NULL set it to TRUE when dividing by zero fails.
Bram Moolenaare21c1582019-03-02 11:57:09 +010076 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +020077 varnumber_T
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010078num_modulus(varnumber_T n1, varnumber_T n2, int *failed)
Bram Moolenaare21c1582019-03-02 11:57:09 +010079{
Bram Moolenaar99880f92021-01-20 21:23:14 +010080 if (n2 == 0 && in_vim9script())
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010081 {
Bram Moolenaar99880f92021-01-20 21:23:14 +010082 emsg(_(e_divide_by_zero));
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +010083 if (failed != NULL)
84 *failed = TRUE;
85 }
Bram Moolenaare21c1582019-03-02 11:57:09 +010086 return (n2 == 0) ? 0 : (n1 % n2);
87}
88
Bram Moolenaar33570922005-01-25 22:26:29 +000089/*
90 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +000091 */
92 void
Bram Moolenaar7454a062016-01-30 15:14:10 +010093eval_init(void)
Bram Moolenaara7043832005-01-21 11:56:39 +000094{
Bram Moolenaare5cdf152019-08-29 22:09:46 +020095 evalvars_init();
Bram Moolenaara9b579f2016-07-17 18:29:19 +020096 func_init();
Bram Moolenaara7043832005-01-21 11:56:39 +000097}
98
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000099#if defined(EXITFREE) || defined(PROTO)
100 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100101eval_clear(void)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000102{
Bram Moolenaare5cdf152019-08-29 22:09:46 +0200103 evalvars_clear();
Bram Moolenaar7ebcba62020-01-12 17:42:55 +0100104 free_scriptnames(); // must come after evalvars_clear().
Bram Moolenaar9b486ca2011-05-19 18:26:40 +0200105 free_locales();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000106
Bram Moolenaarda6c0332019-09-01 16:01:30 +0200107 // autoloaded script names
108 free_autoload_scriptnames();
Bram Moolenaaraa35dd12006-04-29 22:03:41 +0000109
Bram Moolenaar75ee5442019-06-06 18:05:25 +0200110 // unreferenced lists and dicts
111 (void)garbage_collect(FALSE);
Bram Moolenaarc07f67a2019-06-06 19:03:17 +0200112
113 // functions not garbage collected
114 free_all_functions();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000115}
116#endif
117
Bram Moolenaare6b53242020-07-01 17:28:33 +0200118 void
Bram Moolenaar37c83712020-06-30 21:18:36 +0200119fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip)
120{
Bram Moolenaar844fb642021-10-23 13:32:30 +0100121 init_evalarg(evalarg);
Bram Moolenaar37c83712020-06-30 21:18:36 +0200122 evalarg->eval_flags = skip ? 0 : EVAL_EVALUATE;
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000123
124 if (eap == NULL)
125 return;
126
127 evalarg->eval_cstack = eap->cstack;
Zoltan Arpadffy6fdb6282023-12-19 20:53:07 +0100128 if (sourcing_a_script(eap) || eap->ea_getline == get_list_line)
Bram Moolenaar37c83712020-06-30 21:18:36 +0200129 {
Zoltan Arpadffy6fdb6282023-12-19 20:53:07 +0100130 evalarg->eval_getline = eap->ea_getline;
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000131 evalarg->eval_cookie = eap->cookie;
Bram Moolenaar37c83712020-06-30 21:18:36 +0200132 }
133}
134
Bram Moolenaar071d4272004-06-13 20:20:40 +0000135/*
136 * Top level evaluation function, returning a boolean.
137 * Sets "error" to TRUE if there was an error.
138 * Return TRUE or FALSE.
139 */
140 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100141eval_to_bool(
142 char_u *arg,
143 int *error,
Bram Moolenaarb171fb12020-06-24 20:34:03 +0200144 exarg_T *eap,
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100145 int skip, // only parse, don't execute
146 int use_simple_function)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147{
Bram Moolenaar33570922005-01-25 22:26:29 +0000148 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200149 varnumber_T retval = FALSE;
Bram Moolenaarfaf86262020-06-27 23:07:36 +0200150 evalarg_T evalarg;
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100151 int r;
Bram Moolenaarfaf86262020-06-27 23:07:36 +0200152
Bram Moolenaar37c83712020-06-30 21:18:36 +0200153 fill_evalarg_from_eap(&evalarg, eap, skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000154
155 if (skip)
156 ++emsg_skip;
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100157 if (use_simple_function)
158 r = eval0_simple_funccal(arg, &tv, eap, &evalarg);
159 else
160 r = eval0(arg, &tv, eap, &evalarg);
161 if (r == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000163 else
164 {
165 *error = FALSE;
166 if (!skip)
167 {
Bram Moolenaar3e06a1e2020-08-10 21:57:54 +0200168 if (in_vim9script())
Bram Moolenaar13106602020-10-04 16:06:05 +0200169 retval = tv_get_bool_chk(&tv, error);
Bram Moolenaar3e06a1e2020-08-10 21:57:54 +0200170 else
171 retval = (tv_get_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000172 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173 }
174 }
175 if (skip)
176 --emsg_skip;
Bram Moolenaarfaf86262020-06-27 23:07:36 +0200177 clear_evalarg(&evalarg, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200179 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000180}
181
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100182/*
183 * Call eval1() and give an error message if not done at a lower level.
184 */
185 static int
Bram Moolenaar47e880d2020-06-30 22:02:02 +0200186eval1_emsg(char_u **arg, typval_T *rettv, exarg_T *eap)
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100187{
Bram Moolenaar6acc79f2019-01-14 22:53:31 +0100188 char_u *start = *arg;
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100189 int ret;
190 int did_emsg_before = did_emsg;
191 int called_emsg_before = called_emsg;
Bram Moolenaar47e880d2020-06-30 22:02:02 +0200192 evalarg_T evalarg;
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100193
Bram Moolenaar47e880d2020-06-30 22:02:02 +0200194 fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
195
196 ret = eval1(arg, rettv, &evalarg);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100197 if (ret == FAIL)
198 {
199 // Report the invalid expression unless the expression evaluation has
200 // been cancelled due to an aborting error, an interrupt, or an
201 // exception, or we already gave a more specific error.
202 // Also check called_emsg for when using assert_fails().
203 if (!aborting() && did_emsg == did_emsg_before
204 && called_emsg == called_emsg_before)
Bram Moolenaar108010a2021-06-27 22:03:33 +0200205 semsg(_(e_invalid_expression_str), start);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100206 }
Bram Moolenaar47e880d2020-06-30 22:02:02 +0200207 clear_evalarg(&evalarg, eap);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +0100208 return ret;
209}
210
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100211/*
Bram Moolenaara9c01042020-06-07 14:50:50 +0200212 * Return whether a typval is a valid expression to pass to eval_expr_typval()
213 * or eval_expr_to_bool(). An empty string returns FALSE;
214 */
215 int
216eval_expr_valid_arg(typval_T *tv)
217{
218 return tv->v_type != VAR_UNKNOWN
219 && (tv->v_type != VAR_STRING
220 || (tv->vval.v_string != NULL && *tv->vval.v_string != NUL));
221}
222
223/*
Bram Moolenaar82418262022-09-28 16:16:15 +0100224 * When calling eval_expr_typval() many times we only need one funccall_T.
225 * Returns NULL when no funccall_T is to be used.
226 * When returning non-NULL remove_funccal() must be called later.
227 */
228 funccall_T *
229eval_expr_get_funccal(typval_T *expr, typval_T *rettv)
230{
231 if (expr->v_type != VAR_PARTIAL)
232 return NULL;
233
234 partial_T *partial = expr->vval.v_partial;
235 if (partial == NULL)
236 return NULL;
237 if (partial->pt_func == NULL
238 || partial->pt_func->uf_def_status == UF_NOT_COMPILED)
239 return NULL;
240
241 return create_funccal(partial->pt_func, rettv);
242}
243
244/*
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +0200245 * Evaluate a partial.
246 * Pass arguments "argv[argc]".
247 * "fc_arg" is from eval_expr_get_funccal() or NULL;
248 * Return the result in "rettv" and OK or FAIL.
249 */
250 static int
251eval_expr_partial(
252 typval_T *expr,
253 typval_T *argv,
254 int argc,
255 funccall_T *fc_arg,
256 typval_T *rettv)
257{
258 partial_T *partial = expr->vval.v_partial;
259
260 if (partial == NULL)
261 return FAIL;
262
263 if (partial->pt_func != NULL
264 && partial->pt_func->uf_def_status != UF_NOT_COMPILED)
265 {
266 funccall_T *fc = fc_arg != NULL ? fc_arg
267 : create_funccal(partial->pt_func, rettv);
268 int r;
269
270 if (fc == NULL)
271 return FAIL;
272
273 // Shortcut to call a compiled function with minimal overhead.
274 r = call_def_function(partial->pt_func, argc, argv, DEF_USE_PT_ARGV,
275 partial, NULL, fc, rettv);
276 if (fc_arg == NULL)
277 remove_funccal();
278 if (r == FAIL)
279 return FAIL;
280 }
281 else
282 {
283 char_u *s = partial_name(partial);
284 funcexe_T funcexe;
285
286 if (s == NULL || *s == NUL)
287 return FAIL;
288
289 CLEAR_FIELD(funcexe);
290 funcexe.fe_evaluate = TRUE;
291 funcexe.fe_partial = partial;
292 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
293 return FAIL;
294 }
295
296 return OK;
297}
298
299/*
300 * Evaluate an expression which is a function.
301 * Pass arguments "argv[argc]".
302 * Return the result in "rettv" and OK or FAIL.
303 */
304 static int
305eval_expr_func(
306 typval_T *expr,
307 typval_T *argv,
308 int argc,
309 typval_T *rettv)
310{
311 funcexe_T funcexe;
312 char_u buf[NUMBUFLEN];
313 char_u *s;
314
315 if (expr->v_type == VAR_FUNC)
316 s = expr->vval.v_string;
317 else
318 s = tv_get_string_buf_chk_strict(expr, buf, in_vim9script());
319 if (s == NULL || *s == NUL)
320 return FAIL;
321
322 CLEAR_FIELD(funcexe);
323 funcexe.fe_evaluate = TRUE;
324 if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
325 return FAIL;
326
327 return OK;
328}
329
330/*
331 * Evaluate an expression, which is a string.
332 * Return the result in "rettv" and OK or FAIL.
333 */
334 static int
335eval_expr_string(
336 typval_T *expr,
337 typval_T *rettv)
338{
339 char_u *s;
340 char_u buf[NUMBUFLEN];
341
342 s = tv_get_string_buf_chk_strict(expr, buf, in_vim9script());
343 if (s == NULL)
344 return FAIL;
345
346 s = skipwhite(s);
347 if (eval1_emsg(&s, rettv, NULL) == FAIL)
348 return FAIL;
349
350 if (*skipwhite(s) != NUL) // check for trailing chars after expr
351 {
352 clear_tv(rettv);
353 semsg(_(e_invalid_expression_str), s);
354 return FAIL;
355 }
356
357 return OK;
358}
359
360/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100361 * Evaluate an expression, which can be a function, partial or string.
362 * Pass arguments "argv[argc]".
zeertzjqad0c4422023-08-17 22:15:47 +0200363 * If "want_func" is TRUE treat a string as a function name, not an expression.
Bram Moolenaar82418262022-09-28 16:16:15 +0100364 * "fc_arg" is from eval_expr_get_funccal() or NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100365 * Return the result in "rettv" and OK or FAIL.
366 */
Bram Moolenaar543c9b12019-04-05 22:50:40 +0200367 int
Bram Moolenaar82418262022-09-28 16:16:15 +0100368eval_expr_typval(
369 typval_T *expr,
zeertzjqad0c4422023-08-17 22:15:47 +0200370 int want_func,
Bram Moolenaar82418262022-09-28 16:16:15 +0100371 typval_T *argv,
372 int argc,
373 funccall_T *fc_arg,
374 typval_T *rettv)
Bram Moolenaar48570482017-10-30 21:48:41 +0100375{
zeertzjqad0c4422023-08-17 22:15:47 +0200376 if (expr->v_type == VAR_PARTIAL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +0200377 return eval_expr_partial(expr, argv, argc, fc_arg, rettv);
John Marriottbd4614f2024-11-18 20:25:21 +0100378 if (expr->v_type == VAR_INSTR)
Bram Moolenaarf18332f2021-05-07 17:55:55 +0200379 return exe_typval_instr(expr, rettv);
John Marriottbd4614f2024-11-18 20:25:21 +0100380 if (expr->v_type == VAR_FUNC || want_func)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +0200381 return eval_expr_func(expr, argv, argc, rettv);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +0200382
John Marriottbd4614f2024-11-18 20:25:21 +0100383 return eval_expr_string(expr, rettv);
Bram Moolenaar48570482017-10-30 21:48:41 +0100384}
385
386/*
387 * Like eval_to_bool() but using a typval_T instead of a string.
388 * Works for string, funcref and partial.
389 */
390 int
391eval_expr_to_bool(typval_T *expr, int *error)
392{
393 typval_T rettv;
394 int res;
395
zeertzjqad0c4422023-08-17 22:15:47 +0200396 if (eval_expr_typval(expr, FALSE, NULL, 0, NULL, &rettv) == FAIL)
Bram Moolenaar48570482017-10-30 21:48:41 +0100397 {
398 *error = TRUE;
399 return FALSE;
400 }
Bram Moolenaare15eebd2020-08-18 19:11:38 +0200401 res = (tv_get_bool_chk(&rettv, error) != 0);
Bram Moolenaar48570482017-10-30 21:48:41 +0100402 clear_tv(&rettv);
403 return res;
404}
405
Bram Moolenaar071d4272004-06-13 20:20:40 +0000406/*
407 * Top level evaluation function, returning a string. If "skip" is TRUE,
408 * only parsing to "nextcmd" is done, without reporting errors. Return
409 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
410 */
411 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100412eval_to_string_skip(
413 char_u *arg,
Bram Moolenaarb171fb12020-06-24 20:34:03 +0200414 exarg_T *eap,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +0100415 int skip) // only parse, don't execute
Bram Moolenaar071d4272004-06-13 20:20:40 +0000416{
Bram Moolenaar33570922005-01-25 22:26:29 +0000417 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418 char_u *retval;
Bram Moolenaar006ad482020-06-30 20:55:15 +0200419 evalarg_T evalarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420
Bram Moolenaar37c83712020-06-30 21:18:36 +0200421 fill_evalarg_from_eap(&evalarg, eap, skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000422 if (skip)
423 ++emsg_skip;
Bram Moolenaar006ad482020-06-30 20:55:15 +0200424 if (eval0(arg, &tv, eap, &evalarg) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000425 retval = NULL;
426 else
427 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100428 retval = vim_strsave(tv_get_string(&tv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000429 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 }
431 if (skip)
432 --emsg_skip;
Bram Moolenaar006ad482020-06-30 20:55:15 +0200433 clear_evalarg(&evalarg, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000434
435 return retval;
436}
437
438/*
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100439 * Initialize "evalarg" for use.
440 */
441 void
442init_evalarg(evalarg_T *evalarg)
443{
444 CLEAR_POINTER(evalarg);
445 ga_init2(&evalarg->eval_tofree_ga, sizeof(char_u *), 20);
446}
447
448/*
449 * If "evalarg->eval_tofree" is not NULL free it later.
450 * Caller is expected to overwrite "evalarg->eval_tofree" next.
451 */
452 static void
453free_eval_tofree_later(evalarg_T *evalarg)
454{
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000455 if (evalarg->eval_tofree == NULL)
456 return;
457
458 if (ga_grow(&evalarg->eval_tofree_ga, 1) == OK)
459 ((char_u **)evalarg->eval_tofree_ga.ga_data)
460 [evalarg->eval_tofree_ga.ga_len++]
461 = evalarg->eval_tofree;
462 else
463 vim_free(evalarg->eval_tofree);
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100464}
465
466/*
467 * After using "evalarg" filled from "eap": free the memory.
468 */
469 void
470clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
471{
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000472 if (evalarg == NULL)
473 return;
474
475 garray_T *etga = &evalarg->eval_tofree_ga;
476
477 if (evalarg->eval_tofree != NULL || evalarg->eval_using_cmdline)
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100478 {
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000479 if (eap != NULL)
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100480 {
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000481 // We may need to keep the original command line, e.g. for
482 // ":let" it has the variable names. But we may also need
483 // the new one, "nextcmd" points into it. Keep both.
484 vim_free(eap->cmdline_tofree);
485 eap->cmdline_tofree = *eap->cmdlinep;
Bram Moolenaarf8addf12022-09-23 12:44:25 +0100486
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000487 if (evalarg->eval_using_cmdline && etga->ga_len > 0)
488 {
489 // "nextcmd" points into the last line in eval_tofree_ga,
490 // need to keep it around.
491 --etga->ga_len;
492 *eap->cmdlinep = ((char_u **)etga->ga_data)[etga->ga_len];
493 vim_free(evalarg->eval_tofree);
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100494 }
495 else
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000496 *eap->cmdlinep = evalarg->eval_tofree;
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100497 }
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000498 else
499 vim_free(evalarg->eval_tofree);
500 evalarg->eval_tofree = NULL;
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100501 }
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +0000502
503 ga_clear_strings(etga);
504 VIM_CLEAR(evalarg->eval_tofree_lambda);
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100505}
506
507/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000508 * Skip over an expression at "*pp".
509 * Return FAIL for an error, OK otherwise.
510 */
511 int
Bram Moolenaar683581e2020-10-22 21:22:58 +0200512skip_expr(char_u **pp, evalarg_T *evalarg)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000513{
Bram Moolenaar33570922005-01-25 22:26:29 +0000514 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000515
516 *pp = skipwhite(*pp);
Bram Moolenaar683581e2020-10-22 21:22:58 +0200517 return eval1(pp, &rettv, evalarg);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000518}
519
520/*
Bram Moolenaar03717bf2021-04-28 20:00:40 +0200521 * Skip over an expression at "*arg".
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200522 * If in Vim9 script and line breaks are encountered, the lines are
523 * concatenated. "evalarg->eval_tofree" will be set accordingly.
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200524 * "arg" is advanced to just after the expression.
525 * "start" is set to the start of the expression, "end" to just after the end.
526 * Also when the expression is copied to allocated memory.
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200527 * Return FAIL for an error, OK otherwise.
528 */
529 int
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200530skip_expr_concatenate(
531 char_u **arg,
532 char_u **start,
533 char_u **end,
534 evalarg_T *evalarg)
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200535{
536 typval_T rettv;
537 int res;
Bram Moolenaareb6880b2020-07-12 17:07:05 +0200538 int vim9script = in_vim9script();
Bram Moolenaar9c2b0662020-09-01 19:56:15 +0200539 garray_T *gap = evalarg == NULL ? NULL : &evalarg->eval_ga;
Bram Moolenaarecb66452021-05-18 15:09:18 +0200540 garray_T *freegap = evalarg == NULL ? NULL : &evalarg->eval_freega;
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200541 int save_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
Bram Moolenaaraeb2bdd2020-08-18 22:32:03 +0200542 int evaluate = evalarg == NULL
543 ? FALSE : (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200544
Bram Moolenaaraeb2bdd2020-08-18 22:32:03 +0200545 if (vim9script && evaluate
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200546 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL))
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200547 {
548 ga_init2(gap, sizeof(char_u *), 10);
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200549 // leave room for "start"
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200550 if (ga_grow(gap, 1) == OK)
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200551 ++gap->ga_len;
Bram Moolenaarecb66452021-05-18 15:09:18 +0200552 ga_init2(freegap, sizeof(char_u *), 10);
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200553 }
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200554 *start = *arg;
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200555
556 // Don't evaluate the expression.
557 if (evalarg != NULL)
558 evalarg->eval_flags &= ~EVAL_EVALUATE;
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200559 *arg = skipwhite(*arg);
560 res = eval1(arg, &rettv, evalarg);
561 *end = *arg;
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200562 if (evalarg != NULL)
563 evalarg->eval_flags = save_flags;
564
Bram Moolenaaraeb2bdd2020-08-18 22:32:03 +0200565 if (vim9script && evaluate
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200566 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL))
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200567 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200568 if (evalarg->eval_ga.ga_len == 1)
569 {
Bram Moolenaarecb66452021-05-18 15:09:18 +0200570 // just the one line, no need to concatenate
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200571 ga_clear(gap);
572 gap->ga_itemsize = 0;
573 }
574 else
575 {
576 char_u *p;
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200577 size_t endoff = STRLEN(*arg);
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200578
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200579 // Line breaks encountered, concatenate all the lines.
580 *((char_u **)gap->ga_data) = *start;
Bram Moolenaar03717bf2021-04-28 20:00:40 +0200581 p = ga_concat_strings(gap, " ");
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200582
583 // free the lines only when using getsourceline()
584 if (evalarg->eval_cookie != NULL)
585 {
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200586 // Do not free the first line, the caller can still use it.
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200587 *((char_u **)gap->ga_data) = NULL;
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200588 // Do not free the last line, "arg" points into it, free it
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +0100589 // later. Also free "eval_tofree" later if needed.
590 free_eval_tofree_later(evalarg);
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200591 evalarg->eval_tofree =
592 ((char_u **)gap->ga_data)[gap->ga_len - 1];
593 ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200594 ga_clear_strings(gap);
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +0200595 ga_clear(freegap);
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200596 }
597 else
Bram Moolenaarecb66452021-05-18 15:09:18 +0200598 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200599 ga_clear(gap);
Bram Moolenaarecb66452021-05-18 15:09:18 +0200600
601 // free lines that were explicitly marked for freeing
602 ga_clear_strings(freegap);
603 }
604
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200605 gap->ga_itemsize = 0;
606 if (p == NULL)
607 return FAIL;
608 *start = p;
Bram Moolenaar8e2730a2020-07-08 22:01:49 +0200609 vim_free(evalarg->eval_tofree_lambda);
610 evalarg->eval_tofree_lambda = p;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200611 // Compute "end" relative to the end.
612 *end = *start + STRLEN(*start) - endoff;
613 }
Bram Moolenaare40fbc22020-06-27 18:06:45 +0200614 }
615
616 return res;
617}
618
619/*
Bram Moolenaar883cf972021-01-15 18:04:43 +0100620 * Convert "tv" to a string.
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200621 * When "join_list" is TRUE convert a List into a sequence of lines.
Bram Moolenaar883cf972021-01-15 18:04:43 +0100622 * Returns an allocated string (NULL when out of memory).
623 */
624 char_u *
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200625typval2string(typval_T *tv, int join_list)
Bram Moolenaar883cf972021-01-15 18:04:43 +0100626{
627 garray_T ga;
628 char_u *retval;
Bram Moolenaar883cf972021-01-15 18:04:43 +0100629
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200630 if (join_list && tv->v_type == VAR_LIST)
Bram Moolenaar883cf972021-01-15 18:04:43 +0100631 {
Bram Moolenaar04935fb2022-01-08 16:19:22 +0000632 ga_init2(&ga, sizeof(char), 80);
Bram Moolenaar883cf972021-01-15 18:04:43 +0100633 if (tv->vval.v_list != NULL)
634 {
635 list_join(&ga, tv->vval.v_list, (char_u *)"\n", TRUE, FALSE, 0);
636 if (tv->vval.v_list->lv_len > 0)
637 ga_append(&ga, NL);
638 }
639 ga_append(&ga, NUL);
640 retval = (char_u *)ga.ga_data;
641 }
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200642 else if (tv->v_type == VAR_LIST || tv->v_type == VAR_DICT)
643 {
644 char_u *tofree;
645 char_u numbuf[NUMBUFLEN];
646
647 retval = tv2string(tv, &tofree, numbuf, 0);
648 // Make a copy if we have a value but it's not in allocated memory.
649 if (retval != NULL && tofree == NULL)
650 retval = vim_strsave(retval);
651 }
Bram Moolenaar883cf972021-01-15 18:04:43 +0100652 else
653 retval = vim_strsave(tv_get_string(tv));
654 return retval;
655}
656
657/*
Bram Moolenaar7a4b8982020-07-08 17:36:21 +0200658 * Top level evaluation function, returning a string. Does not handle line
659 * breaks.
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200660 * When "join_list" is TRUE convert a List into a sequence of lines.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661 * Return pointer to allocated memory, or NULL for failure.
662 */
663 char_u *
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100664eval_to_string_eap(
Bram Moolenaar7454a062016-01-30 15:14:10 +0100665 char_u *arg,
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200666 int join_list,
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100667 exarg_T *eap,
668 int use_simple_function)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000669{
Bram Moolenaar33570922005-01-25 22:26:29 +0000670 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000671 char_u *retval;
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100672 evalarg_T evalarg;
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100673 int r;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100675 fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100676 if (use_simple_function)
677 r = eval0_simple_funccal(arg, &tv, NULL, &evalarg);
678 else
679 r = eval0(arg, &tv, NULL, &evalarg);
680 if (r == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 retval = NULL;
682 else
683 {
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200684 retval = typval2string(&tv, join_list);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000685 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 }
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100687 clear_evalarg(&evalarg, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688
689 return retval;
690}
691
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100692 char_u *
693eval_to_string(
694 char_u *arg,
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200695 int join_list,
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100696 int use_simple_function)
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100697{
Yegappan Lakshmananbce51d92024-04-15 19:19:52 +0200698 return eval_to_string_eap(arg, join_list, NULL, use_simple_function);
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100699}
700
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701/*
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000702 * Call eval_to_string() without using current local variables and using
zeertzjqcfe45652022-05-27 17:26:55 +0100703 * textlock. When "use_sandbox" is TRUE use the sandbox.
Bram Moolenaarc9edd6b2020-08-12 22:18:23 +0200704 * Use legacy Vim script syntax.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705 */
706 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100707eval_to_string_safe(
708 char_u *arg,
Bram Moolenaar9530b582022-01-22 13:39:08 +0000709 int use_sandbox,
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100710 int keep_script_version,
711 int use_simple_function)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000712{
713 char_u *retval;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200714 funccal_entry_T funccal_entry;
Bram Moolenaarc9edd6b2020-08-12 22:18:23 +0200715 int save_sc_version = current_sctx.sc_version;
Christian Brabandt070ac342021-09-09 12:12:03 +0200716 int save_garbage = may_garbage_collect;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717
Bram Moolenaar9530b582022-01-22 13:39:08 +0000718 if (!keep_script_version)
719 current_sctx.sc_version = 1;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200720 save_funccal(&funccal_entry);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000721 if (use_sandbox)
722 ++sandbox;
zeertzjqcfe45652022-05-27 17:26:55 +0100723 ++textlock;
Christian Brabandt070ac342021-09-09 12:12:03 +0200724 may_garbage_collect = FALSE;
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100725 retval = eval_to_string(arg, FALSE, use_simple_function);
Bram Moolenaarb71eaae2006-01-20 23:10:18 +0000726 if (use_sandbox)
727 --sandbox;
zeertzjqcfe45652022-05-27 17:26:55 +0100728 --textlock;
Christian Brabandt070ac342021-09-09 12:12:03 +0200729 may_garbage_collect = save_garbage;
Bram Moolenaar27e80c82018-10-14 21:41:01 +0200730 restore_funccal();
Bram Moolenaarc9edd6b2020-08-12 22:18:23 +0200731 current_sctx.sc_version = save_sc_version;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 return retval;
733}
734
Bram Moolenaar071d4272004-06-13 20:20:40 +0000735/*
736 * Top level evaluation function, returning a number.
737 * Evaluates "expr" silently.
738 * Returns -1 for an error.
739 */
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200740 varnumber_T
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100741eval_to_number(char_u *expr, int use_simple_function)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742{
Bram Moolenaar33570922005-01-25 22:26:29 +0000743 typval_T rettv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200744 varnumber_T retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +0000745 char_u *p = skipwhite(expr);
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100746 int r = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000747
748 ++emsg_off;
749
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100750 if (use_simple_function)
751 r = may_call_simple_func(expr, &rettv);
752 if (r == NOTDONE)
753 r = eval1(&p, &rettv, &EVALARG_EVALUATE);
754 if (r == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755 retval = -1;
756 else
757 {
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100758 retval = tv_get_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000759 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 }
761 --emsg_off;
762
763 return retval;
764}
765
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000766/*
Bram Moolenaar4770d092006-01-12 23:22:24 +0000767 * Top level evaluation function.
768 * Returns an allocated typval_T with the result.
769 * Returns NULL when there is an error.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000770 */
771 typval_T *
Bram Moolenaarb171fb12020-06-24 20:34:03 +0200772eval_expr(char_u *arg, exarg_T *eap)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000773{
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100774 return eval_expr_ext(arg, eap, FALSE);
775}
776
777 typval_T *
778eval_expr_ext(char_u *arg, exarg_T *eap, int use_simple_function)
779{
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000780 typval_T *tv;
Bram Moolenaar37c83712020-06-30 21:18:36 +0200781 evalarg_T evalarg;
782
783 fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000784
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200785 tv = ALLOC_ONE(typval_T);
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100786 if (tv != NULL)
787 {
788 int r = NOTDONE;
789
790 if (use_simple_function)
791 r = eval0_simple_funccal(arg, tv, eap, &evalarg);
792 if (r == NOTDONE)
793 r = eval0(arg, tv, eap, &evalarg);
794
795 if (r == FAIL)
796 VIM_CLEAR(tv);
797 }
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000798
Bram Moolenaar37c83712020-06-30 21:18:36 +0200799 clear_evalarg(&evalarg, eap);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000800 return tv;
801}
802
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803/*
Bram Moolenaar15d16352022-01-17 20:09:08 +0000804 * "*arg" points to what can be a function name in the form of "import.Name" or
805 * "Funcref". Return the name of the function. Set "tofree" to something that
806 * was allocated.
807 * If "verbose" is FALSE no errors are given.
808 * Return NULL for any failure.
809 */
810 static char_u *
811deref_function_name(
Bram Moolenaar54969f42022-02-07 13:56:44 +0000812 char_u **arg,
813 char_u **tofree,
814 evalarg_T *evalarg,
815 int verbose)
Bram Moolenaar15d16352022-01-17 20:09:08 +0000816{
817 typval_T ref;
818 char_u *name = *arg;
Bram Moolenaar06fef1b2022-09-03 21:53:28 +0100819 int save_flags = 0;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000820
821 ref.v_type = VAR_UNKNOWN;
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +0100822 if (evalarg != NULL)
823 {
824 // need to evaluate this to get an import, like in "a.Func"
825 save_flags = evalarg->eval_flags;
826 evalarg->eval_flags |= EVAL_EVALUATE;
827 }
Yegappan Lakshmanana061f342022-05-22 19:13:49 +0100828 if (eval9(arg, &ref, evalarg, FALSE) == FAIL)
Bram Moolenaar12eb2eb2022-04-15 22:57:09 +0100829 {
830 dictitem_T *v;
831
832 // If <SID>VarName was used it would not be found, try another way.
833 v = find_var_also_in_script(name, NULL, FALSE);
834 if (v == NULL)
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +0100835 {
836 name = NULL;
837 goto theend;
838 }
Bram Moolenaar12eb2eb2022-04-15 22:57:09 +0100839 copy_tv(&v->di_tv, &ref);
840 }
Bram Moolenaar15d16352022-01-17 20:09:08 +0000841 if (*skipwhite(*arg) != NUL)
842 {
843 if (verbose)
844 semsg(_(e_trailing_characters_str), *arg);
845 name = NULL;
846 }
847 else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
848 {
849 name = ref.vval.v_string;
850 ref.vval.v_string = NULL;
851 *tofree = name;
852 }
853 else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
854 {
855 if (ref.vval.v_partial->pt_argc > 0
856 || ref.vval.v_partial->pt_dict != NULL)
857 {
858 if (verbose)
859 emsg(_(e_cannot_use_partial_here));
860 name = NULL;
861 }
862 else
863 {
864 name = vim_strsave(partial_name(ref.vval.v_partial));
865 *tofree = name;
866 }
867 }
868 else
869 {
870 if (verbose)
871 semsg(_(e_not_callable_type_str), name);
872 name = NULL;
873 }
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +0100874
875theend:
Bram Moolenaar15d16352022-01-17 20:09:08 +0000876 clear_tv(&ref);
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +0100877 if (evalarg != NULL)
878 evalarg->eval_flags = save_flags;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000879 return name;
880}
881
882/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100883 * Call some Vim script function and return the result in "*rettv".
Bram Moolenaarffa96842018-06-12 22:05:14 +0200884 * Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
885 * should have type VAR_UNKNOWN.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000886 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887 */
Bram Moolenaar82139082011-09-14 16:52:09 +0200888 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100889call_vim_function(
890 char_u *func,
891 int argc,
Bram Moolenaarffa96842018-06-12 22:05:14 +0200892 typval_T *argv,
Bram Moolenaarded27a12018-08-01 19:06:03 +0200893 typval_T *rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894{
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000895 int ret;
Bram Moolenaarc6538bc2019-08-03 18:17:11 +0200896 funcexe_T funcexe;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000897 char_u *arg;
898 char_u *name;
899 char_u *tofree = NULL;
Bram Moolenaarfe8e9f62022-03-16 13:09:15 +0000900 int ignore_errors;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901
Bram Moolenaar5d18efe2019-12-01 21:11:22 +0100902 rettv->v_type = VAR_UNKNOWN; // clear_tv() uses this
Bram Moolenaara80faa82020-04-12 19:37:17 +0200903 CLEAR_FIELD(funcexe);
Bram Moolenaar851f86b2021-12-13 14:26:44 +0000904 funcexe.fe_firstline = curwin->w_cursor.lnum;
905 funcexe.fe_lastline = curwin->w_cursor.lnum;
906 funcexe.fe_evaluate = TRUE;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000907
Bram Moolenaarfe8e9f62022-03-16 13:09:15 +0000908 // The name might be "import.Func" or "Funcref". We don't know, we need to
909 // ignore errors for an undefined name. But we do want errors when an
Bram Moolenaarda6d42c2022-03-17 11:46:55 +0000910 // autoload script has errors. Guess that when there is a dot in the name
911 // showing errors is the right choice.
912 ignore_errors = vim_strchr(func, '.') == NULL;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000913 arg = func;
Bram Moolenaarfe8e9f62022-03-16 13:09:15 +0000914 if (ignore_errors)
915 ++emsg_off;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000916 name = deref_function_name(&arg, &tofree, &EVALARG_EVALUATE, FALSE);
Bram Moolenaarfe8e9f62022-03-16 13:09:15 +0000917 if (ignore_errors)
918 --emsg_off;
Bram Moolenaar15d16352022-01-17 20:09:08 +0000919 if (name == NULL)
920 name = func;
921
922 ret = call_func(name, -1, rettv, argc, argv, &funcexe);
923
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000924 if (ret == FAIL)
925 clear_tv(rettv);
Bram Moolenaar15d16352022-01-17 20:09:08 +0000926 vim_free(tofree);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000927
928 return ret;
929}
930
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100931/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100932 * Call Vim script function "func" and return the result as a string.
Dominique Pelle748b3082022-01-08 12:41:16 +0000933 * Uses "argv[0]" to "argv[argc - 1]" for the function arguments. "argv[argc]"
934 * should have type VAR_UNKNOWN.
Bram Moolenaar25ceb222005-07-30 22:45:36 +0000935 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000936 */
937 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100938call_func_retstr(
939 char_u *func,
940 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +0200941 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000942{
943 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +0000944 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000945
Bram Moolenaarded27a12018-08-01 19:06:03 +0200946 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000947 return NULL;
948
Bram Moolenaard155d7a2018-12-21 16:04:21 +0100949 retval = vim_strsave(tv_get_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000950 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 return retval;
952}
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000953
Bram Moolenaar25ceb222005-07-30 22:45:36 +0000954/*
Bram Moolenaarb544f3c2017-02-23 19:03:28 +0100955 * Call Vim script function "func" and return the result as a List.
Dominique Pelle748b3082022-01-08 12:41:16 +0000956 * Uses "argv" and "argc" as call_func_retstr().
Bram Moolenaar9bf749b2008-07-27 13:57:29 +0000957 * Returns NULL when there is something wrong.
Bram Moolenaar55e93662022-09-10 13:52:26 +0100958 * Gives an error when the returned value is not a list.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000959 */
960 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100961call_func_retlist(
962 char_u *func,
963 int argc,
Bram Moolenaarded27a12018-08-01 19:06:03 +0200964 typval_T *argv)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000965{
966 typval_T rettv;
967
Bram Moolenaarded27a12018-08-01 19:06:03 +0200968 if (call_vim_function(func, argc, argv, &rettv) == FAIL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000969 return NULL;
970
971 if (rettv.v_type != VAR_LIST)
972 {
Bram Moolenaar55e93662022-09-10 13:52:26 +0100973 semsg(_(e_custom_list_completion_function_does_not_return_list_but_str),
974 vartype_name(rettv.v_type));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +0000975 clear_tv(&rettv);
976 return NULL;
977 }
978
979 return rettv.vval.v_list;
980}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981
Bram Moolenaare70dd112022-01-21 16:31:11 +0000982#if defined(FEAT_FOLDING) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983/*
Bram Moolenaar32b3f822021-01-06 21:59:39 +0100984 * Evaluate "arg", which is 'foldexpr'.
985 * Note: caller must set "curwin" to match "arg".
986 * Returns the foldlevel, and any character preceding it in "*cp". Doesn't
987 * give error messages.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988 */
989 int
Bram Moolenaare70dd112022-01-21 16:31:11 +0000990eval_foldexpr(win_T *wp, int *cp)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000991{
Bram Moolenaare70dd112022-01-21 16:31:11 +0000992 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +0000993 typval_T tv;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +0200994 varnumber_T retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995 char_u *s;
Bram Moolenaare70dd112022-01-21 16:31:11 +0000996 sctx_T saved_sctx = current_sctx;
Bram Moolenaard1f56e62006-02-22 21:25:37 +0000997 int use_sandbox = was_set_insecurely((char_u *)"foldexpr",
Bram Moolenaara4e0b972022-10-01 19:43:52 +0100998 OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001000 arg = skipwhite(wp->w_p_fde);
Bram Moolenaare70dd112022-01-21 16:31:11 +00001001 current_sctx = wp->w_p_script_ctx[WV_FDE];
1002
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 ++emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001004 if (use_sandbox)
1005 ++sandbox;
zeertzjqcfe45652022-05-27 17:26:55 +01001006 ++textlock;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001007 *cp = NUL;
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001008
Bram Moolenaara4e0b972022-10-01 19:43:52 +01001009 // Evaluate the expression. If the expression is "FuncName()" call the
1010 // function directly.
1011 if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012 retval = 0;
1013 else
1014 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01001015 // If the result is a number, just return the number.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001016 if (tv.v_type == VAR_NUMBER)
1017 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001018 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 retval = 0;
1020 else
1021 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01001022 // If the result is a string, check if there is a non-digit before
1023 // the number.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001024 s = tv.vval.v_string;
zeertzjqa991ce92023-10-06 19:16:36 +02001025 if (*s != NUL && !VIM_ISDIGIT(*s) && *s != '-')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001026 *cp = *s++;
1027 retval = atol((char *)s);
1028 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001029 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030 }
1031 --emsg_off;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00001032 if (use_sandbox)
1033 --sandbox;
zeertzjqcfe45652022-05-27 17:26:55 +01001034 --textlock;
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02001035 clear_evalarg(&EVALARG_EVALUATE, NULL);
Bram Moolenaare70dd112022-01-21 16:31:11 +00001036 current_sctx = saved_sctx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001037
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001038 return (int)retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039}
1040#endif
1041
Ernie Rael64885642023-10-04 20:16:22 +02001042#ifdef LOG_LOCKVAR
1043typedef struct flag_string_S
1044{
1045 int flag;
1046 char *str;
1047} flag_string_T;
1048
1049 static char *
1050flags_tostring(int flags, flag_string_T *_fstring, char *buf, size_t n)
1051{
1052 char *p = buf;
1053 *p = NUL;
1054 for (flag_string_T *fstring = _fstring; fstring->flag; ++fstring)
1055 {
1056 if ((fstring->flag & flags) != 0)
1057 {
1058 size_t len = STRLEN(fstring->str);
1059 if (n > p - buf + len + 7)
1060 {
1061 STRCAT(p, fstring->str);
1062 p += len;
1063 STRCAT(p, " ");
1064 ++p;
1065 }
1066 else
1067 {
1068 STRCAT(buf, "...");
1069 break;
1070 }
1071 }
1072 }
1073 return buf;
1074}
1075
1076flag_string_T glv_flag_strings[] = {
1077 { GLV_QUIET, "QUIET" },
1078 { GLV_NO_AUTOLOAD, "NO_AUTOLOAD" },
1079 { GLV_READ_ONLY, "READ_ONLY" },
1080 { GLV_NO_DECL, "NO_DECL" },
1081 { GLV_COMPILING, "COMPILING" },
1082 { GLV_ASSIGN_WITH_OP, "ASSIGN_WITH_OP" },
1083 { GLV_PREFER_FUNC, "PREFER_FUNC" },
1084 { 0, NULL }
1085};
1086#endif
1087
Bram Moolenaar071d4272004-06-13 20:20:40 +00001088/*
Ernie Raelee865f32023-09-29 19:53:55 +02001089 * Fill in "lp" using "root". This is used in a special case when
1090 * "get_lval()" parses a bare word when "lval_root" is not NULL.
1091 *
1092 * This is typically called with "lval_root" as "root". For a class, find
1093 * the name from lp in the class from root, fill in lval_T if found. For a
1094 * complex type, list/dict use it as the result; just put the root into
1095 * ll_tv.
1096 *
1097 * "lval_root" is a hack used during run-time/instr-execution to provide the
1098 * starting point for "get_lval()" to traverse a chain of indexes. In some
1099 * cases get_lval sees a bare name and uses this function to populate the
1100 * lval_T.
1101 *
1102 * For setting up "lval_root" (currently only used with lockvar)
1103 * compile_lock_unlock - pushes object on stack (which becomes lval_root)
1104 * execute_instructions: ISN_LOCKUNLOCK - sets lval_root from stack.
1105 */
1106 static void
Ernie Rael4c8da022023-10-11 21:35:11 +02001107fill_lval_from_lval_root(lval_T *lp, lval_root_T *lr)
Ernie Raelee865f32023-09-29 19:53:55 +02001108{
1109#ifdef LOG_LOCKVAR
Ernie Rael4c8da022023-10-11 21:35:11 +02001110 ch_log(NULL, "LKVAR: fill_lval_from_lval_root(): name %s, tv %p",
1111 lp->ll_name, (void*)lr->lr_tv);
Ernie Raelee865f32023-09-29 19:53:55 +02001112#endif
Ernie Rael4c8da022023-10-11 21:35:11 +02001113 if (lr->lr_tv == NULL)
1114 return;
Ernie Rael64885642023-10-04 20:16:22 +02001115 if (!lr->lr_is_arg && lr->lr_tv->v_type == VAR_CLASS)
Ernie Raelee865f32023-09-29 19:53:55 +02001116 {
Ernie Rael64885642023-10-04 20:16:22 +02001117 if (lr->lr_tv->vval.v_class != NULL)
Ernie Raelee865f32023-09-29 19:53:55 +02001118 {
1119 // Special special case. Look for a bare class variable reference.
Ernie Rael64885642023-10-04 20:16:22 +02001120 class_T *cl = lr->lr_tv->vval.v_class;
Ernie Raelee865f32023-09-29 19:53:55 +02001121 int m_idx;
1122 ocmember_T *m = class_member_lookup(cl, lp->ll_name,
1123 lp->ll_name_end - lp->ll_name, &m_idx);
1124 if (m != NULL)
1125 {
1126 // Assuming "inside class" since bare reference.
Ernie Rael64885642023-10-04 20:16:22 +02001127 lp->ll_class = lr->lr_tv->vval.v_class;
Ernie Raelee865f32023-09-29 19:53:55 +02001128 lp->ll_oi = m_idx;
1129 lp->ll_valtype = m->ocm_type;
1130 lp->ll_tv = &lp->ll_class->class_members_tv[m_idx];
1131#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +02001132 ch_log(NULL, "LKVAR: ... class member %s.%s",
1133 lp->ll_class->class_name, lp->ll_name);
Ernie Raelee865f32023-09-29 19:53:55 +02001134#endif
1135 return;
1136 }
1137 }
1138 }
1139
1140#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +02001141 ch_log(NULL, "LKVAR: ... type: %s", vartype_name(lr->lr_tv->v_type));
Ernie Raelee865f32023-09-29 19:53:55 +02001142#endif
Ernie Rael64885642023-10-04 20:16:22 +02001143 lp->ll_tv = lr->lr_tv;
Ernie Raelee865f32023-09-29 19:53:55 +02001144 lp->ll_is_root = TRUE;
1145}
1146
1147/*
Ernie Rael64885642023-10-04 20:16:22 +02001148 * Check if the class has permission to access the member.
1149 * Returns OK or FAIL.
1150 */
1151 static int
1152get_lval_check_access(
1153 class_T *cl_exec, // executing class, NULL if :def or script level
1154 class_T *cl, // class which contains the member
1155 ocmember_T *om, // member being accessed
1156 char_u *p, // char after member name
1157 int flags) // GLV flags to check if writing to lval
1158{
1159#ifdef LOG_LOCKVAR
1160 ch_log(NULL, "LKVAR: get_lval_check_access(), cl_exec %p, cl %p, %c",
1161 (void*)cl_exec, (void*)cl, *p);
1162#endif
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001163 if (cl_exec != NULL && cl_exec == cl)
1164 return OK;
1165
1166 char *msg = NULL;
1167 switch (om->ocm_access)
Ernie Rael64885642023-10-04 20:16:22 +02001168 {
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001169 case VIM_ACCESS_PRIVATE:
1170 msg = e_cannot_access_protected_variable_str;
1171 break;
1172 case VIM_ACCESS_READ:
1173 // If [idx] or .key following, read only OK.
1174 if (*p == '[' || *p == '.')
Ernie Raele6c9aa52023-10-06 19:55:52 +02001175 break;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001176 if ((flags & GLV_READ_ONLY) == 0)
1177 {
1178 if (IS_ENUM(cl))
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001179 {
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001180 if (om->ocm_type->tt_type == VAR_OBJECT)
1181 semsg(_(e_enumvalue_str_cannot_be_modified),
1182 cl->class_name, om->ocm_name);
Yegappan Lakshmanan3164cf82024-03-28 10:36:42 +01001183 else
1184 msg = e_variable_is_not_writable_str;
1185 }
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001186 else
1187 msg = e_variable_is_not_writable_str;
1188 }
1189 break;
1190 case VIM_ACCESS_ALL:
1191 break;
1192 }
1193 if (msg != NULL)
1194 {
1195 emsg_var_cl_define(msg, om->ocm_name, 0, cl);
1196 return FAIL;
Ernie Rael64885642023-10-04 20:16:22 +02001197 }
1198 return OK;
1199}
1200
1201/*
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001202 * Get lval information for a variable imported from script "imp_sid". On
1203 * success, updates "lp" with the variable name, type, script ID and typval.
1204 * The variable name starts at or after "p".
1205 * If "rettv" is not NULL it points to the value to be assigned. This used to
1206 * match the rhs and lhs types.
1207 * Returns a pointer to the character after the variable name if the imported
1208 * variable is valid and writable.
1209 * Returns NULL if the variable is not exported or typval is not found or the
1210 * rhs type doesn't match the lhs type or the variable is not writable.
1211 */
1212 static char_u *
1213get_lval_imported(
1214 lval_T *lp,
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001215 scid_T imp_sid,
1216 char_u *p,
1217 dictitem_T **dip,
Yegappan Lakshmanan9937d8b2024-05-08 20:24:33 +02001218 int fne_flags)
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001219{
1220 ufunc_T *ufunc;
1221 type_T *type = NULL;
1222 int cc;
1223 int rc = FAIL;
1224
1225 p = skipwhite(p);
1226
1227 import_check_sourced_sid(&imp_sid);
1228 lp->ll_sid = imp_sid;
1229 lp->ll_name = p;
1230 p = find_name_end(lp->ll_name, NULL, NULL, fne_flags);
1231 lp->ll_name_end = p;
1232
1233 // check the item is exported
1234 cc = *p;
1235 *p = NUL;
1236 if (find_exported(imp_sid, lp->ll_name, &ufunc, &type, NULL, NULL,
1237 TRUE) == -1)
1238 goto failed;
1239
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001240 // Get the typval for the exported item
1241 hashtab_T *ht = &SCRIPT_VARS(imp_sid);
1242 if (ht == NULL)
1243 goto failed;
1244
1245 dictitem_T *di = find_var_in_ht(ht, 0, lp->ll_name, TRUE);
1246 if (di == NULL)
Yegappan Lakshmanan3fa8f772024-04-04 21:42:07 +02001247 // script is autoloaded. So variable will be found later
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001248 goto success;
1249
1250 *dip = di;
1251
1252 // Check whether the variable is writable.
1253 svar_T *sv = find_typval_in_script(&di->di_tv, imp_sid, FALSE);
1254 if (sv != NULL && sv->sv_const != 0)
1255 {
1256 semsg(_(e_cannot_change_readonly_variable_str), lp->ll_name);
1257 goto failed;
1258 }
1259
1260 // check whether variable is locked
1261 if (value_check_lock(di->di_tv.v_lock, lp->ll_name, FALSE))
1262 goto failed;
1263
1264 lp->ll_tv = &di->di_tv;
Yegappan Lakshmanan9937d8b2024-05-08 20:24:33 +02001265 lp->ll_valtype = type;
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001266
1267success:
1268 rc = OK;
1269
1270failed:
1271 *p = cc;
1272 return rc == OK ? p : NULL;
1273}
1274
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001275typedef enum {
1276 GLV_FAIL,
1277 GLV_OK,
1278 GLV_STOP
1279} glv_status_T;
1280
1281/*
1282 * Get an Dict lval variable that can be assigned a value to: "name",
1283 * "name[expr]", "name[expr][expr]", "name.key", "name.key[expr]" etc.
1284 * "name" points to the start of the name.
1285 * If "rettv" is not NULL it points to the value to be assigned.
1286 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1287 * wrong; must end in space or cmd separator.
1288 *
1289 * flags:
1290 * GLV_QUIET: do not give error messages
1291 * GLV_READ_ONLY: will not change the variable
1292 * GLV_NO_AUTOLOAD: do not use script autoloading
1293 *
1294 * The Dict is returned in 'lp'. Returns GLV_OK on success and GLV_FAIL on
1295 * failure. Returns GLV_STOP to stop processing the characters following
1296 * 'key_end'.
1297 */
1298 static int
1299get_lval_dict_item(
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001300 lval_T *lp,
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001301 char_u *name,
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001302 char_u *key,
1303 int len,
1304 char_u **key_end,
1305 typval_T *var1,
1306 int flags,
1307 int unlet,
1308 typval_T *rettv)
1309{
1310 int quiet = flags & GLV_QUIET;
1311 char_u *p = *key_end;
1312
1313 if (len == -1)
1314 {
1315 // "[key]": get key from "var1"
1316 key = tv_get_string_chk(var1); // is number or string
1317 if (key == NULL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001318 return GLV_FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001319 }
1320 lp->ll_list = NULL;
1321 lp->ll_object = NULL;
1322 lp->ll_class = NULL;
1323
1324 // a NULL dict is equivalent with an empty dict
1325 if (lp->ll_tv->vval.v_dict == NULL)
1326 {
1327 lp->ll_tv->vval.v_dict = dict_alloc();
1328 if (lp->ll_tv->vval.v_dict == NULL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001329 return GLV_FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001330 ++lp->ll_tv->vval.v_dict->dv_refcount;
1331 }
1332 lp->ll_dict = lp->ll_tv->vval.v_dict;
1333
1334 lp->ll_di = dict_find(lp->ll_dict, key, len);
1335
1336 // When assigning to a scope dictionary check that a function and
1337 // variable name is valid (only variable name unless it is l: or
1338 // g: dictionary). Disallow overwriting a builtin function.
1339 if (rettv != NULL && lp->ll_dict->dv_scope != 0)
1340 {
1341 int prevval;
1342
1343 if (len != -1)
1344 {
1345 prevval = key[len];
1346 key[len] = NUL;
1347 }
1348 else
1349 prevval = 0; // avoid compiler warning
1350 int wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
1351 && (rettv->v_type == VAR_FUNC
1352 || rettv->v_type == VAR_PARTIAL)
1353 && var_wrong_func_name(key, lp->ll_di == NULL))
1354 || !valid_varname(key, -1, TRUE);
1355 if (len != -1)
1356 key[len] = prevval;
1357 if (wrong)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001358 return GLV_FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001359 }
1360
1361 if (lp->ll_valtype != NULL)
1362 // use the type of the member
1363 lp->ll_valtype = lp->ll_valtype->tt_member;
1364
1365 if (lp->ll_di == NULL)
1366 {
1367 // Can't add "v:" or "a:" variable.
1368 if (lp->ll_dict == get_vimvar_dict()
1369 || &lp->ll_dict->dv_hashtab == get_funccal_args_ht())
1370 {
1371 semsg(_(e_illegal_variable_name_str), name);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001372 return GLV_FAIL;
1373 }
1374
1375 // Key does not exist in dict: may need to add it.
1376 if (*p == '[' || *p == '.' || unlet)
1377 {
1378 if (!quiet)
1379 semsg(_(e_key_not_present_in_dictionary_str), key);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001380 return GLV_FAIL;
1381 }
1382 if (len == -1)
1383 lp->ll_newkey = vim_strsave(key);
1384 else
1385 lp->ll_newkey = vim_strnsave(key, len);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001386 if (lp->ll_newkey == NULL)
1387 p = NULL;
1388
1389 *key_end = p;
1390 return GLV_STOP;
1391 }
1392 // existing variable, need to check if it can be changed
1393 else if ((flags & GLV_READ_ONLY) == 0
1394 && (var_check_ro(lp->ll_di->di_flags, name, FALSE)
1395 || var_check_lock(lp->ll_di->di_flags, name, FALSE)))
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001396 return GLV_FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001397
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001398 lp->ll_tv = &lp->ll_di->di_tv;
1399
1400 return GLV_OK;
1401}
1402
1403/*
1404 * Get an blob lval variable that can be assigned a value to: "name",
1405 * "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", etc.
1406 *
1407 * 'var1' specifies the starting blob index and 'var2' specifies the ending
1408 * blob index. If the first index is not specified in a range, then 'empty1'
1409 * is TRUE. If 'quiet' is TRUE, then error messages are not displayed for
1410 * invalid indexes.
1411 *
1412 * The blob is returned in 'lp'. Returns OK on success and FAIL on failure.
1413 */
1414 static int
1415get_lval_blob(
1416 lval_T *lp,
1417 typval_T *var1,
1418 typval_T *var2,
1419 int empty1,
1420 int quiet)
1421{
1422 long bloblen = blob_len(lp->ll_tv->vval.v_blob);
1423
1424 // Get the number and item for the only or first index of the List.
1425 if (empty1)
1426 lp->ll_n1 = 0;
1427 else
1428 // is number or string
1429 lp->ll_n1 = (long)tv_get_number(var1);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001430
1431 if (check_blob_index(bloblen, lp->ll_n1, quiet) == FAIL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001432 return FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001433 if (lp->ll_range && !lp->ll_empty2)
1434 {
1435 lp->ll_n2 = (long)tv_get_number(var2);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001436 if (check_blob_range(bloblen, lp->ll_n1, lp->ll_n2, quiet) == FAIL)
1437 return FAIL;
1438 }
1439
1440 if (!lp->ll_range)
1441 // Indexing a single byte in a blob. So the rhs type is a
1442 // number.
1443 lp->ll_valtype = &t_number;
1444
1445 lp->ll_blob = lp->ll_tv->vval.v_blob;
1446 lp->ll_tv = NULL;
1447
1448 return OK;
1449}
1450
1451/*
1452 * Get a List lval variable that can be assigned a value to: "name",
1453 * "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", etc.
1454 *
1455 * 'var1' specifies the starting List index and 'var2' specifies the ending
1456 * List index. If the first index is not specified in a range, then 'empty1'
1457 * is TRUE. If 'quiet' is TRUE, then error messages are not displayed for
1458 * invalid indexes.
1459 *
1460 * The List is returned in 'lp'. Returns OK on success and FAIL on failure.
1461 */
1462 static int
1463get_lval_list(
1464 lval_T *lp,
1465 typval_T *var1,
1466 typval_T *var2,
1467 int empty1,
1468 int flags,
1469 int quiet)
1470{
1471 /*
1472 * Get the number and item for the only or first index of the List.
1473 */
1474 if (empty1)
1475 lp->ll_n1 = 0;
1476 else
1477 // is number or string
1478 lp->ll_n1 = (long)tv_get_number(var1);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001479
1480 lp->ll_dict = NULL;
1481 lp->ll_object = NULL;
1482 lp->ll_class = NULL;
1483 lp->ll_list = lp->ll_tv->vval.v_list;
1484 lp->ll_li = check_range_index_one(lp->ll_list, &lp->ll_n1,
1485 (flags & GLV_ASSIGN_WITH_OP) == 0, quiet);
1486 if (lp->ll_li == NULL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001487 return FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001488
1489 if (lp->ll_valtype != NULL && !lp->ll_range)
1490 // use the type of the member
1491 lp->ll_valtype = lp->ll_valtype->tt_member;
1492
1493 /*
1494 * May need to find the item or absolute index for the second
1495 * index of a range.
1496 * When no index given: "lp->ll_empty2" is TRUE.
1497 * Otherwise "lp->ll_n2" is set to the second index.
1498 */
1499 if (lp->ll_range && !lp->ll_empty2)
1500 {
1501 lp->ll_n2 = (long)tv_get_number(var2);
1502 // is number or string
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001503 if (check_range_index_two(lp->ll_list,
1504 &lp->ll_n1, lp->ll_li, &lp->ll_n2, quiet) == FAIL)
1505 return FAIL;
1506 }
1507
1508 lp->ll_tv = &lp->ll_li->li_tv;
1509
1510 return OK;
1511}
1512
1513/*
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001514 * Get a class or object lval method in class "cl". The 'key' argument points
1515 * to the method name and 'key_end' points to the character after 'key'.
1516 * 'v_type' is VAR_CLASS or VAR_OBJECT.
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001517 *
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001518 * The method index, method function pointer and method type are returned in
1519 * "lp".
1520 */
1521 static void
1522get_lval_oc_method(
1523 lval_T *lp,
1524 class_T *cl,
1525 char_u *key,
1526 char_u *key_end,
1527 vartype_T v_type)
1528{
1529 // Look for a method with this name.
1530 // round 1: class functions (skipped for an object)
1531 // round 2: object methods
1532 for (int round = v_type == VAR_OBJECT ? 2 : 1; round <= 2; ++round)
1533 {
1534 int m_idx;
1535 ufunc_T *fp;
1536
1537 fp = method_lookup(cl, round == 1 ? VAR_CLASS : VAR_OBJECT,
1538 key, key_end - key, &m_idx);
1539 lp->ll_oi = m_idx;
1540 if (fp != NULL)
1541 {
1542 lp->ll_ufunc = fp;
1543 lp->ll_valtype = fp->uf_func_type;
1544 break;
1545 }
1546 }
1547}
1548
1549/*
1550 * Get a class or object lval variable in class "cl". The "key" argument
1551 * points to the variable name and "key_end" points to the character after
1552 * "key". "v_type" is VAR_CLASS or VAR_OBJECT. "cl_exec" is the class that is
1553 * executing, or NULL.
1554 *
1555 * The variable index, typval and type are returned in "lp". Returns FAIL if
1556 * the variable is not writable. Otherwise returns OK.
1557 */
1558 static int
1559get_lval_oc_variable(
1560 lval_T *lp,
1561 class_T *cl,
1562 char_u *key,
1563 char_u *key_end,
1564 vartype_T v_type,
1565 class_T *cl_exec,
1566 int flags)
1567{
1568 int m_idx;
1569 ocmember_T *om;
1570
1571 om = member_lookup(cl, v_type, key, key_end - key, &m_idx);
1572 lp->ll_oi = m_idx;
1573 if (om == NULL)
1574 return OK;
1575
1576 // Check variable is accessible
1577 if (get_lval_check_access(cl_exec, cl, om, key_end, flags) == FAIL)
1578 return FAIL;
1579
1580 // When lhs is used to modify the variable, check it is not a read-only
1581 // variable.
1582 if ((flags & GLV_READ_ONLY) == 0 && (*key_end != '.' && *key_end != '[')
1583 && oc_var_check_ro(cl, om))
1584 return FAIL;
1585
1586 lp->ll_valtype = om->ocm_type;
1587
1588 if (v_type == VAR_OBJECT)
1589 lp->ll_tv = ((typval_T *)(lp->ll_tv->vval.v_object + 1)) + m_idx;
1590 else
1591 lp->ll_tv = &cl->class_members_tv[m_idx];
1592
1593 return OK;
1594}
1595
1596/*
1597 * Get a Class or Object lval variable or method that can be assigned a value
1598 * to: "name", "name.key", "name.key[expr]" etc.
1599 *
1600 * The 'key' argument points to the member name and 'key_end' points to the
1601 * character after 'key'. 'v_type' is VAR_CLASS or VAR_OBJECT. 'cl_exec' is
1602 * the class that is executing, or NULL. If 'quiet' is TRUE, then error
1603 * messages are not displayed for invalid indexes.
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001604 *
1605 * The Class or Object is returned in 'lp'. Returns OK on success and FAIL on
1606 * failure.
1607 */
1608 static int
1609get_lval_class_or_obj(
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001610 lval_T *lp,
1611 char_u *key,
1612 char_u *key_end,
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001613 vartype_T v_type,
1614 class_T *cl_exec,
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001615 int flags,
1616 int quiet)
1617{
1618 lp->ll_dict = NULL;
1619 lp->ll_list = NULL;
1620
1621 class_T *cl;
1622 if (v_type == VAR_OBJECT)
1623 {
1624 if (lp->ll_tv->vval.v_object == NULL)
1625 {
1626 if (!quiet)
1627 emsg(_(e_using_null_object));
1628 return FAIL;
1629 }
1630 cl = lp->ll_tv->vval.v_object->obj_class;
1631 lp->ll_object = lp->ll_tv->vval.v_object;
1632 }
1633 else
1634 {
1635 cl = lp->ll_tv->vval.v_class;
1636 lp->ll_object = NULL;
1637 }
1638 lp->ll_class = cl;
1639
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001640 if (cl == NULL)
1641 // TODO: what if class is NULL?
1642 return OK;
1643
1644 lp->ll_valtype = NULL;
1645
1646 if (flags & GLV_PREFER_FUNC)
1647 get_lval_oc_method(lp, cl, key, key_end, v_type);
1648
1649 // Look for object/class member variable
1650 if (lp->ll_valtype == NULL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001651 {
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001652 if (get_lval_oc_variable(lp, cl, key, key_end, v_type, cl_exec, flags)
1653 == FAIL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001654 return FAIL;
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001655 }
1656
1657 if (lp->ll_valtype == NULL)
1658 {
1659 member_not_found_msg(cl, v_type, key, key_end - key);
1660 return FAIL;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02001661 }
1662
1663 return OK;
1664}
1665
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001666/*
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001667 * Check whether dot (".") is allowed after the variable "name" with type
1668 * "v_type". Only Dict, Class and Object types support a dot after the name.
1669 * Returns TRUE if dot is allowed after the name.
1670 */
1671 static int
1672dot_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
1673{
1674 if (v_type != VAR_DICT && v_type != VAR_OBJECT && v_type != VAR_CLASS)
1675 {
1676 if (!quiet)
1677 semsg(_(e_dot_not_allowed_after_str_str),
1678 vartype_name(v_type), name);
1679 return FALSE;
1680 }
1681
1682 return TRUE;
1683}
1684
1685/*
1686 * Check whether left bracket ("[") is allowed after the variable "name" with
1687 * type "v_type". Only Dict, List and Blob types support a bracket after the
1688 * variable name. Returns TRUE if bracket is allowed after the name.
1689 */
1690 static int
1691bracket_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
1692{
1693 if (v_type == VAR_CLASS || v_type == VAR_OBJECT)
1694 {
1695 if (!quiet)
1696 semsg(_(e_index_not_allowed_after_str_str),
1697 vartype_name(v_type), name);
1698 return FALSE;
1699 }
1700
1701 return TRUE;
1702}
1703
1704/*
1705 * Check whether the variable "name" with type "v_type" can be followed by an
1706 * index. Only Dict, List, Blob, Object and Class types support indexing.
1707 * Returns TRUE if indexing is allowed after the name.
1708 */
1709 static int
1710index_allowed_after_type(char_u *name, vartype_T v_type, int quiet)
1711{
1712 if (v_type != VAR_LIST && v_type != VAR_DICT && v_type != VAR_BLOB &&
1713 v_type != VAR_OBJECT && v_type != VAR_CLASS)
1714 {
1715 if (!quiet)
1716 semsg(_(e_index_not_allowed_after_str_str),
1717 vartype_name(v_type), name);
1718 return FALSE;
1719 }
1720
1721 return TRUE;
1722}
1723
1724/*
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001725 * Get the lval of a list/dict/blob/object/class subitem starting at "p". Loop
1726 * until no more [idx] or .key is following.
1727 *
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001728 * If "rettv" is not NULL it points to the value to be assigned.
1729 * "unlet" is TRUE for ":unlet".
1730 *
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001731 * Returns a pointer to the character after the subscript on success or NULL on
1732 * failure.
1733 */
1734 static char_u *
1735get_lval_subscript(
1736 lval_T *lp,
1737 char_u *p,
1738 char_u *name,
1739 typval_T *rettv,
1740 hashtab_T *ht,
1741 dictitem_T *v,
1742 int unlet,
1743 int flags, // GLV_ values
1744 class_T *cl_exec)
1745{
1746 int vim9script = in_vim9script();
1747 int quiet = flags & GLV_QUIET;
1748 char_u *key = NULL;
1749 int len;
1750 typval_T var1;
1751 typval_T var2;
1752 int empty1 = FALSE;
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001753 int rc = FAIL;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001754
1755 /*
1756 * Loop until no more [idx] or .key is following.
1757 */
1758 var1.v_type = VAR_UNKNOWN;
1759 var2.v_type = VAR_UNKNOWN;
1760
1761 while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.'))
1762 {
1763 vartype_T v_type = lp->ll_tv->v_type;
1764
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001765 if (*p == '.' && !dot_allowed_after_type(name, v_type, quiet))
1766 goto done;
1767
1768 if (*p == '[' && !bracket_allowed_after_type(name, v_type, quiet))
1769 goto done;
1770
1771 if (!index_allowed_after_type(name, v_type, quiet))
1772 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001773
1774 // A NULL list/blob works like an empty list/blob, allocate one now.
1775 int r = OK;
1776 if (v_type == VAR_LIST && lp->ll_tv->vval.v_list == NULL)
1777 r = rettv_list_alloc(lp->ll_tv);
1778 else if (v_type == VAR_BLOB && lp->ll_tv->vval.v_blob == NULL)
1779 r = rettv_blob_alloc(lp->ll_tv);
1780 if (r == FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001781 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001782
1783 if (lp->ll_range)
1784 {
1785 if (!quiet)
1786 emsg(_(e_slice_must_come_last));
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001787 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001788 }
1789#ifdef LOG_LOCKVAR
1790 ch_log(NULL, "LKVAR: get_lval() loop: p: %s, type: %s", p,
1791 vartype_name(v_type));
1792#endif
1793
1794 if (vim9script && lp->ll_valtype == NULL
1795 && v != NULL
1796 && lp->ll_tv == &v->di_tv
1797 && ht != NULL && ht == get_script_local_ht())
1798 {
1799 svar_T *sv = find_typval_in_script(lp->ll_tv, 0, TRUE);
1800
1801 // Vim9 script local variable: get the type
1802 if (sv != NULL)
1803 {
1804 lp->ll_valtype = sv->sv_type;
1805#ifdef LOG_LOCKVAR
1806 ch_log(NULL, "LKVAR: ... loop: vim9 assign type: %s",
1807 vartype_name(lp->ll_valtype->tt_type));
1808#endif
1809 }
1810 }
1811
1812 len = -1;
1813 if (*p == '.')
1814 {
1815 key = p + 1;
1816
1817 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
1818 ;
1819 if (len == 0)
1820 {
1821 if (!quiet)
1822 emsg(_(e_cannot_use_empty_key_for_dictionary));
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001823 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001824 }
1825 p = key + len;
1826 }
1827 else
1828 {
1829 // Get the index [expr] or the first index [expr: ].
1830 p = skipwhite(p + 1);
1831 if (*p == ':')
1832 empty1 = TRUE;
1833 else
1834 {
1835 empty1 = FALSE;
1836 if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) // recursive!
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001837 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001838 if (tv_get_string_chk(&var1) == NULL)
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001839 // not a number or string
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001840 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001841 p = skipwhite(p);
1842 }
1843
1844 // Optionally get the second index [ :expr].
1845 if (*p == ':')
1846 {
1847 if (v_type == VAR_DICT)
1848 {
1849 if (!quiet)
1850 emsg(_(e_cannot_slice_dictionary));
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001851 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001852 }
1853 if (rettv != NULL
1854 && !(rettv->v_type == VAR_LIST
1855 && rettv->vval.v_list != NULL)
1856 && !(rettv->v_type == VAR_BLOB
1857 && rettv->vval.v_blob != NULL))
1858 {
1859 if (!quiet)
1860 emsg(_(e_slice_requires_list_or_blob_value));
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001861 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001862 }
1863 p = skipwhite(p + 1);
1864 if (*p == ']')
1865 lp->ll_empty2 = TRUE;
1866 else
1867 {
1868 lp->ll_empty2 = FALSE;
1869 // recursive!
1870 if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001871 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001872 if (tv_get_string_chk(&var2) == NULL)
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001873 // not a number or string
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001874 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001875 }
1876 lp->ll_range = TRUE;
1877 }
1878 else
1879 lp->ll_range = FALSE;
1880
1881 if (*p != ']')
1882 {
1883 if (!quiet)
1884 emsg(_(e_missing_closing_square_brace));
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001885 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001886 }
1887
1888 // Skip to past ']'.
1889 ++p;
1890 }
1891#ifdef LOG_LOCKVAR
1892 if (len == -1)
1893 ch_log(NULL, "LKVAR: ... loop: p: %s, '[' key: %s", p,
1894 empty1 ? ":" : (char*)tv_get_string(&var1));
1895 else
1896 ch_log(NULL, "LKVAR: ... loop: p: %s, '.' key: %s", p, key);
1897#endif
1898
1899 if (v_type == VAR_DICT)
1900 {
1901 glv_status_T glv_status;
1902
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001903 glv_status = get_lval_dict_item(lp, name, key, len, &p, &var1,
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001904 flags, unlet, rettv);
1905 if (glv_status == GLV_FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001906 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001907 if (glv_status == GLV_STOP)
1908 break;
1909 }
1910 else if (v_type == VAR_BLOB)
1911 {
1912 if (get_lval_blob(lp, &var1, &var2, empty1, quiet) == FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001913 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001914
1915 break;
1916 }
1917 else if (v_type == VAR_LIST)
1918 {
1919 if (get_lval_list(lp, &var1, &var2, empty1, flags, quiet) == FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001920 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001921 }
1922 else // v_type == VAR_CLASS || v_type == VAR_OBJECT
1923 {
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02001924 if (get_lval_class_or_obj(lp, key, p, v_type, cl_exec, flags,
1925 quiet) == FAIL)
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001926 goto done;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001927 }
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001928
1929 clear_tv(&var1);
1930 clear_tv(&var2);
1931 var1.v_type = VAR_UNKNOWN;
1932 var2.v_type = VAR_UNKNOWN;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001933 }
1934
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001935 rc = OK;
1936
1937done:
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001938 clear_tv(&var1);
Yegappan Lakshmanandbac0da2024-05-25 20:23:54 +02001939 clear_tv(&var2);
1940 return rc == OK ? p : NULL;
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02001941}
1942
1943/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001944 * Get an lval: variable, Dict item or List item that can be assigned a value
1945 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
1946 * "name.key", "name.key[expr]" etc.
1947 * Indexing only works if "name" is an existing List or Dictionary.
1948 * "name" points to the start of the name.
1949 * If "rettv" is not NULL it points to the value to be assigned.
1950 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1951 * wrong; must end in space or cmd separator.
1952 *
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001953 * flags:
1954 * GLV_QUIET: do not give error messages
Bram Moolenaar3a257732017-02-21 20:47:13 +01001955 * GLV_READ_ONLY: will not change the variable
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001956 * GLV_NO_AUTOLOAD: do not use script autoloading
1957 *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001958 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00001959 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001960 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001961 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02001962 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001963get_lval(
1964 char_u *name,
1965 typval_T *rettv,
1966 lval_T *lp,
1967 int unlet,
1968 int skip,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01001969 int flags, // GLV_ values
1970 int fne_flags) // flags for find_name_end()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001971{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001972 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001973 char_u *expr_start, *expr_end;
1974 int cc;
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02001975 dictitem_T *v = NULL;
Bram Moolenaar896ad2c2020-11-21 14:03:43 +01001976 hashtab_T *ht = NULL;
Bram Moolenaar6d977d62014-01-14 15:24:39 +01001977 int quiet = flags & GLV_QUIET;
Ernie Rael86eda072023-09-05 07:33:48 +02001978 int writing = 0;
Bram Moolenaar4525a572022-02-13 11:57:33 +00001979 int vim9script = in_vim9script();
Ernie Rael64885642023-10-04 20:16:22 +02001980 class_T *cl_exec = NULL; // class that is executing, or NULL.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001981
Ernie Raelee865f32023-09-29 19:53:55 +02001982#ifdef LOG_LOCKVAR
Ernie Rael64885642023-10-04 20:16:22 +02001983 if (lval_root == NULL)
Ernie Rael4c8da022023-10-11 21:35:11 +02001984 ch_log(NULL, "LKVAR: get_lval(): name: %s, lval_root (nil)", name);
Ernie Rael64885642023-10-04 20:16:22 +02001985 else
Ernie Rael4c8da022023-10-11 21:35:11 +02001986 ch_log(NULL, "LKVAR: get_lval(): name: %s, lr_tv %p lr_is_arg %d",
1987 name, (void*)lval_root->lr_tv, lval_root->lr_is_arg);
Ernie Rael64885642023-10-04 20:16:22 +02001988 char buf[80];
Ernie Rael4c8da022023-10-11 21:35:11 +02001989 ch_log(NULL, "LKVAR: ...: GLV flags: %s",
Ernie Rael64885642023-10-04 20:16:22 +02001990 flags_tostring(flags, glv_flag_strings, buf, sizeof(buf)));
Ernie Raelee865f32023-09-29 19:53:55 +02001991#endif
1992
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01001993 // Clear everything in "lp".
Bram Moolenaara80faa82020-04-12 19:37:17 +02001994 CLEAR_POINTER(lp);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001995
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01001996 if (skip || (flags & GLV_COMPILING))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001997 {
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01001998 // When skipping or compiling just find the end of the name.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001999 lp->ll_name = name;
Bram Moolenaar9b5384b2020-06-29 22:31:36 +02002000 lp->ll_name_end = find_name_end(name, NULL, NULL,
2001 FNE_INCL_BR | fne_flags);
2002 return lp->ll_name_end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002003 }
2004
Bram Moolenaara749a422022-02-12 19:52:25 +00002005 // Cannot use "s:var" at the Vim9 script level. "s: type" is OK.
Bram Moolenaar4525a572022-02-13 11:57:33 +00002006 if (vim9script && at_script_level()
Bram Moolenaara749a422022-02-12 19:52:25 +00002007 && name[0] == 's' && name[1] == ':' && !VIM_ISWHITE(name[2]))
2008 {
2009 semsg(_(e_cannot_use_s_colon_in_vim9_script_str), name);
2010 return NULL;
2011 }
2012
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002013 // Find the end of the name.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002014 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002015 lp->ll_name_end = p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002016 if (expr_start != NULL)
2017 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002018 // Don't expand the name when we already know there is an error.
Bram Moolenaar1c465442017-03-12 20:10:05 +01002019 if (unlet && !VIM_ISWHITE(*p) && !ends_excmd(*p)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002020 && *p != '[' && *p != '.')
2021 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00002022 semsg(_(e_trailing_characters_str), p);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002023 return NULL;
2024 }
2025
2026 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2027 if (lp->ll_exp_name == NULL)
2028 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002029 // Report an invalid expression in braces, unless the
2030 // expression evaluation has been cancelled due to an
2031 // aborting error, an interrupt, or an exception.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002032 if (!aborting() && !quiet)
2033 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002034 emsg_severe = TRUE;
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00002035 semsg(_(e_invalid_argument_str), name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002036 return NULL;
2037 }
2038 }
2039 lp->ll_name = lp->ll_exp_name;
2040 }
2041 else
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002042 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002043 lp->ll_name = name;
2044
Bram Moolenaar4525a572022-02-13 11:57:33 +00002045 if (vim9script)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002046 {
Bram Moolenaar95dd9f22020-08-07 19:28:08 +02002047 // "a: type" is declaring variable "a" with a type, not "a:".
Bram Moolenaar2e17fef2022-03-18 19:44:48 +00002048 // However, "g:[key]" is indexing a dictionary.
2049 if (p == name + 2 && p[-1] == ':' && *p != '[')
Bram Moolenaar95dd9f22020-08-07 19:28:08 +02002050 {
2051 --p;
2052 lp->ll_name_end = p;
2053 }
Bram Moolenaarce93d162023-01-30 21:12:34 +00002054 if (*skipwhite(p) == ':')
Bram Moolenaar95dd9f22020-08-07 19:28:08 +02002055 {
Bram Moolenaarc653e4a2022-01-05 10:16:30 +00002056 char_u *tp = skipwhite(p + 1);
Bram Moolenaar60faf862021-08-23 22:22:45 +02002057
Bram Moolenaar9510d222022-09-11 15:14:05 +01002058 if (is_scoped_variable(name))
2059 {
2060 semsg(_(e_cannot_use_type_with_this_variable_str), name);
2061 return NULL;
2062 }
Bram Moolenaarce93d162023-01-30 21:12:34 +00002063 if (VIM_ISWHITE(*p))
2064 {
2065 semsg(_(e_no_white_space_allowed_before_colon_str), p);
2066 return NULL;
2067 }
Bram Moolenaar60faf862021-08-23 22:22:45 +02002068 if (tp == p + 1 && !quiet)
2069 {
2070 semsg(_(e_white_space_required_after_str_str), ":", p);
2071 return NULL;
2072 }
Bram Moolenaar4c8b5462022-03-16 20:01:39 +00002073 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
Bram Moolenaarc653e4a2022-01-05 10:16:30 +00002074 {
Bram Moolenaar4c8b5462022-03-16 20:01:39 +00002075 semsg(_(e_using_type_not_in_script_context_str), p);
2076 return NULL;
Bram Moolenaarc653e4a2022-01-05 10:16:30 +00002077 }
Yegappan Lakshmananb5a07192023-10-05 20:14:43 +02002078 if (vim9script && (flags & GLV_NO_DECL) &&
2079 !(flags & GLV_FOR_LOOP))
2080 {
2081 // Using a type and not in a "var" declaration.
2082 semsg(_(e_trailing_characters_str), p);
2083 return NULL;
2084 }
2085
Bram Moolenaarc653e4a2022-01-05 10:16:30 +00002086
Bram Moolenaar95dd9f22020-08-07 19:28:08 +02002087 // parse the type after the name
Bram Moolenaar4c8b5462022-03-16 20:01:39 +00002088 lp->ll_type = parse_type(&tp,
2089 &SCRIPT_ITEM(current_sctx.sc_sid)->sn_type_list,
2090 !quiet);
Bram Moolenaar9e68c322020-12-25 12:38:04 +01002091 if (lp->ll_type == NULL && !quiet)
2092 return NULL;
Bram Moolenaar95dd9f22020-08-07 19:28:08 +02002093 lp->ll_name_end = tp;
2094 }
Ernie Raelee865f32023-09-29 19:53:55 +02002095 // TODO: check inside class?
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002096 }
2097 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002098 if (lp->ll_name == NULL)
2099 return p;
2100
Bram Moolenaar62aec932022-01-29 21:45:34 +00002101 if (*p == '.')
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002102 {
Bram Moolenaar4b1d9632022-02-13 21:51:08 +00002103 imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, TRUE);
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002104 if (import != NULL)
2105 {
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02002106 p++; // skip '.'
Yegappan Lakshmanan9937d8b2024-05-08 20:24:33 +02002107 p = get_lval_imported(lp, import->imp_sid, p, &v, fne_flags);
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02002108 if (p == NULL)
Bram Moolenaar5d982692022-01-12 15:15:27 +00002109 return NULL;
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002110 }
2111 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002112
Ernie Rael0f058d12023-10-14 11:25:04 +02002113 // Without [idx] or .key we are done.
2114 if (*p != '[' && *p != '.')
Ernie Raelee865f32023-09-29 19:53:55 +02002115 {
2116 if (lval_root != NULL)
Ernie Rael4c8da022023-10-11 21:35:11 +02002117 fill_lval_from_lval_root(lp, lval_root);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002118 return p;
Ernie Raelee865f32023-09-29 19:53:55 +02002119 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002120
Ernie Rael0f058d12023-10-14 11:25:04 +02002121 if (vim9script && lval_root != NULL)
2122 cl_exec = lval_root->lr_cl_exec;
Ernie Rael4c8da022023-10-11 21:35:11 +02002123 if (vim9script && lval_root != NULL && lval_root->lr_tv != NULL)
Bram Moolenaaraacc9662021-08-13 19:40:51 +02002124 {
2125 // using local variable
Ernie Rael64885642023-10-04 20:16:22 +02002126 lp->ll_tv = lval_root->lr_tv;
Bram Moolenaar78a9c2e2021-08-13 20:12:13 +02002127 v = NULL;
Bram Moolenaaraacc9662021-08-13 19:40:51 +02002128 }
Yegappan Lakshmananf1750ca2024-04-02 20:41:04 +02002129 else if (lp->ll_tv == NULL)
Bram Moolenaaraacc9662021-08-13 19:40:51 +02002130 {
2131 cc = *p;
2132 *p = NUL;
2133 // When we would write to the variable pass &ht and prevent autoload.
2134 writing = !(flags & GLV_READ_ONLY);
2135 v = find_var(lp->ll_name, writing ? &ht : NULL,
Bram Moolenaar32b3f822021-01-06 21:59:39 +01002136 (flags & GLV_NO_AUTOLOAD) || writing);
Bram Moolenaaraacc9662021-08-13 19:40:51 +02002137 if (v == NULL && !quiet)
2138 semsg(_(e_undefined_variable_str), lp->ll_name);
2139 *p = cc;
2140 if (v == NULL)
2141 return NULL;
2142 lp->ll_tv = &v->di_tv;
2143 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002144
Bram Moolenaar4525a572022-02-13 11:57:33 +00002145 if (vim9script && (flags & GLV_NO_DECL) == 0)
Bram Moolenaar8f22f5c2020-12-19 22:10:13 +01002146 {
2147 if (!quiet)
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00002148 semsg(_(e_variable_already_declared_str), lp->ll_name);
Bram Moolenaar8f22f5c2020-12-19 22:10:13 +01002149 return NULL;
2150 }
2151
Yegappan Lakshmanan44cadaa2024-05-24 07:44:10 +02002152 // If the next character is a "." or a "[", then process the subitem.
2153 p = get_lval_subscript(lp, p, name, rettv, ht, v, unlet, flags, cl_exec);
2154 if (p == NULL)
2155 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002156
Yegappan Lakshmanan9937d8b2024-05-08 20:24:33 +02002157 if (vim9script && lp->ll_valtype != NULL && rettv != NULL)
2158 {
2159 where_T where = WHERE_INIT;
2160
2161 // In a vim9 script, do type check and make sure the variable is
2162 // writable.
2163 if (check_typval_type(lp->ll_valtype, rettv, where) == FAIL)
2164 return NULL;
2165 }
2166
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002167 lp->ll_name_end = p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002168 return p;
2169}
2170
2171/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002172 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002173 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02002174 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002175clear_lval(lval_T *lp)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002176{
2177 vim_free(lp->ll_exp_name);
2178 vim_free(lp->ll_newkey);
2179}
2180
2181/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002182 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002183 * "endp" points to just after the parsed name.
Bram Moolenaarff697e62019-02-12 22:28:33 +01002184 * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
2185 * "%" for "%=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002186 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002187 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002188set_var_lval(
2189 lval_T *lp,
2190 char_u *endp,
2191 typval_T *rettv,
2192 int copy,
Bram Moolenaarf785aa12021-02-11 21:19:34 +01002193 int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
2194 char_u *op,
2195 int var_idx) // index for "let [a, b] = list"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196{
2197 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002198 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002199
2200 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002201 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002202 cc = *endp;
2203 *endp = NUL;
h-east2bd6a092023-05-19 19:01:17 +01002204 if (in_vim9script() && check_reserved_name(lp->ll_name, FALSE) == FAIL)
Bram Moolenaard0edaf92021-05-28 21:06:08 +02002205 return;
2206
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002207 if (lp->ll_blob != NULL)
2208 {
2209 int error = FALSE, val;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002210
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002211 if (op != NULL && *op != '=')
2212 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00002213 semsg(_(e_wrong_variable_type_for_str_equal), op);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002214 return;
2215 }
Bram Moolenaara187c432020-09-16 21:08:28 +02002216 if (value_check_lock(lp->ll_blob->bv_lock, lp->ll_name, FALSE))
Bram Moolenaar021bda52020-08-17 21:07:22 +02002217 return;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002218
2219 if (lp->ll_range && rettv->v_type == VAR_BLOB)
2220 {
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01002221 if (lp->ll_empty2)
2222 lp->ll_n2 = blob_len(lp->ll_blob) - 1;
2223
Bram Moolenaar68452172021-04-12 21:21:02 +02002224 if (blob_set_range(lp->ll_blob, lp->ll_n1, lp->ll_n2,
2225 rettv) == FAIL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002226 return;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002227 }
2228 else
2229 {
2230 val = (int)tv_get_number_chk(rettv, &error);
2231 if (!error)
Bram Moolenaare8209b92021-04-18 16:08:52 +02002232 blob_set_append(lp->ll_blob, lp->ll_n1, val);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002233 }
2234 }
2235 else if (op != NULL && *op != '=')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002236 {
Bram Moolenaar79518e22017-02-17 16:31:35 +01002237 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002238
Bram Moolenaarf6a8d422021-04-13 21:48:03 +02002239 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
2240 && (flags & ASSIGN_FOR_LOOP) == 0)
Bram Moolenaar9937a052019-06-15 15:45:06 +02002241 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00002242 emsg(_(e_cannot_modify_existing_variable));
Bram Moolenaar9937a052019-06-15 15:45:06 +02002243 *endp = cc;
2244 return;
2245 }
2246
Bram Moolenaarff697e62019-02-12 22:28:33 +01002247 // handle +=, -=, *=, /=, %= and .=
Bram Moolenaar79518e22017-02-17 16:31:35 +01002248 di = NULL;
John Marriottbd4614f2024-11-18 20:25:21 +01002249 if (eval_variable(lp->ll_name, (int)(lp->ll_name_end - lp->ll_name),
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002250 lp->ll_sid, &tv, &di, EVAL_VAR_VERBOSE) == OK)
Bram Moolenaar79518e22017-02-17 16:31:35 +01002251 {
Ernie Raele75fde62023-12-21 17:18:54 +01002252 if (di != NULL && check_typval_is_value(&di->di_tv) == FAIL)
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02002253 {
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02002254 clear_tv(&tv);
2255 return;
2256 }
2257
Bram Moolenaar79518e22017-02-17 16:31:35 +01002258 if ((di == NULL
Bram Moolenaar05c00c02019-02-11 22:00:11 +01002259 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2260 && !tv_check_lock(&di->di_tv, lp->ll_name, FALSE)))
Bram Moolenaar79518e22017-02-17 16:31:35 +01002261 && tv_op(&tv, rettv, op) == OK)
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002262 set_var_const(lp->ll_name, lp->ll_sid, NULL, &tv, FALSE,
Yegappan Lakshmanan1af35632024-02-06 11:03:36 +01002263 ASSIGN_NO_DECL | ASSIGN_COMPOUND_OP, 0);
Bram Moolenaar79518e22017-02-17 16:31:35 +01002264 clear_tv(&tv);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002265 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002266 }
Bram Moolenaar79518e22017-02-17 16:31:35 +01002267 else
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02002268 {
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02002269 if (lp->ll_type != NULL && check_typval_arg_type(lp->ll_type, rettv,
2270 NULL, 0) == FAIL)
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02002271 return;
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002272 set_var_const(lp->ll_name, lp->ll_sid, lp->ll_type, rettv, copy,
Bram Moolenaarf785aa12021-02-11 21:19:34 +01002273 flags, var_idx);
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02002274 }
Bram Moolenaar79518e22017-02-17 16:31:35 +01002275 *endp = cc;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002276 }
Bram Moolenaara187c432020-09-16 21:08:28 +02002277 else if (value_check_lock(lp->ll_newkey == NULL
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002278 ? lp->ll_tv->v_lock
Bram Moolenaar77354e72015-04-21 16:49:05 +02002279 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002280 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002281 else if (lp->ll_range)
2282 {
Bram Moolenaarf6a8d422021-04-13 21:48:03 +02002283 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
2284 && (flags & ASSIGN_FOR_LOOP) == 0)
Bram Moolenaar9937a052019-06-15 15:45:06 +02002285 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002286 emsg(_(e_cannot_lock_range));
Bram Moolenaar9937a052019-06-15 15:45:06 +02002287 return;
2288 }
2289
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02002290 (void)list_assign_range(lp->ll_list, rettv->vval.v_list,
2291 lp->ll_n1, lp->ll_n2, lp->ll_empty2, op, lp->ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002292 }
2293 else
2294 {
2295 /*
Bram Moolenaar3d473ee2022-12-14 20:59:32 +00002296 * Assign to a List, Dictionary or Object item.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002297 */
Bram Moolenaarf6a8d422021-04-13 21:48:03 +02002298 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
2299 && (flags & ASSIGN_FOR_LOOP) == 0)
Bram Moolenaar9937a052019-06-15 15:45:06 +02002300 {
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002301 emsg(_(e_cannot_lock_list_or_dict));
Bram Moolenaar9937a052019-06-15 15:45:06 +02002302 return;
2303 }
Bram Moolenaar10c65862020-10-08 21:16:42 +02002304
2305 if (lp->ll_valtype != NULL
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02002306 && check_typval_arg_type(lp->ll_valtype, rettv,
2307 NULL, 0) == FAIL)
Bram Moolenaar10c65862020-10-08 21:16:42 +02002308 return;
2309
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002310 if (lp->ll_newkey != NULL)
2311 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002312 if (op != NULL && *op != '=')
2313 {
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00002314 semsg(_(e_key_not_present_in_dictionary_str), lp->ll_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002315 return;
2316 }
Bram Moolenaar6f1d2aa2021-06-01 21:21:55 +02002317 if (dict_wrong_func_name(lp->ll_tv->vval.v_dict, rettv,
2318 lp->ll_newkey))
Bram Moolenaar3d9c4ee2021-05-31 22:15:26 +02002319 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002320
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002321 // Need to add an item to the Dictionary.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002322 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002323 if (di == NULL)
2324 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002325 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2326 {
2327 vim_free(di);
2328 return;
2329 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002330 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002331 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002332 else if (op != NULL && *op != '=')
2333 {
2334 tv_op(lp->ll_tv, rettv, op);
2335 return;
2336 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002337 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002338 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002339
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002340 /*
2341 * Assign the value to the variable or list item.
2342 */
2343 if (copy)
2344 copy_tv(rettv, lp->ll_tv);
2345 else
2346 {
2347 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002348 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002349 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002350 }
2351 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002352}
2353
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002354/*
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002355 * Handle "blob1 += blob2".
2356 * Returns OK or FAIL.
2357 */
2358 static int
2359tv_op_blob(typval_T *tv1, typval_T *tv2, char_u *op)
2360{
2361 if (*op != '+' || tv2->v_type != VAR_BLOB)
2362 return FAIL;
2363
2364 // Blob += Blob
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02002365 if (tv2->vval.v_blob == NULL)
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002366 return OK;
2367
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02002368 if (tv1->vval.v_blob == NULL)
2369 {
2370 tv1->vval.v_blob = tv2->vval.v_blob;
2371 ++tv1->vval.v_blob->bv_refcount;
2372 return OK;
2373 }
2374
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002375 blob_T *b1 = tv1->vval.v_blob;
2376 blob_T *b2 = tv2->vval.v_blob;
2377 int len = blob_len(b2);
2378
2379 for (int i = 0; i < len; i++)
2380 ga_append(&b1->bv_ga, blob_get(b2, i));
2381
2382 return OK;
2383}
2384
2385/*
2386 * Handle "list1 += list2".
2387 * Returns OK or FAIL.
2388 */
2389 static int
2390tv_op_list(typval_T *tv1, typval_T *tv2, char_u *op)
2391{
2392 if (*op != '+' || tv2->v_type != VAR_LIST)
2393 return FAIL;
2394
2395 // List += List
2396 if (tv2->vval.v_list == NULL)
2397 return OK;
2398
2399 if (tv1->vval.v_list == NULL)
2400 {
2401 tv1->vval.v_list = tv2->vval.v_list;
2402 ++tv1->vval.v_list->lv_refcount;
2403 }
2404 else
2405 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2406
2407 return OK;
2408}
2409
2410/*
2411 * Handle number operations:
2412 * nr += nr , nr -= nr , nr *=nr , nr /= nr , nr %= nr
2413 *
2414 * Returns OK or FAIL.
2415 */
2416 static int
2417tv_op_number(typval_T *tv1, typval_T *tv2, char_u *op)
2418{
2419 varnumber_T n;
2420 int failed = FALSE;
2421
2422 n = tv_get_number(tv1);
2423 if (tv2->v_type == VAR_FLOAT)
2424 {
2425 float_T f = n;
2426
2427 if (*op == '%')
2428 return FAIL;
2429 switch (*op)
2430 {
2431 case '+': f += tv2->vval.v_float; break;
2432 case '-': f -= tv2->vval.v_float; break;
2433 case '*': f *= tv2->vval.v_float; break;
2434 case '/': f /= tv2->vval.v_float; break;
2435 }
2436 clear_tv(tv1);
2437 tv1->v_type = VAR_FLOAT;
2438 tv1->vval.v_float = f;
2439 }
2440 else
2441 {
2442 switch (*op)
2443 {
2444 case '+': n += tv_get_number(tv2); break;
2445 case '-': n -= tv_get_number(tv2); break;
2446 case '*': n *= tv_get_number(tv2); break;
2447 case '/': n = num_divide(n, tv_get_number(tv2), &failed); break;
2448 case '%': n = num_modulus(n, tv_get_number(tv2), &failed); break;
2449 }
2450 clear_tv(tv1);
2451 tv1->v_type = VAR_NUMBER;
2452 tv1->vval.v_number = n;
2453 }
2454
2455 return failed ? FAIL : OK;
2456}
2457
2458/*
2459 * Handle "str1 .= str2"
2460 * Returns OK or FAIL.
2461 */
2462 static int
2463tv_op_string(typval_T *tv1, typval_T *tv2, char_u *op UNUSED)
2464{
2465 char_u numbuf[NUMBUFLEN];
2466 char_u *s;
2467
2468 if (tv2->v_type == VAR_FLOAT)
2469 return FAIL;
2470
2471 // str .= str
2472 s = tv_get_string(tv1);
2473 s = concat_str(s, tv_get_string_buf(tv2, numbuf));
2474 clear_tv(tv1);
2475 tv1->v_type = VAR_STRING;
2476 tv1->vval.v_string = s;
2477
2478 return OK;
2479}
2480
2481/*
2482 * Handle "tv1 += tv2", "tv1 -= tv2", "tv1 *= tv2", "tv1 /= tv2", "tv1 %= tv2"
2483 * and "tv1 .= tv2"
2484 * Returns OK or FAIL.
2485 */
2486 static int
2487tv_op_nr_or_string(typval_T *tv1, typval_T *tv2, char_u *op)
2488{
2489 if (tv2->v_type == VAR_LIST)
2490 return FAIL;
2491
2492 if (vim_strchr((char_u *)"+-*/%", *op) != NULL)
2493 return tv_op_number(tv1, tv2, op);
2494
2495 return tv_op_string(tv1, tv2, op);
2496}
2497
2498/*
2499 * Handle "f1 += f2", "f1 -= f2", "f1 *= f2", "f1 /= f2".
2500 * Returns OK or FAIL.
2501 */
2502 static int
2503tv_op_float(typval_T *tv1, typval_T *tv2, char_u *op)
2504{
2505 float_T f;
2506
2507 if (*op == '%' || *op == '.'
2508 || (tv2->v_type != VAR_FLOAT
2509 && tv2->v_type != VAR_NUMBER
2510 && tv2->v_type != VAR_STRING))
2511 return FAIL;
2512
2513 if (tv2->v_type == VAR_FLOAT)
2514 f = tv2->vval.v_float;
2515 else
2516 f = tv_get_number(tv2);
2517 switch (*op)
2518 {
2519 case '+': tv1->vval.v_float += f; break;
2520 case '-': tv1->vval.v_float -= f; break;
2521 case '*': tv1->vval.v_float *= f; break;
2522 case '/': tv1->vval.v_float /= f; break;
2523 }
2524
2525 return OK;
2526}
2527
2528/*
Bram Moolenaarff697e62019-02-12 22:28:33 +01002529 * Handle "tv1 += tv2", "tv1 -= tv2", "tv1 *= tv2", "tv1 /= tv2", "tv1 %= tv2"
2530 * and "tv1 .= tv2"
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002531 * Returns OK or FAIL.
2532 */
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02002533 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002534tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002535{
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002536 // Can't do anything with a Funcref or Dict on the right.
Bram Moolenaarf24f51d2021-08-01 12:01:49 +02002537 // v:true and friends only work with "..=".
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002538 if (tv2->v_type == VAR_FUNC || tv2->v_type == VAR_DICT
2539 || ((tv2->v_type == VAR_BOOL || tv2->v_type == VAR_SPECIAL)
2540 && *op != '.'))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002541 {
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002542 semsg(_(e_wrong_variable_type_for_str_equal), op);
2543 return FAIL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002544 }
2545
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002546 int retval = FAIL;
2547 switch (tv1->v_type)
2548 {
2549 case VAR_UNKNOWN:
2550 case VAR_ANY:
2551 case VAR_VOID:
2552 case VAR_DICT:
2553 case VAR_FUNC:
2554 case VAR_PARTIAL:
2555 case VAR_BOOL:
2556 case VAR_SPECIAL:
2557 case VAR_JOB:
2558 case VAR_CHANNEL:
2559 case VAR_INSTR:
2560 case VAR_OBJECT:
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002561 case VAR_CLASS:
2562 case VAR_TYPEALIAS:
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02002563 break;
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002564
2565 case VAR_BLOB:
2566 retval = tv_op_blob(tv1, tv2, op);
2567 break;
2568
2569 case VAR_LIST:
2570 retval = tv_op_list(tv1, tv2, op);
2571 break;
2572
2573 case VAR_NUMBER:
2574 case VAR_STRING:
2575 retval = tv_op_nr_or_string(tv1, tv2, op);
2576 break;
2577
2578 case VAR_FLOAT:
2579 retval = tv_op_float(tv1, tv2, op);
2580 break;
2581 }
2582
2583 if (retval != OK)
Ernie Raele75fde62023-12-21 17:18:54 +01002584 semsg(_(e_wrong_variable_type_for_str_equal), op);
Yegappan Lakshmanan4ceb4dc2024-05-12 09:24:35 +02002585
2586 return retval;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002587}
2588
2589/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002590 * Evaluate the expression used in a ":for var in expr" command.
2591 * "arg" points to "var".
2592 * Set "*errp" to TRUE for an error, FALSE otherwise;
2593 * Return a pointer that holds the info. Null when there is an error.
2594 */
2595 void *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002596eval_for_line(
2597 char_u *arg,
2598 int *errp,
Bram Moolenaarb171fb12020-06-24 20:34:03 +02002599 exarg_T *eap,
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002600 evalarg_T *evalarg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002601{
Bram Moolenaar33570922005-01-25 22:26:29 +00002602 forinfo_T *fi;
Bram Moolenaar404557e2021-07-05 21:41:48 +02002603 char_u *var_list_end;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002604 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002605 typval_T tv;
2606 list_T *l;
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002607 int skip = !(evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002608
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002609 *errp = TRUE; // default: there is an error
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002610
Bram Moolenaarc799fe22019-05-28 23:08:19 +02002611 fi = ALLOC_CLEAR_ONE(forinfo_T);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002612 if (fi == NULL)
2613 return NULL;
2614
Bram Moolenaar404557e2021-07-05 21:41:48 +02002615 var_list_end = skip_var_list(arg, TRUE, &fi->fi_varcount,
2616 &fi->fi_semicolon, FALSE);
2617 if (var_list_end == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002618 return fi;
2619
Bram Moolenaar404557e2021-07-05 21:41:48 +02002620 expr = skipwhite_and_linebreak(var_list_end, evalarg);
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002621 if (expr[0] != 'i' || expr[1] != 'n'
2622 || !(expr[2] == NUL || VIM_ISWHITE(expr[2])))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002623 {
Bram Moolenaar404557e2021-07-05 21:41:48 +02002624 if (in_vim9script() && *expr == ':' && expr != var_list_end)
2625 semsg(_(e_no_white_space_allowed_before_colon_str), expr);
2626 else
Bram Moolenaar3a846e62022-01-01 16:21:00 +00002627 emsg(_(e_missing_in_after_for));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002628 return fi;
2629 }
2630
2631 if (skip)
2632 ++emsg_skip;
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002633 expr = skipwhite_and_linebreak(expr + 2, evalarg);
2634 if (eval0(expr, &tv, eap, evalarg) == OK)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002635 {
2636 *errp = FALSE;
2637 if (!skip)
2638 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002639 if (tv.v_type == VAR_LIST)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002640 {
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002641 l = tv.vval.v_list;
2642 if (l == NULL)
2643 {
2644 // a null list is like an empty list: do nothing
2645 clear_tv(&tv);
2646 }
2647 else
2648 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002649 // Need a real list here.
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02002650 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002651
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002652 // No need to increment the refcount, it's already set for
2653 // the list being used in "tv".
2654 fi->fi_list = l;
2655 list_add_watch(l, &fi->fi_lw);
2656 fi->fi_lw.lw_item = l->lv_first;
2657 }
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002658 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002659 else if (tv.v_type == VAR_BLOB)
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002660 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002661 fi->fi_bi = 0;
2662 if (tv.vval.v_blob != NULL)
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002663 {
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002664 typval_T btv;
2665
2666 // Make a copy, so that the iteration still works when the
2667 // blob is changed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002668 blob_copy(tv.vval.v_blob, &btv);
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002669 fi->fi_blob = btv.vval.v_blob;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002670 }
Bram Moolenaardd29ea12019-01-23 21:56:21 +01002671 clear_tv(&tv);
Bram Moolenaard8585ed2016-05-01 23:05:53 +02002672 }
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002673 else if (tv.v_type == VAR_STRING)
2674 {
2675 fi->fi_byte_idx = 0;
2676 fi->fi_string = tv.vval.v_string;
2677 tv.vval.v_string = NULL;
2678 if (fi->fi_string == NULL)
2679 fi->fi_string = vim_strsave((char_u *)"");
2680 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002681 else
2682 {
Sean Dewar80d73952021-08-04 19:25:54 +02002683 emsg(_(e_string_list_or_blob_required));
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002684 clear_tv(&tv);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002685 }
2686 }
2687 }
2688 if (skip)
2689 --emsg_skip;
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002690 fi->fi_break_count = evalarg->eval_break_count;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002691
2692 return fi;
2693}
2694
2695/*
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002696 * Used when looping over a :for line, skip the "in expr" part.
2697 */
2698 void
2699skip_for_lines(void *fi_void, evalarg_T *evalarg)
2700{
2701 forinfo_T *fi = (forinfo_T *)fi_void;
2702 int i;
2703
2704 for (i = 0; i < fi->fi_break_count; ++i)
Bram Moolenaare442d592022-05-05 12:20:28 +01002705 eval_next_line(NULL, evalarg);
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02002706}
2707
2708/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002709 * Use the first item in a ":for" list. Advance to the next.
2710 * Assign the values to the variable (list). "arg" points to the first one.
2711 * Return TRUE when a valid item was found, FALSE when at end of list or
2712 * something wrong.
2713 */
2714 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002715next_for_item(void *fi_void, char_u *arg)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002716{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002717 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002718 int result;
Bram Moolenaarf6a8d422021-04-13 21:48:03 +02002719 int flag = ASSIGN_FOR_LOOP | (in_vim9script()
Bram Moolenaar442b29c2021-07-05 22:23:00 +02002720 ? (ASSIGN_FINAL
2721 // first round: error if variable exists
2722 | (fi->fi_bi == 0 ? 0 : ASSIGN_DECL)
Bram Moolenaar766ae5b2022-09-14 00:30:51 +01002723 | ASSIGN_NO_MEMBER_TYPE
2724 | ASSIGN_UPDATE_BLOCK_ID)
Bram Moolenaarf6a8d422021-04-13 21:48:03 +02002725 : 0);
Bram Moolenaar33570922005-01-25 22:26:29 +00002726 listitem_T *item;
Bram Moolenaarad2d4962021-07-18 17:08:50 +02002727 int skip_assign = in_vim9script() && arg[0] == '_'
2728 && !eval_isnamec(arg[1]);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002729
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002730 if (fi->fi_blob != NULL)
2731 {
2732 typval_T tv;
2733
2734 if (fi->fi_bi >= blob_len(fi->fi_blob))
2735 return FALSE;
2736 tv.v_type = VAR_NUMBER;
2737 tv.v_lock = VAR_FIXED;
2738 tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
2739 ++fi->fi_bi;
Bram Moolenaarad2d4962021-07-18 17:08:50 +02002740 if (skip_assign)
2741 return TRUE;
Bram Moolenaar9937a052019-06-15 15:45:06 +02002742 return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002743 fi->fi_varcount, flag, NULL) == OK;
2744 }
2745
2746 if (fi->fi_string != NULL)
2747 {
2748 typval_T tv;
2749 int len;
2750
2751 len = mb_ptr2len(fi->fi_string + fi->fi_byte_idx);
2752 if (len == 0)
2753 return FALSE;
2754 tv.v_type = VAR_STRING;
2755 tv.v_lock = VAR_FIXED;
2756 tv.vval.v_string = vim_strnsave(fi->fi_string + fi->fi_byte_idx, len);
2757 fi->fi_byte_idx += len;
Bram Moolenaar442b29c2021-07-05 22:23:00 +02002758 ++fi->fi_bi;
Bram Moolenaarad2d4962021-07-18 17:08:50 +02002759 if (skip_assign)
2760 result = TRUE;
2761 else
2762 result = ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002763 fi->fi_varcount, flag, NULL) == OK;
Bram Moolenaarbb5d87c2021-03-26 22:15:26 +01002764 vim_free(tv.vval.v_string);
2765 return result;
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01002766 }
2767
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002768 item = fi->fi_lw.lw_item;
2769 if (item == NULL)
2770 result = FALSE;
2771 else
2772 {
2773 fi->fi_lw.lw_item = item->li_next;
Bram Moolenaar442b29c2021-07-05 22:23:00 +02002774 ++fi->fi_bi;
Bram Moolenaarad2d4962021-07-18 17:08:50 +02002775 if (skip_assign)
2776 result = TRUE;
2777 else
2778 result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002779 fi->fi_varcount, flag, NULL) == OK);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002780 }
2781 return result;
2782}
2783
2784/*
2785 * Free the structure used to store info used by ":for".
2786 */
2787 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002788free_for_info(void *fi_void)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002789{
Bram Moolenaar33570922005-01-25 22:26:29 +00002790 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002791
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002792 if (fi == NULL)
2793 return;
2794 if (fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002795 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002796 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002797 list_unref(fi->fi_list);
2798 }
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002799 else if (fi->fi_blob != NULL)
Bram Moolenaarecc8bc42019-01-13 16:07:21 +01002800 blob_unref(fi->fi_blob);
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01002801 else
2802 vim_free(fi->fi_string);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002803 vim_free(fi);
2804}
2805
Bram Moolenaar071d4272004-06-13 20:20:40 +00002806 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002807set_context_for_expression(
2808 expand_T *xp,
2809 char_u *arg,
2810 cmdidx_T cmdidx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002811{
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002812 int has_expr = cmdidx != CMD_let && cmdidx != CMD_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002814 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002815
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002816 if (cmdidx == CMD_let || cmdidx == CMD_var
2817 || cmdidx == CMD_const || cmdidx == CMD_final)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002818 {
2819 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002820 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002821 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002822 // ":let var1 var2 ...": find last space.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002823 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002824 {
2825 xp->xp_pattern = p;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01002826 MB_PTR_BACK(arg, p);
Bram Moolenaar1c465442017-03-12 20:10:05 +01002827 if (VIM_ISWHITE(*p))
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002828 break;
2829 }
2830 return;
2831 }
2832 }
2833 else
2834 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2835 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836 while ((xp->xp_pattern = vim_strpbrk(arg,
2837 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2838 {
2839 c = *xp->xp_pattern;
2840 if (c == '&')
2841 {
2842 c = xp->xp_pattern[1];
2843 if (c == '&')
2844 {
2845 ++xp->xp_pattern;
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002846 xp->xp_context = has_expr ? EXPAND_EXPRESSION : EXPAND_NOTHING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002847 }
2848 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002849 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002850 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002851 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
2852 xp->xp_pattern += 2;
2853
2854 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002855 }
2856 else if (c == '$')
2857 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002858 // environment variable
Bram Moolenaar071d4272004-06-13 20:20:40 +00002859 xp->xp_context = EXPAND_ENV_VARS;
2860 }
2861 else if (c == '=')
2862 {
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002863 has_expr = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002864 xp->xp_context = EXPAND_EXPRESSION;
2865 }
Bram Moolenaara32095f2016-03-28 19:27:13 +02002866 else if (c == '#'
2867 && xp->xp_context == EXPAND_EXPRESSION)
2868 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002869 // Autoload function/variable contains '#'.
Bram Moolenaara32095f2016-03-28 19:27:13 +02002870 break;
2871 }
Bram Moolenaar8a349ff2014-11-12 20:09:06 +01002872 else if ((c == '<' || c == '#')
Bram Moolenaar071d4272004-06-13 20:20:40 +00002873 && xp->xp_context == EXPAND_FUNCTIONS
2874 && vim_strchr(xp->xp_pattern, '(') == NULL)
2875 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002876 // Function name can start with "<SNR>" and contain '#'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002877 break;
2878 }
Bram Moolenaar30fd8202020-09-26 15:09:30 +02002879 else if (has_expr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002880 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002881 if (c == '"') // string
Bram Moolenaar071d4272004-06-13 20:20:40 +00002882 {
2883 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2884 if (c == '\\' && xp->xp_pattern[1] != NUL)
2885 ++xp->xp_pattern;
2886 xp->xp_context = EXPAND_NOTHING;
2887 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002888 else if (c == '\'') // literal string
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002890 // Trick: '' is like stopping and starting a literal string.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002891 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2892 /* skip */ ;
2893 xp->xp_context = EXPAND_NOTHING;
2894 }
2895 else if (c == '|')
2896 {
2897 if (xp->xp_pattern[1] == '|')
2898 {
2899 ++xp->xp_pattern;
2900 xp->xp_context = EXPAND_EXPRESSION;
2901 }
2902 else
2903 xp->xp_context = EXPAND_COMMANDS;
2904 }
2905 else
2906 xp->xp_context = EXPAND_EXPRESSION;
2907 }
2908 else
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002909 // Doesn't look like something valid, expand as an expression
2910 // anyway.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002911 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002912 arg = xp->xp_pattern;
2913 if (*arg != NUL)
2914 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2915 /* skip */ ;
2916 }
Bram Moolenaar4941b5e2020-12-24 17:15:53 +01002917
2918 // ":exe one two" completes "two"
2919 if ((cmdidx == CMD_execute
2920 || cmdidx == CMD_echo
2921 || cmdidx == CMD_echon
Bram Moolenaar37fef162022-08-29 18:16:32 +01002922 || cmdidx == CMD_echomsg
2923 || cmdidx == CMD_echowindow)
Bram Moolenaar4941b5e2020-12-24 17:15:53 +01002924 && xp->xp_context == EXPAND_EXPRESSION)
2925 {
2926 for (;;)
2927 {
2928 char_u *n = skiptowhite(arg);
2929
2930 if (n == arg || IS_WHITE_OR_NUL(*skipwhite(n)))
2931 break;
2932 arg = skipwhite(n);
2933 }
2934 }
2935
Bram Moolenaar071d4272004-06-13 20:20:40 +00002936 xp->xp_pattern = arg;
2937}
2938
Bram Moolenaar071d4272004-06-13 20:20:40 +00002939/*
Bram Moolenaarea6553b2016-03-27 15:13:38 +02002940 * Return TRUE if "pat" matches "text".
2941 * Does not use 'cpo' and always uses 'magic'.
2942 */
Bram Moolenaarecaa70e2019-07-14 14:55:39 +02002943 int
Bram Moolenaarea6553b2016-03-27 15:13:38 +02002944pattern_match(char_u *pat, char_u *text, int ic)
2945{
2946 int matches = FALSE;
2947 char_u *save_cpo;
2948 regmatch_T regmatch;
2949
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002950 // avoid 'l' flag in 'cpoptions'
Bram Moolenaarea6553b2016-03-27 15:13:38 +02002951 save_cpo = p_cpo;
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01002952 p_cpo = empty_option;
Bram Moolenaarea6553b2016-03-27 15:13:38 +02002953 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
2954 if (regmatch.regprog != NULL)
2955 {
2956 regmatch.rm_ic = ic;
2957 matches = vim_regexec_nl(&regmatch, text, (colnr_T)0);
2958 vim_regfree(regmatch.regprog);
2959 }
2960 p_cpo = save_cpo;
2961 return matches;
2962}
2963
2964/*
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002965 * Handle a name followed by "(". Both for just "name(arg)" and for
2966 * "expr->name(arg)".
2967 * Returns OK or FAIL.
2968 */
2969 static int
2970eval_func(
2971 char_u **arg, // points to "(", will be advanced
Bram Moolenaare6b53242020-07-01 17:28:33 +02002972 evalarg_T *evalarg,
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002973 char_u *name,
2974 int name_len,
2975 typval_T *rettv,
Bram Moolenaar32e35112020-05-14 22:41:15 +02002976 int flags,
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002977 typval_T *basetv) // "expr" for "expr->name(arg)"
2978{
Bram Moolenaar32e35112020-05-14 22:41:15 +02002979 int evaluate = flags & EVAL_EVALUATE;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002980 char_u *s = name;
2981 int len = name_len;
2982 partial_T *partial;
2983 int ret = OK;
Bram Moolenaar32b3f822021-01-06 21:59:39 +01002984 type_T *type = NULL;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00002985 int found_var = FALSE;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002986
2987 if (!evaluate)
2988 check_vars(s, len);
2989
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002990 // If "s" is the name of a variable of type VAR_FUNC
2991 // use its contents.
Bram Moolenaar32b3f822021-01-06 21:59:39 +01002992 s = deref_func_name(s, &len, &partial,
Bram Moolenaar937610b2022-01-19 17:21:29 +00002993 in_vim9script() ? &type : NULL, !evaluate, FALSE, &found_var);
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002994
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01002995 // Need to make a copy, in case evaluating the arguments makes
2996 // the name invalid.
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002997 s = vim_strsave(s);
zeertzjqb7f6f932023-04-13 22:12:50 +01002998 if (s == NULL || (evaluate && *s == NUL))
Bram Moolenaar761fdf02019-08-05 23:10:16 +02002999 ret = FAIL;
3000 else
3001 {
3002 funcexe_T funcexe;
3003
3004 // Invoke the function.
Bram Moolenaara80faa82020-04-12 19:37:17 +02003005 CLEAR_FIELD(funcexe);
Bram Moolenaar851f86b2021-12-13 14:26:44 +00003006 funcexe.fe_firstline = curwin->w_cursor.lnum;
3007 funcexe.fe_lastline = curwin->w_cursor.lnum;
3008 funcexe.fe_evaluate = evaluate;
3009 funcexe.fe_partial = partial;
Yegappan Lakshmanan1ace49f2023-10-15 09:53:41 +02003010 if (partial != NULL)
3011 {
3012 funcexe.fe_object = partial->pt_obj;
3013 if (funcexe.fe_object != NULL)
3014 ++funcexe.fe_object->obj_refcount;
3015 }
Bram Moolenaar851f86b2021-12-13 14:26:44 +00003016 funcexe.fe_basetv = basetv;
3017 funcexe.fe_check_type = type;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003018 funcexe.fe_found_var = found_var;
Bram Moolenaare6b53242020-07-01 17:28:33 +02003019 ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003020 }
3021 vim_free(s);
3022
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003023 // If evaluate is FALSE rettv->v_type was not set in
3024 // get_func_tv, but it's needed in handle_subscript() to parse
3025 // what follows. So set it here.
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003026 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(')
3027 {
3028 rettv->vval.v_string = NULL;
3029 rettv->v_type = VAR_FUNC;
3030 }
3031
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003032 // Stop the expression evaluation when immediately
3033 // aborting on error, or when an interrupt occurred or
3034 // an exception was thrown but not caught.
Bram Moolenaar761fdf02019-08-05 23:10:16 +02003035 if (evaluate && aborting())
3036 {
3037 if (ret == OK)
3038 clear_tv(rettv);
3039 ret = FAIL;
3040 }
3041 return ret;
3042}
3043
3044/*
Bram Moolenaar75ebd2a2022-06-03 17:39:46 +01003045 * After a NL, skip over empty lines and comment-only lines.
3046 */
3047 static char_u *
3048newline_skip_comments(char_u *arg)
3049{
3050 char_u *p = arg + 1;
3051
3052 for (;;)
3053 {
3054 p = skipwhite(p);
3055
3056 if (*p == NUL)
3057 break;
3058 if (vim9_comment_start(p))
3059 {
3060 char_u *nl = vim_strchr(p, NL);
3061
3062 if (nl == NULL)
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02003063 break;
Bram Moolenaar75ebd2a2022-06-03 17:39:46 +01003064 p = nl;
3065 }
3066 if (*p != NL)
3067 break;
3068 ++p; // skip another NL
3069 }
3070 return p;
3071}
3072
3073/*
Bram Moolenaar93be1642020-10-11 21:34:41 +02003074 * Get the next line source line without advancing. But do skip over comment
3075 * lines.
Bram Moolenaar03717bf2021-04-28 20:00:40 +02003076 * Only called for Vim9 script.
Bram Moolenaar93be1642020-10-11 21:34:41 +02003077 */
3078 static char_u *
3079getline_peek_skip_comments(evalarg_T *evalarg)
3080{
3081 for (;;)
3082 {
3083 char_u *next = getline_peek(evalarg->eval_getline,
3084 evalarg->eval_cookie);
3085 char_u *p;
3086
3087 if (next == NULL)
3088 break;
3089 p = skipwhite(next);
3090 if (*p != NUL && !vim9_comment_start(p))
3091 return next;
Bram Moolenaare442d592022-05-05 12:20:28 +01003092 if (eval_next_line(NULL, evalarg) == NULL)
Bram Moolenaar43216612022-03-25 11:16:28 +00003093 break;
Bram Moolenaar93be1642020-10-11 21:34:41 +02003094 }
3095 return NULL;
3096}
3097
3098/*
Bram Moolenaar962d7212020-07-04 14:15:00 +02003099 * If inside Vim9 script, "arg" points to the end of a line (ignoring a #
3100 * comment) and there is a next line, return the next line (skipping blanks)
3101 * and set "getnext".
Bram Moolenaara6aa1642021-04-23 19:32:23 +02003102 * Otherwise return the next non-white at or after "arg" and set "getnext" to
3103 * FALSE.
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003104 * "arg" must point somewhere inside a line, not at the start.
3105 */
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003106 char_u *
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003107eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
3108{
Bram Moolenaar9d489562020-07-30 20:08:50 +02003109 char_u *p = skipwhite(arg);
3110
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003111 *getnext = FALSE;
Bram Moolenaareb6880b2020-07-12 17:07:05 +02003112 if (in_vim9script()
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003113 && evalarg != NULL
Bram Moolenaara13e7ac2022-05-06 21:24:31 +01003114 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL
3115 || *p == NL)
Bram Moolenaare442d592022-05-05 12:20:28 +01003116 && (*p == NUL || *p == NL
3117 || (vim9_comment_start(p) && VIM_ISWHITE(p[-1]))))
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003118 {
Bram Moolenaar9d489562020-07-30 20:08:50 +02003119 char_u *next;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003120
Bram Moolenaare442d592022-05-05 12:20:28 +01003121 if (*p == NL)
Bram Moolenaar75ebd2a2022-06-03 17:39:46 +01003122 next = newline_skip_comments(p);
Bram Moolenaare442d592022-05-05 12:20:28 +01003123 else if (evalarg->eval_cookie != NULL)
Bram Moolenaar93be1642020-10-11 21:34:41 +02003124 next = getline_peek_skip_comments(evalarg);
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003125 else
Bram Moolenaar9d489562020-07-30 20:08:50 +02003126 next = peek_next_line_from_context(evalarg->eval_cctx);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003127
Bram Moolenaar9d489562020-07-30 20:08:50 +02003128 if (next != NULL)
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003129 {
Bram Moolenaar69082912022-09-22 21:35:19 +01003130 *getnext = *p != NL;
Bram Moolenaar9d489562020-07-30 20:08:50 +02003131 return skipwhite(next);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003132 }
3133 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02003134 return p;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003135}
3136
3137/*
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003138 * To be called after eval_next_non_blank() sets "getnext" to TRUE.
Bram Moolenaar03717bf2021-04-28 20:00:40 +02003139 * Only called for Vim9 script.
Yegappan Lakshmanan28d71b52024-01-12 17:21:55 +01003140 *
3141 * If "arg" is not NULL, then the caller should assign the return value to
3142 * "arg".
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003143 */
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003144 char_u *
Bram Moolenaare442d592022-05-05 12:20:28 +01003145eval_next_line(char_u *arg, evalarg_T *evalarg)
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003146{
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003147 garray_T *gap = &evalarg->eval_ga;
3148 char_u *line;
3149
Bram Moolenaar39be4982022-05-06 21:51:50 +01003150 if (arg != NULL)
3151 {
3152 if (*arg == NL)
Bram Moolenaar75ebd2a2022-06-03 17:39:46 +01003153 return newline_skip_comments(arg);
Bram Moolenaar39be4982022-05-06 21:51:50 +01003154 // Truncate before a trailing comment, so that concatenating the lines
3155 // won't turn the rest into a comment.
3156 if (*skipwhite(arg) == '#')
3157 *arg = NUL;
3158 }
Bram Moolenaare442d592022-05-05 12:20:28 +01003159
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003160 if (evalarg->eval_cookie != NULL)
Bram Moolenaar825b5442020-08-20 15:52:21 +02003161 line = evalarg->eval_getline(0, evalarg->eval_cookie, 0,
3162 GETLINE_CONCAT_ALL);
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003163 else
3164 line = next_line_from_context(evalarg->eval_cctx, TRUE);
Bram Moolenaar43216612022-03-25 11:16:28 +00003165 if (line == NULL)
3166 return NULL;
3167
Bram Moolenaarb7a78f72020-06-28 18:43:40 +02003168 ++evalarg->eval_break_count;
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003169 if (gap->ga_itemsize > 0 && ga_grow(gap, 1) == OK)
3170 {
Bram Moolenaar03717bf2021-04-28 20:00:40 +02003171 char_u *p = skipwhite(line);
3172
3173 // Going to concatenate the lines after parsing. For an empty or
3174 // comment line use an empty string.
3175 if (*p == NUL || vim9_comment_start(p))
3176 {
3177 vim_free(line);
3178 line = vim_strsave((char_u *)"");
3179 }
3180
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003181 ((char_u **)gap->ga_data)[gap->ga_len] = line;
3182 ++gap->ga_len;
3183 }
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003184 else if (evalarg->eval_cookie != NULL)
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003185 {
Bram Moolenaar91c7cbf2022-08-18 13:28:31 +01003186 free_eval_tofree_later(evalarg);
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003187 evalarg->eval_tofree = line;
3188 }
Bram Moolenaarc6ba2f92021-07-18 13:42:29 +02003189
3190 // Advanced to the next line, "arg" no longer points into the previous
Yegappan Lakshmanan28d71b52024-01-12 17:21:55 +01003191 // line. The caller assigns the return value to "arg".
3192 // If "arg" is NULL, then the return value is discarded. In that case,
3193 // "arg" still points to the previous line. So don't reset
3194 // "eval_using_cmdline".
3195 if (arg != NULL)
3196 evalarg->eval_using_cmdline = FALSE;
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003197 return skipwhite(line);
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003198}
3199
Bram Moolenaare6b53242020-07-01 17:28:33 +02003200/*
3201 * Call eval_next_non_blank() and get the next line if needed.
3202 */
Bram Moolenaar9215f012020-06-27 21:18:00 +02003203 char_u *
3204skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg)
3205{
3206 int getnext;
Bram Moolenaarce7eada2021-12-15 15:41:44 +00003207 char_u *p = skipwhite_and_nl(arg);
Bram Moolenaar9215f012020-06-27 21:18:00 +02003208
Bram Moolenaar962d7212020-07-04 14:15:00 +02003209 if (evalarg == NULL)
3210 return skipwhite(arg);
Bram Moolenaar9215f012020-06-27 21:18:00 +02003211 eval_next_non_blank(p, evalarg, &getnext);
3212 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01003213 return eval_next_line(arg, evalarg);
Bram Moolenaar9215f012020-06-27 21:18:00 +02003214 return p;
3215}
3216
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003217/*
Bram Moolenaara4e0b972022-10-01 19:43:52 +01003218 * The "eval" functions have an "evalarg" argument: When NULL or
3219 * "evalarg->eval_flags" does not have EVAL_EVALUATE, then the argument is only
3220 * parsed but not executed. The functions may return OK, but the rettv will be
3221 * of type VAR_UNKNOWN. The functions still returns FAIL for a syntax error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222 */
3223
3224/*
3225 * Handle zero level expression.
3226 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003227 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003228 * Note: "rettv.v_lock" is not set.
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003229 * "evalarg" can be NULL, EVALARG_EVALUATE or a pointer.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003230 * Return OK or FAIL.
3231 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02003232 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01003233eval0(
3234 char_u *arg,
3235 typval_T *rettv,
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003236 exarg_T *eap,
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003237 evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003238{
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003239 return eval0_retarg(arg, rettv, eap, evalarg, NULL);
3240}
3241
3242/*
Bram Moolenaara4e0b972022-10-01 19:43:52 +01003243 * If "arg" is a simple function call without arguments then call it and return
3244 * the result. Otherwise return NOTDONE.
3245 */
3246 int
3247may_call_simple_func(
3248 char_u *arg,
3249 typval_T *rettv)
3250{
3251 char_u *parens = (char_u *)strstr((char *)arg, "()");
3252 int r = NOTDONE;
3253
3254 // If the expression is "FuncName()" then we can skip a lot of overhead.
3255 if (parens != NULL && *skipwhite(parens + 2) == NUL)
3256 {
3257 char_u *p = STRNCMP(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg;
3258
3259 if (to_name_end(p, TRUE) == parens)
zeertzjqc1ed7882024-08-01 22:46:54 +02003260 r = call_simple_func(arg, (size_t)(parens - arg), rettv);
Bram Moolenaara4e0b972022-10-01 19:43:52 +01003261 }
3262 return r;
3263}
3264
3265/*
3266 * Handle zero level expression with optimization for a simple function call.
3267 * Same arguments and return value as eval0().
3268 */
3269 int
3270eval0_simple_funccal(
3271 char_u *arg,
3272 typval_T *rettv,
3273 exarg_T *eap,
3274 evalarg_T *evalarg)
3275{
3276 int r = may_call_simple_func(arg, rettv);
3277
3278 if (r == NOTDONE)
3279 r = eval0_retarg(arg, rettv, eap, evalarg, NULL);
3280 return r;
3281}
3282
3283/*
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003284 * Like eval0() but when "retarg" is not NULL store the pointer to after the
3285 * expression and don't check what comes after the expression.
3286 */
3287 int
3288eval0_retarg(
3289 char_u *arg,
3290 typval_T *rettv,
3291 exarg_T *eap,
3292 evalarg_T *evalarg,
3293 char_u **retarg)
3294{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003295 int ret;
3296 char_u *p;
Bram Moolenaar02929a32021-12-17 14:46:12 +00003297 char_u *expr_end;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003298 int did_emsg_before = did_emsg;
3299 int called_emsg_before = called_emsg;
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003300 int check_for_end = retarg == NULL;
Bram Moolenaarfae55a92021-06-17 22:08:30 +02003301 int end_error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003302
3303 p = skipwhite(arg);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003304 ret = eval1(&p, rettv, evalarg);
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003305
Bram Moolenaar79481362022-06-27 20:15:10 +01003306 if (ret != FAIL)
3307 {
3308 expr_end = p;
3309 p = skipwhite(p);
Bram Moolenaar02929a32021-12-17 14:46:12 +00003310
Bram Moolenaar79481362022-06-27 20:15:10 +01003311 // In Vim9 script a command block is not split at NL characters for
3312 // commands using an expression argument. Skip over a '#' comment to
3313 // check for a following NL. Require white space before the '#'.
3314 if (in_vim9script() && p > expr_end && retarg == NULL)
3315 while (*p == '#')
3316 {
3317 char_u *nl = vim_strchr(p, NL);
Bram Moolenaar02929a32021-12-17 14:46:12 +00003318
Bram Moolenaar79481362022-06-27 20:15:10 +01003319 if (nl == NULL)
3320 break;
3321 p = skipwhite(nl + 1);
3322 if (eap != NULL && *p != NUL)
3323 eap->nextcmd = p;
3324 check_for_end = FALSE;
3325 }
3326
3327 if (check_for_end)
3328 end_error = !ends_excmd2(arg, p);
3329 }
3330
Bram Moolenaarfae55a92021-06-17 22:08:30 +02003331 if (ret == FAIL || end_error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003332 {
3333 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003334 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003335 /*
3336 * Report the invalid expression unless the expression evaluation has
3337 * been cancelled due to an aborting error, an interrupt, or an
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01003338 * exception, or we already gave a more specific error.
3339 * Also check called_emsg for when using assert_fails().
Bram Moolenaar071d4272004-06-13 20:20:40 +00003340 */
Bram Moolenaar32e35112020-05-14 22:41:15 +02003341 if (!aborting()
3342 && did_emsg == did_emsg_before
3343 && called_emsg == called_emsg_before
Bram Moolenaar5c7a2992021-03-20 13:29:38 +01003344 && (!in_vim9script() || !vim9_bad_comment(p)))
Bram Moolenaarfae55a92021-06-17 22:08:30 +02003345 {
3346 if (end_error)
Bram Moolenaar74409f62022-01-01 15:58:22 +00003347 semsg(_(e_trailing_characters_str), p);
Bram Moolenaarfae55a92021-06-17 22:08:30 +02003348 else
Bram Moolenaar108010a2021-06-27 22:03:33 +02003349 semsg(_(e_invalid_expression_str), arg);
Bram Moolenaarfae55a92021-06-17 22:08:30 +02003350 }
Bram Moolenaard0fe6202020-12-05 17:11:12 +01003351
zeertzjqf2588b62023-05-05 17:22:35 +01003352 if (eap != NULL && p != NULL)
3353 {
3354 // Some of the expression may not have been consumed.
3355 // Only execute a next command if it cannot be a "||" operator.
3356 // The next command may be "catch".
3357 char_u *nextcmd = check_nextcmd(p);
3358 if (nextcmd != NULL && *nextcmd != '|')
3359 eap->nextcmd = nextcmd;
3360 }
Bram Moolenaard0fe6202020-12-05 17:11:12 +01003361 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003362 }
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003363
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003364 if (retarg != NULL)
3365 *retarg = p;
3366 else if (check_for_end && eap != NULL)
Bram Moolenaar63b91732021-08-05 20:40:03 +02003367 set_nextcmd(eap, p);
Bram Moolenaarb171fb12020-06-24 20:34:03 +02003368
Bram Moolenaar071d4272004-06-13 20:20:40 +00003369 return ret;
3370}
3371
3372/*
3373 * Handle top level expression:
Bram Moolenaarb67cc162009-02-04 15:27:06 +00003374 * expr2 ? expr1 : expr1
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003375 * expr2 ?? expr1
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 *
3377 * "arg" must point to the first non-white of the expression.
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003378 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003379 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003380 * Note: "rettv.v_lock" is not set.
3381 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003382 * Return OK or FAIL.
3383 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02003384 int
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003385eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003386{
Bram Moolenaar793648f2020-06-26 21:28:25 +02003387 char_u *p;
3388 int getnext;
3389
Bram Moolenaar4a091b92020-09-12 22:10:00 +02003390 CLEAR_POINTER(rettv);
3391
Bram Moolenaar071d4272004-06-13 20:20:40 +00003392 /*
3393 * Get the first variable.
3394 */
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003395 if (eval2(arg, rettv, evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003396 return FAIL;
3397
Bram Moolenaar793648f2020-06-26 21:28:25 +02003398 p = eval_next_non_blank(*arg, evalarg, &getnext);
3399 if (*p == '?')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003400 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003401 int op_falsy = p[1] == '?';
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003402 int result;
3403 typval_T var2;
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003404 evalarg_T *evalarg_used = evalarg;
3405 evalarg_T local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003406 int orig_flags;
Bram Moolenaar7acde512020-06-24 23:02:40 +02003407 int evaluate;
Bram Moolenaar13106602020-10-04 16:06:05 +02003408 int vim9script = in_vim9script();
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003409
3410 if (evalarg == NULL)
3411 {
Bram Moolenaar844fb642021-10-23 13:32:30 +01003412 init_evalarg(&local_evalarg);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003413 evalarg_used = &local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003414 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003415 orig_flags = evalarg_used->eval_flags;
3416 evaluate = evalarg_used->eval_flags & EVAL_EVALUATE;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003417
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003418 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01003419 *arg = eval_next_line(*arg, evalarg_used);
Bram Moolenaar9d489562020-07-30 20:08:50 +02003420 else
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003421 {
Bram Moolenaar13106602020-10-04 16:06:05 +02003422 if (evaluate && vim9script && !VIM_ISWHITE(p[-1]))
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003423 {
Bram Moolenaar90193e62021-04-04 20:49:50 +02003424 error_white_both(p, op_falsy ? 2 : 1);
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003425 clear_tv(rettv);
3426 return FAIL;
3427 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02003428 *arg = p;
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003429 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003430
Bram Moolenaar071d4272004-06-13 20:20:40 +00003431 result = FALSE;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003432 if (evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003434 int error = FALSE;
3435
Bram Moolenaar13106602020-10-04 16:06:05 +02003436 if (op_falsy)
Bram Moolenaar56acb092020-08-16 14:48:19 +02003437 result = tv2bool(rettv);
Bram Moolenaar13106602020-10-04 16:06:05 +02003438 else if (vim9script)
3439 result = tv_get_bool_chk(rettv, &error);
Bram Moolenaar56acb092020-08-16 14:48:19 +02003440 else if (tv_get_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003441 result = TRUE;
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003442 if (error || !op_falsy || !result)
3443 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003444 if (error)
3445 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003446 }
3447
3448 /*
Bram Moolenaar32e35112020-05-14 22:41:15 +02003449 * Get the second variable. Recursive!
Bram Moolenaar071d4272004-06-13 20:20:40 +00003450 */
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003451 if (op_falsy)
3452 ++*arg;
Bram Moolenaar13106602020-10-04 16:06:05 +02003453 if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[1]))
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003454 {
mityu4ac198c2021-05-28 17:52:40 +02003455 error_white_both(*arg - (op_falsy ? 1 : 0), op_falsy ? 2 : 1);
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003456 clear_tv(rettv);
3457 return FAIL;
3458 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003459 *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003460 evalarg_used->eval_flags = (op_falsy ? !result : result)
zeertzjqb7f6f932023-04-13 22:12:50 +01003461 ? orig_flags : (orig_flags & ~EVAL_EVALUATE);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003462 if (eval1(arg, &var2, evalarg_used) == FAIL)
Bram Moolenaar69e445522020-08-22 22:37:20 +02003463 {
3464 evalarg_used->eval_flags = orig_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003465 return FAIL;
Bram Moolenaar69e445522020-08-22 22:37:20 +02003466 }
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003467 if (!op_falsy || !result)
3468 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003469
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003470 if (!op_falsy)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003471 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003472 /*
3473 * Check for the ":".
3474 */
3475 p = eval_next_non_blank(*arg, evalarg_used, &getnext);
3476 if (*p != ':')
3477 {
Bram Moolenaare1242042021-12-16 20:56:57 +00003478 emsg(_(e_missing_colon_after_questionmark));
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003479 if (evaluate && result)
3480 clear_tv(rettv);
3481 evalarg_used->eval_flags = orig_flags;
3482 return FAIL;
3483 }
3484 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01003485 *arg = eval_next_line(*arg, evalarg_used);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003486 else
3487 {
Bram Moolenaar13106602020-10-04 16:06:05 +02003488 if (evaluate && vim9script && !VIM_ISWHITE(p[-1]))
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003489 {
3490 error_white_both(p, 1);
3491 clear_tv(rettv);
3492 evalarg_used->eval_flags = orig_flags;
3493 return FAIL;
3494 }
3495 *arg = p;
3496 }
3497
3498 /*
3499 * Get the third variable. Recursive!
3500 */
Bram Moolenaar13106602020-10-04 16:06:05 +02003501 if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[1]))
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003502 {
mityu4ac198c2021-05-28 17:52:40 +02003503 error_white_both(*arg, 1);
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003504 clear_tv(rettv);
Bram Moolenaar69e445522020-08-22 22:37:20 +02003505 evalarg_used->eval_flags = orig_flags;
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003506 return FAIL;
3507 }
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003508 *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used);
3509 evalarg_used->eval_flags = !result ? orig_flags
zeertzjqb7f6f932023-04-13 22:12:50 +01003510 : (orig_flags & ~EVAL_EVALUATE);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02003511 if (eval1(arg, &var2, evalarg_used) == FAIL)
3512 {
3513 if (evaluate && result)
3514 clear_tv(rettv);
3515 evalarg_used->eval_flags = orig_flags;
3516 return FAIL;
3517 }
3518 if (evaluate && !result)
3519 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003520 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003521
3522 if (evalarg == NULL)
3523 clear_evalarg(&local_evalarg, NULL);
3524 else
3525 evalarg->eval_flags = orig_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003526 }
3527
3528 return OK;
3529}
3530
3531/*
3532 * Handle first level expression:
3533 * expr2 || expr2 || expr2 logical OR
3534 *
3535 * "arg" must point to the first non-white of the expression.
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003536 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003537 *
3538 * Return OK or FAIL.
3539 */
3540 static int
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003541eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542{
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003543 char_u *p;
3544 int getnext;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003545
3546 /*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01003547 * Get the first expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003548 */
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003549 if (eval3(arg, rettv, evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003550 return FAIL;
3551
3552 /*
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003553 * Handle the "||" operator.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003554 */
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003555 p = eval_next_non_blank(*arg, evalarg, &getnext);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003556 if (p[0] == '|' && p[1] == '|')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003557 {
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003558 evalarg_T *evalarg_used = evalarg;
3559 evalarg_T local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003560 int evaluate;
3561 int orig_flags;
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003562 long result = FALSE;
3563 typval_T var2;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003564 int error = FALSE;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003565 int vim9script = in_vim9script();
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003566
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003567 if (evalarg == NULL)
3568 {
Bram Moolenaar844fb642021-10-23 13:32:30 +01003569 init_evalarg(&local_evalarg);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003570 evalarg_used = &local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003571 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003572 orig_flags = evalarg_used->eval_flags;
3573 evaluate = orig_flags & EVAL_EVALUATE;
3574 if (evaluate)
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003575 {
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003576 if (vim9script)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003577 result = tv_get_bool_chk(rettv, &error);
3578 else if (tv_get_number_chk(rettv, &error) != 0)
3579 result = TRUE;
3580 clear_tv(rettv);
3581 if (error)
3582 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003583 }
3584
3585 /*
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003586 * Repeat until there is no following "||".
Bram Moolenaar071d4272004-06-13 20:20:40 +00003587 */
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003588 while (p[0] == '|' && p[1] == '|')
3589 {
3590 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01003591 *arg = eval_next_line(*arg, evalarg_used);
Bram Moolenaar9d489562020-07-30 20:08:50 +02003592 else
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003593 {
Bram Moolenaar4525a572022-02-13 11:57:33 +00003594 if (evaluate && vim9script && !VIM_ISWHITE(p[-1]))
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003595 {
3596 error_white_both(p, 2);
3597 clear_tv(rettv);
3598 return FAIL;
3599 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02003600 *arg = p;
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003601 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003602
3603 /*
3604 * Get the second variable.
3605 */
Bram Moolenaar4525a572022-02-13 11:57:33 +00003606 if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[2]))
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003607 {
mityu4ac198c2021-05-28 17:52:40 +02003608 error_white_both(*arg, 2);
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003609 clear_tv(rettv);
3610 return FAIL;
3611 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003612 *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used);
3613 evalarg_used->eval_flags = !result ? orig_flags
zeertzjqb7f6f932023-04-13 22:12:50 +01003614 : (orig_flags & ~EVAL_EVALUATE);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003615 if (eval3(arg, &var2, evalarg_used) == FAIL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003616 return FAIL;
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003617
3618 /*
3619 * Compute the result.
3620 */
3621 if (evaluate && !result)
3622 {
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003623 if (vim9script)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003624 result = tv_get_bool_chk(&var2, &error);
3625 else if (tv_get_number_chk(&var2, &error) != 0)
3626 result = TRUE;
3627 clear_tv(&var2);
3628 if (error)
3629 return FAIL;
3630 }
3631 if (evaluate)
3632 {
3633 if (vim9script)
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003634 {
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003635 rettv->v_type = VAR_BOOL;
3636 rettv->vval.v_number = result ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003637 }
3638 else
3639 {
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003640 rettv->v_type = VAR_NUMBER;
3641 rettv->vval.v_number = result;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003642 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003643 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003644
3645 p = eval_next_non_blank(*arg, evalarg_used, &getnext);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003646 }
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003647
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003648 if (evalarg == NULL)
3649 clear_evalarg(&local_evalarg, NULL);
3650 else
3651 evalarg->eval_flags = orig_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003652 }
3653
3654 return OK;
3655}
3656
3657/*
3658 * Handle second level expression:
3659 * expr3 && expr3 && expr3 logical AND
3660 *
3661 * "arg" must point to the first non-white of the expression.
Bram Moolenaarfdac71c2020-08-05 12:44:41 +02003662 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003663 *
3664 * Return OK or FAIL.
3665 */
3666 static int
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003667eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003668{
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003669 char_u *p;
3670 int getnext;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003671
3672 /*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01003673 * Get the first expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003674 */
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003675 if (eval4(arg, rettv, evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003676 return FAIL;
3677
3678 /*
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003679 * Handle the "&&" operator.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003680 */
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003681 p = eval_next_non_blank(*arg, evalarg, &getnext);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003682 if (p[0] == '&' && p[1] == '&')
Bram Moolenaar071d4272004-06-13 20:20:40 +00003683 {
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003684 evalarg_T *evalarg_used = evalarg;
3685 evalarg_T local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003686 int orig_flags;
3687 int evaluate;
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003688 long result = TRUE;
3689 typval_T var2;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003690 int error = FALSE;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003691 int vim9script = in_vim9script();
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003692
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003693 if (evalarg == NULL)
3694 {
Bram Moolenaar844fb642021-10-23 13:32:30 +01003695 init_evalarg(&local_evalarg);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003696 evalarg_used = &local_evalarg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003697 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003698 orig_flags = evalarg_used->eval_flags;
3699 evaluate = orig_flags & EVAL_EVALUATE;
3700 if (evaluate)
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003701 {
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003702 if (vim9script)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003703 result = tv_get_bool_chk(rettv, &error);
3704 else if (tv_get_number_chk(rettv, &error) == 0)
3705 result = FALSE;
3706 clear_tv(rettv);
3707 if (error)
3708 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003709 }
3710
3711 /*
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003712 * Repeat until there is no following "&&".
Bram Moolenaar071d4272004-06-13 20:20:40 +00003713 */
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003714 while (p[0] == '&' && p[1] == '&')
3715 {
3716 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01003717 *arg = eval_next_line(*arg, evalarg_used);
Bram Moolenaar9d489562020-07-30 20:08:50 +02003718 else
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003719 {
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003720 if (evaluate && vim9script && !VIM_ISWHITE(p[-1]))
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003721 {
3722 error_white_both(p, 2);
3723 clear_tv(rettv);
3724 return FAIL;
3725 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02003726 *arg = p;
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003727 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003728
3729 /*
3730 * Get the second variable.
3731 */
Bram Moolenaar4525a572022-02-13 11:57:33 +00003732 if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[2]))
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003733 {
mityu4ac198c2021-05-28 17:52:40 +02003734 error_white_both(*arg, 2);
Bram Moolenaar3c1c9fd2020-08-05 12:32:38 +02003735 clear_tv(rettv);
3736 return FAIL;
3737 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003738 *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used);
3739 evalarg_used->eval_flags = result ? orig_flags
zeertzjqb7f6f932023-04-13 22:12:50 +01003740 : (orig_flags & ~EVAL_EVALUATE);
Bram Moolenaarc1ec0422020-09-09 22:27:58 +02003741 CLEAR_FIELD(var2);
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003742 if (eval4(arg, &var2, evalarg_used) == FAIL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003743 return FAIL;
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003744
3745 /*
3746 * Compute the result.
3747 */
3748 if (evaluate && result)
3749 {
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003750 if (vim9script)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003751 result = tv_get_bool_chk(&var2, &error);
3752 else if (tv_get_number_chk(&var2, &error) == 0)
3753 result = FALSE;
3754 clear_tv(&var2);
3755 if (error)
3756 return FAIL;
3757 }
3758 if (evaluate)
3759 {
3760 if (vim9script)
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003761 {
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003762 rettv->v_type = VAR_BOOL;
3763 rettv->vval.v_number = result ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003764 }
3765 else
3766 {
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003767 rettv->v_type = VAR_NUMBER;
3768 rettv->vval.v_number = result;
Bram Moolenaar8c34ea52020-07-13 22:29:02 +02003769 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003770 }
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003771
3772 p = eval_next_non_blank(*arg, evalarg_used, &getnext);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 }
Bram Moolenaarbe7ee482020-06-26 21:38:51 +02003774
Bram Moolenaar8af81d62020-07-12 16:32:19 +02003775 if (evalarg == NULL)
3776 clear_evalarg(&local_evalarg, NULL);
3777 else
3778 evalarg->eval_flags = orig_flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003779 }
3780
3781 return OK;
3782}
3783
3784/*
3785 * Handle third level expression:
3786 * var1 == var2
3787 * var1 =~ var2
3788 * var1 != var2
3789 * var1 !~ var2
3790 * var1 > var2
3791 * var1 >= var2
3792 * var1 < var2
3793 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003794 * var1 is var2
3795 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003796 *
3797 * "arg" must point to the first non-white of the expression.
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003798 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003799 *
3800 * Return OK or FAIL.
3801 */
3802 static int
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003803eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003804{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003805 char_u *p;
Bram Moolenaare6536aa2020-06-26 22:00:38 +02003806 int getnext;
Bram Moolenaar657137c2021-01-09 15:45:23 +01003807 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003808 int len = 2;
Bram Moolenaar696ba232020-07-29 21:20:41 +02003809 int type_is = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003810
3811 /*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01003812 * Get the first expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813 */
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003814 if (eval5(arg, rettv, evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003815 return FAIL;
3816
Bram Moolenaare6536aa2020-06-26 22:00:38 +02003817 p = eval_next_non_blank(*arg, evalarg, &getnext);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01003818
Bram Moolenaar696ba232020-07-29 21:20:41 +02003819 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003820
3821 /*
Bram Moolenaar8c8de832008-06-24 22:58:06 +00003822 * If there is a comparative operator, use it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003823 */
Bram Moolenaar87396072019-12-31 22:36:18 +01003824 if (type != EXPR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003825 {
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02003826 typval_T var2;
3827 int ic;
3828 int vim9script = in_vim9script();
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003829 int evaluate = evalarg == NULL
3830 ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar1b1df952022-03-10 20:01:50 +00003831 long comp_lnum = SOURCING_LNUM;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02003832
Bram Moolenaare6536aa2020-06-26 22:00:38 +02003833 if (getnext)
mityu4ac198c2021-05-28 17:52:40 +02003834 {
Bram Moolenaare442d592022-05-05 12:20:28 +01003835 *arg = eval_next_line(*arg, evalarg);
mityu4ac198c2021-05-28 17:52:40 +02003836 p = *arg;
3837 }
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003838 else if (evaluate && vim9script && !VIM_ISWHITE(**arg))
3839 {
mityu4ac198c2021-05-28 17:52:40 +02003840 error_white_both(*arg, len);
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003841 clear_tv(rettv);
3842 return FAIL;
3843 }
Bram Moolenaare6536aa2020-06-26 22:00:38 +02003844
Bram Moolenaar696ba232020-07-29 21:20:41 +02003845 if (vim9script && type_is && (p[len] == '?' || p[len] == '#'))
3846 {
Bram Moolenaar108010a2021-06-27 22:03:33 +02003847 semsg(_(e_invalid_expression_str), p);
Bram Moolenaar696ba232020-07-29 21:20:41 +02003848 clear_tv(rettv);
3849 return FAIL;
3850 }
3851
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003852 // extra question mark appended: ignore case
Bram Moolenaar071d4272004-06-13 20:20:40 +00003853 if (p[len] == '?')
3854 {
3855 ic = TRUE;
3856 ++len;
3857 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01003858 // extra '#' appended: match case
Bram Moolenaar071d4272004-06-13 20:20:40 +00003859 else if (p[len] == '#')
3860 {
3861 ic = FALSE;
3862 ++len;
3863 }
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02003864 // nothing appended: use 'ignorecase' if not in Vim script
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865 else
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02003866 ic = vim9script ? FALSE : p_ic;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003867
3868 /*
3869 * Get the second variable.
3870 */
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003871 if (evaluate && vim9script && !IS_WHITE_OR_NUL(p[len]))
3872 {
Bram Moolenaar90193e62021-04-04 20:49:50 +02003873 error_white_both(p, len);
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003874 clear_tv(rettv);
3875 return FAIL;
3876 }
Bram Moolenaar9215f012020-06-27 21:18:00 +02003877 *arg = skipwhite_and_linebreak(p + len, evalarg);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02003878 if (eval5(arg, &var2, evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003879 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003880 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003881 return FAIL;
3882 }
Bram Moolenaarff1cd392020-08-05 11:51:30 +02003883 if (evaluate)
Bram Moolenaar31988702018-02-13 12:57:42 +01003884 {
Bram Moolenaar543e6f32020-07-10 22:45:38 +02003885 int ret;
Bram Moolenaar31988702018-02-13 12:57:42 +01003886
Bram Moolenaar1b1df952022-03-10 20:01:50 +00003887 // use the line of the comparison for messages
3888 SOURCING_LNUM = comp_lnum;
Bram Moolenaarc71f36a2020-07-21 21:31:00 +02003889 if (vim9script && check_compare_types(type, rettv, &var2) == FAIL)
Bram Moolenaar543e6f32020-07-10 22:45:38 +02003890 {
3891 ret = FAIL;
3892 clear_tv(rettv);
3893 }
3894 else
3895 ret = typval_compare(rettv, &var2, type, ic);
Bram Moolenaar31988702018-02-13 12:57:42 +01003896 clear_tv(&var2);
3897 return ret;
3898 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003899 }
3900
3901 return OK;
3902}
3903
Bram Moolenaar081db1a2020-10-22 20:09:43 +02003904/*
3905 * Make a copy of blob "tv1" and append blob "tv2".
3906 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907 void
3908eval_addblob(typval_T *tv1, typval_T *tv2)
3909{
3910 blob_T *b1 = tv1->vval.v_blob;
3911 blob_T *b2 = tv2->vval.v_blob;
3912 blob_T *b = blob_alloc();
3913 int i;
3914
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00003915 if (b == NULL)
3916 return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003917
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00003918 for (i = 0; i < blob_len(b1); i++)
3919 ga_append(&b->bv_ga, blob_get(b1, i));
3920 for (i = 0; i < blob_len(b2); i++)
3921 ga_append(&b->bv_ga, blob_get(b2, i));
3922
3923 clear_tv(tv1);
3924 rettv_blob_set(tv1, b);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003925}
3926
Bram Moolenaar081db1a2020-10-22 20:09:43 +02003927/*
3928 * Make a copy of list "tv1" and append list "tv2".
3929 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003930 int
3931eval_addlist(typval_T *tv1, typval_T *tv2)
3932{
3933 typval_T var3;
3934
3935 // concatenate Lists
3936 if (list_concat(tv1->vval.v_list, tv2->vval.v_list, &var3) == FAIL)
3937 {
3938 clear_tv(tv1);
3939 clear_tv(tv2);
3940 return FAIL;
3941 }
3942 clear_tv(tv1);
3943 *tv1 = var3;
3944 return OK;
3945}
3946
Bram Moolenaar071d4272004-06-13 20:20:40 +00003947/*
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02003948 * Left or right shift the number "tv1" by the number "tv2" and store the
3949 * result in "tv1".
3950 *
3951 * Return OK or FAIL.
3952 */
3953 static int
3954eval_shift_number(typval_T *tv1, typval_T *tv2, int shift_type)
3955{
3956 if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
3957 {
3958 // right operand should be a positive number
3959 if (tv2->v_type != VAR_NUMBER)
3960 emsg(_(e_bitshift_ops_must_be_number));
3961 else
3962 emsg(_(e_bitshift_ops_must_be_positive));
3963 clear_tv(tv1);
3964 clear_tv(tv2);
3965 return FAIL;
3966 }
3967
3968 if (tv2->vval.v_number > MAX_LSHIFT_BITS)
3969 // shifting more bits than we have always results in zero
3970 tv1->vval.v_number = 0;
3971 else if (shift_type == EXPR_LSHIFT)
3972 tv1->vval.v_number =
3973 (uvarnumber_T)tv1->vval.v_number << tv2->vval.v_number;
3974 else
3975 tv1->vval.v_number =
3976 (uvarnumber_T)tv1->vval.v_number >> tv2->vval.v_number;
3977
3978 return OK;
3979}
3980
3981/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01003982 * Handle the bitwise left/right shift operator expression:
3983 * var1 << var2
3984 * var1 >> var2
3985 *
3986 * "arg" must point to the first non-white of the expression.
3987 * "arg" is advanced to just after the recognized expression.
3988 *
3989 * Return OK or FAIL.
3990 */
3991 static int
3992eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
3993{
3994 /*
3995 * Get the first expression.
3996 */
3997 if (eval6(arg, rettv, evalarg) == FAIL)
3998 return FAIL;
3999
4000 /*
4001 * Repeat computing, until no '<<' or '>>' is following.
4002 */
4003 for (;;)
4004 {
4005 char_u *p;
4006 int getnext;
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004007 exprtype_T exprtype;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004008 int evaluate;
4009 typval_T var2;
4010 int vim9script;
4011
4012 p = eval_next_non_blank(*arg, evalarg, &getnext);
4013 if (p[0] == '<' && p[1] == '<')
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004014 exprtype = EXPR_LSHIFT;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004015 else if (p[0] == '>' && p[1] == '>')
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004016 exprtype = EXPR_RSHIFT;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004017 else
4018 return OK;
4019
4020 // Handle a bitwise left or right shift operator
Yegappan Lakshmanande3295d2023-10-15 09:44:50 +02004021 evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
4022 if (evaluate && rettv->v_type != VAR_NUMBER)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004023 {
4024 // left operand should be a number
4025 emsg(_(e_bitshift_ops_must_be_number));
4026 clear_tv(rettv);
4027 return FAIL;
4028 }
4029
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004030 vim9script = in_vim9script();
4031 if (getnext)
4032 {
4033 *arg = eval_next_line(*arg, evalarg);
4034 p = *arg;
4035 }
4036 else if (evaluate && vim9script && !VIM_ISWHITE(**arg))
4037 {
4038 error_white_both(*arg, 2);
4039 clear_tv(rettv);
4040 return FAIL;
4041 }
4042
4043 /*
4044 * Get the second variable.
4045 */
4046 if (evaluate && vim9script && !IS_WHITE_OR_NUL(p[2]))
4047 {
4048 error_white_both(p, 2);
4049 clear_tv(rettv);
4050 return FAIL;
4051 }
4052 *arg = skipwhite_and_linebreak(p + 2, evalarg);
4053 if (eval6(arg, &var2, evalarg) == FAIL)
4054 {
4055 clear_tv(rettv);
4056 return FAIL;
4057 }
4058
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004059 if (evaluate)
4060 {
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004061 if (eval_shift_number(rettv, &var2, exprtype) == FAIL)
Yegappan Lakshmanande3295d2023-10-15 09:44:50 +02004062 return FAIL;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004063 }
4064
4065 clear_tv(&var2);
4066 }
4067
4068 return OK;
4069}
4070
4071/*
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004072 * Concatenate strings "tv1" and "tv2" and store the result in "tv1".
4073 */
4074 static int
4075eval_concat_str(typval_T *tv1, typval_T *tv2)
4076{
4077 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4078 char_u *s1 = tv_get_string_buf(tv1, buf1);
4079 char_u *s2 = NULL;
4080 char_u *p;
4081 int vim9script = in_vim9script();
4082
4083 if (vim9script && (tv2->v_type == VAR_VOID
4084 || tv2->v_type == VAR_CHANNEL
4085 || tv2->v_type == VAR_JOB))
4086 semsg(_(e_using_invalid_value_as_string_str),
4087 vartype_name(tv2->v_type));
4088 else if (vim9script && tv2->v_type == VAR_FLOAT)
4089 {
4090 vim_snprintf((char *)buf2, NUMBUFLEN, "%g",
4091 tv2->vval.v_float);
4092 s2 = buf2;
4093 }
4094 else
4095 s2 = tv_get_string_buf_chk(tv2, buf2);
4096 if (s2 == NULL) // type error ?
4097 {
4098 clear_tv(tv1);
4099 clear_tv(tv2);
4100 return FAIL;
4101 }
4102
4103 p = concat_str(s1, s2);
4104 clear_tv(tv1);
4105 tv1->v_type = VAR_STRING;
4106 tv1->vval.v_string = p;
4107
4108 return OK;
4109}
4110
4111/*
4112 * Add or subtract numbers "tv1" and "tv2" and store the result in "tv1".
4113 * The numbers can be whole numbers or floats.
4114 */
4115 static int
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004116eval_addsub_number(typval_T *tv1, typval_T *tv2, int op)
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004117{
4118 int error = FALSE;
4119 varnumber_T n1, n2;
4120 float_T f1 = 0, f2 = 0;
4121
4122 if (tv1->v_type == VAR_FLOAT)
4123 {
4124 f1 = tv1->vval.v_float;
4125 n1 = 0;
4126 }
4127 else
4128 {
4129 n1 = tv_get_number_chk(tv1, &error);
4130 if (error)
4131 {
4132 // This can only happen for "list + non-list" or
4133 // "blob + non-blob". For "non-list + ..." or
4134 // "something - ...", we returned before evaluating the
4135 // 2nd operand.
4136 clear_tv(tv1);
4137 clear_tv(tv2);
4138 return FAIL;
4139 }
4140 if (tv2->v_type == VAR_FLOAT)
4141 f1 = n1;
4142 }
4143 if (tv2->v_type == VAR_FLOAT)
4144 {
4145 f2 = tv2->vval.v_float;
4146 n2 = 0;
4147 }
4148 else
4149 {
4150 n2 = tv_get_number_chk(tv2, &error);
4151 if (error)
4152 {
4153 clear_tv(tv1);
4154 clear_tv(tv2);
4155 return FAIL;
4156 }
4157 if (tv1->v_type == VAR_FLOAT)
4158 f2 = n2;
4159 }
4160 clear_tv(tv1);
4161
4162 // If there is a float on either side the result is a float.
4163 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
4164 {
4165 if (op == '+')
4166 f1 = f1 + f2;
4167 else
4168 f1 = f1 - f2;
4169 tv1->v_type = VAR_FLOAT;
4170 tv1->vval.v_float = f1;
4171 }
4172 else
4173 {
4174 if (op == '+')
4175 n1 = n1 + n2;
4176 else
4177 n1 = n1 - n2;
4178 tv1->v_type = VAR_NUMBER;
4179 tv1->vval.v_number = n1;
4180 }
4181
4182 return OK;
4183}
4184
4185/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004186 * Handle fifth level expression:
Bram Moolenaar54969f42022-02-07 13:56:44 +00004187 * + number addition, concatenation of list or blob
Bram Moolenaar071d4272004-06-13 20:20:40 +00004188 * - number subtraction
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004189 * . string concatenation (if script version is 1)
Bram Moolenaar0f248b02019-04-04 15:36:05 +02004190 * .. string concatenation
Bram Moolenaar071d4272004-06-13 20:20:40 +00004191 *
4192 * "arg" must point to the first non-white of the expression.
Bram Moolenaarff1cd392020-08-05 11:51:30 +02004193 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004194 *
4195 * Return OK or FAIL.
4196 */
4197 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004198eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004199{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004200 /*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004201 * Get the first expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004202 */
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004203 if (eval7(arg, rettv, evalarg, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004204 return FAIL;
4205
4206 /*
4207 * Repeat computing, until no '+', '-' or '.' is following.
4208 */
4209 for (;;)
4210 {
Bram Moolenaar3ac9c472020-07-13 21:28:03 +02004211 int evaluate;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004212 int getnext;
4213 char_u *p;
4214 int op;
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004215 int oplen;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004216 int concat;
4217 typval_T var2;
Bram Moolenaar2e086612020-08-25 22:37:48 +02004218 int vim9script = in_vim9script();
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004219
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004220 // "." is only string concatenation when scriptversion is 1
Bram Moolenaarf76ec1e2021-03-03 17:58:16 +01004221 // "+=", "-=" and "..=" are assignments
Bram Moolenaarbdc0f1c2021-04-24 19:08:24 +02004222 // "++" and "--" on the next line are a separate command.
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004223 p = eval_next_non_blank(*arg, evalarg, &getnext);
4224 op = *p;
Bram Moolenaardd9de502021-08-15 13:49:42 +02004225 concat = op == '.' && (*(p + 1) == '.' || in_old_script(2));
Bram Moolenaarf76ec1e2021-03-03 17:58:16 +01004226 if ((op != '+' && op != '-' && !concat) || p[1] == '='
4227 || (p[1] == '.' && p[2] == '='))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004228 break;
Bram Moolenaarbdc0f1c2021-04-24 19:08:24 +02004229 if (getnext && (op == '+' || op == '-') && p[0] == p[1])
4230 break;
Bram Moolenaar3ac9c472020-07-13 21:28:03 +02004231
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004232 evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004233 oplen = (concat && p[1] == '.') ? 2 : 1;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004234 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01004235 *arg = eval_next_line(*arg, evalarg);
Bram Moolenaar9d489562020-07-30 20:08:50 +02004236 else
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004237 {
Bram Moolenaar2e086612020-08-25 22:37:48 +02004238 if (evaluate && vim9script && !VIM_ISWHITE(**arg))
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004239 {
mityu4ac198c2021-05-28 17:52:40 +02004240 error_white_both(*arg, oplen);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004241 clear_tv(rettv);
4242 return FAIL;
4243 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02004244 *arg = p;
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004245 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004246 if ((op != '+' || (rettv->v_type != VAR_LIST
4247 && rettv->v_type != VAR_BLOB))
Bram Moolenaar8c8de832008-06-24 22:58:06 +00004248 && (op == '.' || rettv->v_type != VAR_FLOAT)
Bram Moolenaar081db1a2020-10-22 20:09:43 +02004249 && evaluate)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004250 {
Bram Moolenaar081db1a2020-10-22 20:09:43 +02004251 int error = FALSE;
4252
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004253 // For "list + ...", an illegal use of the first operand as
4254 // a number cannot be determined before evaluating the 2nd
4255 // operand: if this is also a list, all is ok.
4256 // For "something . ...", "something - ..." or "non-list + ...",
4257 // we know that the first operand needs to be a string or number
4258 // without evaluating the 2nd operand. So check before to avoid
4259 // side effects after an error.
Bram Moolenaar081db1a2020-10-22 20:09:43 +02004260 if (op != '.')
4261 tv_get_number_chk(rettv, &error);
4262 if ((op == '.' && tv_get_string_chk(rettv) == NULL) || error)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004263 {
4264 clear_tv(rettv);
4265 return FAIL;
4266 }
4267 }
4268
Bram Moolenaar071d4272004-06-13 20:20:40 +00004269 /*
4270 * Get the second variable.
4271 */
Bram Moolenaar2e086612020-08-25 22:37:48 +02004272 if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[oplen]))
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004273 {
mityu89dcb4d2021-05-28 13:50:17 +02004274 error_white_both(*arg, oplen);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004275 clear_tv(rettv);
4276 return FAIL;
4277 }
4278 *arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004279 if (eval7(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004280 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004281 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004282 return FAIL;
4283 }
4284
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004285 if (evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004286 {
4287 /*
4288 * Compute the result.
4289 */
4290 if (op == '.')
4291 {
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004292 if (eval_concat_str(rettv, &var2) == FAIL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004293 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004294 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004295 else if (op == '+' && rettv->v_type == VAR_BLOB
4296 && var2.v_type == VAR_BLOB)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004297 eval_addblob(rettv, &var2);
Bram Moolenaare9a41262005-01-15 22:18:47 +00004298 else if (op == '+' && rettv->v_type == VAR_LIST
4299 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004300 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004301 if (eval_addlist(rettv, &var2) == FAIL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004302 return FAIL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004303 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004304 else
4305 {
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004306 if (eval_addsub_number(rettv, &var2, op) == FAIL)
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004307 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004308 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004309 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004310 }
4311 }
4312 return OK;
4313}
4314
4315/*
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004316 * Multiply or divide or compute the modulo of numbers "tv1" and "tv2" and
4317 * store the result in "tv1". The numbers can be whole numbers or floats.
4318 */
4319 static int
4320eval_multdiv_number(typval_T *tv1, typval_T *tv2, int op)
4321{
4322 varnumber_T n1, n2;
4323 float_T f1, f2;
4324 int error;
4325 int use_float = FALSE;
4326
4327 f1 = 0;
4328 f2 = 0;
4329 error = FALSE;
4330 if (tv1->v_type == VAR_FLOAT)
4331 {
4332 f1 = tv1->vval.v_float;
4333 use_float = TRUE;
4334 n1 = 0;
4335 }
4336 else
4337 n1 = tv_get_number_chk(tv1, &error);
4338 clear_tv(tv1);
4339 if (error)
4340 {
4341 clear_tv(tv2);
4342 return FAIL;
4343 }
4344
4345 if (tv2->v_type == VAR_FLOAT)
4346 {
4347 if (!use_float)
4348 {
4349 f1 = n1;
4350 use_float = TRUE;
4351 }
4352 f2 = tv2->vval.v_float;
4353 n2 = 0;
4354 }
4355 else
4356 {
4357 n2 = tv_get_number_chk(tv2, &error);
4358 clear_tv(tv2);
4359 if (error)
4360 return FAIL;
4361 if (use_float)
4362 f2 = n2;
4363 }
4364
4365 /*
4366 * Compute the result.
4367 * When either side is a float the result is a float.
4368 */
4369 if (use_float)
4370 {
4371 if (op == '*')
4372 f1 = f1 * f2;
4373 else if (op == '/')
4374 {
4375#ifdef VMS
4376 // VMS crashes on divide by zero, work around it
4377 if (f2 == 0.0)
4378 {
4379 if (f1 == 0)
4380 f1 = -1 * __F_FLT_MAX - 1L; // similar to NaN
4381 else if (f1 < 0)
4382 f1 = -1 * __F_FLT_MAX;
4383 else
4384 f1 = __F_FLT_MAX;
4385 }
4386 else
4387 f1 = f1 / f2;
4388#else
4389 // We rely on the floating point library to handle divide
4390 // by zero to result in "inf" and not a crash.
4391 f1 = f1 / f2;
4392#endif
4393 }
4394 else
4395 {
4396 emsg(_(e_cannot_use_percent_with_float));
4397 return FAIL;
4398 }
4399 tv1->v_type = VAR_FLOAT;
4400 tv1->vval.v_float = f1;
4401 }
4402 else
4403 {
4404 int failed = FALSE;
4405
4406 if (op == '*')
4407 n1 = n1 * n2;
4408 else if (op == '/')
4409 n1 = num_divide(n1, n2, &failed);
4410 else
4411 n1 = num_modulus(n1, n2, &failed);
4412 if (failed)
4413 return FAIL;
4414
4415 tv1->v_type = VAR_NUMBER;
4416 tv1->vval.v_number = n1;
4417 }
4418
4419 return OK;
4420}
4421
4422/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004423 * Handle sixth level expression:
Bram Moolenaar071d4272004-06-13 20:20:40 +00004424 * * number multiplication
4425 * / number division
4426 * % number modulo
4427 *
4428 * "arg" must point to the first non-white of the expression.
Bram Moolenaarff1cd392020-08-05 11:51:30 +02004429 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004430 *
4431 * Return OK or FAIL.
4432 */
4433 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004434eval7(
Bram Moolenaar7454a062016-01-30 15:14:10 +01004435 char_u **arg,
4436 typval_T *rettv,
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004437 evalarg_T *evalarg,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01004438 int want_string) // after "." operator
Bram Moolenaar071d4272004-06-13 20:20:40 +00004439{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440 /*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004441 * Get the first expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 */
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004443 if (eval8(arg, rettv, evalarg, want_string) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 return FAIL;
4445
4446 /*
4447 * Repeat computing, until no '*', '/' or '%' is following.
4448 */
4449 for (;;)
4450 {
Bram Moolenaar3ac9c472020-07-13 21:28:03 +02004451 int evaluate;
4452 int getnext;
4453 typval_T var2;
Bram Moolenaar9d489562020-07-30 20:08:50 +02004454 char_u *p;
Bram Moolenaar3ac9c472020-07-13 21:28:03 +02004455 int op;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004456
Bram Moolenaarf76ec1e2021-03-03 17:58:16 +01004457 // "*=", "/=" and "%=" are assignments
Bram Moolenaar9d489562020-07-30 20:08:50 +02004458 p = eval_next_non_blank(*arg, evalarg, &getnext);
4459 op = *p;
Bram Moolenaarf76ec1e2021-03-03 17:58:16 +01004460 if ((op != '*' && op != '/' && op != '%') || p[1] == '=')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004461 break;
Bram Moolenaar3ac9c472020-07-13 21:28:03 +02004462
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004463 evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004464 if (getnext)
Bram Moolenaare442d592022-05-05 12:20:28 +01004465 *arg = eval_next_line(*arg, evalarg);
Bram Moolenaar9d489562020-07-30 20:08:50 +02004466 else
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004467 {
4468 if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg))
4469 {
mityu4ac198c2021-05-28 17:52:40 +02004470 error_white_both(*arg, 1);
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004471 clear_tv(rettv);
4472 return FAIL;
4473 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02004474 *arg = p;
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004475 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004476
Bram Moolenaar071d4272004-06-13 20:20:40 +00004477 /*
4478 * Get the second variable.
4479 */
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004480 if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1]))
4481 {
Bram Moolenaara9749532021-03-06 18:18:19 +01004482 error_white_both(*arg, 1);
Bram Moolenaarb4caa162020-08-05 11:36:52 +02004483 clear_tv(rettv);
4484 return FAIL;
4485 }
4486 *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004487 if (eval8(arg, &var2, evalarg, FALSE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004488 return FAIL;
4489
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004490 if (evaluate)
Yegappan Lakshmanan734286e2024-06-03 18:52:22 +02004491 // Compute the result.
4492 if (eval_multdiv_number(rettv, &var2, op) == FAIL)
4493 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004494 }
4495
4496 return OK;
4497}
4498
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004499/*
4500 * Handle a type cast before a base level expression.
4501 * "arg" must point to the first non-white of the expression.
4502 * "arg" is advanced to just after the recognized expression.
4503 * Return OK or FAIL.
4504 */
4505 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004506eval8(
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004507 char_u **arg,
4508 typval_T *rettv,
4509 evalarg_T *evalarg,
4510 int want_string) // after "." operator
4511{
4512 type_T *want_type = NULL;
4513 garray_T type_list; // list of pointers to allocated types
4514 int res;
4515 int evaluate = evalarg == NULL ? 0
4516 : (evalarg->eval_flags & EVAL_EVALUATE);
4517
4518 // Recognize <type> in Vim9 script only.
Bram Moolenaar678b2072021-07-26 21:10:11 +02004519 if (in_vim9script() && **arg == '<' && eval_isnamec1((*arg)[1])
4520 && STRNCMP(*arg, "<SNR>", 5) != 0)
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004521 {
4522 ++*arg;
4523 ga_init2(&type_list, sizeof(type_T *), 10);
4524 want_type = parse_type(arg, &type_list, TRUE);
4525 if (want_type == NULL && (evaluate || **arg != '>'))
4526 {
4527 clear_type_list(&type_list);
4528 return FAIL;
4529 }
4530
4531 if (**arg != '>')
4532 {
4533 if (*skipwhite(*arg) == '>')
4534 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
4535 else
4536 emsg(_(e_missing_gt));
4537 clear_type_list(&type_list);
4538 return FAIL;
4539 }
4540 ++*arg;
4541 *arg = skipwhite_and_linebreak(*arg, evalarg);
4542 }
4543
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004544 res = eval9(arg, rettv, evalarg, want_string);
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004545
4546 if (want_type != NULL && evaluate)
4547 {
4548 if (res == OK)
4549 {
Bram Moolenaar114dbda2022-01-03 12:28:03 +00004550 type_T *actual = typval2type(rettv, get_copyID(), &type_list,
4551 TVTT_DO_MEMBER);
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004552
Bram Moolenaar60dc8272021-07-29 22:48:54 +02004553 if (!equal_type(want_type, actual, 0))
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004554 {
Yegappan Lakshmananfeaccd22023-10-28 15:53:55 +02004555 if (want_type->tt_type == VAR_BOOL
4556 && actual->tt_type != VAR_BOOL
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004557 && (actual->tt_flags & TTFLAG_BOOL_OK))
4558 {
4559 int n = tv2bool(rettv);
4560
4561 // can use "0" and "1" for boolean in some places
4562 clear_tv(rettv);
4563 rettv->v_type = VAR_BOOL;
4564 rettv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
4565 }
4566 else
4567 {
Bram Moolenaar2b59df02021-07-22 15:14:25 +02004568 where_T where = WHERE_INIT;
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004569
Bram Moolenaar459fbdb2021-04-21 17:57:26 +02004570 res = check_type(want_type, actual, TRUE, where);
4571 }
4572 }
4573 }
4574 clear_type_list(&type_list);
4575 }
4576
4577 return res;
4578}
4579
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004580 int
4581eval_leader(char_u **arg, int vim9)
4582{
4583 char_u *s = *arg;
4584 char_u *p = *arg;
4585
4586 while (*p == '!' || *p == '-' || *p == '+')
4587 {
4588 char_u *n = skipwhite(p + 1);
4589
4590 // ++, --, -+ and +- are not accepted in Vim9 script
4591 if (vim9 && (*p == '-' || *p == '+') && (*n == '-' || *n == '+'))
4592 {
Bram Moolenaar108010a2021-06-27 22:03:33 +02004593 semsg(_(e_invalid_expression_str), s);
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004594 return FAIL;
4595 }
4596 p = n;
4597 }
4598 *arg = p;
4599 return OK;
4600}
4601
Bram Moolenaar071d4272004-06-13 20:20:40 +00004602/*
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004603 * Check for a predefined value "true", "false" and "null.*".
4604 * Return OK when recognized.
4605 */
4606 int
4607handle_predefined(char_u *s, int len, typval_T *rettv)
4608{
4609 switch (len)
4610 {
4611 case 4: if (STRNCMP(s, "true", 4) == 0)
4612 {
4613 rettv->v_type = VAR_BOOL;
4614 rettv->vval.v_number = VVAL_TRUE;
4615 return OK;
4616 }
4617 if (STRNCMP(s, "null", 4) == 0)
4618 {
4619 rettv->v_type = VAR_SPECIAL;
4620 rettv->vval.v_number = VVAL_NULL;
4621 return OK;
4622 }
4623 break;
4624 case 5: if (STRNCMP(s, "false", 5) == 0)
4625 {
4626 rettv->v_type = VAR_BOOL;
4627 rettv->vval.v_number = VVAL_FALSE;
4628 return OK;
4629 }
4630 break;
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004631 case 8: if (STRNCMP(s, "null_job", 8) == 0)
4632 {
Bram Moolenaar4f3321f2022-03-13 13:12:27 +00004633#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004634 rettv->v_type = VAR_JOB;
4635 rettv->vval.v_job = NULL;
Bram Moolenaar4f3321f2022-03-13 13:12:27 +00004636#else
4637 rettv->v_type = VAR_SPECIAL;
4638 rettv->vval.v_number = VVAL_NULL;
4639#endif
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004640 return OK;
4641 }
4642 break;
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004643 case 9:
4644 if (STRNCMP(s, "null_", 5) != 0)
4645 break;
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02004646 // null_list
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004647 if (STRNCMP(s + 5, "list", 4) == 0)
4648 {
4649 rettv->v_type = VAR_LIST;
4650 rettv->vval.v_list = NULL;
4651 return OK;
4652 }
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02004653 // null_dict
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004654 if (STRNCMP(s + 5, "dict", 4) == 0)
4655 {
4656 rettv->v_type = VAR_DICT;
4657 rettv->vval.v_dict = NULL;
4658 return OK;
4659 }
Yegappan Lakshmanan4776e642024-05-19 09:06:50 +02004660 // null_blob
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004661 if (STRNCMP(s + 5, "blob", 4) == 0)
4662 {
4663 rettv->v_type = VAR_BLOB;
4664 rettv->vval.v_blob = NULL;
4665 return OK;
4666 }
4667 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004668 case 10: if (STRNCMP(s, "null_class", 10) == 0)
4669 {
4670 rettv->v_type = VAR_CLASS;
4671 rettv->vval.v_class = NULL;
4672 return OK;
4673 }
4674 break;
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004675 case 11: if (STRNCMP(s, "null_string", 11) == 0)
4676 {
4677 rettv->v_type = VAR_STRING;
4678 rettv->vval.v_string = NULL;
4679 return OK;
4680 }
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004681 if (STRNCMP(s, "null_object", 11) == 0)
4682 {
4683 rettv->v_type = VAR_OBJECT;
4684 rettv->vval.v_object = NULL;
4685 return OK;
4686 }
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004687 break;
4688 case 12:
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004689 if (STRNCMP(s, "null_channel", 12) == 0)
4690 {
Bram Moolenaar4f3321f2022-03-13 13:12:27 +00004691#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004692 rettv->v_type = VAR_CHANNEL;
4693 rettv->vval.v_channel = NULL;
Bram Moolenaar4f3321f2022-03-13 13:12:27 +00004694#else
4695 rettv->v_type = VAR_SPECIAL;
4696 rettv->vval.v_number = VVAL_NULL;
4697#endif
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004698 return OK;
4699 }
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004700 if (STRNCMP(s, "null_partial", 12) == 0)
4701 {
4702 rettv->v_type = VAR_PARTIAL;
4703 rettv->vval.v_partial = NULL;
4704 return OK;
4705 }
4706 break;
4707 case 13: if (STRNCMP(s, "null_function", 13) == 0)
4708 {
4709 rettv->v_type = VAR_FUNC;
4710 rettv->vval.v_string = NULL;
4711 return OK;
4712 }
4713 break;
4714 }
4715 return FAIL;
4716}
4717
4718/*
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004719 * Handle register contents: @r.
4720 */
4721 static void
4722eval9_reg_contents(
4723 char_u **arg,
4724 typval_T *rettv,
4725 int evaluate)
4726{
4727 int vim9script = in_vim9script();
4728
4729 ++*arg; // skip '@'
4730 if (evaluate)
4731 {
4732 if (vim9script && IS_WHITE_OR_NUL(**arg))
4733 semsg(_(e_syntax_error_at_str), *arg);
4734 else if (vim9script && !valid_yank_reg(**arg, FALSE))
4735 emsg_invreg(**arg);
4736 else
4737 {
4738 rettv->v_type = VAR_STRING;
4739 rettv->vval.v_string = get_reg_contents(**arg,
4740 GREG_EXPR_SRC);
4741 }
4742 }
4743 if (**arg != NUL)
4744 ++*arg;
4745}
4746
4747/*
4748 * Handle a nested expression: (expression) or lambda: (arg) => expr
4749 */
4750 static int
4751eval9_nested_expr(
4752 char_u **arg,
4753 typval_T *rettv,
4754 evalarg_T *evalarg,
4755 int evaluate)
4756{
4757 int ret = NOTDONE;
4758 int vim9script = in_vim9script();
4759
4760 if (vim9script)
4761 {
4762 ret = get_lambda_tv(arg, rettv, TRUE, evalarg);
4763 if (ret == OK && evaluate)
4764 {
4765 ufunc_T *ufunc = rettv->vval.v_partial->pt_func;
4766
4767 // Compile it here to get the return type. The return
4768 // type is optional, when it's missing use t_unknown.
4769 // This is recognized in compile_return().
4770 if (ufunc->uf_ret_type->tt_type == VAR_VOID)
4771 ufunc->uf_ret_type = &t_unknown;
4772 if (compile_def_function(ufunc, FALSE,
4773 get_compile_type(ufunc), NULL) == FAIL)
4774 {
4775 clear_tv(rettv);
4776 ret = FAIL;
4777 }
4778 }
4779 }
4780 if (ret == NOTDONE)
4781 {
4782 *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
4783 ret = eval1(arg, rettv, evalarg); // recursive!
4784
4785 *arg = skipwhite_and_linebreak(*arg, evalarg);
4786 if (**arg == ')')
4787 ++*arg;
4788 else if (ret == OK)
4789 {
4790 emsg(_(e_missing_closing_paren));
4791 clear_tv(rettv);
4792 ret = FAIL;
4793 }
4794 }
4795
4796 return ret;
4797}
4798
4799/*
4800* Handle be a variable or function name.
4801* Can also be a curly-braces kind of name: {expr}.
4802*/
4803 static int
4804eval9_var_func_name(
4805 char_u **arg,
4806 typval_T *rettv,
4807 evalarg_T *evalarg,
4808 int evaluate,
4809 char_u **name_start)
4810{
4811 char_u *s;
4812 int len;
4813 char_u *alias;
4814 int ret = OK;
4815 int vim9script = in_vim9script();
4816
4817 s = *arg;
4818 len = get_name_len(arg, &alias, evaluate, TRUE);
4819 if (alias != NULL)
4820 s = alias;
4821
4822 if (len <= 0)
4823 ret = FAIL;
4824 else
4825 {
4826 int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
4827
4828 if (evaluate && vim9script && len == 1 && *s == '_')
4829 {
4830 emsg(_(e_cannot_use_underscore_here));
4831 ret = FAIL;
4832 }
4833 else if (evaluate && vim9script && len > 2
4834 && s[0] == 's' && s[1] == ':')
4835 {
4836 semsg(_(e_cannot_use_s_colon_in_vim9_script_str), s);
4837 ret = FAIL;
4838 }
4839 else if ((vim9script ? **arg : *skipwhite(*arg)) == '(')
4840 {
4841 // "name(..." recursive!
4842 *arg = skipwhite(*arg);
4843 ret = eval_func(arg, evalarg, s, len, rettv, flags, NULL);
4844 }
4845 else if (evaluate)
4846 {
4847 // get the value of "true", "false", etc. or a variable
4848 ret = FAIL;
4849 if (vim9script)
4850 ret = handle_predefined(s, len, rettv);
4851 if (ret == FAIL)
4852 {
4853 *name_start = s;
4854 ret = eval_variable(s, len, 0, rettv, NULL,
4855 EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT);
4856 }
4857 }
4858 else
4859 {
4860 // skip the name
4861 check_vars(s, len);
4862 ret = OK;
4863 }
4864 }
4865 vim_free(alias);
4866
4867 return ret;
4868}
4869
4870/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871 * Handle sixth level expression:
4872 * number number constant
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01004873 * 0zFFFFFFFF Blob constant
Bram Moolenaarbae0c162007-05-10 19:30:25 +00004874 * "string" string constant
4875 * 'string' literal string constant
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876 * &option-name option value
4877 * @r register contents
4878 * identifier variable value
4879 * function() function call
4880 * $VAR environment variable
4881 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004882 * [expr, expr] List
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004883 * {arg, arg -> expr} Lambda
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004884 * {key: val, key: val} Dictionary
Bram Moolenaar4c6d9042019-07-16 22:04:02 +02004885 * #{key: val, key: val} Dictionary with literal keys
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 *
4887 * Also handle:
4888 * ! in front logical NOT
4889 * - in front unary minus
4890 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004891 * trailing [] subscript in String or List
4892 * trailing .name entry in Dictionary
Bram Moolenaarac92e252019-08-03 21:58:38 +02004893 * trailing ->name() method call
Bram Moolenaar071d4272004-06-13 20:20:40 +00004894 *
4895 * "arg" must point to the first non-white of the expression.
Bram Moolenaarff1cd392020-08-05 11:51:30 +02004896 * "arg" is advanced to just after the recognized expression.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004897 *
4898 * Return OK or FAIL.
4899 */
4900 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004901eval9(
Bram Moolenaar7454a062016-01-30 15:14:10 +01004902 char_u **arg,
4903 typval_T *rettv,
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004904 evalarg_T *evalarg,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004905 int want_string) // after "." operator
Bram Moolenaar071d4272004-06-13 20:20:40 +00004906{
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02004907 int evaluate = evalarg != NULL
4908 && (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar32884ad2022-01-07 12:45:29 +00004909 char_u *name_start = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004910 char_u *start_leader, *end_leader;
4911 int ret = OK;
Bram Moolenaar4525a572022-02-13 11:57:33 +00004912 static int recurse = 0;
4913 int vim9script = in_vim9script();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004914
4915 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004916 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004917 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004918 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004919 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920
4921 /*
Bram Moolenaaredf3f972016-08-29 22:49:24 +02004922 * Skip '!', '-' and '+' characters. They are handled later.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004923 */
4924 start_leader = *arg;
Bram Moolenaar4525a572022-02-13 11:57:33 +00004925 if (eval_leader(arg, vim9script) == FAIL)
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004926 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004927 end_leader = *arg;
4928
Keith Thompson184f71c2024-01-04 21:19:04 +01004929 if (**arg == '.' && (!SAFE_isdigit(*(*arg + 1)) || in_old_script(2)))
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004930 {
Bram Moolenaar108010a2021-06-27 22:03:33 +02004931 semsg(_(e_invalid_expression_str), *arg);
Bram Moolenaar558ca4a2019-04-04 18:15:38 +02004932 ++*arg;
4933 return FAIL;
4934 }
4935
Bram Moolenaarfe6fb262022-01-24 18:16:12 +00004936 // Limit recursion to 1000 levels. At least at 10000 we run out of stack
Bram Moolenaar50e05252022-01-24 18:36:39 +00004937 // and crash. With MSVC the stack is smaller.
4938 if (recurse ==
4939#ifdef _MSC_VER
4940 300
4941#else
4942 1000
4943#endif
4944 )
Bram Moolenaarfe6fb262022-01-24 18:16:12 +00004945 {
4946 semsg(_(e_expression_too_recursive_str), *arg);
4947 return FAIL;
4948 }
4949 ++recurse;
4950
Bram Moolenaar071d4272004-06-13 20:20:40 +00004951 switch (**arg)
4952 {
4953 /*
4954 * Number constant.
4955 */
4956 case '0':
4957 case '1':
4958 case '2':
4959 case '3':
4960 case '4':
4961 case '5':
4962 case '6':
4963 case '7':
4964 case '8':
4965 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004966 case '.': ret = eval_number(arg, rettv, evaluate, want_string);
Bram Moolenaar0b1cd522020-06-27 13:11:50 +02004967
4968 // Apply prefixed "-" and "+" now. Matters especially when
4969 // "->" follows.
Bram Moolenaar3e06a1e2020-08-10 21:57:54 +02004970 if (ret == OK && evaluate && end_leader > start_leader
4971 && rettv->v_type != VAR_BLOB)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004972 ret = eval9_leader(rettv, TRUE, start_leader, &end_leader);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004973 break;
4974
4975 /*
4976 * String constant: "string".
4977 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01004978 case '"': ret = eval_string(arg, rettv, evaluate, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979 break;
4980
4981 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004982 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004983 */
Bram Moolenaar0abc2872022-05-10 13:24:30 +01004984 case '\'': ret = eval_lit_string(arg, rettv, evaluate, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004985 break;
4986
4987 /*
4988 * List: [expr, expr]
4989 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004990 case '[': ret = eval_list(arg, rettv, evalarg, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004991 break;
4992
4993 /*
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004994 * Literal Dictionary: #{key: val, key: val}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004995 */
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02004996 case '#': ret = eval_lit_dict(arg, rettv, evalarg);
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02004997 break;
4998
4999 /*
Bram Moolenaar069c1e72016-07-15 21:25:08 +02005000 * Lambda: {arg, arg -> expr}
Bram Moolenaard5abb4c2019-07-13 22:46:10 +02005001 * Dictionary: {'key': val, 'key': val}
Bram Moolenaar8c711452005-01-14 21:53:12 +00005002 */
Bram Moolenaar4525a572022-02-13 11:57:33 +00005003 case '{': if (vim9script)
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01005004 ret = NOTDONE;
5005 else
Bram Moolenaar4525a572022-02-13 11:57:33 +00005006 ret = get_lambda_tv(arg, rettv, vim9script, evalarg);
Bram Moolenaar069c1e72016-07-15 21:25:08 +02005007 if (ret == NOTDONE)
Bram Moolenaar8ea93902020-06-27 14:11:53 +02005008 ret = eval_dict(arg, rettv, evalarg, FALSE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005009 break;
5010
5011 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005012 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00005013 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02005014 case '&': ret = eval_option(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005015 break;
5016
5017 /*
5018 * Environment variable: $VAR.
LemonBoy2eaef102022-05-06 13:14:50 +01005019 * Interpolated string: $"string" or $'string'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020 */
LemonBoy2eaef102022-05-06 13:14:50 +01005021 case '$': if ((*arg)[1] == '"' || (*arg)[1] == '\'')
5022 ret = eval_interp_string(arg, rettv, evaluate);
5023 else
5024 ret = eval_env_var(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005025 break;
5026
5027 /*
5028 * Register contents: @r.
5029 */
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005030 case '@': eval9_reg_contents(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031 break;
5032
5033 /*
5034 * nested expression: (expression).
Bram Moolenaarecb66452021-05-18 15:09:18 +02005035 * or lambda: (arg) => expr
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036 */
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005037 case '(': ret = eval9_nested_expr(arg, rettv, evalarg, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005038 break;
5039
Bram Moolenaar8c711452005-01-14 21:53:12 +00005040 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005041 break;
5042 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005043
5044 if (ret == NOTDONE)
5045 {
5046 /*
5047 * Must be a variable or function name.
5048 * Can also be a curly-braces kind of name: {expr}.
5049 */
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005050 ret = eval9_var_func_name(arg, rettv, evalarg, evaluate, &name_start);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005051 }
5052
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005053 // Handle following '[', '(' and '.' for expr[expr], expr.name,
5054 // expr(expr), expr->name(expr)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005055 if (ret == OK)
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +01005056 ret = handle_subscript(arg, name_start, rettv, evalarg, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005057
5058 /*
5059 * Apply logical NOT and unary '-', from right to left, ignore '+'.
5060 */
5061 if (ret == OK && evaluate && end_leader > start_leader)
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01005062 ret = eval9_leader(rettv, FALSE, start_leader, &end_leader);
Bram Moolenaarfe6fb262022-01-24 18:16:12 +00005063
5064 --recurse;
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005065 return ret;
5066}
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005067
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005068/*
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01005069 * Apply the leading "!" and "-" before an eval9 expression to "rettv".
Bram Moolenaar0b1cd522020-06-27 13:11:50 +02005070 * When "numeric_only" is TRUE only handle "+" and "-".
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005071 * Adjusts "end_leaderp" until it is at "start_leader".
5072 */
5073 static int
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01005074eval9_leader(
Bram Moolenaar0b1cd522020-06-27 13:11:50 +02005075 typval_T *rettv,
5076 int numeric_only,
5077 char_u *start_leader,
5078 char_u **end_leaderp)
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005079{
5080 char_u *end_leader = *end_leaderp;
5081 int ret = OK;
5082 int error = FALSE;
5083 varnumber_T val = 0;
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005084 vartype_T type = rettv->v_type;
Bram Moolenaar4525a572022-02-13 11:57:33 +00005085 int vim9script = in_vim9script();
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005086 float_T f = 0.0;
5087
5088 if (rettv->v_type == VAR_FLOAT)
5089 f = rettv->vval.v_float;
5090 else
Bram Moolenaar27491cd2020-10-15 21:54:56 +02005091 {
5092 while (VIM_ISWHITE(end_leader[-1]))
5093 --end_leader;
Bram Moolenaar4525a572022-02-13 11:57:33 +00005094 if (vim9script && end_leader[-1] == '!')
Bram Moolenaar3e06a1e2020-08-10 21:57:54 +02005095 val = tv2bool(rettv);
5096 else
5097 val = tv_get_number_chk(rettv, &error);
Bram Moolenaar27491cd2020-10-15 21:54:56 +02005098 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005099 if (error)
5100 {
5101 clear_tv(rettv);
5102 ret = FAIL;
5103 }
5104 else
5105 {
5106 while (end_leader > start_leader)
5107 {
5108 --end_leader;
5109 if (*end_leader == '!')
5110 {
Bram Moolenaar0b1cd522020-06-27 13:11:50 +02005111 if (numeric_only)
5112 {
5113 ++end_leader;
5114 break;
5115 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005116 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar659bb222020-11-12 20:16:39 +01005117 {
Bram Moolenaar4525a572022-02-13 11:57:33 +00005118 if (vim9script)
Bram Moolenaar659bb222020-11-12 20:16:39 +01005119 {
5120 rettv->v_type = VAR_BOOL;
5121 val = f == 0.0 ? VVAL_TRUE : VVAL_FALSE;
5122 }
5123 else
5124 f = !f;
5125 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005126 else
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005127 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005128 val = !val;
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005129 type = VAR_BOOL;
5130 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005131 }
5132 else if (*end_leader == '-')
5133 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005134 if (rettv->v_type == VAR_FLOAT)
5135 f = -f;
5136 else
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005137 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005138 val = -val;
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005139 type = VAR_NUMBER;
5140 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005141 }
5142 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005143 if (rettv->v_type == VAR_FLOAT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005144 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005145 clear_tv(rettv);
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005146 rettv->vval.v_float = f;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005147 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005148 else
5149 {
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005150 clear_tv(rettv);
Bram Moolenaar4525a572022-02-13 11:57:33 +00005151 if (vim9script)
Bram Moolenaar6e4cfff2020-08-09 22:17:55 +02005152 rettv->v_type = type;
5153 else
5154 rettv->v_type = VAR_NUMBER;
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005155 rettv->vval.v_number = val;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005156 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005157 }
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02005158 *end_leaderp = end_leader;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005159 return ret;
5160}
5161
5162/*
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005163 * Call the function referred to in "rettv".
5164 */
5165 static int
5166call_func_rettv(
5167 char_u **arg,
Bram Moolenaare6b53242020-07-01 17:28:33 +02005168 evalarg_T *evalarg,
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005169 typval_T *rettv,
5170 int evaluate,
5171 dict_T *selfdict,
5172 typval_T *basetv)
5173{
5174 partial_T *pt = NULL;
5175 funcexe_T funcexe;
5176 typval_T functv;
5177 char_u *s;
5178 int ret;
5179
5180 // need to copy the funcref so that we can clear rettv
5181 if (evaluate)
5182 {
5183 functv = *rettv;
5184 rettv->v_type = VAR_UNKNOWN;
5185
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005186 // Invoke the function. Recursive!
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005187 if (functv.v_type == VAR_PARTIAL)
5188 {
5189 pt = functv.vval.v_partial;
5190 s = partial_name(pt);
5191 }
5192 else
Bram Moolenaar22db0d52021-06-12 12:16:55 +02005193 {
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005194 s = functv.vval.v_string;
Bram Moolenaar22db0d52021-06-12 12:16:55 +02005195 if (s == NULL || *s == NUL)
5196 {
5197 emsg(_(e_empty_function_name));
Bram Moolenaar744aecf2021-06-12 12:33:48 +02005198 ret = FAIL;
Bram Moolenaar22db0d52021-06-12 12:16:55 +02005199 goto theend;
5200 }
5201 }
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005202 }
5203 else
5204 s = (char_u *)"";
5205
Bram Moolenaara80faa82020-04-12 19:37:17 +02005206 CLEAR_FIELD(funcexe);
Bram Moolenaar851f86b2021-12-13 14:26:44 +00005207 funcexe.fe_firstline = curwin->w_cursor.lnum;
5208 funcexe.fe_lastline = curwin->w_cursor.lnum;
5209 funcexe.fe_evaluate = evaluate;
5210 funcexe.fe_partial = pt;
5211 funcexe.fe_selfdict = selfdict;
5212 funcexe.fe_basetv = basetv;
Bram Moolenaare6b53242020-07-01 17:28:33 +02005213 ret = get_func_tv(s, -1, rettv, arg, evalarg, &funcexe);
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005214
Bram Moolenaar22db0d52021-06-12 12:16:55 +02005215theend:
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005216 // Clear the funcref afterwards, so that deleting it while
5217 // evaluating the arguments is possible (see test55).
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005218 if (evaluate)
5219 clear_tv(&functv);
5220
5221 return ret;
5222}
5223
5224/*
5225 * Evaluate "->method()".
Bram Moolenaar7cebe8b2021-01-23 14:22:16 +01005226 * "*arg" points to "method".
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005227 * Returns FAIL or OK. "*arg" is advanced to after the ')'.
5228 */
5229 static int
5230eval_lambda(
5231 char_u **arg,
5232 typval_T *rettv,
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005233 evalarg_T *evalarg,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005234 int verbose) // give error messages
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005235{
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005236 int evaluate = evalarg != NULL
5237 && (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005238 typval_T base = *rettv;
5239 int ret;
5240
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005241 rettv->v_type = VAR_UNKNOWN;
5242
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01005243 if (**arg == '{')
5244 {
5245 // ->{lambda}()
5246 ret = get_lambda_tv(arg, rettv, FALSE, evalarg);
5247 }
5248 else
5249 {
5250 // ->(lambda)()
5251 ++*arg;
5252 ret = eval1(arg, rettv, evalarg);
5253 *arg = skipwhite_and_linebreak(*arg, evalarg);
Bram Moolenaar8b91e712022-04-17 15:06:35 +01005254 if (**arg != ')')
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01005255 {
Bram Moolenaare1242042021-12-16 20:56:57 +00005256 emsg(_(e_missing_closing_paren));
Bram Moolenaar8b91e712022-04-17 15:06:35 +01005257 return FAIL;
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01005258 }
Bram Moolenaar8b91e712022-04-17 15:06:35 +01005259 if (rettv->v_type != VAR_STRING && rettv->v_type != VAR_FUNC
5260 && rettv->v_type != VAR_PARTIAL)
5261 {
5262 emsg(_(e_string_or_function_required_for_arrow_parens_expr));
5263 return FAIL;
5264 }
5265 ++*arg;
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01005266 }
Bram Moolenaar0ff822d2019-12-08 18:41:34 +01005267 if (ret != OK)
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005268 return FAIL;
Bram Moolenaar8b91e712022-04-17 15:06:35 +01005269
5270 if (**arg != '(')
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005271 {
5272 if (verbose)
5273 {
5274 if (*skipwhite(*arg) == '(')
Bram Moolenaar3a846e62022-01-01 16:21:00 +00005275 emsg(_(e_no_white_space_allowed_before_parenthesis));
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005276 else
Bram Moolenaare1242042021-12-16 20:56:57 +00005277 semsg(_(e_missing_parenthesis_str), "lambda");
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005278 }
5279 clear_tv(rettv);
Bram Moolenaar86173482019-10-01 17:02:16 +02005280 ret = FAIL;
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005281 }
Bram Moolenaar86173482019-10-01 17:02:16 +02005282 else
Bram Moolenaare6b53242020-07-01 17:28:33 +02005283 ret = call_func_rettv(arg, evalarg, rettv, evaluate, NULL, &base);
Bram Moolenaar86173482019-10-01 17:02:16 +02005284
5285 // Clear the funcref afterwards, so that deleting it while
5286 // evaluating the arguments is possible (see test55).
5287 if (evaluate)
5288 clear_tv(&base);
5289
5290 return ret;
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005291}
5292
5293/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02005294 * Evaluate "->method()".
Bram Moolenaar7cebe8b2021-01-23 14:22:16 +01005295 * "*arg" points to "method".
Bram Moolenaarac92e252019-08-03 21:58:38 +02005296 * Returns FAIL or OK. "*arg" is advanced to after the ')'.
5297 */
5298 static int
5299eval_method(
5300 char_u **arg,
5301 typval_T *rettv,
Bram Moolenaare6b53242020-07-01 17:28:33 +02005302 evalarg_T *evalarg,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005303 int verbose) // give error messages
Bram Moolenaarac92e252019-08-03 21:58:38 +02005304{
5305 char_u *name;
5306 long len;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005307 char_u *alias;
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005308 char_u *tofree = NULL;
Bram Moolenaarac92e252019-08-03 21:58:38 +02005309 typval_T base = *rettv;
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005310 int ret = OK;
Bram Moolenaare6b53242020-07-01 17:28:33 +02005311 int evaluate = evalarg != NULL
5312 && (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaarac92e252019-08-03 21:58:38 +02005313
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005314 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaarac92e252019-08-03 21:58:38 +02005315
Bram Moolenaarac92e252019-08-03 21:58:38 +02005316 name = *arg;
Bram Moolenaar6ac69ed2022-09-03 12:09:07 +01005317 len = get_name_len(arg, &alias, evaluate, evaluate);
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005318 if (alias != NULL)
5319 name = alias;
5320
5321 if (len <= 0)
Bram Moolenaarac92e252019-08-03 21:58:38 +02005322 {
5323 if (verbose)
Bram Moolenaar9a846fb2022-01-01 21:59:18 +00005324 emsg(_(e_missing_name_after_method));
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005325 ret = FAIL;
Bram Moolenaarac92e252019-08-03 21:58:38 +02005326 }
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005327 else
Bram Moolenaarac92e252019-08-03 21:58:38 +02005328 {
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005329 char_u *paren;
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005330
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005331 // If there is no "(" immediately following, but there is further on,
5332 // it can be "import.Func()", "dict.Func()", "list[nr]", etc.
5333 // Does not handle anything where "(" is part of the expression.
5334 *arg = skipwhite(*arg);
5335
5336 if (**arg != '(' && alias == NULL
5337 && (paren = vim_strchr(*arg, '(')) != NULL)
5338 {
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005339 *arg = name;
Bram Moolenaar34820942022-12-19 20:28:38 +00005340
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02005341 // Truncate the name at the "(". Avoid trying to get another line
Bram Moolenaar34820942022-12-19 20:28:38 +00005342 // by making "getline" NULL.
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005343 *paren = NUL;
Bram Moolenaar34820942022-12-19 20:28:38 +00005344 char_u *(*getline)(int, void *, int, getline_opt_T) = NULL;
5345 if (evalarg != NULL)
5346 {
5347 getline = evalarg->eval_getline;
5348 evalarg->eval_getline = NULL;
5349 }
5350
5351 char_u *deref = deref_function_name(arg, &tofree, evalarg, verbose);
Bram Moolenaar64283d52022-01-18 10:37:29 +00005352 if (deref == NULL)
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005353 {
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005354 *arg = name + len;
5355 ret = FAIL;
5356 }
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005357 else
Bram Moolenaar64283d52022-01-18 10:37:29 +00005358 {
5359 name = deref;
K.Takata1a804522022-01-26 16:45:20 +00005360 len = (long)STRLEN(name);
Bram Moolenaar64283d52022-01-18 10:37:29 +00005361 }
Bram Moolenaar34820942022-12-19 20:28:38 +00005362
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005363 *paren = '(';
Bram Moolenaar34820942022-12-19 20:28:38 +00005364 if (getline != NULL)
5365 evalarg->eval_getline = getline;
Bram Moolenaar761fdf02019-08-05 23:10:16 +02005366 }
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005367
5368 if (ret == OK)
Bram Moolenaar51841322019-08-08 21:10:01 +02005369 {
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005370 *arg = skipwhite(*arg);
5371
5372 if (**arg != '(')
5373 {
5374 if (verbose)
5375 semsg(_(e_missing_parenthesis_str), name);
5376 ret = FAIL;
5377 }
5378 else if (VIM_ISWHITE((*arg)[-1]))
5379 {
5380 if (verbose)
5381 emsg(_(e_no_white_space_allowed_before_parenthesis));
5382 ret = FAIL;
5383 }
5384 else
5385 ret = eval_func(arg, evalarg, name, len, rettv,
Bram Moolenaar32e35112020-05-14 22:41:15 +02005386 evaluate ? EVAL_EVALUATE : 0, &base);
Bram Moolenaar857c8bb2022-01-15 21:08:19 +00005387 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02005388 }
Bram Moolenaarac92e252019-08-03 21:58:38 +02005389
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02005390 // Clear the funcref afterwards, so that deleting it while
5391 // evaluating the arguments is possible (see test55).
Bram Moolenaarac92e252019-08-03 21:58:38 +02005392 if (evaluate)
5393 clear_tv(&base);
Bram Moolenaarc665dab2022-01-16 19:38:07 +00005394 vim_free(tofree);
Bram Moolenaarac92e252019-08-03 21:58:38 +02005395
Yegappan Lakshmananfe424d12024-05-17 18:20:43 +02005396 if (alias != NULL)
5397 vim_free(alias);
5398
Bram Moolenaarac92e252019-08-03 21:58:38 +02005399 return ret;
5400}
5401
5402/*
Bram Moolenaar9e54a0e2006-04-14 20:42:25 +00005403 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
5404 * "*arg" points to the '[' or '.'.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005405 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
5406 */
5407 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01005408eval_index(
5409 char_u **arg,
5410 typval_T *rettv,
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005411 evalarg_T *evalarg,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005412 int verbose) // give error messages
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005413{
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005414 int evaluate = evalarg != NULL
5415 && (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005416 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00005417 typval_T var1, var2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005418 int range = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005419 char_u *key = NULL;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005420 int keylen = -1;
Bram Moolenaar4525a572022-02-13 11:57:33 +00005421 int vim9script = in_vim9script();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005422
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005423 if (check_can_index(rettv, evaluate, verbose) == FAIL)
5424 return FAIL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005425
Bram Moolenaar0a38dd22015-08-25 16:49:01 +02005426 init_tv(&var1);
5427 init_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005428 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005429 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005430 /*
5431 * dict.name
5432 */
5433 key = *arg + 1;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005434 for (keylen = 0; eval_isdictc(key[keylen]); ++keylen)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005435 ;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005436 if (keylen == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005437 return FAIL;
Bram Moolenaarc6e57b72020-09-12 21:27:03 +02005438 *arg = key + keylen;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005439 }
5440 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005441 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005442 /*
5443 * something[idx]
5444 *
5445 * Get the (first) variable from inside the [].
5446 */
Bram Moolenaar442af2f2020-07-03 21:09:52 +02005447 *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005448 if (**arg == ':')
5449 empty1 = TRUE;
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005450 else if (eval1(arg, &var1, evalarg) == FAIL) // recursive!
Bram Moolenaar8c711452005-01-14 21:53:12 +00005451 return FAIL;
Bram Moolenaar4525a572022-02-13 11:57:33 +00005452 else if (vim9script && **arg == ':')
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01005453 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005454 semsg(_(e_white_space_required_before_and_after_str_at_str),
5455 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01005456 clear_tv(&var1);
5457 return FAIL;
5458 }
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01005459 else if (evaluate)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005460 {
Bram Moolenaarf47c5a82021-12-19 15:17:21 +00005461 int error = FALSE;
5462
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01005463 // allow for indexing with float
Bram Moolenaar4525a572022-02-13 11:57:33 +00005464 if (vim9script && rettv->v_type == VAR_DICT
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01005465 && var1.v_type == VAR_FLOAT)
5466 {
5467 var1.vval.v_string = typval_tostring(&var1, TRUE);
5468 var1.v_type = VAR_STRING;
5469 }
Bram Moolenaar73e28dc2022-09-17 21:08:33 +01005470
Bram Moolenaar4525a572022-02-13 11:57:33 +00005471 if (vim9script && rettv->v_type == VAR_LIST)
Bram Moolenaarf47c5a82021-12-19 15:17:21 +00005472 tv_get_number_chk(&var1, &error);
5473 else
5474 error = tv_get_string_chk(&var1) == NULL;
5475 if (error)
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01005476 {
5477 // not a number or string
5478 clear_tv(&var1);
5479 return FAIL;
5480 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005481 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005482
5483 /*
5484 * Get the second variable from inside the [:].
5485 */
Bram Moolenaar442af2f2020-07-03 21:09:52 +02005486 *arg = skipwhite_and_linebreak(*arg, evalarg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005487 if (**arg == ':')
5488 {
5489 range = TRUE;
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01005490 ++*arg;
Bram Moolenaar4525a572022-02-13 11:57:33 +00005491 if (vim9script && !IS_WHITE_OR_NUL(**arg) && **arg != ']')
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01005492 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005493 semsg(_(e_white_space_required_before_and_after_str_at_str),
5494 ":", *arg - 1);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01005495 if (!empty1)
5496 clear_tv(&var1);
5497 return FAIL;
5498 }
5499 *arg = skipwhite_and_linebreak(*arg, evalarg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005500 if (**arg == ']')
5501 empty2 = TRUE;
Bram Moolenaare40fbc22020-06-27 18:06:45 +02005502 else if (eval1(arg, &var2, evalarg) == FAIL) // recursive!
Bram Moolenaar8c711452005-01-14 21:53:12 +00005503 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005504 if (!empty1)
5505 clear_tv(&var1);
5506 return FAIL;
5507 }
Bram Moolenaard155d7a2018-12-21 16:04:21 +01005508 else if (evaluate && tv_get_string_chk(&var2) == NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005509 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005510 // not a number or string
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005511 if (!empty1)
5512 clear_tv(&var1);
5513 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005514 return FAIL;
5515 }
5516 }
5517
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005518 // Check for the ']'.
Bram Moolenaar442af2f2020-07-03 21:09:52 +02005519 *arg = skipwhite_and_linebreak(*arg, evalarg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005520 if (**arg != ']')
5521 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00005522 if (verbose)
Bram Moolenaare1242042021-12-16 20:56:57 +00005523 emsg(_(e_missing_closing_square_brace));
Bram Moolenaar8c711452005-01-14 21:53:12 +00005524 clear_tv(&var1);
5525 if (range)
5526 clear_tv(&var2);
5527 return FAIL;
5528 }
Bram Moolenaarf9235712020-08-16 18:42:53 +02005529 *arg = *arg + 1; // skip over the ']'
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005530 }
5531
5532 if (evaluate)
5533 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005534 int res = eval_index_inner(rettv, range,
Bram Moolenaar6601b622021-01-13 21:47:15 +01005535 empty1 ? NULL : &var1, empty2 ? NULL : &var2, FALSE,
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005536 key, keylen, verbose);
Bram Moolenaar6601b622021-01-13 21:47:15 +01005537
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005538 if (!empty1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005539 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005540 if (range)
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005541 clear_tv(&var2);
5542 return res;
5543 }
5544 return OK;
5545}
5546
5547/*
5548 * Check if "rettv" can have an [index] or [sli:ce]
5549 */
5550 int
5551check_can_index(typval_T *rettv, int evaluate, int verbose)
5552{
5553 switch (rettv->v_type)
5554 {
5555 case VAR_FUNC:
5556 case VAR_PARTIAL:
5557 if (verbose)
Bram Moolenaarf47c5a82021-12-19 15:17:21 +00005558 emsg(_(e_cannot_index_a_funcref));
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005559 return FAIL;
5560 case VAR_FLOAT:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005561 if (verbose)
Bram Moolenaar74409f62022-01-01 15:58:22 +00005562 emsg(_(e_using_float_as_string));
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005563 return FAIL;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005564 case VAR_BOOL:
5565 case VAR_SPECIAL:
5566 case VAR_JOB:
5567 case VAR_CHANNEL:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005568 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005569 case VAR_OBJECT:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005570 if (verbose)
5571 emsg(_(e_cannot_index_special_variable));
5572 return FAIL;
Ernie Raele75fde62023-12-21 17:18:54 +01005573 case VAR_CLASS:
5574 case VAR_TYPEALIAS:
5575 if (verbose)
5576 check_typval_is_value(rettv);
5577 return FAIL;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005578 case VAR_UNKNOWN:
5579 case VAR_ANY:
5580 case VAR_VOID:
5581 if (evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005582 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005583 emsg(_(e_cannot_index_special_variable));
5584 return FAIL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005585 }
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005586 // FALLTHROUGH
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005587
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005588 case VAR_STRING:
5589 case VAR_LIST:
5590 case VAR_DICT:
5591 case VAR_BLOB:
5592 break;
5593 case VAR_NUMBER:
5594 if (in_vim9script())
5595 emsg(_(e_cannot_index_number));
5596 break;
5597 }
5598 return OK;
5599}
5600
5601/*
5602 * Apply index or range to "rettv".
5603 * "var1" is the first index, NULL for [:expr].
5604 * "var2" is the second index, NULL for [expr] and [expr: ]
Bram Moolenaar6601b622021-01-13 21:47:15 +01005605 * "exclusive" is TRUE for slice(): second index is exclusive, use character
5606 * index for string.
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005607 * Alternatively, "key" is not NULL, then key[keylen] is the dict index.
5608 */
5609 int
5610eval_index_inner(
5611 typval_T *rettv,
5612 int is_range,
5613 typval_T *var1,
5614 typval_T *var2,
Bram Moolenaar6601b622021-01-13 21:47:15 +01005615 int exclusive,
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005616 char_u *key,
5617 int keylen,
5618 int verbose)
5619{
Bram Moolenaar6601b622021-01-13 21:47:15 +01005620 varnumber_T n1, n2 = 0;
5621 long len;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005622
5623 n1 = 0;
5624 if (var1 != NULL && rettv->v_type != VAR_DICT)
5625 n1 = tv_get_number(var1);
5626
5627 if (is_range)
5628 {
5629 if (rettv->v_type == VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005630 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005631 if (verbose)
5632 emsg(_(e_cannot_slice_dictionary));
5633 return FAIL;
5634 }
Bram Moolenaar6601b622021-01-13 21:47:15 +01005635 if (var2 != NULL)
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005636 n2 = tv_get_number(var2);
Bram Moolenaar6601b622021-01-13 21:47:15 +01005637 else
5638 n2 = VARNUM_MAX;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005639 }
Bram Moolenaara03f2332016-02-06 18:09:59 +01005640
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005641 switch (rettv->v_type)
5642 {
5643 case VAR_UNKNOWN:
5644 case VAR_ANY:
5645 case VAR_VOID:
5646 case VAR_FUNC:
5647 case VAR_PARTIAL:
5648 case VAR_FLOAT:
5649 case VAR_BOOL:
5650 case VAR_SPECIAL:
5651 case VAR_JOB:
5652 case VAR_CHANNEL:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005653 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00005654 case VAR_CLASS:
5655 case VAR_OBJECT:
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02005656 case VAR_TYPEALIAS:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005657 break; // not evaluating, skipping over subscript
5658
5659 case VAR_NUMBER:
5660 case VAR_STRING:
5661 {
5662 char_u *s = tv_get_string(rettv);
5663
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005664 len = (long)STRLEN(s);
Bram Moolenaar6601b622021-01-13 21:47:15 +01005665 if (in_vim9script() || exclusive)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02005666 {
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005667 if (is_range)
Bram Moolenaar6601b622021-01-13 21:47:15 +01005668 s = string_slice(s, n1, n2, exclusive);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02005669 else
5670 s = char_from_string(s, n1);
5671 }
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005672 else if (is_range)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005673 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005674 // The resulting variable is a substring. If the indexes
5675 // are out of range the result is empty.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005676 if (n1 < 0)
5677 {
5678 n1 = len + n1;
5679 if (n1 < 0)
5680 n1 = 0;
5681 }
5682 if (n2 < 0)
5683 n2 = len + n2;
5684 else if (n2 >= len)
5685 n2 = len;
5686 if (n1 >= len || n2 < 0 || n1 > n2)
5687 s = NULL;
5688 else
Bram Moolenaardf44a272020-06-07 20:49:05 +02005689 s = vim_strnsave(s + n1, n2 - n1 + 1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005690 }
5691 else
5692 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01005693 // The resulting variable is a string of a single
5694 // character. If the index is too big or negative the
5695 // result is empty.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005696 if (n1 >= len || n1 < 0)
5697 s = NULL;
5698 else
5699 s = vim_strnsave(s + n1, 1);
5700 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005701 clear_tv(rettv);
5702 rettv->v_type = VAR_STRING;
5703 rettv->vval.v_string = s;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005704 }
5705 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005706
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005707 case VAR_BLOB:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02005708 blob_slice_or_index(rettv->vval.v_blob, is_range, n1, n2,
5709 exclusive, rettv);
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005710 break;
5711
5712 case VAR_LIST:
5713 if (var1 == NULL)
5714 n1 = 0;
5715 if (var2 == NULL)
Bram Moolenaar6601b622021-01-13 21:47:15 +01005716 n2 = VARNUM_MAX;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005717 if (list_slice_or_index(rettv->vval.v_list,
Bram Moolenaar6601b622021-01-13 21:47:15 +01005718 is_range, n1, n2, exclusive, rettv, verbose) == FAIL)
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005719 return FAIL;
5720 break;
5721
5722 case VAR_DICT:
5723 {
5724 dictitem_T *item;
5725 typval_T tmp;
5726
5727 if (key == NULL)
5728 {
5729 key = tv_get_string_chk(var1);
5730 if (key == NULL)
5731 return FAIL;
5732 }
5733
Bram Moolenaar5c1ec432021-11-29 13:44:55 +00005734 item = dict_find(rettv->vval.v_dict, key, keylen);
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005735
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005736 if (item == NULL)
Bram Moolenaar5c1ec432021-11-29 13:44:55 +00005737 {
5738 if (verbose)
5739 {
5740 if (keylen > 0)
5741 key[keylen] = NUL;
Bram Moolenaara9fa8c52023-01-02 18:10:04 +00005742 semsg(_(e_key_not_present_in_dictionary_str), key);
Bram Moolenaar5c1ec432021-11-29 13:44:55 +00005743 }
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005744 return FAIL;
Bram Moolenaar5c1ec432021-11-29 13:44:55 +00005745 }
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005746
5747 copy_tv(&item->di_tv, &tmp);
5748 clear_tv(rettv);
5749 *rettv = tmp;
5750 }
5751 break;
5752 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005753 return OK;
5754}
5755
5756/*
Bram Moolenaar4c683752020-04-05 21:38:23 +02005757 * Return the function name of partial "pt".
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005758 */
5759 char_u *
5760partial_name(partial_T *pt)
5761{
Dominique Pellefe8ebdb2021-05-13 14:55:55 +02005762 if (pt != NULL)
5763 {
5764 if (pt->pt_name != NULL)
5765 return pt->pt_name;
5766 if (pt->pt_func != NULL)
5767 return pt->pt_func->uf_name;
5768 }
Bram Moolenaar92b83cc2020-04-25 15:24:44 +02005769 return (char_u *)"";
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005770}
5771
Bram Moolenaarddecc252016-04-06 22:59:37 +02005772 static void
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005773partial_free(partial_T *pt)
Bram Moolenaarddecc252016-04-06 22:59:37 +02005774{
5775 int i;
5776
5777 for (i = 0; i < pt->pt_argc; ++i)
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005778 clear_tv(&pt->pt_argv[i]);
Bram Moolenaarddecc252016-04-06 22:59:37 +02005779 vim_free(pt->pt_argv);
Bram Moolenaar107e1ee2016-04-08 17:07:19 +02005780 dict_unref(pt->pt_dict);
Bram Moolenaar437bafe2016-08-01 15:40:54 +02005781 if (pt->pt_name != NULL)
5782 {
5783 func_unref(pt->pt_name);
5784 vim_free(pt->pt_name);
5785 }
5786 else
5787 func_ptr_unref(pt->pt_func);
Yegappan Lakshmanan29bb67f2023-10-14 11:18:50 +02005788 object_unref(pt->pt_obj);
Bram Moolenaarf7779c62020-05-03 15:38:16 +02005789
Bram Moolenaar54656012021-06-09 20:50:46 +02005790 // "out_up" is no longer used, decrement refcount on partial that owns it.
5791 partial_unref(pt->pt_outer.out_up_partial);
5792
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00005793 // Using pt_outer from another partial.
5794 partial_unref(pt->pt_outer_partial);
5795
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02005796 // Decrease the reference count for the context of a closure. If down
5797 // to the minimum it may be time to free it.
Bram Moolenaarf7779c62020-05-03 15:38:16 +02005798 if (pt->pt_funcstack != NULL)
5799 {
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02005800 --pt->pt_funcstack->fs_refcount;
5801 funcstack_check_refcount(pt->pt_funcstack);
Bram Moolenaarf7779c62020-05-03 15:38:16 +02005802 }
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01005803 // Similarly for loop variables.
Bram Moolenaarcc341812022-09-19 15:54:34 +01005804 for (i = 0; i < MAX_LOOP_DEPTH; ++i)
5805 if (pt->pt_loopvars[i] != NULL)
5806 {
5807 --pt->pt_loopvars[i]->lvs_refcount;
5808 loopvars_check_refcount(pt->pt_loopvars[i]);
5809 }
Bram Moolenaarf7779c62020-05-03 15:38:16 +02005810
Bram Moolenaarddecc252016-04-06 22:59:37 +02005811 vim_free(pt);
5812}
5813
5814/*
5815 * Unreference a closure: decrement the reference count and free it when it
5816 * becomes zero.
5817 */
5818 void
5819partial_unref(partial_T *pt)
5820{
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00005821 if (pt == NULL)
5822 return;
5823
5824 int done = FALSE;
5825
5826 if (--pt->pt_refcount <= 0)
5827 partial_free(pt);
5828
5829 // If the reference count goes down to one, the funcstack may be the
5830 // only reference and can be freed if no other partials reference it.
5831 else if (pt->pt_refcount == 1)
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02005832 {
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00005833 // careful: if the funcstack is freed it may contain this partial
5834 // and it gets freed as well
5835 if (pt->pt_funcstack != NULL)
5836 done = funcstack_check_refcount(pt->pt_funcstack);
Bram Moolenaaracd6b992022-09-17 16:27:39 +01005837
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00005838 if (!done)
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01005839 {
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00005840 int depth;
Bram Moolenaaracd6b992022-09-17 16:27:39 +01005841
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00005842 for (depth = 0; depth < MAX_LOOP_DEPTH; ++depth)
5843 if (pt->pt_loopvars[depth] != NULL
5844 && loopvars_check_refcount(pt->pt_loopvars[depth]))
Bram Moolenaarcc341812022-09-19 15:54:34 +01005845 break;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01005846 }
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +02005847 }
Bram Moolenaarddecc252016-04-06 22:59:37 +02005848}
5849
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005850/*
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02005851 * Return a textual representation of a string in "tv".
5852 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5853 * When both "echo_style" and "composite_val" are FALSE, put quotes around
5854 * strings as "string()", otherwise does not put quotes around strings.
5855 * May return NULL.
5856 */
5857 static char_u *
5858string_tv2string(
5859 typval_T *tv,
5860 char_u **tofree,
5861 int echo_style,
5862 int composite_val)
5863{
5864 char_u *r = NULL;
5865
5866 if (echo_style && !composite_val)
5867 {
5868 *tofree = NULL;
5869 r = tv->vval.v_string;
5870 if (r == NULL)
5871 r = (char_u *)"";
5872 }
5873 else
5874 {
5875 *tofree = string_quote(tv->vval.v_string, FALSE);
5876 r = *tofree;
5877 }
5878
5879 return r;
5880}
5881
5882/*
5883 * Return a textual representation of a function in "tv".
5884 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5885 * When "echo_style" is FALSE, put quotes around the function name as
5886 * "function()", otherwise does not put quotes around function name.
5887 * May return NULL.
5888 */
5889 static char_u *
5890func_tv2string(typval_T *tv, char_u **tofree, int echo_style)
5891{
5892 char_u *r = NULL;
5893 char_u buf[MAX_FUNC_NAME_LEN];
5894
5895 if (echo_style)
5896 {
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005897 *tofree = NULL;
5898
Yegappan Lakshmanan8904d672024-05-29 07:51:50 +02005899 if (tv->vval.v_string == NULL)
Yegappan Lakshmanan8904d672024-05-29 07:51:50 +02005900 r = (char_u *)"function()";
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02005901 else
Yegappan Lakshmanan8904d672024-05-29 07:51:50 +02005902 {
5903 r = make_ufunc_name_readable(tv->vval.v_string, buf,
5904 MAX_FUNC_NAME_LEN);
5905 if (r == buf)
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005906 r = *tofree = vim_strsave(buf);
Yegappan Lakshmanan8904d672024-05-29 07:51:50 +02005907 }
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02005908 }
5909 else
5910 {
Yegappan Lakshmanan51c45e82024-05-30 07:50:08 +02005911 char_u *s = NULL;
5912
5913 if (tv->vval.v_string != NULL)
5914 s = make_ufunc_name_readable(tv->vval.v_string, buf,
5915 MAX_FUNC_NAME_LEN);
5916
5917 r = *tofree = string_quote(s, TRUE);
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02005918 }
5919
5920 return r;
5921}
5922
5923/*
Ernie Rael9d779c52024-07-07 20:41:44 +02005924 * Return a textual representation of the object method in "tv", a VAR_PARTIAL.
5925 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5926 * When "echo_style" is FALSE, put quotes around the function name as
5927 * "function()", otherwise does not put quotes around function name.
5928 * May return NULL.
5929 */
5930 static char_u *
5931method_tv2string(typval_T *tv, char_u **tofree, int echo_style)
5932{
5933 char_u buf[MAX_FUNC_NAME_LEN];
5934 partial_T *pt = tv->vval.v_partial;
5935
5936 size_t len = vim_snprintf((char *)buf, sizeof(buf), "<SNR>%d_%s.%s",
5937 pt->pt_func->uf_script_ctx.sc_sid,
5938 pt->pt_func->uf_class->class_name,
5939 pt->pt_func->uf_name);
5940 if (len >= sizeof(buf))
5941 {
5942 if (echo_style)
5943 {
5944 *tofree = NULL;
5945 return (char_u *)"function()";
5946 }
5947 else
5948 return *tofree = string_quote((char_u*)"", TRUE);
5949 }
5950
5951 return *tofree = echo_style ? vim_strsave(buf) : string_quote(buf, TRUE);
5952}
5953
5954/*
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02005955 * Return a textual representation of a partial in "tv".
5956 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5957 * "numbuf" is used for a number. May return NULL.
5958 */
5959 static char_u *
5960partial_tv2string(
5961 typval_T *tv,
5962 char_u **tofree,
5963 char_u *numbuf,
5964 int copyID)
5965{
5966 char_u *r = NULL;
5967 partial_T *pt;
5968 char_u *fname;
5969 garray_T ga;
5970 int i;
5971 char_u *tf;
5972
5973 pt = tv->vval.v_partial;
5974 fname = string_quote(pt == NULL ? NULL : partial_name(pt), FALSE);
5975
5976 ga_init2(&ga, 1, 100);
5977 ga_concat(&ga, (char_u *)"function(");
5978 if (fname != NULL)
5979 {
5980 // When using uf_name prepend "g:" for a global function.
5981 if (pt != NULL && pt->pt_name == NULL && fname[0] == '\''
5982 && vim_isupper(fname[1]))
5983 {
5984 ga_concat(&ga, (char_u *)"'g:");
5985 ga_concat(&ga, fname + 1);
5986 }
5987 else
5988 ga_concat(&ga, fname);
5989 vim_free(fname);
5990 }
5991 if (pt != NULL && pt->pt_argc > 0)
5992 {
5993 ga_concat(&ga, (char_u *)", [");
5994 for (i = 0; i < pt->pt_argc; ++i)
5995 {
5996 if (i > 0)
5997 ga_concat(&ga, (char_u *)", ");
5998 ga_concat(&ga, tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
5999 vim_free(tf);
6000 }
6001 ga_concat(&ga, (char_u *)"]");
6002 }
6003 if (pt != NULL && pt->pt_dict != NULL)
6004 {
6005 typval_T dtv;
6006
6007 ga_concat(&ga, (char_u *)", ");
6008 dtv.v_type = VAR_DICT;
6009 dtv.vval.v_dict = pt->pt_dict;
6010 ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
6011 vim_free(tf);
6012 }
6013 // terminate with ')' and a NUL
6014 ga_concat_len(&ga, (char_u *)")", 2);
6015
6016 *tofree = ga.ga_data;
6017 r = *tofree;
6018
6019 return r;
6020}
6021
6022/*
6023 * Return a textual representation of a List in "tv".
6024 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6025 * When "copyID" is not zero replace recursive lists with "...". When
6026 * "restore_copyID" is FALSE, repeated items in lists are replaced with "...".
6027 * May return NULL.
6028 */
6029 static char_u *
6030list_tv2string(
6031 typval_T *tv,
6032 char_u **tofree,
6033 int copyID,
6034 int restore_copyID)
6035{
6036 char_u *r = NULL;
6037
6038 if (tv->vval.v_list == NULL)
6039 {
6040 // NULL list is equivalent to empty list.
6041 *tofree = NULL;
6042 r = (char_u *)"[]";
6043 }
6044 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
6045 && tv->vval.v_list->lv_len > 0)
6046 {
6047 *tofree = NULL;
6048 r = (char_u *)"[...]";
6049 }
6050 else
6051 {
Christian Brabandtb335a932024-05-21 18:39:10 +02006052 int old_copyID;
6053 if (restore_copyID)
6054 old_copyID = tv->vval.v_list->lv_copyID;
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006055
6056 tv->vval.v_list->lv_copyID = copyID;
6057 *tofree = list2string(tv, copyID, restore_copyID);
6058 if (restore_copyID)
6059 tv->vval.v_list->lv_copyID = old_copyID;
6060 r = *tofree;
6061 }
6062
6063 return r;
6064}
6065
6066/*
6067 * Return a textual representation of a Dict in "tv".
6068 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6069 * When "copyID" is not zero replace recursive dicts with "...".
6070 * When "restore_copyID" is FALSE, repeated items in the dictionary are
6071 * replaced with "...". May return NULL.
6072 */
6073 static char_u *
6074dict_tv2string(
6075 typval_T *tv,
6076 char_u **tofree,
6077 int copyID,
6078 int restore_copyID)
6079{
6080 char_u *r = NULL;
6081
6082 if (tv->vval.v_dict == NULL)
6083 {
6084 // NULL dict is equivalent to empty dict.
6085 *tofree = NULL;
6086 r = (char_u *)"{}";
6087 }
6088 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
6089 && tv->vval.v_dict->dv_hashtab.ht_used != 0)
6090 {
6091 *tofree = NULL;
6092 r = (char_u *)"{...}";
6093 }
6094 else
6095 {
Christian Brabandtb335a932024-05-21 18:39:10 +02006096 int old_copyID;
6097 if (restore_copyID)
6098 old_copyID = tv->vval.v_dict->dv_copyID;
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006099
6100 tv->vval.v_dict->dv_copyID = copyID;
6101 *tofree = dict2string(tv, copyID, restore_copyID);
6102 if (restore_copyID)
6103 tv->vval.v_dict->dv_copyID = old_copyID;
6104 r = *tofree;
6105 }
6106
6107 return r;
6108}
6109
6110/*
6111 * Return a textual representation of a job or a channel in "tv".
6112 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6113 * "numbuf" is used for a number.
6114 * When "composite_val" is FALSE, put quotes around strings as "string()",
6115 * otherwise does not put quotes around strings.
6116 * May return NULL.
6117 */
6118 static char_u *
6119jobchan_tv2string(
Dominique Pellé0268ff32024-07-28 21:12:20 +02006120 typval_T *tv UNUSED,
6121 char_u **tofree UNUSED,
6122 char_u *numbuf UNUSED,
6123 int composite_val UNUSED)
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006124{
6125 char_u *r = NULL;
6126
6127#ifdef FEAT_JOB_CHANNEL
6128 *tofree = NULL;
6129
6130 if (tv->v_type == VAR_JOB)
6131 r = job_to_string_buf(tv, numbuf);
6132 else
6133 r = channel_to_string_buf(tv, numbuf);
6134
6135 if (composite_val)
6136 {
6137 *tofree = string_quote(r, FALSE);
6138 r = *tofree;
6139 }
6140#endif
6141
6142 return r;
6143}
6144
6145/*
6146 * Return a textual representation of a class in "tv".
6147 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6148 * May return NULL.
6149 */
6150 static char_u *
6151class_tv2string(typval_T *tv, char_u **tofree)
6152{
6153 char_u *r = NULL;
John Marriottbd4614f2024-11-18 20:25:21 +01006154 size_t rsize;
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006155 class_T *cl = tv->vval.v_class;
John Marriottbd4614f2024-11-18 20:25:21 +01006156 char_u *class_name = (char_u *)"[unknown]";
6157 size_t class_namelen = 9;
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006158 char *s = "class";
John Marriottbd4614f2024-11-18 20:25:21 +01006159 size_t slen = 5;
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006160
John Marriottbd4614f2024-11-18 20:25:21 +01006161 if (cl != NULL)
6162 {
6163 class_name = cl->class_name;
6164 class_namelen = STRLEN(cl->class_name);
6165 if (IS_INTERFACE(cl))
6166 {
6167 s = "interface";
6168 slen = 9;
6169 }
6170 else if (IS_ENUM(cl))
6171 {
6172 s = "enum";
6173 slen = 4;
6174 }
6175 }
6176
6177 rsize = slen + 1 + class_namelen + 1;
6178 r = *tofree = alloc(rsize);
6179 if (r != NULL)
6180 vim_snprintf((char *)r, rsize, "%s %s", s, (char *)class_name);
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006181
6182 return r;
6183}
6184
6185/*
Ernie Rael05ff4e42024-07-04 16:50:11 +02006186 * Return a textual representation of an Object in "tv".
6187 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6188 * When "copyID" is not zero replace recursive object with "...".
6189 * When "restore_copyID" is FALSE, repeated items in the object are
6190 * replaced with "...". May return NULL.
6191 */
6192 static char_u *
6193object_tv2string(
6194 typval_T *tv,
6195 char_u **tofree,
6196 int copyID,
6197 int restore_copyID,
6198 char_u *numbuf,
6199 int echo_style,
6200 int composite_val)
6201{
6202 char_u *r = NULL;
6203
6204 object_T *obj = tv->vval.v_object;
6205 if (obj == NULL || obj->obj_class == NULL)
6206 {
6207 *tofree = NULL;
6208 r = (char_u *)"object of [unknown]";
6209 }
6210 else if (copyID != 0 && obj->obj_copyID == copyID
zeertzjqd9be94c2024-07-14 10:20:20 +02006211 && obj->obj_class->class_obj_member_count != 0)
Ernie Rael05ff4e42024-07-04 16:50:11 +02006212 {
John Marriottbd4614f2024-11-18 20:25:21 +01006213 size_t n = 25 + STRLEN((char *)obj->obj_class->class_name);
Ernie Rael05ff4e42024-07-04 16:50:11 +02006214 r = alloc(n);
6215 if (r != NULL)
Ernie Rael5285b3c2024-07-08 20:42:45 +02006216 (void)vim_snprintf((char *)r, n, "object of %s {...}",
Ernie Rael05ff4e42024-07-04 16:50:11 +02006217 obj->obj_class->class_name);
6218 *tofree = r;
6219 }
6220 else
6221 {
6222 int old_copyID;
6223 if (restore_copyID)
6224 old_copyID = obj->obj_copyID;
6225
6226 obj->obj_copyID = copyID;
6227 *tofree = object2string(obj, numbuf, copyID, echo_style,
6228 restore_copyID, composite_val);
6229 if (restore_copyID)
6230 obj->obj_copyID = old_copyID;
6231 r = *tofree;
6232 }
6233
6234 return r;
6235}
6236
6237/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006238 * Return a string with the string representation of a variable.
6239 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006240 * "numbuf" is used for a number.
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006241 * When "copyID" is not zero replace recursive lists and dicts with "...".
Bram Moolenaar35422f42017-08-05 16:33:56 +02006242 * When both "echo_style" and "composite_val" are FALSE, put quotes around
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01006243 * strings as "string()", otherwise does not put quotes around strings, as
Bram Moolenaar35422f42017-08-05 16:33:56 +02006244 * ":echo" displays values.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006245 * When "restore_copyID" is FALSE, repeated items in dictionaries and lists
6246 * are replaced with "...".
Bram Moolenaar92c5aba2007-08-14 20:29:31 +00006247 * May return NULL.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006248 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02006249 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006250echo_string_core(
Bram Moolenaar7454a062016-01-30 15:14:10 +01006251 typval_T *tv,
6252 char_u **tofree,
6253 char_u *numbuf,
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006254 int copyID,
6255 int echo_style,
6256 int restore_copyID,
Bram Moolenaar35422f42017-08-05 16:33:56 +02006257 int composite_val)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006258{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006259 static int recurse = 0;
6260 char_u *r = NULL;
6261
Bram Moolenaar33570922005-01-25 22:26:29 +00006262 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006263 {
Bram Moolenaar8502c702014-06-17 12:51:16 +02006264 if (!did_echo_string_emsg)
6265 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006266 // Only give this message once for a recursive call to avoid
6267 // flooding the user with errors. And stop iterating over lists
Ernie Rael05ff4e42024-07-04 16:50:11 +02006268 // and dicts and objects.
Bram Moolenaar8502c702014-06-17 12:51:16 +02006269 did_echo_string_emsg = TRUE;
Bram Moolenaara6f79292022-01-04 21:30:47 +00006270 emsg(_(e_variable_nested_too_deep_for_displaying));
Bram Moolenaar8502c702014-06-17 12:51:16 +02006271 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006272 *tofree = NULL;
Bram Moolenaar8502c702014-06-17 12:51:16 +02006273 return (char_u *)"{E724}";
Bram Moolenaare9a41262005-01-15 22:18:47 +00006274 }
6275 ++recurse;
6276
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006277 switch (tv->v_type)
6278 {
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006279 case VAR_STRING:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006280 r = string_tv2string(tv, tofree, echo_style, composite_val);
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006281 break;
6282
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006283 case VAR_FUNC:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006284 r = func_tv2string(tv, tofree, echo_style);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006285 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006286
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006287 case VAR_PARTIAL:
Ernie Rael9d779c52024-07-07 20:41:44 +02006288 if (tv->vval.v_partial == NULL
6289 || tv->vval.v_partial->pt_obj == NULL)
6290 r = partial_tv2string(tv, tofree, numbuf, copyID);
6291 else
6292 r = method_tv2string(tv, tofree, echo_style);
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006293 break;
Bram Moolenaar1735bc92016-03-14 23:05:14 +01006294
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006295 case VAR_BLOB:
Bram Moolenaar8c8b8bb2019-01-13 17:48:04 +01006296 r = blob2string(tv->vval.v_blob, tofree, numbuf);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006297 break;
6298
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006299 case VAR_LIST:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006300 r = list_tv2string(tv, tofree, copyID, restore_copyID);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006301 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006302
Bram Moolenaar8c711452005-01-14 21:53:12 +00006303 case VAR_DICT:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006304 r = dict_tv2string(tv, tofree, copyID, restore_copyID);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006305 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006306
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006307 case VAR_NUMBER:
Bram Moolenaara03f2332016-02-06 18:09:59 +01006308 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02006309 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006310 case VAR_VOID:
Bram Moolenaar35422f42017-08-05 16:33:56 +02006311 *tofree = NULL;
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006312 r = tv_get_string_buf(tv, numbuf);
Bram Moolenaar35422f42017-08-05 16:33:56 +02006313 break;
6314
Bram Moolenaar835dc632016-02-07 14:27:38 +01006315 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01006316 case VAR_CHANNEL:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006317 r = jobchan_tv2string(tv, tofree, numbuf, composite_val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006318 break;
Bram Moolenaarb71eaae2006-01-20 23:10:18 +00006319
Bram Moolenaarf18332f2021-05-07 17:55:55 +02006320 case VAR_INSTR:
6321 *tofree = NULL;
6322 r = (char_u *)"instructions";
6323 break;
6324
Bram Moolenaar00b28d62022-12-08 15:32:33 +00006325 case VAR_CLASS:
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006326 r = class_tv2string(tv, tofree);
Bram Moolenaar00b28d62022-12-08 15:32:33 +00006327 break;
6328
6329 case VAR_OBJECT:
Ernie Rael05ff4e42024-07-04 16:50:11 +02006330 r = object_tv2string(tv, tofree, copyID, restore_copyID,
6331 numbuf, echo_style, composite_val);
Bram Moolenaar00b28d62022-12-08 15:32:33 +00006332 break;
6333
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006334 case VAR_FLOAT:
6335 *tofree = NULL;
6336 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
6337 r = numbuf;
6338 break;
Bram Moolenaar8c8de832008-06-24 22:58:06 +00006339
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01006340 case VAR_BOOL:
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006341 case VAR_SPECIAL:
6342 *tofree = NULL;
Bram Moolenaar17a13432016-01-24 14:22:10 +01006343 r = (char_u *)get_var_special_name(tv->vval.v_number);
Bram Moolenaar520e1e42016-01-23 19:46:28 +01006344 break;
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02006345
6346 case VAR_TYPEALIAS:
6347 *tofree = vim_strsave(tv->vval.v_typealias->ta_name);
6348 r = *tofree;
6349 if (r == NULL)
6350 r = (char_u *)"";
6351 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006352 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006353
Bram Moolenaar8502c702014-06-17 12:51:16 +02006354 if (--recurse == 0)
6355 did_echo_string_emsg = FALSE;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006356 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006357}
6358
6359/*
6360 * Return a string with the string representation of a variable.
6361 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6362 * "numbuf" is used for a number.
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006363 * Does not put quotes around strings, as ":echo" displays values.
Yegappan Lakshmanan22029ed2024-05-20 13:57:11 +02006364 * When "copyID" is not zero replace recursive lists and dicts with "...".
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006365 * May return NULL.
6366 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006367 char_u *
Bram Moolenaar18dfb442016-05-31 22:31:23 +02006368echo_string(
6369 typval_T *tv,
6370 char_u **tofree,
6371 char_u *numbuf,
6372 int copyID)
6373{
6374 return echo_string_core(tv, tofree, numbuf, copyID, TRUE, FALSE, FALSE);
6375}
6376
6377/*
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006378 * Convert the specified byte index of line 'lnum' in buffer 'buf' to a
6379 * character index. Works only for loaded buffers. Returns -1 on failure.
Bram Moolenaar91458462021-01-13 20:08:38 +01006380 * The index of the first byte and the first character is zero.
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006381 */
6382 int
6383buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
6384{
6385 char_u *str;
Bram Moolenaar91458462021-01-13 20:08:38 +01006386 char_u *t;
6387 int count;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006388
6389 if (buf == NULL || buf->b_ml.ml_mfp == NULL)
6390 return -1;
6391
6392 if (lnum > buf->b_ml.ml_line_count)
6393 lnum = buf->b_ml.ml_line_count;
6394
6395 str = ml_get_buf(buf, lnum, FALSE);
6396 if (str == NULL)
6397 return -1;
6398
6399 if (*str == NUL)
Bram Moolenaar91458462021-01-13 20:08:38 +01006400 return 0;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006401
Bram Moolenaar91458462021-01-13 20:08:38 +01006402 // count the number of characters
6403 t = str;
6404 for (count = 0; *t != NUL && t <= str + byteidx; count++)
6405 t += mb_ptr2len(t);
6406
6407 // In insert mode, when the cursor is at the end of a non-empty line,
6408 // byteidx points to the NUL character immediately past the end of the
6409 // string. In this case, add one to the character count.
6410 if (*t == NUL && byteidx != 0 && t == str + byteidx)
6411 count++;
6412
6413 return count - 1;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006414}
6415
6416/*
6417 * Convert the specified character index of line 'lnum' in buffer 'buf' to a
Bram Moolenaar91458462021-01-13 20:08:38 +01006418 * byte index. Works only for loaded buffers. Returns -1 on failure.
6419 * The index of the first byte and the first character is zero.
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006420 */
6421 int
6422buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
6423{
6424 char_u *str;
6425 char_u *t;
6426
6427 if (buf == NULL || buf->b_ml.ml_mfp == NULL)
6428 return -1;
6429
6430 if (lnum > buf->b_ml.ml_line_count)
6431 lnum = buf->b_ml.ml_line_count;
6432
6433 str = ml_get_buf(buf, lnum, FALSE);
6434 if (str == NULL)
6435 return -1;
6436
6437 // Convert the character offset to a byte offset
6438 t = str;
6439 while (*t != NUL && --charidx > 0)
6440 t += mb_ptr2len(t);
6441
Bram Moolenaar91458462021-01-13 20:08:38 +01006442 return t - str;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006443}
6444
6445/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006446 * Translate a String variable into a position.
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006447 * Returns NULL when there is an error.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006448 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006449 pos_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006450var2fpos(
6451 typval_T *varp,
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006452 int dollar_lnum, // TRUE when $ is last line
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006453 int *fnum, // set to fnum for '0, 'A, etc.
6454 int charcol) // return character column
Bram Moolenaar071d4272004-06-13 20:20:40 +00006455{
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006456 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006457 static pos_T pos;
Bram Moolenaar261bfea2006-03-01 22:12:31 +00006458 pos_T *pp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006459
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006460 // Argument can be [lnum, col, coladd].
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006461 if (varp->v_type == VAR_LIST)
6462 {
6463 list_T *l;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006464 int len;
Bram Moolenaara5525202006-03-02 22:52:09 +00006465 int error = FALSE;
Bram Moolenaar477933c2007-07-17 14:32:23 +00006466 listitem_T *li;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006467
6468 l = varp->vval.v_list;
6469 if (l == NULL)
6470 return NULL;
6471
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006472 // Get the line number
Bram Moolenaara5525202006-03-02 22:52:09 +00006473 pos.lnum = list_find_nr(l, 0L, &error);
6474 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006475 return NULL; // invalid line number
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006476 if (charcol)
6477 len = (long)mb_charlen(ml_get(pos.lnum));
6478 else
John Marriottbfcc8952024-03-11 22:04:45 +01006479 len = (long)ml_get_len(pos.lnum);
Bram Moolenaar477933c2007-07-17 14:32:23 +00006480
Bram Moolenaarec65d772020-08-20 22:29:12 +02006481 // Get the column number
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006482 // We accept "$" for the column number: last column.
Bram Moolenaar477933c2007-07-17 14:32:23 +00006483 li = list_find(l, 1L);
6484 if (li != NULL && li->li_tv.v_type == VAR_STRING
6485 && li->li_tv.vval.v_string != NULL
6486 && STRCMP(li->li_tv.vval.v_string, "$") == 0)
Bram Moolenaarec65d772020-08-20 22:29:12 +02006487 {
Bram Moolenaar477933c2007-07-17 14:32:23 +00006488 pos.col = len + 1;
Bram Moolenaarec65d772020-08-20 22:29:12 +02006489 }
6490 else
6491 {
6492 pos.col = list_find_nr(l, 1L, &error);
6493 if (error)
6494 return NULL;
6495 }
Bram Moolenaar477933c2007-07-17 14:32:23 +00006496
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006497 // Accept a position up to the NUL after the line.
Bram Moolenaar4c3f5362006-04-11 21:38:50 +00006498 if (pos.col == 0 || (int)pos.col > len + 1)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006499 return NULL; // invalid column number
Bram Moolenaara5525202006-03-02 22:52:09 +00006500 --pos.col;
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006501
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006502 // Get the virtual offset. Defaults to zero.
Bram Moolenaara5525202006-03-02 22:52:09 +00006503 pos.coladd = list_find_nr(l, 2L, &error);
6504 if (error)
6505 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006506
Bram Moolenaar32466aa2006-02-24 23:53:04 +00006507 return &pos;
6508 }
6509
Bram Moolenaarc5809432021-03-27 21:23:30 +01006510 if (in_vim9script() && check_for_string_arg(varp, 0) == FAIL)
6511 return NULL;
6512
Bram Moolenaard155d7a2018-12-21 16:04:21 +01006513 name = tv_get_string_chk(varp);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006514 if (name == NULL)
6515 return NULL;
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006516
6517 pos.lnum = 0;
Bram Moolenaar8dac2ac2021-12-27 20:57:06 +00006518 if (name[0] == '.' && (!in_vim9script() || name[1] == NUL))
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006519 {
Bram Moolenaar8dac2ac2021-12-27 20:57:06 +00006520 // cursor
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006521 pos = curwin->w_cursor;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006522 }
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006523 else if (name[0] == 'v' && name[1] == NUL)
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006524 {
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006525 // Visual start
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006526 if (VIsual_active)
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006527 pos = VIsual;
6528 else
6529 pos = curwin->w_cursor;
Bram Moolenaar9ecd0232008-06-20 15:31:51 +00006530 }
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006531 else if (name[0] == '\'' && (!in_vim9script()
Bram Moolenaar8dac2ac2021-12-27 20:57:06 +00006532 || (name[1] != NUL && name[2] == NUL)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006533 {
Bram Moolenaar8dac2ac2021-12-27 20:57:06 +00006534 // mark
Bram Moolenaar9d182dd2013-01-23 15:53:15 +01006535 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006536 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
6537 return NULL;
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006538 pos = *pp;
6539 }
6540 if (pos.lnum != 0)
6541 {
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006542 if (charcol)
Bram Moolenaar3caf1cc2022-04-11 13:05:16 +01006543 pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col);
6544 return &pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006545 }
Bram Moolenaara5525202006-03-02 22:52:09 +00006546
Bram Moolenaara5525202006-03-02 22:52:09 +00006547 pos.coladd = 0;
Bram Moolenaara5525202006-03-02 22:52:09 +00006548
Bram Moolenaar477933c2007-07-17 14:32:23 +00006549 if (name[0] == 'w' && dollar_lnum)
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006550 {
Bram Moolenaar85090142023-06-01 19:27:08 +01006551 // the "w_valid" flags are not reset when moving the cursor, but they
6552 // do matter for update_topline() and validate_botline().
6553 check_cursor_moved(curwin);
6554
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006555 pos.col = 0;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006556 if (name[1] == '0') // "w0": first visible line
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006557 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006558 update_topline();
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006559 // In silent Ex mode topline is zero, but that's not a valid line
6560 // number; use one instead.
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006561 pos.lnum = curwin->w_topline > 0 ? curwin->w_topline : 1;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006562 return &pos;
6563 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006564 else if (name[1] == '$') // "w$": last visible line
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006565 {
Bram Moolenaarf740b292006-02-16 22:11:02 +00006566 validate_botline();
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006567 // In silent Ex mode botline is zero, return zero then.
Bram Moolenaara1d5fa62017-04-03 22:02:55 +02006568 pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
Bram Moolenaarf52c7252006-02-10 23:23:57 +00006569 return &pos;
6570 }
6571 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006572 else if (name[0] == '$') // last column or line
Bram Moolenaar071d4272004-06-13 20:20:40 +00006573 {
Bram Moolenaar477933c2007-07-17 14:32:23 +00006574 if (dollar_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006575 {
6576 pos.lnum = curbuf->b_ml.ml_line_count;
6577 pos.col = 0;
6578 }
6579 else
6580 {
6581 pos.lnum = curwin->w_cursor.lnum;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006582 if (charcol)
6583 pos.col = (colnr_T)mb_charlen(ml_get_curline());
6584 else
John Marriottbfcc8952024-03-11 22:04:45 +01006585 pos.col = ml_get_curline_len();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006586 }
6587 return &pos;
6588 }
Bram Moolenaar0f1227f2021-07-11 16:01:58 +02006589 if (in_vim9script())
6590 semsg(_(e_invalid_value_for_line_number_str), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006591 return NULL;
6592}
6593
6594/*
Bram Moolenaarcdef1ce2022-10-20 14:17:18 +01006595 * Convert list in "arg" into position "posp" and optional file number "fnump".
Bram Moolenaar79f23442022-10-10 12:42:57 +01006596 * When "fnump" is NULL there is no file number, only 3 items: [lnum, col, off]
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006597 * Note that the column is passed on as-is, the caller may want to decrement
6598 * it to use 1 for the first column.
Bram Moolenaar79f23442022-10-10 12:42:57 +01006599 * If "charcol" is TRUE use the column as the character index instead of the
6600 * byte index.
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006601 * Return FAIL when conversion is not possible, doesn't check the position for
6602 * validity.
6603 */
Bram Moolenaar73dad1e2016-07-17 22:13:49 +02006604 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006605list2fpos(
6606 typval_T *arg,
6607 pos_T *posp,
6608 int *fnump,
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006609 colnr_T *curswantp,
6610 int charcol)
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006611{
6612 list_T *l = arg->vval.v_list;
6613 long i = 0;
6614 long n;
6615
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006616 // List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
6617 // there when "fnump" isn't NULL; "coladd" and "curswant" are optional.
Bram Moolenaarbde35262006-07-23 20:12:24 +00006618 if (arg->v_type != VAR_LIST
6619 || l == NULL
6620 || l->lv_len < (fnump == NULL ? 2 : 3)
Bram Moolenaar493c1782014-05-28 14:34:46 +02006621 || l->lv_len > (fnump == NULL ? 4 : 5))
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006622 return FAIL;
6623
6624 if (fnump != NULL)
6625 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006626 n = list_find_nr(l, i++, NULL); // fnum
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006627 if (n < 0)
6628 return FAIL;
6629 if (n == 0)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006630 n = curbuf->b_fnum; // current buffer
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006631 *fnump = n;
6632 }
6633
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006634 n = list_find_nr(l, i++, NULL); // lnum
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006635 if (n < 0)
6636 return FAIL;
6637 posp->lnum = n;
6638
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006639 n = list_find_nr(l, i++, NULL); // col
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006640 if (n < 0)
6641 return FAIL;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006642 // If character position is specified, then convert to byte position
Bram Moolenaar79f23442022-10-10 12:42:57 +01006643 // If the line number is zero use the cursor line.
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006644 if (charcol)
6645 {
6646 buf_T *buf;
6647
6648 // Get the text for the specified line in a loaded buffer
6649 buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump);
6650 if (buf == NULL || buf->b_ml.ml_mfp == NULL)
6651 return FAIL;
6652
Bram Moolenaar79f23442022-10-10 12:42:57 +01006653 n = buf_charidx_to_byteidx(buf,
6654 posp->lnum == 0 ? curwin->w_cursor.lnum : posp->lnum, n) + 1;
Bram Moolenaar6f02b002021-01-10 20:22:54 +01006655 }
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006656 posp->col = n;
6657
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006658 n = list_find_nr(l, i, NULL); // off
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006659 if (n < 0)
Bram Moolenaarbde35262006-07-23 20:12:24 +00006660 posp->coladd = 0;
6661 else
6662 posp->coladd = n;
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006663
Bram Moolenaar493c1782014-05-28 14:34:46 +02006664 if (curswantp != NULL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006665 *curswantp = list_find_nr(l, i + 1, NULL); // curswant
Bram Moolenaar493c1782014-05-28 14:34:46 +02006666
Bram Moolenaar0e34f622006-03-03 23:00:03 +00006667 return OK;
6668}
6669
6670/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006671 * Get the length of an environment variable name.
6672 * Advance "arg" to the first character after the name.
6673 * Return 0 for error.
6674 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +02006675 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006676get_env_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006677{
6678 char_u *p;
6679 int len;
6680
6681 for (p = *arg; vim_isIDc(*p); ++p)
6682 ;
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006683 if (p == *arg) // no name found
Bram Moolenaar071d4272004-06-13 20:20:40 +00006684 return 0;
6685
6686 len = (int)(p - *arg);
6687 *arg = p;
6688 return len;
6689}
6690
6691/*
6692 * Get the length of the name of a function or internal variable.
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02006693 * "arg" is advanced to after the name.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006694 * Return 0 if something is wrong.
6695 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006696 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006697get_id_len(char_u **arg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006698{
6699 char_u *p;
6700 int len;
6701
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006702 // Find the end of the name.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006703 for (p = *arg; eval_isnamec(*p); ++p)
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006704 {
6705 if (*p == ':')
6706 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006707 // "s:" is start of "s:var", but "n:" is not and can be used in
6708 // slice "[n:]". Also "xx:" is not a namespace.
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006709 len = (int)(p - *arg);
6710 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL)
6711 || len > 1)
6712 break;
6713 }
6714 }
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006715 if (p == *arg) // no name found
Bram Moolenaar071d4272004-06-13 20:20:40 +00006716 return 0;
6717
6718 len = (int)(p - *arg);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02006719 *arg = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006720
6721 return len;
6722}
6723
6724/*
Bram Moolenaara7043832005-01-21 11:56:39 +00006725 * Get the length of the name of a variable or function.
6726 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +00006727 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006728 * Return -1 if curly braces expansion failed.
6729 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006730 * If the name contains 'magic' {}'s, expand them and return the
6731 * expanded name in an allocated string via 'alias' - caller must free.
6732 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +02006733 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006734get_name_len(
6735 char_u **arg,
6736 char_u **alias,
6737 int evaluate,
6738 int verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006739{
6740 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006741 char_u *p;
6742 char_u *expr_start;
6743 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006744
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006745 *alias = NULL; // default to no alias
Bram Moolenaar071d4272004-06-13 20:20:40 +00006746
6747 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
6748 && (*arg)[2] == (int)KE_SNR)
6749 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006750 // hard coded <SNR>, already translated
Bram Moolenaar071d4272004-06-13 20:20:40 +00006751 *arg += 3;
6752 return get_id_len(arg) + 3;
6753 }
6754 len = eval_fname_script(*arg);
6755 if (len > 0)
6756 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006757 // literal "<SID>", "s:" or "<SNR>"
Bram Moolenaar071d4272004-06-13 20:20:40 +00006758 *arg += len;
6759 }
6760
Bram Moolenaar071d4272004-06-13 20:20:40 +00006761 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006762 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006763 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006764 p = find_name_end(*arg, &expr_start, &expr_end,
6765 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006766 if (expr_start != NULL)
6767 {
6768 char_u *temp_string;
6769
6770 if (!evaluate)
6771 {
6772 len += (int)(p - *arg);
6773 *arg = skipwhite(p);
6774 return len;
6775 }
6776
6777 /*
6778 * Include any <SID> etc in the expanded string:
6779 * Thus the -len here.
6780 */
6781 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
6782 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006783 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006784 *alias = temp_string;
6785 *arg = skipwhite(p);
6786 return (int)STRLEN(temp_string);
6787 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788
6789 len += get_id_len(arg);
Bram Moolenaar8309b052019-01-13 16:46:22 +01006790 // Only give an error when there is something, otherwise it will be
6791 // reported at a higher level.
6792 if (len == 0 && verbose && **arg != NUL)
Bram Moolenaar108010a2021-06-27 22:03:33 +02006793 semsg(_(e_invalid_expression_str), *arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006794
6795 return len;
6796}
6797
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006798/*
6799 * Find the end of a variable or function name, taking care of magic braces.
6800 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
6801 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006802 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006803 * Return a pointer to just after the name. Equal to "arg" if there is no
6804 * valid name.
6805 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006806 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006807find_name_end(
6808 char_u *arg,
6809 char_u **expr_start,
6810 char_u **expr_end,
6811 int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006812{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006813 int mb_nest = 0;
6814 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006815 char_u *p;
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006816 int len;
zeertzjq9a91d2b2024-04-09 21:47:10 +02006817 int allow_curly = !in_vim9script();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006818
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006819 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006820 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006821 *expr_start = NULL;
6822 *expr_end = NULL;
6823 }
6824
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006825 // Quick check for valid starting character.
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006826 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg)
zeertzjqa93d9cd2023-05-02 16:25:47 +01006827 && (*arg != '{' || !allow_curly))
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006828 return arg;
6829
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006830 for (p = arg; *p != NUL
6831 && (eval_isnamec(*p)
zeertzjqa93d9cd2023-05-02 16:25:47 +01006832 || (*p == '{' && allow_curly)
Bram Moolenaar63be3d42020-07-23 13:11:37 +02006833 || ((flags & FNE_INCL_BR) && (*p == '['
Bram Moolenaarb13ab992020-07-27 21:43:28 +02006834 || (*p == '.' && eval_isdictc(p[1]))))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006835 || mb_nest != 0
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006836 || br_nest != 0); MB_PTR_ADV(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006837 {
Bram Moolenaar8af24422005-08-08 22:06:28 +00006838 if (*p == '\'')
6839 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006840 // skip over 'string' to avoid counting [ and ] inside it.
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006841 for (p = p + 1; *p != NUL && *p != '\''; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00006842 ;
6843 if (*p == NUL)
6844 break;
6845 }
6846 else if (*p == '"')
6847 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006848 // skip over "str\"ing" to avoid counting [ and ] inside it.
Bram Moolenaar91acfff2017-03-12 19:22:36 +01006849 for (p = p + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p))
Bram Moolenaar8af24422005-08-08 22:06:28 +00006850 if (*p == '\\' && p[1] != NUL)
6851 ++p;
6852 if (*p == NUL)
6853 break;
6854 }
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006855 else if (br_nest == 0 && mb_nest == 0 && *p == ':')
6856 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006857 // "s:" is start of "s:var", but "n:" is not and can be used in
6858 // slice "[n:]". Also "xx:" is not a namespace. But {ns}: is.
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006859 len = (int)(p - arg);
6860 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL)
Bram Moolenaar4119cf82016-01-17 14:59:01 +01006861 || (len > 1 && p[-1] != '}'))
Bram Moolenaar9bbf63d2016-01-16 16:49:28 +01006862 break;
6863 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006864
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006865 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006866 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006867 if (*p == '[')
6868 ++br_nest;
6869 else if (*p == ']')
6870 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006871 }
Bram Moolenaar8af24422005-08-08 22:06:28 +00006872
zeertzjqa93d9cd2023-05-02 16:25:47 +01006873 if (br_nest == 0 && allow_curly)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006874 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006875 if (*p == '{')
6876 {
6877 mb_nest++;
6878 if (expr_start != NULL && *expr_start == NULL)
6879 *expr_start = p;
6880 }
6881 else if (*p == '}')
6882 {
6883 mb_nest--;
6884 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
6885 *expr_end = p;
6886 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006887 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006888 }
6889
6890 return p;
6891}
6892
6893/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006894 * Expands out the 'magic' {}'s in a variable/function name.
6895 * Note that this can call itself recursively, to deal with
6896 * constructs like foo{bar}{baz}{bam}
6897 * The four pointer arguments point to "foo{expre}ss{ion}bar"
6898 * "in_start" ^
6899 * "expr_start" ^
6900 * "expr_end" ^
6901 * "in_end" ^
6902 *
6903 * Returns a new allocated string, which the caller must free.
6904 * Returns NULL for failure.
6905 */
6906 static char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01006907make_expanded_name(
6908 char_u *in_start,
6909 char_u *expr_start,
6910 char_u *expr_end,
6911 char_u *in_end)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006912{
6913 char_u c1;
6914 char_u *retval = NULL;
6915 char_u *temp_result;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006916
6917 if (expr_end == NULL || in_end == NULL)
6918 return NULL;
6919 *expr_start = NUL;
6920 *expr_end = NUL;
6921 c1 = *in_end;
6922 *in_end = NUL;
6923
Bram Moolenaara4e0b972022-10-01 19:43:52 +01006924 temp_result = eval_to_string(expr_start + 1, FALSE, FALSE);
Bram Moolenaarb171fb12020-06-24 20:34:03 +02006925 if (temp_result != NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006926 {
John Marriottbd4614f2024-11-18 20:25:21 +01006927 size_t retvalsize = (size_t)(expr_start - in_start)
6928 + STRLEN(temp_result)
6929 + (size_t)(in_end - expr_end) + 1;
6930
6931 retval = alloc(retvalsize);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006932 if (retval != NULL)
John Marriottbd4614f2024-11-18 20:25:21 +01006933 vim_snprintf((char *)retval, retvalsize, "%s%s%s",
6934 in_start, temp_result, expr_end + 1);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006935 }
6936 vim_free(temp_result);
6937
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006938 *in_end = c1; // put char back for error messages
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006939 *expr_start = '{';
6940 *expr_end = '}';
6941
6942 if (retval != NULL)
6943 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006944 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006945 if (expr_start != NULL)
6946 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01006947 // Further expansion!
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006948 temp_result = make_expanded_name(retval, expr_start,
6949 expr_end, temp_result);
6950 vim_free(retval);
6951 retval = temp_result;
6952 }
6953 }
6954
6955 return retval;
6956}
6957
6958/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006959 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +00006960 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006961 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006962 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006963eval_isnamec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006964{
Bram Moolenaarb13ab992020-07-27 21:43:28 +02006965 return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006966}
6967
6968/*
6969 * Return TRUE if character "c" can be used as the first character in a
6970 * variable or function name (excluding '{' and '}').
6971 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006972 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006973eval_isnamec1(int c)
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00006974{
Bram Moolenaarb13ab992020-07-27 21:43:28 +02006975 return ASCII_ISALPHA(c) || c == '_';
6976}
6977
6978/*
6979 * Return TRUE if character "c" can be used as the first character of a
6980 * dictionary key.
6981 */
6982 int
6983eval_isdictc(int c)
6984{
6985 return ASCII_ISALNUM(c) || c == '_';
Bram Moolenaar071d4272004-06-13 20:20:40 +00006986}
6987
6988/*
Bram Moolenaarac92e252019-08-03 21:58:38 +02006989 * Handle:
6990 * - expr[expr], expr[expr:expr] subscript
6991 * - ".name" lookup
6992 * - function call with Funcref variable: func(expr)
6993 * - method call: var->method()
6994 *
6995 * Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len()
Bram Moolenaar32884ad2022-01-07 12:45:29 +00006996 * "name_start" points to a variable before the subscript or is NULL.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006997 */
Bram Moolenaara9b579f2016-07-17 18:29:19 +02006998 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01006999handle_subscript(
7000 char_u **arg,
Bram Moolenaar32884ad2022-01-07 12:45:29 +00007001 char_u *name_start,
Bram Moolenaar7454a062016-01-30 15:14:10 +01007002 typval_T *rettv,
Bram Moolenaare40fbc22020-06-27 18:06:45 +02007003 evalarg_T *evalarg,
Bram Moolenaar0b1cd522020-06-27 13:11:50 +02007004 int verbose) // give error messages
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007005{
Bram Moolenaare40fbc22020-06-27 18:06:45 +02007006 int evaluate = evalarg != NULL
7007 && (evalarg->eval_flags & EVAL_EVALUATE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007008 int ret = OK;
7009 dict_T *selfdict = NULL;
Bram Moolenaar442af2f2020-07-03 21:09:52 +02007010 int check_white = TRUE;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007011 int getnext;
7012 char_u *p;
Bram Moolenaar442af2f2020-07-03 21:09:52 +02007013
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007014 while (ret == OK)
Bram Moolenaar442af2f2020-07-03 21:09:52 +02007015 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007016 // When at the end of the line and ".name" or "->{" or "->X" follows in
7017 // the next line then consume the line break.
7018 p = eval_next_non_blank(*arg, evalarg, &getnext);
7019 if (getnext
Bram Moolenaarb149d222023-01-24 13:03:37 +00007020 && ((*p == '.'
7021 && ((rettv->v_type == VAR_DICT && eval_isdictc(p[1]))
7022 || rettv->v_type == VAR_CLASS
7023 || rettv->v_type == VAR_OBJECT))
Bram Moolenaara7330422021-06-08 20:46:45 +02007024 || (p[0] == '-' && p[1] == '>' && (p[2] == '{'
7025 || ASCII_ISALPHA(in_vim9script() ? *skipwhite(p + 2)
7026 : p[2])))))
Bram Moolenaar442af2f2020-07-03 21:09:52 +02007027 {
Bram Moolenaare442d592022-05-05 12:20:28 +01007028 *arg = eval_next_line(*arg, evalarg);
Bram Moolenaaraeb2bdd2020-08-18 22:32:03 +02007029 p = *arg;
Bram Moolenaar442af2f2020-07-03 21:09:52 +02007030 check_white = FALSE;
7031 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007032
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007033 if (rettv->v_type == VAR_ANY)
7034 {
7035 char_u *exp_name;
7036 int cc;
7037 int idx;
LemonBoyaf59e342022-04-24 21:55:00 +01007038 ufunc_T *ufunc;
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007039 type_T *type;
7040
Bram Moolenaard5f400c2022-01-06 21:10:28 +00007041 // Found script from "import {name} as name", script item name must
Bram Moolenaar5d982692022-01-12 15:15:27 +00007042 // follow. "rettv->vval.v_number" has the script ID.
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007043 if (**arg != '.')
7044 {
7045 if (verbose)
Bram Moolenaar32884ad2022-01-07 12:45:29 +00007046 semsg(_(e_expected_dot_after_name_str),
7047 name_start != NULL ? name_start: *arg);
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007048 ret = FAIL;
7049 break;
7050 }
7051 ++*arg;
7052 if (IS_WHITE_OR_NUL(**arg))
7053 {
7054 if (verbose)
7055 emsg(_(e_no_white_space_allowed_after_dot));
7056 ret = FAIL;
7057 break;
7058 }
7059
7060 // isolate the name
7061 exp_name = *arg;
7062 while (eval_isnamec(**arg))
7063 ++*arg;
7064 cc = **arg;
7065 **arg = NUL;
7066
7067 idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type,
Bram Moolenaar7f9a5a62022-09-23 16:37:18 +01007068 evalarg == NULL ? NULL : evalarg->eval_cctx,
7069 evalarg == NULL ? NULL : evalarg->eval_cstack, verbose);
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007070 **arg = cc;
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007071
7072 if (idx < 0 && ufunc == NULL)
7073 {
7074 ret = FAIL;
7075 break;
7076 }
7077 if (idx >= 0)
7078 {
7079 scriptitem_T *si = SCRIPT_ITEM(rettv->vval.v_number);
7080 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
7081
7082 copy_tv(sv->sv_tv, rettv);
7083 }
7084 else
7085 {
7086 rettv->v_type = VAR_FUNC;
7087 rettv->vval.v_string = vim_strsave(ufunc->uf_name);
7088 }
Bram Moolenaard5f400c2022-01-06 21:10:28 +00007089 continue;
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01007090 }
7091
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007092 if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
7093 || rettv->v_type == VAR_PARTIAL))
7094 && (!check_white || !VIM_ISWHITE(*(*arg - 1))))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007095 {
Bram Moolenaare6b53242020-07-01 17:28:33 +02007096 ret = call_func_rettv(arg, evalarg, rettv, evaluate,
7097 selfdict, NULL);
Bram Moolenaar3f242a82016-03-18 19:39:25 +01007098
Bram Moolenaar22a0c0c2019-08-09 23:25:08 +02007099 // Stop the expression evaluation when immediately aborting on
7100 // error, or when an interrupt occurred or an exception was thrown
7101 // but not caught.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007102 if (aborting())
7103 {
7104 if (ret == OK)
7105 clear_tv(rettv);
7106 ret = FAIL;
7107 }
7108 dict_unref(selfdict);
7109 selfdict = NULL;
7110 }
Bram Moolenaar9d489562020-07-30 20:08:50 +02007111 else if (p[0] == '-' && p[1] == '>')
Bram Moolenaarac92e252019-08-03 21:58:38 +02007112 {
Bram Moolenaar0820f4d2021-05-15 20:06:58 +02007113 if (in_vim9script())
7114 *arg = skipwhite(p + 2);
7115 else
7116 *arg = p + 2;
zeertzjqc481ad32023-03-11 16:18:51 +00007117 if (VIM_ISWHITE(**arg))
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02007118 {
zeertzjqc481ad32023-03-11 16:18:51 +00007119 emsg(_(e_no_white_space_allowed_before_parenthesis));
7120 ret = FAIL;
Bram Moolenaar9cfe8f62019-08-17 21:04:16 +02007121 }
zeertzjqc481ad32023-03-11 16:18:51 +00007122 else if ((**arg == '{' && !in_vim9script()) || **arg == '(')
7123 // expr->{lambda}() or expr->(lambda)()
7124 ret = eval_lambda(arg, rettv, evalarg, verbose);
7125 else
7126 // expr->name()
7127 ret = eval_method(arg, rettv, evalarg, verbose);
Bram Moolenaarac92e252019-08-03 21:58:38 +02007128 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007129 // "." is ".name" lookup when we found a dict or when evaluating and
7130 // scriptversion is at least 2, where string concatenation is "..".
7131 else if (**arg == '['
7132 || (**arg == '.' && (rettv->v_type == VAR_DICT
7133 || (!evaluate
7134 && (*arg)[1] != '.'
Bram Moolenaardd9de502021-08-15 13:49:42 +02007135 && !in_old_script(2)))))
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007136 {
7137 dict_unref(selfdict);
7138 if (rettv->v_type == VAR_DICT)
7139 {
7140 selfdict = rettv->vval.v_dict;
7141 if (selfdict != NULL)
7142 ++selfdict->dv_refcount;
7143 }
7144 else
7145 selfdict = NULL;
Bram Moolenaare40fbc22020-06-27 18:06:45 +02007146 if (eval_index(arg, rettv, evalarg, verbose) == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007147 {
7148 clear_tv(rettv);
7149 ret = FAIL;
7150 }
7151 }
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007152 else if (**arg == '.' && (rettv->v_type == VAR_CLASS
7153 || rettv->v_type == VAR_OBJECT))
7154 {
7155 // class member: SomeClass.varname
7156 // class method: SomeClass.SomeMethod()
7157 // class constructor: SomeClass.new()
7158 // object member: someObject.varname
7159 // object method: someObject.SomeMethod()
7160 if (class_object_index(arg, rettv, evalarg, verbose) == FAIL)
7161 {
7162 clear_tv(rettv);
7163 ret = FAIL;
7164 }
7165 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02007166 else
7167 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007168 }
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007169
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007170 // Turn "dict.Func" into a partial for "Func" bound to "dict".
7171 // Don't do this when "Func" is already a partial that was bound
7172 // explicitly (pt_auto is FALSE).
Bram Moolenaar1d429612016-05-24 15:44:17 +02007173 if (selfdict != NULL
7174 && (rettv->v_type == VAR_FUNC
7175 || (rettv->v_type == VAR_PARTIAL
7176 && (rettv->vval.v_partial->pt_auto
7177 || rettv->vval.v_partial->pt_dict == NULL))))
Bram Moolenaara9b579f2016-07-17 18:29:19 +02007178 selfdict = make_partial(selfdict, rettv);
Bram Moolenaarab1fa392016-03-15 19:33:34 +01007179
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007180 dict_unref(selfdict);
7181 return ret;
7182}
7183
7184/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00007185 * Make a copy of an item.
7186 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar381692b2022-02-02 20:01:27 +00007187 * "top" is TRUE for the toplevel of copy().
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007188 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
7189 * reference to an already copied list/dict can be used.
7190 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +00007191 */
Bram Moolenaarcd524592016-07-17 14:57:05 +02007192 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01007193item_copy(
7194 typval_T *from,
7195 typval_T *to,
7196 int deep,
Bram Moolenaar381692b2022-02-02 20:01:27 +00007197 int top,
Bram Moolenaar7454a062016-01-30 15:14:10 +01007198 int copyID)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007199{
7200 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007201 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007202
Bram Moolenaar33570922005-01-25 22:26:29 +00007203 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007204 {
Bram Moolenaara6f79292022-01-04 21:30:47 +00007205 emsg(_(e_variable_nested_too_deep_for_making_copy));
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007206 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007207 }
7208 ++recurse;
7209
7210 switch (from->v_type)
7211 {
7212 case VAR_NUMBER:
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007213 case VAR_FLOAT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007214 case VAR_STRING:
7215 case VAR_FUNC:
Bram Moolenaar1735bc92016-03-14 23:05:14 +01007216 case VAR_PARTIAL:
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01007217 case VAR_BOOL:
Bram Moolenaar15550002016-01-31 18:45:24 +01007218 case VAR_SPECIAL:
Bram Moolenaar835dc632016-02-07 14:27:38 +01007219 case VAR_JOB:
Bram Moolenaar77073442016-02-13 23:23:53 +01007220 case VAR_CHANNEL:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02007221 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007222 case VAR_CLASS:
7223 case VAR_OBJECT:
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02007224 case VAR_TYPEALIAS:
Bram Moolenaare9a41262005-01-15 22:18:47 +00007225 copy_tv(from, to);
7226 break;
7227 case VAR_LIST:
7228 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007229 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007230 if (from->vval.v_list == NULL)
7231 to->vval.v_list = NULL;
7232 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
7233 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007234 // use the copy made earlier
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007235 to->vval.v_list = from->vval.v_list->lv_copylist;
7236 ++to->vval.v_list->lv_refcount;
7237 }
7238 else
Bram Moolenaar381692b2022-02-02 20:01:27 +00007239 to->vval.v_list = list_copy(from->vval.v_list,
7240 deep, top, copyID);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007241 if (to->vval.v_list == NULL)
7242 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007243 break;
Bram Moolenaar3d28b582019-01-15 22:44:17 +01007244 case VAR_BLOB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007245 ret = blob_copy(from->vval.v_blob, to);
Bram Moolenaar3d28b582019-01-15 22:44:17 +01007246 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007247 case VAR_DICT:
7248 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007249 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007250 if (from->vval.v_dict == NULL)
7251 to->vval.v_dict = NULL;
7252 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
7253 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007254 // use the copy made earlier
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007255 to->vval.v_dict = from->vval.v_dict->dv_copydict;
7256 ++to->vval.v_dict->dv_refcount;
7257 }
7258 else
Bram Moolenaar381692b2022-02-02 20:01:27 +00007259 to->vval.v_dict = dict_copy(from->vval.v_dict,
7260 deep, top, copyID);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007261 if (to->vval.v_dict == NULL)
7262 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007263 break;
Bram Moolenaara03f2332016-02-06 18:09:59 +01007264 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02007265 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007266 case VAR_VOID:
Bram Moolenaardd589232020-02-29 17:38:12 +01007267 internal_error_no_abort("item_copy(UNKNOWN)");
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007268 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007269 }
7270 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007271 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007272}
7273
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007274 void
7275echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr)
7276{
7277 char_u *tofree;
7278 char_u numbuf[NUMBUFLEN];
7279 char_u *p = echo_string(rettv, &tofree, numbuf, get_copyID());
7280
7281 if (*atstart)
7282 {
7283 *atstart = FALSE;
7284 // Call msg_start() after eval1(), evaluating the expression
7285 // may cause a message to appear.
7286 if (with_space)
7287 {
7288 // Mark the saved text as finishing the line, so that what
7289 // follows is displayed on a new line when scrolling back
7290 // at the more prompt.
7291 msg_sb_eol();
7292 msg_start();
7293 }
7294 }
7295 else if (with_space)
7296 msg_puts_attr(" ", echo_attr);
7297
7298 if (p != NULL)
7299 for ( ; *p != NUL && !got_int; ++p)
7300 {
7301 if (*p == '\n' || *p == '\r' || *p == TAB)
7302 {
7303 if (*p != TAB && *needclr)
7304 {
7305 // remove any text still there from the command
7306 msg_clr_eos();
7307 *needclr = FALSE;
7308 }
7309 msg_putchar_attr(*p, echo_attr);
7310 }
7311 else
7312 {
7313 if (has_mbyte)
7314 {
7315 int i = (*mb_ptr2len)(p);
7316
7317 (void)msg_outtrans_len_attr(p, i, echo_attr);
7318 p += i - 1;
7319 }
7320 else
7321 (void)msg_outtrans_len_attr(p, 1, echo_attr);
7322 }
7323 }
7324 vim_free(tofree);
7325}
7326
Bram Moolenaare9a41262005-01-15 22:18:47 +00007327/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007328 * ":echo expr1 ..." print each argument separated with a space, add a
7329 * newline at the end.
7330 * ":echon expr1 ..." print each argument plain.
7331 */
7332 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007333ex_echo(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007334{
7335 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00007336 typval_T rettv;
Bram Moolenaar68db9962021-05-09 23:19:22 +02007337 char_u *arg_start;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007338 int needclr = TRUE;
7339 int atstart = TRUE;
Bram Moolenaar76a63452018-11-28 20:38:37 +01007340 int did_emsg_before = did_emsg;
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01007341 int called_emsg_before = called_emsg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02007342 evalarg_T evalarg;
7343
Bram Moolenaare707c882020-07-01 13:07:37 +02007344 fill_evalarg_from_eap(&evalarg, eap, eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007345
7346 if (eap->skip)
7347 ++emsg_skip;
Bram Moolenaar7a092242020-04-16 22:10:49 +02007348 while ((!ends_excmd2(eap->cmd, arg) || *arg == '"') && !got_int)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007349 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007350 // If eval1() causes an error message the text from the command may
7351 // still need to be cleared. E.g., "echo 22,44".
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007352 need_clr_eos = needclr;
7353
Bram Moolenaar68db9962021-05-09 23:19:22 +02007354 arg_start = arg;
Bram Moolenaar5409f5d2020-06-24 18:37:35 +02007355 if (eval1(&arg, &rettv, &evalarg) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007356 {
7357 /*
7358 * Report the invalid expression unless the expression evaluation
7359 * has been cancelled due to an aborting error, an interrupt, or an
7360 * exception.
7361 */
Bram Moolenaarc0f5a782019-01-13 15:16:13 +01007362 if (!aborting() && did_emsg == did_emsg_before
7363 && called_emsg == called_emsg_before)
Bram Moolenaar108010a2021-06-27 22:03:33 +02007364 semsg(_(e_invalid_expression_str), arg_start);
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007365 need_clr_eos = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007366 break;
7367 }
Bram Moolenaar8c8de832008-06-24 22:58:06 +00007368 need_clr_eos = FALSE;
7369
Bram Moolenaar071d4272004-06-13 20:20:40 +00007370 if (!eap->skip)
Bram Moolenaar68db9962021-05-09 23:19:22 +02007371 {
7372 if (rettv.v_type == VAR_VOID)
7373 {
7374 semsg(_(e_expression_does_not_result_in_value_str), arg_start);
7375 break;
7376 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007377 echo_one(&rettv, eap->cmdidx == CMD_echo, &atstart, &needclr);
Bram Moolenaar68db9962021-05-09 23:19:22 +02007378 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007379
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007380 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007381 arg = skipwhite(arg);
7382 }
Bram Moolenaar63b91732021-08-05 20:40:03 +02007383 set_nextcmd(eap, arg);
Bram Moolenaarfaf86262020-06-27 23:07:36 +02007384 clear_evalarg(&evalarg, eap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007385
7386 if (eap->skip)
7387 --emsg_skip;
7388 else
7389 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007390 // remove text that may still be there from the command
Bram Moolenaar071d4272004-06-13 20:20:40 +00007391 if (needclr)
7392 msg_clr_eos();
7393 if (eap->cmdidx == CMD_echo)
7394 msg_end();
7395 }
7396}
7397
7398/*
7399 * ":echohl {name}".
7400 */
7401 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007402ex_echohl(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007403{
Bram Moolenaar1b9645d2017-09-17 23:03:31 +02007404 echo_attr = syn_name2attr(eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007405}
7406
7407/*
Bram Moolenaarda6c0332019-09-01 16:01:30 +02007408 * Returns the :echo attribute
7409 */
7410 int
7411get_echo_attr(void)
7412{
7413 return echo_attr;
7414}
7415
7416/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007417 * ":execute expr1 ..." execute the result of an expression.
7418 * ":echomsg expr1 ..." Print a message
Bram Moolenaar37fef162022-08-29 18:16:32 +01007419 * ":echowindow expr1 ..." Print a message in the messages window
Bram Moolenaar071d4272004-06-13 20:20:40 +00007420 * ":echoerr expr1 ..." Print an error
Bram Moolenaar4c868302021-03-22 16:19:45 +01007421 * ":echoconsole expr1 ..." Print a message on stdout
Bram Moolenaar071d4272004-06-13 20:20:40 +00007422 * Each gets spaces around each argument and a newline at the end for
7423 * echo commands
7424 */
7425 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01007426ex_execute(exarg_T *eap)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007427{
7428 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00007429 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007430 int ret = OK;
7431 char_u *p;
7432 garray_T ga;
7433 int len;
Bram Moolenaarc03fe662021-07-11 16:52:45 +02007434 long start_lnum = SOURCING_LNUM;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007435
7436 ga_init2(&ga, 1, 80);
7437
7438 if (eap->skip)
7439 ++emsg_skip;
Bram Moolenaar4a8d9f22020-04-16 22:54:32 +02007440 while (!ends_excmd2(eap->cmd, arg) || *arg == '"')
Bram Moolenaar071d4272004-06-13 20:20:40 +00007441 {
Bram Moolenaar47e880d2020-06-30 22:02:02 +02007442 ret = eval1_emsg(&arg, &rettv, eap);
Bram Moolenaarce9d50d2019-01-14 22:22:29 +01007443 if (ret == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007444 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007445
7446 if (!eap->skip)
7447 {
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01007448 char_u buf[NUMBUFLEN];
7449
7450 if (eap->cmdidx == CMD_execute)
Bram Moolenaarb6625912020-01-08 20:09:01 +01007451 {
7452 if (rettv.v_type == VAR_CHANNEL || rettv.v_type == VAR_JOB)
7453 {
Bram Moolenaar68db9962021-05-09 23:19:22 +02007454 semsg(_(e_using_invalid_value_as_string_str),
7455 vartype_name(rettv.v_type));
Bram Moolenaarb6625912020-01-08 20:09:01 +01007456 p = NULL;
7457 }
7458 else
7459 p = tv_get_string_buf(&rettv, buf);
7460 }
Bram Moolenaar461a7fc2018-12-22 13:28:07 +01007461 else
7462 p = tv_stringify(&rettv, buf);
Bram Moolenaar9db2afe2020-01-08 18:56:20 +01007463 if (p == NULL)
7464 {
7465 clear_tv(&rettv);
7466 ret = FAIL;
7467 break;
7468 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007469 len = (int)STRLEN(p);
7470 if (ga_grow(&ga, len + 2) == FAIL)
7471 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007472 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007473 ret = FAIL;
7474 break;
7475 }
7476 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007477 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007479 ga.ga_len += len;
7480 }
7481
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007482 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007483 arg = skipwhite(arg);
7484 }
7485
7486 if (ret != FAIL && ga.ga_data != NULL)
7487 {
Bram Moolenaarc03fe662021-07-11 16:52:45 +02007488 // use the first line of continuation lines for messages
7489 SOURCING_LNUM = start_lnum;
7490
Bram Moolenaar37fef162022-08-29 18:16:32 +01007491 if (eap->cmdidx == CMD_echomsg
7492 || eap->cmdidx == CMD_echowindow
7493 || eap->cmdidx == CMD_echoerr)
Bram Moolenaar57002ad2017-03-16 19:04:19 +01007494 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007495 // Mark the already saved text as finishing the line, so that what
7496 // follows is displayed on a new line when scrolling back at the
7497 // more prompt.
Bram Moolenaar57002ad2017-03-16 19:04:19 +01007498 msg_sb_eol();
Bram Moolenaar57002ad2017-03-16 19:04:19 +01007499 }
7500
Yasuhiro Matsumotoa02a8a42022-09-02 12:16:21 +01007501 if (eap->cmdidx == CMD_echomsg)
Bram Moolenaar4770d092006-01-12 23:22:24 +00007502 {
Bram Moolenaar32526b32019-01-19 17:43:09 +01007503 msg_attr(ga.ga_data, echo_attr);
Bram Moolenaar4770d092006-01-12 23:22:24 +00007504 out_flush();
7505 }
Yasuhiro Matsumotoa02a8a42022-09-02 12:16:21 +01007506 else if (eap->cmdidx == CMD_echowindow)
7507 {
7508#ifdef HAS_MESSAGE_WINDOW
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01007509 start_echowindow(eap->addr_count > 0 ? eap->line2 : 0);
Yasuhiro Matsumotoa02a8a42022-09-02 12:16:21 +01007510#endif
7511 msg_attr(ga.ga_data, echo_attr);
7512#ifdef HAS_MESSAGE_WINDOW
7513 end_echowindow();
7514#endif
7515 }
Bram Moolenaar4c868302021-03-22 16:19:45 +01007516 else if (eap->cmdidx == CMD_echoconsole)
7517 {
7518 ui_write(ga.ga_data, (int)STRLEN(ga.ga_data), TRUE);
7519 ui_write((char_u *)"\r\n", 2, TRUE);
7520 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007521 else if (eap->cmdidx == CMD_echoerr)
7522 {
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007523 int save_did_emsg = did_emsg;
7524
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007525 // We don't want to abort following commands, restore did_emsg.
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007526 emsg(ga.ga_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007527 if (!force_abort)
7528 did_emsg = save_did_emsg;
7529 }
7530 else if (eap->cmdidx == CMD_execute)
Bram Moolenaar5b1d6e92022-02-11 20:33:48 +00007531 {
7532 int save_sticky_cmdmod_flags = sticky_cmdmod_flags;
7533
7534 // "legacy exe cmd" and "vim9cmd exe cmd" applies to "cmd".
7535 sticky_cmdmod_flags = cmdmod.cmod_flags
7536 & (CMOD_LEGACY | CMOD_VIM9CMD);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007537 do_cmdline((char_u *)ga.ga_data,
Zoltan Arpadffy6fdb6282023-12-19 20:53:07 +01007538 eap->ea_getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
Bram Moolenaar5b1d6e92022-02-11 20:33:48 +00007539 sticky_cmdmod_flags = save_sticky_cmdmod_flags;
7540 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007541 }
7542
7543 ga_clear(&ga);
7544
7545 if (eap->skip)
7546 --emsg_skip;
Bram Moolenaar63b91732021-08-05 20:40:03 +02007547 set_nextcmd(eap, arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007548}
7549
7550/*
7551 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
7552 * "arg" points to the "&" or '+' when called, to "option" when returning.
7553 * Returns NULL when no option name found. Otherwise pointer to the char
7554 * after the option name.
7555 */
Bram Moolenaar0522ba02019-08-27 22:48:30 +02007556 char_u *
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00007557find_option_end(char_u **arg, int *scope)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007558{
7559 char_u *p = *arg;
7560
7561 ++p;
7562 if (*p == 'g' && p[1] == ':')
7563 {
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00007564 *scope = OPT_GLOBAL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007565 p += 2;
7566 }
7567 else if (*p == 'l' && p[1] == ':')
7568 {
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00007569 *scope = OPT_LOCAL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007570 p += 2;
7571 }
7572 else
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00007573 *scope = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007574
7575 if (!ASCII_ISALPHA(*p))
7576 return NULL;
7577 *arg = p;
7578
7579 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007580 p += 4; // termcap option
Bram Moolenaar071d4272004-06-13 20:20:40 +00007581 else
7582 while (ASCII_ISALPHA(*p))
7583 ++p;
7584 return p;
7585}
7586
7587/*
Bram Moolenaar661b1822005-07-28 22:36:45 +00007588 * Display script name where an item was last set.
7589 * Should only be invoked when 'verbose' is non-zero.
7590 */
7591 void
Bram Moolenaarf29c1c62018-09-10 21:05:02 +02007592last_set_msg(sctx_T script_ctx)
Bram Moolenaar661b1822005-07-28 22:36:45 +00007593{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +00007594 char_u *p;
7595
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00007596 if (script_ctx.sc_sid == 0)
7597 return;
7598
7599 p = home_replace_save(NULL, get_scriptname(script_ctx.sc_sid));
7600 if (p == NULL)
7601 return;
7602
7603 verbose_enter();
7604 msg_puts(_("\n\tLast set from "));
7605 msg_puts((char *)p);
7606 if (script_ctx.sc_lnum > 0)
Bram Moolenaar661b1822005-07-28 22:36:45 +00007607 {
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00007608 msg_puts(_(line_msg));
7609 msg_outnum((long)script_ctx.sc_lnum);
Bram Moolenaar661b1822005-07-28 22:36:45 +00007610 }
Yegappan Lakshmanan87c1cbb2022-12-27 19:54:52 +00007611 verbose_leave();
7612 vim_free(p);
Bram Moolenaar661b1822005-07-28 22:36:45 +00007613}
7614
Bram Moolenaarb005cd82019-09-04 15:54:55 +02007615#endif // FEAT_EVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00007616
7617/*
7618 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
Bram Moolenaar72ab7292016-07-19 19:10:51 +02007619 * When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007620 * "flags" can be "g" to do a global substitute.
7621 * Returns an allocated string, NULL for error.
7622 */
7623 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01007624do_string_sub(
7625 char_u *str,
John Marriottbd4614f2024-11-18 20:25:21 +01007626 size_t len,
Bram Moolenaar7454a062016-01-30 15:14:10 +01007627 char_u *pat,
7628 char_u *sub,
Bram Moolenaar72ab7292016-07-19 19:10:51 +02007629 typval_T *expr,
John Marriottbd4614f2024-11-18 20:25:21 +01007630 char_u *flags,
7631 size_t *ret_len) // length of returned buffer
Bram Moolenaar071d4272004-06-13 20:20:40 +00007632{
Bram Moolenaar071d4272004-06-13 20:20:40 +00007633 regmatch_T regmatch;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007634 garray_T ga;
7635 char_u *ret;
7636 char_u *save_cpo;
7637
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007638 // Make 'cpoptions' empty, so that the 'l' flag doesn't work here
Bram Moolenaar071d4272004-06-13 20:20:40 +00007639 save_cpo = p_cpo;
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +00007640 p_cpo = empty_option;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007641
7642 ga_init2(&ga, 1, 200);
7643
Bram Moolenaar071d4272004-06-13 20:20:40 +00007644 regmatch.rm_ic = p_ic;
7645 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
7646 if (regmatch.regprog != NULL)
7647 {
John Marriottbd4614f2024-11-18 20:25:21 +01007648 char_u *tail = str;
7649 char_u *end = str + len;
7650 int do_all = (flags[0] == 'g');
7651 int sublen;
7652 int i;
7653 char_u *zero_width = NULL;
7654
Bram Moolenaar071d4272004-06-13 20:20:40 +00007655 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
7656 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007657 // Skip empty match except for first match.
Bram Moolenaar8af26912014-01-23 20:09:34 +01007658 if (regmatch.startp[0] == regmatch.endp[0])
7659 {
7660 if (zero_width == regmatch.startp[0])
7661 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007662 // avoid getting stuck on a match with an empty string
Bram Moolenaar1614a142019-10-06 22:00:13 +02007663 i = mb_ptr2len(tail);
Bram Moolenaar8e7048c2014-06-12 18:39:22 +02007664 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail,
7665 (size_t)i);
7666 ga.ga_len += i;
7667 tail += i;
Bram Moolenaar8af26912014-01-23 20:09:34 +01007668 continue;
7669 }
7670 zero_width = regmatch.startp[0];
7671 }
7672
Bram Moolenaar071d4272004-06-13 20:20:40 +00007673 /*
7674 * Get some space for a temporary buffer to do the substitution
7675 * into. It will contain:
7676 * - The text up to where the match is.
7677 * - The substituted text.
7678 * - The text after the match.
7679 */
Bram Moolenaar4aaf3e72022-05-30 20:58:55 +01007680 sublen = vim_regsub(&regmatch, sub, expr, tail, 0, REGSUB_MAGIC);
Bram Moolenaar3ac1d972023-01-04 17:17:54 +00007681 if (sublen <= 0)
7682 {
7683 ga_clear(&ga);
7684 break;
7685 }
Bram Moolenaare90c8532014-11-05 16:03:44 +01007686 if (ga_grow(&ga, (int)((end - tail) + sublen -
Bram Moolenaar071d4272004-06-13 20:20:40 +00007687 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
7688 {
7689 ga_clear(&ga);
7690 break;
7691 }
7692
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007693 // copy the text up to where the match is
Bram Moolenaar071d4272004-06-13 20:20:40 +00007694 i = (int)(regmatch.startp[0] - tail);
7695 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007696 // add the substituted text
Bram Moolenaar4aaf3e72022-05-30 20:58:55 +01007697 (void)vim_regsub(&regmatch, sub, expr,
7698 (char_u *)ga.ga_data + ga.ga_len + i, sublen,
7699 REGSUB_COPY | REGSUB_MAGIC);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007700 ga.ga_len += i + sublen - 1;
Bram Moolenaarceb84af2013-09-29 21:11:05 +02007701 tail = regmatch.endp[0];
7702 if (*tail == NUL)
7703 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007704 if (!do_all)
7705 break;
7706 }
7707
7708 if (ga.ga_data != NULL)
John Marriottbd4614f2024-11-18 20:25:21 +01007709 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00007710 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
John Marriottbd4614f2024-11-18 20:25:21 +01007711 ga.ga_len += (int)(end - tail);
7712 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007713
Bram Moolenaar473de612013-06-08 18:19:48 +02007714 vim_regfree(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007715 }
7716
John Marriottbd4614f2024-11-18 20:25:21 +01007717 if (ga.ga_data != NULL)
7718 {
7719 str = (char_u *)ga.ga_data;
7720 len = (size_t)ga.ga_len;
7721 }
7722 ret = vim_strnsave(str, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007723 ga_clear(&ga);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +00007724 if (p_cpo == empty_option)
7725 p_cpo = save_cpo;
7726 else
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01007727 {
Bram Moolenaar5d18efe2019-12-01 21:11:22 +01007728 // Darn, evaluating {sub} expression or {expr} changed the value.
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01007729 // If it's still empty it was changed and restored, need to restore in
7730 // the complicated way.
7731 if (*p_cpo == NUL)
Bram Moolenaar31e5c602022-04-15 13:53:33 +01007732 set_option_value_give_err((char_u *)"cpo", 0L, save_cpo, 0);
Bram Moolenaar9c24ccc2008-07-14 21:05:15 +00007733 free_string_option(save_cpo);
Bram Moolenaare5a2dc82021-01-03 19:52:05 +01007734 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007735
John Marriottbd4614f2024-11-18 20:25:21 +01007736 if (ret_len != NULL)
7737 *ret_len = len;
7738
Bram Moolenaar071d4272004-06-13 20:20:40 +00007739 return ret;
7740}