comparison src/evalvars.c @ 17873:d50a5faa75bd v8.1.1933

patch 8.1.1933: the eval.c file is too big Commit: https://github.com/vim/vim/commit/0522ba0359c96a8c2a4fc8fca0d3b58e49dda759 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Aug 27 22:48:30 2019 +0200 patch 8.1.1933: the eval.c file is too big Problem: The eval.c file is too big. Solution: Move code related to variables to evalvars.c. (Yegappan Lakshmanan, closes #4868)
author Bram Moolenaar <Bram@vim.org>
date Tue, 27 Aug 2019 23:00:04 +0200
parents
children 5e2d8840da11
comparison
equal deleted inserted replaced
17872:a4a0f826d4d7 17873:d50a5faa75bd
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 char *e_letunexp = N_("E18: Unexpected characters in :let");
19
20 static void ex_let_const(exarg_T *eap, int is_const);
21 static char_u *skip_var_one(char_u *arg);
22 static void list_glob_vars(int *first);
23 static void list_buf_vars(int *first);
24 static void list_win_vars(int *first);
25 static void list_tab_vars(int *first);
26 static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
27 static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op);
28 static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
29 static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
30 static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
31 static void item_lock(typval_T *tv, int deep, int lock);
32 static void list_one_var(dictitem_T *v, char *prefix, int *first);
33 static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
34
35 /*
36 * Get a list of lines from a HERE document. The here document is a list of
37 * lines surrounded by a marker.
38 * cmd << {marker}
39 * {line1}
40 * {line2}
41 * ....
42 * {marker}
43 *
44 * The {marker} is a string. If the optional 'trim' word is supplied before the
45 * marker, then the leading indentation before the lines (matching the
46 * indentation in the 'cmd' line) is stripped.
47 * Returns a List with {lines} or NULL.
48 */
49 static list_T *
50 heredoc_get(exarg_T *eap, char_u *cmd)
51 {
52 char_u *theline;
53 char_u *marker;
54 list_T *l;
55 char_u *p;
56 int marker_indent_len = 0;
57 int text_indent_len = 0;
58 char_u *text_indent = NULL;
59
60 if (eap->getline == NULL)
61 {
62 emsg(_("E991: cannot use =<< here"));
63 return NULL;
64 }
65
66 // Check for the optional 'trim' word before the marker
67 cmd = skipwhite(cmd);
68 if (STRNCMP(cmd, "trim", 4) == 0 && (cmd[4] == NUL || VIM_ISWHITE(cmd[4])))
69 {
70 cmd = skipwhite(cmd + 4);
71
72 // Trim the indentation from all the lines in the here document.
73 // The amount of indentation trimmed is the same as the indentation of
74 // the first line after the :let command line. To find the end marker
75 // the indent of the :let command line is trimmed.
76 p = *eap->cmdlinep;
77 while (VIM_ISWHITE(*p))
78 {
79 p++;
80 marker_indent_len++;
81 }
82 text_indent_len = -1;
83 }
84
85 // The marker is the next word.
86 if (*cmd != NUL && *cmd != '"')
87 {
88 marker = skipwhite(cmd);
89 p = skiptowhite(marker);
90 if (*skipwhite(p) != NUL && *skipwhite(p) != '"')
91 {
92 emsg(_(e_trailing));
93 return NULL;
94 }
95 *p = NUL;
96 if (vim_islower(*marker))
97 {
98 emsg(_("E221: Marker cannot start with lower case letter"));
99 return NULL;
100 }
101 }
102 else
103 {
104 emsg(_("E172: Missing marker"));
105 return NULL;
106 }
107
108 l = list_alloc();
109 if (l == NULL)
110 return NULL;
111
112 for (;;)
113 {
114 int mi = 0;
115 int ti = 0;
116
117 theline = eap->getline(NUL, eap->cookie, 0, FALSE);
118 if (theline == NULL)
119 {
120 semsg(_("E990: Missing end marker '%s'"), marker);
121 break;
122 }
123
124 // with "trim": skip the indent matching the :let line to find the
125 // marker
126 if (marker_indent_len > 0
127 && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0)
128 mi = marker_indent_len;
129 if (STRCMP(marker, theline + mi) == 0)
130 {
131 vim_free(theline);
132 break;
133 }
134
135 if (text_indent_len == -1 && *theline != NUL)
136 {
137 // set the text indent from the first line.
138 p = theline;
139 text_indent_len = 0;
140 while (VIM_ISWHITE(*p))
141 {
142 p++;
143 text_indent_len++;
144 }
145 text_indent = vim_strnsave(theline, text_indent_len);
146 }
147 // with "trim": skip the indent matching the first line
148 if (text_indent != NULL)
149 for (ti = 0; ti < text_indent_len; ++ti)
150 if (theline[ti] != text_indent[ti])
151 break;
152
153 if (list_append_string(l, theline + ti, -1) == FAIL)
154 break;
155 vim_free(theline);
156 }
157 vim_free(text_indent);
158
159 return l;
160 }
161
162 /*
163 * ":let" list all variable values
164 * ":let var1 var2" list variable values
165 * ":let var = expr" assignment command.
166 * ":let var += expr" assignment command.
167 * ":let var -= expr" assignment command.
168 * ":let var *= expr" assignment command.
169 * ":let var /= expr" assignment command.
170 * ":let var %= expr" assignment command.
171 * ":let var .= expr" assignment command.
172 * ":let var ..= expr" assignment command.
173 * ":let [var1, var2] = expr" unpack list.
174 */
175 void
176 ex_let(exarg_T *eap)
177 {
178 ex_let_const(eap, FALSE);
179 }
180
181 /*
182 * ":const" list all variable values
183 * ":const var1 var2" list variable values
184 * ":const var = expr" assignment command.
185 * ":const [var1, var2] = expr" unpack list.
186 */
187 void
188 ex_const(exarg_T *eap)
189 {
190 ex_let_const(eap, TRUE);
191 }
192
193 static void
194 ex_let_const(exarg_T *eap, int is_const)
195 {
196 char_u *arg = eap->arg;
197 char_u *expr = NULL;
198 typval_T rettv;
199 int i;
200 int var_count = 0;
201 int semicolon = 0;
202 char_u op[2];
203 char_u *argend;
204 int first = TRUE;
205 int concat;
206
207 argend = skip_var_list(arg, &var_count, &semicolon);
208 if (argend == NULL)
209 return;
210 if (argend > arg && argend[-1] == '.') // for var.='str'
211 --argend;
212 expr = skipwhite(argend);
213 concat = expr[0] == '.'
214 && ((expr[1] == '=' && current_sctx.sc_version < 2)
215 || (expr[1] == '.' && expr[2] == '='));
216 if (*expr != '=' && !((vim_strchr((char_u *)"+-*/%", *expr) != NULL
217 && expr[1] == '=') || concat))
218 {
219 // ":let" without "=": list variables
220 if (*arg == '[')
221 emsg(_(e_invarg));
222 else if (expr[0] == '.')
223 emsg(_("E985: .= is not supported with script version 2"));
224 else if (!ends_excmd(*arg))
225 // ":let var1 var2"
226 arg = list_arg_vars(eap, arg, &first);
227 else if (!eap->skip)
228 {
229 // ":let"
230 list_glob_vars(&first);
231 list_buf_vars(&first);
232 list_win_vars(&first);
233 list_tab_vars(&first);
234 list_script_vars(&first);
235 list_func_vars(&first);
236 list_vim_vars(&first);
237 }
238 eap->nextcmd = check_nextcmd(arg);
239 }
240 else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
241 {
242 list_T *l;
243
244 // HERE document
245 l = heredoc_get(eap, expr + 3);
246 if (l != NULL)
247 {
248 rettv_list_set(&rettv, l);
249 op[0] = '=';
250 op[1] = NUL;
251 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
252 is_const, op);
253 clear_tv(&rettv);
254 }
255 }
256 else
257 {
258 op[0] = '=';
259 op[1] = NUL;
260 if (*expr != '=')
261 {
262 if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
263 {
264 op[0] = *expr; // +=, -=, *=, /=, %= or .=
265 if (expr[0] == '.' && expr[1] == '.') // ..=
266 ++expr;
267 }
268 expr = skipwhite(expr + 2);
269 }
270 else
271 expr = skipwhite(expr + 1);
272
273 if (eap->skip)
274 ++emsg_skip;
275 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
276 if (eap->skip)
277 {
278 if (i != FAIL)
279 clear_tv(&rettv);
280 --emsg_skip;
281 }
282 else if (i != FAIL)
283 {
284 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
285 is_const, op);
286 clear_tv(&rettv);
287 }
288 }
289 }
290
291 /*
292 * Assign the typevalue "tv" to the variable or variables at "arg_start".
293 * Handles both "var" with any type and "[var, var; var]" with a list type.
294 * When "op" is not NULL it points to a string with characters that
295 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
296 * or concatenate.
297 * Returns OK or FAIL;
298 */
299 int
300 ex_let_vars(
301 char_u *arg_start,
302 typval_T *tv,
303 int copy, // copy values from "tv", don't move
304 int semicolon, // from skip_var_list()
305 int var_count, // from skip_var_list()
306 int is_const, // lock variables for const
307 char_u *op)
308 {
309 char_u *arg = arg_start;
310 list_T *l;
311 int i;
312 listitem_T *item;
313 typval_T ltv;
314
315 if (*arg != '[')
316 {
317 // ":let var = expr" or ":for var in list"
318 if (ex_let_one(arg, tv, copy, is_const, op, op) == NULL)
319 return FAIL;
320 return OK;
321 }
322
323 // ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
324 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
325 {
326 emsg(_(e_listreq));
327 return FAIL;
328 }
329
330 i = list_len(l);
331 if (semicolon == 0 && var_count < i)
332 {
333 emsg(_("E687: Less targets than List items"));
334 return FAIL;
335 }
336 if (var_count - semicolon > i)
337 {
338 emsg(_("E688: More targets than List items"));
339 return FAIL;
340 }
341
342 item = l->lv_first;
343 while (*arg != ']')
344 {
345 arg = skipwhite(arg + 1);
346 arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
347 (char_u *)",;]", op);
348 item = item->li_next;
349 if (arg == NULL)
350 return FAIL;
351
352 arg = skipwhite(arg);
353 if (*arg == ';')
354 {
355 // Put the rest of the list (may be empty) in the var after ';'.
356 // Create a new list for this.
357 l = list_alloc();
358 if (l == NULL)
359 return FAIL;
360 while (item != NULL)
361 {
362 list_append_tv(l, &item->li_tv);
363 item = item->li_next;
364 }
365
366 ltv.v_type = VAR_LIST;
367 ltv.v_lock = 0;
368 ltv.vval.v_list = l;
369 l->lv_refcount = 1;
370
371 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, is_const,
372 (char_u *)"]", op);
373 clear_tv(&ltv);
374 if (arg == NULL)
375 return FAIL;
376 break;
377 }
378 else if (*arg != ',' && *arg != ']')
379 {
380 internal_error("ex_let_vars()");
381 return FAIL;
382 }
383 }
384
385 return OK;
386 }
387
388 /*
389 * Skip over assignable variable "var" or list of variables "[var, var]".
390 * Used for ":let varvar = expr" and ":for varvar in expr".
391 * For "[var, var]" increment "*var_count" for each variable.
392 * for "[var, var; var]" set "semicolon".
393 * Return NULL for an error.
394 */
395 char_u *
396 skip_var_list(
397 char_u *arg,
398 int *var_count,
399 int *semicolon)
400 {
401 char_u *p, *s;
402
403 if (*arg == '[')
404 {
405 // "[var, var]": find the matching ']'.
406 p = arg;
407 for (;;)
408 {
409 p = skipwhite(p + 1); // skip whites after '[', ';' or ','
410 s = skip_var_one(p);
411 if (s == p)
412 {
413 semsg(_(e_invarg2), p);
414 return NULL;
415 }
416 ++*var_count;
417
418 p = skipwhite(s);
419 if (*p == ']')
420 break;
421 else if (*p == ';')
422 {
423 if (*semicolon == 1)
424 {
425 emsg(_("Double ; in list of variables"));
426 return NULL;
427 }
428 *semicolon = 1;
429 }
430 else if (*p != ',')
431 {
432 semsg(_(e_invarg2), p);
433 return NULL;
434 }
435 }
436 return p + 1;
437 }
438 else
439 return skip_var_one(arg);
440 }
441
442 /*
443 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
444 * l[idx].
445 */
446 static char_u *
447 skip_var_one(char_u *arg)
448 {
449 if (*arg == '@' && arg[1] != NUL)
450 return arg + 2;
451 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
452 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
453 }
454
455 /*
456 * List variables for hashtab "ht" with prefix "prefix".
457 * If "empty" is TRUE also list NULL strings as empty strings.
458 */
459 void
460 list_hashtable_vars(
461 hashtab_T *ht,
462 char *prefix,
463 int empty,
464 int *first)
465 {
466 hashitem_T *hi;
467 dictitem_T *di;
468 int todo;
469 char_u buf[IOSIZE];
470
471 todo = (int)ht->ht_used;
472 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
473 {
474 if (!HASHITEM_EMPTY(hi))
475 {
476 --todo;
477 di = HI2DI(hi);
478
479 // apply :filter /pat/ to variable name
480 vim_strncpy((char_u *)buf, (char_u *)prefix, IOSIZE - 1);
481 vim_strcat((char_u *)buf, di->di_key, IOSIZE);
482 if (message_filtered(buf))
483 continue;
484
485 if (empty || di->di_tv.v_type != VAR_STRING
486 || di->di_tv.vval.v_string != NULL)
487 list_one_var(di, prefix, first);
488 }
489 }
490 }
491
492 /*
493 * List global variables.
494 */
495 static void
496 list_glob_vars(int *first)
497 {
498 list_hashtable_vars(&globvarht, "", TRUE, first);
499 }
500
501 /*
502 * List buffer variables.
503 */
504 static void
505 list_buf_vars(int *first)
506 {
507 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", TRUE, first);
508 }
509
510 /*
511 * List window variables.
512 */
513 static void
514 list_win_vars(int *first)
515 {
516 list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", TRUE, first);
517 }
518
519 /*
520 * List tab page variables.
521 */
522 static void
523 list_tab_vars(int *first)
524 {
525 list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", TRUE, first);
526 }
527
528 /*
529 * List variables in "arg".
530 */
531 static char_u *
532 list_arg_vars(exarg_T *eap, char_u *arg, int *first)
533 {
534 int error = FALSE;
535 int len;
536 char_u *name;
537 char_u *name_start;
538 char_u *arg_subsc;
539 char_u *tofree;
540 typval_T tv;
541
542 while (!ends_excmd(*arg) && !got_int)
543 {
544 if (error || eap->skip)
545 {
546 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
547 if (!VIM_ISWHITE(*arg) && !ends_excmd(*arg))
548 {
549 emsg_severe = TRUE;
550 emsg(_(e_trailing));
551 break;
552 }
553 }
554 else
555 {
556 // get_name_len() takes care of expanding curly braces
557 name_start = name = arg;
558 len = get_name_len(&arg, &tofree, TRUE, TRUE);
559 if (len <= 0)
560 {
561 // This is mainly to keep test 49 working: when expanding
562 // curly braces fails overrule the exception error message.
563 if (len < 0 && !aborting())
564 {
565 emsg_severe = TRUE;
566 semsg(_(e_invarg2), arg);
567 break;
568 }
569 error = TRUE;
570 }
571 else
572 {
573 if (tofree != NULL)
574 name = tofree;
575 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL)
576 error = TRUE;
577 else
578 {
579 // handle d.key, l[idx], f(expr)
580 arg_subsc = arg;
581 if (handle_subscript(&arg, &tv, TRUE, TRUE,
582 name, &name) == FAIL)
583 error = TRUE;
584 else
585 {
586 if (arg == arg_subsc && len == 2 && name[1] == ':')
587 {
588 switch (*name)
589 {
590 case 'g': list_glob_vars(first); break;
591 case 'b': list_buf_vars(first); break;
592 case 'w': list_win_vars(first); break;
593 case 't': list_tab_vars(first); break;
594 case 'v': list_vim_vars(first); break;
595 case 's': list_script_vars(first); break;
596 case 'l': list_func_vars(first); break;
597 default:
598 semsg(_("E738: Can't list variables for %s"), name);
599 }
600 }
601 else
602 {
603 char_u numbuf[NUMBUFLEN];
604 char_u *tf;
605 int c;
606 char_u *s;
607
608 s = echo_string(&tv, &tf, numbuf, 0);
609 c = *arg;
610 *arg = NUL;
611 list_one_var_a("",
612 arg == arg_subsc ? name : name_start,
613 tv.v_type,
614 s == NULL ? (char_u *)"" : s,
615 first);
616 *arg = c;
617 vim_free(tf);
618 }
619 clear_tv(&tv);
620 }
621 }
622 }
623
624 vim_free(tofree);
625 }
626
627 arg = skipwhite(arg);
628 }
629
630 return arg;
631 }
632
633 /*
634 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
635 * Returns a pointer to the char just after the var name.
636 * Returns NULL if there is an error.
637 */
638 static char_u *
639 ex_let_one(
640 char_u *arg, // points to variable name
641 typval_T *tv, // value to assign to variable
642 int copy, // copy value from "tv"
643 int is_const, // lock variable for const
644 char_u *endchars, // valid chars after variable name or NULL
645 char_u *op) // "+", "-", "." or NULL
646 {
647 int c1;
648 char_u *name;
649 char_u *p;
650 char_u *arg_end = NULL;
651 int len;
652 int opt_flags;
653 char_u *tofree = NULL;
654
655 // ":let $VAR = expr": Set environment variable.
656 if (*arg == '$')
657 {
658 if (is_const)
659 {
660 emsg(_("E996: Cannot lock an environment variable"));
661 return NULL;
662 }
663 // Find the end of the name.
664 ++arg;
665 name = arg;
666 len = get_env_len(&arg);
667 if (len == 0)
668 semsg(_(e_invarg2), name - 1);
669 else
670 {
671 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
672 semsg(_(e_letwrong), op);
673 else if (endchars != NULL
674 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
675 emsg(_(e_letunexp));
676 else if (!check_secure())
677 {
678 c1 = name[len];
679 name[len] = NUL;
680 p = tv_get_string_chk(tv);
681 if (p != NULL && op != NULL && *op == '.')
682 {
683 int mustfree = FALSE;
684 char_u *s = vim_getenv(name, &mustfree);
685
686 if (s != NULL)
687 {
688 p = tofree = concat_str(s, p);
689 if (mustfree)
690 vim_free(s);
691 }
692 }
693 if (p != NULL)
694 {
695 vim_setenv(name, p);
696 if (STRICMP(name, "HOME") == 0)
697 init_homedir();
698 else if (didset_vim && STRICMP(name, "VIM") == 0)
699 didset_vim = FALSE;
700 else if (didset_vimruntime
701 && STRICMP(name, "VIMRUNTIME") == 0)
702 didset_vimruntime = FALSE;
703 arg_end = arg;
704 }
705 name[len] = c1;
706 vim_free(tofree);
707 }
708 }
709 }
710
711 // ":let &option = expr": Set option value.
712 // ":let &l:option = expr": Set local option value.
713 // ":let &g:option = expr": Set global option value.
714 else if (*arg == '&')
715 {
716 if (is_const)
717 {
718 emsg(_("E996: Cannot lock an option"));
719 return NULL;
720 }
721 // Find the end of the name.
722 p = find_option_end(&arg, &opt_flags);
723 if (p == NULL || (endchars != NULL
724 && vim_strchr(endchars, *skipwhite(p)) == NULL))
725 emsg(_(e_letunexp));
726 else
727 {
728 long n;
729 int opt_type;
730 long numval;
731 char_u *stringval = NULL;
732 char_u *s;
733
734 c1 = *p;
735 *p = NUL;
736
737 n = (long)tv_get_number(tv);
738 s = tv_get_string_chk(tv); // != NULL if number or string
739 if (s != NULL && op != NULL && *op != '=')
740 {
741 opt_type = get_option_value(arg, &numval,
742 &stringval, opt_flags);
743 if ((opt_type == 1 && *op == '.')
744 || (opt_type == 0 && *op != '.'))
745 {
746 semsg(_(e_letwrong), op);
747 s = NULL; // don't set the value
748 }
749 else
750 {
751 if (opt_type == 1) // number
752 {
753 switch (*op)
754 {
755 case '+': n = numval + n; break;
756 case '-': n = numval - n; break;
757 case '*': n = numval * n; break;
758 case '/': n = (long)num_divide(numval, n); break;
759 case '%': n = (long)num_modulus(numval, n); break;
760 }
761 }
762 else if (opt_type == 0 && stringval != NULL) // string
763 {
764 s = concat_str(stringval, s);
765 vim_free(stringval);
766 stringval = s;
767 }
768 }
769 }
770 if (s != NULL)
771 {
772 set_option_value(arg, n, s, opt_flags);
773 arg_end = p;
774 }
775 *p = c1;
776 vim_free(stringval);
777 }
778 }
779
780 // ":let @r = expr": Set register contents.
781 else if (*arg == '@')
782 {
783 if (is_const)
784 {
785 emsg(_("E996: Cannot lock a register"));
786 return NULL;
787 }
788 ++arg;
789 if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
790 semsg(_(e_letwrong), op);
791 else if (endchars != NULL
792 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
793 emsg(_(e_letunexp));
794 else
795 {
796 char_u *ptofree = NULL;
797 char_u *s;
798
799 p = tv_get_string_chk(tv);
800 if (p != NULL && op != NULL && *op == '.')
801 {
802 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
803 if (s != NULL)
804 {
805 p = ptofree = concat_str(s, p);
806 vim_free(s);
807 }
808 }
809 if (p != NULL)
810 {
811 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
812 arg_end = arg + 1;
813 }
814 vim_free(ptofree);
815 }
816 }
817
818 // ":let var = expr": Set internal variable.
819 // ":let {expr} = expr": Idem, name made with curly braces
820 else if (eval_isnamec1(*arg) || *arg == '{')
821 {
822 lval_T lv;
823
824 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
825 if (p != NULL && lv.ll_name != NULL)
826 {
827 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
828 emsg(_(e_letunexp));
829 else
830 {
831 set_var_lval(&lv, p, tv, copy, is_const, op);
832 arg_end = p;
833 }
834 }
835 clear_lval(&lv);
836 }
837
838 else
839 semsg(_(e_invarg2), arg);
840
841 return arg_end;
842 }
843
844 /*
845 * ":unlet[!] var1 ... " command.
846 */
847 void
848 ex_unlet(exarg_T *eap)
849 {
850 ex_unletlock(eap, eap->arg, 0);
851 }
852
853 /*
854 * ":lockvar" and ":unlockvar" commands
855 */
856 void
857 ex_lockvar(exarg_T *eap)
858 {
859 char_u *arg = eap->arg;
860 int deep = 2;
861
862 if (eap->forceit)
863 deep = -1;
864 else if (vim_isdigit(*arg))
865 {
866 deep = getdigits(&arg);
867 arg = skipwhite(arg);
868 }
869
870 ex_unletlock(eap, arg, deep);
871 }
872
873 /*
874 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
875 */
876 static void
877 ex_unletlock(
878 exarg_T *eap,
879 char_u *argstart,
880 int deep)
881 {
882 char_u *arg = argstart;
883 char_u *name_end;
884 int error = FALSE;
885 lval_T lv;
886
887 do
888 {
889 if (*arg == '$')
890 {
891 char_u *name = ++arg;
892
893 if (get_env_len(&arg) == 0)
894 {
895 semsg(_(e_invarg2), name - 1);
896 return;
897 }
898 vim_unsetenv(name);
899 arg = skipwhite(arg);
900 continue;
901 }
902
903 // Parse the name and find the end.
904 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
905 FNE_CHECK_START);
906 if (lv.ll_name == NULL)
907 error = TRUE; // error but continue parsing
908 if (name_end == NULL || (!VIM_ISWHITE(*name_end)
909 && !ends_excmd(*name_end)))
910 {
911 if (name_end != NULL)
912 {
913 emsg_severe = TRUE;
914 emsg(_(e_trailing));
915 }
916 if (!(eap->skip || error))
917 clear_lval(&lv);
918 break;
919 }
920
921 if (!error && !eap->skip)
922 {
923 if (eap->cmdidx == CMD_unlet)
924 {
925 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
926 error = TRUE;
927 }
928 else
929 {
930 if (do_lock_var(&lv, name_end, deep,
931 eap->cmdidx == CMD_lockvar) == FAIL)
932 error = TRUE;
933 }
934 }
935
936 if (!eap->skip)
937 clear_lval(&lv);
938
939 arg = skipwhite(name_end);
940 } while (!ends_excmd(*arg));
941
942 eap->nextcmd = check_nextcmd(arg);
943 }
944
945 static int
946 do_unlet_var(
947 lval_T *lp,
948 char_u *name_end,
949 int forceit)
950 {
951 int ret = OK;
952 int cc;
953
954 if (lp->ll_tv == NULL)
955 {
956 cc = *name_end;
957 *name_end = NUL;
958
959 // Normal name or expanded name.
960 if (do_unlet(lp->ll_name, forceit) == FAIL)
961 ret = FAIL;
962 *name_end = cc;
963 }
964 else if ((lp->ll_list != NULL
965 && var_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE))
966 || (lp->ll_dict != NULL
967 && var_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE)))
968 return FAIL;
969 else if (lp->ll_range)
970 {
971 listitem_T *li;
972 listitem_T *ll_li = lp->ll_li;
973 int ll_n1 = lp->ll_n1;
974
975 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
976 {
977 li = ll_li->li_next;
978 if (var_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE))
979 return FAIL;
980 ll_li = li;
981 ++ll_n1;
982 }
983
984 // Delete a range of List items.
985 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
986 {
987 li = lp->ll_li->li_next;
988 listitem_remove(lp->ll_list, lp->ll_li);
989 lp->ll_li = li;
990 ++lp->ll_n1;
991 }
992 }
993 else
994 {
995 if (lp->ll_list != NULL)
996 // unlet a List item.
997 listitem_remove(lp->ll_list, lp->ll_li);
998 else
999 // unlet a Dictionary item.
1000 dictitem_remove(lp->ll_dict, lp->ll_di);
1001 }
1002
1003 return ret;
1004 }
1005
1006 /*
1007 * "unlet" a variable. Return OK if it existed, FAIL if not.
1008 * When "forceit" is TRUE don't complain if the variable doesn't exist.
1009 */
1010 int
1011 do_unlet(char_u *name, int forceit)
1012 {
1013 hashtab_T *ht;
1014 hashitem_T *hi;
1015 char_u *varname;
1016 dict_T *d;
1017 dictitem_T *di;
1018
1019 ht = find_var_ht(name, &varname);
1020 if (ht != NULL && *varname != NUL)
1021 {
1022 d = get_current_funccal_dict(ht);
1023 if (d == NULL)
1024 {
1025 if (ht == &globvarht)
1026 d = &globvardict;
1027 else if (is_compatht(ht))
1028 d = &vimvardict;
1029 else
1030 {
1031 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
1032 d = di == NULL ? NULL : di->di_tv.vval.v_dict;
1033 }
1034 if (d == NULL)
1035 {
1036 internal_error("do_unlet()");
1037 return FAIL;
1038 }
1039 }
1040 hi = hash_find(ht, varname);
1041 if (HASHITEM_EMPTY(hi))
1042 hi = find_hi_in_scoped_ht(name, &ht);
1043 if (hi != NULL && !HASHITEM_EMPTY(hi))
1044 {
1045 di = HI2DI(hi);
1046 if (var_check_fixed(di->di_flags, name, FALSE)
1047 || var_check_ro(di->di_flags, name, FALSE)
1048 || var_check_lock(d->dv_lock, name, FALSE))
1049 return FAIL;
1050
1051 delete_var(ht, hi);
1052 return OK;
1053 }
1054 }
1055 if (forceit)
1056 return OK;
1057 semsg(_("E108: No such variable: \"%s\""), name);
1058 return FAIL;
1059 }
1060
1061 /*
1062 * Lock or unlock variable indicated by "lp".
1063 * "deep" is the levels to go (-1 for unlimited);
1064 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
1065 */
1066 static int
1067 do_lock_var(
1068 lval_T *lp,
1069 char_u *name_end,
1070 int deep,
1071 int lock)
1072 {
1073 int ret = OK;
1074 int cc;
1075 dictitem_T *di;
1076
1077 if (deep == 0) // nothing to do
1078 return OK;
1079
1080 if (lp->ll_tv == NULL)
1081 {
1082 cc = *name_end;
1083 *name_end = NUL;
1084
1085 // Normal name or expanded name.
1086 di = find_var(lp->ll_name, NULL, TRUE);
1087 if (di == NULL)
1088 ret = FAIL;
1089 else if ((di->di_flags & DI_FLAGS_FIX)
1090 && di->di_tv.v_type != VAR_DICT
1091 && di->di_tv.v_type != VAR_LIST)
1092 // For historic reasons this error is not given for a list or dict.
1093 // E.g., the b: dict could be locked/unlocked.
1094 semsg(_("E940: Cannot lock or unlock variable %s"), lp->ll_name);
1095 else
1096 {
1097 if (lock)
1098 di->di_flags |= DI_FLAGS_LOCK;
1099 else
1100 di->di_flags &= ~DI_FLAGS_LOCK;
1101 item_lock(&di->di_tv, deep, lock);
1102 }
1103 *name_end = cc;
1104 }
1105 else if (lp->ll_range)
1106 {
1107 listitem_T *li = lp->ll_li;
1108
1109 // (un)lock a range of List items.
1110 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
1111 {
1112 item_lock(&li->li_tv, deep, lock);
1113 li = li->li_next;
1114 ++lp->ll_n1;
1115 }
1116 }
1117 else if (lp->ll_list != NULL)
1118 // (un)lock a List item.
1119 item_lock(&lp->ll_li->li_tv, deep, lock);
1120 else
1121 // (un)lock a Dictionary item.
1122 item_lock(&lp->ll_di->di_tv, deep, lock);
1123
1124 return ret;
1125 }
1126
1127 /*
1128 * Lock or unlock an item. "deep" is nr of levels to go.
1129 */
1130 static void
1131 item_lock(typval_T *tv, int deep, int lock)
1132 {
1133 static int recurse = 0;
1134 list_T *l;
1135 listitem_T *li;
1136 dict_T *d;
1137 blob_T *b;
1138 hashitem_T *hi;
1139 int todo;
1140
1141 if (recurse >= DICT_MAXNEST)
1142 {
1143 emsg(_("E743: variable nested too deep for (un)lock"));
1144 return;
1145 }
1146 if (deep == 0)
1147 return;
1148 ++recurse;
1149
1150 // lock/unlock the item itself
1151 if (lock)
1152 tv->v_lock |= VAR_LOCKED;
1153 else
1154 tv->v_lock &= ~VAR_LOCKED;
1155
1156 switch (tv->v_type)
1157 {
1158 case VAR_UNKNOWN:
1159 case VAR_NUMBER:
1160 case VAR_STRING:
1161 case VAR_FUNC:
1162 case VAR_PARTIAL:
1163 case VAR_FLOAT:
1164 case VAR_SPECIAL:
1165 case VAR_JOB:
1166 case VAR_CHANNEL:
1167 break;
1168
1169 case VAR_BLOB:
1170 if ((b = tv->vval.v_blob) != NULL)
1171 {
1172 if (lock)
1173 b->bv_lock |= VAR_LOCKED;
1174 else
1175 b->bv_lock &= ~VAR_LOCKED;
1176 }
1177 break;
1178 case VAR_LIST:
1179 if ((l = tv->vval.v_list) != NULL)
1180 {
1181 if (lock)
1182 l->lv_lock |= VAR_LOCKED;
1183 else
1184 l->lv_lock &= ~VAR_LOCKED;
1185 if (deep < 0 || deep > 1)
1186 // recursive: lock/unlock the items the List contains
1187 for (li = l->lv_first; li != NULL; li = li->li_next)
1188 item_lock(&li->li_tv, deep - 1, lock);
1189 }
1190 break;
1191 case VAR_DICT:
1192 if ((d = tv->vval.v_dict) != NULL)
1193 {
1194 if (lock)
1195 d->dv_lock |= VAR_LOCKED;
1196 else
1197 d->dv_lock &= ~VAR_LOCKED;
1198 if (deep < 0 || deep > 1)
1199 {
1200 // recursive: lock/unlock the items the List contains
1201 todo = (int)d->dv_hashtab.ht_used;
1202 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
1203 {
1204 if (!HASHITEM_EMPTY(hi))
1205 {
1206 --todo;
1207 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
1208 }
1209 }
1210 }
1211 }
1212 }
1213 --recurse;
1214 }
1215
1216 /*
1217 * Get the value of internal variable "name".
1218 * Return OK or FAIL. If OK is returned "rettv" must be cleared.
1219 */
1220 int
1221 get_var_tv(
1222 char_u *name,
1223 int len, // length of "name"
1224 typval_T *rettv, // NULL when only checking existence
1225 dictitem_T **dip, // non-NULL when typval's dict item is needed
1226 int verbose, // may give error message
1227 int no_autoload) // do not use script autoloading
1228 {
1229 int ret = OK;
1230 typval_T *tv = NULL;
1231 dictitem_T *v;
1232 int cc;
1233
1234 // truncate the name, so that we can use strcmp()
1235 cc = name[len];
1236 name[len] = NUL;
1237
1238 // Check for user-defined variables.
1239 v = find_var(name, NULL, no_autoload);
1240 if (v != NULL)
1241 {
1242 tv = &v->di_tv;
1243 if (dip != NULL)
1244 *dip = v;
1245 }
1246
1247 if (tv == NULL)
1248 {
1249 if (rettv != NULL && verbose)
1250 semsg(_(e_undefvar), name);
1251 ret = FAIL;
1252 }
1253 else if (rettv != NULL)
1254 copy_tv(tv, rettv);
1255
1256 name[len] = cc;
1257
1258 return ret;
1259 }
1260
1261 /*
1262 * Get the string value of a (global/local) variable.
1263 * Note: see tv_get_string() for how long the pointer remains valid.
1264 * Returns NULL when it doesn't exist.
1265 */
1266 char_u *
1267 get_var_value(char_u *name)
1268 {
1269 dictitem_T *v;
1270
1271 v = find_var(name, NULL, FALSE);
1272 if (v == NULL)
1273 return NULL;
1274 return tv_get_string(&v->di_tv);
1275 }
1276
1277 /*
1278 * Clean up a list of internal variables.
1279 * Frees all allocated variables and the value they contain.
1280 * Clears hashtab "ht", does not free it.
1281 */
1282 void
1283 vars_clear(hashtab_T *ht)
1284 {
1285 vars_clear_ext(ht, TRUE);
1286 }
1287
1288 /*
1289 * Like vars_clear(), but only free the value if "free_val" is TRUE.
1290 */
1291 void
1292 vars_clear_ext(hashtab_T *ht, int free_val)
1293 {
1294 int todo;
1295 hashitem_T *hi;
1296 dictitem_T *v;
1297
1298 hash_lock(ht);
1299 todo = (int)ht->ht_used;
1300 for (hi = ht->ht_array; todo > 0; ++hi)
1301 {
1302 if (!HASHITEM_EMPTY(hi))
1303 {
1304 --todo;
1305
1306 // Free the variable. Don't remove it from the hashtab,
1307 // ht_array might change then. hash_clear() takes care of it
1308 // later.
1309 v = HI2DI(hi);
1310 if (free_val)
1311 clear_tv(&v->di_tv);
1312 if (v->di_flags & DI_FLAGS_ALLOC)
1313 vim_free(v);
1314 }
1315 }
1316 hash_clear(ht);
1317 ht->ht_used = 0;
1318 }
1319
1320 /*
1321 * Delete a variable from hashtab "ht" at item "hi".
1322 * Clear the variable value and free the dictitem.
1323 */
1324 void
1325 delete_var(hashtab_T *ht, hashitem_T *hi)
1326 {
1327 dictitem_T *di = HI2DI(hi);
1328
1329 hash_remove(ht, hi);
1330 clear_tv(&di->di_tv);
1331 vim_free(di);
1332 }
1333
1334 /*
1335 * List the value of one internal variable.
1336 */
1337 static void
1338 list_one_var(dictitem_T *v, char *prefix, int *first)
1339 {
1340 char_u *tofree;
1341 char_u *s;
1342 char_u numbuf[NUMBUFLEN];
1343
1344 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID());
1345 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
1346 s == NULL ? (char_u *)"" : s, first);
1347 vim_free(tofree);
1348 }
1349
1350 static void
1351 list_one_var_a(
1352 char *prefix,
1353 char_u *name,
1354 int type,
1355 char_u *string,
1356 int *first) // when TRUE clear rest of screen and set to FALSE
1357 {
1358 // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg"
1359 msg_start();
1360 msg_puts(prefix);
1361 if (name != NULL) // "a:" vars don't have a name stored
1362 msg_puts((char *)name);
1363 msg_putchar(' ');
1364 msg_advance(22);
1365 if (type == VAR_NUMBER)
1366 msg_putchar('#');
1367 else if (type == VAR_FUNC || type == VAR_PARTIAL)
1368 msg_putchar('*');
1369 else if (type == VAR_LIST)
1370 {
1371 msg_putchar('[');
1372 if (*string == '[')
1373 ++string;
1374 }
1375 else if (type == VAR_DICT)
1376 {
1377 msg_putchar('{');
1378 if (*string == '{')
1379 ++string;
1380 }
1381 else
1382 msg_putchar(' ');
1383
1384 msg_outtrans(string);
1385
1386 if (type == VAR_FUNC || type == VAR_PARTIAL)
1387 msg_puts("()");
1388 if (*first)
1389 {
1390 msg_clr_eos();
1391 *first = FALSE;
1392 }
1393 }
1394
1395 /*
1396 * Set variable "name" to value in "tv".
1397 * If the variable already exists, the value is updated.
1398 * Otherwise the variable is created.
1399 */
1400 void
1401 set_var(
1402 char_u *name,
1403 typval_T *tv,
1404 int copy) // make copy of value in "tv"
1405 {
1406 set_var_const(name, tv, copy, FALSE);
1407 }
1408
1409 /*
1410 * Set variable "name" to value in "tv".
1411 * If the variable already exists and "is_const" is FALSE the value is updated.
1412 * Otherwise the variable is created.
1413 */
1414 void
1415 set_var_const(
1416 char_u *name,
1417 typval_T *tv,
1418 int copy, // make copy of value in "tv"
1419 int is_const) // disallow to modify existing variable
1420 {
1421 dictitem_T *v;
1422 char_u *varname;
1423 hashtab_T *ht;
1424
1425 ht = find_var_ht(name, &varname);
1426 if (ht == NULL || *varname == NUL)
1427 {
1428 semsg(_(e_illvar), name);
1429 return;
1430 }
1431 v = find_var_in_ht(ht, 0, varname, TRUE);
1432
1433 // Search in parent scope which is possible to reference from lambda
1434 if (v == NULL)
1435 v = find_var_in_scoped_ht(name, TRUE);
1436
1437 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
1438 && var_check_func_name(name, v == NULL))
1439 return;
1440
1441 if (v != NULL)
1442 {
1443 if (is_const)
1444 {
1445 emsg(_(e_cannot_mod));
1446 return;
1447 }
1448
1449 // existing variable, need to clear the value
1450 if (var_check_ro(v->di_flags, name, FALSE)
1451 || var_check_lock(v->di_tv.v_lock, name, FALSE))
1452 return;
1453
1454 // Handle setting internal v: variables separately where needed to
1455 // prevent changing the type.
1456 if (is_vimvarht(ht))
1457 {
1458 if (v->di_tv.v_type == VAR_STRING)
1459 {
1460 VIM_CLEAR(v->di_tv.vval.v_string);
1461 if (copy || tv->v_type != VAR_STRING)
1462 {
1463 char_u *val = tv_get_string(tv);
1464
1465 // Careful: when assigning to v:errmsg and tv_get_string()
1466 // causes an error message the variable will alrady be set.
1467 if (v->di_tv.vval.v_string == NULL)
1468 v->di_tv.vval.v_string = vim_strsave(val);
1469 }
1470 else
1471 {
1472 // Take over the string to avoid an extra alloc/free.
1473 v->di_tv.vval.v_string = tv->vval.v_string;
1474 tv->vval.v_string = NULL;
1475 }
1476 return;
1477 }
1478 else if (v->di_tv.v_type == VAR_NUMBER)
1479 {
1480 v->di_tv.vval.v_number = tv_get_number(tv);
1481 if (STRCMP(varname, "searchforward") == 0)
1482 set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
1483 #ifdef FEAT_SEARCH_EXTRA
1484 else if (STRCMP(varname, "hlsearch") == 0)
1485 {
1486 no_hlsearch = !v->di_tv.vval.v_number;
1487 redraw_all_later(SOME_VALID);
1488 }
1489 #endif
1490 return;
1491 }
1492 else if (v->di_tv.v_type != tv->v_type)
1493 {
1494 semsg(_("E963: setting %s to value with wrong type"), name);
1495 return;
1496 }
1497 }
1498
1499 clear_tv(&v->di_tv);
1500 }
1501 else // add a new variable
1502 {
1503 // Can't add "v:" or "a:" variable.
1504 if (is_vimvarht(ht) || ht == get_funccal_args_ht())
1505 {
1506 semsg(_(e_illvar), name);
1507 return;
1508 }
1509
1510 // Make sure the variable name is valid.
1511 if (!valid_varname(varname))
1512 return;
1513
1514 v = alloc(sizeof(dictitem_T) + STRLEN(varname));
1515 if (v == NULL)
1516 return;
1517 STRCPY(v->di_key, varname);
1518 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
1519 {
1520 vim_free(v);
1521 return;
1522 }
1523 v->di_flags = DI_FLAGS_ALLOC;
1524 if (is_const)
1525 v->di_flags |= DI_FLAGS_LOCK;
1526 }
1527
1528 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
1529 copy_tv(tv, &v->di_tv);
1530 else
1531 {
1532 v->di_tv = *tv;
1533 v->di_tv.v_lock = 0;
1534 init_tv(tv);
1535 }
1536
1537 if (is_const)
1538 v->di_tv.v_lock |= VAR_LOCKED;
1539 }
1540
1541 /*
1542 * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
1543 * Also give an error message.
1544 */
1545 int
1546 var_check_ro(int flags, char_u *name, int use_gettext)
1547 {
1548 if (flags & DI_FLAGS_RO)
1549 {
1550 semsg(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
1551 return TRUE;
1552 }
1553 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
1554 {
1555 semsg(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
1556 return TRUE;
1557 }
1558 return FALSE;
1559 }
1560
1561 /*
1562 * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
1563 * Also give an error message.
1564 */
1565 int
1566 var_check_fixed(int flags, char_u *name, int use_gettext)
1567 {
1568 if (flags & DI_FLAGS_FIX)
1569 {
1570 semsg(_("E795: Cannot delete variable %s"),
1571 use_gettext ? (char_u *)_(name) : name);
1572 return TRUE;
1573 }
1574 return FALSE;
1575 }
1576
1577 /*
1578 * Check if a funcref is assigned to a valid variable name.
1579 * Return TRUE and give an error if not.
1580 */
1581 int
1582 var_check_func_name(
1583 char_u *name, // points to start of variable name
1584 int new_var) // TRUE when creating the variable
1585 {
1586 // Allow for w: b: s: and t:.
1587 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':')
1588 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
1589 ? name[2] : name[0]))
1590 {
1591 semsg(_("E704: Funcref variable name must start with a capital: %s"),
1592 name);
1593 return TRUE;
1594 }
1595 // Don't allow hiding a function. When "v" is not NULL we might be
1596 // assigning another function to the same var, the type is checked
1597 // below.
1598 if (new_var && function_exists(name, FALSE))
1599 {
1600 semsg(_("E705: Variable name conflicts with existing function: %s"),
1601 name);
1602 return TRUE;
1603 }
1604 return FALSE;
1605 }
1606
1607 /*
1608 * Return TRUE if "flags" indicates variable "name" is locked (immutable).
1609 * Also give an error message, using "name" or _("name") when use_gettext is
1610 * TRUE.
1611 */
1612 int
1613 var_check_lock(int lock, char_u *name, int use_gettext)
1614 {
1615 if (lock & VAR_LOCKED)
1616 {
1617 semsg(_("E741: Value is locked: %s"),
1618 name == NULL ? (char_u *)_("Unknown")
1619 : use_gettext ? (char_u *)_(name)
1620 : name);
1621 return TRUE;
1622 }
1623 if (lock & VAR_FIXED)
1624 {
1625 semsg(_("E742: Cannot change value of %s"),
1626 name == NULL ? (char_u *)_("Unknown")
1627 : use_gettext ? (char_u *)_(name)
1628 : name);
1629 return TRUE;
1630 }
1631 return FALSE;
1632 }
1633
1634 /*
1635 * Check if a variable name is valid.
1636 * Return FALSE and give an error if not.
1637 */
1638 int
1639 valid_varname(char_u *varname)
1640 {
1641 char_u *p;
1642
1643 for (p = varname; *p != NUL; ++p)
1644 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
1645 && *p != AUTOLOAD_CHAR)
1646 {
1647 semsg(_(e_illvar), varname);
1648 return FALSE;
1649 }
1650 return TRUE;
1651 }
1652
1653 /*
1654 * getwinvar() and gettabwinvar()
1655 */
1656 static void
1657 getwinvar(
1658 typval_T *argvars,
1659 typval_T *rettv,
1660 int off) // 1 for gettabwinvar()
1661 {
1662 win_T *win;
1663 char_u *varname;
1664 dictitem_T *v;
1665 tabpage_T *tp = NULL;
1666 int done = FALSE;
1667 win_T *oldcurwin;
1668 tabpage_T *oldtabpage;
1669 int need_switch_win;
1670
1671 if (off == 1)
1672 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
1673 else
1674 tp = curtab;
1675 win = find_win_by_nr(&argvars[off], tp);
1676 varname = tv_get_string_chk(&argvars[off + 1]);
1677 ++emsg_off;
1678
1679 rettv->v_type = VAR_STRING;
1680 rettv->vval.v_string = NULL;
1681
1682 if (win != NULL && varname != NULL)
1683 {
1684 // Set curwin to be our win, temporarily. Also set the tabpage,
1685 // otherwise the window is not valid. Only do this when needed,
1686 // autocommands get blocked.
1687 need_switch_win = !(tp == curtab && win == curwin);
1688 if (!need_switch_win
1689 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
1690 {
1691 if (*varname == '&')
1692 {
1693 if (varname[1] == NUL)
1694 {
1695 // get all window-local options in a dict
1696 dict_T *opts = get_winbuf_options(FALSE);
1697
1698 if (opts != NULL)
1699 {
1700 rettv_dict_set(rettv, opts);
1701 done = TRUE;
1702 }
1703 }
1704 else if (get_option_tv(&varname, rettv, 1) == OK)
1705 // window-local-option
1706 done = TRUE;
1707 }
1708 else
1709 {
1710 // Look up the variable.
1711 // Let getwinvar({nr}, "") return the "w:" dictionary.
1712 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
1713 varname, FALSE);
1714 if (v != NULL)
1715 {
1716 copy_tv(&v->di_tv, rettv);
1717 done = TRUE;
1718 }
1719 }
1720 }
1721
1722 if (need_switch_win)
1723 // restore previous notion of curwin
1724 restore_win(oldcurwin, oldtabpage, TRUE);
1725 }
1726
1727 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
1728 // use the default return value
1729 copy_tv(&argvars[off + 2], rettv);
1730
1731 --emsg_off;
1732 }
1733
1734 /*
1735 * "setwinvar()" and "settabwinvar()" functions
1736 */
1737 static void
1738 setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off)
1739 {
1740 win_T *win;
1741 win_T *save_curwin;
1742 tabpage_T *save_curtab;
1743 int need_switch_win;
1744 char_u *varname, *winvarname;
1745 typval_T *varp;
1746 char_u nbuf[NUMBUFLEN];
1747 tabpage_T *tp = NULL;
1748
1749 if (check_secure())
1750 return;
1751
1752 if (off == 1)
1753 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
1754 else
1755 tp = curtab;
1756 win = find_win_by_nr(&argvars[off], tp);
1757 varname = tv_get_string_chk(&argvars[off + 1]);
1758 varp = &argvars[off + 2];
1759
1760 if (win != NULL && varname != NULL && varp != NULL)
1761 {
1762 need_switch_win = !(tp == curtab && win == curwin);
1763 if (!need_switch_win
1764 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK)
1765 {
1766 if (*varname == '&')
1767 {
1768 long numval;
1769 char_u *strval;
1770 int error = FALSE;
1771
1772 ++varname;
1773 numval = (long)tv_get_number_chk(varp, &error);
1774 strval = tv_get_string_buf_chk(varp, nbuf);
1775 if (!error && strval != NULL)
1776 set_option_value(varname, numval, strval, OPT_LOCAL);
1777 }
1778 else
1779 {
1780 winvarname = alloc(STRLEN(varname) + 3);
1781 if (winvarname != NULL)
1782 {
1783 STRCPY(winvarname, "w:");
1784 STRCPY(winvarname + 2, varname);
1785 set_var(winvarname, varp, TRUE);
1786 vim_free(winvarname);
1787 }
1788 }
1789 }
1790 if (need_switch_win)
1791 restore_win(save_curwin, save_curtab, TRUE);
1792 }
1793 }
1794
1795 int
1796 var_exists(char_u *var)
1797 {
1798 char_u *name;
1799 char_u *tofree;
1800 typval_T tv;
1801 int len = 0;
1802 int n = FALSE;
1803
1804 // get_name_len() takes care of expanding curly braces
1805 name = var;
1806 len = get_name_len(&var, &tofree, TRUE, FALSE);
1807 if (len > 0)
1808 {
1809 if (tofree != NULL)
1810 name = tofree;
1811 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK);
1812 if (n)
1813 {
1814 // handle d.key, l[idx], f(expr)
1815 n = (handle_subscript(&var, &tv, TRUE, FALSE, name, &name) == OK);
1816 if (n)
1817 clear_tv(&tv);
1818 }
1819 }
1820 if (*var != NUL)
1821 n = FALSE;
1822
1823 vim_free(tofree);
1824 return n;
1825 }
1826
1827 /*
1828 * "gettabvar()" function
1829 */
1830 void
1831 f_gettabvar(typval_T *argvars, typval_T *rettv)
1832 {
1833 win_T *oldcurwin;
1834 tabpage_T *tp, *oldtabpage;
1835 dictitem_T *v;
1836 char_u *varname;
1837 int done = FALSE;
1838
1839 rettv->v_type = VAR_STRING;
1840 rettv->vval.v_string = NULL;
1841
1842 varname = tv_get_string_chk(&argvars[1]);
1843 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
1844 if (tp != NULL && varname != NULL)
1845 {
1846 // Set tp to be our tabpage, temporarily. Also set the window to the
1847 // first window in the tabpage, otherwise the window is not valid.
1848 if (switch_win(&oldcurwin, &oldtabpage,
1849 tp == curtab || tp->tp_firstwin == NULL ? firstwin
1850 : tp->tp_firstwin, tp, TRUE) == OK)
1851 {
1852 // look up the variable
1853 // Let gettabvar({nr}, "") return the "t:" dictionary.
1854 v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
1855 if (v != NULL)
1856 {
1857 copy_tv(&v->di_tv, rettv);
1858 done = TRUE;
1859 }
1860 }
1861
1862 // restore previous notion of curwin
1863 restore_win(oldcurwin, oldtabpage, TRUE);
1864 }
1865
1866 if (!done && argvars[2].v_type != VAR_UNKNOWN)
1867 copy_tv(&argvars[2], rettv);
1868 }
1869
1870 /*
1871 * "gettabwinvar()" function
1872 */
1873 void
1874 f_gettabwinvar(typval_T *argvars, typval_T *rettv)
1875 {
1876 getwinvar(argvars, rettv, 1);
1877 }
1878
1879 /*
1880 * "getwinvar()" function
1881 */
1882 void
1883 f_getwinvar(typval_T *argvars, typval_T *rettv)
1884 {
1885 getwinvar(argvars, rettv, 0);
1886 }
1887
1888 /*
1889 * "settabvar()" function
1890 */
1891 void
1892 f_settabvar(typval_T *argvars, typval_T *rettv)
1893 {
1894 tabpage_T *save_curtab;
1895 tabpage_T *tp;
1896 char_u *varname, *tabvarname;
1897 typval_T *varp;
1898
1899 rettv->vval.v_number = 0;
1900
1901 if (check_secure())
1902 return;
1903
1904 tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
1905 varname = tv_get_string_chk(&argvars[1]);
1906 varp = &argvars[2];
1907
1908 if (varname != NULL && varp != NULL && tp != NULL)
1909 {
1910 save_curtab = curtab;
1911 goto_tabpage_tp(tp, FALSE, FALSE);
1912
1913 tabvarname = alloc(STRLEN(varname) + 3);
1914 if (tabvarname != NULL)
1915 {
1916 STRCPY(tabvarname, "t:");
1917 STRCPY(tabvarname + 2, varname);
1918 set_var(tabvarname, varp, TRUE);
1919 vim_free(tabvarname);
1920 }
1921
1922 // Restore current tabpage
1923 if (valid_tabpage(save_curtab))
1924 goto_tabpage_tp(save_curtab, FALSE, FALSE);
1925 }
1926 }
1927
1928 /*
1929 * "settabwinvar()" function
1930 */
1931 void
1932 f_settabwinvar(typval_T *argvars, typval_T *rettv)
1933 {
1934 setwinvar(argvars, rettv, 1);
1935 }
1936
1937 /*
1938 * "setwinvar()" function
1939 */
1940 void
1941 f_setwinvar(typval_T *argvars, typval_T *rettv)
1942 {
1943 setwinvar(argvars, rettv, 0);
1944 }
1945
1946 #endif // FEAT_EVAL