blob: d7a565af2096eb17acc21d5c1ecc764d743a1c7c [file] [log] [blame]
Bram Moolenaar0522ba02019-08-27 22:48:30 +02001/* 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
18static char *e_letunexp = N_("E18: Unexpected characters in :let");
19
Bram Moolenaare5cdf152019-08-29 22:09:46 +020020static dictitem_T globvars_var; // variable used for g:
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 */
26static 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
42static struct vimvar
43{
44 char *vv_name; // name of variable, without v:
45 dictitem16_T vv_di; // value and name for key (max 16 chars!)
46 char vv_flags; // VV_COMPAT, VV_RO, VV_RO_SBX
47} vimvars[VV_LEN] =
48{
Bram Moolenaar8d71b542019-08-30 15:46:30 +020049 // The order here must match the VV_ defines in vim.h!
50 // Initializing a union does not work, leave tv.vval empty to get zero's.
Bram Moolenaare5cdf152019-08-29 22:09:46 +020051 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
52 {VV_NAME("count1", VAR_NUMBER), VV_RO},
53 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
54 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
55 {VV_NAME("warningmsg", VAR_STRING), 0},
56 {VV_NAME("statusmsg", VAR_STRING), 0},
57 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
58 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
59 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
60 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
61 {VV_NAME("termresponse", VAR_STRING), VV_RO},
62 {VV_NAME("fname", VAR_STRING), VV_RO},
63 {VV_NAME("lang", VAR_STRING), VV_RO},
64 {VV_NAME("lc_time", VAR_STRING), VV_RO},
65 {VV_NAME("ctype", VAR_STRING), VV_RO},
66 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
67 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
68 {VV_NAME("fname_in", VAR_STRING), VV_RO},
69 {VV_NAME("fname_out", VAR_STRING), VV_RO},
70 {VV_NAME("fname_new", VAR_STRING), VV_RO},
71 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
72 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
73 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
74 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
75 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
76 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
77 {VV_NAME("progname", VAR_STRING), VV_RO},
78 {VV_NAME("servername", VAR_STRING), VV_RO},
79 {VV_NAME("dying", VAR_NUMBER), VV_RO},
80 {VV_NAME("exception", VAR_STRING), VV_RO},
81 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
82 {VV_NAME("register", VAR_STRING), VV_RO},
83 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
84 {VV_NAME("insertmode", VAR_STRING), VV_RO},
85 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
86 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
87 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
88 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
89 {VV_NAME("fcs_choice", VAR_STRING), 0},
90 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
91 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
92 {VV_NAME("beval_winid", VAR_NUMBER), VV_RO},
93 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
94 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
95 {VV_NAME("beval_text", VAR_STRING), VV_RO},
96 {VV_NAME("scrollstart", VAR_STRING), 0},
97 {VV_NAME("swapname", VAR_STRING), VV_RO},
98 {VV_NAME("swapchoice", VAR_STRING), 0},
99 {VV_NAME("swapcommand", VAR_STRING), VV_RO},
100 {VV_NAME("char", VAR_STRING), 0},
101 {VV_NAME("mouse_win", VAR_NUMBER), 0},
102 {VV_NAME("mouse_winid", VAR_NUMBER), 0},
103 {VV_NAME("mouse_lnum", VAR_NUMBER), 0},
104 {VV_NAME("mouse_col", VAR_NUMBER), 0},
105 {VV_NAME("operator", VAR_STRING), VV_RO},
106 {VV_NAME("searchforward", VAR_NUMBER), 0},
107 {VV_NAME("hlsearch", VAR_NUMBER), 0},
108 {VV_NAME("oldfiles", VAR_LIST), 0},
109 {VV_NAME("windowid", VAR_NUMBER), VV_RO},
110 {VV_NAME("progpath", VAR_STRING), VV_RO},
111 {VV_NAME("completed_item", VAR_DICT), VV_RO},
112 {VV_NAME("option_new", VAR_STRING), VV_RO},
113 {VV_NAME("option_old", VAR_STRING), VV_RO},
114 {VV_NAME("option_oldlocal", VAR_STRING), VV_RO},
115 {VV_NAME("option_oldglobal", VAR_STRING), VV_RO},
116 {VV_NAME("option_command", VAR_STRING), VV_RO},
117 {VV_NAME("option_type", VAR_STRING), VV_RO},
118 {VV_NAME("errors", VAR_LIST), 0},
119 {VV_NAME("false", VAR_SPECIAL), VV_RO},
120 {VV_NAME("true", VAR_SPECIAL), VV_RO},
121 {VV_NAME("null", VAR_SPECIAL), VV_RO},
122 {VV_NAME("none", VAR_SPECIAL), VV_RO},
123 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO},
124 {VV_NAME("testing", VAR_NUMBER), 0},
125 {VV_NAME("t_number", VAR_NUMBER), VV_RO},
126 {VV_NAME("t_string", VAR_NUMBER), VV_RO},
127 {VV_NAME("t_func", VAR_NUMBER), VV_RO},
128 {VV_NAME("t_list", VAR_NUMBER), VV_RO},
129 {VV_NAME("t_dict", VAR_NUMBER), VV_RO},
130 {VV_NAME("t_float", VAR_NUMBER), VV_RO},
131 {VV_NAME("t_bool", VAR_NUMBER), VV_RO},
132 {VV_NAME("t_none", VAR_NUMBER), VV_RO},
133 {VV_NAME("t_job", VAR_NUMBER), VV_RO},
134 {VV_NAME("t_channel", VAR_NUMBER), VV_RO},
135 {VV_NAME("t_blob", VAR_NUMBER), VV_RO},
136 {VV_NAME("termrfgresp", VAR_STRING), VV_RO},
137 {VV_NAME("termrbgresp", VAR_STRING), VV_RO},
138 {VV_NAME("termu7resp", VAR_STRING), VV_RO},
139 {VV_NAME("termstyleresp", VAR_STRING), VV_RO},
140 {VV_NAME("termblinkresp", VAR_STRING), VV_RO},
141 {VV_NAME("event", VAR_DICT), VV_RO},
142 {VV_NAME("versionlong", VAR_NUMBER), VV_RO},
143 {VV_NAME("echospace", VAR_NUMBER), VV_RO},
144};
145
146// shorthand
147#define vv_type vv_di.di_tv.v_type
148#define vv_nr vv_di.di_tv.vval.v_number
149#define vv_float vv_di.di_tv.vval.v_float
150#define vv_str vv_di.di_tv.vval.v_string
151#define vv_list vv_di.di_tv.vval.v_list
152#define vv_dict vv_di.di_tv.vval.v_dict
153#define vv_blob vv_di.di_tv.vval.v_blob
154#define vv_tv vv_di.di_tv
155
156static dictitem_T vimvars_var; // variable used for v:
157#define vimvarht vimvardict.dv_hashtab
158
159// for VIM_VERSION_ defines
160#include "version.h"
161
162/*
163 * Array to hold the hashtab with variables local to each sourced script.
164 * Each item holds a variable (nameless) that points to the dict_T.
165 */
166typedef struct
167{
168 dictitem_T sv_var;
169 dict_T sv_dict;
170} scriptvar_T;
171
172static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL};
173#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1])
174#define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab)
175
Bram Moolenaar0522ba02019-08-27 22:48:30 +0200176static void ex_let_const(exarg_T *eap, int is_const);
177static char_u *skip_var_one(char_u *arg);
178static void list_glob_vars(int *first);
179static void list_buf_vars(int *first);
180static void list_win_vars(int *first);
181static void list_tab_vars(int *first);
182static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
183static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op);
184static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
185static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
186static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
187static void item_lock(typval_T *tv, int deep, int lock);
188static void list_one_var(dictitem_T *v, char *prefix, int *first);
189static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
190
191/*
Bram Moolenaare5cdf152019-08-29 22:09:46 +0200192 * Initialize global and vim special variables
193 */
194 void
195evalvars_init(void)
196{
197 int i;
198 struct vimvar *p;
199
200 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
201 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
202 vimvardict.dv_lock = VAR_FIXED;
203 hash_init(&compat_hashtab);
204
205 for (i = 0; i < VV_LEN; ++i)
206 {
207 p = &vimvars[i];
208 if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN)
209 {
210 iemsg("INTERNAL: name too long, increase size of dictitem16_T");
211 getout(1);
212 }
213 STRCPY(p->vv_di.di_key, p->vv_name);
214 if (p->vv_flags & VV_RO)
215 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
216 else if (p->vv_flags & VV_RO_SBX)
217 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
218 else
219 p->vv_di.di_flags = DI_FLAGS_FIX;
220
221 // add to v: scope dict, unless the value is not always available
222 if (p->vv_type != VAR_UNKNOWN)
223 hash_add(&vimvarht, p->vv_di.di_key);
224 if (p->vv_flags & VV_COMPAT)
225 // add to compat scope dict
226 hash_add(&compat_hashtab, p->vv_di.di_key);
227 }
228 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
229 vimvars[VV_VERSIONLONG].vv_nr = VIM_VERSION_100 * 10000 + highest_patch();
230
231 set_vim_var_nr(VV_SEARCHFORWARD, 1L);
232 set_vim_var_nr(VV_HLSEARCH, 1L);
233 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
234 set_vim_var_list(VV_ERRORS, list_alloc());
235 set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
236
237 set_vim_var_nr(VV_FALSE, VVAL_FALSE);
238 set_vim_var_nr(VV_TRUE, VVAL_TRUE);
239 set_vim_var_nr(VV_NONE, VVAL_NONE);
240 set_vim_var_nr(VV_NULL, VVAL_NULL);
241
242 set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER);
243 set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING);
244 set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC);
245 set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST);
246 set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT);
247 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT);
248 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL);
249 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE);
250 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB);
251 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL);
252 set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB);
253
254 set_vim_var_nr(VV_ECHOSPACE, sc_col - 1);
255
256 set_reg_var(0); // default for v:register is not 0 but '"'
257}
258
259#if defined(EXITFREE) || defined(PROTO)
260/*
261 * Free all vim variables information on exit
262 */
263 void
264evalvars_clear(void)
265{
266 int i;
267 struct vimvar *p;
268
269 for (i = 0; i < VV_LEN; ++i)
270 {
271 p = &vimvars[i];
272 if (p->vv_di.di_tv.v_type == VAR_STRING)
273 VIM_CLEAR(p->vv_str);
274 else if (p->vv_di.di_tv.v_type == VAR_LIST)
275 {
276 list_unref(p->vv_list);
277 p->vv_list = NULL;
278 }
279 }
280 hash_clear(&vimvarht);
281 hash_init(&vimvarht); // garbage_collect() will access it
282 hash_clear(&compat_hashtab);
283
284 // global variables
285 vars_clear(&globvarht);
286
287 // Script-local variables. First clear all the variables and in a second
288 // loop free the scriptvar_T, because a variable in one script might hold
289 // a reference to the whole scope of another script.
290 for (i = 1; i <= ga_scripts.ga_len; ++i)
291 vars_clear(&SCRIPT_VARS(i));
292 for (i = 1; i <= ga_scripts.ga_len; ++i)
293 vim_free(SCRIPT_SV(i));
294 ga_clear(&ga_scripts);
295}
296#endif
297
298 int
299garbage_collect_vimvars(int copyID)
300{
301 return set_ref_in_ht(&vimvarht, copyID, NULL);
302}
303
304 int
305garbage_collect_scriptvars(int copyID)
306{
307 int i;
308 int abort = FALSE;
309
310 for (i = 1; i <= ga_scripts.ga_len; ++i)
311 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
312
313 return abort;
314}
315
316/*
317 * Set an internal variable to a string value. Creates the variable if it does
318 * not already exist.
319 */
320 void
321set_internal_string_var(char_u *name, char_u *value)
322{
323 char_u *val;
324 typval_T *tvp;
325
326 val = vim_strsave(value);
327 if (val != NULL)
328 {
329 tvp = alloc_string_tv(val);
330 if (tvp != NULL)
331 {
332 set_var(name, tvp, FALSE);
333 free_tv(tvp);
334 }
335 }
336}
337
338/*
339 * Prepare v: variable "idx" to be used.
340 * Save the current typeval in "save_tv".
341 * When not used yet add the variable to the v: hashtable.
342 */
343 void
344prepare_vimvar(int idx, typval_T *save_tv)
345{
346 *save_tv = vimvars[idx].vv_tv;
347 if (vimvars[idx].vv_type == VAR_UNKNOWN)
348 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
349}
350
351/*
352 * Restore v: variable "idx" to typeval "save_tv".
353 * When no longer defined, remove the variable from the v: hashtable.
354 */
355 void
356restore_vimvar(int idx, typval_T *save_tv)
357{
358 hashitem_T *hi;
359
360 vimvars[idx].vv_tv = *save_tv;
361 if (vimvars[idx].vv_type == VAR_UNKNOWN)
362 {
363 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
364 if (HASHITEM_EMPTY(hi))
365 internal_error("restore_vimvar()");
366 else
367 hash_remove(&vimvarht, hi);
368 }
369}
370
371/*
372 * List Vim variables.
373 */
374 static void
375list_vim_vars(int *first)
376{
377 list_hashtable_vars(&vimvarht, "v:", FALSE, first);
378}
379
380/*
381 * List script-local variables, if there is a script.
382 */
383 static void
384list_script_vars(int *first)
385{
386 if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len)
387 list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid),
388 "s:", FALSE, first);
389}
390
391/*
Bram Moolenaar0522ba02019-08-27 22:48:30 +0200392 * Get a list of lines from a HERE document. The here document is a list of
393 * lines surrounded by a marker.
394 * cmd << {marker}
395 * {line1}
396 * {line2}
397 * ....
398 * {marker}
399 *
400 * The {marker} is a string. If the optional 'trim' word is supplied before the
401 * marker, then the leading indentation before the lines (matching the
402 * indentation in the 'cmd' line) is stripped.
403 * Returns a List with {lines} or NULL.
404 */
405 static list_T *
406heredoc_get(exarg_T *eap, char_u *cmd)
407{
408 char_u *theline;
409 char_u *marker;
410 list_T *l;
411 char_u *p;
412 int marker_indent_len = 0;
413 int text_indent_len = 0;
414 char_u *text_indent = NULL;
415
416 if (eap->getline == NULL)
417 {
418 emsg(_("E991: cannot use =<< here"));
419 return NULL;
420 }
421
422 // Check for the optional 'trim' word before the marker
423 cmd = skipwhite(cmd);
424 if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
425 {
426 cmd = skipwhite(cmd + 4);
427
428 // Trim the indentation from all the lines in the here document.
429 // The amount of indentation trimmed is the same as the indentation of
430 // the first line after the :let command line. To find the end marker
431 // the indent of the :let command line is trimmed.
432 p = *eap->cmdlinep;
433 while (VIM_ISWHITE(*p))
434 {
435 p++;
436 marker_indent_len++;
437 }
438 text_indent_len = -1;
439 }
440
441 // The marker is the next word.
442 if (*cmd != NUL && *cmd != '"')
443 {
444 marker = skipwhite(cmd);
445 p = skiptowhite(marker);
446 if (*skipwhite(p) != NUL && *skipwhite(p) != '"')
447 {
448 emsg(_(e_trailing));
449 return NULL;
450 }
451 *p = NUL;
452 if (vim_islower(*marker))
453 {
454 emsg(_("E221: Marker cannot start with lower case letter"));
455 return NULL;
456 }
457 }
458 else
459 {
460 emsg(_("E172: Missing marker"));
461 return NULL;
462 }
463
464 l = list_alloc();
465 if (l == NULL)
466 return NULL;
467
468 for (;;)
469 {
470 int mi = 0;
471 int ti = 0;
472
473 theline = eap->getline(NUL, eap->cookie, 0, FALSE);
474 if (theline == NULL)
475 {
476 semsg(_("E990: Missing end marker '%s'"), marker);
477 break;
478 }
479
480 // with "trim": skip the indent matching the :let line to find the
481 // marker
482 if (marker_indent_len > 0
483 && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
484 mi = marker_indent_len;
485 if (STRCMP(marker, theline + mi) == 0)
486 {
487 vim_free(theline);
488 break;
489 }
490
491 if (text_indent_len == -1 && *theline != NUL)
492 {
493 // set the text indent from the first line.
494 p = theline;
495 text_indent_len = 0;
496 while (VIM_ISWHITE(*p))
497 {
498 p++;
499 text_indent_len++;
500 }
501 text_indent = vim_strnsave(theline, text_indent_len);
502 }
503 // with "trim": skip the indent matching the first line
504 if (text_indent != NULL)
505 for (ti = 0; ti < text_indent_len; ++ti)
506 if (theline[ti] != text_indent[ti])
507 break;
508
509 if (list_append_string(l, theline + ti, -1) == FAIL)
510 break;
511 vim_free(theline);
512 }
513 vim_free(text_indent);
514
515 return l;
516}
517
518/*
519 * ":let" list all variable values
520 * ":let var1 var2" list variable values
521 * ":let var = expr" assignment command.
522 * ":let var += expr" assignment command.
523 * ":let var -= expr" assignment command.
524 * ":let var *= expr" assignment command.
525 * ":let var /= expr" assignment command.
526 * ":let var %= expr" assignment command.
527 * ":let var .= expr" assignment command.
528 * ":let var ..= expr" assignment command.
529 * ":let [var1, var2] = expr" unpack list.
530 */
531 void
532ex_let(exarg_T *eap)
533{
534 ex_let_const(eap, FALSE);
535}
536
537/*
538 * ":const" list all variable values
539 * ":const var1 var2" list variable values
540 * ":const var = expr" assignment command.
541 * ":const [var1, var2] = expr" unpack list.
542 */
543 void
544ex_const(exarg_T *eap)
545{
546 ex_let_const(eap, TRUE);
547}
548
549 static void
550ex_let_const(exarg_T *eap, int is_const)
551{
552 char_u *arg = eap->arg;
553 char_u *expr = NULL;
554 typval_T rettv;
555 int i;
556 int var_count = 0;
557 int semicolon = 0;
558 char_u op[2];
559 char_u *argend;
560 int first = TRUE;
561 int concat;
562
563 argend = skip_var_list(arg, &var_count, &semicolon);
564 if (argend == NULL)
565 return;
566 if (argend > arg && argend[-1] == '.') // for var.='str'
567 --argend;
568 expr = skipwhite(argend);
569 concat = expr[0] == '.'
570 && ((expr[1] == '=' && current_sctx.sc_version < 2)
571 || (expr[1] == '.' && expr[2] == '='));
572 if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%", *expr) != NULL
573 && expr[1] == '=') || concat))
574 {
575 // ":let" without "=": list variables
576 if (*arg == '[')
577 emsg(_(e_invarg));
578 else if (expr[0] == '.')
579 emsg(_("E985: .= is not supported with script version 2"));
580 else if (!ends_excmd(*arg))
581 // ":let var1 var2"
582 arg = list_arg_vars(eap, arg, &first);
583 else if (!eap->skip)
584 {
585 // ":let"
586 list_glob_vars(&first);
587 list_buf_vars(&first);
588 list_win_vars(&first);
589 list_tab_vars(&first);
590 list_script_vars(&first);
591 list_func_vars(&first);
592 list_vim_vars(&first);
593 }
594 eap->nextcmd = check_nextcmd(arg);
595 }
596 else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
597 {
598 list_T *l;
599
600 // HERE document
601 l = heredoc_get(eap, expr + 3);
602 if (l != NULL)
603 {
604 rettv_list_set(&rettv, l);
605 op[0] = '=';
606 op[1] = NUL;
607 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
608 is_const, op);
609 clear_tv(&rettv);
610 }
611 }
612 else
613 {
614 op[0] = '=';
615 op[1] = NUL;
616 if (*expr != '=')
617 {
618 if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
619 {
620 op[0] = *expr; // +=, -=, *=, /=, %= or .=
621 if (expr[0] == '.' && expr[1] == '.') // ..=
622 ++expr;
623 }
624 expr = skipwhite(expr + 2);
625 }
626 else
627 expr = skipwhite(expr + 1);
628
629 if (eap->skip)
630 ++emsg_skip;
631 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
632 if (eap->skip)
633 {
634 if (i != FAIL)
635 clear_tv(&rettv);
636 --emsg_skip;
637 }
638 else if (i != FAIL)
639 {
640 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
641 is_const, op);
642 clear_tv(&rettv);
643 }
644 }
645}
646
647/*
648 * Assign the typevalue "tv" to the variable or variables at "arg_start".
649 * Handles both "var" with any type and "[var, var; var]" with a list type.
650 * When "op" is not NULL it points to a string with characters that
651 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
652 * or concatenate.
653 * Returns OK or FAIL;
654 */
655 int
656ex_let_vars(
657 char_u *arg_start,
658 typval_T *tv,
659 int copy, // copy values from "tv", don't move
660 int semicolon, // from skip_var_list()
661 int var_count, // from skip_var_list()
662 int is_const, // lock variables for const
663 char_u *op)
664{
665 char_u *arg = arg_start;
666 list_T *l;
667 int i;
668 listitem_T *item;
669 typval_T ltv;
670
671 if (*arg != '[')
672 {
673 // ":let var = expr" or ":for var in list"
674 if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL)
675 return FAIL;
676 return OK;
677 }
678
679 // ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
680 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
681 {
682 emsg(_(e_listreq));
683 return FAIL;
684 }
685
686 i = list_len(l);
687 if (semicolon == 0 && var_count < i)
688 {
689 emsg(_("E687: Less targets than List items"));
690 return FAIL;
691 }
692 if (var_count - semicolon > i)
693 {
694 emsg(_("E688: More targets than List items"));
695 return FAIL;
696 }
697
698 item = l->lv_first;
699 while (*arg != ']')
700 {
701 arg = skipwhite(arg + 1);
702 arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
703 (char_u *)",;]", op);
704 item = item->li_next;
705 if (arg == NULL)
706 return FAIL;
707
708 arg = skipwhite(arg);
709 if (*arg == ';')
710 {
711 // Put the rest of the list (may be empty) in the var after ';'.
712 // Create a new list for this.
713 l = list_alloc();
714 if (l == NULL)
715 return FAIL;
716 while (item != NULL)
717 {
718 list_append_tv(l, &item->li_tv);
719 item = item->li_next;
720 }
721
722 ltv.v_type = VAR_LIST;
723 ltv.v_lock = 0;
724 ltv.vval.v_list = l;
725 l->lv_refcount = 1;
726
727 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, is_const,
728 (char_u *)"]", op);
729 clear_tv(&ltv);
730 if (arg == NULL)
731 return FAIL;
732 break;
733 }
734 else if (*arg != ',' && *arg != ']')
735 {
736 internal_error("ex_let_vars()");
737 return FAIL;
738 }
739 }
740
741 return OK;
742}
743
744/*
745 * Skip over assignable variable "var" or list of variables "[var, var]".
746 * Used for ":let varvar = expr" and ":for varvar in expr".
747 * For "[var, var]" increment "*var_count" for each variable.
748 * for "[var, var; var]" set "semicolon".
749 * Return NULL for an error.
750 */
751 char_u *
752skip_var_list(
753 char_u *arg,
754 int *var_count,
755 int *semicolon)
756{
757 char_u *p, *s;
758
759 if (*arg == '[')
760 {
761 // "[var, var]": find the matching ']'.
762 p = arg;
763 for (;;)
764 {
765 p = skipwhite(p + 1); // skip whites after '[', ';' or ','
766 s = skip_var_one(p);
767 if (s == p)
768 {
769 semsg(_(e_invarg2), p);
770 return NULL;
771 }
772 ++*var_count;
773
774 p = skipwhite(s);
775 if (*p == ']')
776 break;
777 else if (*p == ';')
778 {
779 if (*semicolon == 1)
780 {
781 emsg(_("Double ; in list of variables"));
782 return NULL;
783 }
784 *semicolon = 1;
785 }
786 else if (*p != ',')
787 {
788 semsg(_(e_invarg2), p);
789 return NULL;
790 }
791 }
792 return p + 1;
793 }
794 else
795 return skip_var_one(arg);
796}
797
798/*
799 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
800 * l[idx].
801 */
802 static char_u *
803skip_var_one(char_u *arg)
804{
805 if (*arg == '@' && arg[1] != NUL)
806 return arg + 2;
807 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
808 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
809}
810
811/*
812 * List variables for hashtab "ht" with prefix "prefix".
813 * If "empty" is TRUE also list NULL strings as empty strings.
814 */
815 void
816list_hashtable_vars(
817 hashtab_T *ht,
818 char *prefix,
819 int empty,
820 int *first)
821{
822 hashitem_T *hi;
823 dictitem_T *di;
824 int todo;
825 char_u buf[IOSIZE];
826
827 todo = (int)ht->ht_used;
828 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
829 {
830 if (!HASHITEM_EMPTY(hi))
831 {
832 --todo;
833 di = HI2DI(hi);
834
835 // apply :filter /pat/ to variable name
836 vim_strncpy((char_u *)buf, (char_u *)prefix, IOSIZE - 1);
837 vim_strcat((char_u *)buf, di->di_key, IOSIZE);
838 if (message_filtered(buf))
839 continue;
840
841 if (empty || di->di_tv.v_type != VAR_STRING
842 || di->di_tv.vval.v_string != NULL)
843 list_one_var(di, prefix, first);
844 }
845 }
846}
847
848/*
849 * List global variables.
850 */
851 static void
852list_glob_vars(int *first)
853{
854 list_hashtable_vars(&globvarht, "", TRUE, first);
855}
856
857/*
858 * List buffer variables.
859 */
860 static void
861list_buf_vars(int *first)
862{
863 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", TRUE, first);
864}
865
866/*
867 * List window variables.
868 */
869 static void
870list_win_vars(int *first)
871{
872 list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", TRUE, first);
873}
874
875/*
876 * List tab page variables.
877 */
878 static void
879list_tab_vars(int *first)
880{
881 list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", TRUE, first);
882}
883
884/*
885 * List variables in "arg".
886 */
887 static char_u *
888list_arg_vars(exarg_T *eap, char_u *arg, int *first)
889{
890 int error = FALSE;
891 int len;
892 char_u *name;
893 char_u *name_start;
894 char_u *arg_subsc;
895 char_u *tofree;
896 typval_T tv;
897
898 while (!ends_excmd(*arg) && !got_int)
899 {
900 if (error || eap->skip)
901 {
902 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
903 if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg))
904 {
905 emsg_severe = TRUE;
906 emsg(_(e_trailing));
907 break;
908 }
909 }
910 else
911 {
912 // get_name_len() takes care of expanding curly braces
913 name_start = name = arg;
914 len = get_name_len(&arg, &tofree, TRUE, TRUE);
915 if (len <= 0)
916 {
917 // This is mainly to keep test 49 working: when expanding
918 // curly braces fails overrule the exception error message.
919 if (len < 0 && !aborting())
920 {
921 emsg_severe = TRUE;
922 semsg(_(e_invarg2), arg);
923 break;
924 }
925 error = TRUE;
926 }
927 else
928 {
929 if (tofree != NULL)
930 name = tofree;
931 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
932 error = TRUE;
933 else
934 {
935 // handle d.key, l[idx], f(expr)
936 arg_subsc = arg;
937 if (handle_subscript(&arg, &tv, TRUE, TRUE,
938 name, &name) == FAIL)
939 error = TRUE;
940 else
941 {
942 if (arg == arg_subsc && len == 2 && name[1] == ':')
943 {
944 switch (*name)
945 {
946 case 'g': list_glob_vars(first); break;
947 case 'b': list_buf_vars(first); break;
948 case 'w': list_win_vars(first); break;
949 case 't': list_tab_vars(first); break;
950 case 'v': list_vim_vars(first); break;
951 case 's': list_script_vars(first); break;
952 case 'l': list_func_vars(first); break;
953 default:
954 semsg(_("E738: Can't list variables for %s"), name);
955 }
956 }
957 else
958 {
959 char_u numbuf[NUMBUFLEN];
960 char_u *tf;
961 int c;
962 char_u *s;
963
964 s = echo_string(&tv, &tf, numbuf, 0);
965 c = *arg;
966 *arg = NUL;
967 list_one_var_a("",
968 arg == arg_subsc ? name : name_start,
969 tv.v_type,
970 s == NULL ? (char_u *)"" : s,
971 first);
972 *arg = c;
973 vim_free(tf);
974 }
975 clear_tv(&tv);
976 }
977 }
978 }
979
980 vim_free(tofree);
981 }
982
983 arg = skipwhite(arg);
984 }
985
986 return arg;
987}
988
989/*
990 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
991 * Returns a pointer to the char just after the var name.
992 * Returns NULL if there is an error.
993 */
994 static char_u *
995ex_let_one(
996 char_u *arg, // points to variable name
997 typval_T *tv, // value to assign to variable
998 int copy, // copy value from "tv"
999 int is_const, // lock variable for const
1000 char_u *endchars, // valid chars after variable name or NULL
1001 char_u *op) // "+", "-", "." or NULL
1002{
1003 int c1;
1004 char_u *name;
1005 char_u *p;
1006 char_u *arg_end = NULL;
1007 int len;
1008 int opt_flags;
1009 char_u *tofree = NULL;
1010
1011 // ":let $VAR = expr": Set environment variable.
1012 if (*arg == '$')
1013 {
1014 if (is_const)
1015 {
1016 emsg(_("E996: Cannot lock an environment variable"));
1017 return NULL;
1018 }
1019 // Find the end of the name.
1020 ++arg;
1021 name = arg;
1022 len = get_env_len(&arg);
1023 if (len == 0)
1024 semsg(_(e_invarg2), name - 1);
1025 else
1026 {
1027 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
1028 semsg(_(e_letwrong), op);
1029 else if (endchars != NULL
1030 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
1031 emsg(_(e_letunexp));
1032 else if (!check_secure())
1033 {
1034 c1 = name[len];
1035 name[len] = NUL;
1036 p = tv_get_string_chk(tv);
1037 if (p != NULL && op != NULL && *op == '.')
1038 {
1039 int mustfree = FALSE;
1040 char_u *s = vim_getenv(name, &mustfree);
1041
1042 if (s != NULL)
1043 {
1044 p = tofree = concat_str(s, p);
1045 if (mustfree)
1046 vim_free(s);
1047 }
1048 }
1049 if (p != NULL)
1050 {
1051 vim_setenv(name, p);
1052 if (STRICMP(name, "HOME") == 0)
1053 init_homedir();
1054 else if (didset_vim && STRICMP(name, "VIM") == 0)
1055 didset_vim = FALSE;
1056 else if (didset_vimruntime
1057 && STRICMP(name, "VIMRUNTIME") == 0)
1058 didset_vimruntime = FALSE;
1059 arg_end = arg;
1060 }
1061 name[len] = c1;
1062 vim_free(tofree);
1063 }
1064 }
1065 }
1066
1067 // ":let &option = expr": Set option value.
1068 // ":let &l:option = expr": Set local option value.
1069 // ":let &g:option = expr": Set global option value.
1070 else if (*arg == '&')
1071 {
1072 if (is_const)
1073 {
1074 emsg(_("E996: Cannot lock an option"));
1075 return NULL;
1076 }
1077 // Find the end of the name.
1078 p = find_option_end(&arg, &opt_flags);
1079 if (p == NULL || (endchars != NULL
1080 && vim_strchr(endchars, *skipwhite(p)) == NULL))
1081 emsg(_(e_letunexp));
1082 else
1083 {
1084 long n;
1085 int opt_type;
1086 long numval;
1087 char_u *stringval = NULL;
1088 char_u *s;
1089
1090 c1 = *p;
1091 *p = NUL;
1092
1093 n = (long)tv_get_number(tv);
1094 s = tv_get_string_chk(tv); // != NULL if number or string
1095 if (s != NULL && op != NULL && *op != '=')
1096 {
1097 opt_type = get_option_value(arg, &numval,
1098 &stringval, opt_flags);
1099 if ((opt_type == 1 && *op == '.')
1100 || (opt_type == 0 && *op != '.'))
1101 {
1102 semsg(_(e_letwrong), op);
1103 s = NULL; // don't set the value
1104 }
1105 else
1106 {
1107 if (opt_type == 1) // number
1108 {
1109 switch (*op)
1110 {
1111 case '+': n = numval + n; break;
1112 case '-': n = numval - n; break;
1113 case '*': n = numval * n; break;
1114 case '/': n = (long)num_divide(numval, n); break;
1115 case '%': n = (long)num_modulus(numval, n); break;
1116 }
1117 }
1118 else if (opt_type == 0 && stringval != NULL) // string
1119 {
1120 s = concat_str(stringval, s);
1121 vim_free(stringval);
1122 stringval = s;
1123 }
1124 }
1125 }
1126 if (s != NULL)
1127 {
1128 set_option_value(arg, n, s, opt_flags);
1129 arg_end = p;
1130 }
1131 *p = c1;
1132 vim_free(stringval);
1133 }
1134 }
1135
1136 // ":let @r = expr": Set register contents.
1137 else if (*arg == '@')
1138 {
1139 if (is_const)
1140 {
1141 emsg(_("E996: Cannot lock a register"));
1142 return NULL;
1143 }
1144 ++arg;
1145 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
1146 semsg(_(e_letwrong), op);
1147 else if (endchars != NULL
1148 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
1149 emsg(_(e_letunexp));
1150 else
1151 {
1152 char_u *ptofree = NULL;
1153 char_u *s;
1154
1155 p = tv_get_string_chk(tv);
1156 if (p != NULL && op != NULL && *op == '.')
1157 {
1158 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
1159 if (s != NULL)
1160 {
1161 p = ptofree = concat_str(s, p);
1162 vim_free(s);
1163 }
1164 }
1165 if (p != NULL)
1166 {
1167 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
1168 arg_end = arg + 1;
1169 }
1170 vim_free(ptofree);
1171 }
1172 }
1173
1174 // ":let var = expr": Set internal variable.
1175 // ":let {expr} = expr": Idem, name made with curly braces
1176 else if (eval_isnamec1(*arg) || *arg == '{')
1177 {
1178 lval_T lv;
1179
1180 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
1181 if (p != NULL && lv.ll_name != NULL)
1182 {
1183 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1184 emsg(_(e_letunexp));
1185 else
1186 {
1187 set_var_lval(&lv, p, tv, copy, is_const, op);
1188 arg_end = p;
1189 }
1190 }
1191 clear_lval(&lv);
1192 }
1193
1194 else
1195 semsg(_(e_invarg2), arg);
1196
1197 return arg_end;
1198}
1199
1200/*
1201 * ":unlet[!] var1 ... " command.
1202 */
1203 void
1204ex_unlet(exarg_T *eap)
1205{
1206 ex_unletlock(eap, eap->arg, 0);
1207}
1208
1209/*
1210 * ":lockvar" and ":unlockvar" commands
1211 */
1212 void
1213ex_lockvar(exarg_T *eap)
1214{
1215 char_u *arg = eap->arg;
1216 int deep = 2;
1217
1218 if (eap->forceit)
1219 deep = -1;
1220 else if (vim_isdigit(*arg))
1221 {
1222 deep = getdigits(&arg);
1223 arg = skipwhite(arg);
1224 }
1225
1226 ex_unletlock(eap, arg, deep);
1227}
1228
1229/*
1230 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
1231 */
1232 static void
1233ex_unletlock(
1234 exarg_T *eap,
1235 char_u *argstart,
1236 int deep)
1237{
1238 char_u *arg = argstart;
1239 char_u *name_end;
1240 int error = FALSE;
1241 lval_T lv;
1242
1243 do
1244 {
1245 if (*arg == '$')
1246 {
1247 char_u *name = ++arg;
1248
1249 if (get_env_len(&arg) == 0)
1250 {
1251 semsg(_(e_invarg2), name - 1);
1252 return;
1253 }
1254 vim_unsetenv(name);
1255 arg = skipwhite(arg);
1256 continue;
1257 }
1258
1259 // Parse the name and find the end.
1260 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
1261 FNE_CHECK_START);
1262 if (lv.ll_name == NULL)
1263 error = TRUE; // error but continue parsing
1264 if (name_end == NULL || (!VIM_ISWHITE(*name_end)
1265 && !ends_excmd(*name_end)))
1266 {
1267 if (name_end != NULL)
1268 {
1269 emsg_severe = TRUE;
1270 emsg(_(e_trailing));
1271 }
1272 if (!(eap->skip || error))
1273 clear_lval(&lv);
1274 break;
1275 }
1276
1277 if (!error && !eap->skip)
1278 {
1279 if (eap->cmdidx == CMD_unlet)
1280 {
1281 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
1282 error = TRUE;
1283 }
1284 else
1285 {
1286 if (do_lock_var(&lv, name_end, deep,
1287 eap->cmdidx == CMD_lockvar) == FAIL)
1288 error = TRUE;
1289 }
1290 }
1291
1292 if (!eap->skip)
1293 clear_lval(&lv);
1294
1295 arg = skipwhite(name_end);
1296 } while (!ends_excmd(*arg));
1297
1298 eap->nextcmd = check_nextcmd(arg);
1299}
1300
1301 static int
1302do_unlet_var(
1303 lval_T *lp,
1304 char_u *name_end,
1305 int forceit)
1306{
1307 int ret = OK;
1308 int cc;
1309
1310 if (lp->ll_tv == NULL)
1311 {
1312 cc = *name_end;
1313 *name_end = NUL;
1314
1315 // Normal name or expanded name.
1316 if (do_unlet(lp->ll_name, forceit) == FAIL)
1317 ret = FAIL;
1318 *name_end = cc;
1319 }
1320 else if ((lp->ll_list != NULL
1321 && var_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
1322 || (lp->ll_dict != NULL
1323 && var_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
1324 return FAIL;
1325 else if (lp->ll_range)
1326 {
1327 listitem_T *li;
1328 listitem_T *ll_li = lp->ll_li;
1329 int ll_n1 = lp->ll_n1;
1330
1331 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
1332 {
1333 li = ll_li->li_next;
1334 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
1335 return FAIL;
1336 ll_li = li;
1337 ++ll_n1;
1338 }
1339
1340 // Delete a range of List items.
1341 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
1342 {
1343 li = lp->ll_li->li_next;
1344 listitem_remove(lp->ll_list, lp->ll_li);
1345 lp->ll_li = li;
1346 ++lp->ll_n1;
1347 }
1348 }
1349 else
1350 {
1351 if (lp->ll_list != NULL)
1352 // unlet a List item.
1353 listitem_remove(lp->ll_list, lp->ll_li);
1354 else
1355 // unlet a Dictionary item.
1356 dictitem_remove(lp->ll_dict, lp->ll_di);
1357 }
1358
1359 return ret;
1360}
1361
1362/*
1363 * "unlet" a variable. Return OK if it existed, FAIL if not.
1364 * When "forceit" is TRUE don't complain if the variable doesn't exist.
1365 */
1366 int
1367do_unlet(char_u *name, int forceit)
1368{
1369 hashtab_T *ht;
1370 hashitem_T *hi;
1371 char_u *varname;
1372 dict_T *d;
1373 dictitem_T *di;
1374
1375 ht = find_var_ht(name, &varname);
1376 if (ht != NULL && *varname != NUL)
1377 {
1378 d = get_current_funccal_dict(ht);
1379 if (d == NULL)
1380 {
1381 if (ht == &globvarht)
1382 d = &globvardict;
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001383 else if (ht == &compat_hashtab)
Bram Moolenaar0522ba02019-08-27 22:48:30 +02001384 d = &vimvardict;
1385 else
1386 {
1387 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
1388 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
1389 }
1390 if (d == NULL)
1391 {
1392 internal_error("do_unlet()");
1393 return FAIL;
1394 }
1395 }
1396 hi = hash_find(ht, varname);
1397 if (HASHITEM_EMPTY(hi))
1398 hi = find_hi_in_scoped_ht(name, &ht);
1399 if (hi != NULL && !HASHITEM_EMPTY(hi))
1400 {
1401 di = HI2DI(hi);
1402 if (var_check_fixed(di->di_flags, name, FALSE)
1403 || var_check_ro(di->di_flags, name, FALSE)
1404 || var_check_lock(d->dv_lock, name, FALSE))
1405 return FAIL;
1406
1407 delete_var(ht, hi);
1408 return OK;
1409 }
1410 }
1411 if (forceit)
1412 return OK;
1413 semsg(_("E108: No such variable: \"%s\""), name);
1414 return FAIL;
1415}
1416
1417/*
1418 * Lock or unlock variable indicated by "lp".
1419 * "deep" is the levels to go (-1 for unlimited);
1420 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
1421 */
1422 static int
1423do_lock_var(
1424 lval_T *lp,
1425 char_u *name_end,
1426 int deep,
1427 int lock)
1428{
1429 int ret = OK;
1430 int cc;
1431 dictitem_T *di;
1432
1433 if (deep == 0) // nothing to do
1434 return OK;
1435
1436 if (lp->ll_tv == NULL)
1437 {
1438 cc = *name_end;
1439 *name_end = NUL;
1440
1441 // Normal name or expanded name.
1442 di = find_var(lp->ll_name, NULL, TRUE);
1443 if (di == NULL)
1444 ret = FAIL;
1445 else if ((di->di_flags & DI_FLAGS_FIX)
1446 && di->di_tv.v_type != VAR_DICT
1447 && di->di_tv.v_type != VAR_LIST)
1448 // For historic reasons this error is not given for a list or dict.
1449 // E.g., the b: dict could be locked/unlocked.
1450 semsg(_("E940: Cannot lock or unlock variable %s"), lp->ll_name);
1451 else
1452 {
1453 if (lock)
1454 di->di_flags |= DI_FLAGS_LOCK;
1455 else
1456 di->di_flags &= ~DI_FLAGS_LOCK;
1457 item_lock(&di->di_tv, deep, lock);
1458 }
1459 *name_end = cc;
1460 }
1461 else if (lp->ll_range)
1462 {
1463 listitem_T *li = lp->ll_li;
1464
1465 // (un)lock a range of List items.
1466 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
1467 {
1468 item_lock(&li->li_tv, deep, lock);
1469 li = li->li_next;
1470 ++lp->ll_n1;
1471 }
1472 }
1473 else if (lp->ll_list != NULL)
1474 // (un)lock a List item.
1475 item_lock(&lp->ll_li->li_tv, deep, lock);
1476 else
1477 // (un)lock a Dictionary item.
1478 item_lock(&lp->ll_di->di_tv, deep, lock);
1479
1480 return ret;
1481}
1482
1483/*
1484 * Lock or unlock an item. "deep" is nr of levels to go.
1485 */
1486 static void
1487item_lock(typval_T *tv, int deep, int lock)
1488{
1489 static int recurse = 0;
1490 list_T *l;
1491 listitem_T *li;
1492 dict_T *d;
1493 blob_T *b;
1494 hashitem_T *hi;
1495 int todo;
1496
1497 if (recurse >= DICT_MAXNEST)
1498 {
1499 emsg(_("E743: variable nested too deep for (un)lock"));
1500 return;
1501 }
1502 if (deep == 0)
1503 return;
1504 ++recurse;
1505
1506 // lock/unlock the item itself
1507 if (lock)
1508 tv->v_lock |= VAR_LOCKED;
1509 else
1510 tv->v_lock &= ~VAR_LOCKED;
1511
1512 switch (tv->v_type)
1513 {
1514 case VAR_UNKNOWN:
1515 case VAR_NUMBER:
1516 case VAR_STRING:
1517 case VAR_FUNC:
1518 case VAR_PARTIAL:
1519 case VAR_FLOAT:
1520 case VAR_SPECIAL:
1521 case VAR_JOB:
1522 case VAR_CHANNEL:
1523 break;
1524
1525 case VAR_BLOB:
1526 if ((b = tv->vval.v_blob) != NULL)
1527 {
1528 if (lock)
1529 b->bv_lock |= VAR_LOCKED;
1530 else
1531 b->bv_lock &= ~VAR_LOCKED;
1532 }
1533 break;
1534 case VAR_LIST:
1535 if ((l = tv->vval.v_list) != NULL)
1536 {
1537 if (lock)
1538 l->lv_lock |= VAR_LOCKED;
1539 else
1540 l->lv_lock &= ~VAR_LOCKED;
1541 if (deep < 0 || deep > 1)
1542 // recursive: lock/unlock the items the List contains
1543 for (li = l->lv_first; li != NULL; li = li->li_next)
1544 item_lock(&li->li_tv, deep - 1, lock);
1545 }
1546 break;
1547 case VAR_DICT:
1548 if ((d = tv->vval.v_dict) != NULL)
1549 {
1550 if (lock)
1551 d->dv_lock |= VAR_LOCKED;
1552 else
1553 d->dv_lock &= ~VAR_LOCKED;
1554 if (deep < 0 || deep > 1)
1555 {
1556 // recursive: lock/unlock the items the List contains
1557 todo = (int)d->dv_hashtab.ht_used;
1558 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
1559 {
1560 if (!HASHITEM_EMPTY(hi))
1561 {
1562 --todo;
1563 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
1564 }
1565 }
1566 }
1567 }
1568 }
1569 --recurse;
1570}
1571
1572/*
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001573 * Local string buffer for the next two functions to store a variable name
1574 * with its prefix. Allocated in cat_prefix_varname(), freed later in
1575 * get_user_var_name().
1576 */
1577
1578static char_u *varnamebuf = NULL;
1579static int varnamebuflen = 0;
1580
1581/*
1582 * Function to concatenate a prefix and a variable name.
1583 */
1584 static char_u *
1585cat_prefix_varname(int prefix, char_u *name)
1586{
1587 int len;
1588
1589 len = (int)STRLEN(name) + 3;
1590 if (len > varnamebuflen)
1591 {
1592 vim_free(varnamebuf);
Bram Moolenaar8d71b542019-08-30 15:46:30 +02001593 len += 10; // some additional space
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001594 varnamebuf = alloc(len);
1595 if (varnamebuf == NULL)
1596 {
1597 varnamebuflen = 0;
1598 return NULL;
1599 }
1600 varnamebuflen = len;
1601 }
1602 *varnamebuf = prefix;
1603 varnamebuf[1] = ':';
1604 STRCPY(varnamebuf + 2, name);
1605 return varnamebuf;
1606}
1607
1608/*
1609 * Function given to ExpandGeneric() to obtain the list of user defined
1610 * (global/buffer/window/built-in) variable names.
1611 */
1612 char_u *
1613get_user_var_name(expand_T *xp, int idx)
1614{
1615 static long_u gdone;
1616 static long_u bdone;
1617 static long_u wdone;
1618 static long_u tdone;
1619 static int vidx;
1620 static hashitem_T *hi;
1621 hashtab_T *ht;
1622
1623 if (idx == 0)
1624 {
1625 gdone = bdone = wdone = vidx = 0;
1626 tdone = 0;
1627 }
1628
1629 // Global variables
1630 if (gdone < globvarht.ht_used)
1631 {
1632 if (gdone++ == 0)
1633 hi = globvarht.ht_array;
1634 else
1635 ++hi;
1636 while (HASHITEM_EMPTY(hi))
1637 ++hi;
1638 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
1639 return cat_prefix_varname('g', hi->hi_key);
1640 return hi->hi_key;
1641 }
1642
1643 // b: variables
1644 ht = &curbuf->b_vars->dv_hashtab;
1645 if (bdone < ht->ht_used)
1646 {
1647 if (bdone++ == 0)
1648 hi = ht->ht_array;
1649 else
1650 ++hi;
1651 while (HASHITEM_EMPTY(hi))
1652 ++hi;
1653 return cat_prefix_varname('b', hi->hi_key);
1654 }
1655
1656 // w: variables
1657 ht = &curwin->w_vars->dv_hashtab;
1658 if (wdone < ht->ht_used)
1659 {
1660 if (wdone++ == 0)
1661 hi = ht->ht_array;
1662 else
1663 ++hi;
1664 while (HASHITEM_EMPTY(hi))
1665 ++hi;
1666 return cat_prefix_varname('w', hi->hi_key);
1667 }
1668
1669 // t: variables
1670 ht = &curtab->tp_vars->dv_hashtab;
1671 if (tdone < ht->ht_used)
1672 {
1673 if (tdone++ == 0)
1674 hi = ht->ht_array;
1675 else
1676 ++hi;
1677 while (HASHITEM_EMPTY(hi))
1678 ++hi;
1679 return cat_prefix_varname('t', hi->hi_key);
1680 }
1681
1682 // v: variables
1683 if (vidx < VV_LEN)
1684 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
1685
1686 VIM_CLEAR(varnamebuf);
1687 varnamebuflen = 0;
1688 return NULL;
1689}
1690
1691/*
Bram Moolenaar34ed68d2019-08-29 22:48:24 +02001692 * Set type of v: variable to "type".
1693 */
1694 void
1695set_vim_var_type(int idx, vartype_T type)
1696{
1697 vimvars[idx].vv_type = type;
1698}
1699
1700/*
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001701 * Set number v: variable to "val".
Bram Moolenaar8d71b542019-08-30 15:46:30 +02001702 * Note that this does not set the type, use set_vim_var_type() for that.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001703 */
1704 void
1705set_vim_var_nr(int idx, varnumber_T val)
1706{
Bram Moolenaare5cdf152019-08-29 22:09:46 +02001707 vimvars[idx].vv_nr = val;
1708}
1709
1710/*
1711 * Get typval_T v: variable value.
1712 */
1713 typval_T *
1714get_vim_var_tv(int idx)
1715{
1716 return &vimvars[idx].vv_tv;
1717}
1718
1719/*
1720 * Get number v: variable value.
1721 */
1722 varnumber_T
1723get_vim_var_nr(int idx)
1724{
1725 return vimvars[idx].vv_nr;
1726}
1727
1728/*
1729 * Get string v: variable value. Uses a static buffer, can only be used once.
1730 * If the String variable has never been set, return an empty string.
1731 * Never returns NULL;
1732 */
1733 char_u *
1734get_vim_var_str(int idx)
1735{
1736 return tv_get_string(&vimvars[idx].vv_tv);
1737}
1738
1739/*
1740 * Get List v: variable value. Caller must take care of reference count when
1741 * needed.
1742 */
1743 list_T *
1744get_vim_var_list(int idx)
1745{
1746 return vimvars[idx].vv_list;
1747}
1748
1749/*
1750 * Get Dict v: variable value. Caller must take care of reference count when
1751 * needed.
1752 */
1753 dict_T *
1754get_vim_var_dict(int idx)
1755{
1756 return vimvars[idx].vv_dict;
1757}
1758
1759/*
1760 * Set v:char to character "c".
1761 */
1762 void
1763set_vim_var_char(int c)
1764{
1765 char_u buf[MB_MAXBYTES + 1];
1766
1767 if (has_mbyte)
1768 buf[(*mb_char2bytes)(c, buf)] = NUL;
1769 else
1770 {
1771 buf[0] = c;
1772 buf[1] = NUL;
1773 }
1774 set_vim_var_string(VV_CHAR, buf, -1);
1775}
1776
1777/*
1778 * Set v:count to "count" and v:count1 to "count1".
1779 * When "set_prevcount" is TRUE first set v:prevcount from v:count.
1780 */
1781 void
1782set_vcount(
1783 long count,
1784 long count1,
1785 int set_prevcount)
1786{
1787 if (set_prevcount)
1788 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
1789 vimvars[VV_COUNT].vv_nr = count;
1790 vimvars[VV_COUNT1].vv_nr = count1;
1791}
1792
1793/*
1794 * Save variables that might be changed as a side effect. Used when executing
1795 * a timer callback.
1796 */
1797 void
1798save_vimvars(vimvars_save_T *vvsave)
1799{
1800 vvsave->vv_prevcount = vimvars[VV_PREVCOUNT].vv_nr;
1801 vvsave->vv_count = vimvars[VV_COUNT].vv_nr;
1802 vvsave->vv_count1 = vimvars[VV_COUNT1].vv_nr;
1803}
1804
1805/*
1806 * Restore variables saved by save_vimvars().
1807 */
1808 void
1809restore_vimvars(vimvars_save_T *vvsave)
1810{
1811 vimvars[VV_PREVCOUNT].vv_nr = vvsave->vv_prevcount;
1812 vimvars[VV_COUNT].vv_nr = vvsave->vv_count;
1813 vimvars[VV_COUNT1].vv_nr = vvsave->vv_count1;
1814}
1815
1816/*
1817 * Set string v: variable to a copy of "val". If 'copy' is FALSE, then set the
1818 * value.
1819 */
1820 void
1821set_vim_var_string(
1822 int idx,
1823 char_u *val,
1824 int len) // length of "val" to use or -1 (whole string)
1825{
1826 clear_tv(&vimvars[idx].vv_di.di_tv);
1827 vimvars[idx].vv_type = VAR_STRING;
1828 if (val == NULL)
1829 vimvars[idx].vv_str = NULL;
1830 else if (len == -1)
1831 vimvars[idx].vv_str = vim_strsave(val);
1832 else
1833 vimvars[idx].vv_str = vim_strnsave(val, len);
1834}
1835
1836/*
1837 * Set List v: variable to "val".
1838 */
1839 void
1840set_vim_var_list(int idx, list_T *val)
1841{
1842 clear_tv(&vimvars[idx].vv_di.di_tv);
1843 vimvars[idx].vv_type = VAR_LIST;
1844 vimvars[idx].vv_list = val;
1845 if (val != NULL)
1846 ++val->lv_refcount;
1847}
1848
1849/*
1850 * Set Dictionary v: variable to "val".
1851 */
1852 void
1853set_vim_var_dict(int idx, dict_T *val)
1854{
1855 clear_tv(&vimvars[idx].vv_di.di_tv);
1856 vimvars[idx].vv_type = VAR_DICT;
1857 vimvars[idx].vv_dict = val;
1858 if (val != NULL)
1859 {
1860 ++val->dv_refcount;
1861 dict_set_items_ro(val);
1862 }
1863}
1864
1865/*
1866 * Set v:register if needed.
1867 */
1868 void
1869set_reg_var(int c)
1870{
1871 char_u regname;
1872
1873 if (c == 0 || c == ' ')
1874 regname = '"';
1875 else
1876 regname = c;
1877 // Avoid free/alloc when the value is already right.
1878 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
1879 set_vim_var_string(VV_REG, &regname, 1);
1880}
1881
1882/*
1883 * Get or set v:exception. If "oldval" == NULL, return the current value.
1884 * Otherwise, restore the value to "oldval" and return NULL.
1885 * Must always be called in pairs to save and restore v:exception! Does not
1886 * take care of memory allocations.
1887 */
1888 char_u *
1889v_exception(char_u *oldval)
1890{
1891 if (oldval == NULL)
1892 return vimvars[VV_EXCEPTION].vv_str;
1893
1894 vimvars[VV_EXCEPTION].vv_str = oldval;
1895 return NULL;
1896}
1897
1898/*
1899 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
1900 * Otherwise, restore the value to "oldval" and return NULL.
1901 * Must always be called in pairs to save and restore v:throwpoint! Does not
1902 * take care of memory allocations.
1903 */
1904 char_u *
1905v_throwpoint(char_u *oldval)
1906{
1907 if (oldval == NULL)
1908 return vimvars[VV_THROWPOINT].vv_str;
1909
1910 vimvars[VV_THROWPOINT].vv_str = oldval;
1911 return NULL;
1912}
1913
1914/*
1915 * Set v:cmdarg.
1916 * If "eap" != NULL, use "eap" to generate the value and return the old value.
1917 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
1918 * Must always be called in pairs!
1919 */
1920 char_u *
1921set_cmdarg(exarg_T *eap, char_u *oldarg)
1922{
1923 char_u *oldval;
1924 char_u *newval;
1925 unsigned len;
1926
1927 oldval = vimvars[VV_CMDARG].vv_str;
1928 if (eap == NULL)
1929 {
1930 vim_free(oldval);
1931 vimvars[VV_CMDARG].vv_str = oldarg;
1932 return NULL;
1933 }
1934
1935 if (eap->force_bin == FORCE_BIN)
1936 len = 6;
1937 else if (eap->force_bin == FORCE_NOBIN)
1938 len = 8;
1939 else
1940 len = 0;
1941
1942 if (eap->read_edit)
1943 len += 7;
1944
1945 if (eap->force_ff != 0)
1946 len += 10; // " ++ff=unix"
1947 if (eap->force_enc != 0)
1948 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
1949 if (eap->bad_char != 0)
1950 len += 7 + 4; // " ++bad=" + "keep" or "drop"
1951
1952 newval = alloc(len + 1);
1953 if (newval == NULL)
1954 return NULL;
1955
1956 if (eap->force_bin == FORCE_BIN)
1957 sprintf((char *)newval, " ++bin");
1958 else if (eap->force_bin == FORCE_NOBIN)
1959 sprintf((char *)newval, " ++nobin");
1960 else
1961 *newval = NUL;
1962
1963 if (eap->read_edit)
1964 STRCAT(newval, " ++edit");
1965
1966 if (eap->force_ff != 0)
1967 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
1968 eap->force_ff == 'u' ? "unix"
1969 : eap->force_ff == 'd' ? "dos"
1970 : "mac");
1971 if (eap->force_enc != 0)
1972 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
1973 eap->cmd + eap->force_enc);
1974 if (eap->bad_char == BAD_KEEP)
1975 STRCPY(newval + STRLEN(newval), " ++bad=keep");
1976 else if (eap->bad_char == BAD_DROP)
1977 STRCPY(newval + STRLEN(newval), " ++bad=drop");
1978 else if (eap->bad_char != 0)
1979 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char);
1980 vimvars[VV_CMDARG].vv_str = newval;
1981 return oldval;
1982}
1983
1984/*
Bram Moolenaar0522ba02019-08-27 22:48:30 +02001985 * Get the value of internal variable "name".
1986 * Return OK or FAIL. If OK is returned "rettv" must be cleared.
1987 */
1988 int
1989get_var_tv(
1990 char_u *name,
1991 int len, // length of "name"
1992 typval_T *rettv, // NULL when only checking existence
1993 dictitem_T **dip, // non-NULL when typval's dict item is needed
1994 int verbose, // may give error message
1995 int no_autoload) // do not use script autoloading
1996{
1997 int ret = OK;
1998 typval_T *tv = NULL;
1999 dictitem_T *v;
2000 int cc;
2001
2002 // truncate the name, so that we can use strcmp()
2003 cc = name[len];
2004 name[len] = NUL;
2005
2006 // Check for user-defined variables.
2007 v = find_var(name, NULL, no_autoload);
2008 if (v != NULL)
2009 {
2010 tv = &v->di_tv;
2011 if (dip != NULL)
2012 *dip = v;
2013 }
2014
2015 if (tv == NULL)
2016 {
2017 if (rettv != NULL && verbose)
2018 semsg(_(e_undefvar), name);
2019 ret = FAIL;
2020 }
2021 else if (rettv != NULL)
2022 copy_tv(tv, rettv);
2023
2024 name[len] = cc;
2025
2026 return ret;
2027}
2028
2029/*
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002030 * Check if variable "name[len]" is a local variable or an argument.
2031 * If so, "*eval_lavars_used" is set to TRUE.
2032 */
2033 void
2034check_vars(char_u *name, int len)
2035{
2036 int cc;
2037 char_u *varname;
2038 hashtab_T *ht;
2039
2040 if (eval_lavars_used == NULL)
2041 return;
2042
2043 // truncate the name, so that we can use strcmp()
2044 cc = name[len];
2045 name[len] = NUL;
2046
2047 ht = find_var_ht(name, &varname);
2048 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht())
2049 {
2050 if (find_var(name, NULL, TRUE) != NULL)
2051 *eval_lavars_used = TRUE;
2052 }
2053
2054 name[len] = cc;
2055}
2056
2057/*
2058 * Find variable "name" in the list of variables.
2059 * Return a pointer to it if found, NULL if not found.
2060 * Careful: "a:0" variables don't have a name.
2061 * When "htp" is not NULL we are writing to the variable, set "htp" to the
2062 * hashtab_T used.
2063 */
2064 dictitem_T *
2065find_var(char_u *name, hashtab_T **htp, int no_autoload)
2066{
2067 char_u *varname;
2068 hashtab_T *ht;
2069 dictitem_T *ret = NULL;
2070
2071 ht = find_var_ht(name, &varname);
2072 if (htp != NULL)
2073 *htp = ht;
2074 if (ht == NULL)
2075 return NULL;
2076 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
2077 if (ret != NULL)
2078 return ret;
2079
Bram Moolenaar8d71b542019-08-30 15:46:30 +02002080 // Search in parent scope for lambda
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002081 return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
2082}
2083
2084/*
2085 * Find variable "varname" in hashtab "ht" with name "htname".
2086 * Returns NULL if not found.
2087 */
2088 dictitem_T *
2089find_var_in_ht(
2090 hashtab_T *ht,
2091 int htname,
2092 char_u *varname,
2093 int no_autoload)
2094{
2095 hashitem_T *hi;
2096
2097 if (*varname == NUL)
2098 {
2099 // Must be something like "s:", otherwise "ht" would be NULL.
2100 switch (htname)
2101 {
2102 case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var;
2103 case 'g': return &globvars_var;
2104 case 'v': return &vimvars_var;
2105 case 'b': return &curbuf->b_bufvar;
2106 case 'w': return &curwin->w_winvar;
2107 case 't': return &curtab->tp_winvar;
2108 case 'l': return get_funccal_local_var();
2109 case 'a': return get_funccal_args_var();
2110 }
2111 return NULL;
2112 }
2113
2114 hi = hash_find(ht, varname);
2115 if (HASHITEM_EMPTY(hi))
2116 {
2117 // For global variables we may try auto-loading the script. If it
2118 // worked find the variable again. Don't auto-load a script if it was
2119 // loaded already, otherwise it would be loaded every time when
2120 // checking if a function name is a Funcref variable.
2121 if (ht == &globvarht && !no_autoload)
2122 {
2123 // Note: script_autoload() may make "hi" invalid. It must either
2124 // be obtained again or not used.
2125 if (!script_autoload(varname, FALSE) || aborting())
2126 return NULL;
2127 hi = hash_find(ht, varname);
2128 }
2129 if (HASHITEM_EMPTY(hi))
2130 return NULL;
2131 }
2132 return HI2DI(hi);
2133}
2134
2135/*
2136 * Find the hashtab used for a variable name.
2137 * Return NULL if the name is not valid.
2138 * Set "varname" to the start of name without ':'.
2139 */
2140 hashtab_T *
2141find_var_ht(char_u *name, char_u **varname)
2142{
2143 hashitem_T *hi;
2144 hashtab_T *ht;
2145
2146 if (name[0] == NUL)
2147 return NULL;
2148 if (name[1] != ':')
2149 {
2150 // The name must not start with a colon or #.
2151 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
2152 return NULL;
2153 *varname = name;
2154
2155 // "version" is "v:version" in all scopes if scriptversion < 3.
2156 // Same for a few other variables marked with VV_COMPAT.
2157 if (current_sctx.sc_version < 3)
2158 {
2159 hi = hash_find(&compat_hashtab, name);
2160 if (!HASHITEM_EMPTY(hi))
2161 return &compat_hashtab;
2162 }
2163
2164 ht = get_funccal_local_ht();
2165 if (ht == NULL)
2166 return &globvarht; // global variable
2167 return ht; // local variable
2168 }
2169 *varname = name + 2;
2170 if (*name == 'g') // global variable
2171 return &globvarht;
2172 // There must be no ':' or '#' in the rest of the name, unless g: is used
2173 if (vim_strchr(name + 2, ':') != NULL
2174 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
2175 return NULL;
2176 if (*name == 'b') // buffer variable
2177 return &curbuf->b_vars->dv_hashtab;
2178 if (*name == 'w') // window variable
2179 return &curwin->w_vars->dv_hashtab;
2180 if (*name == 't') // tab page variable
2181 return &curtab->tp_vars->dv_hashtab;
2182 if (*name == 'v') // v: variable
2183 return &vimvarht;
2184 if (*name == 'a') // a: function argument
2185 return get_funccal_args_ht();
2186 if (*name == 'l') // l: local function variable
2187 return get_funccal_local_ht();
2188 if (*name == 's' // script variable
2189 && current_sctx.sc_sid > 0
2190 && current_sctx.sc_sid <= ga_scripts.ga_len)
2191 return &SCRIPT_VARS(current_sctx.sc_sid);
2192 return NULL;
2193}
2194
2195/*
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002196 * Get the string value of a (global/local) variable.
2197 * Note: see tv_get_string() for how long the pointer remains valid.
2198 * Returns NULL when it doesn't exist.
2199 */
2200 char_u *
2201get_var_value(char_u *name)
2202{
2203 dictitem_T *v;
2204
2205 v = find_var(name, NULL, FALSE);
2206 if (v == NULL)
2207 return NULL;
2208 return tv_get_string(&v->di_tv);
2209}
2210
2211/*
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002212 * Allocate a new hashtab for a sourced script. It will be used while
2213 * sourcing this script and when executing functions defined in the script.
2214 */
2215 void
2216new_script_vars(scid_T id)
2217{
2218 int i;
2219 hashtab_T *ht;
2220 scriptvar_T *sv;
2221
2222 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
2223 {
Bram Moolenaar8d71b542019-08-30 15:46:30 +02002224 // Re-allocating ga_data means that an ht_array pointing to
2225 // ht_smallarray becomes invalid. We can recognize this: ht_mask is
2226 // at its init value. Also reset "v_dict", it's always the same.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002227 for (i = 1; i <= ga_scripts.ga_len; ++i)
2228 {
2229 ht = &SCRIPT_VARS(i);
2230 if (ht->ht_mask == HT_INIT_SIZE - 1)
2231 ht->ht_array = ht->ht_smallarray;
2232 sv = SCRIPT_SV(i);
2233 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
2234 }
2235
2236 while (ga_scripts.ga_len < id)
2237 {
2238 sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
2239 ALLOC_CLEAR_ONE(scriptvar_T);
2240 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
2241 ++ga_scripts.ga_len;
2242 }
2243 }
2244}
2245
2246/*
2247 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
2248 * point to it.
2249 */
2250 void
2251init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
2252{
2253 hash_init(&dict->dv_hashtab);
2254 dict->dv_lock = 0;
2255 dict->dv_scope = scope;
2256 dict->dv_refcount = DO_NOT_FREE_CNT;
2257 dict->dv_copyID = 0;
2258 dict_var->di_tv.vval.v_dict = dict;
2259 dict_var->di_tv.v_type = VAR_DICT;
2260 dict_var->di_tv.v_lock = VAR_FIXED;
2261 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
2262 dict_var->di_key[0] = NUL;
2263}
2264
2265/*
2266 * Unreference a dictionary initialized by init_var_dict().
2267 */
2268 void
2269unref_var_dict(dict_T *dict)
2270{
Bram Moolenaar8d71b542019-08-30 15:46:30 +02002271 // Now the dict needs to be freed if no one else is using it, go back to
2272 // normal reference counting.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002273 dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
2274 dict_unref(dict);
2275}
2276
2277/*
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002278 * Clean up a list of internal variables.
2279 * Frees all allocated variables and the value they contain.
2280 * Clears hashtab "ht", does not free it.
2281 */
2282 void
2283vars_clear(hashtab_T *ht)
2284{
2285 vars_clear_ext(ht, TRUE);
2286}
2287
2288/*
2289 * Like vars_clear(), but only free the value if "free_val" is TRUE.
2290 */
2291 void
2292vars_clear_ext(hashtab_T *ht, int free_val)
2293{
2294 int todo;
2295 hashitem_T *hi;
2296 dictitem_T *v;
2297
2298 hash_lock(ht);
2299 todo = (int)ht->ht_used;
2300 for (hi = ht->ht_array; todo > 0; ++hi)
2301 {
2302 if (!HASHITEM_EMPTY(hi))
2303 {
2304 --todo;
2305
2306 // Free the variable. Don't remove it from the hashtab,
2307 // ht_array might change then. hash_clear() takes care of it
2308 // later.
2309 v = HI2DI(hi);
2310 if (free_val)
2311 clear_tv(&v->di_tv);
2312 if (v->di_flags & DI_FLAGS_ALLOC)
2313 vim_free(v);
2314 }
2315 }
2316 hash_clear(ht);
2317 ht->ht_used = 0;
2318}
2319
2320/*
2321 * Delete a variable from hashtab "ht" at item "hi".
2322 * Clear the variable value and free the dictitem.
2323 */
2324 void
2325delete_var(hashtab_T *ht, hashitem_T *hi)
2326{
2327 dictitem_T *di = HI2DI(hi);
2328
2329 hash_remove(ht, hi);
2330 clear_tv(&di->di_tv);
2331 vim_free(di);
2332}
2333
2334/*
2335 * List the value of one internal variable.
2336 */
2337 static void
2338list_one_var(dictitem_T *v, char *prefix, int *first)
2339{
2340 char_u *tofree;
2341 char_u *s;
2342 char_u numbuf[NUMBUFLEN];
2343
2344 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
2345 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
2346 s == NULL ? (char_u *)"" : s, first);
2347 vim_free(tofree);
2348}
2349
2350 static void
2351list_one_var_a(
2352 char *prefix,
2353 char_u *name,
2354 int type,
2355 char_u *string,
2356 int *first) // when TRUE clear rest of screen and set to FALSE
2357{
2358 // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg"
2359 msg_start();
2360 msg_puts(prefix);
2361 if (name != NULL) // "a:" vars don't have a name stored
2362 msg_puts((char *)name);
2363 msg_putchar(' ');
2364 msg_advance(22);
2365 if (type == VAR_NUMBER)
2366 msg_putchar('#');
2367 else if (type == VAR_FUNC || type == VAR_PARTIAL)
2368 msg_putchar('*');
2369 else if (type == VAR_LIST)
2370 {
2371 msg_putchar('[');
2372 if (*string == '[')
2373 ++string;
2374 }
2375 else if (type == VAR_DICT)
2376 {
2377 msg_putchar('{');
2378 if (*string == '{')
2379 ++string;
2380 }
2381 else
2382 msg_putchar(' ');
2383
2384 msg_outtrans(string);
2385
2386 if (type == VAR_FUNC || type == VAR_PARTIAL)
2387 msg_puts("()");
2388 if (*first)
2389 {
2390 msg_clr_eos();
2391 *first = FALSE;
2392 }
2393}
2394
2395/*
2396 * Set variable "name" to value in "tv".
2397 * If the variable already exists, the value is updated.
2398 * Otherwise the variable is created.
2399 */
2400 void
2401set_var(
2402 char_u *name,
2403 typval_T *tv,
2404 int copy) // make copy of value in "tv"
2405{
2406 set_var_const(name, tv, copy, FALSE);
2407}
2408
2409/*
2410 * Set variable "name" to value in "tv".
2411 * If the variable already exists and "is_const" is FALSE the value is updated.
2412 * Otherwise the variable is created.
2413 */
2414 void
2415set_var_const(
2416 char_u *name,
2417 typval_T *tv,
2418 int copy, // make copy of value in "tv"
2419 int is_const) // disallow to modify existing variable
2420{
2421 dictitem_T *v;
2422 char_u *varname;
2423 hashtab_T *ht;
2424
2425 ht = find_var_ht(name, &varname);
2426 if (ht == NULL || *varname == NUL)
2427 {
2428 semsg(_(e_illvar), name);
2429 return;
2430 }
2431 v = find_var_in_ht(ht, 0, varname, TRUE);
2432
2433 // Search in parent scope which is possible to reference from lambda
2434 if (v == NULL)
2435 v = find_var_in_scoped_ht(name, TRUE);
2436
2437 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
2438 && var_check_func_name(name, v == NULL))
2439 return;
2440
2441 if (v != NULL)
2442 {
2443 if (is_const)
2444 {
2445 emsg(_(e_cannot_mod));
2446 return;
2447 }
2448
2449 // existing variable, need to clear the value
2450 if (var_check_ro(v->di_flags, name, FALSE)
2451 || var_check_lock(v->di_tv.v_lock, name, FALSE))
2452 return;
2453
2454 // Handle setting internal v: variables separately where needed to
2455 // prevent changing the type.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002456 if (ht == &vimvarht)
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002457 {
2458 if (v->di_tv.v_type == VAR_STRING)
2459 {
2460 VIM_CLEAR(v->di_tv.vval.v_string);
2461 if (copy || tv->v_type != VAR_STRING)
2462 {
2463 char_u *val = tv_get_string(tv);
2464
2465 // Careful: when assigning to v:errmsg and tv_get_string()
2466 // causes an error message the variable will alrady be set.
2467 if (v->di_tv.vval.v_string == NULL)
2468 v->di_tv.vval.v_string = vim_strsave(val);
2469 }
2470 else
2471 {
2472 // Take over the string to avoid an extra alloc/free.
2473 v->di_tv.vval.v_string = tv->vval.v_string;
2474 tv->vval.v_string = NULL;
2475 }
2476 return;
2477 }
2478 else if (v->di_tv.v_type == VAR_NUMBER)
2479 {
2480 v->di_tv.vval.v_number = tv_get_number(tv);
2481 if (STRCMP(varname, "searchforward") == 0)
2482 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
2483#ifdef FEAT_SEARCH_EXTRA
2484 else if (STRCMP(varname, "hlsearch") == 0)
2485 {
2486 no_hlsearch = !v->di_tv.vval.v_number;
2487 redraw_all_later(SOME_VALID);
2488 }
2489#endif
2490 return;
2491 }
2492 else if (v->di_tv.v_type != tv->v_type)
2493 {
2494 semsg(_("E963: setting %s to value with wrong type"), name);
2495 return;
2496 }
2497 }
2498
2499 clear_tv(&v->di_tv);
2500 }
2501 else // add a new variable
2502 {
2503 // Can't add "v:" or "a:" variable.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002504 if (ht == &vimvarht || ht == get_funccal_args_ht())
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002505 {
2506 semsg(_(e_illvar), name);
2507 return;
2508 }
2509
2510 // Make sure the variable name is valid.
2511 if (!valid_varname(varname))
2512 return;
2513
2514 v = alloc(sizeof(dictitem_T) + STRLEN(varname));
2515 if (v == NULL)
2516 return;
2517 STRCPY(v->di_key, varname);
2518 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
2519 {
2520 vim_free(v);
2521 return;
2522 }
2523 v->di_flags = DI_FLAGS_ALLOC;
2524 if (is_const)
2525 v->di_flags |= DI_FLAGS_LOCK;
2526 }
2527
2528 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
2529 copy_tv(tv, &v->di_tv);
2530 else
2531 {
2532 v->di_tv = *tv;
2533 v->di_tv.v_lock = 0;
2534 init_tv(tv);
2535 }
2536
2537 if (is_const)
2538 v->di_tv.v_lock |= VAR_LOCKED;
2539}
2540
2541/*
2542 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
2543 * Also give an error message.
2544 */
2545 int
2546var_check_ro(int flags, char_u *name, int use_gettext)
2547{
2548 if (flags & DI_FLAGS_RO)
2549 {
2550 semsg(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
2551 return TRUE;
2552 }
2553 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
2554 {
2555 semsg(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
2556 return TRUE;
2557 }
2558 return FALSE;
2559}
2560
2561/*
2562 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
2563 * Also give an error message.
2564 */
2565 int
2566var_check_fixed(int flags, char_u *name, int use_gettext)
2567{
2568 if (flags & DI_FLAGS_FIX)
2569 {
2570 semsg(_("E795: Cannot delete variable %s"),
2571 use_gettext ? (char_u *)_(name) : name);
2572 return TRUE;
2573 }
2574 return FALSE;
2575}
2576
2577/*
2578 * Check if a funcref is assigned to a valid variable name.
2579 * Return TRUE and give an error if not.
2580 */
2581 int
2582var_check_func_name(
2583 char_u *name, // points to start of variable name
2584 int new_var) // TRUE when creating the variable
2585{
2586 // Allow for w: b: s: and t:.
2587 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
2588 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
2589 ? name[2] : name[0]))
2590 {
2591 semsg(_("E704: Funcref variable name must start with a capital: %s"),
2592 name);
2593 return TRUE;
2594 }
2595 // Don't allow hiding a function. When "v" is not NULL we might be
2596 // assigning another function to the same var, the type is checked
2597 // below.
2598 if (new_var && function_exists(name, FALSE))
2599 {
2600 semsg(_("E705: Variable name conflicts with existing function: %s"),
2601 name);
2602 return TRUE;
2603 }
2604 return FALSE;
2605}
2606
2607/*
2608 * Return TRUE if "flags" indicates variable "name" is locked (immutable).
2609 * Also give an error message, using "name" or _("name") when use_gettext is
2610 * TRUE.
2611 */
2612 int
2613var_check_lock(int lock, char_u *name, int use_gettext)
2614{
2615 if (lock & VAR_LOCKED)
2616 {
2617 semsg(_("E741: Value is locked: %s"),
2618 name == NULL ? (char_u *)_("Unknown")
2619 : use_gettext ? (char_u *)_(name)
2620 : name);
2621 return TRUE;
2622 }
2623 if (lock & VAR_FIXED)
2624 {
2625 semsg(_("E742: Cannot change value of %s"),
2626 name == NULL ? (char_u *)_("Unknown")
2627 : use_gettext ? (char_u *)_(name)
2628 : name);
2629 return TRUE;
2630 }
2631 return FALSE;
2632}
2633
2634/*
2635 * Check if a variable name is valid.
2636 * Return FALSE and give an error if not.
2637 */
2638 int
2639valid_varname(char_u *varname)
2640{
2641 char_u *p;
2642
2643 for (p = varname; *p != NUL; ++p)
2644 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
2645 && *p != AUTOLOAD_CHAR)
2646 {
2647 semsg(_(e_illvar), varname);
2648 return FALSE;
2649 }
2650 return TRUE;
2651}
2652
2653/*
2654 * getwinvar() and gettabwinvar()
2655 */
2656 static void
2657getwinvar(
2658 typval_T *argvars,
2659 typval_T *rettv,
2660 int off) // 1 for gettabwinvar()
2661{
2662 win_T *win;
2663 char_u *varname;
2664 dictitem_T *v;
2665 tabpage_T *tp = NULL;
2666 int done = FALSE;
2667 win_T *oldcurwin;
2668 tabpage_T *oldtabpage;
2669 int need_switch_win;
2670
2671 if (off == 1)
2672 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
2673 else
2674 tp = curtab;
2675 win = find_win_by_nr(&argvars[off], tp);
2676 varname = tv_get_string_chk(&argvars[off + 1]);
2677 ++emsg_off;
2678
2679 rettv->v_type = VAR_STRING;
2680 rettv->vval.v_string = NULL;
2681
2682 if (win != NULL && varname != NULL)
2683 {
2684 // Set curwin to be our win, temporarily. Also set the tabpage,
2685 // otherwise the window is not valid. Only do this when needed,
2686 // autocommands get blocked.
2687 need_switch_win = !(tp == curtab && win == curwin);
2688 if (!need_switch_win
2689 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
2690 {
2691 if (*varname == '&')
2692 {
2693 if (varname[1] == NUL)
2694 {
2695 // get all window-local options in a dict
2696 dict_T *opts = get_winbuf_options(FALSE);
2697
2698 if (opts != NULL)
2699 {
2700 rettv_dict_set(rettv, opts);
2701 done = TRUE;
2702 }
2703 }
2704 else if (get_option_tv(&varname, rettv, 1) == OK)
2705 // window-local-option
2706 done = TRUE;
2707 }
2708 else
2709 {
2710 // Look up the variable.
2711 // Let getwinvar({nr}, "") return the "w:" dictionary.
2712 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
2713 varname, FALSE);
2714 if (v != NULL)
2715 {
2716 copy_tv(&v->di_tv, rettv);
2717 done = TRUE;
2718 }
2719 }
2720 }
2721
2722 if (need_switch_win)
2723 // restore previous notion of curwin
2724 restore_win(oldcurwin, oldtabpage, TRUE);
2725 }
2726
2727 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
2728 // use the default return value
2729 copy_tv(&argvars[off + 2], rettv);
2730
2731 --emsg_off;
2732}
2733
2734/*
2735 * "setwinvar()" and "settabwinvar()" functions
2736 */
2737 static void
2738setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
2739{
2740 win_T *win;
2741 win_T *save_curwin;
2742 tabpage_T *save_curtab;
2743 int need_switch_win;
2744 char_u *varname, *winvarname;
2745 typval_T *varp;
2746 char_u nbuf[NUMBUFLEN];
2747 tabpage_T *tp = NULL;
2748
2749 if (check_secure())
2750 return;
2751
2752 if (off == 1)
2753 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
2754 else
2755 tp = curtab;
2756 win = find_win_by_nr(&argvars[off], tp);
2757 varname = tv_get_string_chk(&argvars[off + 1]);
2758 varp = &argvars[off + 2];
2759
2760 if (win != NULL && varname != NULL && varp != NULL)
2761 {
2762 need_switch_win = !(tp == curtab && win == curwin);
2763 if (!need_switch_win
2764 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
2765 {
2766 if (*varname == '&')
2767 {
2768 long numval;
2769 char_u *strval;
2770 int error = FALSE;
2771
2772 ++varname;
2773 numval = (long)tv_get_number_chk(varp, &error);
2774 strval = tv_get_string_buf_chk(varp, nbuf);
2775 if (!error && strval != NULL)
2776 set_option_value(varname, numval, strval, OPT_LOCAL);
2777 }
2778 else
2779 {
2780 winvarname = alloc(STRLEN(varname) + 3);
2781 if (winvarname != NULL)
2782 {
2783 STRCPY(winvarname, "w:");
2784 STRCPY(winvarname + 2, varname);
2785 set_var(winvarname, varp, TRUE);
2786 vim_free(winvarname);
2787 }
2788 }
2789 }
2790 if (need_switch_win)
2791 restore_win(save_curwin, save_curtab, TRUE);
2792 }
2793}
2794
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002795/*
2796 * reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
2797 * v:option_type, and v:option_command.
2798 */
2799 void
2800reset_v_option_vars(void)
2801{
2802 set_vim_var_string(VV_OPTION_NEW, NULL, -1);
2803 set_vim_var_string(VV_OPTION_OLD, NULL, -1);
2804 set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
2805 set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
2806 set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
2807 set_vim_var_string(VV_OPTION_COMMAND, NULL, -1);
2808}
2809
2810/*
2811 * Add an assert error to v:errors.
2812 */
2813 void
2814assert_error(garray_T *gap)
2815{
2816 struct vimvar *vp = &vimvars[VV_ERRORS];
2817
2818 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL)
Bram Moolenaar8d71b542019-08-30 15:46:30 +02002819 // Make sure v:errors is a list.
Bram Moolenaare5cdf152019-08-29 22:09:46 +02002820 set_vim_var_list(VV_ERRORS, list_alloc());
2821 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len);
2822}
2823
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002824 int
2825var_exists(char_u *var)
2826{
2827 char_u *name;
2828 char_u *tofree;
2829 typval_T tv;
2830 int len = 0;
2831 int n = FALSE;
2832
2833 // get_name_len() takes care of expanding curly braces
2834 name = var;
2835 len = get_name_len(&var, &tofree, TRUE, FALSE);
2836 if (len > 0)
2837 {
2838 if (tofree != NULL)
2839 name = tofree;
2840 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK);
2841 if (n)
2842 {
2843 // handle d.key, l[idx], f(expr)
2844 n = (handle_subscript(&var, &tv, TRUE, FALSE, name, &name) == OK);
2845 if (n)
2846 clear_tv(&tv);
2847 }
2848 }
2849 if (*var != NUL)
2850 n = FALSE;
2851
2852 vim_free(tofree);
2853 return n;
2854}
2855
2856/*
2857 * "gettabvar()" function
2858 */
2859 void
2860f_gettabvar(typval_T *argvars, typval_T *rettv)
2861{
2862 win_T *oldcurwin;
2863 tabpage_T *tp, *oldtabpage;
2864 dictitem_T *v;
2865 char_u *varname;
2866 int done = FALSE;
2867
2868 rettv->v_type = VAR_STRING;
2869 rettv->vval.v_string = NULL;
2870
2871 varname = tv_get_string_chk(&argvars[1]);
2872 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
2873 if (tp != NULL && varname != NULL)
2874 {
2875 // Set tp to be our tabpage, temporarily. Also set the window to the
2876 // first window in the tabpage, otherwise the window is not valid.
2877 if (switch_win(&oldcurwin, &oldtabpage,
2878 tp == curtab || tp->tp_firstwin == NULL ? firstwin
2879 : tp->tp_firstwin, tp, TRUE) == OK)
2880 {
2881 // look up the variable
2882 // Let gettabvar({nr}, "") return the "t:" dictionary.
2883 v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
2884 if (v != NULL)
2885 {
2886 copy_tv(&v->di_tv, rettv);
2887 done = TRUE;
2888 }
2889 }
2890
2891 // restore previous notion of curwin
2892 restore_win(oldcurwin, oldtabpage, TRUE);
2893 }
2894
2895 if (!done && argvars[2].v_type != VAR_UNKNOWN)
2896 copy_tv(&argvars[2], rettv);
2897}
2898
2899/*
2900 * "gettabwinvar()" function
2901 */
2902 void
2903f_gettabwinvar(typval_T *argvars, typval_T *rettv)
2904{
2905 getwinvar(argvars, rettv, 1);
2906}
2907
2908/*
2909 * "getwinvar()" function
2910 */
2911 void
2912f_getwinvar(typval_T *argvars, typval_T *rettv)
2913{
2914 getwinvar(argvars, rettv, 0);
2915}
2916
2917/*
Bram Moolenaar8d71b542019-08-30 15:46:30 +02002918 * "getbufvar()" function
2919 */
2920 void
2921f_getbufvar(typval_T *argvars, typval_T *rettv)
2922{
2923 buf_T *buf;
2924 buf_T *save_curbuf;
2925 char_u *varname;
2926 dictitem_T *v;
2927 int done = FALSE;
2928
2929 (void)tv_get_number(&argvars[0]); // issue errmsg if type error
2930 varname = tv_get_string_chk(&argvars[1]);
2931 ++emsg_off;
2932 buf = tv_get_buf(&argvars[0], FALSE);
2933
2934 rettv->v_type = VAR_STRING;
2935 rettv->vval.v_string = NULL;
2936
2937 if (buf != NULL && varname != NULL)
2938 {
2939 // set curbuf to be our buf, temporarily
2940 save_curbuf = curbuf;
2941 curbuf = buf;
2942
2943 if (*varname == '&')
2944 {
2945 if (varname[1] == NUL)
2946 {
2947 // get all buffer-local options in a dict
2948 dict_T *opts = get_winbuf_options(TRUE);
2949
2950 if (opts != NULL)
2951 {
2952 rettv_dict_set(rettv, opts);
2953 done = TRUE;
2954 }
2955 }
2956 else if (get_option_tv(&varname, rettv, TRUE) == OK)
2957 // buffer-local-option
2958 done = TRUE;
2959 }
2960 else
2961 {
2962 // Look up the variable.
2963 // Let getbufvar({nr}, "") return the "b:" dictionary.
2964 v = find_var_in_ht(&curbuf->b_vars->dv_hashtab,
2965 'b', varname, FALSE);
2966 if (v != NULL)
2967 {
2968 copy_tv(&v->di_tv, rettv);
2969 done = TRUE;
2970 }
2971 }
2972
2973 // restore previous notion of curbuf
2974 curbuf = save_curbuf;
2975 }
2976
2977 if (!done && argvars[2].v_type != VAR_UNKNOWN)
2978 // use the default value
2979 copy_tv(&argvars[2], rettv);
2980
2981 --emsg_off;
2982}
2983
2984/*
Bram Moolenaar0522ba02019-08-27 22:48:30 +02002985 * "settabvar()" function
2986 */
2987 void
2988f_settabvar(typval_T *argvars, typval_T *rettv)
2989{
2990 tabpage_T *save_curtab;
2991 tabpage_T *tp;
2992 char_u *varname, *tabvarname;
2993 typval_T *varp;
2994
2995 rettv->vval.v_number = 0;
2996
2997 if (check_secure())
2998 return;
2999
3000 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
3001 varname = tv_get_string_chk(&argvars[1]);
3002 varp = &argvars[2];
3003
3004 if (varname != NULL && varp != NULL && tp != NULL)
3005 {
3006 save_curtab = curtab;
3007 goto_tabpage_tp(tp, FALSE, FALSE);
3008
3009 tabvarname = alloc(STRLEN(varname) + 3);
3010 if (tabvarname != NULL)
3011 {
3012 STRCPY(tabvarname, "t:");
3013 STRCPY(tabvarname + 2, varname);
3014 set_var(tabvarname, varp, TRUE);
3015 vim_free(tabvarname);
3016 }
3017
3018 // Restore current tabpage
3019 if (valid_tabpage(save_curtab))
3020 goto_tabpage_tp(save_curtab, FALSE, FALSE);
3021 }
3022}
3023
3024/*
3025 * "settabwinvar()" function
3026 */
3027 void
3028f_settabwinvar(typval_T *argvars, typval_T *rettv)
3029{
3030 setwinvar(argvars, rettv, 1);
3031}
3032
3033/*
3034 * "setwinvar()" function
3035 */
3036 void
3037f_setwinvar(typval_T *argvars, typval_T *rettv)
3038{
3039 setwinvar(argvars, rettv, 0);
3040}
3041
Bram Moolenaar8d71b542019-08-30 15:46:30 +02003042/*
3043 * "setbufvar()" function
3044 */
3045 void
3046f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
3047{
3048 buf_T *buf;
3049 char_u *varname, *bufvarname;
3050 typval_T *varp;
3051 char_u nbuf[NUMBUFLEN];
3052
3053 if (check_secure())
3054 return;
3055 (void)tv_get_number(&argvars[0]); // issue errmsg if type error
3056 varname = tv_get_string_chk(&argvars[1]);
3057 buf = tv_get_buf(&argvars[0], FALSE);
3058 varp = &argvars[2];
3059
3060 if (buf != NULL && varname != NULL && varp != NULL)
3061 {
3062 if (*varname == '&')
3063 {
3064 long numval;
3065 char_u *strval;
3066 int error = FALSE;
3067 aco_save_T aco;
3068
3069 // set curbuf to be our buf, temporarily
3070 aucmd_prepbuf(&aco, buf);
3071
3072 ++varname;
3073 numval = (long)tv_get_number_chk(varp, &error);
3074 strval = tv_get_string_buf_chk(varp, nbuf);
3075 if (!error && strval != NULL)
3076 set_option_value(varname, numval, strval, OPT_LOCAL);
3077
3078 // reset notion of buffer
3079 aucmd_restbuf(&aco);
3080 }
3081 else
3082 {
3083 buf_T *save_curbuf = curbuf;
3084
3085 bufvarname = alloc(STRLEN(varname) + 3);
3086 if (bufvarname != NULL)
3087 {
3088 curbuf = buf;
3089 STRCPY(bufvarname, "b:");
3090 STRCPY(bufvarname + 2, varname);
3091 set_var(bufvarname, varp, TRUE);
3092 vim_free(bufvarname);
3093 curbuf = save_curbuf;
3094 }
3095 }
3096 }
3097}
3098
Bram Moolenaar0522ba02019-08-27 22:48:30 +02003099#endif // FEAT_EVAL