Mercurial > vim
comparison src/eval.c @ 17922:4d63d47d87ef v8.1.1957
patch 8.1.1957: more code can be moved to evalvars.c
Commit: https://github.com/vim/vim/commit/da6c03342117fb7f4a8110bd9e8627b612a05a64
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Sep 1 16:01:30 2019 +0200
patch 8.1.1957: more code can be moved to evalvars.c
Problem: More code can be moved to evalvars.c.
Solution: Move code to where it fits better. (Yegappan Lakshmanan,
closes #4883)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 01 Sep 2019 16:15:03 +0200 |
parents | e4d3b6c466d4 |
children | 7f3283683d97 |
comparison
equal
deleted
inserted
replaced
17921:14be395d672c | 17922:4d63d47d87ef |
---|---|
35 * The last bit is used for previous_funccal, ignored when comparing. | 35 * The last bit is used for previous_funccal, ignored when comparing. |
36 */ | 36 */ |
37 static int current_copyID = 0; | 37 static int current_copyID = 0; |
38 | 38 |
39 static int echo_attr = 0; /* attributes used for ":echo" */ | 39 static int echo_attr = 0; /* attributes used for ":echo" */ |
40 | |
41 /* The names of packages that once were loaded are remembered. */ | |
42 static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; | |
43 | 40 |
44 /* | 41 /* |
45 * Info used by a ":for" loop. | 42 * Info used by a ":for" loop. |
46 */ | 43 */ |
47 typedef struct | 44 typedef struct |
154 evalvars_clear(); | 151 evalvars_clear(); |
155 | 152 |
156 free_scriptnames(); | 153 free_scriptnames(); |
157 free_locales(); | 154 free_locales(); |
158 | 155 |
159 /* autoloaded script names */ | 156 // autoloaded script names |
160 ga_clear_strings(&ga_loaded); | 157 free_autoload_scriptnames(); |
161 | 158 |
162 // unreferenced lists and dicts | 159 // unreferenced lists and dicts |
163 (void)garbage_collect(FALSE); | 160 (void)garbage_collect(FALSE); |
164 | 161 |
165 // functions not garbage collected | 162 // functions not garbage collected |
166 free_all_functions(); | 163 free_all_functions(); |
167 } | 164 } |
168 #endif | 165 #endif |
169 | |
170 static lval_T *redir_lval = NULL; | |
171 #define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval) | |
172 static garray_T redir_ga; /* only valid when redir_lval is not NULL */ | |
173 static char_u *redir_endp = NULL; | |
174 static char_u *redir_varname = NULL; | |
175 | |
176 /* | |
177 * Start recording command output to a variable | |
178 * When "append" is TRUE append to an existing variable. | |
179 * Returns OK if successfully completed the setup. FAIL otherwise. | |
180 */ | |
181 int | |
182 var_redir_start(char_u *name, int append) | |
183 { | |
184 int save_emsg; | |
185 int err; | |
186 typval_T tv; | |
187 | |
188 /* Catch a bad name early. */ | |
189 if (!eval_isnamec1(*name)) | |
190 { | |
191 emsg(_(e_invarg)); | |
192 return FAIL; | |
193 } | |
194 | |
195 /* Make a copy of the name, it is used in redir_lval until redir ends. */ | |
196 redir_varname = vim_strsave(name); | |
197 if (redir_varname == NULL) | |
198 return FAIL; | |
199 | |
200 redir_lval = ALLOC_CLEAR_ONE(lval_T); | |
201 if (redir_lval == NULL) | |
202 { | |
203 var_redir_stop(); | |
204 return FAIL; | |
205 } | |
206 | |
207 /* The output is stored in growarray "redir_ga" until redirection ends. */ | |
208 ga_init2(&redir_ga, (int)sizeof(char), 500); | |
209 | |
210 /* Parse the variable name (can be a dict or list entry). */ | |
211 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, | |
212 FNE_CHECK_START); | |
213 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL) | |
214 { | |
215 clear_lval(redir_lval); | |
216 if (redir_endp != NULL && *redir_endp != NUL) | |
217 /* Trailing characters are present after the variable name */ | |
218 emsg(_(e_trailing)); | |
219 else | |
220 emsg(_(e_invarg)); | |
221 redir_endp = NULL; /* don't store a value, only cleanup */ | |
222 var_redir_stop(); | |
223 return FAIL; | |
224 } | |
225 | |
226 /* check if we can write to the variable: set it to or append an empty | |
227 * string */ | |
228 save_emsg = did_emsg; | |
229 did_emsg = FALSE; | |
230 tv.v_type = VAR_STRING; | |
231 tv.vval.v_string = (char_u *)""; | |
232 if (append) | |
233 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"."); | |
234 else | |
235 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"="); | |
236 clear_lval(redir_lval); | |
237 err = did_emsg; | |
238 did_emsg |= save_emsg; | |
239 if (err) | |
240 { | |
241 redir_endp = NULL; /* don't store a value, only cleanup */ | |
242 var_redir_stop(); | |
243 return FAIL; | |
244 } | |
245 | |
246 return OK; | |
247 } | |
248 | |
249 /* | |
250 * Append "value[value_len]" to the variable set by var_redir_start(). | |
251 * The actual appending is postponed until redirection ends, because the value | |
252 * appended may in fact be the string we write to, changing it may cause freed | |
253 * memory to be used: | |
254 * :redir => foo | |
255 * :let foo | |
256 * :redir END | |
257 */ | |
258 void | |
259 var_redir_str(char_u *value, int value_len) | |
260 { | |
261 int len; | |
262 | |
263 if (redir_lval == NULL) | |
264 return; | |
265 | |
266 if (value_len == -1) | |
267 len = (int)STRLEN(value); /* Append the entire string */ | |
268 else | |
269 len = value_len; /* Append only "value_len" characters */ | |
270 | |
271 if (ga_grow(&redir_ga, len) == OK) | |
272 { | |
273 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); | |
274 redir_ga.ga_len += len; | |
275 } | |
276 else | |
277 var_redir_stop(); | |
278 } | |
279 | |
280 /* | |
281 * Stop redirecting command output to a variable. | |
282 * Frees the allocated memory. | |
283 */ | |
284 void | |
285 var_redir_stop(void) | |
286 { | |
287 typval_T tv; | |
288 | |
289 if (EVALCMD_BUSY) | |
290 { | |
291 redir_lval = NULL; | |
292 return; | |
293 } | |
294 | |
295 if (redir_lval != NULL) | |
296 { | |
297 /* If there was no error: assign the text to the variable. */ | |
298 if (redir_endp != NULL) | |
299 { | |
300 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ | |
301 tv.v_type = VAR_STRING; | |
302 tv.vval.v_string = redir_ga.ga_data; | |
303 /* Call get_lval() again, if it's inside a Dict or List it may | |
304 * have changed. */ | |
305 redir_endp = get_lval(redir_varname, NULL, redir_lval, | |
306 FALSE, FALSE, 0, FNE_CHECK_START); | |
307 if (redir_endp != NULL && redir_lval->ll_name != NULL) | |
308 set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE, | |
309 (char_u *)"."); | |
310 clear_lval(redir_lval); | |
311 } | |
312 | |
313 /* free the collected output */ | |
314 VIM_CLEAR(redir_ga.ga_data); | |
315 | |
316 VIM_CLEAR(redir_lval); | |
317 } | |
318 VIM_CLEAR(redir_varname); | |
319 } | |
320 | |
321 int | |
322 eval_charconvert( | |
323 char_u *enc_from, | |
324 char_u *enc_to, | |
325 char_u *fname_from, | |
326 char_u *fname_to) | |
327 { | |
328 int err = FALSE; | |
329 | |
330 set_vim_var_string(VV_CC_FROM, enc_from, -1); | |
331 set_vim_var_string(VV_CC_TO, enc_to, -1); | |
332 set_vim_var_string(VV_FNAME_IN, fname_from, -1); | |
333 set_vim_var_string(VV_FNAME_OUT, fname_to, -1); | |
334 if (eval_to_bool(p_ccv, &err, NULL, FALSE)) | |
335 err = TRUE; | |
336 set_vim_var_string(VV_CC_FROM, NULL, -1); | |
337 set_vim_var_string(VV_CC_TO, NULL, -1); | |
338 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
339 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
340 | |
341 if (err) | |
342 return FAIL; | |
343 return OK; | |
344 } | |
345 | |
346 # if defined(FEAT_POSTSCRIPT) || defined(PROTO) | |
347 int | |
348 eval_printexpr(char_u *fname, char_u *args) | |
349 { | |
350 int err = FALSE; | |
351 | |
352 set_vim_var_string(VV_FNAME_IN, fname, -1); | |
353 set_vim_var_string(VV_CMDARG, args, -1); | |
354 if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) | |
355 err = TRUE; | |
356 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
357 set_vim_var_string(VV_CMDARG, NULL, -1); | |
358 | |
359 if (err) | |
360 { | |
361 mch_remove(fname); | |
362 return FAIL; | |
363 } | |
364 return OK; | |
365 } | |
366 # endif | |
367 | |
368 # if defined(FEAT_DIFF) || defined(PROTO) | |
369 void | |
370 eval_diff( | |
371 char_u *origfile, | |
372 char_u *newfile, | |
373 char_u *outfile) | |
374 { | |
375 int err = FALSE; | |
376 | |
377 set_vim_var_string(VV_FNAME_IN, origfile, -1); | |
378 set_vim_var_string(VV_FNAME_NEW, newfile, -1); | |
379 set_vim_var_string(VV_FNAME_OUT, outfile, -1); | |
380 (void)eval_to_bool(p_dex, &err, NULL, FALSE); | |
381 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
382 set_vim_var_string(VV_FNAME_NEW, NULL, -1); | |
383 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
384 } | |
385 | |
386 void | |
387 eval_patch( | |
388 char_u *origfile, | |
389 char_u *difffile, | |
390 char_u *outfile) | |
391 { | |
392 int err; | |
393 | |
394 set_vim_var_string(VV_FNAME_IN, origfile, -1); | |
395 set_vim_var_string(VV_FNAME_DIFF, difffile, -1); | |
396 set_vim_var_string(VV_FNAME_OUT, outfile, -1); | |
397 (void)eval_to_bool(p_pex, &err, NULL, FALSE); | |
398 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
399 set_vim_var_string(VV_FNAME_DIFF, NULL, -1); | |
400 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
401 } | |
402 # endif | |
403 | 166 |
404 /* | 167 /* |
405 * Top level evaluation function, returning a boolean. | 168 * Top level evaluation function, returning a boolean. |
406 * Sets "error" to TRUE if there was an error. | 169 * Sets "error" to TRUE if there was an error. |
407 * Return TRUE or FALSE. | 170 * Return TRUE or FALSE. |
668 } | 431 } |
669 --emsg_off; | 432 --emsg_off; |
670 | 433 |
671 return retval; | 434 return retval; |
672 } | 435 } |
673 | |
674 #if defined(FEAT_SPELL) || defined(PROTO) | |
675 /* | |
676 * Evaluate an expression to a list with suggestions. | |
677 * For the "expr:" part of 'spellsuggest'. | |
678 * Returns NULL when there is an error. | |
679 */ | |
680 list_T * | |
681 eval_spell_expr(char_u *badword, char_u *expr) | |
682 { | |
683 typval_T save_val; | |
684 typval_T rettv; | |
685 list_T *list = NULL; | |
686 char_u *p = skipwhite(expr); | |
687 | |
688 /* Set "v:val" to the bad word. */ | |
689 prepare_vimvar(VV_VAL, &save_val); | |
690 set_vim_var_string(VV_VAL, badword, -1); | |
691 if (p_verbose == 0) | |
692 ++emsg_off; | |
693 | |
694 if (eval1(&p, &rettv, TRUE) == OK) | |
695 { | |
696 if (rettv.v_type != VAR_LIST) | |
697 clear_tv(&rettv); | |
698 else | |
699 list = rettv.vval.v_list; | |
700 } | |
701 | |
702 if (p_verbose == 0) | |
703 --emsg_off; | |
704 clear_tv(get_vim_var_tv(VV_VAL)); | |
705 restore_vimvar(VV_VAL, &save_val); | |
706 | |
707 return list; | |
708 } | |
709 | |
710 /* | |
711 * "list" is supposed to contain two items: a word and a number. Return the | |
712 * word in "pp" and the number as the return value. | |
713 * Return -1 if anything isn't right. | |
714 * Used to get the good word and score from the eval_spell_expr() result. | |
715 */ | |
716 int | |
717 get_spellword(list_T *list, char_u **pp) | |
718 { | |
719 listitem_T *li; | |
720 | |
721 li = list->lv_first; | |
722 if (li == NULL) | |
723 return -1; | |
724 *pp = tv_get_string(&li->li_tv); | |
725 | |
726 li = li->li_next; | |
727 if (li == NULL) | |
728 return -1; | |
729 return (int)tv_get_number(&li->li_tv); | |
730 } | |
731 #endif | |
732 | 436 |
733 /* | 437 /* |
734 * Top level evaluation function. | 438 * Top level evaluation function. |
735 * Returns an allocated typval_T with the result. | 439 * Returns an allocated typval_T with the result. |
736 * Returns NULL when there is an error. | 440 * Returns NULL when there is an error. |
1151 } | 855 } |
1152 | 856 |
1153 if (lp->ll_di == NULL) | 857 if (lp->ll_di == NULL) |
1154 { | 858 { |
1155 // Can't add "v:" or "a:" variable. | 859 // Can't add "v:" or "a:" variable. |
1156 if (lp->ll_dict == &vimvardict | 860 if (lp->ll_dict == get_vimvar_dict() |
1157 || &lp->ll_dict->dv_hashtab == get_funccal_args_ht()) | 861 || &lp->ll_dict->dv_hashtab == get_funccal_args_ht()) |
1158 { | 862 { |
1159 semsg(_(e_illvar), name); | 863 semsg(_(e_illvar), name); |
1160 clear_tv(&var1); | 864 clear_tv(&var1); |
1161 return NULL; | 865 return NULL; |
1918 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) | 1622 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) |
1919 /* skip */ ; | 1623 /* skip */ ; |
1920 } | 1624 } |
1921 xp->xp_pattern = arg; | 1625 xp->xp_pattern = arg; |
1922 } | 1626 } |
1923 | |
1924 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO) | |
1925 /* | |
1926 * Delete all "menutrans_" variables. | |
1927 */ | |
1928 void | |
1929 del_menutrans_vars(void) | |
1930 { | |
1931 hashitem_T *hi; | |
1932 int todo; | |
1933 | |
1934 hash_lock(&globvarht); | |
1935 todo = (int)globvarht.ht_used; | |
1936 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) | |
1937 { | |
1938 if (!HASHITEM_EMPTY(hi)) | |
1939 { | |
1940 --todo; | |
1941 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) | |
1942 delete_var(&globvarht, hi); | |
1943 } | |
1944 } | |
1945 hash_unlock(&globvarht); | |
1946 } | |
1947 #endif | |
1948 | 1627 |
1949 /* | 1628 /* |
1950 * Return TRUE if "pat" matches "text". | 1629 * Return TRUE if "pat" matches "text". |
1951 * Does not use 'cpo' and always uses 'magic'. | 1630 * Does not use 'cpo' and always uses 'magic'. |
1952 */ | 1631 */ |
4213 /* tabpage-local variables */ | 3892 /* tabpage-local variables */ |
4214 FOR_ALL_TABPAGES(tp) | 3893 FOR_ALL_TABPAGES(tp) |
4215 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID, | 3894 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID, |
4216 NULL, NULL); | 3895 NULL, NULL); |
4217 /* global variables */ | 3896 /* global variables */ |
4218 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL); | 3897 abort = abort || garbage_collect_globvars(copyID); |
4219 | 3898 |
4220 /* function-local variables */ | 3899 /* function-local variables */ |
4221 abort = abort || set_ref_in_call_stack(copyID); | 3900 abort = abort || set_ref_in_call_stack(copyID); |
4222 | 3901 |
4223 /* named functions (matters for closures) */ | 3902 /* named functions (matters for closures) */ |
4626 } | 4305 } |
4627 } | 4306 } |
4628 } | 4307 } |
4629 #endif | 4308 #endif |
4630 return abort; | 4309 return abort; |
4631 } | |
4632 | |
4633 static char * | |
4634 get_var_special_name(int nr) | |
4635 { | |
4636 switch (nr) | |
4637 { | |
4638 case VVAL_FALSE: return "v:false"; | |
4639 case VVAL_TRUE: return "v:true"; | |
4640 case VVAL_NONE: return "v:none"; | |
4641 case VVAL_NULL: return "v:null"; | |
4642 } | |
4643 internal_error("get_var_special_name()"); | |
4644 return "42"; | |
4645 } | 4310 } |
4646 | 4311 |
4647 /* | 4312 /* |
4648 * Return a string with the string representation of a variable. | 4313 * Return a string with the string representation of a variable. |
4649 * If the memory is allocated "tofree" is set to it, otherwise NULL. | 4314 * If the memory is allocated "tofree" is set to it, otherwise NULL. |
6202 --recurse; | 5867 --recurse; |
6203 return ret; | 5868 return ret; |
6204 } | 5869 } |
6205 | 5870 |
6206 /* | 5871 /* |
6207 * This function is used by f_input() and f_inputdialog() functions. The third | |
6208 * argument to f_input() specifies the type of completion to use at the | |
6209 * prompt. The third argument to f_inputdialog() specifies the value to return | |
6210 * when the user cancels the prompt. | |
6211 */ | |
6212 void | |
6213 get_user_input( | |
6214 typval_T *argvars, | |
6215 typval_T *rettv, | |
6216 int inputdialog, | |
6217 int secret) | |
6218 { | |
6219 char_u *prompt = tv_get_string_chk(&argvars[0]); | |
6220 char_u *p = NULL; | |
6221 int c; | |
6222 char_u buf[NUMBUFLEN]; | |
6223 int cmd_silent_save = cmd_silent; | |
6224 char_u *defstr = (char_u *)""; | |
6225 int xp_type = EXPAND_NOTHING; | |
6226 char_u *xp_arg = NULL; | |
6227 | |
6228 rettv->v_type = VAR_STRING; | |
6229 rettv->vval.v_string = NULL; | |
6230 | |
6231 #ifdef NO_CONSOLE_INPUT | |
6232 /* While starting up, there is no place to enter text. When running tests | |
6233 * with --not-a-term we assume feedkeys() will be used. */ | |
6234 if (no_console_input() && !is_not_a_term()) | |
6235 return; | |
6236 #endif | |
6237 | |
6238 cmd_silent = FALSE; /* Want to see the prompt. */ | |
6239 if (prompt != NULL) | |
6240 { | |
6241 /* Only the part of the message after the last NL is considered as | |
6242 * prompt for the command line */ | |
6243 p = vim_strrchr(prompt, '\n'); | |
6244 if (p == NULL) | |
6245 p = prompt; | |
6246 else | |
6247 { | |
6248 ++p; | |
6249 c = *p; | |
6250 *p = NUL; | |
6251 msg_start(); | |
6252 msg_clr_eos(); | |
6253 msg_puts_attr((char *)prompt, echo_attr); | |
6254 msg_didout = FALSE; | |
6255 msg_starthere(); | |
6256 *p = c; | |
6257 } | |
6258 cmdline_row = msg_row; | |
6259 | |
6260 if (argvars[1].v_type != VAR_UNKNOWN) | |
6261 { | |
6262 defstr = tv_get_string_buf_chk(&argvars[1], buf); | |
6263 if (defstr != NULL) | |
6264 stuffReadbuffSpec(defstr); | |
6265 | |
6266 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) | |
6267 { | |
6268 char_u *xp_name; | |
6269 int xp_namelen; | |
6270 long argt; | |
6271 | |
6272 /* input() with a third argument: completion */ | |
6273 rettv->vval.v_string = NULL; | |
6274 | |
6275 xp_name = tv_get_string_buf_chk(&argvars[2], buf); | |
6276 if (xp_name == NULL) | |
6277 return; | |
6278 | |
6279 xp_namelen = (int)STRLEN(xp_name); | |
6280 | |
6281 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, | |
6282 &xp_arg) == FAIL) | |
6283 return; | |
6284 } | |
6285 } | |
6286 | |
6287 if (defstr != NULL) | |
6288 { | |
6289 int save_ex_normal_busy = ex_normal_busy; | |
6290 | |
6291 ex_normal_busy = 0; | |
6292 rettv->vval.v_string = | |
6293 getcmdline_prompt(secret ? NUL : '@', p, echo_attr, | |
6294 xp_type, xp_arg); | |
6295 ex_normal_busy = save_ex_normal_busy; | |
6296 } | |
6297 if (inputdialog && rettv->vval.v_string == NULL | |
6298 && argvars[1].v_type != VAR_UNKNOWN | |
6299 && argvars[2].v_type != VAR_UNKNOWN) | |
6300 rettv->vval.v_string = vim_strsave(tv_get_string_buf( | |
6301 &argvars[2], buf)); | |
6302 | |
6303 vim_free(xp_arg); | |
6304 | |
6305 /* since the user typed this, no need to wait for return */ | |
6306 need_wait_return = FALSE; | |
6307 msg_didout = FALSE; | |
6308 } | |
6309 cmd_silent = cmd_silent_save; | |
6310 } | |
6311 | |
6312 /* | |
6313 * ":echo expr1 ..." print each argument separated with a space, add a | 5872 * ":echo expr1 ..." print each argument separated with a space, add a |
6314 * newline at the end. | 5873 * newline at the end. |
6315 * ":echon expr1 ..." print each argument plain. | 5874 * ":echon expr1 ..." print each argument plain. |
6316 */ | 5875 */ |
6317 void | 5876 void |
6423 { | 5982 { |
6424 echo_attr = syn_name2attr(eap->arg); | 5983 echo_attr = syn_name2attr(eap->arg); |
6425 } | 5984 } |
6426 | 5985 |
6427 /* | 5986 /* |
5987 * Returns the :echo attribute | |
5988 */ | |
5989 int | |
5990 get_echo_attr(void) | |
5991 { | |
5992 return echo_attr; | |
5993 } | |
5994 | |
5995 /* | |
6428 * ":execute expr1 ..." execute the result of an expression. | 5996 * ":execute expr1 ..." execute the result of an expression. |
6429 * ":echomsg expr1 ..." Print a message | 5997 * ":echomsg expr1 ..." Print a message |
6430 * ":echoerr expr1 ..." Print an error | 5998 * ":echoerr expr1 ..." Print an error |
6431 * Each gets spaces around each argument and a newline at the end for | 5999 * Each gets spaces around each argument and a newline at the end for |
6432 * echo commands | 6000 * echo commands |
6546 p += 4; /* termcap option */ | 6114 p += 4; /* termcap option */ |
6547 else | 6115 else |
6548 while (ASCII_ISALPHA(*p)) | 6116 while (ASCII_ISALPHA(*p)) |
6549 ++p; | 6117 ++p; |
6550 return p; | 6118 return p; |
6551 } | |
6552 | |
6553 /* | |
6554 * Return the autoload script name for a function or variable name. | |
6555 * Returns NULL when out of memory. | |
6556 * Caller must make sure that "name" contains AUTOLOAD_CHAR. | |
6557 */ | |
6558 char_u * | |
6559 autoload_name(char_u *name) | |
6560 { | |
6561 char_u *p, *q = NULL; | |
6562 char_u *scriptname; | |
6563 | |
6564 // Get the script file name: replace '#' with '/', append ".vim". | |
6565 scriptname = alloc(STRLEN(name) + 14); | |
6566 if (scriptname == NULL) | |
6567 return NULL; | |
6568 STRCPY(scriptname, "autoload/"); | |
6569 STRCAT(scriptname, name); | |
6570 for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL; | |
6571 q = p, ++p) | |
6572 *p = '/'; | |
6573 STRCPY(q, ".vim"); | |
6574 return scriptname; | |
6575 } | |
6576 | |
6577 /* | |
6578 * If "name" has a package name try autoloading the script for it. | |
6579 * Return TRUE if a package was loaded. | |
6580 */ | |
6581 int | |
6582 script_autoload( | |
6583 char_u *name, | |
6584 int reload) /* load script again when already loaded */ | |
6585 { | |
6586 char_u *p; | |
6587 char_u *scriptname, *tofree; | |
6588 int ret = FALSE; | |
6589 int i; | |
6590 | |
6591 /* If there is no '#' after name[0] there is no package name. */ | |
6592 p = vim_strchr(name, AUTOLOAD_CHAR); | |
6593 if (p == NULL || p == name) | |
6594 return FALSE; | |
6595 | |
6596 tofree = scriptname = autoload_name(name); | |
6597 if (scriptname == NULL) | |
6598 return FALSE; | |
6599 | |
6600 /* Find the name in the list of previously loaded package names. Skip | |
6601 * "autoload/", it's always the same. */ | |
6602 for (i = 0; i < ga_loaded.ga_len; ++i) | |
6603 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) | |
6604 break; | |
6605 if (!reload && i < ga_loaded.ga_len) | |
6606 ret = FALSE; /* was loaded already */ | |
6607 else | |
6608 { | |
6609 /* Remember the name if it wasn't loaded already. */ | |
6610 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK) | |
6611 { | |
6612 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname; | |
6613 tofree = NULL; | |
6614 } | |
6615 | |
6616 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ | |
6617 if (source_runtime(scriptname, 0) == OK) | |
6618 ret = TRUE; | |
6619 } | |
6620 | |
6621 vim_free(tofree); | |
6622 return ret; | |
6623 } | 6119 } |
6624 | 6120 |
6625 /* | 6121 /* |
6626 * Display script name where an item was last set. | 6122 * Display script name where an item was last set. |
6627 * Should only be invoked when 'verbose' is non-zero. | 6123 * Should only be invoked when 'verbose' is non-zero. |
7737 did_emsg = FALSE; | 7233 did_emsg = FALSE; |
7738 | 7234 |
7739 prepare_vimvar(VV_KEY, &save_key); | 7235 prepare_vimvar(VV_KEY, &save_key); |
7740 if (argvars[0].v_type == VAR_DICT) | 7236 if (argvars[0].v_type == VAR_DICT) |
7741 { | 7237 { |
7238 set_vim_var_type(VV_KEY, VAR_STRING); | |
7239 | |
7742 ht = &d->dv_hashtab; | 7240 ht = &d->dv_hashtab; |
7743 hash_lock(ht); | 7241 hash_lock(ht); |
7744 todo = (int)ht->ht_used; | 7242 todo = (int)ht->ht_used; |
7745 for (hi = ht->ht_array; todo > 0; ++hi) | 7243 for (hi = ht->ht_array; todo > 0; ++hi) |
7746 { | 7244 { |