forked from aniani/vim
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)
This commit is contained in:
371
src/evalvars.c
371
src/evalvars.c
@@ -18,6 +18,8 @@
|
||||
static char *e_letunexp = N_("E18: Unexpected characters in :let");
|
||||
|
||||
static dictitem_T globvars_var; // variable used for g:
|
||||
static dict_T globvardict; // Dictionary with g: variables
|
||||
#define globvarht globvardict.dv_hashtab
|
||||
|
||||
/*
|
||||
* Old Vim variables such as "v:version" are also available without the "v:".
|
||||
@@ -154,6 +156,7 @@ static struct vimvar
|
||||
#define vv_tv vv_di.di_tv
|
||||
|
||||
static dictitem_T vimvars_var; // variable used for v:
|
||||
static dict_T vimvardict; // Dictionary with v: variables
|
||||
#define vimvarht vimvardict.dv_hashtab
|
||||
|
||||
// for VIM_VERSION_ defines
|
||||
@@ -185,6 +188,7 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
|
||||
static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
|
||||
static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock);
|
||||
static void item_lock(typval_T *tv, int deep, int lock);
|
||||
static void delete_var(hashtab_T *ht, hashitem_T *hi);
|
||||
static void list_one_var(dictitem_T *v, char *prefix, int *first);
|
||||
static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
|
||||
|
||||
@@ -295,6 +299,12 @@ evalvars_clear(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
garbage_collect_globvars(int copyID)
|
||||
{
|
||||
return set_ref_in_ht(&globvarht, copyID, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
garbage_collect_vimvars(int copyID)
|
||||
{
|
||||
@@ -335,6 +345,148 @@ set_internal_string_var(char_u *name, char_u *value)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eval_charconvert(
|
||||
char_u *enc_from,
|
||||
char_u *enc_to,
|
||||
char_u *fname_from,
|
||||
char_u *fname_to)
|
||||
{
|
||||
int err = FALSE;
|
||||
|
||||
set_vim_var_string(VV_CC_FROM, enc_from, -1);
|
||||
set_vim_var_string(VV_CC_TO, enc_to, -1);
|
||||
set_vim_var_string(VV_FNAME_IN, fname_from, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
|
||||
if (eval_to_bool(p_ccv, &err, NULL, FALSE))
|
||||
err = TRUE;
|
||||
set_vim_var_string(VV_CC_FROM, NULL, -1);
|
||||
set_vim_var_string(VV_CC_TO, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, NULL, -1);
|
||||
|
||||
if (err)
|
||||
return FAIL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
|
||||
int
|
||||
eval_printexpr(char_u *fname, char_u *args)
|
||||
{
|
||||
int err = FALSE;
|
||||
|
||||
set_vim_var_string(VV_FNAME_IN, fname, -1);
|
||||
set_vim_var_string(VV_CMDARG, args, -1);
|
||||
if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
|
||||
err = TRUE;
|
||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
||||
set_vim_var_string(VV_CMDARG, NULL, -1);
|
||||
|
||||
if (err)
|
||||
{
|
||||
mch_remove(fname);
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(FEAT_DIFF) || defined(PROTO)
|
||||
void
|
||||
eval_diff(
|
||||
char_u *origfile,
|
||||
char_u *newfile,
|
||||
char_u *outfile)
|
||||
{
|
||||
int err = FALSE;
|
||||
|
||||
set_vim_var_string(VV_FNAME_IN, origfile, -1);
|
||||
set_vim_var_string(VV_FNAME_NEW, newfile, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
|
||||
(void)eval_to_bool(p_dex, &err, NULL, FALSE);
|
||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_NEW, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, NULL, -1);
|
||||
}
|
||||
|
||||
void
|
||||
eval_patch(
|
||||
char_u *origfile,
|
||||
char_u *difffile,
|
||||
char_u *outfile)
|
||||
{
|
||||
int err;
|
||||
|
||||
set_vim_var_string(VV_FNAME_IN, origfile, -1);
|
||||
set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
|
||||
(void)eval_to_bool(p_pex, &err, NULL, FALSE);
|
||||
set_vim_var_string(VV_FNAME_IN, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
|
||||
set_vim_var_string(VV_FNAME_OUT, NULL, -1);
|
||||
}
|
||||
# endif
|
||||
|
||||
#if defined(FEAT_SPELL) || defined(PROTO)
|
||||
/*
|
||||
* Evaluate an expression to a list with suggestions.
|
||||
* For the "expr:" part of 'spellsuggest'.
|
||||
* Returns NULL when there is an error.
|
||||
*/
|
||||
list_T *
|
||||
eval_spell_expr(char_u *badword, char_u *expr)
|
||||
{
|
||||
typval_T save_val;
|
||||
typval_T rettv;
|
||||
list_T *list = NULL;
|
||||
char_u *p = skipwhite(expr);
|
||||
|
||||
// Set "v:val" to the bad word.
|
||||
prepare_vimvar(VV_VAL, &save_val);
|
||||
set_vim_var_string(VV_VAL, badword, -1);
|
||||
if (p_verbose == 0)
|
||||
++emsg_off;
|
||||
|
||||
if (eval1(&p, &rettv, TRUE) == OK)
|
||||
{
|
||||
if (rettv.v_type != VAR_LIST)
|
||||
clear_tv(&rettv);
|
||||
else
|
||||
list = rettv.vval.v_list;
|
||||
}
|
||||
|
||||
if (p_verbose == 0)
|
||||
--emsg_off;
|
||||
clear_tv(get_vim_var_tv(VV_VAL));
|
||||
restore_vimvar(VV_VAL, &save_val);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* "list" is supposed to contain two items: a word and a number. Return the
|
||||
* word in "pp" and the number as the return value.
|
||||
* Return -1 if anything isn't right.
|
||||
* Used to get the good word and score from the eval_spell_expr() result.
|
||||
*/
|
||||
int
|
||||
get_spellword(list_T *list, char_u **pp)
|
||||
{
|
||||
listitem_T *li;
|
||||
|
||||
li = list->lv_first;
|
||||
if (li == NULL)
|
||||
return -1;
|
||||
*pp = tv_get_string(&li->li_tv);
|
||||
|
||||
li = li->li_next;
|
||||
if (li == NULL)
|
||||
return -1;
|
||||
return (int)tv_get_number(&li->li_tv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prepare v: variable "idx" to be used.
|
||||
* Save the current typeval in "save_tv".
|
||||
@@ -1569,6 +1721,31 @@ item_lock(typval_T *tv, int deep, int lock)
|
||||
--recurse;
|
||||
}
|
||||
|
||||
#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
|
||||
/*
|
||||
* Delete all "menutrans_" variables.
|
||||
*/
|
||||
void
|
||||
del_menutrans_vars(void)
|
||||
{
|
||||
hashitem_T *hi;
|
||||
int todo;
|
||||
|
||||
hash_lock(&globvarht);
|
||||
todo = (int)globvarht.ht_used;
|
||||
for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
--todo;
|
||||
if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
|
||||
delete_var(&globvarht, hi);
|
||||
}
|
||||
}
|
||||
hash_unlock(&globvarht);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local string buffer for the next two functions to store a variable name
|
||||
* with its prefix. Allocated in cat_prefix_varname(), freed later in
|
||||
@@ -1688,6 +1865,47 @@ get_user_var_name(expand_T *xp, int idx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
get_var_special_name(int nr)
|
||||
{
|
||||
switch (nr)
|
||||
{
|
||||
case VVAL_FALSE: return "v:false";
|
||||
case VVAL_TRUE: return "v:true";
|
||||
case VVAL_NONE: return "v:none";
|
||||
case VVAL_NULL: return "v:null";
|
||||
}
|
||||
internal_error("get_var_special_name()");
|
||||
return "42";
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the global variable dictionary
|
||||
*/
|
||||
dict_T *
|
||||
get_globvar_dict(void)
|
||||
{
|
||||
return &globvardict;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the global variable hash table
|
||||
*/
|
||||
hashtab_T *
|
||||
get_globvar_ht(void)
|
||||
{
|
||||
return &globvarht;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the v: variable dictionary
|
||||
*/
|
||||
dict_T *
|
||||
get_vimvar_dict(void)
|
||||
{
|
||||
return &vimvardict;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set type of v: variable to "type".
|
||||
*/
|
||||
@@ -2321,7 +2539,7 @@ vars_clear_ext(hashtab_T *ht, int free_val)
|
||||
* Delete a variable from hashtab "ht" at item "hi".
|
||||
* Clear the variable value and free the dictitem.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
delete_var(hashtab_T *ht, hashitem_T *hi)
|
||||
{
|
||||
dictitem_T *di = HI2DI(hi);
|
||||
@@ -2853,6 +3071,157 @@ var_exists(char_u *var)
|
||||
return n;
|
||||
}
|
||||
|
||||
static lval_T *redir_lval = NULL;
|
||||
#define EVALCMD_BUSY (redir_lval == (lval_T *)&redir_lval)
|
||||
static garray_T redir_ga; // only valid when redir_lval is not NULL
|
||||
static char_u *redir_endp = NULL;
|
||||
static char_u *redir_varname = NULL;
|
||||
|
||||
/*
|
||||
* Start recording command output to a variable
|
||||
* When "append" is TRUE append to an existing variable.
|
||||
* Returns OK if successfully completed the setup. FAIL otherwise.
|
||||
*/
|
||||
int
|
||||
var_redir_start(char_u *name, int append)
|
||||
{
|
||||
int save_emsg;
|
||||
int err;
|
||||
typval_T tv;
|
||||
|
||||
// Catch a bad name early.
|
||||
if (!eval_isnamec1(*name))
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// Make a copy of the name, it is used in redir_lval until redir ends.
|
||||
redir_varname = vim_strsave(name);
|
||||
if (redir_varname == NULL)
|
||||
return FAIL;
|
||||
|
||||
redir_lval = ALLOC_CLEAR_ONE(lval_T);
|
||||
if (redir_lval == NULL)
|
||||
{
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// The output is stored in growarray "redir_ga" until redirection ends.
|
||||
ga_init2(&redir_ga, (int)sizeof(char), 500);
|
||||
|
||||
// Parse the variable name (can be a dict or list entry).
|
||||
redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
|
||||
FNE_CHECK_START);
|
||||
if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
|
||||
{
|
||||
clear_lval(redir_lval);
|
||||
if (redir_endp != NULL && *redir_endp != NUL)
|
||||
// Trailing characters are present after the variable name
|
||||
emsg(_(e_trailing));
|
||||
else
|
||||
emsg(_(e_invarg));
|
||||
redir_endp = NULL; // don't store a value, only cleanup
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// check if we can write to the variable: set it to or append an empty
|
||||
// string
|
||||
save_emsg = did_emsg;
|
||||
did_emsg = FALSE;
|
||||
tv.v_type = VAR_STRING;
|
||||
tv.vval.v_string = (char_u *)"";
|
||||
if (append)
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)".");
|
||||
else
|
||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"=");
|
||||
clear_lval(redir_lval);
|
||||
err = did_emsg;
|
||||
did_emsg |= save_emsg;
|
||||
if (err)
|
||||
{
|
||||
redir_endp = NULL; // don't store a value, only cleanup
|
||||
var_redir_stop();
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append "value[value_len]" to the variable set by var_redir_start().
|
||||
* The actual appending is postponed until redirection ends, because the value
|
||||
* appended may in fact be the string we write to, changing it may cause freed
|
||||
* memory to be used:
|
||||
* :redir => foo
|
||||
* :let foo
|
||||
* :redir END
|
||||
*/
|
||||
void
|
||||
var_redir_str(char_u *value, int value_len)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (redir_lval == NULL)
|
||||
return;
|
||||
|
||||
if (value_len == -1)
|
||||
len = (int)STRLEN(value); // Append the entire string
|
||||
else
|
||||
len = value_len; // Append only "value_len" characters
|
||||
|
||||
if (ga_grow(&redir_ga, len) == OK)
|
||||
{
|
||||
mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
|
||||
redir_ga.ga_len += len;
|
||||
}
|
||||
else
|
||||
var_redir_stop();
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop redirecting command output to a variable.
|
||||
* Frees the allocated memory.
|
||||
*/
|
||||
void
|
||||
var_redir_stop(void)
|
||||
{
|
||||
typval_T tv;
|
||||
|
||||
if (EVALCMD_BUSY)
|
||||
{
|
||||
redir_lval = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (redir_lval != NULL)
|
||||
{
|
||||
// If there was no error: assign the text to the variable.
|
||||
if (redir_endp != NULL)
|
||||
{
|
||||
ga_append(&redir_ga, NUL); // Append the trailing NUL.
|
||||
tv.v_type = VAR_STRING;
|
||||
tv.vval.v_string = redir_ga.ga_data;
|
||||
// Call get_lval() again, if it's inside a Dict or List it may
|
||||
// have changed.
|
||||
redir_endp = get_lval(redir_varname, NULL, redir_lval,
|
||||
FALSE, FALSE, 0, FNE_CHECK_START);
|
||||
if (redir_endp != NULL && redir_lval->ll_name != NULL)
|
||||
set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE,
|
||||
(char_u *)".");
|
||||
clear_lval(redir_lval);
|
||||
}
|
||||
|
||||
// free the collected output
|
||||
VIM_CLEAR(redir_ga.ga_data);
|
||||
|
||||
VIM_CLEAR(redir_lval);
|
||||
}
|
||||
VIM_CLEAR(redir_varname);
|
||||
}
|
||||
|
||||
/*
|
||||
* "gettabvar()" function
|
||||
*/
|
||||
|
Reference in New Issue
Block a user