Mercurial > vim
comparison src/evalvars.c @ 17885:5e2d8840da11 v8.1.1939
patch 8.1.1939: code for handling v: variables in generic eval file
Commit: https://github.com/vim/vim/commit/e5cdf153bcb348c68011b308c8988cea42d6ddeb
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Aug 29 22:09:46 2019 +0200
patch 8.1.1939: code for handling v: variables in generic eval file
Problem: Code for handling v: variables in generic eval file.
Solution: Move v: variables to evalvars.c. (Yegappan Lakshmanan,
closes #4872)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 29 Aug 2019 22:15:04 +0200 |
parents | d50a5faa75bd |
children | 39ffd167a307 |
comparison
equal
deleted
inserted
replaced
17884:ae47d7c8416c | 17885:5e2d8840da11 |
---|---|
14 #include "vim.h" | 14 #include "vim.h" |
15 | 15 |
16 #if defined(FEAT_EVAL) || defined(PROTO) | 16 #if defined(FEAT_EVAL) || defined(PROTO) |
17 | 17 |
18 static char *e_letunexp = N_("E18: Unexpected characters in :let"); | 18 static char *e_letunexp = N_("E18: Unexpected characters in :let"); |
19 | |
20 static dictitem_T globvars_var; // variable used for g: | |
21 | |
22 /* | |
23 * Old Vim variables such as "v:version" are also available without the "v:". | |
24 * Also in functions. We need a special hashtable for them. | |
25 */ | |
26 static hashtab_T compat_hashtab; | |
27 | |
28 /* | |
29 * Array to hold the value of v: variables. | |
30 * The value is in a dictitem, so that it can also be used in the v: scope. | |
31 * The reason to use this table anyway is for very quick access to the | |
32 * variables with the VV_ defines. | |
33 */ | |
34 | |
35 // values for vv_flags: | |
36 #define VV_COMPAT 1 // compatible, also used without "v:" | |
37 #define VV_RO 2 // read-only | |
38 #define VV_RO_SBX 4 // read-only in the sandbox | |
39 | |
40 #define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}} | |
41 | |
42 static struct vimvar | |
43 { | |
44 char *vv_name; // name of variable, without v: | |
45 dictitem16_T vv_di; // value and name for key (max 16 chars!) | |
46 char vv_flags; // VV_COMPAT, VV_RO, VV_RO_SBX | |
47 } vimvars[VV_LEN] = | |
48 { | |
49 /* | |
50 * The order here must match the VV_ defines in vim.h! | |
51 * Initializing a union does not work, leave tv.vval empty to get zero's. | |
52 */ | |
53 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, | |
54 {VV_NAME("count1", VAR_NUMBER), VV_RO}, | |
55 {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, | |
56 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, | |
57 {VV_NAME("warningmsg", VAR_STRING), 0}, | |
58 {VV_NAME("statusmsg", VAR_STRING), 0}, | |
59 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, | |
60 {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, | |
61 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, | |
62 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, | |
63 {VV_NAME("termresponse", VAR_STRING), VV_RO}, | |
64 {VV_NAME("fname", VAR_STRING), VV_RO}, | |
65 {VV_NAME("lang", VAR_STRING), VV_RO}, | |
66 {VV_NAME("lc_time", VAR_STRING), VV_RO}, | |
67 {VV_NAME("ctype", VAR_STRING), VV_RO}, | |
68 {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, | |
69 {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, | |
70 {VV_NAME("fname_in", VAR_STRING), VV_RO}, | |
71 {VV_NAME("fname_out", VAR_STRING), VV_RO}, | |
72 {VV_NAME("fname_new", VAR_STRING), VV_RO}, | |
73 {VV_NAME("fname_diff", VAR_STRING), VV_RO}, | |
74 {VV_NAME("cmdarg", VAR_STRING), VV_RO}, | |
75 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, | |
76 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, | |
77 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, | |
78 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, | |
79 {VV_NAME("progname", VAR_STRING), VV_RO}, | |
80 {VV_NAME("servername", VAR_STRING), VV_RO}, | |
81 {VV_NAME("dying", VAR_NUMBER), VV_RO}, | |
82 {VV_NAME("exception", VAR_STRING), VV_RO}, | |
83 {VV_NAME("throwpoint", VAR_STRING), VV_RO}, | |
84 {VV_NAME("register", VAR_STRING), VV_RO}, | |
85 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, | |
86 {VV_NAME("insertmode", VAR_STRING), VV_RO}, | |
87 {VV_NAME("val", VAR_UNKNOWN), VV_RO}, | |
88 {VV_NAME("key", VAR_UNKNOWN), VV_RO}, | |
89 {VV_NAME("profiling", VAR_NUMBER), VV_RO}, | |
90 {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, | |
91 {VV_NAME("fcs_choice", VAR_STRING), 0}, | |
92 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, | |
93 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, | |
94 {VV_NAME("beval_winid", VAR_NUMBER), VV_RO}, | |
95 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, | |
96 {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, | |
97 {VV_NAME("beval_text", VAR_STRING), VV_RO}, | |
98 {VV_NAME("scrollstart", VAR_STRING), 0}, | |
99 {VV_NAME("swapname", VAR_STRING), VV_RO}, | |
100 {VV_NAME("swapchoice", VAR_STRING), 0}, | |
101 {VV_NAME("swapcommand", VAR_STRING), VV_RO}, | |
102 {VV_NAME("char", VAR_STRING), 0}, | |
103 {VV_NAME("mouse_win", VAR_NUMBER), 0}, | |
104 {VV_NAME("mouse_winid", VAR_NUMBER), 0}, | |
105 {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, | |
106 {VV_NAME("mouse_col", VAR_NUMBER), 0}, | |
107 {VV_NAME("operator", VAR_STRING), VV_RO}, | |
108 {VV_NAME("searchforward", VAR_NUMBER), 0}, | |
109 {VV_NAME("hlsearch", VAR_NUMBER), 0}, | |
110 {VV_NAME("oldfiles", VAR_LIST), 0}, | |
111 {VV_NAME("windowid", VAR_NUMBER), VV_RO}, | |
112 {VV_NAME("progpath", VAR_STRING), VV_RO}, | |
113 {VV_NAME("completed_item", VAR_DICT), VV_RO}, | |
114 {VV_NAME("option_new", VAR_STRING), VV_RO}, | |
115 {VV_NAME("option_old", VAR_STRING), VV_RO}, | |
116 {VV_NAME("option_oldlocal", VAR_STRING), VV_RO}, | |
117 {VV_NAME("option_oldglobal", VAR_STRING), VV_RO}, | |
118 {VV_NAME("option_command", VAR_STRING), VV_RO}, | |
119 {VV_NAME("option_type", VAR_STRING), VV_RO}, | |
120 {VV_NAME("errors", VAR_LIST), 0}, | |
121 {VV_NAME("false", VAR_SPECIAL), VV_RO}, | |
122 {VV_NAME("true", VAR_SPECIAL), VV_RO}, | |
123 {VV_NAME("null", VAR_SPECIAL), VV_RO}, | |
124 {VV_NAME("none", VAR_SPECIAL), VV_RO}, | |
125 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, | |
126 {VV_NAME("testing", VAR_NUMBER), 0}, | |
127 {VV_NAME("t_number", VAR_NUMBER), VV_RO}, | |
128 {VV_NAME("t_string", VAR_NUMBER), VV_RO}, | |
129 {VV_NAME("t_func", VAR_NUMBER), VV_RO}, | |
130 {VV_NAME("t_list", VAR_NUMBER), VV_RO}, | |
131 {VV_NAME("t_dict", VAR_NUMBER), VV_RO}, | |
132 {VV_NAME("t_float", VAR_NUMBER), VV_RO}, | |
133 {VV_NAME("t_bool", VAR_NUMBER), VV_RO}, | |
134 {VV_NAME("t_none", VAR_NUMBER), VV_RO}, | |
135 {VV_NAME("t_job", VAR_NUMBER), VV_RO}, | |
136 {VV_NAME("t_channel", VAR_NUMBER), VV_RO}, | |
137 {VV_NAME("t_blob", VAR_NUMBER), VV_RO}, | |
138 {VV_NAME("termrfgresp", VAR_STRING), VV_RO}, | |
139 {VV_NAME("termrbgresp", VAR_STRING), VV_RO}, | |
140 {VV_NAME("termu7resp", VAR_STRING), VV_RO}, | |
141 {VV_NAME("termstyleresp", VAR_STRING), VV_RO}, | |
142 {VV_NAME("termblinkresp", VAR_STRING), VV_RO}, | |
143 {VV_NAME("event", VAR_DICT), VV_RO}, | |
144 {VV_NAME("versionlong", VAR_NUMBER), VV_RO}, | |
145 {VV_NAME("echospace", VAR_NUMBER), VV_RO}, | |
146 }; | |
147 | |
148 // shorthand | |
149 #define vv_type vv_di.di_tv.v_type | |
150 #define vv_nr vv_di.di_tv.vval.v_number | |
151 #define vv_float vv_di.di_tv.vval.v_float | |
152 #define vv_str vv_di.di_tv.vval.v_string | |
153 #define vv_list vv_di.di_tv.vval.v_list | |
154 #define vv_dict vv_di.di_tv.vval.v_dict | |
155 #define vv_blob vv_di.di_tv.vval.v_blob | |
156 #define vv_tv vv_di.di_tv | |
157 | |
158 static dictitem_T vimvars_var; // variable used for v: | |
159 #define vimvarht vimvardict.dv_hashtab | |
160 | |
161 // for VIM_VERSION_ defines | |
162 #include "version.h" | |
163 | |
164 /* | |
165 * Array to hold the hashtab with variables local to each sourced script. | |
166 * Each item holds a variable (nameless) that points to the dict_T. | |
167 */ | |
168 typedef struct | |
169 { | |
170 dictitem_T sv_var; | |
171 dict_T sv_dict; | |
172 } scriptvar_T; | |
173 | |
174 static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; | |
175 #define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) | |
176 #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) | |
19 | 177 |
20 static void ex_let_const(exarg_T *eap, int is_const); | 178 static void ex_let_const(exarg_T *eap, int is_const); |
21 static char_u *skip_var_one(char_u *arg); | 179 static char_u *skip_var_one(char_u *arg); |
22 static void list_glob_vars(int *first); | 180 static void list_glob_vars(int *first); |
23 static void list_buf_vars(int *first); | 181 static void list_buf_vars(int *first); |
29 static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); | 187 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); | 188 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); | 189 static void item_lock(typval_T *tv, int deep, int lock); |
32 static void list_one_var(dictitem_T *v, char *prefix, int *first); | 190 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); | 191 static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first); |
192 | |
193 /* | |
194 * Initialize global and vim special variables | |
195 */ | |
196 void | |
197 evalvars_init(void) | |
198 { | |
199 int i; | |
200 struct vimvar *p; | |
201 | |
202 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); | |
203 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE); | |
204 vimvardict.dv_lock = VAR_FIXED; | |
205 hash_init(&compat_hashtab); | |
206 | |
207 for (i = 0; i < VV_LEN; ++i) | |
208 { | |
209 p = &vimvars[i]; | |
210 if (STRLEN(p->vv_name) > DICTITEM16_KEY_LEN) | |
211 { | |
212 iemsg("INTERNAL: name too long, increase size of dictitem16_T"); | |
213 getout(1); | |
214 } | |
215 STRCPY(p->vv_di.di_key, p->vv_name); | |
216 if (p->vv_flags & VV_RO) | |
217 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; | |
218 else if (p->vv_flags & VV_RO_SBX) | |
219 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX; | |
220 else | |
221 p->vv_di.di_flags = DI_FLAGS_FIX; | |
222 | |
223 // add to v: scope dict, unless the value is not always available | |
224 if (p->vv_type != VAR_UNKNOWN) | |
225 hash_add(&vimvarht, p->vv_di.di_key); | |
226 if (p->vv_flags & VV_COMPAT) | |
227 // add to compat scope dict | |
228 hash_add(&compat_hashtab, p->vv_di.di_key); | |
229 } | |
230 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; | |
231 vimvars[VV_VERSIONLONG].vv_nr = VIM_VERSION_100 * 10000 + highest_patch(); | |
232 | |
233 set_vim_var_nr(VV_SEARCHFORWARD, 1L); | |
234 set_vim_var_nr(VV_HLSEARCH, 1L); | |
235 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); | |
236 set_vim_var_list(VV_ERRORS, list_alloc()); | |
237 set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED)); | |
238 | |
239 set_vim_var_nr(VV_FALSE, VVAL_FALSE); | |
240 set_vim_var_nr(VV_TRUE, VVAL_TRUE); | |
241 set_vim_var_nr(VV_NONE, VVAL_NONE); | |
242 set_vim_var_nr(VV_NULL, VVAL_NULL); | |
243 | |
244 set_vim_var_nr(VV_TYPE_NUMBER, VAR_TYPE_NUMBER); | |
245 set_vim_var_nr(VV_TYPE_STRING, VAR_TYPE_STRING); | |
246 set_vim_var_nr(VV_TYPE_FUNC, VAR_TYPE_FUNC); | |
247 set_vim_var_nr(VV_TYPE_LIST, VAR_TYPE_LIST); | |
248 set_vim_var_nr(VV_TYPE_DICT, VAR_TYPE_DICT); | |
249 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT); | |
250 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL); | |
251 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE); | |
252 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB); | |
253 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL); | |
254 set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB); | |
255 | |
256 set_vim_var_nr(VV_ECHOSPACE, sc_col - 1); | |
257 | |
258 set_reg_var(0); // default for v:register is not 0 but '"' | |
259 } | |
260 | |
261 #if defined(EXITFREE) || defined(PROTO) | |
262 /* | |
263 * Free all vim variables information on exit | |
264 */ | |
265 void | |
266 evalvars_clear(void) | |
267 { | |
268 int i; | |
269 struct vimvar *p; | |
270 | |
271 for (i = 0; i < VV_LEN; ++i) | |
272 { | |
273 p = &vimvars[i]; | |
274 if (p->vv_di.di_tv.v_type == VAR_STRING) | |
275 VIM_CLEAR(p->vv_str); | |
276 else if (p->vv_di.di_tv.v_type == VAR_LIST) | |
277 { | |
278 list_unref(p->vv_list); | |
279 p->vv_list = NULL; | |
280 } | |
281 } | |
282 hash_clear(&vimvarht); | |
283 hash_init(&vimvarht); // garbage_collect() will access it | |
284 hash_clear(&compat_hashtab); | |
285 | |
286 // global variables | |
287 vars_clear(&globvarht); | |
288 | |
289 // Script-local variables. First clear all the variables and in a second | |
290 // loop free the scriptvar_T, because a variable in one script might hold | |
291 // a reference to the whole scope of another script. | |
292 for (i = 1; i <= ga_scripts.ga_len; ++i) | |
293 vars_clear(&SCRIPT_VARS(i)); | |
294 for (i = 1; i <= ga_scripts.ga_len; ++i) | |
295 vim_free(SCRIPT_SV(i)); | |
296 ga_clear(&ga_scripts); | |
297 } | |
298 #endif | |
299 | |
300 int | |
301 garbage_collect_vimvars(int copyID) | |
302 { | |
303 return set_ref_in_ht(&vimvarht, copyID, NULL); | |
304 } | |
305 | |
306 int | |
307 garbage_collect_scriptvars(int copyID) | |
308 { | |
309 int i; | |
310 int abort = FALSE; | |
311 | |
312 for (i = 1; i <= ga_scripts.ga_len; ++i) | |
313 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL); | |
314 | |
315 return abort; | |
316 } | |
317 | |
318 /* | |
319 * Set an internal variable to a string value. Creates the variable if it does | |
320 * not already exist. | |
321 */ | |
322 void | |
323 set_internal_string_var(char_u *name, char_u *value) | |
324 { | |
325 char_u *val; | |
326 typval_T *tvp; | |
327 | |
328 val = vim_strsave(value); | |
329 if (val != NULL) | |
330 { | |
331 tvp = alloc_string_tv(val); | |
332 if (tvp != NULL) | |
333 { | |
334 set_var(name, tvp, FALSE); | |
335 free_tv(tvp); | |
336 } | |
337 } | |
338 } | |
339 | |
340 /* | |
341 * Prepare v: variable "idx" to be used. | |
342 * Save the current typeval in "save_tv". | |
343 * When not used yet add the variable to the v: hashtable. | |
344 */ | |
345 void | |
346 prepare_vimvar(int idx, typval_T *save_tv) | |
347 { | |
348 *save_tv = vimvars[idx].vv_tv; | |
349 if (vimvars[idx].vv_type == VAR_UNKNOWN) | |
350 hash_add(&vimvarht, vimvars[idx].vv_di.di_key); | |
351 } | |
352 | |
353 /* | |
354 * Restore v: variable "idx" to typeval "save_tv". | |
355 * When no longer defined, remove the variable from the v: hashtable. | |
356 */ | |
357 void | |
358 restore_vimvar(int idx, typval_T *save_tv) | |
359 { | |
360 hashitem_T *hi; | |
361 | |
362 vimvars[idx].vv_tv = *save_tv; | |
363 if (vimvars[idx].vv_type == VAR_UNKNOWN) | |
364 { | |
365 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key); | |
366 if (HASHITEM_EMPTY(hi)) | |
367 internal_error("restore_vimvar()"); | |
368 else | |
369 hash_remove(&vimvarht, hi); | |
370 } | |
371 } | |
372 | |
373 /* | |
374 * List Vim variables. | |
375 */ | |
376 static void | |
377 list_vim_vars(int *first) | |
378 { | |
379 list_hashtable_vars(&vimvarht, "v:", FALSE, first); | |
380 } | |
381 | |
382 /* | |
383 * List script-local variables, if there is a script. | |
384 */ | |
385 static void | |
386 list_script_vars(int *first) | |
387 { | |
388 if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) | |
389 list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid), | |
390 "s:", FALSE, first); | |
391 } | |
34 | 392 |
35 /* | 393 /* |
36 * Get a list of lines from a HERE document. The here document is a list of | 394 * Get a list of lines from a HERE document. The here document is a list of |
37 * lines surrounded by a marker. | 395 * lines surrounded by a marker. |
38 * cmd << {marker} | 396 * cmd << {marker} |
1022 d = get_current_funccal_dict(ht); | 1380 d = get_current_funccal_dict(ht); |
1023 if (d == NULL) | 1381 if (d == NULL) |
1024 { | 1382 { |
1025 if (ht == &globvarht) | 1383 if (ht == &globvarht) |
1026 d = &globvardict; | 1384 d = &globvardict; |
1027 else if (is_compatht(ht)) | 1385 else if (ht == &compat_hashtab) |
1028 d = &vimvardict; | 1386 d = &vimvardict; |
1029 else | 1387 else |
1030 { | 1388 { |
1031 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE); | 1389 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE); |
1032 d = di == NULL ? NULL : di->di_tv.vval.v_dict; | 1390 d = di == NULL ? NULL : di->di_tv.vval.v_dict; |
1212 } | 1570 } |
1213 --recurse; | 1571 --recurse; |
1214 } | 1572 } |
1215 | 1573 |
1216 /* | 1574 /* |
1575 * Local string buffer for the next two functions to store a variable name | |
1576 * with its prefix. Allocated in cat_prefix_varname(), freed later in | |
1577 * get_user_var_name(). | |
1578 */ | |
1579 | |
1580 static char_u *varnamebuf = NULL; | |
1581 static int varnamebuflen = 0; | |
1582 | |
1583 /* | |
1584 * Function to concatenate a prefix and a variable name. | |
1585 */ | |
1586 static char_u * | |
1587 cat_prefix_varname(int prefix, char_u *name) | |
1588 { | |
1589 int len; | |
1590 | |
1591 len = (int)STRLEN(name) + 3; | |
1592 if (len > varnamebuflen) | |
1593 { | |
1594 vim_free(varnamebuf); | |
1595 len += 10; /* some additional space */ | |
1596 varnamebuf = alloc(len); | |
1597 if (varnamebuf == NULL) | |
1598 { | |
1599 varnamebuflen = 0; | |
1600 return NULL; | |
1601 } | |
1602 varnamebuflen = len; | |
1603 } | |
1604 *varnamebuf = prefix; | |
1605 varnamebuf[1] = ':'; | |
1606 STRCPY(varnamebuf + 2, name); | |
1607 return varnamebuf; | |
1608 } | |
1609 | |
1610 /* | |
1611 * Function given to ExpandGeneric() to obtain the list of user defined | |
1612 * (global/buffer/window/built-in) variable names. | |
1613 */ | |
1614 char_u * | |
1615 get_user_var_name(expand_T *xp, int idx) | |
1616 { | |
1617 static long_u gdone; | |
1618 static long_u bdone; | |
1619 static long_u wdone; | |
1620 static long_u tdone; | |
1621 static int vidx; | |
1622 static hashitem_T *hi; | |
1623 hashtab_T *ht; | |
1624 | |
1625 if (idx == 0) | |
1626 { | |
1627 gdone = bdone = wdone = vidx = 0; | |
1628 tdone = 0; | |
1629 } | |
1630 | |
1631 // Global variables | |
1632 if (gdone < globvarht.ht_used) | |
1633 { | |
1634 if (gdone++ == 0) | |
1635 hi = globvarht.ht_array; | |
1636 else | |
1637 ++hi; | |
1638 while (HASHITEM_EMPTY(hi)) | |
1639 ++hi; | |
1640 if (STRNCMP("g:", xp->xp_pattern, 2) == 0) | |
1641 return cat_prefix_varname('g', hi->hi_key); | |
1642 return hi->hi_key; | |
1643 } | |
1644 | |
1645 // b: variables | |
1646 ht = &curbuf->b_vars->dv_hashtab; | |
1647 if (bdone < ht->ht_used) | |
1648 { | |
1649 if (bdone++ == 0) | |
1650 hi = ht->ht_array; | |
1651 else | |
1652 ++hi; | |
1653 while (HASHITEM_EMPTY(hi)) | |
1654 ++hi; | |
1655 return cat_prefix_varname('b', hi->hi_key); | |
1656 } | |
1657 | |
1658 // w: variables | |
1659 ht = &curwin->w_vars->dv_hashtab; | |
1660 if (wdone < ht->ht_used) | |
1661 { | |
1662 if (wdone++ == 0) | |
1663 hi = ht->ht_array; | |
1664 else | |
1665 ++hi; | |
1666 while (HASHITEM_EMPTY(hi)) | |
1667 ++hi; | |
1668 return cat_prefix_varname('w', hi->hi_key); | |
1669 } | |
1670 | |
1671 // t: variables | |
1672 ht = &curtab->tp_vars->dv_hashtab; | |
1673 if (tdone < ht->ht_used) | |
1674 { | |
1675 if (tdone++ == 0) | |
1676 hi = ht->ht_array; | |
1677 else | |
1678 ++hi; | |
1679 while (HASHITEM_EMPTY(hi)) | |
1680 ++hi; | |
1681 return cat_prefix_varname('t', hi->hi_key); | |
1682 } | |
1683 | |
1684 // v: variables | |
1685 if (vidx < VV_LEN) | |
1686 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name); | |
1687 | |
1688 VIM_CLEAR(varnamebuf); | |
1689 varnamebuflen = 0; | |
1690 return NULL; | |
1691 } | |
1692 | |
1693 /* | |
1694 * Set number v: variable to "val". | |
1695 */ | |
1696 void | |
1697 set_vim_var_nr(int idx, varnumber_T val) | |
1698 { | |
1699 vimvars[idx].vv_type = VAR_NUMBER; | |
1700 vimvars[idx].vv_nr = val; | |
1701 } | |
1702 | |
1703 /* | |
1704 * Get typval_T v: variable value. | |
1705 */ | |
1706 typval_T * | |
1707 get_vim_var_tv(int idx) | |
1708 { | |
1709 return &vimvars[idx].vv_tv; | |
1710 } | |
1711 | |
1712 /* | |
1713 * Get number v: variable value. | |
1714 */ | |
1715 varnumber_T | |
1716 get_vim_var_nr(int idx) | |
1717 { | |
1718 return vimvars[idx].vv_nr; | |
1719 } | |
1720 | |
1721 /* | |
1722 * Get string v: variable value. Uses a static buffer, can only be used once. | |
1723 * If the String variable has never been set, return an empty string. | |
1724 * Never returns NULL; | |
1725 */ | |
1726 char_u * | |
1727 get_vim_var_str(int idx) | |
1728 { | |
1729 return tv_get_string(&vimvars[idx].vv_tv); | |
1730 } | |
1731 | |
1732 /* | |
1733 * Get List v: variable value. Caller must take care of reference count when | |
1734 * needed. | |
1735 */ | |
1736 list_T * | |
1737 get_vim_var_list(int idx) | |
1738 { | |
1739 return vimvars[idx].vv_list; | |
1740 } | |
1741 | |
1742 /* | |
1743 * Get Dict v: variable value. Caller must take care of reference count when | |
1744 * needed. | |
1745 */ | |
1746 dict_T * | |
1747 get_vim_var_dict(int idx) | |
1748 { | |
1749 return vimvars[idx].vv_dict; | |
1750 } | |
1751 | |
1752 /* | |
1753 * Set v:char to character "c". | |
1754 */ | |
1755 void | |
1756 set_vim_var_char(int c) | |
1757 { | |
1758 char_u buf[MB_MAXBYTES + 1]; | |
1759 | |
1760 if (has_mbyte) | |
1761 buf[(*mb_char2bytes)(c, buf)] = NUL; | |
1762 else | |
1763 { | |
1764 buf[0] = c; | |
1765 buf[1] = NUL; | |
1766 } | |
1767 set_vim_var_string(VV_CHAR, buf, -1); | |
1768 } | |
1769 | |
1770 /* | |
1771 * Set v:count to "count" and v:count1 to "count1". | |
1772 * When "set_prevcount" is TRUE first set v:prevcount from v:count. | |
1773 */ | |
1774 void | |
1775 set_vcount( | |
1776 long count, | |
1777 long count1, | |
1778 int set_prevcount) | |
1779 { | |
1780 if (set_prevcount) | |
1781 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr; | |
1782 vimvars[VV_COUNT].vv_nr = count; | |
1783 vimvars[VV_COUNT1].vv_nr = count1; | |
1784 } | |
1785 | |
1786 /* | |
1787 * Save variables that might be changed as a side effect. Used when executing | |
1788 * a timer callback. | |
1789 */ | |
1790 void | |
1791 save_vimvars(vimvars_save_T *vvsave) | |
1792 { | |
1793 vvsave->vv_prevcount = vimvars[VV_PREVCOUNT].vv_nr; | |
1794 vvsave->vv_count = vimvars[VV_COUNT].vv_nr; | |
1795 vvsave->vv_count1 = vimvars[VV_COUNT1].vv_nr; | |
1796 } | |
1797 | |
1798 /* | |
1799 * Restore variables saved by save_vimvars(). | |
1800 */ | |
1801 void | |
1802 restore_vimvars(vimvars_save_T *vvsave) | |
1803 { | |
1804 vimvars[VV_PREVCOUNT].vv_nr = vvsave->vv_prevcount; | |
1805 vimvars[VV_COUNT].vv_nr = vvsave->vv_count; | |
1806 vimvars[VV_COUNT1].vv_nr = vvsave->vv_count1; | |
1807 } | |
1808 | |
1809 /* | |
1810 * Set string v: variable to a copy of "val". If 'copy' is FALSE, then set the | |
1811 * value. | |
1812 */ | |
1813 void | |
1814 set_vim_var_string( | |
1815 int idx, | |
1816 char_u *val, | |
1817 int len) // length of "val" to use or -1 (whole string) | |
1818 { | |
1819 clear_tv(&vimvars[idx].vv_di.di_tv); | |
1820 vimvars[idx].vv_type = VAR_STRING; | |
1821 if (val == NULL) | |
1822 vimvars[idx].vv_str = NULL; | |
1823 else if (len == -1) | |
1824 vimvars[idx].vv_str = vim_strsave(val); | |
1825 else | |
1826 vimvars[idx].vv_str = vim_strnsave(val, len); | |
1827 } | |
1828 | |
1829 /* | |
1830 * Set List v: variable to "val". | |
1831 */ | |
1832 void | |
1833 set_vim_var_list(int idx, list_T *val) | |
1834 { | |
1835 clear_tv(&vimvars[idx].vv_di.di_tv); | |
1836 vimvars[idx].vv_type = VAR_LIST; | |
1837 vimvars[idx].vv_list = val; | |
1838 if (val != NULL) | |
1839 ++val->lv_refcount; | |
1840 } | |
1841 | |
1842 /* | |
1843 * Set Dictionary v: variable to "val". | |
1844 */ | |
1845 void | |
1846 set_vim_var_dict(int idx, dict_T *val) | |
1847 { | |
1848 clear_tv(&vimvars[idx].vv_di.di_tv); | |
1849 vimvars[idx].vv_type = VAR_DICT; | |
1850 vimvars[idx].vv_dict = val; | |
1851 if (val != NULL) | |
1852 { | |
1853 ++val->dv_refcount; | |
1854 dict_set_items_ro(val); | |
1855 } | |
1856 } | |
1857 | |
1858 /* | |
1859 * Set v:register if needed. | |
1860 */ | |
1861 void | |
1862 set_reg_var(int c) | |
1863 { | |
1864 char_u regname; | |
1865 | |
1866 if (c == 0 || c == ' ') | |
1867 regname = '"'; | |
1868 else | |
1869 regname = c; | |
1870 // Avoid free/alloc when the value is already right. | |
1871 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c) | |
1872 set_vim_var_string(VV_REG, ®name, 1); | |
1873 } | |
1874 | |
1875 /* | |
1876 * Get or set v:exception. If "oldval" == NULL, return the current value. | |
1877 * Otherwise, restore the value to "oldval" and return NULL. | |
1878 * Must always be called in pairs to save and restore v:exception! Does not | |
1879 * take care of memory allocations. | |
1880 */ | |
1881 char_u * | |
1882 v_exception(char_u *oldval) | |
1883 { | |
1884 if (oldval == NULL) | |
1885 return vimvars[VV_EXCEPTION].vv_str; | |
1886 | |
1887 vimvars[VV_EXCEPTION].vv_str = oldval; | |
1888 return NULL; | |
1889 } | |
1890 | |
1891 /* | |
1892 * Get or set v:throwpoint. If "oldval" == NULL, return the current value. | |
1893 * Otherwise, restore the value to "oldval" and return NULL. | |
1894 * Must always be called in pairs to save and restore v:throwpoint! Does not | |
1895 * take care of memory allocations. | |
1896 */ | |
1897 char_u * | |
1898 v_throwpoint(char_u *oldval) | |
1899 { | |
1900 if (oldval == NULL) | |
1901 return vimvars[VV_THROWPOINT].vv_str; | |
1902 | |
1903 vimvars[VV_THROWPOINT].vv_str = oldval; | |
1904 return NULL; | |
1905 } | |
1906 | |
1907 /* | |
1908 * Set v:cmdarg. | |
1909 * If "eap" != NULL, use "eap" to generate the value and return the old value. | |
1910 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL. | |
1911 * Must always be called in pairs! | |
1912 */ | |
1913 char_u * | |
1914 set_cmdarg(exarg_T *eap, char_u *oldarg) | |
1915 { | |
1916 char_u *oldval; | |
1917 char_u *newval; | |
1918 unsigned len; | |
1919 | |
1920 oldval = vimvars[VV_CMDARG].vv_str; | |
1921 if (eap == NULL) | |
1922 { | |
1923 vim_free(oldval); | |
1924 vimvars[VV_CMDARG].vv_str = oldarg; | |
1925 return NULL; | |
1926 } | |
1927 | |
1928 if (eap->force_bin == FORCE_BIN) | |
1929 len = 6; | |
1930 else if (eap->force_bin == FORCE_NOBIN) | |
1931 len = 8; | |
1932 else | |
1933 len = 0; | |
1934 | |
1935 if (eap->read_edit) | |
1936 len += 7; | |
1937 | |
1938 if (eap->force_ff != 0) | |
1939 len += 10; // " ++ff=unix" | |
1940 if (eap->force_enc != 0) | |
1941 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7; | |
1942 if (eap->bad_char != 0) | |
1943 len += 7 + 4; // " ++bad=" + "keep" or "drop" | |
1944 | |
1945 newval = alloc(len + 1); | |
1946 if (newval == NULL) | |
1947 return NULL; | |
1948 | |
1949 if (eap->force_bin == FORCE_BIN) | |
1950 sprintf((char *)newval, " ++bin"); | |
1951 else if (eap->force_bin == FORCE_NOBIN) | |
1952 sprintf((char *)newval, " ++nobin"); | |
1953 else | |
1954 *newval = NUL; | |
1955 | |
1956 if (eap->read_edit) | |
1957 STRCAT(newval, " ++edit"); | |
1958 | |
1959 if (eap->force_ff != 0) | |
1960 sprintf((char *)newval + STRLEN(newval), " ++ff=%s", | |
1961 eap->force_ff == 'u' ? "unix" | |
1962 : eap->force_ff == 'd' ? "dos" | |
1963 : "mac"); | |
1964 if (eap->force_enc != 0) | |
1965 sprintf((char *)newval + STRLEN(newval), " ++enc=%s", | |
1966 eap->cmd + eap->force_enc); | |
1967 if (eap->bad_char == BAD_KEEP) | |
1968 STRCPY(newval + STRLEN(newval), " ++bad=keep"); | |
1969 else if (eap->bad_char == BAD_DROP) | |
1970 STRCPY(newval + STRLEN(newval), " ++bad=drop"); | |
1971 else if (eap->bad_char != 0) | |
1972 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char); | |
1973 vimvars[VV_CMDARG].vv_str = newval; | |
1974 return oldval; | |
1975 } | |
1976 | |
1977 /* | |
1217 * Get the value of internal variable "name". | 1978 * Get the value of internal variable "name". |
1218 * Return OK or FAIL. If OK is returned "rettv" must be cleared. | 1979 * Return OK or FAIL. If OK is returned "rettv" must be cleared. |
1219 */ | 1980 */ |
1220 int | 1981 int |
1221 get_var_tv( | 1982 get_var_tv( |
1257 | 2018 |
1258 return ret; | 2019 return ret; |
1259 } | 2020 } |
1260 | 2021 |
1261 /* | 2022 /* |
2023 * Check if variable "name[len]" is a local variable or an argument. | |
2024 * If so, "*eval_lavars_used" is set to TRUE. | |
2025 */ | |
2026 void | |
2027 check_vars(char_u *name, int len) | |
2028 { | |
2029 int cc; | |
2030 char_u *varname; | |
2031 hashtab_T *ht; | |
2032 | |
2033 if (eval_lavars_used == NULL) | |
2034 return; | |
2035 | |
2036 // truncate the name, so that we can use strcmp() | |
2037 cc = name[len]; | |
2038 name[len] = NUL; | |
2039 | |
2040 ht = find_var_ht(name, &varname); | |
2041 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) | |
2042 { | |
2043 if (find_var(name, NULL, TRUE) != NULL) | |
2044 *eval_lavars_used = TRUE; | |
2045 } | |
2046 | |
2047 name[len] = cc; | |
2048 } | |
2049 | |
2050 /* | |
2051 * Find variable "name" in the list of variables. | |
2052 * Return a pointer to it if found, NULL if not found. | |
2053 * Careful: "a:0" variables don't have a name. | |
2054 * When "htp" is not NULL we are writing to the variable, set "htp" to the | |
2055 * hashtab_T used. | |
2056 */ | |
2057 dictitem_T * | |
2058 find_var(char_u *name, hashtab_T **htp, int no_autoload) | |
2059 { | |
2060 char_u *varname; | |
2061 hashtab_T *ht; | |
2062 dictitem_T *ret = NULL; | |
2063 | |
2064 ht = find_var_ht(name, &varname); | |
2065 if (htp != NULL) | |
2066 *htp = ht; | |
2067 if (ht == NULL) | |
2068 return NULL; | |
2069 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); | |
2070 if (ret != NULL) | |
2071 return ret; | |
2072 | |
2073 /* Search in parent scope for lambda */ | |
2074 return find_var_in_scoped_ht(name, no_autoload || htp != NULL); | |
2075 } | |
2076 | |
2077 /* | |
2078 * Find variable "varname" in hashtab "ht" with name "htname". | |
2079 * Returns NULL if not found. | |
2080 */ | |
2081 dictitem_T * | |
2082 find_var_in_ht( | |
2083 hashtab_T *ht, | |
2084 int htname, | |
2085 char_u *varname, | |
2086 int no_autoload) | |
2087 { | |
2088 hashitem_T *hi; | |
2089 | |
2090 if (*varname == NUL) | |
2091 { | |
2092 // Must be something like "s:", otherwise "ht" would be NULL. | |
2093 switch (htname) | |
2094 { | |
2095 case 's': return &SCRIPT_SV(current_sctx.sc_sid)->sv_var; | |
2096 case 'g': return &globvars_var; | |
2097 case 'v': return &vimvars_var; | |
2098 case 'b': return &curbuf->b_bufvar; | |
2099 case 'w': return &curwin->w_winvar; | |
2100 case 't': return &curtab->tp_winvar; | |
2101 case 'l': return get_funccal_local_var(); | |
2102 case 'a': return get_funccal_args_var(); | |
2103 } | |
2104 return NULL; | |
2105 } | |
2106 | |
2107 hi = hash_find(ht, varname); | |
2108 if (HASHITEM_EMPTY(hi)) | |
2109 { | |
2110 // For global variables we may try auto-loading the script. If it | |
2111 // worked find the variable again. Don't auto-load a script if it was | |
2112 // loaded already, otherwise it would be loaded every time when | |
2113 // checking if a function name is a Funcref variable. | |
2114 if (ht == &globvarht && !no_autoload) | |
2115 { | |
2116 // Note: script_autoload() may make "hi" invalid. It must either | |
2117 // be obtained again or not used. | |
2118 if (!script_autoload(varname, FALSE) || aborting()) | |
2119 return NULL; | |
2120 hi = hash_find(ht, varname); | |
2121 } | |
2122 if (HASHITEM_EMPTY(hi)) | |
2123 return NULL; | |
2124 } | |
2125 return HI2DI(hi); | |
2126 } | |
2127 | |
2128 /* | |
2129 * Find the hashtab used for a variable name. | |
2130 * Return NULL if the name is not valid. | |
2131 * Set "varname" to the start of name without ':'. | |
2132 */ | |
2133 hashtab_T * | |
2134 find_var_ht(char_u *name, char_u **varname) | |
2135 { | |
2136 hashitem_T *hi; | |
2137 hashtab_T *ht; | |
2138 | |
2139 if (name[0] == NUL) | |
2140 return NULL; | |
2141 if (name[1] != ':') | |
2142 { | |
2143 // The name must not start with a colon or #. | |
2144 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) | |
2145 return NULL; | |
2146 *varname = name; | |
2147 | |
2148 // "version" is "v:version" in all scopes if scriptversion < 3. | |
2149 // Same for a few other variables marked with VV_COMPAT. | |
2150 if (current_sctx.sc_version < 3) | |
2151 { | |
2152 hi = hash_find(&compat_hashtab, name); | |
2153 if (!HASHITEM_EMPTY(hi)) | |
2154 return &compat_hashtab; | |
2155 } | |
2156 | |
2157 ht = get_funccal_local_ht(); | |
2158 if (ht == NULL) | |
2159 return &globvarht; // global variable | |
2160 return ht; // local variable | |
2161 } | |
2162 *varname = name + 2; | |
2163 if (*name == 'g') // global variable | |
2164 return &globvarht; | |
2165 // There must be no ':' or '#' in the rest of the name, unless g: is used | |
2166 if (vim_strchr(name + 2, ':') != NULL | |
2167 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) | |
2168 return NULL; | |
2169 if (*name == 'b') // buffer variable | |
2170 return &curbuf->b_vars->dv_hashtab; | |
2171 if (*name == 'w') // window variable | |
2172 return &curwin->w_vars->dv_hashtab; | |
2173 if (*name == 't') // tab page variable | |
2174 return &curtab->tp_vars->dv_hashtab; | |
2175 if (*name == 'v') // v: variable | |
2176 return &vimvarht; | |
2177 if (*name == 'a') // a: function argument | |
2178 return get_funccal_args_ht(); | |
2179 if (*name == 'l') // l: local function variable | |
2180 return get_funccal_local_ht(); | |
2181 if (*name == 's' // script variable | |
2182 && current_sctx.sc_sid > 0 | |
2183 && current_sctx.sc_sid <= ga_scripts.ga_len) | |
2184 return &SCRIPT_VARS(current_sctx.sc_sid); | |
2185 return NULL; | |
2186 } | |
2187 | |
2188 /* | |
1262 * Get the string value of a (global/local) variable. | 2189 * Get the string value of a (global/local) variable. |
1263 * Note: see tv_get_string() for how long the pointer remains valid. | 2190 * Note: see tv_get_string() for how long the pointer remains valid. |
1264 * Returns NULL when it doesn't exist. | 2191 * Returns NULL when it doesn't exist. |
1265 */ | 2192 */ |
1266 char_u * | 2193 char_u * |
1270 | 2197 |
1271 v = find_var(name, NULL, FALSE); | 2198 v = find_var(name, NULL, FALSE); |
1272 if (v == NULL) | 2199 if (v == NULL) |
1273 return NULL; | 2200 return NULL; |
1274 return tv_get_string(&v->di_tv); | 2201 return tv_get_string(&v->di_tv); |
2202 } | |
2203 | |
2204 /* | |
2205 * Allocate a new hashtab for a sourced script. It will be used while | |
2206 * sourcing this script and when executing functions defined in the script. | |
2207 */ | |
2208 void | |
2209 new_script_vars(scid_T id) | |
2210 { | |
2211 int i; | |
2212 hashtab_T *ht; | |
2213 scriptvar_T *sv; | |
2214 | |
2215 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK) | |
2216 { | |
2217 /* Re-allocating ga_data means that an ht_array pointing to | |
2218 * ht_smallarray becomes invalid. We can recognize this: ht_mask is | |
2219 * at its init value. Also reset "v_dict", it's always the same. */ | |
2220 for (i = 1; i <= ga_scripts.ga_len; ++i) | |
2221 { | |
2222 ht = &SCRIPT_VARS(i); | |
2223 if (ht->ht_mask == HT_INIT_SIZE - 1) | |
2224 ht->ht_array = ht->ht_smallarray; | |
2225 sv = SCRIPT_SV(i); | |
2226 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict; | |
2227 } | |
2228 | |
2229 while (ga_scripts.ga_len < id) | |
2230 { | |
2231 sv = SCRIPT_SV(ga_scripts.ga_len + 1) = | |
2232 ALLOC_CLEAR_ONE(scriptvar_T); | |
2233 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); | |
2234 ++ga_scripts.ga_len; | |
2235 } | |
2236 } | |
2237 } | |
2238 | |
2239 /* | |
2240 * Initialize dictionary "dict" as a scope and set variable "dict_var" to | |
2241 * point to it. | |
2242 */ | |
2243 void | |
2244 init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope) | |
2245 { | |
2246 hash_init(&dict->dv_hashtab); | |
2247 dict->dv_lock = 0; | |
2248 dict->dv_scope = scope; | |
2249 dict->dv_refcount = DO_NOT_FREE_CNT; | |
2250 dict->dv_copyID = 0; | |
2251 dict_var->di_tv.vval.v_dict = dict; | |
2252 dict_var->di_tv.v_type = VAR_DICT; | |
2253 dict_var->di_tv.v_lock = VAR_FIXED; | |
2254 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; | |
2255 dict_var->di_key[0] = NUL; | |
2256 } | |
2257 | |
2258 /* | |
2259 * Unreference a dictionary initialized by init_var_dict(). | |
2260 */ | |
2261 void | |
2262 unref_var_dict(dict_T *dict) | |
2263 { | |
2264 /* Now the dict needs to be freed if no one else is using it, go back to | |
2265 * normal reference counting. */ | |
2266 dict->dv_refcount -= DO_NOT_FREE_CNT - 1; | |
2267 dict_unref(dict); | |
1275 } | 2268 } |
1276 | 2269 |
1277 /* | 2270 /* |
1278 * Clean up a list of internal variables. | 2271 * Clean up a list of internal variables. |
1279 * Frees all allocated variables and the value they contain. | 2272 * Frees all allocated variables and the value they contain. |
1451 || var_check_lock(v->di_tv.v_lock, name, FALSE)) | 2444 || var_check_lock(v->di_tv.v_lock, name, FALSE)) |
1452 return; | 2445 return; |
1453 | 2446 |
1454 // Handle setting internal v: variables separately where needed to | 2447 // Handle setting internal v: variables separately where needed to |
1455 // prevent changing the type. | 2448 // prevent changing the type. |
1456 if (is_vimvarht(ht)) | 2449 if (ht == &vimvarht) |
1457 { | 2450 { |
1458 if (v->di_tv.v_type == VAR_STRING) | 2451 if (v->di_tv.v_type == VAR_STRING) |
1459 { | 2452 { |
1460 VIM_CLEAR(v->di_tv.vval.v_string); | 2453 VIM_CLEAR(v->di_tv.vval.v_string); |
1461 if (copy || tv->v_type != VAR_STRING) | 2454 if (copy || tv->v_type != VAR_STRING) |
1499 clear_tv(&v->di_tv); | 2492 clear_tv(&v->di_tv); |
1500 } | 2493 } |
1501 else // add a new variable | 2494 else // add a new variable |
1502 { | 2495 { |
1503 // Can't add "v:" or "a:" variable. | 2496 // Can't add "v:" or "a:" variable. |
1504 if (is_vimvarht(ht) || ht == get_funccal_args_ht()) | 2497 if (ht == &vimvarht || ht == get_funccal_args_ht()) |
1505 { | 2498 { |
1506 semsg(_(e_illvar), name); | 2499 semsg(_(e_illvar), name); |
1507 return; | 2500 return; |
1508 } | 2501 } |
1509 | 2502 |
1790 if (need_switch_win) | 2783 if (need_switch_win) |
1791 restore_win(save_curwin, save_curtab, TRUE); | 2784 restore_win(save_curwin, save_curtab, TRUE); |
1792 } | 2785 } |
1793 } | 2786 } |
1794 | 2787 |
2788 /* | |
2789 * reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal, | |
2790 * v:option_type, and v:option_command. | |
2791 */ | |
2792 void | |
2793 reset_v_option_vars(void) | |
2794 { | |
2795 set_vim_var_string(VV_OPTION_NEW, NULL, -1); | |
2796 set_vim_var_string(VV_OPTION_OLD, NULL, -1); | |
2797 set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1); | |
2798 set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1); | |
2799 set_vim_var_string(VV_OPTION_TYPE, NULL, -1); | |
2800 set_vim_var_string(VV_OPTION_COMMAND, NULL, -1); | |
2801 } | |
2802 | |
2803 /* | |
2804 * Add an assert error to v:errors. | |
2805 */ | |
2806 void | |
2807 assert_error(garray_T *gap) | |
2808 { | |
2809 struct vimvar *vp = &vimvars[VV_ERRORS]; | |
2810 | |
2811 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) | |
2812 /* Make sure v:errors is a list. */ | |
2813 set_vim_var_list(VV_ERRORS, list_alloc()); | |
2814 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len); | |
2815 } | |
2816 | |
1795 int | 2817 int |
1796 var_exists(char_u *var) | 2818 var_exists(char_u *var) |
1797 { | 2819 { |
1798 char_u *name; | 2820 char_u *name; |
1799 char_u *tofree; | 2821 char_u *tofree; |