Mercurial > vim
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), <v, FALSE, is_const, | |
372 (char_u *)"]", op); | |
373 clear_tv(<v); | |
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 |