xref: /vim-8.2.3635/src/evalvars.c (revision a1198124)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
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  * evalvars.c: functions for dealing with variables
12  */
13 
14 #include "vim.h"
15 
16 #if defined(FEAT_EVAL) || defined(PROTO)
17 
18 static dictitem_T	globvars_var;		// variable used for g:
19 static dict_T		globvardict;		// Dictionary with g: variables
20 #define globvarht globvardict.dv_hashtab
21 
22 /*
23  * Old Vim variables such as "v:version" are also available without the "v:".
24  * Also in functions.  We need a special hashtable for them.
25  */
26 static hashtab_T	compat_hashtab;
27 
28 /*
29  * Array to hold the value of v: variables.
30  * The value is in a dictitem, so that it can also be used in the v: scope.
31  * The reason to use this table anyway is for very quick access to the
32  * variables with the VV_ defines.
33  */
34 
35 // values for vv_flags:
36 #define VV_COMPAT	1	// compatible, also used without "v:"
37 #define VV_RO		2	// read-only
38 #define VV_RO_SBX	4	// read-only in the sandbox
39 
40 #define VV_NAME(s, t)	s, {{t, 0, {0}}, 0, {0}}
41 
42 typedef struct vimvar vimvar_T;
43 
44 static struct vimvar
45 {
46     char	*vv_name;	// name of variable, without v:
47     dictitem16_T vv_di;		// value and name for key (max 16 chars!)
48     char	vv_flags;	// VV_COMPAT, VV_RO, VV_RO_SBX
49 } vimvars[VV_LEN] =
50 {
51     // The order here must match the VV_ defines in vim.h!
52     // Initializing a union does not work, leave tv.vval empty to get zero's.
53     {VV_NAME("count",		 VAR_NUMBER), VV_COMPAT+VV_RO},
54     {VV_NAME("count1",		 VAR_NUMBER), VV_RO},
55     {VV_NAME("prevcount",	 VAR_NUMBER), VV_RO},
56     {VV_NAME("errmsg",		 VAR_STRING), VV_COMPAT},
57     {VV_NAME("warningmsg",	 VAR_STRING), 0},
58     {VV_NAME("statusmsg",	 VAR_STRING), 0},
59     {VV_NAME("shell_error",	 VAR_NUMBER), VV_COMPAT+VV_RO},
60     {VV_NAME("this_session",	 VAR_STRING), VV_COMPAT},
61     {VV_NAME("version",		 VAR_NUMBER), VV_COMPAT+VV_RO},
62     {VV_NAME("lnum",		 VAR_NUMBER), VV_RO_SBX},
63     {VV_NAME("termresponse",	 VAR_STRING), VV_RO},
64     {VV_NAME("fname",		 VAR_STRING), VV_RO},
65     {VV_NAME("lang",		 VAR_STRING), VV_RO},
66     {VV_NAME("lc_time",		 VAR_STRING), VV_RO},
67     {VV_NAME("ctype",		 VAR_STRING), VV_RO},
68     {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
69     {VV_NAME("charconvert_to",	 VAR_STRING), VV_RO},
70     {VV_NAME("fname_in",	 VAR_STRING), VV_RO},
71     {VV_NAME("fname_out",	 VAR_STRING), VV_RO},
72     {VV_NAME("fname_new",	 VAR_STRING), VV_RO},
73     {VV_NAME("fname_diff",	 VAR_STRING), VV_RO},
74     {VV_NAME("cmdarg",		 VAR_STRING), VV_RO},
75     {VV_NAME("foldstart",	 VAR_NUMBER), VV_RO_SBX},
76     {VV_NAME("foldend",		 VAR_NUMBER), VV_RO_SBX},
77     {VV_NAME("folddashes",	 VAR_STRING), VV_RO_SBX},
78     {VV_NAME("foldlevel",	 VAR_NUMBER), VV_RO_SBX},
79     {VV_NAME("progname",	 VAR_STRING), VV_RO},
80     {VV_NAME("servername",	 VAR_STRING), VV_RO},
81     {VV_NAME("dying",		 VAR_NUMBER), VV_RO},
82     {VV_NAME("exception",	 VAR_STRING), VV_RO},
83     {VV_NAME("throwpoint",	 VAR_STRING), VV_RO},
84     {VV_NAME("register",	 VAR_STRING), VV_RO},
85     {VV_NAME("cmdbang",		 VAR_NUMBER), VV_RO},
86     {VV_NAME("insertmode",	 VAR_STRING), VV_RO},
87     {VV_NAME("val",		 VAR_UNKNOWN), VV_RO},
88     {VV_NAME("key",		 VAR_UNKNOWN), VV_RO},
89     {VV_NAME("profiling",	 VAR_NUMBER), VV_RO},
90     {VV_NAME("fcs_reason",	 VAR_STRING), VV_RO},
91     {VV_NAME("fcs_choice",	 VAR_STRING), 0},
92     {VV_NAME("beval_bufnr",	 VAR_NUMBER), VV_RO},
93     {VV_NAME("beval_winnr",	 VAR_NUMBER), VV_RO},
94     {VV_NAME("beval_winid",	 VAR_NUMBER), VV_RO},
95     {VV_NAME("beval_lnum",	 VAR_NUMBER), VV_RO},
96     {VV_NAME("beval_col",	 VAR_NUMBER), VV_RO},
97     {VV_NAME("beval_text",	 VAR_STRING), VV_RO},
98     {VV_NAME("scrollstart",	 VAR_STRING), 0},
99     {VV_NAME("swapname",	 VAR_STRING), VV_RO},
100     {VV_NAME("swapchoice",	 VAR_STRING), 0},
101     {VV_NAME("swapcommand",	 VAR_STRING), VV_RO},
102     {VV_NAME("char",		 VAR_STRING), 0},
103     {VV_NAME("mouse_win",	 VAR_NUMBER), 0},
104     {VV_NAME("mouse_winid",	 VAR_NUMBER), 0},
105     {VV_NAME("mouse_lnum",	 VAR_NUMBER), 0},
106     {VV_NAME("mouse_col",	 VAR_NUMBER), 0},
107     {VV_NAME("operator",	 VAR_STRING), VV_RO},
108     {VV_NAME("searchforward",	 VAR_NUMBER), 0},
109     {VV_NAME("hlsearch",	 VAR_NUMBER), 0},
110     {VV_NAME("oldfiles",	 VAR_LIST), 0},
111     {VV_NAME("windowid",	 VAR_NUMBER), VV_RO},
112     {VV_NAME("progpath",	 VAR_STRING), VV_RO},
113     {VV_NAME("completed_item",	 VAR_DICT), VV_RO},
114     {VV_NAME("option_new",	 VAR_STRING), VV_RO},
115     {VV_NAME("option_old",	 VAR_STRING), VV_RO},
116     {VV_NAME("option_oldlocal",	 VAR_STRING), VV_RO},
117     {VV_NAME("option_oldglobal", VAR_STRING), VV_RO},
118     {VV_NAME("option_command",	 VAR_STRING), VV_RO},
119     {VV_NAME("option_type",	 VAR_STRING), VV_RO},
120     {VV_NAME("errors",		 VAR_LIST), 0},
121     {VV_NAME("false",		 VAR_BOOL), VV_RO},
122     {VV_NAME("true",		 VAR_BOOL), VV_RO},
123     {VV_NAME("none",		 VAR_SPECIAL), VV_RO},
124     {VV_NAME("null",		 VAR_SPECIAL), VV_RO},
125     {VV_NAME("numbermax",	 VAR_NUMBER), VV_RO},
126     {VV_NAME("numbermin",	 VAR_NUMBER), VV_RO},
127     {VV_NAME("numbersize",	 VAR_NUMBER), VV_RO},
128     {VV_NAME("vim_did_enter",	 VAR_NUMBER), VV_RO},
129     {VV_NAME("testing",		 VAR_NUMBER), 0},
130     {VV_NAME("t_number",	 VAR_NUMBER), VV_RO},
131     {VV_NAME("t_string",	 VAR_NUMBER), VV_RO},
132     {VV_NAME("t_func",		 VAR_NUMBER), VV_RO},
133     {VV_NAME("t_list",		 VAR_NUMBER), VV_RO},
134     {VV_NAME("t_dict",		 VAR_NUMBER), VV_RO},
135     {VV_NAME("t_float",		 VAR_NUMBER), VV_RO},
136     {VV_NAME("t_bool",		 VAR_NUMBER), VV_RO},
137     {VV_NAME("t_none",		 VAR_NUMBER), VV_RO},
138     {VV_NAME("t_job",		 VAR_NUMBER), VV_RO},
139     {VV_NAME("t_channel",	 VAR_NUMBER), VV_RO},
140     {VV_NAME("t_blob",		 VAR_NUMBER), VV_RO},
141     {VV_NAME("termrfgresp",	 VAR_STRING), VV_RO},
142     {VV_NAME("termrbgresp",	 VAR_STRING), VV_RO},
143     {VV_NAME("termu7resp",	 VAR_STRING), VV_RO},
144     {VV_NAME("termstyleresp",	 VAR_STRING), VV_RO},
145     {VV_NAME("termblinkresp",	 VAR_STRING), VV_RO},
146     {VV_NAME("event",		 VAR_DICT), VV_RO},
147     {VV_NAME("versionlong",	 VAR_NUMBER), VV_RO},
148     {VV_NAME("echospace",	 VAR_NUMBER), VV_RO},
149     {VV_NAME("argv",		 VAR_LIST), VV_RO},
150     {VV_NAME("collate",		 VAR_STRING), VV_RO},
151     {VV_NAME("exiting",		 VAR_SPECIAL), VV_RO},
152     {VV_NAME("colornames",       VAR_DICT), VV_RO},
153     {VV_NAME("sizeofint",	 VAR_NUMBER), VV_RO},
154     {VV_NAME("sizeoflong",	 VAR_NUMBER), VV_RO},
155     {VV_NAME("sizeofpointer",	 VAR_NUMBER), VV_RO},
156 };
157 
158 // shorthand
159 #define vv_type		vv_di.di_tv.v_type
160 #define vv_nr		vv_di.di_tv.vval.v_number
161 #define vv_float	vv_di.di_tv.vval.v_float
162 #define vv_str		vv_di.di_tv.vval.v_string
163 #define vv_list		vv_di.di_tv.vval.v_list
164 #define vv_dict		vv_di.di_tv.vval.v_dict
165 #define vv_blob		vv_di.di_tv.vval.v_blob
166 #define vv_tv		vv_di.di_tv
167 
168 static dictitem_T	vimvars_var;		// variable used for v:
169 static dict_T		vimvardict;		// Dictionary with v: variables
170 #define vimvarht  vimvardict.dv_hashtab
171 
172 // for VIM_VERSION_ defines
173 #include "version.h"
174 
175 static void list_glob_vars(int *first);
176 static void list_buf_vars(int *first);
177 static void list_win_vars(int *first);
178 static void list_tab_vars(int *first);
179 static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
180 static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op, int var_idx);
181 static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
182 static int do_lock_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
183 static void list_one_var(dictitem_T *v, char *prefix, int *first);
184 static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
185 
186 /*
187  * Initialize global and vim special variables
188  */
189     void
evalvars_init(void)190 evalvars_init(void)
191 {
192     int		    i;
193     struct vimvar   *p;
194 
195     init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
196     init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
197     vimvardict.dv_lock = VAR_FIXED;
198     hash_init(&compat_hashtab);
199 
200     for (i = 0; i < VV_LEN; ++i)
201     {
202 	p = &vimvars[i];
203 	if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN)
204 	{
205 	    iemsg("INTERNAL: name too long, increase size of dictitem16_T");
206 	    getout(1);
207 	}
208 	STRCPY(p->vv_di.di_key, p->vv_name);
209 	if (p->vv_flags & VV_RO)
210 	    p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
211 	else if (p->vv_flags & VV_RO_SBX)
212 	    p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
213 	else
214 	    p->vv_di.di_flags = DI_FLAGS_FIX;
215 
216 	// add to v: scope dict, unless the value is not always available
217 	if (p->vv_type != VAR_UNKNOWN)
218 	    hash_add(&vimvarht, p->vv_di.di_key);
219 	if (p->vv_flags & VV_COMPAT)
220 	    // add to compat scope dict
221 	    hash_add(&compat_hashtab, p->vv_di.di_key);
222     }
223     set_vim_var_nr(VV_VERSION, VIM_VERSION_100);
224     set_vim_var_nr(VV_VERSIONLONG, VIM_VERSION_100 * 10000 + highest_patch());
225 
226     set_vim_var_nr(VV_SEARCHFORWARD, 1L);
227     set_vim_var_nr(VV_HLSEARCH, 1L);
228     set_vim_var_nr(VV_EXITING, VVAL_NULL);
229     set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
230     set_vim_var_list(VV_ERRORS, list_alloc());
231     set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
232 
233     set_vim_var_nr(VV_FALSE, VVAL_FALSE);
234     set_vim_var_nr(VV_TRUE, VVAL_TRUE);
235     set_vim_var_nr(VV_NONE, VVAL_NONE);
236     set_vim_var_nr(VV_NULL, VVAL_NULL);
237     set_vim_var_nr(VV_NUMBERMAX, VARNUM_MAX);
238     set_vim_var_nr(VV_NUMBERMIN, VARNUM_MIN);
239     set_vim_var_nr(VV_NUMBERSIZE, sizeof(varnumber_T) * 8);
240     set_vim_var_nr(VV_SIZEOFINT, sizeof(int));
241     set_vim_var_nr(VV_SIZEOFLONG, sizeof(long));
242     set_vim_var_nr(VV_SIZEOFPOINTER, sizeof(char *));
243 
244     set_vim_var_nr(VV_TYPE_NUMBER,  VAR_TYPE_NUMBER);
245     set_vim_var_nr(VV_TYPE_STRING,  VAR_TYPE_STRING);
246     set_vim_var_nr(VV_TYPE_FUNC,    VAR_TYPE_FUNC);
247     set_vim_var_nr(VV_TYPE_LIST,    VAR_TYPE_LIST);
248     set_vim_var_nr(VV_TYPE_DICT,    VAR_TYPE_DICT);
249     set_vim_var_nr(VV_TYPE_FLOAT,   VAR_TYPE_FLOAT);
250     set_vim_var_nr(VV_TYPE_BOOL,    VAR_TYPE_BOOL);
251     set_vim_var_nr(VV_TYPE_NONE,    VAR_TYPE_NONE);
252     set_vim_var_nr(VV_TYPE_JOB,     VAR_TYPE_JOB);
253     set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL);
254     set_vim_var_nr(VV_TYPE_BLOB,    VAR_TYPE_BLOB);
255 
256     set_vim_var_nr(VV_ECHOSPACE,    sc_col - 1);
257 
258     set_vim_var_dict(VV_COLORNAMES, dict_alloc());
259 
260     // Default for v:register is not 0 but '"'.  This is adjusted once the
261     // clipboard has been setup by calling reset_reg_var().
262     set_reg_var(0);
263 }
264 
265 #if defined(EXITFREE) || defined(PROTO)
266 /*
267  * Free all vim variables information on exit
268  */
269     void
evalvars_clear(void)270 evalvars_clear(void)
271 {
272     int		    i;
273     struct vimvar   *p;
274 
275     for (i = 0; i < VV_LEN; ++i)
276     {
277 	p = &vimvars[i];
278 	if (p->vv_di.di_tv.v_type == VAR_STRING)
279 	    VIM_CLEAR(p->vv_str);
280 	else if (p->vv_di.di_tv.v_type == VAR_LIST)
281 	{
282 	    list_unref(p->vv_list);
283 	    p->vv_list = NULL;
284 	}
285     }
286     hash_clear(&vimvarht);
287     hash_init(&vimvarht);  // garbage_collect() will access it
288     hash_clear(&compat_hashtab);
289 
290     // global variables
291     vars_clear(&globvarht);
292 
293     // Script-local variables. Clear all the variables here.
294     // The scriptvar_T is cleared later in free_scriptnames(), because a
295     // variable in one script might hold a reference to the whole scope of
296     // another script.
297     for (i = 1; i <= script_items.ga_len; ++i)
298 	vars_clear(&SCRIPT_VARS(i));
299 }
300 #endif
301 
302     int
garbage_collect_globvars(int copyID)303 garbage_collect_globvars(int copyID)
304 {
305     return set_ref_in_ht(&globvarht, copyID, NULL);
306 }
307 
308     int
garbage_collect_vimvars(int copyID)309 garbage_collect_vimvars(int copyID)
310 {
311     return set_ref_in_ht(&vimvarht, copyID, NULL);
312 }
313 
314     int
garbage_collect_scriptvars(int copyID)315 garbage_collect_scriptvars(int copyID)
316 {
317     int		    i;
318     int		    idx;
319     int		    abort = FALSE;
320     scriptitem_T    *si;
321 
322     for (i = 1; i <= script_items.ga_len; ++i)
323     {
324 	abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
325 
326 	si = SCRIPT_ITEM(i);
327 	for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
328 	{
329 	    svar_T    *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
330 
331 	    if (sv->sv_name != NULL)
332 		abort = abort || set_ref_in_item(sv->sv_tv, copyID, NULL, NULL);
333 	}
334     }
335 
336     return abort;
337 }
338 
339 /*
340  * Set an internal variable to a string value. Creates the variable if it does
341  * not already exist.
342  */
343     void
set_internal_string_var(char_u * name,char_u * value)344 set_internal_string_var(char_u *name, char_u *value)
345 {
346     char_u	*val;
347     typval_T	*tvp;
348 
349     val = vim_strsave(value);
350     if (val != NULL)
351     {
352 	tvp = alloc_string_tv(val);
353 	if (tvp != NULL)
354 	{
355 	    set_var(name, tvp, FALSE);
356 	    free_tv(tvp);
357 	}
358     }
359 }
360 
361     int
eval_charconvert(char_u * enc_from,char_u * enc_to,char_u * fname_from,char_u * fname_to)362 eval_charconvert(
363     char_u	*enc_from,
364     char_u	*enc_to,
365     char_u	*fname_from,
366     char_u	*fname_to)
367 {
368     int		err = FALSE;
369 
370     set_vim_var_string(VV_CC_FROM, enc_from, -1);
371     set_vim_var_string(VV_CC_TO, enc_to, -1);
372     set_vim_var_string(VV_FNAME_IN, fname_from, -1);
373     set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
374     if (eval_to_bool(p_ccv, &err, NULL, FALSE))
375 	err = TRUE;
376     set_vim_var_string(VV_CC_FROM, NULL, -1);
377     set_vim_var_string(VV_CC_TO, NULL, -1);
378     set_vim_var_string(VV_FNAME_IN, NULL, -1);
379     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
380 
381     if (err)
382 	return FAIL;
383     return OK;
384 }
385 
386 # if defined(FEAT_POSTSCRIPT) || defined(PROTO)
387     int
eval_printexpr(char_u * fname,char_u * args)388 eval_printexpr(char_u *fname, char_u *args)
389 {
390     int		err = FALSE;
391 
392     set_vim_var_string(VV_FNAME_IN, fname, -1);
393     set_vim_var_string(VV_CMDARG, args, -1);
394     if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
395 	err = TRUE;
396     set_vim_var_string(VV_FNAME_IN, NULL, -1);
397     set_vim_var_string(VV_CMDARG, NULL, -1);
398 
399     if (err)
400     {
401 	mch_remove(fname);
402 	return FAIL;
403     }
404     return OK;
405 }
406 # endif
407 
408 # if defined(FEAT_DIFF) || defined(PROTO)
409     void
eval_diff(char_u * origfile,char_u * newfile,char_u * outfile)410 eval_diff(
411     char_u	*origfile,
412     char_u	*newfile,
413     char_u	*outfile)
414 {
415     int		err = FALSE;
416 
417     set_vim_var_string(VV_FNAME_IN, origfile, -1);
418     set_vim_var_string(VV_FNAME_NEW, newfile, -1);
419     set_vim_var_string(VV_FNAME_OUT, outfile, -1);
420     (void)eval_to_bool(p_dex, &err, NULL, FALSE);
421     set_vim_var_string(VV_FNAME_IN, NULL, -1);
422     set_vim_var_string(VV_FNAME_NEW, NULL, -1);
423     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
424 }
425 
426     void
eval_patch(char_u * origfile,char_u * difffile,char_u * outfile)427 eval_patch(
428     char_u	*origfile,
429     char_u	*difffile,
430     char_u	*outfile)
431 {
432     int		err;
433 
434     set_vim_var_string(VV_FNAME_IN, origfile, -1);
435     set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
436     set_vim_var_string(VV_FNAME_OUT, outfile, -1);
437     (void)eval_to_bool(p_pex, &err, NULL, FALSE);
438     set_vim_var_string(VV_FNAME_IN, NULL, -1);
439     set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
440     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
441 }
442 # endif
443 
444 #if defined(FEAT_SPELL) || defined(PROTO)
445 /*
446  * Evaluate an expression to a list with suggestions.
447  * For the "expr:" part of 'spellsuggest'.
448  * Returns NULL when there is an error.
449  */
450     list_T *
eval_spell_expr(char_u * badword,char_u * expr)451 eval_spell_expr(char_u *badword, char_u *expr)
452 {
453     typval_T	save_val;
454     typval_T	rettv;
455     list_T	*list = NULL;
456     char_u	*p = skipwhite(expr);
457 
458     // Set "v:val" to the bad word.
459     prepare_vimvar(VV_VAL, &save_val);
460     set_vim_var_string(VV_VAL, badword, -1);
461     if (p_verbose == 0)
462 	++emsg_off;
463 
464     if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK)
465     {
466 	if (rettv.v_type != VAR_LIST)
467 	    clear_tv(&rettv);
468 	else
469 	    list = rettv.vval.v_list;
470     }
471 
472     if (p_verbose == 0)
473 	--emsg_off;
474     clear_tv(get_vim_var_tv(VV_VAL));
475     restore_vimvar(VV_VAL, &save_val);
476 
477     return list;
478 }
479 
480 /*
481  * "list" is supposed to contain two items: a word and a number.  Return the
482  * word in "pp" and the number as the return value.
483  * Return -1 if anything isn't right.
484  * Used to get the good word and score from the eval_spell_expr() result.
485  */
486     int
get_spellword(list_T * list,char_u ** pp)487 get_spellword(list_T *list, char_u **pp)
488 {
489     listitem_T	*li;
490 
491     li = list->lv_first;
492     if (li == NULL)
493 	return -1;
494     *pp = tv_get_string(&li->li_tv);
495 
496     li = li->li_next;
497     if (li == NULL)
498 	return -1;
499     return (int)tv_get_number(&li->li_tv);
500 }
501 #endif
502 
503 /*
504  * Prepare v: variable "idx" to be used.
505  * Save the current typeval in "save_tv" and clear it.
506  * When not used yet add the variable to the v: hashtable.
507  */
508     void
prepare_vimvar(int idx,typval_T * save_tv)509 prepare_vimvar(int idx, typval_T *save_tv)
510 {
511     *save_tv = vimvars[idx].vv_tv;
512     vimvars[idx].vv_str = NULL;  // don't free it now
513     if (vimvars[idx].vv_type == VAR_UNKNOWN)
514 	hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
515 }
516 
517 /*
518  * Restore v: variable "idx" to typeval "save_tv".
519  * Note that the v: variable must have been cleared already.
520  * When no longer defined, remove the variable from the v: hashtable.
521  */
522     void
restore_vimvar(int idx,typval_T * save_tv)523 restore_vimvar(int idx, typval_T *save_tv)
524 {
525     hashitem_T	*hi;
526 
527     vimvars[idx].vv_tv = *save_tv;
528     if (vimvars[idx].vv_type == VAR_UNKNOWN)
529     {
530 	hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
531 	if (HASHITEM_EMPTY(hi))
532 	    internal_error("restore_vimvar()");
533 	else
534 	    hash_remove(&vimvarht, hi);
535     }
536 }
537 
538 /*
539  * List Vim variables.
540  */
541     static void
list_vim_vars(int * first)542 list_vim_vars(int *first)
543 {
544     list_hashtable_vars(&vimvarht, "v:", FALSE, first);
545 }
546 
547 /*
548  * List script-local variables, if there is a script.
549  */
550     static void
list_script_vars(int * first)551 list_script_vars(int *first)
552 {
553     if (SCRIPT_ID_VALID(current_sctx.sc_sid))
554 	list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
555 							   "s:", FALSE, first);
556 }
557 
558 /*
559  * Get a list of lines from a HERE document. The here document is a list of
560  * lines surrounded by a marker.
561  *	cmd << {marker}
562  *	  {line1}
563  *	  {line2}
564  *	  ....
565  *	{marker}
566  *
567  * The {marker} is a string. If the optional 'trim' word is supplied before the
568  * marker, then the leading indentation before the lines (matching the
569  * indentation in the 'cmd' line) is stripped.
570  *
571  * When getting lines for an embedded script (e.g. python, lua, perl, ruby,
572  * tcl, mzscheme), script_get is set to TRUE. In this case, if the marker is
573  * missing, then '.' is accepted as a marker.
574  *
575  * Returns a List with {lines} or NULL.
576  */
577     list_T *
heredoc_get(exarg_T * eap,char_u * cmd,int script_get)578 heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
579 {
580     char_u	*theline;
581     char_u	*marker;
582     list_T	*l;
583     char_u	*p;
584     int		marker_indent_len = 0;
585     int		text_indent_len = 0;
586     char_u	*text_indent = NULL;
587     char_u	dot[] = ".";
588     int		comment_char = in_vim9script() ? '#' : '"';
589 
590     if (eap->getline == NULL)
591     {
592 	emsg(_("E991: cannot use =<< here"));
593 	return NULL;
594     }
595 
596     // Check for the optional 'trim' word before the marker
597     cmd = skipwhite(cmd);
598     if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
599     {
600 	cmd = skipwhite(cmd + 4);
601 
602 	// Trim the indentation from all the lines in the here document.
603 	// The amount of indentation trimmed is the same as the indentation of
604 	// the first line after the :let command line.  To find the end marker
605 	// the indent of the :let command line is trimmed.
606 	p = *eap->cmdlinep;
607 	while (VIM_ISWHITE(*p))
608 	{
609 	    p++;
610 	    marker_indent_len++;
611 	}
612 	text_indent_len = -1;
613     }
614 
615     // The marker is the next word.
616     if (*cmd != NUL && *cmd != comment_char)
617     {
618 	marker = skipwhite(cmd);
619 	p = skiptowhite(marker);
620 	if (*skipwhite(p) != NUL && *skipwhite(p) != comment_char)
621 	{
622 	    semsg(_(e_trailing_arg), p);
623 	    return NULL;
624 	}
625 	*p = NUL;
626 	if (!script_get && vim_islower(*marker))
627 	{
628 	    emsg(_("E221: Marker cannot start with lower case letter"));
629 	    return NULL;
630 	}
631     }
632     else
633     {
634 	// When getting lines for an embedded script, if the marker is missing,
635 	// accept '.' as the marker.
636 	if (script_get)
637 	    marker = dot;
638 	else
639 	{
640 	    emsg(_("E172: Missing marker"));
641 	    return NULL;
642 	}
643     }
644 
645     l = list_alloc();
646     if (l == NULL)
647 	return NULL;
648 
649     for (;;)
650     {
651 	int	mi = 0;
652 	int	ti = 0;
653 
654 	theline = eap->getline(NUL, eap->cookie, 0, FALSE);
655 	if (theline == NULL)
656 	{
657 	    semsg(_("E990: Missing end marker '%s'"), marker);
658 	    break;
659 	}
660 
661 	// with "trim": skip the indent matching the :let line to find the
662 	// marker
663 	if (marker_indent_len > 0
664 		&& STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
665 	    mi = marker_indent_len;
666 	if (STRCMP(marker, theline + mi) == 0)
667 	{
668 	    vim_free(theline);
669 	    break;
670 	}
671 
672 	if (text_indent_len == -1 && *theline != NUL)
673 	{
674 	    // set the text indent from the first line.
675 	    p = theline;
676 	    text_indent_len = 0;
677 	    while (VIM_ISWHITE(*p))
678 	    {
679 		p++;
680 		text_indent_len++;
681 	    }
682 	    text_indent = vim_strnsave(theline, text_indent_len);
683 	}
684 	// with "trim": skip the indent matching the first line
685 	if (text_indent != NULL)
686 	    for (ti = 0; ti < text_indent_len; ++ti)
687 		if (theline[ti] != text_indent[ti])
688 		    break;
689 
690 	if (list_append_string(l, theline + ti, -1) == FAIL)
691 	    break;
692 	vim_free(theline);
693     }
694     vim_free(text_indent);
695 
696     return l;
697 }
698 
699 /*
700  * Vim9 variable declaration:
701  * ":var name"
702  * ":var name: type"
703  * ":var name = expr"
704  * ":var name: type = expr"
705  * etc.
706  */
707     void
ex_var(exarg_T * eap)708 ex_var(exarg_T *eap)
709 {
710     if (!in_vim9script())
711     {
712 	semsg(_(e_str_cannot_be_used_in_legacy_vim_script), ":var");
713 	return;
714     }
715     ex_let(eap);
716 }
717 
718 /*
719  * ":let"			list all variable values
720  * ":let var1 var2"		list variable values
721  * ":let var = expr"		assignment command.
722  * ":let var += expr"		assignment command.
723  * ":let var -= expr"		assignment command.
724  * ":let var *= expr"		assignment command.
725  * ":let var /= expr"		assignment command.
726  * ":let var %= expr"		assignment command.
727  * ":let var .= expr"		assignment command.
728  * ":let var ..= expr"		assignment command.
729  * ":let [var1, var2] = expr"	unpack list.
730  * ":let var =<< ..."		heredoc
731  * ":let var: string"		Vim9 declaration
732  *
733  * ":final var = expr"		assignment command.
734  * ":final [var1, var2] = expr"	unpack list.
735  *
736  * ":const"			list all variable values
737  * ":const var1 var2"		list variable values
738  * ":const var = expr"		assignment command.
739  * ":const [var1, var2] = expr"	unpack list.
740  */
741     void
ex_let(exarg_T * eap)742 ex_let(exarg_T *eap)
743 {
744     char_u	*arg = eap->arg;
745     char_u	*expr = NULL;
746     typval_T	rettv;
747     int		i;
748     int		var_count = 0;
749     int		semicolon = 0;
750     char_u	op[4];
751     char_u	*argend;
752     int		first = TRUE;
753     int		concat;
754     int		has_assign;
755     int		flags = 0;
756     int		vim9script = in_vim9script();
757 
758     if (eap->cmdidx == CMD_final && !vim9script)
759     {
760 	// In legacy Vim script ":final" is short for ":finally".
761 	ex_finally(eap);
762 	return;
763     }
764     if (eap->cmdidx == CMD_let && vim9script)
765     {
766 	emsg(_(e_cannot_use_let_in_vim9_script));
767 	return;
768     }
769 
770     if (eap->cmdidx == CMD_const)
771 	flags |= ASSIGN_CONST;
772     else if (eap->cmdidx == CMD_final)
773 	flags |= ASSIGN_FINAL;
774 
775     // Vim9 assignment without ":let", ":const" or ":final"
776     if (eap->arg == eap->cmd)
777 	flags |= ASSIGN_NO_DECL;
778 
779     argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
780     if (argend == NULL)
781 	return;
782     if (argend > arg && argend[-1] == '.')  // for var.='str'
783 	--argend;
784     expr = skipwhite(argend);
785     concat = expr[0] == '.'
786 	&& ((expr[1] == '=' && in_old_script(2))
787 		|| (expr[1] == '.' && expr[2] == '='));
788     has_assign =  *expr == '=' || (vim_strchr((char_u *)"+-*/%", *expr) != NULL
789 							    && expr[1] == '=');
790     if (!has_assign && !concat)
791     {
792 	// ":let" without "=": list variables
793 	if (*arg == '[')
794 	    emsg(_(e_invarg));
795 	else if (expr[0] == '.' && expr[1] == '=')
796 	    emsg(_("E985: .= is not supported with script version >= 2"));
797 	else if (!ends_excmd2(eap->cmd, arg))
798 	{
799 	    if (vim9script)
800 	    {
801 		if (!ends_excmd2(eap->cmd, skipwhite(argend)))
802 		    semsg(_(e_trailing_arg), argend);
803 		else
804 		    // Vim9 declaration ":var name: type"
805 		    arg = vim9_declare_scriptvar(eap, arg);
806 	    }
807 	    else
808 	    {
809 		// ":let var1 var2" - list values
810 		arg = list_arg_vars(eap, arg, &first);
811 	    }
812 	}
813 	else if (!eap->skip)
814 	{
815 	    // ":let"
816 	    list_glob_vars(&first);
817 	    list_buf_vars(&first);
818 	    list_win_vars(&first);
819 	    list_tab_vars(&first);
820 	    list_script_vars(&first);
821 	    list_func_vars(&first);
822 	    list_vim_vars(&first);
823 	}
824 	set_nextcmd(eap, arg);
825     }
826     else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
827     {
828 	list_T	*l;
829 	long	cur_lnum = SOURCING_LNUM;
830 
831 	// HERE document
832 	l = heredoc_get(eap, expr + 3, FALSE);
833 	if (l != NULL)
834 	{
835 	    rettv_list_set(&rettv, l);
836 	    if (!eap->skip)
837 	    {
838 		// errors are for the assignment, not the end marker
839 		SOURCING_LNUM = cur_lnum;
840 		op[0] = '=';
841 		op[1] = NUL;
842 		(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
843 								flags, op);
844 	    }
845 	    clear_tv(&rettv);
846 	}
847     }
848     else
849     {
850 	evalarg_T   evalarg;
851 	int	    len = 1;
852 
853 	CLEAR_FIELD(rettv);
854 	i = FAIL;
855 	if (has_assign || concat)
856 	{
857 	    int cur_lnum;
858 
859 	    op[0] = '=';
860 	    op[1] = NUL;
861 	    if (*expr != '=')
862 	    {
863 		if (vim9script && (flags & ASSIGN_NO_DECL) == 0)
864 		{
865 		    // +=, /=, etc. require an existing variable
866 		    semsg(_(e_cannot_use_operator_on_new_variable), eap->arg);
867 		    i = FAIL;
868 		}
869 		else if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
870 		{
871 		    op[0] = *expr;   // +=, -=, *=, /=, %= or .=
872 		    ++len;
873 		    if (expr[0] == '.' && expr[1] == '.') // ..=
874 		    {
875 			++expr;
876 			++len;
877 		    }
878 		}
879 		expr += 2;
880 	    }
881 	    else
882 		++expr;
883 
884 	    if (vim9script && (!VIM_ISWHITE(*argend)
885 						   || !IS_WHITE_OR_NUL(*expr)))
886 	    {
887 		vim_strncpy(op, expr - len, len);
888 		semsg(_(e_white_space_required_before_and_after_str_at_str),
889 								   op, argend);
890 		i = FAIL;
891 	    }
892 
893 	    if (eap->skip)
894 		++emsg_skip;
895 	    fill_evalarg_from_eap(&evalarg, eap, eap->skip);
896 	    expr = skipwhite_and_linebreak(expr, &evalarg);
897 	    cur_lnum = SOURCING_LNUM;
898 	    i = eval0(expr, &rettv, eap, &evalarg);
899 	    if (eap->skip)
900 		--emsg_skip;
901 	    clear_evalarg(&evalarg, eap);
902 
903 	    // Restore the line number so that any type error is given for the
904 	    // declaration, not the expression.
905 	    SOURCING_LNUM = cur_lnum;
906 	}
907 	if (eap->skip)
908 	{
909 	    if (i != FAIL)
910 		clear_tv(&rettv);
911 	}
912 	else if (i != FAIL)
913 	{
914 	    (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
915 								    flags, op);
916 	    clear_tv(&rettv);
917 	}
918     }
919 }
920 
921 /*
922  * Assign the typeval "tv" to the variable or variables at "arg_start".
923  * Handles both "var" with any type and "[var, var; var]" with a list type.
924  * When "op" is not NULL it points to a string with characters that
925  * must appear after the variable(s).  Use "+", "-" or "." for add, subtract
926  * or concatenate.
927  * Returns OK or FAIL;
928  */
929     int
ex_let_vars(char_u * arg_start,typval_T * tv,int copy,int semicolon,int var_count,int flags,char_u * op)930 ex_let_vars(
931     char_u	*arg_start,
932     typval_T	*tv,
933     int		copy,		// copy values from "tv", don't move
934     int		semicolon,	// from skip_var_list()
935     int		var_count,	// from skip_var_list()
936     int		flags,		// ASSIGN_FINAL, ASSIGN_CONST, etc.
937     char_u	*op)
938 {
939     char_u	*arg = arg_start;
940     list_T	*l;
941     int		i;
942     int		var_idx = 0;
943     listitem_T	*item;
944     typval_T	ltv;
945 
946     if (*arg != '[')
947     {
948 	// ":let var = expr" or ":for var in list"
949 	if (ex_let_one(arg, tv, copy, flags, op, op, var_idx) == NULL)
950 	    return FAIL;
951 	return OK;
952     }
953 
954     // ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
955     if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
956     {
957 	emsg(_(e_listreq));
958 	return FAIL;
959     }
960 
961     i = list_len(l);
962     if (semicolon == 0 && var_count < i)
963     {
964 	emsg(_("E687: Less targets than List items"));
965 	return FAIL;
966     }
967     if (var_count - semicolon > i)
968     {
969 	emsg(_("E688: More targets than List items"));
970 	return FAIL;
971     }
972 
973     CHECK_LIST_MATERIALIZE(l);
974     item = l->lv_first;
975     while (*arg != ']')
976     {
977 	arg = skipwhite(arg + 1);
978 	++var_idx;
979 	arg = ex_let_one(arg, &item->li_tv, TRUE,
980 			  flags | ASSIGN_UNPACK, (char_u *)",;]", op, var_idx);
981 	item = item->li_next;
982 	if (arg == NULL)
983 	    return FAIL;
984 
985 	arg = skipwhite(arg);
986 	if (*arg == ';')
987 	{
988 	    // Put the rest of the list (may be empty) in the var after ';'.
989 	    // Create a new list for this.
990 	    l = list_alloc();
991 	    if (l == NULL)
992 		return FAIL;
993 	    while (item != NULL)
994 	    {
995 		list_append_tv(l, &item->li_tv);
996 		item = item->li_next;
997 	    }
998 
999 	    ltv.v_type = VAR_LIST;
1000 	    ltv.v_lock = 0;
1001 	    ltv.vval.v_list = l;
1002 	    l->lv_refcount = 1;
1003 	    ++var_idx;
1004 
1005 	    arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1006 			    flags | ASSIGN_UNPACK, (char_u *)"]", op, var_idx);
1007 	    clear_tv(&ltv);
1008 	    if (arg == NULL)
1009 		return FAIL;
1010 	    break;
1011 	}
1012 	else if (*arg != ',' && *arg != ']')
1013 	{
1014 	    internal_error("ex_let_vars()");
1015 	    return FAIL;
1016 	}
1017     }
1018 
1019     return OK;
1020 }
1021 
1022 /*
1023  * Skip over assignable variable "var" or list of variables "[var, var]".
1024  * Used for ":let varvar = expr" and ":for varvar in expr".
1025  * For "[var, var]" increment "*var_count" for each variable.
1026  * for "[var, var; var]" set "semicolon" to 1.
1027  * If "silent" is TRUE do not give an "invalid argument" error message.
1028  * Return NULL for an error.
1029  */
1030     char_u *
skip_var_list(char_u * arg,int include_type,int * var_count,int * semicolon,int silent)1031 skip_var_list(
1032     char_u	*arg,
1033     int		include_type,
1034     int		*var_count,
1035     int		*semicolon,
1036     int		silent)
1037 {
1038     char_u	*p, *s;
1039 
1040     if (*arg == '[')
1041     {
1042 	// "[var, var]": find the matching ']'.
1043 	p = arg;
1044 	for (;;)
1045 	{
1046 	    p = skipwhite(p + 1);	// skip whites after '[', ';' or ','
1047 	    s = skip_var_one(p, include_type);
1048 	    if (s == p)
1049 	    {
1050 		if (!silent)
1051 		    semsg(_(e_invarg2), p);
1052 		return NULL;
1053 	    }
1054 	    ++*var_count;
1055 
1056 	    p = skipwhite(s);
1057 	    if (*p == ']')
1058 		break;
1059 	    else if (*p == ';')
1060 	    {
1061 		if (*semicolon == 1)
1062 		{
1063 		    emsg(_("E452: Double ; in list of variables"));
1064 		    return NULL;
1065 		}
1066 		*semicolon = 1;
1067 	    }
1068 	    else if (*p != ',')
1069 	    {
1070 		if (!silent)
1071 		    semsg(_(e_invarg2), p);
1072 		return NULL;
1073 	    }
1074 	}
1075 	return p + 1;
1076     }
1077     else
1078 	return skip_var_one(arg, include_type);
1079 }
1080 
1081 /*
1082  * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
1083  * l[idx].
1084  * In Vim9 script also skip over ": type" if "include_type" is TRUE.
1085  */
1086     char_u *
skip_var_one(char_u * arg,int include_type)1087 skip_var_one(char_u *arg, int include_type)
1088 {
1089     char_u	*end;
1090     int		vim9 = in_vim9script();
1091 
1092     if (*arg == '@' && arg[1] != NUL)
1093 	return arg + 2;
1094     end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1095 				   NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
1096 
1097     // "a: type" is declaring variable "a" with a type, not "a:".
1098     // Same for "s: type".
1099     if (vim9 && end == arg + 2 && end[-1] == ':')
1100 	--end;
1101 
1102     if (include_type && vim9)
1103     {
1104 	if (*end == ':')
1105 	    end = skip_type(skipwhite(end + 1), FALSE);
1106     }
1107     return end;
1108 }
1109 
1110 /*
1111  * List variables for hashtab "ht" with prefix "prefix".
1112  * If "empty" is TRUE also list NULL strings as empty strings.
1113  */
1114     void
list_hashtable_vars(hashtab_T * ht,char * prefix,int empty,int * first)1115 list_hashtable_vars(
1116     hashtab_T	*ht,
1117     char	*prefix,
1118     int		empty,
1119     int		*first)
1120 {
1121     hashitem_T	*hi;
1122     dictitem_T	*di;
1123     int		todo;
1124     char_u	buf[IOSIZE];
1125 
1126     todo = (int)ht->ht_used;
1127     for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1128     {
1129 	if (!HASHITEM_EMPTY(hi))
1130 	{
1131 	    --todo;
1132 	    di = HI2DI(hi);
1133 
1134 	    // apply :filter /pat/ to variable name
1135 	    vim_strncpy((char_u *)buf, (char_u *)prefix, IOSIZE - 1);
1136 	    vim_strcat((char_u *)buf, di->di_key, IOSIZE);
1137 	    if (message_filtered(buf))
1138 		continue;
1139 
1140 	    if (empty || di->di_tv.v_type != VAR_STRING
1141 					   || di->di_tv.vval.v_string != NULL)
1142 		list_one_var(di, prefix, first);
1143 	}
1144     }
1145 }
1146 
1147 /*
1148  * List global variables.
1149  */
1150     static void
list_glob_vars(int * first)1151 list_glob_vars(int *first)
1152 {
1153     list_hashtable_vars(&globvarht, "", TRUE, first);
1154 }
1155 
1156 /*
1157  * List buffer variables.
1158  */
1159     static void
list_buf_vars(int * first)1160 list_buf_vars(int *first)
1161 {
1162     list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", TRUE, first);
1163 }
1164 
1165 /*
1166  * List window variables.
1167  */
1168     static void
list_win_vars(int * first)1169 list_win_vars(int *first)
1170 {
1171     list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", TRUE, first);
1172 }
1173 
1174 /*
1175  * List tab page variables.
1176  */
1177     static void
list_tab_vars(int * first)1178 list_tab_vars(int *first)
1179 {
1180     list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", TRUE, first);
1181 }
1182 
1183 /*
1184  * List variables in "arg".
1185  */
1186     static char_u *
list_arg_vars(exarg_T * eap,char_u * arg,int * first)1187 list_arg_vars(exarg_T *eap, char_u *arg, int *first)
1188 {
1189     int		error = FALSE;
1190     int		len;
1191     char_u	*name;
1192     char_u	*name_start;
1193     char_u	*arg_subsc;
1194     char_u	*tofree;
1195     typval_T    tv;
1196 
1197     while (!ends_excmd2(eap->cmd, arg) && !got_int)
1198     {
1199 	if (error || eap->skip)
1200 	{
1201 	    arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
1202 	    if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg))
1203 	    {
1204 		emsg_severe = TRUE;
1205 		if (!did_emsg)
1206 		    semsg(_(e_trailing_arg), arg);
1207 		break;
1208 	    }
1209 	}
1210 	else
1211 	{
1212 	    // get_name_len() takes care of expanding curly braces
1213 	    name_start = name = arg;
1214 	    len = get_name_len(&arg, &tofree, TRUE, TRUE);
1215 	    if (len <= 0)
1216 	    {
1217 		// This is mainly to keep test 49 working: when expanding
1218 		// curly braces fails overrule the exception error message.
1219 		if (len < 0 && !aborting())
1220 		{
1221 		    emsg_severe = TRUE;
1222 		    semsg(_(e_invarg2), arg);
1223 		    break;
1224 		}
1225 		error = TRUE;
1226 	    }
1227 	    else
1228 	    {
1229 		arg = skipwhite(arg);
1230 		if (tofree != NULL)
1231 		    name = tofree;
1232 		if (eval_variable(name, len, &tv, NULL,
1233 						     EVAL_VAR_VERBOSE) == FAIL)
1234 		    error = TRUE;
1235 		else
1236 		{
1237 		    // handle d.key, l[idx], f(expr)
1238 		    arg_subsc = arg;
1239 		    if (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, TRUE)
1240 								       == FAIL)
1241 			error = TRUE;
1242 		    else
1243 		    {
1244 			if (arg == arg_subsc && len == 2 && name[1] == ':')
1245 			{
1246 			    switch (*name)
1247 			    {
1248 				case 'g': list_glob_vars(first); break;
1249 				case 'b': list_buf_vars(first); break;
1250 				case 'w': list_win_vars(first); break;
1251 				case 't': list_tab_vars(first); break;
1252 				case 'v': list_vim_vars(first); break;
1253 				case 's': list_script_vars(first); break;
1254 				case 'l': list_func_vars(first); break;
1255 				default:
1256 					  semsg(_("E738: Can't list variables for %s"), name);
1257 			    }
1258 			}
1259 			else
1260 			{
1261 			    char_u	numbuf[NUMBUFLEN];
1262 			    char_u	*tf;
1263 			    int		c;
1264 			    char_u	*s;
1265 
1266 			    s = echo_string(&tv, &tf, numbuf, 0);
1267 			    c = *arg;
1268 			    *arg = NUL;
1269 			    list_one_var_a("",
1270 				    arg == arg_subsc ? name : name_start,
1271 				    tv.v_type,
1272 				    s == NULL ? (char_u *)"" : s,
1273 				    first);
1274 			    *arg = c;
1275 			    vim_free(tf);
1276 			}
1277 			clear_tv(&tv);
1278 		    }
1279 		}
1280 	    }
1281 
1282 	    vim_free(tofree);
1283 	}
1284 
1285 	arg = skipwhite(arg);
1286     }
1287 
1288     return arg;
1289 }
1290 
1291 /*
1292  * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1293  * Returns a pointer to the char just after the var name.
1294  * Returns NULL if there is an error.
1295  */
1296     static char_u *
ex_let_one(char_u * arg,typval_T * tv,int copy,int flags,char_u * endchars,char_u * op,int var_idx)1297 ex_let_one(
1298     char_u	*arg,		// points to variable name
1299     typval_T	*tv,		// value to assign to variable
1300     int		copy,		// copy value from "tv"
1301     int		flags,		// ASSIGN_CONST, ASSIGN_FINAL, etc.
1302     char_u	*endchars,	// valid chars after variable name  or NULL
1303     char_u	*op,		// "+", "-", "."  or NULL
1304     int		var_idx)	// variable index for "let [a, b] = list"
1305 {
1306     int		c1;
1307     char_u	*name;
1308     char_u	*p;
1309     char_u	*arg_end = NULL;
1310     int		len;
1311     int		opt_flags;
1312     char_u	*tofree = NULL;
1313 
1314     if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
1315 			&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
1316 				  && vim_strchr((char_u *)"$@&", *arg) != NULL)
1317     {
1318 	vim9_declare_error(arg);
1319 	return NULL;
1320     }
1321 
1322     // ":let $VAR = expr": Set environment variable.
1323     if (*arg == '$')
1324     {
1325 	if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
1326 					     && (flags & ASSIGN_FOR_LOOP) == 0)
1327 	{
1328 	    emsg(_("E996: Cannot lock an environment variable"));
1329 	    return NULL;
1330 	}
1331 
1332 	// Find the end of the name.
1333 	++arg;
1334 	name = arg;
1335 	len = get_env_len(&arg);
1336 	if (len == 0)
1337 	    semsg(_(e_invarg2), name - 1);
1338 	else
1339 	{
1340 	    if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
1341 		semsg(_(e_letwrong), op);
1342 	    else if (endchars != NULL
1343 			     && vim_strchr(endchars, *skipwhite(arg)) == NULL)
1344 		emsg(_(e_unexpected_characters_in_let));
1345 	    else if (!check_secure())
1346 	    {
1347 		c1 = name[len];
1348 		name[len] = NUL;
1349 		p = tv_get_string_chk(tv);
1350 		if (p != NULL && op != NULL && *op == '.')
1351 		{
1352 		    int	    mustfree = FALSE;
1353 		    char_u  *s = vim_getenv(name, &mustfree);
1354 
1355 		    if (s != NULL)
1356 		    {
1357 			p = tofree = concat_str(s, p);
1358 			if (mustfree)
1359 			    vim_free(s);
1360 		    }
1361 		}
1362 		if (p != NULL)
1363 		{
1364 		    vim_setenv_ext(name, p);
1365 		    arg_end = arg;
1366 		}
1367 		name[len] = c1;
1368 		vim_free(tofree);
1369 	    }
1370 	}
1371     }
1372 
1373     // ":let &option = expr": Set option value.
1374     // ":let &l:option = expr": Set local option value.
1375     // ":let &g:option = expr": Set global option value.
1376     // ":for &ts in range(8)": Set option value for for loop
1377     else if (*arg == '&')
1378     {
1379 	if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
1380 					     && (flags & ASSIGN_FOR_LOOP) == 0)
1381 	{
1382 	    emsg(_(e_const_option));
1383 	    return NULL;
1384 	}
1385 	// Find the end of the name.
1386 	p = find_option_end(&arg, &opt_flags);
1387 	if (p == NULL || (endchars != NULL
1388 			      && vim_strchr(endchars, *skipwhite(p)) == NULL))
1389 	    emsg(_(e_unexpected_characters_in_let));
1390 	else
1391 	{
1392 	    long	n = 0;
1393 	    getoption_T	opt_type;
1394 	    long	numval;
1395 	    char_u	*stringval = NULL;
1396 	    char_u	*s = NULL;
1397 	    int		failed = FALSE;
1398 
1399 	    c1 = *p;
1400 	    *p = NUL;
1401 
1402 	    opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
1403 	    if ((opt_type == gov_bool
1404 			|| opt_type == gov_number
1405 			|| opt_type == gov_hidden_bool
1406 			|| opt_type == gov_hidden_number)
1407 			     && (tv->v_type != VAR_STRING || !in_vim9script()))
1408 	    {
1409 		if (opt_type == gov_bool || opt_type == gov_hidden_bool)
1410 		    // bool, possibly hidden
1411 		    n = (long)tv_get_bool(tv);
1412 		else
1413 		    // number, possibly hidden
1414 		    n = (long)tv_get_number(tv);
1415 	    }
1416 
1417 	    // Avoid setting a string option to the text "v:false" or similar.
1418 	    // In Vim9 script also don't convert a number to string.
1419 	    if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL
1420 			     && (!in_vim9script() || tv->v_type != VAR_NUMBER))
1421 		s = tv_get_string_chk(tv);
1422 
1423 	    if (op != NULL && *op != '=')
1424 	    {
1425 		if (((opt_type == gov_bool || opt_type == gov_number)
1426 								 && *op == '.')
1427 			|| (opt_type == gov_string && *op != '.'))
1428 		{
1429 		    semsg(_(e_letwrong), op);
1430 		    failed = TRUE;  // don't set the value
1431 
1432 		}
1433 		else
1434 		{
1435 		    // number, in legacy script also bool
1436 		    if (opt_type == gov_number
1437 				 || (opt_type == gov_bool && !in_vim9script()))
1438 		    {
1439 			switch (*op)
1440 			{
1441 			    case '+': n = numval + n; break;
1442 			    case '-': n = numval - n; break;
1443 			    case '*': n = numval * n; break;
1444 			    case '/': n = (long)num_divide(numval, n,
1445 							       &failed); break;
1446 			    case '%': n = (long)num_modulus(numval, n,
1447 							       &failed); break;
1448 			}
1449 			s = NULL;
1450 		    }
1451 		    else if (opt_type == gov_string
1452 					     && stringval != NULL && s != NULL)
1453 		    {
1454 			// string
1455 			s = concat_str(stringval, s);
1456 			vim_free(stringval);
1457 			stringval = s;
1458 		    }
1459 		}
1460 	    }
1461 
1462 	    if (!failed)
1463 	    {
1464 		if (opt_type != gov_string || s != NULL)
1465 		{
1466 		    set_option_value(arg, n, s, opt_flags);
1467 		    arg_end = p;
1468 		}
1469 		else
1470 		    emsg(_(e_stringreq));
1471 	    }
1472 	    *p = c1;
1473 	    vim_free(stringval);
1474 	}
1475     }
1476 
1477     // ":let @r = expr": Set register contents.
1478     else if (*arg == '@')
1479     {
1480 	if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
1481 					     && (flags & ASSIGN_FOR_LOOP) == 0)
1482 	{
1483 	    emsg(_("E996: Cannot lock a register"));
1484 	    return NULL;
1485 	}
1486 	++arg;
1487 	if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
1488 	    semsg(_(e_letwrong), op);
1489 	else if (endchars != NULL
1490 			 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
1491 	    emsg(_(e_unexpected_characters_in_let));
1492 	else
1493 	{
1494 	    char_u	*ptofree = NULL;
1495 	    char_u	*s;
1496 
1497 	    p = tv_get_string_chk(tv);
1498 	    if (p != NULL && op != NULL && *op == '.')
1499 	    {
1500 		s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
1501 		if (s != NULL)
1502 		{
1503 		    p = ptofree = concat_str(s, p);
1504 		    vim_free(s);
1505 		}
1506 	    }
1507 	    if (p != NULL)
1508 	    {
1509 		write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
1510 		arg_end = arg + 1;
1511 	    }
1512 	    vim_free(ptofree);
1513 	}
1514     }
1515 
1516     // ":let var = expr": Set internal variable.
1517     // ":let var: type = expr": Set internal variable with type.
1518     // ":let {expr} = expr": Idem, name made with curly braces
1519     else if (eval_isnamec1(*arg) || *arg == '{')
1520     {
1521 	lval_T	lv;
1522 
1523 	p = get_lval(arg, tv, &lv, FALSE, FALSE,
1524 		(flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
1525 					   ? GLV_NO_DECL : 0, FNE_CHECK_START);
1526 	if (p != NULL && lv.ll_name != NULL)
1527 	{
1528 	    if (endchars != NULL && vim_strchr(endchars,
1529 					   *skipwhite(lv.ll_name_end)) == NULL)
1530 		emsg(_(e_unexpected_characters_in_let));
1531 	    else
1532 	    {
1533 		set_var_lval(&lv, p, tv, copy, flags, op, var_idx);
1534 		arg_end = lv.ll_name_end;
1535 	    }
1536 	}
1537 	clear_lval(&lv);
1538     }
1539 
1540     else
1541 	semsg(_(e_invarg2), arg);
1542 
1543     return arg_end;
1544 }
1545 
1546 /*
1547  * ":unlet[!] var1 ... " command.
1548  */
1549     void
ex_unlet(exarg_T * eap)1550 ex_unlet(exarg_T *eap)
1551 {
1552     ex_unletlock(eap, eap->arg, 0, 0, do_unlet_var, NULL);
1553 }
1554 
1555 /*
1556  * ":lockvar" and ":unlockvar" commands
1557  */
1558     void
ex_lockvar(exarg_T * eap)1559 ex_lockvar(exarg_T *eap)
1560 {
1561     char_u	*arg = eap->arg;
1562     int		deep = 2;
1563 
1564     if (eap->forceit)
1565 	deep = -1;
1566     else if (vim_isdigit(*arg))
1567     {
1568 	deep = getdigits(&arg);
1569 	arg = skipwhite(arg);
1570     }
1571 
1572     ex_unletlock(eap, arg, deep, 0, do_lock_var, NULL);
1573 }
1574 
1575 /*
1576  * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
1577  * Also used for Vim9 script.  "callback" is invoked as:
1578  *	callback(&lv, name_end, eap, deep, cookie)
1579  */
1580     void
ex_unletlock(exarg_T * eap,char_u * argstart,int deep,int glv_flags,int (* callback)(lval_T *,char_u *,exarg_T *,int,void *),void * cookie)1581 ex_unletlock(
1582     exarg_T	*eap,
1583     char_u	*argstart,
1584     int		deep,
1585     int		glv_flags,
1586     int		(*callback)(lval_T *, char_u *, exarg_T *, int, void *),
1587     void	*cookie)
1588 {
1589     char_u	*arg = argstart;
1590     char_u	*name_end;
1591     int		error = FALSE;
1592     lval_T	lv;
1593 
1594     do
1595     {
1596 	if (*arg == '$')
1597 	{
1598 	    lv.ll_name = arg;
1599 	    lv.ll_tv = NULL;
1600 	    ++arg;
1601 	    if (get_env_len(&arg) == 0)
1602 	    {
1603 		semsg(_(e_invarg2), arg - 1);
1604 		return;
1605 	    }
1606 	    if (!error && !eap->skip
1607 			      && callback(&lv, arg, eap, deep, cookie) == FAIL)
1608 		error = TRUE;
1609 	    name_end = arg;
1610 	}
1611 	else
1612 	{
1613 	    // Parse the name and find the end.
1614 	    name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error,
1615 				     glv_flags | GLV_NO_DECL, FNE_CHECK_START);
1616 	    if (lv.ll_name == NULL)
1617 		error = TRUE;	    // error but continue parsing
1618 	    if (name_end == NULL || (!VIM_ISWHITE(*name_end)
1619 						    && !ends_excmd(*name_end)))
1620 	    {
1621 		if (name_end != NULL)
1622 		{
1623 		    emsg_severe = TRUE;
1624 		    semsg(_(e_trailing_arg), name_end);
1625 		}
1626 		if (!(eap->skip || error))
1627 		    clear_lval(&lv);
1628 		break;
1629 	    }
1630 
1631 	    if (!error && !eap->skip
1632 			 && callback(&lv, name_end, eap, deep, cookie) == FAIL)
1633 		error = TRUE;
1634 
1635 	    if (!eap->skip)
1636 		clear_lval(&lv);
1637 	}
1638 
1639 	arg = skipwhite(name_end);
1640     } while (!ends_excmd2(name_end, arg));
1641 
1642     set_nextcmd(eap, arg);
1643 }
1644 
1645     static int
do_unlet_var(lval_T * lp,char_u * name_end,exarg_T * eap,int deep UNUSED,void * cookie UNUSED)1646 do_unlet_var(
1647     lval_T	*lp,
1648     char_u	*name_end,
1649     exarg_T	*eap,
1650     int		deep UNUSED,
1651     void	*cookie UNUSED)
1652 {
1653     int		forceit = eap->forceit;
1654     int		ret = OK;
1655     int		cc;
1656 
1657     if (lp->ll_tv == NULL)
1658     {
1659 	cc = *name_end;
1660 	*name_end = NUL;
1661 
1662 	// Environment variable, normal name or expanded name.
1663 	if (*lp->ll_name == '$')
1664 	    vim_unsetenv(lp->ll_name + 1);
1665 	else if (do_unlet(lp->ll_name, forceit) == FAIL)
1666 	    ret = FAIL;
1667 	*name_end = cc;
1668     }
1669     else if ((lp->ll_list != NULL
1670 		 && value_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
1671 	    || (lp->ll_dict != NULL
1672 		&& value_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
1673 	return FAIL;
1674     else if (lp->ll_range)
1675     {
1676 	if (list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_name, lp->ll_n1,
1677 					   !lp->ll_empty2, lp->ll_n2) == FAIL)
1678 	    return FAIL;
1679     }
1680     else
1681     {
1682 	if (lp->ll_list != NULL)
1683 	    // unlet a List item.
1684 	    listitem_remove(lp->ll_list, lp->ll_li);
1685 	else
1686 	    // unlet a Dictionary item.
1687 	    dictitem_remove(lp->ll_dict, lp->ll_di);
1688     }
1689 
1690     return ret;
1691 }
1692 
1693 /*
1694  * Unlet one item or a range of items from a list.
1695  * Return OK or FAIL.
1696  */
1697     int
list_unlet_range(list_T * l,listitem_T * li_first,char_u * name,long n1_arg,int has_n2,long n2)1698 list_unlet_range(
1699 	list_T	    *l,
1700 	listitem_T  *li_first,
1701 	char_u	    *name,
1702 	long	    n1_arg,
1703 	int	    has_n2,
1704 	long	    n2)
1705 {
1706     listitem_T  *li = li_first;
1707     int		n1 = n1_arg;
1708 
1709     while (li != NULL && (!has_n2 || n2 >= n1))
1710     {
1711 	if (value_check_lock(li->li_tv.v_lock, name, FALSE))
1712 	    return FAIL;
1713 	li = li->li_next;
1714 	++n1;
1715     }
1716 
1717     // Delete a range of List items.
1718     li = li_first;
1719     n1 = n1_arg;
1720     while (li != NULL && (!has_n2 || n2 >= n1))
1721     {
1722 	listitem_T *next = li->li_next;
1723 
1724 	listitem_remove(l, li);
1725 	li = next;
1726 	++n1;
1727     }
1728     return OK;
1729 }
1730 /*
1731  * "unlet" a variable.  Return OK if it existed, FAIL if not.
1732  * When "forceit" is TRUE don't complain if the variable doesn't exist.
1733  */
1734     int
do_unlet(char_u * name,int forceit)1735 do_unlet(char_u *name, int forceit)
1736 {
1737     hashtab_T	*ht;
1738     hashitem_T	*hi;
1739     char_u	*varname;
1740     dict_T	*d;
1741     dictitem_T	*di;
1742 
1743     // can't :unlet a script variable in Vim9 script
1744     if (in_vim9script() && check_vim9_unlet(name) == FAIL)
1745 	return FAIL;
1746 
1747     ht = find_var_ht(name, &varname);
1748 
1749     // can't :unlet a script variable in Vim9 script from a function
1750     if (ht == get_script_local_ht()
1751 	    && SCRIPT_ID_VALID(current_sctx.sc_sid)
1752 	    && SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
1753 							 == SCRIPT_VERSION_VIM9
1754 	    && check_vim9_unlet(name) == FAIL)
1755 	return FAIL;
1756 
1757     if (ht != NULL && *varname != NUL)
1758     {
1759 	d = get_current_funccal_dict(ht);
1760 	if (d == NULL)
1761 	{
1762 	    if (ht == &globvarht)
1763 		d = &globvardict;
1764 	    else if (ht == &compat_hashtab)
1765 		d = &vimvardict;
1766 	    else
1767 	    {
1768 		di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
1769 		d = di == NULL ? NULL : di->di_tv.vval.v_dict;
1770 	    }
1771 	    if (d == NULL)
1772 	    {
1773 		internal_error("do_unlet()");
1774 		return FAIL;
1775 	    }
1776 	}
1777 	hi = hash_find(ht, varname);
1778 	if (HASHITEM_EMPTY(hi))
1779 	    hi = find_hi_in_scoped_ht(name, &ht);
1780 	if (hi != NULL && !HASHITEM_EMPTY(hi))
1781 	{
1782 	    di = HI2DI(hi);
1783 	    if (var_check_fixed(di->di_flags, name, FALSE)
1784 		    || var_check_ro(di->di_flags, name, FALSE)
1785 		    || value_check_lock(d->dv_lock, name, FALSE))
1786 		return FAIL;
1787 
1788 	    delete_var(ht, hi);
1789 	    return OK;
1790 	}
1791     }
1792     if (forceit)
1793 	return OK;
1794     semsg(_("E108: No such variable: \"%s\""), name);
1795     return FAIL;
1796 }
1797 
1798 /*
1799  * Lock or unlock variable indicated by "lp".
1800  * "deep" is the levels to go (-1 for unlimited);
1801  * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
1802  */
1803     static int
do_lock_var(lval_T * lp,char_u * name_end,exarg_T * eap,int deep,void * cookie UNUSED)1804 do_lock_var(
1805     lval_T	*lp,
1806     char_u	*name_end,
1807     exarg_T	*eap,
1808     int		deep,
1809     void	*cookie UNUSED)
1810 {
1811     int		lock = eap->cmdidx == CMD_lockvar;
1812     int		ret = OK;
1813     int		cc;
1814     dictitem_T	*di;
1815 
1816     if (lp->ll_tv == NULL)
1817     {
1818 	cc = *name_end;
1819 	*name_end = NUL;
1820 	if (*lp->ll_name == '$')
1821 	{
1822 	    semsg(_(e_lock_unlock), lp->ll_name);
1823 	    ret = FAIL;
1824 	}
1825 	else
1826 	{
1827 	    // Normal name or expanded name.
1828 	    di = find_var(lp->ll_name, NULL, TRUE);
1829 	    if (di == NULL)
1830 		ret = FAIL;
1831 	    else if ((di->di_flags & DI_FLAGS_FIX)
1832 			    && di->di_tv.v_type != VAR_DICT
1833 			    && di->di_tv.v_type != VAR_LIST)
1834 	    {
1835 		// For historic reasons this error is not given for a list or
1836 		// dict.  E.g., the b: dict could be locked/unlocked.
1837 		semsg(_(e_lock_unlock), lp->ll_name);
1838 		ret = FAIL;
1839 	    }
1840 	    else
1841 	    {
1842 		if (lock)
1843 		    di->di_flags |= DI_FLAGS_LOCK;
1844 		else
1845 		    di->di_flags &= ~DI_FLAGS_LOCK;
1846 		if (deep != 0)
1847 		    item_lock(&di->di_tv, deep, lock, FALSE);
1848 	    }
1849 	}
1850 	*name_end = cc;
1851     }
1852     else if (deep == 0)
1853     {
1854 	// nothing to do
1855     }
1856     else if (lp->ll_range)
1857     {
1858 	listitem_T    *li = lp->ll_li;
1859 
1860 	// (un)lock a range of List items.
1861 	while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
1862 	{
1863 	    item_lock(&li->li_tv, deep, lock, FALSE);
1864 	    li = li->li_next;
1865 	    ++lp->ll_n1;
1866 	}
1867     }
1868     else if (lp->ll_list != NULL)
1869 	// (un)lock a List item.
1870 	item_lock(&lp->ll_li->li_tv, deep, lock, FALSE);
1871     else
1872 	// (un)lock a Dictionary item.
1873 	item_lock(&lp->ll_di->di_tv, deep, lock, FALSE);
1874 
1875     return ret;
1876 }
1877 
1878 /*
1879  * Lock or unlock an item.  "deep" is nr of levels to go.
1880  * When "check_refcount" is TRUE do not lock a list or dict with a reference
1881  * count larger than 1.
1882  */
1883     void
item_lock(typval_T * tv,int deep,int lock,int check_refcount)1884 item_lock(typval_T *tv, int deep, int lock, int check_refcount)
1885 {
1886     static int	recurse = 0;
1887     list_T	*l;
1888     listitem_T	*li;
1889     dict_T	*d;
1890     blob_T	*b;
1891     hashitem_T	*hi;
1892     int		todo;
1893 
1894     if (recurse >= DICT_MAXNEST)
1895     {
1896 	emsg(_("E743: variable nested too deep for (un)lock"));
1897 	return;
1898     }
1899     if (deep == 0)
1900 	return;
1901     ++recurse;
1902 
1903     // lock/unlock the item itself
1904     if (lock)
1905 	tv->v_lock |= VAR_LOCKED;
1906     else
1907 	tv->v_lock &= ~VAR_LOCKED;
1908 
1909     switch (tv->v_type)
1910     {
1911 	case VAR_UNKNOWN:
1912 	case VAR_ANY:
1913 	case VAR_VOID:
1914 	case VAR_NUMBER:
1915 	case VAR_BOOL:
1916 	case VAR_STRING:
1917 	case VAR_FUNC:
1918 	case VAR_PARTIAL:
1919 	case VAR_FLOAT:
1920 	case VAR_SPECIAL:
1921 	case VAR_JOB:
1922 	case VAR_CHANNEL:
1923 	case VAR_INSTR:
1924 	    break;
1925 
1926 	case VAR_BLOB:
1927 	    if ((b = tv->vval.v_blob) != NULL
1928 				    && !(check_refcount && b->bv_refcount > 1))
1929 	    {
1930 		if (lock)
1931 		    b->bv_lock |= VAR_LOCKED;
1932 		else
1933 		    b->bv_lock &= ~VAR_LOCKED;
1934 	    }
1935 	    break;
1936 	case VAR_LIST:
1937 	    if ((l = tv->vval.v_list) != NULL
1938 				    && !(check_refcount && l->lv_refcount > 1))
1939 	    {
1940 		if (lock)
1941 		    l->lv_lock |= VAR_LOCKED;
1942 		else
1943 		    l->lv_lock &= ~VAR_LOCKED;
1944 		if ((deep < 0 || deep > 1) && l->lv_first != &range_list_item)
1945 		    // recursive: lock/unlock the items the List contains
1946 		    FOR_ALL_LIST_ITEMS(l, li)
1947 			item_lock(&li->li_tv, deep - 1, lock, check_refcount);
1948 	    }
1949 	    break;
1950 	case VAR_DICT:
1951 	    if ((d = tv->vval.v_dict) != NULL
1952 				    && !(check_refcount && d->dv_refcount > 1))
1953 	    {
1954 		if (lock)
1955 		    d->dv_lock |= VAR_LOCKED;
1956 		else
1957 		    d->dv_lock &= ~VAR_LOCKED;
1958 		if (deep < 0 || deep > 1)
1959 		{
1960 		    // recursive: lock/unlock the items the List contains
1961 		    todo = (int)d->dv_hashtab.ht_used;
1962 		    for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
1963 		    {
1964 			if (!HASHITEM_EMPTY(hi))
1965 			{
1966 			    --todo;
1967 			    item_lock(&HI2DI(hi)->di_tv, deep - 1, lock,
1968 							       check_refcount);
1969 			}
1970 		    }
1971 		}
1972 	    }
1973     }
1974     --recurse;
1975 }
1976 
1977 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
1978 /*
1979  * Delete all "menutrans_" variables.
1980  */
1981     void
del_menutrans_vars(void)1982 del_menutrans_vars(void)
1983 {
1984     hashitem_T	*hi;
1985     int		todo;
1986 
1987     hash_lock(&globvarht);
1988     todo = (int)globvarht.ht_used;
1989     for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
1990     {
1991 	if (!HASHITEM_EMPTY(hi))
1992 	{
1993 	    --todo;
1994 	    if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
1995 		delete_var(&globvarht, hi);
1996 	}
1997     }
1998     hash_unlock(&globvarht);
1999 }
2000 #endif
2001 
2002 /*
2003  * Local string buffer for the next two functions to store a variable name
2004  * with its prefix. Allocated in cat_prefix_varname(), freed later in
2005  * get_user_var_name().
2006  */
2007 
2008 static char_u	*varnamebuf = NULL;
2009 static int	varnamebuflen = 0;
2010 
2011 /*
2012  * Function to concatenate a prefix and a variable name.
2013  */
2014     char_u *
cat_prefix_varname(int prefix,char_u * name)2015 cat_prefix_varname(int prefix, char_u *name)
2016 {
2017     int		len;
2018 
2019     len = (int)STRLEN(name) + 3;
2020     if (len > varnamebuflen)
2021     {
2022 	vim_free(varnamebuf);
2023 	len += 10;			// some additional space
2024 	varnamebuf = alloc(len);
2025 	if (varnamebuf == NULL)
2026 	{
2027 	    varnamebuflen = 0;
2028 	    return NULL;
2029 	}
2030 	varnamebuflen = len;
2031     }
2032     *varnamebuf = prefix;
2033     varnamebuf[1] = ':';
2034     STRCPY(varnamebuf + 2, name);
2035     return varnamebuf;
2036 }
2037 
2038 /*
2039  * Function given to ExpandGeneric() to obtain the list of user defined
2040  * (global/buffer/window/built-in) variable names.
2041  */
2042     char_u *
get_user_var_name(expand_T * xp,int idx)2043 get_user_var_name(expand_T *xp, int idx)
2044 {
2045     static long_u	gdone;
2046     static long_u	bdone;
2047     static long_u	wdone;
2048     static long_u	tdone;
2049     static int		vidx;
2050     static hashitem_T	*hi;
2051     hashtab_T		*ht;
2052 
2053     if (idx == 0)
2054     {
2055 	gdone = bdone = wdone = vidx = 0;
2056 	tdone = 0;
2057     }
2058 
2059     // Global variables
2060     if (gdone < globvarht.ht_used)
2061     {
2062 	if (gdone++ == 0)
2063 	    hi = globvarht.ht_array;
2064 	else
2065 	    ++hi;
2066 	while (HASHITEM_EMPTY(hi))
2067 	    ++hi;
2068 	if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
2069 	    return cat_prefix_varname('g', hi->hi_key);
2070 	return hi->hi_key;
2071     }
2072 
2073     // b: variables
2074     ht =
2075 #ifdef FEAT_CMDWIN
2076 	// In cmdwin, the alternative buffer should be used.
2077 	is_in_cmdwin() ? &prevwin->w_buffer->b_vars->dv_hashtab :
2078 #endif
2079 	&curbuf->b_vars->dv_hashtab;
2080     if (bdone < ht->ht_used)
2081     {
2082 	if (bdone++ == 0)
2083 	    hi = ht->ht_array;
2084 	else
2085 	    ++hi;
2086 	while (HASHITEM_EMPTY(hi))
2087 	    ++hi;
2088 	return cat_prefix_varname('b', hi->hi_key);
2089     }
2090 
2091     // w: variables
2092     ht =
2093 #ifdef FEAT_CMDWIN
2094 	// In cmdwin, the alternative window should be used.
2095 	is_in_cmdwin() ? &prevwin->w_vars->dv_hashtab :
2096 #endif
2097 	&curwin->w_vars->dv_hashtab;
2098     if (wdone < ht->ht_used)
2099     {
2100 	if (wdone++ == 0)
2101 	    hi = ht->ht_array;
2102 	else
2103 	    ++hi;
2104 	while (HASHITEM_EMPTY(hi))
2105 	    ++hi;
2106 	return cat_prefix_varname('w', hi->hi_key);
2107     }
2108 
2109     // t: variables
2110     ht = &curtab->tp_vars->dv_hashtab;
2111     if (tdone < ht->ht_used)
2112     {
2113 	if (tdone++ == 0)
2114 	    hi = ht->ht_array;
2115 	else
2116 	    ++hi;
2117 	while (HASHITEM_EMPTY(hi))
2118 	    ++hi;
2119 	return cat_prefix_varname('t', hi->hi_key);
2120     }
2121 
2122     // v: variables
2123     if (vidx < VV_LEN)
2124 	return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
2125 
2126     VIM_CLEAR(varnamebuf);
2127     varnamebuflen = 0;
2128     return NULL;
2129 }
2130 
2131     char *
get_var_special_name(int nr)2132 get_var_special_name(int nr)
2133 {
2134     switch (nr)
2135     {
2136 	case VVAL_FALSE: return in_vim9script() ? "false" : "v:false";
2137 	case VVAL_TRUE:  return in_vim9script() ? "true" : "v:true";
2138 	case VVAL_NULL:  return in_vim9script() ? "null" : "v:null";
2139 	case VVAL_NONE:  return "v:none";
2140     }
2141     internal_error("get_var_special_name()");
2142     return "42";
2143 }
2144 
2145 /*
2146  * Returns the global variable dictionary
2147  */
2148     dict_T *
get_globvar_dict(void)2149 get_globvar_dict(void)
2150 {
2151     return &globvardict;
2152 }
2153 
2154 /*
2155  * Returns the global variable hash table
2156  */
2157     hashtab_T *
get_globvar_ht(void)2158 get_globvar_ht(void)
2159 {
2160     return &globvarht;
2161 }
2162 
2163 /*
2164  * Returns the v: variable dictionary
2165  */
2166     dict_T *
get_vimvar_dict(void)2167 get_vimvar_dict(void)
2168 {
2169     return &vimvardict;
2170 }
2171 
2172 /*
2173  * Returns the index of a v:variable.  Negative if not found.
2174  * Returns DI_ flags in "di_flags".
2175  */
2176     int
find_vim_var(char_u * name,int * di_flags)2177 find_vim_var(char_u *name, int *di_flags)
2178 {
2179     dictitem_T	    *di = find_var_in_ht(&vimvarht, 0, name, TRUE);
2180     struct vimvar   *vv;
2181 
2182     if (di == NULL)
2183 	return -1;
2184     *di_flags = di->di_flags;
2185     vv = (struct vimvar *)((char *)di - offsetof(vimvar_T, vv_di));
2186     return (int)(vv - vimvars);
2187 }
2188 
2189 
2190 /*
2191  * Set type of v: variable to "type".
2192  */
2193     void
set_vim_var_type(int idx,vartype_T type)2194 set_vim_var_type(int idx, vartype_T type)
2195 {
2196     vimvars[idx].vv_type = type;
2197 }
2198 
2199 /*
2200  * Set number v: variable to "val".
2201  * Note that this does not set the type, use set_vim_var_type() for that.
2202  */
2203     void
set_vim_var_nr(int idx,varnumber_T val)2204 set_vim_var_nr(int idx, varnumber_T val)
2205 {
2206     vimvars[idx].vv_nr = val;
2207 }
2208 
2209     char *
get_vim_var_name(int idx)2210 get_vim_var_name(int idx)
2211 {
2212     return vimvars[idx].vv_name;
2213 }
2214 
2215 /*
2216  * Get typval_T v: variable value.
2217  */
2218     typval_T *
get_vim_var_tv(int idx)2219 get_vim_var_tv(int idx)
2220 {
2221     return &vimvars[idx].vv_tv;
2222 }
2223 
2224 /*
2225  * Set v: variable to "tv".  Only accepts the same type.
2226  * Takes over the value of "tv".
2227  */
2228     int
set_vim_var_tv(int idx,typval_T * tv)2229 set_vim_var_tv(int idx, typval_T *tv)
2230 {
2231     if (vimvars[idx].vv_type != tv->v_type)
2232     {
2233 	emsg(_(e_type_mismatch_for_v_variable));
2234 	clear_tv(tv);
2235 	return FAIL;
2236     }
2237     // VV_RO is also checked when compiling, but let's check here as well.
2238     if (vimvars[idx].vv_flags & VV_RO)
2239     {
2240 	semsg(_(e_cannot_change_readonly_variable_str), vimvars[idx].vv_name);
2241 	return FAIL;
2242     }
2243     if (sandbox && (vimvars[idx].vv_flags & VV_RO_SBX))
2244     {
2245 	semsg(_(e_readonlysbx), vimvars[idx].vv_name);
2246 	return FAIL;
2247     }
2248     clear_tv(&vimvars[idx].vv_di.di_tv);
2249     vimvars[idx].vv_di.di_tv = *tv;
2250     return OK;
2251 }
2252 
2253 /*
2254  * Get number v: variable value.
2255  */
2256     varnumber_T
get_vim_var_nr(int idx)2257 get_vim_var_nr(int idx)
2258 {
2259     return vimvars[idx].vv_nr;
2260 }
2261 
2262 /*
2263  * Get string v: variable value.  Uses a static buffer, can only be used once.
2264  * If the String variable has never been set, return an empty string.
2265  * Never returns NULL;
2266  */
2267     char_u *
get_vim_var_str(int idx)2268 get_vim_var_str(int idx)
2269 {
2270     return tv_get_string(&vimvars[idx].vv_tv);
2271 }
2272 
2273 /*
2274  * Get List v: variable value.  Caller must take care of reference count when
2275  * needed.
2276  */
2277     list_T *
get_vim_var_list(int idx)2278 get_vim_var_list(int idx)
2279 {
2280     return vimvars[idx].vv_list;
2281 }
2282 
2283 /*
2284  * Get Dict v: variable value.  Caller must take care of reference count when
2285  * needed.
2286  */
2287     dict_T *
get_vim_var_dict(int idx)2288 get_vim_var_dict(int idx)
2289 {
2290     return vimvars[idx].vv_dict;
2291 }
2292 
2293 /*
2294  * Set v:char to character "c".
2295  */
2296     void
set_vim_var_char(int c)2297 set_vim_var_char(int c)
2298 {
2299     char_u	buf[MB_MAXBYTES + 1];
2300 
2301     if (has_mbyte)
2302 	buf[(*mb_char2bytes)(c, buf)] = NUL;
2303     else
2304     {
2305 	buf[0] = c;
2306 	buf[1] = NUL;
2307     }
2308     set_vim_var_string(VV_CHAR, buf, -1);
2309 }
2310 
2311 /*
2312  * Set v:count to "count" and v:count1 to "count1".
2313  * When "set_prevcount" is TRUE first set v:prevcount from v:count.
2314  */
2315     void
set_vcount(long count,long count1,int set_prevcount)2316 set_vcount(
2317     long	count,
2318     long	count1,
2319     int		set_prevcount)
2320 {
2321     if (set_prevcount)
2322 	vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
2323     vimvars[VV_COUNT].vv_nr = count;
2324     vimvars[VV_COUNT1].vv_nr = count1;
2325 }
2326 
2327 /*
2328  * Save variables that might be changed as a side effect.  Used when executing
2329  * a timer callback.
2330  */
2331     void
save_vimvars(vimvars_save_T * vvsave)2332 save_vimvars(vimvars_save_T *vvsave)
2333 {
2334     vvsave->vv_prevcount = vimvars[VV_PREVCOUNT].vv_nr;
2335     vvsave->vv_count = vimvars[VV_COUNT].vv_nr;
2336     vvsave->vv_count1 = vimvars[VV_COUNT1].vv_nr;
2337 }
2338 
2339 /*
2340  * Restore variables saved by save_vimvars().
2341  */
2342     void
restore_vimvars(vimvars_save_T * vvsave)2343 restore_vimvars(vimvars_save_T *vvsave)
2344 {
2345     vimvars[VV_PREVCOUNT].vv_nr = vvsave->vv_prevcount;
2346     vimvars[VV_COUNT].vv_nr = vvsave->vv_count;
2347     vimvars[VV_COUNT1].vv_nr = vvsave->vv_count1;
2348 }
2349 
2350 /*
2351  * Set string v: variable to a copy of "val". If 'copy' is FALSE, then set the
2352  * value.
2353  */
2354     void
set_vim_var_string(int idx,char_u * val,int len)2355 set_vim_var_string(
2356     int		idx,
2357     char_u	*val,
2358     int		len)	    // length of "val" to use or -1 (whole string)
2359 {
2360     clear_tv(&vimvars[idx].vv_di.di_tv);
2361     vimvars[idx].vv_type = VAR_STRING;
2362     if (val == NULL)
2363 	vimvars[idx].vv_str = NULL;
2364     else if (len == -1)
2365 	vimvars[idx].vv_str = vim_strsave(val);
2366     else
2367 	vimvars[idx].vv_str = vim_strnsave(val, len);
2368 }
2369 
2370 /*
2371  * Set List v: variable to "val".
2372  */
2373     void
set_vim_var_list(int idx,list_T * val)2374 set_vim_var_list(int idx, list_T *val)
2375 {
2376     clear_tv(&vimvars[idx].vv_di.di_tv);
2377     vimvars[idx].vv_type = VAR_LIST;
2378     vimvars[idx].vv_list = val;
2379     if (val != NULL)
2380 	++val->lv_refcount;
2381 }
2382 
2383 /*
2384  * Set Dictionary v: variable to "val".
2385  */
2386     void
set_vim_var_dict(int idx,dict_T * val)2387 set_vim_var_dict(int idx, dict_T *val)
2388 {
2389     clear_tv(&vimvars[idx].vv_di.di_tv);
2390     vimvars[idx].vv_type = VAR_DICT;
2391     vimvars[idx].vv_dict = val;
2392     if (val != NULL)
2393     {
2394 	++val->dv_refcount;
2395 	dict_set_items_ro(val);
2396     }
2397 }
2398 
2399 /*
2400  * Set the v:argv list.
2401  */
2402     void
set_argv_var(char ** argv,int argc)2403 set_argv_var(char **argv, int argc)
2404 {
2405     list_T	*l = list_alloc();
2406     int		i;
2407 
2408     if (l == NULL)
2409 	getout(1);
2410     l->lv_lock = VAR_FIXED;
2411     for (i = 0; i < argc; ++i)
2412     {
2413 	if (list_append_string(l, (char_u *)argv[i], -1) == FAIL)
2414 	    getout(1);
2415 	l->lv_u.mat.lv_last->li_tv.v_lock = VAR_FIXED;
2416     }
2417     set_vim_var_list(VV_ARGV, l);
2418 }
2419 
2420 /*
2421  * Reset v:register, taking the 'clipboard' setting into account.
2422  */
2423     void
reset_reg_var(void)2424 reset_reg_var(void)
2425 {
2426     int regname = 0;
2427 
2428     // Adjust the register according to 'clipboard', so that when
2429     // "unnamed" is present it becomes '*' or '+' instead of '"'.
2430 #ifdef FEAT_CLIPBOARD
2431     adjust_clip_reg(&regname);
2432 #endif
2433     set_reg_var(regname);
2434 }
2435 
2436 /*
2437  * Set v:register if needed.
2438  */
2439     void
set_reg_var(int c)2440 set_reg_var(int c)
2441 {
2442     char_u	regname;
2443 
2444     if (c == 0 || c == ' ')
2445 	regname = '"';
2446     else
2447 	regname = c;
2448     // Avoid free/alloc when the value is already right.
2449     if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
2450 	set_vim_var_string(VV_REG, &regname, 1);
2451 }
2452 
2453 /*
2454  * Get or set v:exception.  If "oldval" == NULL, return the current value.
2455  * Otherwise, restore the value to "oldval" and return NULL.
2456  * Must always be called in pairs to save and restore v:exception!  Does not
2457  * take care of memory allocations.
2458  */
2459     char_u *
v_exception(char_u * oldval)2460 v_exception(char_u *oldval)
2461 {
2462     if (oldval == NULL)
2463 	return vimvars[VV_EXCEPTION].vv_str;
2464 
2465     vimvars[VV_EXCEPTION].vv_str = oldval;
2466     return NULL;
2467 }
2468 
2469 /*
2470  * Get or set v:throwpoint.  If "oldval" == NULL, return the current value.
2471  * Otherwise, restore the value to "oldval" and return NULL.
2472  * Must always be called in pairs to save and restore v:throwpoint!  Does not
2473  * take care of memory allocations.
2474  */
2475     char_u *
v_throwpoint(char_u * oldval)2476 v_throwpoint(char_u *oldval)
2477 {
2478     if (oldval == NULL)
2479 	return vimvars[VV_THROWPOINT].vv_str;
2480 
2481     vimvars[VV_THROWPOINT].vv_str = oldval;
2482     return NULL;
2483 }
2484 
2485 /*
2486  * Set v:cmdarg.
2487  * If "eap" != NULL, use "eap" to generate the value and return the old value.
2488  * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
2489  * Must always be called in pairs!
2490  */
2491     char_u *
set_cmdarg(exarg_T * eap,char_u * oldarg)2492 set_cmdarg(exarg_T *eap, char_u *oldarg)
2493 {
2494     char_u	*oldval;
2495     char_u	*newval;
2496     unsigned	len;
2497 
2498     oldval = vimvars[VV_CMDARG].vv_str;
2499     if (eap == NULL)
2500     {
2501 	vim_free(oldval);
2502 	vimvars[VV_CMDARG].vv_str = oldarg;
2503 	return NULL;
2504     }
2505 
2506     if (eap->force_bin == FORCE_BIN)
2507 	len = 6;
2508     else if (eap->force_bin == FORCE_NOBIN)
2509 	len = 8;
2510     else
2511 	len = 0;
2512 
2513     if (eap->read_edit)
2514 	len += 7;
2515 
2516     if (eap->force_ff != 0)
2517 	len += 10; // " ++ff=unix"
2518     if (eap->force_enc != 0)
2519 	len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
2520     if (eap->bad_char != 0)
2521 	len += 7 + 4;  // " ++bad=" + "keep" or "drop"
2522 
2523     newval = alloc(len + 1);
2524     if (newval == NULL)
2525 	return NULL;
2526 
2527     if (eap->force_bin == FORCE_BIN)
2528 	sprintf((char *)newval, " ++bin");
2529     else if (eap->force_bin == FORCE_NOBIN)
2530 	sprintf((char *)newval, " ++nobin");
2531     else
2532 	*newval = NUL;
2533 
2534     if (eap->read_edit)
2535 	STRCAT(newval, " ++edit");
2536 
2537     if (eap->force_ff != 0)
2538 	sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
2539 						eap->force_ff == 'u' ? "unix"
2540 						: eap->force_ff == 'd' ? "dos"
2541 						: "mac");
2542     if (eap->force_enc != 0)
2543 	sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
2544 					       eap->cmd + eap->force_enc);
2545     if (eap->bad_char == BAD_KEEP)
2546 	STRCPY(newval + STRLEN(newval), " ++bad=keep");
2547     else if (eap->bad_char == BAD_DROP)
2548 	STRCPY(newval + STRLEN(newval), " ++bad=drop");
2549     else if (eap->bad_char != 0)
2550 	sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
2551     vimvars[VV_CMDARG].vv_str = newval;
2552     return oldval;
2553 }
2554 
2555 /*
2556  * Get the value of internal variable "name".
2557  * If "flags" has EVAL_VAR_IMPORT may return a VAR_ANY with v_number set to the
2558  * imported script ID.
2559  * Return OK or FAIL.  If OK is returned "rettv" must be cleared.
2560  */
2561     int
eval_variable(char_u * name,int len,typval_T * rettv,dictitem_T ** dip,int flags)2562 eval_variable(
2563     char_u	*name,
2564     int		len,		// length of "name"
2565     typval_T	*rettv,		// NULL when only checking existence
2566     dictitem_T	**dip,		// non-NULL when typval's dict item is needed
2567     int		flags)		// EVAL_VAR_ flags
2568 {
2569     int		ret = OK;
2570     typval_T	*tv = NULL;
2571     int		found = FALSE;
2572     hashtab_T	*ht = NULL;
2573     int		cc;
2574     type_T	*type = NULL;
2575 
2576     // truncate the name, so that we can use strcmp()
2577     cc = name[len];
2578     name[len] = NUL;
2579 
2580     // Check for local variable when debugging.
2581     if ((tv = lookup_debug_var(name)) == NULL)
2582     {
2583 	// Check for user-defined variables.
2584 	dictitem_T	*v = find_var(name, &ht, flags & EVAL_VAR_NOAUTOLOAD);
2585 
2586 	if (v != NULL)
2587 	{
2588 	    tv = &v->di_tv;
2589 	    if (dip != NULL)
2590 		*dip = v;
2591 	}
2592 	else
2593 	    ht = NULL;
2594     }
2595 
2596     if (tv == NULL && (in_vim9script() || STRNCMP(name, "s:", 2) == 0))
2597     {
2598 	imported_T  *import;
2599 	char_u	    *p = STRNCMP(name, "s:", 2) == 0 ? name + 2 : name;
2600 
2601 	import = find_imported(p, 0, NULL);
2602 
2603 	// imported variable from another script
2604 	if (import != NULL)
2605 	{
2606 	    if (import->imp_funcname != NULL)
2607 	    {
2608 		found = TRUE;
2609 		if (rettv != NULL)
2610 		{
2611 		    rettv->v_type = VAR_FUNC;
2612 		    rettv->vval.v_string = vim_strsave(import->imp_funcname);
2613 		}
2614 	    }
2615 	    else if (import->imp_flags & IMP_FLAGS_STAR)
2616 	    {
2617 		if ((flags & EVAL_VAR_IMPORT) == 0)
2618 		{
2619 		    if (flags & EVAL_VAR_VERBOSE)
2620 			emsg(_(e_import_as_name_not_supported_here));
2621 		    ret = FAIL;
2622 		}
2623 		else
2624 		{
2625 		    if (rettv != NULL)
2626 		    {
2627 			rettv->v_type = VAR_ANY;
2628 			rettv->vval.v_number = import->imp_sid;
2629 		    }
2630 		    found = TRUE;
2631 		}
2632 	    }
2633 	    else
2634 	    {
2635 		scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
2636 		svar_T		*sv = ((svar_T *)si->sn_var_vals.ga_data)
2637 						    + import->imp_var_vals_idx;
2638 		tv = sv->sv_tv;
2639 		type = sv->sv_type;
2640 	    }
2641 	}
2642 	else if (in_vim9script())
2643 	{
2644 	    ufunc_T *ufunc = find_func(name, FALSE, NULL);
2645 
2646 	    // In Vim9 script we can get a function reference by using the
2647 	    // function name.
2648 	    if (ufunc != NULL)
2649 	    {
2650 		found = TRUE;
2651 		if (rettv != NULL)
2652 		{
2653 		    rettv->v_type = VAR_FUNC;
2654 		    rettv->vval.v_string = vim_strsave(ufunc->uf_name);
2655 		    if (rettv->vval.v_string != NULL)
2656 			func_ref(ufunc->uf_name);
2657 		}
2658 	    }
2659 	}
2660     }
2661 
2662     if (!found)
2663     {
2664 	if (tv == NULL)
2665 	{
2666 	    if (rettv != NULL && (flags & EVAL_VAR_VERBOSE))
2667 		semsg(_(e_undefined_variable_str), name);
2668 	    ret = FAIL;
2669 	}
2670 	else if (rettv != NULL)
2671 	{
2672 	    if (ht != NULL && ht == get_script_local_ht()
2673 		    && tv != &SCRIPT_SV(current_sctx.sc_sid)->sv_var.di_tv)
2674 	    {
2675 		svar_T *sv = find_typval_in_script(tv);
2676 
2677 		if (sv != NULL)
2678 		    type = sv->sv_type;
2679 	    }
2680 
2681 	    // If a list or dict variable wasn't initialized, do it now.
2682 	    if (tv->v_type == VAR_DICT && tv->vval.v_dict == NULL)
2683 	    {
2684 		tv->vval.v_dict = dict_alloc();
2685 		if (tv->vval.v_dict != NULL)
2686 		{
2687 		    ++tv->vval.v_dict->dv_refcount;
2688 		    tv->vval.v_dict->dv_type = alloc_type(type);
2689 		}
2690 	    }
2691 	    else if (tv->v_type == VAR_LIST && tv->vval.v_list == NULL)
2692 	    {
2693 		tv->vval.v_list = list_alloc();
2694 		if (tv->vval.v_list != NULL)
2695 		{
2696 		    ++tv->vval.v_list->lv_refcount;
2697 		    tv->vval.v_list->lv_type = alloc_type(type);
2698 		}
2699 	    }
2700 	    else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL)
2701 	    {
2702 		tv->vval.v_blob = blob_alloc();
2703 		if (tv->vval.v_blob != NULL)
2704 		    ++tv->vval.v_blob->bv_refcount;
2705 	    }
2706 	    copy_tv(tv, rettv);
2707 	}
2708     }
2709 
2710     name[len] = cc;
2711 
2712     return ret;
2713 }
2714 
2715 /*
2716  * Check if variable "name[len]" is a local variable or an argument.
2717  * If so, "*eval_lavars_used" is set to TRUE.
2718  */
2719     void
check_vars(char_u * name,int len)2720 check_vars(char_u *name, int len)
2721 {
2722     int		cc;
2723     char_u	*varname;
2724     hashtab_T	*ht;
2725 
2726     if (eval_lavars_used == NULL)
2727 	return;
2728 
2729     // truncate the name, so that we can use strcmp()
2730     cc = name[len];
2731     name[len] = NUL;
2732 
2733     ht = find_var_ht(name, &varname);
2734     if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht())
2735     {
2736 	if (find_var(name, NULL, TRUE) != NULL)
2737 	    *eval_lavars_used = TRUE;
2738     }
2739 
2740     name[len] = cc;
2741 }
2742 
2743 /*
2744  * Find variable "name" in the list of variables.
2745  * Return a pointer to it if found, NULL if not found.
2746  * Careful: "a:0" variables don't have a name.
2747  * When "htp" is not NULL  set "htp" to the hashtab_T used.
2748  */
2749     dictitem_T *
find_var(char_u * name,hashtab_T ** htp,int no_autoload)2750 find_var(char_u *name, hashtab_T **htp, int no_autoload)
2751 {
2752     char_u	*varname;
2753     hashtab_T	*ht;
2754     dictitem_T	*ret = NULL;
2755 
2756     ht = find_var_ht(name, &varname);
2757     if (htp != NULL)
2758 	*htp = ht;
2759     if (ht == NULL)
2760 	return NULL;
2761     ret = find_var_in_ht(ht, *name, varname, no_autoload);
2762     if (ret != NULL)
2763 	return ret;
2764 
2765     // Search in parent scope for lambda
2766     ret = find_var_in_scoped_ht(name, no_autoload);
2767     if (ret != NULL)
2768 	return ret;
2769 
2770     // in Vim9 script items without a scope can be script-local
2771     if (in_vim9script() && name[0] != NUL && name[1] != ':')
2772     {
2773 	ht = get_script_local_ht();
2774 	if (ht != NULL)
2775 	{
2776 	    ret = find_var_in_ht(ht, *name, varname, no_autoload);
2777 	    if (ret != NULL)
2778 	    {
2779 		if (htp != NULL)
2780 		    *htp = ht;
2781 		return ret;
2782 	    }
2783 	}
2784     }
2785 
2786     return NULL;
2787 }
2788 
2789 /*
2790  * Find variable "varname" in hashtab "ht" with name "htname".
2791  * When "varname" is empty returns curwin/curtab/etc vars dictionary.
2792  * Returns NULL if not found.
2793  */
2794     dictitem_T *
find_var_in_ht(hashtab_T * ht,int htname,char_u * varname,int no_autoload)2795 find_var_in_ht(
2796     hashtab_T	*ht,
2797     int		htname,
2798     char_u	*varname,
2799     int		no_autoload)
2800 {
2801     hashitem_T	*hi;
2802 
2803     if (*varname == NUL)
2804     {
2805 	// Must be something like "s:", otherwise "ht" would be NULL.
2806 	switch (htname)
2807 	{
2808 	    case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var;
2809 	    case 'g': return &globvars_var;
2810 	    case 'v': return &vimvars_var;
2811 	    case 'b': return &curbuf->b_bufvar;
2812 	    case 'w': return &curwin->w_winvar;
2813 	    case 't': return &curtab->tp_winvar;
2814 	    case 'l': return get_funccal_local_var();
2815 	    case 'a': return get_funccal_args_var();
2816 	}
2817 	return NULL;
2818     }
2819 
2820     hi = hash_find(ht, varname);
2821     if (HASHITEM_EMPTY(hi))
2822     {
2823 	// For global variables we may try auto-loading the script.  If it
2824 	// worked find the variable again.  Don't auto-load a script if it was
2825 	// loaded already, otherwise it would be loaded every time when
2826 	// checking if a function name is a Funcref variable.
2827 	if (ht == &globvarht && !no_autoload)
2828 	{
2829 	    // Note: script_autoload() may make "hi" invalid. It must either
2830 	    // be obtained again or not used.
2831 	    if (!script_autoload(varname, FALSE) || aborting())
2832 		return NULL;
2833 	    hi = hash_find(ht, varname);
2834 	}
2835 	if (HASHITEM_EMPTY(hi))
2836 	    return NULL;
2837     }
2838     return HI2DI(hi);
2839 }
2840 
2841 /*
2842  * Get the script-local hashtab.  NULL if not in a script context.
2843  */
2844     hashtab_T *
get_script_local_ht(void)2845 get_script_local_ht(void)
2846 {
2847     scid_T sid = current_sctx.sc_sid;
2848 
2849     if (SCRIPT_ID_VALID(sid))
2850 	return &SCRIPT_VARS(sid);
2851     return NULL;
2852 }
2853 
2854 /*
2855  * Look for "name[len]" in script-local variables and functions.
2856  * When "cmd" is TRUE it must look like a command, a function must be followed
2857  * by "(" or "->".
2858  * Return OK when found, FAIL when not found.
2859  */
2860     int
lookup_scriptitem(char_u * name,size_t len,int cmd,cctx_T * dummy UNUSED)2861 lookup_scriptitem(
2862 	char_u	*name,
2863 	size_t	len,
2864 	int	cmd,
2865 	cctx_T	*dummy UNUSED)
2866 {
2867     hashtab_T	*ht = get_script_local_ht();
2868     char_u	buffer[30];
2869     char_u	*p;
2870     int		res;
2871     hashitem_T	*hi;
2872     int		is_global = FALSE;
2873     char_u	*fname = name;
2874 
2875     if (ht == NULL)
2876 	return FAIL;
2877     if (len < sizeof(buffer) - 1)
2878     {
2879 	// avoid an alloc/free for short names
2880 	vim_strncpy(buffer, name, len);
2881 	p = buffer;
2882     }
2883     else
2884     {
2885 	p = vim_strnsave(name, len);
2886 	if (p == NULL)
2887 	    return FAIL;
2888     }
2889 
2890     hi = hash_find(ht, p);
2891     res = HASHITEM_EMPTY(hi) ? FAIL : OK;
2892 
2893     // if not script-local, then perhaps imported
2894     if (res == FAIL && find_imported(p, 0, NULL) != NULL)
2895 	res = OK;
2896     if (p != buffer)
2897 	vim_free(p);
2898 
2899     // Find a function, so that a following "->" works.
2900     // When used as a command require "(" or "->" to follow, "Cmd" is a user
2901     // command while "Cmd()" is a function call.
2902     if (res != OK)
2903     {
2904 	p = skipwhite(name + len);
2905 
2906 	if (!cmd || name[len] == '(' || (p[0] == '-' && p[1] == '>'))
2907 	{
2908 	    // Do not check for an internal function, since it might also be a
2909 	    // valid command, such as ":split" versus "split()".
2910 	    // Skip "g:" before a function name.
2911 	    if (name[0] == 'g' && name[1] == ':')
2912 	    {
2913 		is_global = TRUE;
2914 		fname = name + 2;
2915 	    }
2916 	    if (find_func(fname, is_global, NULL) != NULL)
2917 		res = OK;
2918 	}
2919     }
2920 
2921     return res;
2922 }
2923 
2924 /*
2925  * Find the hashtab used for a variable name.
2926  * Return NULL if the name is not valid.
2927  * Set "varname" to the start of name without ':'.
2928  */
2929     hashtab_T *
find_var_ht(char_u * name,char_u ** varname)2930 find_var_ht(char_u *name, char_u **varname)
2931 {
2932     hashitem_T	*hi;
2933     hashtab_T	*ht;
2934 
2935     if (name[0] == NUL)
2936 	return NULL;
2937     if (name[1] != ':')
2938     {
2939 	// The name must not start with a colon or #.
2940 	if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
2941 	    return NULL;
2942 	*varname = name;
2943 
2944 	// "version" is "v:version" in all scopes if scriptversion < 3.
2945 	// Same for a few other variables marked with VV_COMPAT.
2946 	if (in_old_script(3))
2947 	{
2948 	    hi = hash_find(&compat_hashtab, name);
2949 	    if (!HASHITEM_EMPTY(hi))
2950 		return &compat_hashtab;
2951 	}
2952 
2953 	ht = get_funccal_local_ht();
2954 	if (ht != NULL)
2955 	    return ht;				// local variable
2956 
2957 	// In Vim9 script items at the script level are script-local, except
2958 	// for autoload names.
2959 	if (in_vim9script() && vim_strchr(name, AUTOLOAD_CHAR) == NULL)
2960 	{
2961 	    ht = get_script_local_ht();
2962 	    if (ht != NULL)
2963 		return ht;
2964 	}
2965 
2966 	return &globvarht;			// global variable
2967     }
2968     *varname = name + 2;
2969     if (*name == 'g')				// global variable
2970 	return &globvarht;
2971     // There must be no ':' or '#' in the rest of the name, unless g: is used
2972     if (vim_strchr(name + 2, ':') != NULL
2973 			       || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
2974 	return NULL;
2975     if (*name == 'b')				// buffer variable
2976 	return &curbuf->b_vars->dv_hashtab;
2977     if (*name == 'w')				// window variable
2978 	return &curwin->w_vars->dv_hashtab;
2979     if (*name == 't')				// tab page variable
2980 	return &curtab->tp_vars->dv_hashtab;
2981     if (*name == 'v')				// v: variable
2982 	return &vimvarht;
2983     if (get_current_funccal() != NULL
2984 	       && get_current_funccal()->func->uf_def_status == UF_NOT_COMPILED)
2985     {
2986 	// a: and l: are only used in functions defined with ":function"
2987 	if (*name == 'a')			// a: function argument
2988 	    return get_funccal_args_ht();
2989 	if (*name == 'l')			// l: local function variable
2990 	    return get_funccal_local_ht();
2991     }
2992     if (*name == 's')				// script variable
2993     {
2994 	ht = get_script_local_ht();
2995 	if (ht != NULL)
2996 	    return ht;
2997     }
2998     return NULL;
2999 }
3000 
3001 /*
3002  * Get the string value of a (global/local) variable.
3003  * Note: see tv_get_string() for how long the pointer remains valid.
3004  * Returns NULL when it doesn't exist.
3005  */
3006     char_u *
get_var_value(char_u * name)3007 get_var_value(char_u *name)
3008 {
3009     dictitem_T	*v;
3010 
3011     v = find_var(name, NULL, FALSE);
3012     if (v == NULL)
3013 	return NULL;
3014     return tv_get_string(&v->di_tv);
3015 }
3016 
3017 /*
3018  * Allocate a new hashtab for a sourced script.  It will be used while
3019  * sourcing this script and when executing functions defined in the script.
3020  */
3021     void
new_script_vars(scid_T id)3022 new_script_vars(scid_T id)
3023 {
3024     scriptvar_T *sv;
3025 
3026     sv = ALLOC_CLEAR_ONE(scriptvar_T);
3027     if (sv == NULL)
3028 	return;
3029     init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
3030     SCRIPT_ITEM(id)->sn_vars = sv;
3031 }
3032 
3033 /*
3034  * Initialize dictionary "dict" as a scope and set variable "dict_var" to
3035  * point to it.
3036  */
3037     void
init_var_dict(dict_T * dict,dictitem_T * dict_var,int scope)3038 init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
3039 {
3040     hash_init(&dict->dv_hashtab);
3041     dict->dv_lock = 0;
3042     dict->dv_scope = scope;
3043     dict->dv_refcount = DO_NOT_FREE_CNT;
3044     dict->dv_copyID = 0;
3045     dict_var->di_tv.vval.v_dict = dict;
3046     dict_var->di_tv.v_type = VAR_DICT;
3047     dict_var->di_tv.v_lock = VAR_FIXED;
3048     dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
3049     dict_var->di_key[0] = NUL;
3050 }
3051 
3052 /*
3053  * Unreference a dictionary initialized by init_var_dict().
3054  */
3055     void
unref_var_dict(dict_T * dict)3056 unref_var_dict(dict_T *dict)
3057 {
3058     // Now the dict needs to be freed if no one else is using it, go back to
3059     // normal reference counting.
3060     dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
3061     dict_unref(dict);
3062 }
3063 
3064 /*
3065  * Clean up a list of internal variables.
3066  * Frees all allocated variables and the value they contain.
3067  * Clears hashtab "ht", does not free it.
3068  */
3069     void
vars_clear(hashtab_T * ht)3070 vars_clear(hashtab_T *ht)
3071 {
3072     vars_clear_ext(ht, TRUE);
3073 }
3074 
3075 /*
3076  * Like vars_clear(), but only free the value if "free_val" is TRUE.
3077  */
3078     void
vars_clear_ext(hashtab_T * ht,int free_val)3079 vars_clear_ext(hashtab_T *ht, int free_val)
3080 {
3081     int		todo;
3082     hashitem_T	*hi;
3083     dictitem_T	*v;
3084 
3085     hash_lock(ht);
3086     todo = (int)ht->ht_used;
3087     for (hi = ht->ht_array; todo > 0; ++hi)
3088     {
3089 	if (!HASHITEM_EMPTY(hi))
3090 	{
3091 	    --todo;
3092 
3093 	    // Free the variable.  Don't remove it from the hashtab,
3094 	    // ht_array might change then.  hash_clear() takes care of it
3095 	    // later.
3096 	    v = HI2DI(hi);
3097 	    if (free_val)
3098 		clear_tv(&v->di_tv);
3099 	    if (v->di_flags & DI_FLAGS_ALLOC)
3100 		vim_free(v);
3101 	}
3102     }
3103     hash_clear(ht);
3104     hash_init(ht);
3105 }
3106 
3107 /*
3108  * Delete a variable from hashtab "ht" at item "hi".
3109  * Clear the variable value and free the dictitem.
3110  */
3111     void
delete_var(hashtab_T * ht,hashitem_T * hi)3112 delete_var(hashtab_T *ht, hashitem_T *hi)
3113 {
3114     dictitem_T	*di = HI2DI(hi);
3115 
3116     hash_remove(ht, hi);
3117     clear_tv(&di->di_tv);
3118     vim_free(di);
3119 }
3120 
3121 /*
3122  * List the value of one internal variable.
3123  */
3124     static void
list_one_var(dictitem_T * v,char * prefix,int * first)3125 list_one_var(dictitem_T *v, char *prefix, int *first)
3126 {
3127     char_u	*tofree;
3128     char_u	*s;
3129     char_u	numbuf[NUMBUFLEN];
3130 
3131     s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
3132     list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
3133 					 s == NULL ? (char_u *)"" : s, first);
3134     vim_free(tofree);
3135 }
3136 
3137     static void
list_one_var_a(char * prefix,char_u * name,int type,char_u * string,int * first)3138 list_one_var_a(
3139     char	*prefix,
3140     char_u	*name,
3141     int		type,
3142     char_u	*string,
3143     int		*first)  // when TRUE clear rest of screen and set to FALSE
3144 {
3145     // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg"
3146     msg_start();
3147     msg_puts(prefix);
3148     if (name != NULL)	// "a:" vars don't have a name stored
3149 	msg_puts((char *)name);
3150     msg_putchar(' ');
3151     msg_advance(22);
3152     if (type == VAR_NUMBER)
3153 	msg_putchar('#');
3154     else if (type == VAR_FUNC || type == VAR_PARTIAL)
3155 	msg_putchar('*');
3156     else if (type == VAR_LIST)
3157     {
3158 	msg_putchar('[');
3159 	if (*string == '[')
3160 	    ++string;
3161     }
3162     else if (type == VAR_DICT)
3163     {
3164 	msg_putchar('{');
3165 	if (*string == '{')
3166 	    ++string;
3167     }
3168     else
3169 	msg_putchar(' ');
3170 
3171     msg_outtrans(string);
3172 
3173     if (type == VAR_FUNC || type == VAR_PARTIAL)
3174 	msg_puts("()");
3175     if (*first)
3176     {
3177 	msg_clr_eos();
3178 	*first = FALSE;
3179     }
3180 }
3181 
3182 /*
3183  * Set variable "name" to value in "tv".
3184  * If the variable already exists, the value is updated.
3185  * Otherwise the variable is created.
3186  */
3187     void
set_var(char_u * name,typval_T * tv,int copy)3188 set_var(
3189     char_u	*name,
3190     typval_T	*tv,
3191     int		copy)	    // make copy of value in "tv"
3192 {
3193     set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0);
3194 }
3195 
3196 /*
3197  * Set variable "name" to value in "tv".
3198  * If the variable already exists and "is_const" is FALSE the value is updated.
3199  * Otherwise the variable is created.
3200  */
3201     void
set_var_const(char_u * name,type_T * type,typval_T * tv_arg,int copy,int flags_arg,int var_idx)3202 set_var_const(
3203     char_u	*name,
3204     type_T	*type,
3205     typval_T	*tv_arg,
3206     int		copy,	    // make copy of value in "tv"
3207     int		flags_arg,  // ASSIGN_CONST, ASSIGN_FINAL, etc.
3208     int		var_idx)    // index for ":let [a, b] = list"
3209 {
3210     typval_T	*tv = tv_arg;
3211     typval_T	bool_tv;
3212     dictitem_T	*di;
3213     typval_T	*dest_tv = NULL;
3214     char_u	*varname;
3215     hashtab_T	*ht;
3216     int		is_script_local;
3217     int		vim9script = in_vim9script();
3218     int		var_in_vim9script;
3219     int		flags = flags_arg;
3220 
3221     ht = find_var_ht(name, &varname);
3222     if (ht == NULL || *varname == NUL)
3223     {
3224 	semsg(_(e_illvar), name);
3225 	goto failed;
3226     }
3227     is_script_local = ht == get_script_local_ht();
3228 
3229     if (vim9script
3230 	    && !is_script_local
3231 	    && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
3232 	    && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
3233 	    && name[1] == ':')
3234     {
3235 	vim9_declare_error(name);
3236 	goto failed;
3237     }
3238     if ((flags & ASSIGN_FOR_LOOP) && name[1] == ':'
3239 			      && vim_strchr((char_u *)"gwbt", name[0]) != NULL)
3240 	// Do not make g:var, w:var, b:var or t:var final.
3241 	flags &= ~ASSIGN_FINAL;
3242 
3243     var_in_vim9script = is_script_local && current_script_is_vim9();
3244     if (var_in_vim9script && name[0] == '_' && name[1] == NUL)
3245     {
3246 	// For "[a, _] = list" the underscore is ignored.
3247 	if ((flags & ASSIGN_UNPACK) == 0)
3248 	    emsg(_(e_cannot_use_underscore_here));
3249 	goto failed;
3250     }
3251 
3252     di = find_var_in_ht(ht, 0, varname, TRUE);
3253 
3254     if (di == NULL && var_in_vim9script)
3255     {
3256 	imported_T  *import = find_imported(varname, 0, NULL);
3257 
3258 	if (import != NULL)
3259 	{
3260 	    scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
3261 	    svar_T	    *sv;
3262 	    where_T	    where = WHERE_INIT;
3263 
3264 	    // imported variable from another script
3265 	    if ((flags & ASSIGN_NO_DECL) == 0)
3266 	    {
3267 		semsg(_(e_redefining_imported_item_str), name);
3268 		goto failed;
3269 	    }
3270 	    if (import->imp_flags & IMP_FLAGS_STAR)
3271 	    {
3272 		semsg(_(e_cannot_use_str_itself_it_is_imported_with_star),
3273 									 name);
3274 		goto failed;
3275 	    }
3276 	    sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx;
3277 
3278 	    where.wt_variable = TRUE;
3279 	    if (check_typval_type(sv->sv_type, tv, where) == FAIL
3280 		    || value_check_lock(sv->sv_tv->v_lock, name, FALSE))
3281 	    {
3282 		goto failed;
3283 	    }
3284 
3285 	    dest_tv = sv->sv_tv;
3286 	    clear_tv(dest_tv);
3287 	}
3288     }
3289 
3290     if (dest_tv == NULL)
3291     {
3292 	// Search in parent scope which is possible to reference from lambda
3293 	if (di == NULL)
3294 	    di = find_var_in_scoped_ht(name, TRUE);
3295 
3296 	if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
3297 				      && var_wrong_func_name(name, di == NULL))
3298 	    goto failed;
3299 
3300 	if (need_convert_to_bool(type, tv))
3301 	{
3302 	    // Destination is a bool and the value is not, but it can be
3303 	    // converted.
3304 	    CLEAR_FIELD(bool_tv);
3305 	    bool_tv.v_type = VAR_BOOL;
3306 	    bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
3307 	    tv = &bool_tv;
3308 	}
3309 
3310 	if (di != NULL)
3311 	{
3312 	    // Item already exists.  Allowed to replace when reloading.
3313 	    if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
3314 	    {
3315 		if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
3316 					     && (flags & ASSIGN_FOR_LOOP) == 0)
3317 		{
3318 		    emsg(_(e_cannot_mod));
3319 		    goto failed;
3320 		}
3321 
3322 		if (is_script_local && vim9script
3323 			      && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
3324 		{
3325 		    semsg(_(e_redefining_script_item_str), name);
3326 		    goto failed;
3327 		}
3328 
3329 		if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0)
3330 		{
3331 		    where_T where = WHERE_INIT;
3332 
3333 		    // check the type and adjust to bool if needed
3334 		    where.wt_index = var_idx;
3335 		    where.wt_variable = TRUE;
3336 		    if (check_script_var_type(&di->di_tv, tv, name, where)
3337 								       == FAIL)
3338 			goto failed;
3339 		}
3340 
3341 		if ((flags & ASSIGN_FOR_LOOP) == 0
3342 				     && var_check_permission(di, name) == FAIL)
3343 		    goto failed;
3344 	    }
3345 	    else
3346 	    {
3347 		// can only redefine once
3348 		di->di_flags &= ~DI_FLAGS_RELOAD;
3349 
3350 		// A Vim9 script-local variable is also present in sn_all_vars
3351 		// and sn_var_vals.  It may set "type" from "tv".
3352 		if (var_in_vim9script)
3353 		    update_vim9_script_var(FALSE, di, flags, tv, &type,
3354 					 (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
3355 	    }
3356 
3357 	    // existing variable, need to clear the value
3358 
3359 	    // Handle setting internal di: variables separately where needed to
3360 	    // prevent changing the type.
3361 	    if (ht == &vimvarht)
3362 	    {
3363 		if (di->di_tv.v_type == VAR_STRING)
3364 		{
3365 		    VIM_CLEAR(di->di_tv.vval.v_string);
3366 		    if (copy || tv->v_type != VAR_STRING)
3367 		    {
3368 			char_u *val = tv_get_string(tv);
3369 
3370 			// Careful: when assigning to v:errmsg and
3371 			// tv_get_string() causes an error message the variable
3372 			// will already be set.
3373 			if (di->di_tv.vval.v_string == NULL)
3374 			    di->di_tv.vval.v_string = vim_strsave(val);
3375 		    }
3376 		    else
3377 		    {
3378 			// Take over the string to avoid an extra alloc/free.
3379 			di->di_tv.vval.v_string = tv->vval.v_string;
3380 			tv->vval.v_string = NULL;
3381 		    }
3382 		    goto failed;
3383 		}
3384 		else if (di->di_tv.v_type == VAR_NUMBER)
3385 		{
3386 		    di->di_tv.vval.v_number = tv_get_number(tv);
3387 		    if (STRCMP(varname, "searchforward") == 0)
3388 			set_search_direction(di->di_tv.vval.v_number
3389 								  ? '/' : '?');
3390 #ifdef FEAT_SEARCH_EXTRA
3391 		    else if (STRCMP(varname, "hlsearch") == 0)
3392 		    {
3393 			no_hlsearch = !di->di_tv.vval.v_number;
3394 			redraw_all_later(SOME_VALID);
3395 		    }
3396 #endif
3397 		    goto failed;
3398 		}
3399 		else if (di->di_tv.v_type != tv->v_type)
3400 		{
3401 		    semsg(_("E963: setting %s to value with wrong type"), name);
3402 		    goto failed;
3403 		}
3404 	    }
3405 
3406 	    clear_tv(&di->di_tv);
3407 	}
3408 	else
3409 	{
3410 	    // Item not found, check if a function already exists.
3411 	    if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
3412 		   && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
3413 	    {
3414 		semsg(_(e_redefining_script_item_str), name);
3415 		goto failed;
3416 	    }
3417 
3418 	    // add a new variable
3419 	    if (var_in_vim9script && (flags & ASSIGN_NO_DECL))
3420 	    {
3421 		semsg(_(e_unknown_variable_str), name);
3422 		goto failed;
3423 	    }
3424 
3425 	    // Can't add "v:" or "a:" variable.
3426 	    if (ht == &vimvarht || ht == get_funccal_args_ht())
3427 	    {
3428 		semsg(_(e_illvar), name);
3429 		goto failed;
3430 	    }
3431 
3432 	    // Make sure the variable name is valid.  In Vim9 script an autoload
3433 	    // variable must be prefixed with "g:".
3434 	    if (!valid_varname(varname, !vim9script
3435 					       || STRNCMP(name, "g:", 2) == 0))
3436 		goto failed;
3437 
3438 	    di = alloc(sizeof(dictitem_T) + STRLEN(varname));
3439 	    if (di == NULL)
3440 		goto failed;
3441 	    STRCPY(di->di_key, varname);
3442 	    if (hash_add(ht, DI2HIKEY(di)) == FAIL)
3443 	    {
3444 		vim_free(di);
3445 		goto failed;
3446 	    }
3447 	    di->di_flags = DI_FLAGS_ALLOC;
3448 	    if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
3449 		di->di_flags |= DI_FLAGS_LOCK;
3450 
3451 	    // A Vim9 script-local variable is also added to sn_all_vars and
3452 	    // sn_var_vals. It may set "type" from "tv".
3453 	    if (var_in_vim9script)
3454 		update_vim9_script_var(TRUE, di, flags, tv, &type,
3455 					 (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
3456 	}
3457 
3458 	dest_tv = &di->di_tv;
3459     }
3460 
3461     if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
3462 	copy_tv(tv, dest_tv);
3463     else
3464     {
3465 	*dest_tv = *tv;
3466 	dest_tv->v_lock = 0;
3467 	init_tv(tv);
3468     }
3469 
3470     if (vim9script && type != NULL)
3471     {
3472 	if (type->tt_type == VAR_DICT && dest_tv->vval.v_dict != NULL)
3473 	{
3474 	    if (dest_tv->vval.v_dict->dv_type != type)
3475 	    {
3476 		free_type(dest_tv->vval.v_dict->dv_type);
3477 		dest_tv->vval.v_dict->dv_type = alloc_type(type);
3478 	    }
3479 	}
3480 	else if (type->tt_type == VAR_LIST && dest_tv->vval.v_list != NULL)
3481 	{
3482 	    if (dest_tv->vval.v_list->lv_type != type)
3483 	    {
3484 		free_type(dest_tv->vval.v_list->lv_type);
3485 		dest_tv->vval.v_list->lv_type = alloc_type(type);
3486 	    }
3487 	}
3488     }
3489 
3490     // ":const var = value" locks the value
3491     // ":final var = value" locks "var"
3492     if (flags & ASSIGN_CONST)
3493 	// Like :lockvar! name: lock the value and what it contains, but only
3494 	// if the reference count is up to one.  That locks only literal
3495 	// values.
3496 	item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
3497     return;
3498 
3499 failed:
3500     if (!copy)
3501 	clear_tv(tv_arg);
3502 }
3503 
3504 /*
3505  * Check in this order for backwards compatibility:
3506  * - Whether the variable is read-only
3507  * - Whether the variable value is locked
3508  * - Whether the variable is locked
3509  */
3510     int
var_check_permission(dictitem_T * di,char_u * name)3511 var_check_permission(dictitem_T *di, char_u *name)
3512 {
3513     if (var_check_ro(di->di_flags, name, FALSE)
3514 		    || value_check_lock(di->di_tv.v_lock, name, FALSE)
3515 		    || var_check_lock(di->di_flags, name, FALSE))
3516 	return FAIL;
3517     return OK;
3518 }
3519 
3520 /*
3521  * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
3522  * Also give an error message.
3523  */
3524     int
var_check_ro(int flags,char_u * name,int use_gettext)3525 var_check_ro(int flags, char_u *name, int use_gettext)
3526 {
3527     if (flags & DI_FLAGS_RO)
3528     {
3529 	semsg(_(e_cannot_change_readonly_variable_str),
3530 				       use_gettext ? (char_u *)_(name) : name);
3531 	return TRUE;
3532     }
3533     if ((flags & DI_FLAGS_RO_SBX) && sandbox)
3534     {
3535 	semsg(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
3536 	return TRUE;
3537     }
3538     return FALSE;
3539 }
3540 
3541 /*
3542  * Return TRUE if di_flags "flags" indicates variable "name" is locked.
3543  * Also give an error message.
3544  */
3545     int
var_check_lock(int flags,char_u * name,int use_gettext)3546 var_check_lock(int flags, char_u *name, int use_gettext)
3547 {
3548     if (flags & DI_FLAGS_LOCK)
3549     {
3550 	semsg(_(e_variable_is_locked_str),
3551 				       use_gettext ? (char_u *)_(name) : name);
3552 	return TRUE;
3553     }
3554     return FALSE;
3555 }
3556 
3557 /*
3558  * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
3559  * Also give an error message.
3560  */
3561     int
var_check_fixed(int flags,char_u * name,int use_gettext)3562 var_check_fixed(int flags, char_u *name, int use_gettext)
3563 {
3564     if (flags & DI_FLAGS_FIX)
3565     {
3566 	semsg(_("E795: Cannot delete variable %s"),
3567 				      use_gettext ? (char_u *)_(name) : name);
3568 	return TRUE;
3569     }
3570     return FALSE;
3571 }
3572 
3573 /*
3574  * Check if a funcref is assigned to a valid variable name.
3575  * Return TRUE and give an error if not.
3576  */
3577     int
var_wrong_func_name(char_u * name,int new_var)3578 var_wrong_func_name(
3579     char_u *name,    // points to start of variable name
3580     int    new_var)  // TRUE when creating the variable
3581 {
3582     // Allow for w: b: s: and t:.  In Vim9 script s: is not allowed, because
3583     // the name can be used without the s: prefix.
3584     if (!((vim_strchr((char_u *)"wbt", name[0]) != NULL
3585 		    || (!in_vim9script() && name[0] == 's')) && name[1] == ':')
3586 	    && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
3587 						     ? name[2] : name[0]))
3588     {
3589 	semsg(_("E704: Funcref variable name must start with a capital: %s"),
3590 									name);
3591 	return TRUE;
3592     }
3593     // Don't allow hiding a function.  When "v" is not NULL we might be
3594     // assigning another function to the same var, the type is checked
3595     // below.
3596     if (new_var && function_exists(name, FALSE))
3597     {
3598 	semsg(_("E705: Variable name conflicts with existing function: %s"),
3599 								    name);
3600 	return TRUE;
3601     }
3602     return FALSE;
3603 }
3604 
3605 /*
3606  * Return TRUE if "flags" indicates variable "name" has a locked (immutable)
3607  * value.  Also give an error message, using "name" or _("name") when
3608  * "use_gettext" is TRUE.
3609  */
3610     int
value_check_lock(int lock,char_u * name,int use_gettext)3611 value_check_lock(int lock, char_u *name, int use_gettext)
3612 {
3613     if (lock & VAR_LOCKED)
3614     {
3615 	semsg(_("E741: Value is locked: %s"),
3616 				name == NULL ? (char_u *)_("Unknown")
3617 					     : use_gettext ? (char_u *)_(name)
3618 					     : name);
3619 	return TRUE;
3620     }
3621     if (lock & VAR_FIXED)
3622     {
3623 	semsg(_("E742: Cannot change value of %s"),
3624 				name == NULL ? (char_u *)_("Unknown")
3625 					     : use_gettext ? (char_u *)_(name)
3626 					     : name);
3627 	return TRUE;
3628     }
3629     return FALSE;
3630 }
3631 
3632 /*
3633  * Check if a variable name is valid.  When "autoload" is true "#" is allowed.
3634  * Return FALSE and give an error if not.
3635  */
3636     int
valid_varname(char_u * varname,int autoload)3637 valid_varname(char_u *varname, int autoload)
3638 {
3639     char_u *p;
3640 
3641     for (p = varname; *p != NUL; ++p)
3642 	if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
3643 					 && !(autoload && *p == AUTOLOAD_CHAR))
3644 	{
3645 	    semsg(_(e_illvar), varname);
3646 	    return FALSE;
3647 	}
3648     return TRUE;
3649 }
3650 
3651 /*
3652  * getwinvar() and gettabwinvar()
3653  */
3654     static void
getwinvar(typval_T * argvars,typval_T * rettv,int off)3655 getwinvar(
3656     typval_T	*argvars,
3657     typval_T	*rettv,
3658     int		off)	    // 1 for gettabwinvar()
3659 {
3660     win_T	*win;
3661     char_u	*varname;
3662     dictitem_T	*v;
3663     tabpage_T	*tp = NULL;
3664     int		done = FALSE;
3665     win_T	*oldcurwin;
3666     tabpage_T	*oldtabpage;
3667     int		need_switch_win;
3668 
3669     if (off == 1)
3670 	tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
3671     else
3672 	tp = curtab;
3673     win = find_win_by_nr(&argvars[off], tp);
3674     varname = tv_get_string_chk(&argvars[off + 1]);
3675     ++emsg_off;
3676 
3677     rettv->v_type = VAR_STRING;
3678     rettv->vval.v_string = NULL;
3679 
3680     if (win != NULL && varname != NULL)
3681     {
3682 	// Set curwin to be our win, temporarily.  Also set the tabpage,
3683 	// otherwise the window is not valid. Only do this when needed,
3684 	// autocommands get blocked.
3685 	need_switch_win = !(tp == curtab && win == curwin);
3686 	if (!need_switch_win
3687 		  || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
3688 	{
3689 	    if (*varname == '&')
3690 	    {
3691 		if (varname[1] == NUL)
3692 		{
3693 		    // get all window-local options in a dict
3694 		    dict_T	*opts = get_winbuf_options(FALSE);
3695 
3696 		    if (opts != NULL)
3697 		    {
3698 			rettv_dict_set(rettv, opts);
3699 			done = TRUE;
3700 		    }
3701 		}
3702 		else if (eval_option(&varname, rettv, 1) == OK)
3703 		    // window-local-option
3704 		    done = TRUE;
3705 	    }
3706 	    else
3707 	    {
3708 		// Look up the variable.
3709 		// Let getwinvar({nr}, "") return the "w:" dictionary.
3710 		v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
3711 							      varname, FALSE);
3712 		if (v != NULL)
3713 		{
3714 		    copy_tv(&v->di_tv, rettv);
3715 		    done = TRUE;
3716 		}
3717 	    }
3718 	}
3719 
3720 	if (need_switch_win)
3721 	    // restore previous notion of curwin
3722 	    restore_win(oldcurwin, oldtabpage, TRUE);
3723     }
3724 
3725     if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
3726 	// use the default return value
3727 	copy_tv(&argvars[off + 2], rettv);
3728 
3729     --emsg_off;
3730 }
3731 
3732 /*
3733  * Set option "varname" to the value of "varp" for the current buffer/window.
3734  */
3735     static void
set_option_from_tv(char_u * varname,typval_T * varp)3736 set_option_from_tv(char_u *varname, typval_T *varp)
3737 {
3738     long	numval = 0;
3739     char_u	*strval;
3740     char_u	nbuf[NUMBUFLEN];
3741     int		error = FALSE;
3742 
3743     if (varp->v_type == VAR_BOOL)
3744     {
3745 	numval = (long)varp->vval.v_number;
3746 	strval = (char_u *)"0";  // avoid using "false"
3747     }
3748     else
3749     {
3750 	if (!in_vim9script() || varp->v_type != VAR_STRING)
3751 	    numval = (long)tv_get_number_chk(varp, &error);
3752 	strval = tv_get_string_buf_chk(varp, nbuf);
3753     }
3754     if (!error && strval != NULL)
3755 	set_option_value(varname, numval, strval, OPT_LOCAL);
3756 }
3757 
3758 /*
3759  * "setwinvar()" and "settabwinvar()" functions
3760  */
3761     static void
setwinvar(typval_T * argvars,int off)3762 setwinvar(typval_T *argvars, int off)
3763 {
3764     win_T	*win;
3765     win_T	*save_curwin;
3766     tabpage_T	*save_curtab;
3767     int		need_switch_win;
3768     char_u	*varname, *winvarname;
3769     typval_T	*varp;
3770     tabpage_T	*tp = NULL;
3771 
3772     if (check_secure())
3773 	return;
3774 
3775     if (off == 1)
3776 	tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
3777     else
3778 	tp = curtab;
3779     win = find_win_by_nr(&argvars[off], tp);
3780     varname = tv_get_string_chk(&argvars[off + 1]);
3781     varp = &argvars[off + 2];
3782 
3783     if (win != NULL && varname != NULL && varp != NULL)
3784     {
3785 	need_switch_win = !(tp == curtab && win == curwin);
3786 	if (!need_switch_win
3787 	       || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
3788 	{
3789 	    if (*varname == '&')
3790 		set_option_from_tv(varname + 1, varp);
3791 	    else
3792 	    {
3793 		winvarname = alloc(STRLEN(varname) + 3);
3794 		if (winvarname != NULL)
3795 		{
3796 		    STRCPY(winvarname, "w:");
3797 		    STRCPY(winvarname + 2, varname);
3798 		    set_var(winvarname, varp, TRUE);
3799 		    vim_free(winvarname);
3800 		}
3801 	    }
3802 	}
3803 	if (need_switch_win)
3804 	    restore_win(save_curwin, save_curtab, TRUE);
3805     }
3806 }
3807 
3808 /*
3809  * reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
3810  * v:option_type, and v:option_command.
3811  */
3812     void
reset_v_option_vars(void)3813 reset_v_option_vars(void)
3814 {
3815     set_vim_var_string(VV_OPTION_NEW,  NULL, -1);
3816     set_vim_var_string(VV_OPTION_OLD,  NULL, -1);
3817     set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
3818     set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
3819     set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
3820     set_vim_var_string(VV_OPTION_COMMAND, NULL, -1);
3821 }
3822 
3823 /*
3824  * Add an assert error to v:errors.
3825  */
3826     void
assert_error(garray_T * gap)3827 assert_error(garray_T *gap)
3828 {
3829     struct vimvar   *vp = &vimvars[VV_ERRORS];
3830 
3831     if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
3832 	// Make sure v:errors is a list.
3833 	set_vim_var_list(VV_ERRORS, list_alloc());
3834     list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
3835 }
3836 
3837     int
var_exists(char_u * var)3838 var_exists(char_u *var)
3839 {
3840     char_u	*arg = var;
3841     char_u	*name;
3842     char_u	*tofree;
3843     typval_T    tv;
3844     int		len = 0;
3845     int		n = FALSE;
3846 
3847     // get_name_len() takes care of expanding curly braces
3848     name = var;
3849     len = get_name_len(&arg, &tofree, TRUE, FALSE);
3850     if (len > 0)
3851     {
3852 	if (tofree != NULL)
3853 	    name = tofree;
3854 	n = (eval_variable(name, len, &tv, NULL,
3855 				 EVAL_VAR_NOAUTOLOAD + EVAL_VAR_IMPORT) == OK);
3856 	if (n)
3857 	{
3858 	    // handle d.key, l[idx], f(expr)
3859 	    arg = skipwhite(arg);
3860 	    n = (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, FALSE) == OK);
3861 	    if (n)
3862 		clear_tv(&tv);
3863 	}
3864     }
3865     if (*arg != NUL)
3866 	n = FALSE;
3867 
3868     vim_free(tofree);
3869     return n;
3870 }
3871 
3872 static lval_T	*redir_lval = NULL;
3873 #define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
3874 static garray_T redir_ga;	// only valid when redir_lval is not NULL
3875 static char_u	*redir_endp = NULL;
3876 static char_u	*redir_varname = NULL;
3877 
3878     int
alloc_redir_lval(void)3879 alloc_redir_lval(void)
3880 {
3881     redir_lval = ALLOC_CLEAR_ONE(lval_T);
3882     if (redir_lval == NULL)
3883 	return FAIL;
3884     return OK;
3885 }
3886 
3887     void
clear_redir_lval(void)3888 clear_redir_lval(void)
3889 {
3890     VIM_CLEAR(redir_lval);
3891 }
3892 
3893     void
init_redir_ga(void)3894 init_redir_ga(void)
3895 {
3896     ga_init2(&redir_ga, (int)sizeof(char), 500);
3897 }
3898 
3899 /*
3900  * Start recording command output to a variable
3901  * When "append" is TRUE append to an existing variable.
3902  * Returns OK if successfully completed the setup.  FAIL otherwise.
3903  */
3904     int
var_redir_start(char_u * name,int append)3905 var_redir_start(char_u *name, int append)
3906 {
3907     int		called_emsg_before;
3908     typval_T	tv;
3909 
3910     // Catch a bad name early.
3911     if (!eval_isnamec1(*name))
3912     {
3913 	emsg(_(e_invarg));
3914 	return FAIL;
3915     }
3916 
3917     // Make a copy of the name, it is used in redir_lval until redir ends.
3918     redir_varname = vim_strsave(name);
3919     if (redir_varname == NULL)
3920 	return FAIL;
3921 
3922     if (alloc_redir_lval() == FAIL)
3923     {
3924 	var_redir_stop();
3925 	return FAIL;
3926     }
3927 
3928     // The output is stored in growarray "redir_ga" until redirection ends.
3929     init_redir_ga();
3930 
3931     // Parse the variable name (can be a dict or list entry).
3932     redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
3933 							     FNE_CHECK_START);
3934     if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
3935     {
3936 	clear_lval(redir_lval);
3937 	if (redir_endp != NULL && *redir_endp != NUL)
3938 	    // Trailing characters are present after the variable name
3939 	    semsg(_(e_trailing_arg), redir_endp);
3940 	else
3941 	    semsg(_(e_invarg2), name);
3942 	redir_endp = NULL;  // don't store a value, only cleanup
3943 	var_redir_stop();
3944 	return FAIL;
3945     }
3946 
3947     // check if we can write to the variable: set it to or append an empty
3948     // string
3949     called_emsg_before = called_emsg;
3950     tv.v_type = VAR_STRING;
3951     tv.vval.v_string = (char_u *)"";
3952     if (append)
3953 	set_var_lval(redir_lval, redir_endp, &tv, TRUE,
3954 					     ASSIGN_NO_DECL, (char_u *)".", 0);
3955     else
3956 	set_var_lval(redir_lval, redir_endp, &tv, TRUE,
3957 					     ASSIGN_NO_DECL, (char_u *)"=", 0);
3958     clear_lval(redir_lval);
3959     if (called_emsg > called_emsg_before)
3960     {
3961 	redir_endp = NULL;  // don't store a value, only cleanup
3962 	var_redir_stop();
3963 	return FAIL;
3964     }
3965 
3966     return OK;
3967 }
3968 
3969 /*
3970  * Append "value[value_len]" to the variable set by var_redir_start().
3971  * The actual appending is postponed until redirection ends, because the value
3972  * appended may in fact be the string we write to, changing it may cause freed
3973  * memory to be used:
3974  *   :redir => foo
3975  *   :let foo
3976  *   :redir END
3977  */
3978     void
var_redir_str(char_u * value,int value_len)3979 var_redir_str(char_u *value, int value_len)
3980 {
3981     int		len;
3982 
3983     if (redir_lval == NULL)
3984 	return;
3985 
3986     if (value_len == -1)
3987 	len = (int)STRLEN(value);	// Append the entire string
3988     else
3989 	len = value_len;		// Append only "value_len" characters
3990 
3991     if (ga_grow(&redir_ga, len) == OK)
3992     {
3993 	mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
3994 	redir_ga.ga_len += len;
3995     }
3996     else
3997 	var_redir_stop();
3998 }
3999 
4000 /*
4001  * Stop redirecting command output to a variable.
4002  * Frees the allocated memory.
4003  */
4004     void
var_redir_stop(void)4005 var_redir_stop(void)
4006 {
4007     typval_T	tv;
4008 
4009     if (EVALCMD_BUSY)
4010     {
4011 	redir_lval = NULL;
4012 	return;
4013     }
4014 
4015     if (redir_lval != NULL)
4016     {
4017 	// If there was no error: assign the text to the variable.
4018 	if (redir_endp != NULL)
4019 	{
4020 	    ga_append(&redir_ga, NUL);  // Append the trailing NUL.
4021 	    tv.v_type = VAR_STRING;
4022 	    tv.vval.v_string = redir_ga.ga_data;
4023 	    // Call get_lval() again, if it's inside a Dict or List it may
4024 	    // have changed.
4025 	    redir_endp = get_lval(redir_varname, NULL, redir_lval,
4026 					FALSE, FALSE, 0, FNE_CHECK_START);
4027 	    if (redir_endp != NULL && redir_lval->ll_name != NULL)
4028 		set_var_lval(redir_lval, redir_endp, &tv, FALSE, 0,
4029 							     (char_u *)".", 0);
4030 	    clear_lval(redir_lval);
4031 	}
4032 
4033 	// free the collected output
4034 	VIM_CLEAR(redir_ga.ga_data);
4035 
4036 	VIM_CLEAR(redir_lval);
4037     }
4038     VIM_CLEAR(redir_varname);
4039 }
4040 
4041 /*
4042  * Get the collected redirected text and clear redir_ga.
4043  */
4044     char_u *
get_clear_redir_ga(void)4045 get_clear_redir_ga(void)
4046 {
4047     char_u *res;
4048 
4049     ga_append(&redir_ga, NUL);  // Append the trailing NUL.
4050     res = redir_ga.ga_data;
4051     redir_ga.ga_data = NULL;
4052     return res;
4053 }
4054 
4055 /*
4056  * "gettabvar()" function
4057  */
4058     void
f_gettabvar(typval_T * argvars,typval_T * rettv)4059 f_gettabvar(typval_T *argvars, typval_T *rettv)
4060 {
4061     win_T	*oldcurwin;
4062     tabpage_T	*tp, *oldtabpage;
4063     dictitem_T	*v;
4064     char_u	*varname;
4065     int		done = FALSE;
4066 
4067     rettv->v_type = VAR_STRING;
4068     rettv->vval.v_string = NULL;
4069 
4070     if (in_vim9script()
4071 	    && (check_for_number_arg(argvars, 0) == FAIL
4072 		|| check_for_string_arg(argvars, 1) == FAIL))
4073 	return;
4074 
4075     varname = tv_get_string_chk(&argvars[1]);
4076     tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
4077     if (tp != NULL && varname != NULL)
4078     {
4079 	// Set tp to be our tabpage, temporarily.  Also set the window to the
4080 	// first window in the tabpage, otherwise the window is not valid.
4081 	if (switch_win(&oldcurwin, &oldtabpage,
4082 		tp == curtab || tp->tp_firstwin == NULL ? firstwin
4083 					    : tp->tp_firstwin, tp, TRUE) == OK)
4084 	{
4085 	    // look up the variable
4086 	    // Let gettabvar({nr}, "") return the "t:" dictionary.
4087 	    v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
4088 	    if (v != NULL)
4089 	    {
4090 		copy_tv(&v->di_tv, rettv);
4091 		done = TRUE;
4092 	    }
4093 	}
4094 
4095 	// restore previous notion of curwin
4096 	restore_win(oldcurwin, oldtabpage, TRUE);
4097     }
4098 
4099     if (!done && argvars[2].v_type != VAR_UNKNOWN)
4100 	copy_tv(&argvars[2], rettv);
4101 }
4102 
4103 /*
4104  * "gettabwinvar()" function
4105  */
4106     void
f_gettabwinvar(typval_T * argvars,typval_T * rettv)4107 f_gettabwinvar(typval_T *argvars, typval_T *rettv)
4108 {
4109     if (in_vim9script()
4110 	    && (check_for_number_arg(argvars, 0) == FAIL
4111 		|| check_for_number_arg(argvars, 1) == FAIL
4112 		|| check_for_string_arg(argvars, 2) == FAIL))
4113 	return;
4114 
4115     getwinvar(argvars, rettv, 1);
4116 }
4117 
4118 /*
4119  * "getwinvar()" function
4120  */
4121     void
f_getwinvar(typval_T * argvars,typval_T * rettv)4122 f_getwinvar(typval_T *argvars, typval_T *rettv)
4123 {
4124     if (in_vim9script()
4125 	    && (check_for_number_arg(argvars, 0) == FAIL
4126 		|| check_for_string_arg(argvars, 1) == FAIL))
4127 	return;
4128 
4129     getwinvar(argvars, rettv, 0);
4130 }
4131 
4132 /*
4133  * "getbufvar()" function
4134  */
4135     void
f_getbufvar(typval_T * argvars,typval_T * rettv)4136 f_getbufvar(typval_T *argvars, typval_T *rettv)
4137 {
4138     buf_T	*buf;
4139     char_u	*varname;
4140     dictitem_T	*v;
4141     int		done = FALSE;
4142 
4143     if (in_vim9script()
4144 	    && (check_for_buffer_arg(argvars, 0) == FAIL
4145 		|| check_for_string_arg(argvars, 1) == FAIL))
4146 	return;
4147 
4148     varname = tv_get_string_chk(&argvars[1]);
4149     buf = tv_get_buf_from_arg(&argvars[0]);
4150 
4151     rettv->v_type = VAR_STRING;
4152     rettv->vval.v_string = NULL;
4153 
4154     if (buf != NULL && varname != NULL)
4155     {
4156 	if (*varname == '&')
4157 	{
4158 	    buf_T	*save_curbuf = curbuf;
4159 
4160 	    // set curbuf to be our buf, temporarily
4161 	    curbuf = buf;
4162 
4163 	    if (varname[1] == NUL)
4164 	    {
4165 		// get all buffer-local options in a dict
4166 		dict_T	*opts = get_winbuf_options(TRUE);
4167 
4168 		if (opts != NULL)
4169 		{
4170 		    rettv_dict_set(rettv, opts);
4171 		    done = TRUE;
4172 		}
4173 	    }
4174 	    else if (eval_option(&varname, rettv, TRUE) == OK)
4175 		// buffer-local-option
4176 		done = TRUE;
4177 
4178 	    // restore previous notion of curbuf
4179 	    curbuf = save_curbuf;
4180 	}
4181 	else
4182 	{
4183 	    // Look up the variable.
4184 	    if (*varname == NUL)
4185 		// Let getbufvar({nr}, "") return the "b:" dictionary.
4186 		v = &buf->b_bufvar;
4187 	    else
4188 		v = find_var_in_ht(&buf->b_vars->dv_hashtab, 'b',
4189 							       varname, FALSE);
4190 	    if (v != NULL)
4191 	    {
4192 		copy_tv(&v->di_tv, rettv);
4193 		done = TRUE;
4194 	    }
4195 	}
4196     }
4197 
4198     if (!done && argvars[2].v_type != VAR_UNKNOWN)
4199 	// use the default value
4200 	copy_tv(&argvars[2], rettv);
4201 }
4202 
4203 /*
4204  * "settabvar()" function
4205  */
4206     void
f_settabvar(typval_T * argvars,typval_T * rettv UNUSED)4207 f_settabvar(typval_T *argvars, typval_T *rettv UNUSED)
4208 {
4209     tabpage_T	*save_curtab;
4210     tabpage_T	*tp;
4211     char_u	*varname, *tabvarname;
4212     typval_T	*varp;
4213 
4214     if (check_secure())
4215 	return;
4216 
4217     if (in_vim9script()
4218 	    && (check_for_number_arg(argvars, 0) == FAIL
4219 		|| check_for_string_arg(argvars, 1) == FAIL))
4220 	return;
4221 
4222     tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
4223     varname = tv_get_string_chk(&argvars[1]);
4224     varp = &argvars[2];
4225 
4226     if (varname != NULL && varp != NULL && tp != NULL)
4227     {
4228 	save_curtab = curtab;
4229 	goto_tabpage_tp(tp, FALSE, FALSE);
4230 
4231 	tabvarname = alloc(STRLEN(varname) + 3);
4232 	if (tabvarname != NULL)
4233 	{
4234 	    STRCPY(tabvarname, "t:");
4235 	    STRCPY(tabvarname + 2, varname);
4236 	    set_var(tabvarname, varp, TRUE);
4237 	    vim_free(tabvarname);
4238 	}
4239 
4240 	// Restore current tabpage
4241 	if (valid_tabpage(save_curtab))
4242 	    goto_tabpage_tp(save_curtab, FALSE, FALSE);
4243     }
4244 }
4245 
4246 /*
4247  * "settabwinvar()" function
4248  */
4249     void
f_settabwinvar(typval_T * argvars,typval_T * rettv UNUSED)4250 f_settabwinvar(typval_T *argvars, typval_T *rettv UNUSED)
4251 {
4252     if (in_vim9script()
4253 	    && (check_for_number_arg(argvars, 0) == FAIL
4254 		|| check_for_number_arg(argvars, 1) == FAIL
4255 		|| check_for_string_arg(argvars, 2) == FAIL))
4256 	return;
4257 
4258     setwinvar(argvars, 1);
4259 }
4260 
4261 /*
4262  * "setwinvar()" function
4263  */
4264     void
f_setwinvar(typval_T * argvars,typval_T * rettv UNUSED)4265 f_setwinvar(typval_T *argvars, typval_T *rettv UNUSED)
4266 {
4267     if (in_vim9script()
4268 	    && (check_for_number_arg(argvars, 0) == FAIL
4269 		|| check_for_string_arg(argvars, 1) == FAIL))
4270 	return;
4271 
4272     setwinvar(argvars, 0);
4273 }
4274 
4275 /*
4276  * "setbufvar()" function
4277  */
4278     void
f_setbufvar(typval_T * argvars,typval_T * rettv UNUSED)4279 f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
4280 {
4281     buf_T	*buf;
4282     char_u	*varname, *bufvarname;
4283     typval_T	*varp;
4284 
4285     if (check_secure())
4286 	return;
4287 
4288     if (in_vim9script()
4289 	    && (check_for_buffer_arg(argvars, 0) == FAIL
4290 		|| check_for_string_arg(argvars, 1) == FAIL))
4291 	return;
4292 
4293     varname = tv_get_string_chk(&argvars[1]);
4294     buf = tv_get_buf_from_arg(&argvars[0]);
4295     varp = &argvars[2];
4296 
4297     if (buf != NULL && varname != NULL && varp != NULL)
4298     {
4299 	if (*varname == '&')
4300 	{
4301 	    aco_save_T	aco;
4302 
4303 	    // set curbuf to be our buf, temporarily
4304 	    aucmd_prepbuf(&aco, buf);
4305 
4306 	    set_option_from_tv(varname + 1, varp);
4307 
4308 	    // reset notion of buffer
4309 	    aucmd_restbuf(&aco);
4310 	}
4311 	else
4312 	{
4313 	    bufvarname = alloc(STRLEN(varname) + 3);
4314 	    if (bufvarname != NULL)
4315 	    {
4316 		buf_T *save_curbuf = curbuf;
4317 
4318 		curbuf = buf;
4319 		STRCPY(bufvarname, "b:");
4320 		STRCPY(bufvarname + 2, varname);
4321 		set_var(bufvarname, varp, TRUE);
4322 		vim_free(bufvarname);
4323 		curbuf = save_curbuf;
4324 	    }
4325 	}
4326     }
4327 }
4328 
4329 /*
4330  * Get a callback from "arg".  It can be a Funcref or a function name.
4331  * When "arg" is zero return an empty string.
4332  * "cb_name" is not allocated.
4333  * "cb_name" is set to NULL for an invalid argument.
4334  */
4335     callback_T
get_callback(typval_T * arg)4336 get_callback(typval_T *arg)
4337 {
4338     callback_T  res;
4339     int		r = OK;
4340 
4341     res.cb_free_name = FALSE;
4342     if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
4343     {
4344 	res.cb_partial = arg->vval.v_partial;
4345 	++res.cb_partial->pt_refcount;
4346 	res.cb_name = partial_name(res.cb_partial);
4347     }
4348     else
4349     {
4350 	res.cb_partial = NULL;
4351 	if (arg->v_type == VAR_STRING && arg->vval.v_string != NULL
4352 					       && isdigit(*arg->vval.v_string))
4353 	    r = FAIL;
4354 	else if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
4355 	{
4356 	    // Note that we don't make a copy of the string.
4357 	    res.cb_name = arg->vval.v_string;
4358 	    func_ref(res.cb_name);
4359 	}
4360 	else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
4361 	    res.cb_name = (char_u *)"";
4362 	else
4363 	    r = FAIL;
4364 
4365 	if (r == FAIL)
4366 	{
4367 	    emsg(_("E921: Invalid callback argument"));
4368 	    res.cb_name = NULL;
4369 	}
4370     }
4371     return res;
4372 }
4373 
4374 /*
4375  * Copy a callback into a typval_T.
4376  */
4377     void
put_callback(callback_T * cb,typval_T * tv)4378 put_callback(callback_T *cb, typval_T *tv)
4379 {
4380     if (cb->cb_partial != NULL)
4381     {
4382 	tv->v_type = VAR_PARTIAL;
4383 	tv->vval.v_partial = cb->cb_partial;
4384 	++tv->vval.v_partial->pt_refcount;
4385     }
4386     else
4387     {
4388 	tv->v_type = VAR_FUNC;
4389 	tv->vval.v_string = vim_strsave(cb->cb_name);
4390 	func_ref(cb->cb_name);
4391     }
4392 }
4393 
4394 /*
4395  * Make a copy of "src" into "dest", allocating the function name if needed,
4396  * without incrementing the refcount.
4397  */
4398     void
set_callback(callback_T * dest,callback_T * src)4399 set_callback(callback_T *dest, callback_T *src)
4400 {
4401     if (src->cb_partial == NULL)
4402     {
4403 	// just a function name, make a copy
4404 	dest->cb_name = vim_strsave(src->cb_name);
4405 	dest->cb_free_name = TRUE;
4406     }
4407     else
4408     {
4409 	// cb_name is a pointer into cb_partial
4410 	dest->cb_name = src->cb_name;
4411 	dest->cb_free_name = FALSE;
4412     }
4413     dest->cb_partial = src->cb_partial;
4414 }
4415 
4416 /*
4417  * Copy callback from "src" to "dest", incrementing the refcounts.
4418  */
4419     void
copy_callback(callback_T * dest,callback_T * src)4420 copy_callback(callback_T *dest, callback_T *src)
4421 {
4422     dest->cb_partial = src->cb_partial;
4423     if (dest->cb_partial != NULL)
4424     {
4425 	dest->cb_name = src->cb_name;
4426 	dest->cb_free_name = FALSE;
4427 	++dest->cb_partial->pt_refcount;
4428     }
4429     else
4430     {
4431 	dest->cb_name = vim_strsave(src->cb_name);
4432 	dest->cb_free_name = TRUE;
4433 	func_ref(src->cb_name);
4434     }
4435 }
4436 
4437 /*
4438  * Unref/free "callback" returned by get_callback() or set_callback().
4439  */
4440     void
free_callback(callback_T * callback)4441 free_callback(callback_T *callback)
4442 {
4443     if (callback->cb_partial != NULL)
4444     {
4445 	partial_unref(callback->cb_partial);
4446 	callback->cb_partial = NULL;
4447     }
4448     else if (callback->cb_name != NULL)
4449 	func_unref(callback->cb_name);
4450     if (callback->cb_free_name)
4451     {
4452 	vim_free(callback->cb_name);
4453 	callback->cb_free_name = FALSE;
4454     }
4455     callback->cb_name = NULL;
4456 }
4457 
4458 #endif // FEAT_EVAL
4459