Mercurial > vim
comparison src/evalvars.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 | 745c02392844 |
comparison
equal
deleted
inserted
replaced
17921:14be395d672c | 17922:4d63d47d87ef |
---|---|
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 | 19 |
20 static dictitem_T globvars_var; // variable used for g: | 20 static dictitem_T globvars_var; // variable used for g: |
21 static dict_T globvardict; // Dictionary with g: variables | |
22 #define globvarht globvardict.dv_hashtab | |
21 | 23 |
22 /* | 24 /* |
23 * Old Vim variables such as "v:version" are also available without the "v:". | 25 * Old Vim variables such as "v:version" are also available without the "v:". |
24 * Also in functions. We need a special hashtable for them. | 26 * Also in functions. We need a special hashtable for them. |
25 */ | 27 */ |
152 #define vv_dict vv_di.di_tv.vval.v_dict | 154 #define vv_dict vv_di.di_tv.vval.v_dict |
153 #define vv_blob vv_di.di_tv.vval.v_blob | 155 #define vv_blob vv_di.di_tv.vval.v_blob |
154 #define vv_tv vv_di.di_tv | 156 #define vv_tv vv_di.di_tv |
155 | 157 |
156 static dictitem_T vimvars_var; // variable used for v: | 158 static dictitem_T vimvars_var; // variable used for v: |
159 static dict_T vimvardict; // Dictionary with v: variables | |
157 #define vimvarht vimvardict.dv_hashtab | 160 #define vimvarht vimvardict.dv_hashtab |
158 | 161 |
159 // for VIM_VERSION_ defines | 162 // for VIM_VERSION_ defines |
160 #include "version.h" | 163 #include "version.h" |
161 | 164 |
183 static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op); | 186 static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op); |
184 static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep); | 187 static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep); |
185 static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); | 188 static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); |
186 static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock); | 189 static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock); |
187 static void item_lock(typval_T *tv, int deep, int lock); | 190 static void item_lock(typval_T *tv, int deep, int lock); |
191 static void delete_var(hashtab_T *ht, hashitem_T *hi); | |
188 static void list_one_var(dictitem_T *v, char *prefix, int *first); | 192 static void list_one_var(dictitem_T *v, char *prefix, int *first); |
189 static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first); | 193 static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first); |
190 | 194 |
191 /* | 195 /* |
192 * Initialize global and vim special variables | 196 * Initialize global and vim special variables |
294 ga_clear(&ga_scripts); | 298 ga_clear(&ga_scripts); |
295 } | 299 } |
296 #endif | 300 #endif |
297 | 301 |
298 int | 302 int |
303 garbage_collect_globvars(int copyID) | |
304 { | |
305 return set_ref_in_ht(&globvarht, copyID, NULL); | |
306 } | |
307 | |
308 int | |
299 garbage_collect_vimvars(int copyID) | 309 garbage_collect_vimvars(int copyID) |
300 { | 310 { |
301 return set_ref_in_ht(&vimvarht, copyID, NULL); | 311 return set_ref_in_ht(&vimvarht, copyID, NULL); |
302 } | 312 } |
303 | 313 |
332 set_var(name, tvp, FALSE); | 342 set_var(name, tvp, FALSE); |
333 free_tv(tvp); | 343 free_tv(tvp); |
334 } | 344 } |
335 } | 345 } |
336 } | 346 } |
347 | |
348 int | |
349 eval_charconvert( | |
350 char_u *enc_from, | |
351 char_u *enc_to, | |
352 char_u *fname_from, | |
353 char_u *fname_to) | |
354 { | |
355 int err = FALSE; | |
356 | |
357 set_vim_var_string(VV_CC_FROM, enc_from, -1); | |
358 set_vim_var_string(VV_CC_TO, enc_to, -1); | |
359 set_vim_var_string(VV_FNAME_IN, fname_from, -1); | |
360 set_vim_var_string(VV_FNAME_OUT, fname_to, -1); | |
361 if (eval_to_bool(p_ccv, &err, NULL, FALSE)) | |
362 err = TRUE; | |
363 set_vim_var_string(VV_CC_FROM, NULL, -1); | |
364 set_vim_var_string(VV_CC_TO, NULL, -1); | |
365 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
366 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
367 | |
368 if (err) | |
369 return FAIL; | |
370 return OK; | |
371 } | |
372 | |
373 # if defined(FEAT_POSTSCRIPT) || defined(PROTO) | |
374 int | |
375 eval_printexpr(char_u *fname, char_u *args) | |
376 { | |
377 int err = FALSE; | |
378 | |
379 set_vim_var_string(VV_FNAME_IN, fname, -1); | |
380 set_vim_var_string(VV_CMDARG, args, -1); | |
381 if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) | |
382 err = TRUE; | |
383 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
384 set_vim_var_string(VV_CMDARG, NULL, -1); | |
385 | |
386 if (err) | |
387 { | |
388 mch_remove(fname); | |
389 return FAIL; | |
390 } | |
391 return OK; | |
392 } | |
393 # endif | |
394 | |
395 # if defined(FEAT_DIFF) || defined(PROTO) | |
396 void | |
397 eval_diff( | |
398 char_u *origfile, | |
399 char_u *newfile, | |
400 char_u *outfile) | |
401 { | |
402 int err = FALSE; | |
403 | |
404 set_vim_var_string(VV_FNAME_IN, origfile, -1); | |
405 set_vim_var_string(VV_FNAME_NEW, newfile, -1); | |
406 set_vim_var_string(VV_FNAME_OUT, outfile, -1); | |
407 (void)eval_to_bool(p_dex, &err, NULL, FALSE); | |
408 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
409 set_vim_var_string(VV_FNAME_NEW, NULL, -1); | |
410 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
411 } | |
412 | |
413 void | |
414 eval_patch( | |
415 char_u *origfile, | |
416 char_u *difffile, | |
417 char_u *outfile) | |
418 { | |
419 int err; | |
420 | |
421 set_vim_var_string(VV_FNAME_IN, origfile, -1); | |
422 set_vim_var_string(VV_FNAME_DIFF, difffile, -1); | |
423 set_vim_var_string(VV_FNAME_OUT, outfile, -1); | |
424 (void)eval_to_bool(p_pex, &err, NULL, FALSE); | |
425 set_vim_var_string(VV_FNAME_IN, NULL, -1); | |
426 set_vim_var_string(VV_FNAME_DIFF, NULL, -1); | |
427 set_vim_var_string(VV_FNAME_OUT, NULL, -1); | |
428 } | |
429 # endif | |
430 | |
431 #if defined(FEAT_SPELL) || defined(PROTO) | |
432 /* | |
433 * Evaluate an expression to a list with suggestions. | |
434 * For the "expr:" part of 'spellsuggest'. | |
435 * Returns NULL when there is an error. | |
436 */ | |
437 list_T * | |
438 eval_spell_expr(char_u *badword, char_u *expr) | |
439 { | |
440 typval_T save_val; | |
441 typval_T rettv; | |
442 list_T *list = NULL; | |
443 char_u *p = skipwhite(expr); | |
444 | |
445 // Set "v:val" to the bad word. | |
446 prepare_vimvar(VV_VAL, &save_val); | |
447 set_vim_var_string(VV_VAL, badword, -1); | |
448 if (p_verbose == 0) | |
449 ++emsg_off; | |
450 | |
451 if (eval1(&p, &rettv, TRUE) == OK) | |
452 { | |
453 if (rettv.v_type != VAR_LIST) | |
454 clear_tv(&rettv); | |
455 else | |
456 list = rettv.vval.v_list; | |
457 } | |
458 | |
459 if (p_verbose == 0) | |
460 --emsg_off; | |
461 clear_tv(get_vim_var_tv(VV_VAL)); | |
462 restore_vimvar(VV_VAL, &save_val); | |
463 | |
464 return list; | |
465 } | |
466 | |
467 /* | |
468 * "list" is supposed to contain two items: a word and a number. Return the | |
469 * word in "pp" and the number as the return value. | |
470 * Return -1 if anything isn't right. | |
471 * Used to get the good word and score from the eval_spell_expr() result. | |
472 */ | |
473 int | |
474 get_spellword(list_T *list, char_u **pp) | |
475 { | |
476 listitem_T *li; | |
477 | |
478 li = list->lv_first; | |
479 if (li == NULL) | |
480 return -1; | |
481 *pp = tv_get_string(&li->li_tv); | |
482 | |
483 li = li->li_next; | |
484 if (li == NULL) | |
485 return -1; | |
486 return (int)tv_get_number(&li->li_tv); | |
487 } | |
488 #endif | |
337 | 489 |
338 /* | 490 /* |
339 * Prepare v: variable "idx" to be used. | 491 * Prepare v: variable "idx" to be used. |
340 * Save the current typeval in "save_tv". | 492 * Save the current typeval in "save_tv". |
341 * When not used yet add the variable to the v: hashtable. | 493 * When not used yet add the variable to the v: hashtable. |
1567 } | 1719 } |
1568 } | 1720 } |
1569 --recurse; | 1721 --recurse; |
1570 } | 1722 } |
1571 | 1723 |
1724 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO) | |
1725 /* | |
1726 * Delete all "menutrans_" variables. | |
1727 */ | |
1728 void | |
1729 del_menutrans_vars(void) | |
1730 { | |
1731 hashitem_T *hi; | |
1732 int todo; | |
1733 | |
1734 hash_lock(&globvarht); | |
1735 todo = (int)globvarht.ht_used; | |
1736 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) | |
1737 { | |
1738 if (!HASHITEM_EMPTY(hi)) | |
1739 { | |
1740 --todo; | |
1741 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) | |
1742 delete_var(&globvarht, hi); | |
1743 } | |
1744 } | |
1745 hash_unlock(&globvarht); | |
1746 } | |
1747 #endif | |
1748 | |
1572 /* | 1749 /* |
1573 * Local string buffer for the next two functions to store a variable name | 1750 * Local string buffer for the next two functions to store a variable name |
1574 * with its prefix. Allocated in cat_prefix_varname(), freed later in | 1751 * with its prefix. Allocated in cat_prefix_varname(), freed later in |
1575 * get_user_var_name(). | 1752 * get_user_var_name(). |
1576 */ | 1753 */ |
1684 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name); | 1861 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name); |
1685 | 1862 |
1686 VIM_CLEAR(varnamebuf); | 1863 VIM_CLEAR(varnamebuf); |
1687 varnamebuflen = 0; | 1864 varnamebuflen = 0; |
1688 return NULL; | 1865 return NULL; |
1866 } | |
1867 | |
1868 char * | |
1869 get_var_special_name(int nr) | |
1870 { | |
1871 switch (nr) | |
1872 { | |
1873 case VVAL_FALSE: return "v:false"; | |
1874 case VVAL_TRUE: return "v:true"; | |
1875 case VVAL_NONE: return "v:none"; | |
1876 case VVAL_NULL: return "v:null"; | |
1877 } | |
1878 internal_error("get_var_special_name()"); | |
1879 return "42"; | |
1880 } | |
1881 | |
1882 /* | |
1883 * Returns the global variable dictionary | |
1884 */ | |
1885 dict_T * | |
1886 get_globvar_dict(void) | |
1887 { | |
1888 return &globvardict; | |
1889 } | |
1890 | |
1891 /* | |
1892 * Returns the global variable hash table | |
1893 */ | |
1894 hashtab_T * | |
1895 get_globvar_ht(void) | |
1896 { | |
1897 return &globvarht; | |
1898 } | |
1899 | |
1900 /* | |
1901 * Returns the v: variable dictionary | |
1902 */ | |
1903 dict_T * | |
1904 get_vimvar_dict(void) | |
1905 { | |
1906 return &vimvardict; | |
1689 } | 1907 } |
1690 | 1908 |
1691 /* | 1909 /* |
1692 * Set type of v: variable to "type". | 1910 * Set type of v: variable to "type". |
1693 */ | 1911 */ |
2319 | 2537 |
2320 /* | 2538 /* |
2321 * Delete a variable from hashtab "ht" at item "hi". | 2539 * Delete a variable from hashtab "ht" at item "hi". |
2322 * Clear the variable value and free the dictitem. | 2540 * Clear the variable value and free the dictitem. |
2323 */ | 2541 */ |
2324 void | 2542 static void |
2325 delete_var(hashtab_T *ht, hashitem_T *hi) | 2543 delete_var(hashtab_T *ht, hashitem_T *hi) |
2326 { | 2544 { |
2327 dictitem_T *di = HI2DI(hi); | 2545 dictitem_T *di = HI2DI(hi); |
2328 | 2546 |
2329 hash_remove(ht, hi); | 2547 hash_remove(ht, hi); |
2851 | 3069 |
2852 vim_free(tofree); | 3070 vim_free(tofree); |
2853 return n; | 3071 return n; |
2854 } | 3072 } |
2855 | 3073 |
3074 static lval_T *redir_lval = NULL; | |
3075 #define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval) | |
3076 static garray_T redir_ga; // only valid when redir_lval is not NULL | |
3077 static char_u *redir_endp = NULL; | |
3078 static char_u *redir_varname = NULL; | |
3079 | |
3080 /* | |
3081 * Start recording command output to a variable | |
3082 * When "append" is TRUE append to an existing variable. | |
3083 * Returns OK if successfully completed the setup. FAIL otherwise. | |
3084 */ | |
3085 int | |
3086 var_redir_start(char_u *name, int append) | |
3087 { | |
3088 int save_emsg; | |
3089 int err; | |
3090 typval_T tv; | |
3091 | |
3092 // Catch a bad name early. | |
3093 if (!eval_isnamec1(*name)) | |
3094 { | |
3095 emsg(_(e_invarg)); | |
3096 return FAIL; | |
3097 } | |
3098 | |
3099 // Make a copy of the name, it is used in redir_lval until redir ends. | |
3100 redir_varname = vim_strsave(name); | |
3101 if (redir_varname == NULL) | |
3102 return FAIL; | |
3103 | |
3104 redir_lval = ALLOC_CLEAR_ONE(lval_T); | |
3105 if (redir_lval == NULL) | |
3106 { | |
3107 var_redir_stop(); | |
3108 return FAIL; | |
3109 } | |
3110 | |
3111 // The output is stored in growarray "redir_ga" until redirection ends. | |
3112 ga_init2(&redir_ga, (int)sizeof(char), 500); | |
3113 | |
3114 // Parse the variable name (can be a dict or list entry). | |
3115 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, | |
3116 FNE_CHECK_START); | |
3117 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL) | |
3118 { | |
3119 clear_lval(redir_lval); | |
3120 if (redir_endp != NULL && *redir_endp != NUL) | |
3121 // Trailing characters are present after the variable name | |
3122 emsg(_(e_trailing)); | |
3123 else | |
3124 emsg(_(e_invarg)); | |
3125 redir_endp = NULL; // don't store a value, only cleanup | |
3126 var_redir_stop(); | |
3127 return FAIL; | |
3128 } | |
3129 | |
3130 // check if we can write to the variable: set it to or append an empty | |
3131 // string | |
3132 save_emsg = did_emsg; | |
3133 did_emsg = FALSE; | |
3134 tv.v_type = VAR_STRING; | |
3135 tv.vval.v_string = (char_u *)""; | |
3136 if (append) | |
3137 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"."); | |
3138 else | |
3139 set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"="); | |
3140 clear_lval(redir_lval); | |
3141 err = did_emsg; | |
3142 did_emsg |= save_emsg; | |
3143 if (err) | |
3144 { | |
3145 redir_endp = NULL; // don't store a value, only cleanup | |
3146 var_redir_stop(); | |
3147 return FAIL; | |
3148 } | |
3149 | |
3150 return OK; | |
3151 } | |
3152 | |
3153 /* | |
3154 * Append "value[value_len]" to the variable set by var_redir_start(). | |
3155 * The actual appending is postponed until redirection ends, because the value | |
3156 * appended may in fact be the string we write to, changing it may cause freed | |
3157 * memory to be used: | |
3158 * :redir => foo | |
3159 * :let foo | |
3160 * :redir END | |
3161 */ | |
3162 void | |
3163 var_redir_str(char_u *value, int value_len) | |
3164 { | |
3165 int len; | |
3166 | |
3167 if (redir_lval == NULL) | |
3168 return; | |
3169 | |
3170 if (value_len == -1) | |
3171 len = (int)STRLEN(value); // Append the entire string | |
3172 else | |
3173 len = value_len; // Append only "value_len" characters | |
3174 | |
3175 if (ga_grow(&redir_ga, len) == OK) | |
3176 { | |
3177 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); | |
3178 redir_ga.ga_len += len; | |
3179 } | |
3180 else | |
3181 var_redir_stop(); | |
3182 } | |
3183 | |
3184 /* | |
3185 * Stop redirecting command output to a variable. | |
3186 * Frees the allocated memory. | |
3187 */ | |
3188 void | |
3189 var_redir_stop(void) | |
3190 { | |
3191 typval_T tv; | |
3192 | |
3193 if (EVALCMD_BUSY) | |
3194 { | |
3195 redir_lval = NULL; | |
3196 return; | |
3197 } | |
3198 | |
3199 if (redir_lval != NULL) | |
3200 { | |
3201 // If there was no error: assign the text to the variable. | |
3202 if (redir_endp != NULL) | |
3203 { | |
3204 ga_append(&redir_ga, NUL); // Append the trailing NUL. | |
3205 tv.v_type = VAR_STRING; | |
3206 tv.vval.v_string = redir_ga.ga_data; | |
3207 // Call get_lval() again, if it's inside a Dict or List it may | |
3208 // have changed. | |
3209 redir_endp = get_lval(redir_varname, NULL, redir_lval, | |
3210 FALSE, FALSE, 0, FNE_CHECK_START); | |
3211 if (redir_endp != NULL && redir_lval->ll_name != NULL) | |
3212 set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE, | |
3213 (char_u *)"."); | |
3214 clear_lval(redir_lval); | |
3215 } | |
3216 | |
3217 // free the collected output | |
3218 VIM_CLEAR(redir_ga.ga_data); | |
3219 | |
3220 VIM_CLEAR(redir_lval); | |
3221 } | |
3222 VIM_CLEAR(redir_varname); | |
3223 } | |
3224 | |
2856 /* | 3225 /* |
2857 * "gettabvar()" function | 3226 * "gettabvar()" function |
2858 */ | 3227 */ |
2859 void | 3228 void |
2860 f_gettabvar(typval_T *argvars, typval_T *rettv) | 3229 f_gettabvar(typval_T *argvars, typval_T *rettv) |