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