0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

updated for version 7.0043

This commit is contained in:
Bram Moolenaar
2005-01-21 11:56:39 +00:00
parent dcaf10e19a
commit a7043832f3

View File

@@ -66,11 +66,23 @@ typedef struct
typedef struct
{
typeval tv; /* type and value of the variable */
char_u *v_name; /* name of variable */
char_u v_name[1]; /* name of variable (actually longer) */
} var;
typedef var * VAR;
/*
* In a hashtable item "hi_key" points to "v_name" in a variable.
* This avoids adding a pointer to the hashtable item.
* VAR2HIKEY() converts a var pointer to a hashitem key pointer.
* HIKEY2VAR() converts a hashitem key pointer to a var pointer.
* HI2VAR() converts a hashitem pointer to a var pointer.
*/
static var dumvar;
#define VAR2HIKEY(v) ((v)->v_name)
#define HIKEY2VAR(p) ((VAR)(p - (dumvar.v_name - (char_u *)&dumvar.tv)))
#define HI2VAR(hi) HIKEY2VAR((hi)->hi_key)
/*
* Structure to hold an item of a list: an internal variable without a name.
*/
@@ -127,9 +139,9 @@ typedef struct dictitem_S dictitem;
* HI2DI() converts a hashitem pointer to a dictitem pointer.
*/
static dictitem dumdi;
#define DI2HIKEY(p) ((p)->di_key)
#define DI2HIKEY(di) ((di)->di_key)
#define HIKEY2DI(p) ((dictitem *)(p - (dumdi.di_key - (char_u *)&dumdi.di_tv)))
#define HI2DI(p) HIKEY2DI((p)->hi_key)
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
/*
* Structure to hold info about a Dictionary.
@@ -208,19 +220,13 @@ static char *e_letwrong = N_("E734: Wrong variable type for %s=");
/*
* All user-defined global variables are stored in "variables".
*/
garray_T variables = {0, 0, sizeof(var), 4, NULL};
hashtable variables;
/*
* Array to hold an array with variables local to each sourced script.
* Array to hold the hashtable with variables local to each sourced script.
*/
static garray_T ga_scripts = {0, 0, sizeof(garray_T), 4, NULL};
#define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
#define VAR_ENTRY(idx) (((VAR)(variables.ga_data))[idx])
#define VAR_GAP_ENTRY(idx, gap) (((VAR)((gap)->ga_data))[idx])
#define BVAR_ENTRY(idx) (((VAR)(curbuf->b_vars.ga_data))[idx])
#define WVAR_ENTRY(idx) (((VAR)(curwin->w_vars.ga_data))[idx])
static garray_T ga_scripts = {0, 0, sizeof(hashtable), 4, NULL};
#define SCRIPT_VARS(id) (((hashtable *)ga_scripts.ga_data)[(id) - 1])
static int echo_attr = 0; /* attributes used for ":echo" */
@@ -273,7 +279,7 @@ struct funccall
var a0_var; /* "a:0" variable */
var firstline; /* "a:firstline" variable */
var lastline; /* "a:lastline" variable */
garray_T l_vars; /* local function variables */
hashtable l_vars; /* local function variables */
typeval *rettv; /* return value */
linenr_T breakpoint; /* next line with breakpoint or zero */
int dbg_tick; /* debug_tick when breakpoint was set */
@@ -301,6 +307,16 @@ typedef struct
dictitem *fd_di; /* Dictionary item used */
} funcdict;
/*
* Initialize the global variables.
*/
void
eval_init()
{
hash_init(&variables);
}
/*
* Return the name of the executed function.
*/
@@ -650,7 +666,7 @@ static win_T *find_win_by_nr __ARGS((typeval *vp));
static pos_T *var2fpos __ARGS((typeval *varp, int lnum));
static int get_env_len __ARGS((char_u **arg));
static int get_id_len __ARGS((char_u **arg));
static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate));
static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
static int eval_isnamec __ARGS((int c));
static int find_vim_var __ARGS((char_u *name, int len));
@@ -664,10 +680,10 @@ static long get_tv_number __ARGS((typeval *varp));
static linenr_T get_tv_lnum __ARGS((typeval *argvars));
static char_u *get_tv_string __ARGS((typeval *varp));
static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
static VAR find_var __ARGS((char_u *name, int writing));
static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
static void clear_var __ARGS((VAR v));
static VAR find_var __ARGS((char_u *name, hashtable **htp));
static VAR find_var_in_ht __ARGS((hashtable *ht, char_u *varname));
static hashtable *find_var_ht __ARGS((char_u *name, char_u **varname));
static void delete_var __ARGS((hashtable *ht, hashitem *hi));
static void list_one_var __ARGS((VAR v, char_u *prefix));
static void list_vim_var __ARGS((int i));
static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
@@ -687,16 +703,16 @@ static void func_unref __ARGS((char_u *name));
static void func_ref __ARGS((char_u *name));
static void call_user_func __ARGS((ufunc_T *fp, int argcount, typeval *argvars, typeval *rettv, linenr_T firstline, linenr_T lastline, dictvar *selfdict));
#define get_var_string(p) get_tv_string(&(p)->tv)
#define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b))
#define get_var_number(p) get_tv_number(&((p)->tv))
static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
static int ex_let_vars __ARGS((char_u *arg, typeval *tv, int copy, int semicolon, int var_count, char_u *nextchars));
static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
static char_u *skip_var_one __ARGS((char_u *arg));
static void list_all_vars __ARGS((void));
static void list_hashtable_vars __ARGS((hashtable *ht, char_u *prefix));
static void list_glob_vars __ARGS((void));
static void list_buf_vars __ARGS((void));
static void list_win_vars __ARGS((void));
static void list_vim_vars __ARGS((void));
static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars, char_u *op));
static int check_changedtick __ARGS((char_u *arg));
@@ -1238,8 +1254,13 @@ ex_let(eap)
/* ":let var1 var2" */
arg = list_arg_vars(eap, arg);
else if (!eap->skip)
{
/* ":let" */
list_all_vars();
list_glob_vars();
list_buf_vars();
list_win_vars();
list_vim_vars();
}
eap->nextcmd = check_nextcmd(arg);
}
else
@@ -1433,23 +1454,63 @@ skip_var_one(arg)
return find_name_end(arg, NULL, NULL, TRUE);
}
/*
* List variables for hashtable "ht" with prefix "prefix".
*/
static void
list_all_vars()
list_hashtable_vars(ht, prefix)
hashtable *ht;
char_u *prefix;
{
hashitem *hi;
int todo;
todo = ht->ht_used;
for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
--todo;
list_one_var(HI2VAR(hi), prefix);
}
}
}
/*
* List global variables.
*/
static void
list_glob_vars()
{
list_hashtable_vars(&variables, (char_u *)"");
}
/*
* List buffer variables.
*/
static void
list_buf_vars()
{
list_hashtable_vars(&curbuf->b_vars, (char_u *)"b:");
}
/*
* List window variables.
*/
static void
list_win_vars()
{
list_hashtable_vars(&curwin->w_vars, (char_u *)"w:");
}
/*
* List Vim variables.
*/
static void
list_vim_vars()
{
int i;
/*
* List all variables.
*/
for (i = 0; i < variables.ga_len && !got_int; ++i)
if (VAR_ENTRY(i).v_name != NULL)
list_one_var(&VAR_ENTRY(i), (char_u *)"");
for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
if (BVAR_ENTRY(i).v_name != NULL)
list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
if (WVAR_ENTRY(i).v_name != NULL)
list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
for (i = 0; i < VV_LEN && !got_int; ++i)
if (vimvars[i].tv.v_type == VAR_NUMBER || vimvars[i].vv_str != NULL)
list_vim_var(i);
@@ -1518,6 +1579,20 @@ list_arg_vars(eap, arg)
*name_end = NUL;
arg_len = (int)(name_end - arg);
}
if (arg_len == 2 && arg[1] == ':')
{
switch (*arg)
{
case 'g': list_glob_vars(); break;
case 'b': list_buf_vars(); break;
case 'w': list_win_vars(); break;
case 'v': list_vim_vars(); break;
default:
EMSG2(_("E738: Can't list variables for %s"), arg);
}
}
else
{
i = find_vim_var(arg, arg_len);
if (i >= 0)
list_vim_var(i);
@@ -1532,7 +1607,7 @@ list_arg_vars(eap, arg)
}
else
{
varp = find_var(arg, FALSE);
varp = find_var(arg, NULL);
if (varp == NULL)
{
/* Skip further arguments but do continue to
@@ -1561,6 +1636,7 @@ list_arg_vars(eap, arg)
list_one_var(varp, (char_u *)"");
}
}
}
if (expr_start != NULL)
vim_free(temp_string);
else
@@ -1786,7 +1862,7 @@ check_changedtick(arg)
* wrong; must end in space or cmd separator.
*
* Returns a pointer to just after the name, including indexes.
* When an evaluation error occurs "lp->name" is NULL;
* When an evaluation error occurs "lp->ll_name" is NULL;
* Returns NULL for a parsing error. Still need to free items in "lp"!
*/
static char_u *
@@ -1808,6 +1884,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet)
listitem *ni;
char_u *key = NULL;
int len;
hashtable *ht;
/* Clear everything in "lp". */
vim_memset(lp, 0, sizeof(lval));
@@ -1855,7 +1932,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet)
cc = *p;
*p = NUL;
v = find_var(lp->ll_name, TRUE);
v = find_var(lp->ll_name, &ht);
if (v == NULL && !quiet)
EMSG2(_(e_undefvar), lp->ll_name);
*p = cc;
@@ -2729,14 +2806,25 @@ do_unlet_var(lp, name_end, forceit)
do_unlet(name)
char_u *name;
{
VAR v;
hashtable *ht;
hashitem *hi;
char_u *varname;
v = find_var(name, TRUE);
if (v != NULL)
if (name[0] == 'a' && name[1] == ':')
EMSG2(_(e_readonlyvar), name);
else
{
clear_var(v);
ht = find_var_ht(name, &varname);
if (ht != NULL)
{
hi = hash_find(ht, varname);
if (!HASHITEM_EMPTY(hi))
{
delete_var(ht, hi);
return OK;
}
}
}
return FAIL;
}
@@ -2747,12 +2835,21 @@ do_unlet(name)
void
del_menutrans_vars()
{
int i;
hashitem *hi;
int todo;
for (i = 0; i < variables.ga_len; ++i)
if (VAR_ENTRY(i).v_name != NULL
&& STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0)
clear_var(&VAR_ENTRY(i));
hash_lock(&variables);
todo = variables.ht_used;
for (hi = variables.ht_array; todo > 0 && !got_int; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
--todo;
if (STRNCMP(HI2VAR(hi)->v_name, "menutrans_", 10) == 0)
delete_var(&variables, hi);
}
}
hash_unlock(&variables);
}
#endif
@@ -2808,47 +2905,44 @@ get_user_var_name(xp, idx)
expand_T *xp;
int idx;
{
static int gidx;
static int bidx;
static int widx;
static int gdone;
static int bdone;
static int wdone;
static int vidx;
char_u *name;
static hashitem *hi;
if (idx == 0)
gidx = bidx = widx = vidx = 0;
if (gidx < variables.ga_len) /* Global variables */
{
while ((name = VAR_ENTRY(gidx++).v_name) == NULL
&& gidx < variables.ga_len)
/* skip */;
if (name != NULL)
gdone = bdone = wdone = vidx = 0;
if (gdone < variables.ht_used) /* Global variables */
{
if (gdone++ == 0)
hi = variables.ht_array;
while (HASHITEM_EMPTY(hi))
++hi;
if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
return cat_prefix_varname('g', name);
else
return name;
return cat_prefix_varname('g', hi->hi_key);
return hi->hi_key;
}
}
if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
if (bdone < curbuf->b_vars.ht_used) /* Current buffer variables */
{
while ((name = BVAR_ENTRY(bidx++).v_name) == NULL
&& bidx < curbuf->b_vars.ga_len)
/* skip */;
if (name != NULL)
return cat_prefix_varname('b', name);
if (bdone++ == 0)
hi = curbuf->b_vars.ht_array;
while (HASHITEM_EMPTY(hi))
++hi;
return cat_prefix_varname('b', hi->hi_key);
}
if (bidx == curbuf->b_vars.ga_len)
if (bdone == curbuf->b_vars.ht_used)
{
++bidx;
++bdone;
return (char_u *)"b:changedtick";
}
if (widx < curwin->w_vars.ga_len) /* Current window variables */
if (wdone < curwin->w_vars.ht_used) /* Current window variables */
{
while ((name = WVAR_ENTRY(widx++).v_name) == NULL
&& widx < curwin->w_vars.ga_len)
/* skip */;
if (name != NULL)
return cat_prefix_varname('w', name);
if (bdone++ == 0)
hi = curwin->w_vars.ht_array;
while (HASHITEM_EMPTY(hi))
++hi;
return cat_prefix_varname('w', hi->hi_key);
}
if (vidx < VV_LEN) /* Built-in variables */
return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
@@ -3732,7 +3826,7 @@ eval7(arg, rettv, evaluate)
* Can also be a curly-braces kind of name: {expr}.
*/
s = *arg;
len = get_func_len(arg, &alias, evaluate);
len = get_name_len(arg, &alias, evaluate);
if (alias != NULL)
s = alias;
@@ -5010,6 +5104,7 @@ dict_free(d)
--todo;
}
}
hash_clear(&d->dv_hashtable);
vim_free(d);
}
@@ -5823,7 +5918,7 @@ deref_func_name(name, lenp)
cc = name[*lenp];
name[*lenp] = NUL;
v = find_var(name, FALSE);
v = find_var(name, NULL);
name[*lenp] = cc;
if (v != NULL && v->tv.v_type == VAR_FUNC)
{
@@ -6705,7 +6800,7 @@ f_confirm(argvars, rettv)
def = get_tv_number(&argvars[2]);
if (argvars[3].v_type != VAR_UNKNOWN)
{
/* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
/* avoid that TOUPPER_ASC calls get_tv_string_buf() twice */
c = *get_tv_string_buf(&argvars[3], buf2);
switch (TOUPPER_ASC(c))
{
@@ -7429,6 +7524,7 @@ filter_map(argvars, rettv, map)
listitem *li, *nli;
listvar *l = NULL;
dictitem *di;
hashtable *ht;
hashitem *hi;
dictvar *d = NULL;
typeval save_val;
@@ -7461,8 +7557,10 @@ filter_map(argvars, rettv, map)
save_key = vimvars[VV_KEY].tv;
vimvars[VV_KEY].tv.v_type = VAR_STRING;
todo = d->dv_hashtable.ht_used;
for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi)
ht = &d->dv_hashtable;
hash_lock(ht);
todo = ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
@@ -7476,6 +7574,7 @@ filter_map(argvars, rettv, map)
clear_tv(&vimvars[VV_KEY].tv);
}
}
hash_unlock(ht);
clear_tv(&vimvars[VV_KEY].tv);
vimvars[VV_KEY].tv = save_key;
@@ -7799,6 +7898,7 @@ f_function(argvars, rettv)
{
char_u *s;
rettv->vval.v_number = 0;
s = get_tv_string(&argvars[0]);
if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
EMSG2(_(e_invarg2), s);
@@ -7893,7 +7993,7 @@ f_getbufvar(argvars, rettv)
else
{
/* look up the variable */
v = find_var_in_ga(&buf->b_vars, varname);
v = find_var_in_ht(&buf->b_vars, varname);
if (v != NULL)
copy_tv(&v->tv, rettv);
}
@@ -8417,7 +8517,7 @@ f_getwinvar(argvars, rettv)
else
{
/* look up the variable */
v = find_var_in_ga(&win->w_vars, varname);
v = find_var_in_ht(&win->w_vars, varname);
if (v != NULL)
copy_tv(&v->tv, rettv);
}
@@ -12717,14 +12817,15 @@ get_id_len(arg)
}
/*
* Get the length of the name of a function.
* Get the length of the name of a variable or function.
* Only the name is recognized, does not handle ".key" or "[idx]".
* "arg" is advanced to the first non-white character after the name.
* Return 0 if something is wrong.
* If the name contains 'magic' {}'s, expand them and return the
* expanded name in an allocated string via 'alias' - caller must free.
*/
static int
get_func_len(arg, alias, evaluate)
get_name_len(arg, alias, evaluate)
char_u **arg;
char_u **alias;
int evaluate;
@@ -13089,16 +13190,14 @@ get_var_tv(name, len, rettv)
* Check for built-in v: variables.
*/
else if ((i = find_vim_var(name, len)) >= 0)
{
tv = &vimvars[i].tv;
}
/*
* Check for user-defined variables.
*/
else
{
v = find_var(name, FALSE);
v = find_var(name, NULL);
if (v != NULL)
tv = &v->tv;
}
@@ -13287,8 +13386,8 @@ get_tv_lnum(argvars)
/*
* Get the string value of a variable.
* If it is a Number variable, the number is converted into a string.
* get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
* get_var_string_buf() uses a given buffer.
* get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
* get_tv_string_buf() uses a given buffer.
* If the String variable has never been set, return an empty string.
* Never returns NULL;
*/
@@ -13335,22 +13434,24 @@ get_tv_string_buf(varp, buf)
* Find variable "name" in the list of variables.
* Return a pointer to it if found, NULL if not found.
* Careful: "a:0" variables don't have a name.
* When "htp" is not NULL we are writing to the variable, set "htp" to the
* hashtable used.
*/
static VAR
find_var(name, writing)
find_var(name, htp)
char_u *name;
int writing;
hashtable **htp;
{
int i;
char_u *varname;
garray_T *gap;
hashtable *ht;
if (name[0] == 'a' && name[1] == ':')
{
/* Function arguments "a:".
* NOTE: We use a typecast, because function arguments don't have a
* name. The caller must not try to access the name! */
if (writing)
if (htp != NULL)
{
EMSG2(_(e_readonlyvar), name);
return NULL;
@@ -13379,33 +13480,37 @@ find_var(name, writing)
return NULL;
}
gap = find_var_ga(name, &varname);
if (gap == NULL)
ht = find_var_ht(name, &varname);
if (htp != NULL)
*htp = ht;
if (ht == NULL)
return NULL;
return find_var_in_ga(gap, varname);
}
static VAR
find_var_in_ga(gap, varname)
garray_T *gap;
char_u *varname;
{
int i;
for (i = gap->ga_len; --i >= 0; )
if (VAR_GAP_ENTRY(i, gap).v_name != NULL
&& STRCMP(VAR_GAP_ENTRY(i, gap).v_name, varname) == 0)
break;
if (i < 0)
return NULL;
return &VAR_GAP_ENTRY(i, gap);
return find_var_in_ht(ht, varname);
}
/*
* Find the growarray and start of name without ':' for a variable name.
* Find variable "varname" in hashtable "ht".
* Returns NULL if not found.
*/
static garray_T *
find_var_ga(name, varname)
static VAR
find_var_in_ht(ht, varname)
hashtable *ht;
char_u *varname;
{
hashitem *hi;
hi = hash_find(ht, varname);
if (HASHITEM_EMPTY(hi))
return NULL;
return HI2VAR(hi);
}
/*
* Find the hashtable used for a variable name.
* Set "varname" to the start of name without ':'.
*/
static hashtable *
find_var_ht(name, varname)
char_u *name;
char_u **varname;
{
@@ -13444,22 +13549,35 @@ get_var_value(name)
{
VAR v;
v = find_var(name, FALSE);
v = find_var(name, NULL);
if (v == NULL)
return NULL;
return get_var_string(v);
return get_tv_string(&v->tv);
}
/*
* Allocate a new growarry for a sourced script. It will be used while
* Allocate a new hashtable for a sourced script. It will be used while
* sourcing this script and when executing functions defined in the script.
*/
void
new_script_vars(id)
scid_T id;
{
int i;
hashtable *ht;
if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
{
/* Re-allocating ga_data means that an ht_array pointing to
* ht_smallarray becomes invalid. We can recognize this: ht_mask is
* at its init value. */
for (i = 1; i <= ga_scripts.ga_len; ++i)
{
ht = &SCRIPT_VARS(i);
if (ht->ht_mask == HT_INIT_SIZE - 1)
ht->ht_array = ht->ht_smallarray;
}
while (ga_scripts.ga_len < id)
{
vars_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
@@ -13469,36 +13587,58 @@ new_script_vars(id)
}
/*
* Initialize internal variables for use.
* Initialize hashtable with variables for use.
*/
void
vars_init(gap)
garray_T *gap;
vars_init(ht)
hashtable *ht;
{
ga_init2(gap, (int)sizeof(var), 4);
hash_init(ht);
}
/*
* Clean up a list of internal variables.
*/
void
vars_clear(gap)
garray_T *gap;
vars_clear(ht)
hashtable *ht;
{
int i;
int todo;
hashitem *hi;
VAR v;
for (i = gap->ga_len; --i >= 0; )
clear_var(&VAR_GAP_ENTRY(i, gap));
ga_clear(gap);
todo = ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
--todo;
/* Free the variable. Don't remove it from the hashtable,
* ht_array might change then. hash_clear() takes care of it
* later. */
v = HI2VAR(hi);
clear_tv(&v->tv);
vim_free(v);
}
}
hash_clear(ht);
hash_init(ht);
}
/*
* Delete a variable from hashtable "ht" at item "hi".
*/
static void
clear_var(v)
VAR v;
delete_var(ht, hi)
hashtable *ht;
hashitem *hi;
{
vim_free(v->v_name);
v->v_name = NULL;
VAR v = HI2VAR(hi);
hash_remove(ht, hi);
clear_tv(&v->tv);
vim_free(v);
}
/*
@@ -13587,7 +13727,7 @@ set_var(name, tv, copy)
int i;
VAR v;
char_u *varname;
garray_T *gap;
hashtable *ht;
/*
* Handle setting internal v: variables.
@@ -13635,8 +13775,21 @@ set_var(name, tv, copy)
}
}
v = find_var(name, TRUE);
if (v != NULL) /* existing variable, only need to free string */
if (name[0] == 'a' && name[1] == ':')
{
EMSG2(_(e_readonlyvar), name);
return;
}
ht = find_var_ht(name, &varname);
if (ht == NULL)
{
EMSG2(_("E461: Illegal variable name: %s"), name);
return;
}
v = find_var_in_ht(ht, varname);
if (v != NULL) /* existing variable, need to clear the value */
{
if (v->tv.v_type != tv->v_type
&& !((v->tv.v_type == VAR_STRING
@@ -13651,29 +13804,17 @@ set_var(name, tv, copy)
}
else /* add a new variable */
{
gap = find_var_ga(name, &varname);
if (gap == NULL) /* illegal name */
{
EMSG2(_("E461: Illegal variable name: %s"), name);
v = (VAR)alloc((unsigned)(sizeof(var) + STRLEN(varname)));
if (v == NULL)
return;
STRCPY(v->v_name, varname);
if (hash_add(ht, VAR2HIKEY(v)) == FAIL)
{
vim_free(v);
return;
}
}
/* Try to use an empty entry */
for (i = gap->ga_len; --i >= 0; )
if (VAR_GAP_ENTRY(i, gap).v_name == NULL)
break;
if (i < 0) /* need to allocate more room */
{
if (ga_grow(gap, 1) == FAIL)
return;
i = gap->ga_len;
}
v = &VAR_GAP_ENTRY(i, gap);
if ((v->v_name = vim_strsave(varname)) == NULL)
return;
if (i == gap->ga_len)
++gap->ga_len;
}
if (copy || tv->v_type == VAR_NUMBER)
copy_tv(tv, &v->tv);
else
@@ -14358,7 +14499,7 @@ ex_function(eap)
*/
if (fudi.fd_dict == NULL)
{
v = find_var(name, FALSE);
v = find_var(name, NULL);
if (v != NULL && v->tv.v_type == VAR_FUNC)
{
EMSG2(_("E707: Function name conflicts with variable: %s"), name);
@@ -14463,6 +14604,7 @@ ret_free:
/*
* Get a function name, translating "<SID>" and "<SNR>".
* Also handles a Funcref in a List or Dictionary.
* Returns the function name in allocated memory, or NULL for failure.
* flags:
* TFN_INT: internal function name OK
@@ -14486,11 +14628,22 @@ trans_function_name(pp, skip, flags, fdp)
if (fdp != NULL)
vim_memset(fdp, 0, sizeof(funcdict));
/* A name starting with "<SID>" or "<SNR>" is local to a script. */
start = *pp;
/* Check for hard coded <SNR>: already translated function ID (from a user
* command). */
if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
&& (*pp)[2] == (int)KE_SNR)
{
*pp += 3;
len = get_id_len(pp) + 3;
return vim_strnsave(start, len);
}
/* A name starting with "<SID>" or "<SNR>" is local to a script. But
* don't skip over "s:", get_lval() needs it for "s:dict.func". */
lead = eval_fname_script(start);
if (lead > 0)
if (lead > 2)
start += lead;
end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET);
@@ -14500,7 +14653,7 @@ trans_function_name(pp, skip, flags, fdp)
EMSG(_("E129: Function name required"));
goto theend;
}
if (end == NULL || (lv.ll_tv != NULL && (lead > 0 || lv.ll_range)))
if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
{
/*
* Report an invalid expression in braces, unless the expression
@@ -14553,7 +14706,11 @@ trans_function_name(pp, skip, flags, fdp)
if (lv.ll_exp_name != NULL)
len = STRLEN(lv.ll_exp_name);
else
len = (int)(end - start);
{
if (lead == 2) /* skip over "s:" */
lv.ll_name += 2;
len = (int)(end - lv.ll_name);
}
/*
* Copy the function name to allocated memory.
@@ -14590,7 +14747,7 @@ trans_function_name(pp, skip, flags, fdp)
name[0] = K_SPECIAL;
name[1] = KS_EXTRA;
name[2] = (int)KE_SNR;
if (eval_fname_sid(*pp)) /* If it's "<SID>" */
if (lead > 3) /* If it's "<SID>" */
STRCPY(name + 3, sid_buf);
}
mch_memmove(name + lead, lv.ll_name, (size_t)len);
@@ -14938,26 +15095,26 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
fc.level = ex_nesting_level;
fc.a0_var.tv.v_type = VAR_NUMBER;
fc.a0_var.tv.vval.v_number = argcount - fp->args.ga_len;
fc.a0_var.v_name = NULL;
fc.a0_var.v_name[0] = NUL;
current_funccal = &fc;
fc.firstline.tv.v_type = VAR_NUMBER;
fc.firstline.tv.vval.v_number = firstline;
fc.firstline.v_name = NULL;
fc.firstline.v_name[0] = NUL;
fc.lastline.tv.v_type = VAR_NUMBER;
fc.lastline.tv.vval.v_number = lastline;
fc.lastline.v_name = NULL;
fc.lastline.v_name[0] = NUL;
/* Check if this function has a breakpoint. */
fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
fc.dbg_tick = debug_tick;
if (selfdict != NULL && ga_grow(&fc.l_vars, 1) != FAIL)
if (selfdict != NULL)
{
VAR v = &VAR_GAP_ENTRY(0, &fc.l_vars);
VAR v = (VAR)alloc((unsigned)(sizeof(var) + 4));
/* Set the "self" local variable. */
if ((v->v_name = vim_strsave((char_u *)"self")) != NULL)
if (v != NULL)
{
++fc.l_vars.ga_len;
STRCPY(v->v_name, "self");
hash_add(&fc.l_vars, VAR2HIKEY(v));
v->tv.v_type = VAR_DICT;
v->tv.vval.v_dict = selfdict;
++selfdict->dv_refcount;
@@ -15412,9 +15569,9 @@ read_viminfo_varlist(virp, writing)
write_viminfo_varlist(fp)
FILE *fp;
{
garray_T *gap = &variables; /* global variable */
hashitem *hi;
VAR this_var;
int i;
int todo;
char *s;
char_u *tofree;
char_u numbuf[NUMBUFLEN];
@@ -15423,11 +15580,15 @@ write_viminfo_varlist(fp)
return;
fprintf(fp, _("\n# global variables:\n"));
for (i = gap->ga_len; --i >= 0; )
todo = variables.ht_used;
for (hi = variables.ht_array; todo > 0; ++hi)
{
this_var = &VAR_GAP_ENTRY(i, gap);
if (this_var->v_name != NULL
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
if (!HASHITEM_EMPTY(hi))
{
--todo;
this_var = HI2VAR(hi);
if (var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
{
switch (this_var->tv.v_type)
{
@@ -15442,6 +15603,7 @@ write_viminfo_varlist(fp)
}
}
}
}
#endif
#if defined(FEAT_SESSION) || defined(PROTO)
@@ -15449,25 +15611,28 @@ write_viminfo_varlist(fp)
store_session_globals(fd)
FILE *fd;
{
garray_T *gap = &variables; /* global variable */
hashitem *hi;
VAR this_var;
int i;
int todo;
char_u *p, *t;
for (i = gap->ga_len; --i >= 0; )
todo = variables.ht_used;
for (hi = variables.ht_array; todo > 0; ++hi)
{
this_var = &VAR_GAP_ENTRY(i, gap);
if (this_var->v_name != NULL
&& (this_var->tv.v_type == VAR_NUMBER
if (!HASHITEM_EMPTY(hi))
{
--todo;
this_var = HI2VAR(hi);
if ((this_var->tv.v_type == VAR_NUMBER
|| this_var->tv.v_type == VAR_STRING)
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
{
/* Escape special characters with a backslash. Turn a LF and
* CR into \n and \r. */
p = vim_strsave_escaped(get_var_string(this_var),
p = vim_strsave_escaped(get_tv_string(&this_var->tv),
(char_u *)"\\\"\n\r");
if (p == NULL) /* out of memory */
continue;
break;
for (t = p; *t != NUL; ++t)
if (*t == '\n')
*t = 'n';
@@ -15486,6 +15651,7 @@ store_session_globals(fd)
vim_free(p);
}
}
}
return OK;
}
#endif