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