mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
updated for version 7.0043
This commit is contained in:
542
src/eval.c
542
src/eval.c
@@ -66,11 +66,23 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
typeval tv; /* type and value of the variable */
|
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;
|
} var;
|
||||||
|
|
||||||
typedef var * 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.
|
* 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.
|
* HI2DI() converts a hashitem pointer to a dictitem pointer.
|
||||||
*/
|
*/
|
||||||
static dictitem dumdi;
|
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 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.
|
* 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".
|
* 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};
|
static garray_T ga_scripts = {0, 0, sizeof(hashtable), 4, NULL};
|
||||||
#define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
|
#define SCRIPT_VARS(id) (((hashtable *)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 int echo_attr = 0; /* attributes used for ":echo" */
|
static int echo_attr = 0; /* attributes used for ":echo" */
|
||||||
|
|
||||||
@@ -273,7 +279,7 @@ struct funccall
|
|||||||
var a0_var; /* "a:0" variable */
|
var a0_var; /* "a:0" variable */
|
||||||
var firstline; /* "a:firstline" variable */
|
var firstline; /* "a:firstline" variable */
|
||||||
var lastline; /* "a:lastline" variable */
|
var lastline; /* "a:lastline" variable */
|
||||||
garray_T l_vars; /* local function variables */
|
hashtable l_vars; /* local function variables */
|
||||||
typeval *rettv; /* return value */
|
typeval *rettv; /* return value */
|
||||||
linenr_T breakpoint; /* next line with breakpoint or zero */
|
linenr_T breakpoint; /* next line with breakpoint or zero */
|
||||||
int dbg_tick; /* debug_tick when breakpoint was set */
|
int dbg_tick; /* debug_tick when breakpoint was set */
|
||||||
@@ -301,6 +307,16 @@ typedef struct
|
|||||||
dictitem *fd_di; /* Dictionary item used */
|
dictitem *fd_di; /* Dictionary item used */
|
||||||
} funcdict;
|
} funcdict;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the global variables.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
eval_init()
|
||||||
|
{
|
||||||
|
hash_init(&variables);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the name of the executed function.
|
* 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 pos_T *var2fpos __ARGS((typeval *varp, int lnum));
|
||||||
static int get_env_len __ARGS((char_u **arg));
|
static int get_env_len __ARGS((char_u **arg));
|
||||||
static int get_id_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 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 eval_isnamec __ARGS((int c));
|
||||||
static int find_vim_var __ARGS((char_u *name, int len));
|
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 linenr_T get_tv_lnum __ARGS((typeval *argvars));
|
||||||
static char_u *get_tv_string __ARGS((typeval *varp));
|
static char_u *get_tv_string __ARGS((typeval *varp));
|
||||||
static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
|
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 __ARGS((char_u *name, hashtable **htp));
|
||||||
static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
|
static VAR find_var_in_ht __ARGS((hashtable *ht, char_u *varname));
|
||||||
static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
|
static hashtable *find_var_ht __ARGS((char_u *name, char_u **varname));
|
||||||
static void clear_var __ARGS((VAR v));
|
static void delete_var __ARGS((hashtable *ht, hashitem *hi));
|
||||||
static void list_one_var __ARGS((VAR v, char_u *prefix));
|
static void list_one_var __ARGS((VAR v, char_u *prefix));
|
||||||
static void list_vim_var __ARGS((int i));
|
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));
|
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 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));
|
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 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 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_list __ARGS((char_u *arg, int *var_count, int *semicolon));
|
||||||
static char_u *skip_var_one __ARGS((char_u *arg));
|
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 *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 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));
|
static int check_changedtick __ARGS((char_u *arg));
|
||||||
@@ -1238,8 +1254,13 @@ ex_let(eap)
|
|||||||
/* ":let var1 var2" */
|
/* ":let var1 var2" */
|
||||||
arg = list_arg_vars(eap, arg);
|
arg = list_arg_vars(eap, arg);
|
||||||
else if (!eap->skip)
|
else if (!eap->skip)
|
||||||
|
{
|
||||||
/* ":let" */
|
/* ":let" */
|
||||||
list_all_vars();
|
list_glob_vars();
|
||||||
|
list_buf_vars();
|
||||||
|
list_win_vars();
|
||||||
|
list_vim_vars();
|
||||||
|
}
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
eap->nextcmd = check_nextcmd(arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1433,23 +1454,63 @@ skip_var_one(arg)
|
|||||||
return find_name_end(arg, NULL, NULL, TRUE);
|
return find_name_end(arg, NULL, NULL, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List variables for hashtable "ht" with prefix "prefix".
|
||||||
|
*/
|
||||||
static void
|
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;
|
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)
|
for (i = 0; i < VV_LEN && !got_int; ++i)
|
||||||
if (vimvars[i].tv.v_type == VAR_NUMBER || vimvars[i].vv_str != NULL)
|
if (vimvars[i].tv.v_type == VAR_NUMBER || vimvars[i].vv_str != NULL)
|
||||||
list_vim_var(i);
|
list_vim_var(i);
|
||||||
@@ -1518,6 +1579,20 @@ list_arg_vars(eap, arg)
|
|||||||
*name_end = NUL;
|
*name_end = NUL;
|
||||||
arg_len = (int)(name_end - arg);
|
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);
|
i = find_vim_var(arg, arg_len);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
list_vim_var(i);
|
list_vim_var(i);
|
||||||
@@ -1532,7 +1607,7 @@ list_arg_vars(eap, arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
varp = find_var(arg, FALSE);
|
varp = find_var(arg, NULL);
|
||||||
if (varp == NULL)
|
if (varp == NULL)
|
||||||
{
|
{
|
||||||
/* Skip further arguments but do continue to
|
/* Skip further arguments but do continue to
|
||||||
@@ -1561,6 +1636,7 @@ list_arg_vars(eap, arg)
|
|||||||
list_one_var(varp, (char_u *)"");
|
list_one_var(varp, (char_u *)"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (expr_start != NULL)
|
if (expr_start != NULL)
|
||||||
vim_free(temp_string);
|
vim_free(temp_string);
|
||||||
else
|
else
|
||||||
@@ -1786,7 +1862,7 @@ check_changedtick(arg)
|
|||||||
* wrong; must end in space or cmd separator.
|
* wrong; must end in space or cmd separator.
|
||||||
*
|
*
|
||||||
* Returns a pointer to just after the name, including indexes.
|
* 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"!
|
* Returns NULL for a parsing error. Still need to free items in "lp"!
|
||||||
*/
|
*/
|
||||||
static char_u *
|
static char_u *
|
||||||
@@ -1808,6 +1884,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet)
|
|||||||
listitem *ni;
|
listitem *ni;
|
||||||
char_u *key = NULL;
|
char_u *key = NULL;
|
||||||
int len;
|
int len;
|
||||||
|
hashtable *ht;
|
||||||
|
|
||||||
/* Clear everything in "lp". */
|
/* Clear everything in "lp". */
|
||||||
vim_memset(lp, 0, sizeof(lval));
|
vim_memset(lp, 0, sizeof(lval));
|
||||||
@@ -1855,7 +1932,7 @@ get_lval(name, rettv, lp, unlet, skip, quiet)
|
|||||||
|
|
||||||
cc = *p;
|
cc = *p;
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
v = find_var(lp->ll_name, TRUE);
|
v = find_var(lp->ll_name, &ht);
|
||||||
if (v == NULL && !quiet)
|
if (v == NULL && !quiet)
|
||||||
EMSG2(_(e_undefvar), lp->ll_name);
|
EMSG2(_(e_undefvar), lp->ll_name);
|
||||||
*p = cc;
|
*p = cc;
|
||||||
@@ -2729,14 +2806,25 @@ do_unlet_var(lp, name_end, forceit)
|
|||||||
do_unlet(name)
|
do_unlet(name)
|
||||||
char_u *name;
|
char_u *name;
|
||||||
{
|
{
|
||||||
VAR v;
|
hashtable *ht;
|
||||||
|
hashitem *hi;
|
||||||
|
char_u *varname;
|
||||||
|
|
||||||
v = find_var(name, TRUE);
|
if (name[0] == 'a' && name[1] == ':')
|
||||||
if (v != NULL)
|
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 OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2747,12 +2835,21 @@ do_unlet(name)
|
|||||||
void
|
void
|
||||||
del_menutrans_vars()
|
del_menutrans_vars()
|
||||||
{
|
{
|
||||||
int i;
|
hashitem *hi;
|
||||||
|
int todo;
|
||||||
|
|
||||||
for (i = 0; i < variables.ga_len; ++i)
|
hash_lock(&variables);
|
||||||
if (VAR_ENTRY(i).v_name != NULL
|
todo = variables.ht_used;
|
||||||
&& STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0)
|
for (hi = variables.ht_array; todo > 0 && !got_int; ++hi)
|
||||||
clear_var(&VAR_ENTRY(i));
|
{
|
||||||
|
if (!HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
--todo;
|
||||||
|
if (STRNCMP(HI2VAR(hi)->v_name, "menutrans_", 10) == 0)
|
||||||
|
delete_var(&variables, hi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_unlock(&variables);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2808,47 +2905,44 @@ get_user_var_name(xp, idx)
|
|||||||
expand_T *xp;
|
expand_T *xp;
|
||||||
int idx;
|
int idx;
|
||||||
{
|
{
|
||||||
static int gidx;
|
static int gdone;
|
||||||
static int bidx;
|
static int bdone;
|
||||||
static int widx;
|
static int wdone;
|
||||||
static int vidx;
|
static int vidx;
|
||||||
char_u *name;
|
static hashitem *hi;
|
||||||
|
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
gidx = bidx = widx = vidx = 0;
|
gdone = bdone = wdone = vidx = 0;
|
||||||
if (gidx < variables.ga_len) /* Global variables */
|
if (gdone < variables.ht_used) /* Global variables */
|
||||||
{
|
|
||||||
while ((name = VAR_ENTRY(gidx++).v_name) == NULL
|
|
||||||
&& gidx < variables.ga_len)
|
|
||||||
/* skip */;
|
|
||||||
if (name != NULL)
|
|
||||||
{
|
{
|
||||||
|
if (gdone++ == 0)
|
||||||
|
hi = variables.ht_array;
|
||||||
|
while (HASHITEM_EMPTY(hi))
|
||||||
|
++hi;
|
||||||
if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
|
if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
|
||||||
return cat_prefix_varname('g', name);
|
return cat_prefix_varname('g', hi->hi_key);
|
||||||
else
|
return hi->hi_key;
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
}
|
if (bdone < curbuf->b_vars.ht_used) /* Current buffer variables */
|
||||||
if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
|
|
||||||
{
|
{
|
||||||
while ((name = BVAR_ENTRY(bidx++).v_name) == NULL
|
if (bdone++ == 0)
|
||||||
&& bidx < curbuf->b_vars.ga_len)
|
hi = curbuf->b_vars.ht_array;
|
||||||
/* skip */;
|
while (HASHITEM_EMPTY(hi))
|
||||||
if (name != NULL)
|
++hi;
|
||||||
return cat_prefix_varname('b', name);
|
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";
|
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
|
if (bdone++ == 0)
|
||||||
&& widx < curwin->w_vars.ga_len)
|
hi = curwin->w_vars.ht_array;
|
||||||
/* skip */;
|
while (HASHITEM_EMPTY(hi))
|
||||||
if (name != NULL)
|
++hi;
|
||||||
return cat_prefix_varname('w', name);
|
return cat_prefix_varname('w', hi->hi_key);
|
||||||
}
|
}
|
||||||
if (vidx < VV_LEN) /* Built-in variables */
|
if (vidx < VV_LEN) /* Built-in variables */
|
||||||
return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
|
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}.
|
* Can also be a curly-braces kind of name: {expr}.
|
||||||
*/
|
*/
|
||||||
s = *arg;
|
s = *arg;
|
||||||
len = get_func_len(arg, &alias, evaluate);
|
len = get_name_len(arg, &alias, evaluate);
|
||||||
if (alias != NULL)
|
if (alias != NULL)
|
||||||
s = alias;
|
s = alias;
|
||||||
|
|
||||||
@@ -5010,6 +5104,7 @@ dict_free(d)
|
|||||||
--todo;
|
--todo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hash_clear(&d->dv_hashtable);
|
||||||
vim_free(d);
|
vim_free(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5823,7 +5918,7 @@ deref_func_name(name, lenp)
|
|||||||
|
|
||||||
cc = name[*lenp];
|
cc = name[*lenp];
|
||||||
name[*lenp] = NUL;
|
name[*lenp] = NUL;
|
||||||
v = find_var(name, FALSE);
|
v = find_var(name, NULL);
|
||||||
name[*lenp] = cc;
|
name[*lenp] = cc;
|
||||||
if (v != NULL && v->tv.v_type == VAR_FUNC)
|
if (v != NULL && v->tv.v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
@@ -6705,7 +6800,7 @@ f_confirm(argvars, rettv)
|
|||||||
def = get_tv_number(&argvars[2]);
|
def = get_tv_number(&argvars[2]);
|
||||||
if (argvars[3].v_type != VAR_UNKNOWN)
|
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);
|
c = *get_tv_string_buf(&argvars[3], buf2);
|
||||||
switch (TOUPPER_ASC(c))
|
switch (TOUPPER_ASC(c))
|
||||||
{
|
{
|
||||||
@@ -7429,6 +7524,7 @@ filter_map(argvars, rettv, map)
|
|||||||
listitem *li, *nli;
|
listitem *li, *nli;
|
||||||
listvar *l = NULL;
|
listvar *l = NULL;
|
||||||
dictitem *di;
|
dictitem *di;
|
||||||
|
hashtable *ht;
|
||||||
hashitem *hi;
|
hashitem *hi;
|
||||||
dictvar *d = NULL;
|
dictvar *d = NULL;
|
||||||
typeval save_val;
|
typeval save_val;
|
||||||
@@ -7461,8 +7557,10 @@ filter_map(argvars, rettv, map)
|
|||||||
save_key = vimvars[VV_KEY].tv;
|
save_key = vimvars[VV_KEY].tv;
|
||||||
vimvars[VV_KEY].tv.v_type = VAR_STRING;
|
vimvars[VV_KEY].tv.v_type = VAR_STRING;
|
||||||
|
|
||||||
todo = d->dv_hashtable.ht_used;
|
ht = &d->dv_hashtable;
|
||||||
for (hi = d->dv_hashtable.ht_array; todo > 0; ++hi)
|
hash_lock(ht);
|
||||||
|
todo = ht->ht_used;
|
||||||
|
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||||
{
|
{
|
||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
{
|
{
|
||||||
@@ -7476,6 +7574,7 @@ filter_map(argvars, rettv, map)
|
|||||||
clear_tv(&vimvars[VV_KEY].tv);
|
clear_tv(&vimvars[VV_KEY].tv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hash_unlock(ht);
|
||||||
|
|
||||||
clear_tv(&vimvars[VV_KEY].tv);
|
clear_tv(&vimvars[VV_KEY].tv);
|
||||||
vimvars[VV_KEY].tv = save_key;
|
vimvars[VV_KEY].tv = save_key;
|
||||||
@@ -7799,6 +7898,7 @@ f_function(argvars, rettv)
|
|||||||
{
|
{
|
||||||
char_u *s;
|
char_u *s;
|
||||||
|
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
s = get_tv_string(&argvars[0]);
|
s = get_tv_string(&argvars[0]);
|
||||||
if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
|
if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
|
||||||
EMSG2(_(e_invarg2), s);
|
EMSG2(_(e_invarg2), s);
|
||||||
@@ -7893,7 +7993,7 @@ f_getbufvar(argvars, rettv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* look up the variable */
|
/* 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)
|
if (v != NULL)
|
||||||
copy_tv(&v->tv, rettv);
|
copy_tv(&v->tv, rettv);
|
||||||
}
|
}
|
||||||
@@ -8417,7 +8517,7 @@ f_getwinvar(argvars, rettv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* look up the variable */
|
/* 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)
|
if (v != NULL)
|
||||||
copy_tv(&v->tv, rettv);
|
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.
|
* "arg" is advanced to the first non-white character after the name.
|
||||||
* Return 0 if something is wrong.
|
* Return 0 if something is wrong.
|
||||||
* If the name contains 'magic' {}'s, expand them and return the
|
* If the name contains 'magic' {}'s, expand them and return the
|
||||||
* expanded name in an allocated string via 'alias' - caller must free.
|
* expanded name in an allocated string via 'alias' - caller must free.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_func_len(arg, alias, evaluate)
|
get_name_len(arg, alias, evaluate)
|
||||||
char_u **arg;
|
char_u **arg;
|
||||||
char_u **alias;
|
char_u **alias;
|
||||||
int evaluate;
|
int evaluate;
|
||||||
@@ -13089,16 +13190,14 @@ get_var_tv(name, len, rettv)
|
|||||||
* Check for built-in v: variables.
|
* Check for built-in v: variables.
|
||||||
*/
|
*/
|
||||||
else if ((i = find_vim_var(name, len)) >= 0)
|
else if ((i = find_vim_var(name, len)) >= 0)
|
||||||
{
|
|
||||||
tv = &vimvars[i].tv;
|
tv = &vimvars[i].tv;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for user-defined variables.
|
* Check for user-defined variables.
|
||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v = find_var(name, FALSE);
|
v = find_var(name, NULL);
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
tv = &v->tv;
|
tv = &v->tv;
|
||||||
}
|
}
|
||||||
@@ -13287,8 +13386,8 @@ get_tv_lnum(argvars)
|
|||||||
/*
|
/*
|
||||||
* Get the string value of a variable.
|
* Get the string value of a variable.
|
||||||
* If it is a Number variable, the number is converted into a string.
|
* 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_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
|
||||||
* get_var_string_buf() uses a given buffer.
|
* get_tv_string_buf() uses a given buffer.
|
||||||
* If the String variable has never been set, return an empty string.
|
* If the String variable has never been set, return an empty string.
|
||||||
* Never returns NULL;
|
* Never returns NULL;
|
||||||
*/
|
*/
|
||||||
@@ -13335,22 +13434,24 @@ get_tv_string_buf(varp, buf)
|
|||||||
* Find variable "name" in the list of variables.
|
* Find variable "name" in the list of variables.
|
||||||
* Return a pointer to it if found, NULL if not found.
|
* Return a pointer to it if found, NULL if not found.
|
||||||
* Careful: "a:0" variables don't have a name.
|
* 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
|
static VAR
|
||||||
find_var(name, writing)
|
find_var(name, htp)
|
||||||
char_u *name;
|
char_u *name;
|
||||||
int writing;
|
hashtable **htp;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char_u *varname;
|
char_u *varname;
|
||||||
garray_T *gap;
|
hashtable *ht;
|
||||||
|
|
||||||
if (name[0] == 'a' && name[1] == ':')
|
if (name[0] == 'a' && name[1] == ':')
|
||||||
{
|
{
|
||||||
/* Function arguments "a:".
|
/* Function arguments "a:".
|
||||||
* NOTE: We use a typecast, because function arguments don't have a
|
* NOTE: We use a typecast, because function arguments don't have a
|
||||||
* name. The caller must not try to access the name! */
|
* name. The caller must not try to access the name! */
|
||||||
if (writing)
|
if (htp != NULL)
|
||||||
{
|
{
|
||||||
EMSG2(_(e_readonlyvar), name);
|
EMSG2(_(e_readonlyvar), name);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -13379,33 +13480,37 @@ find_var(name, writing)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gap = find_var_ga(name, &varname);
|
ht = find_var_ht(name, &varname);
|
||||||
if (gap == NULL)
|
if (htp != NULL)
|
||||||
|
*htp = ht;
|
||||||
|
if (ht == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return find_var_in_ga(gap, varname);
|
return find_var_in_ht(ht, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 *
|
static VAR
|
||||||
find_var_ga(name, varname)
|
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 *name;
|
||||||
char_u **varname;
|
char_u **varname;
|
||||||
{
|
{
|
||||||
@@ -13444,22 +13549,35 @@ get_var_value(name)
|
|||||||
{
|
{
|
||||||
VAR v;
|
VAR v;
|
||||||
|
|
||||||
v = find_var(name, FALSE);
|
v = find_var(name, NULL);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return 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.
|
* sourcing this script and when executing functions defined in the script.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
new_script_vars(id)
|
new_script_vars(id)
|
||||||
scid_T id;
|
scid_T id;
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
hashtable *ht;
|
||||||
|
|
||||||
if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
|
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)
|
while (ga_scripts.ga_len < id)
|
||||||
{
|
{
|
||||||
vars_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
|
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
|
void
|
||||||
vars_init(gap)
|
vars_init(ht)
|
||||||
garray_T *gap;
|
hashtable *ht;
|
||||||
{
|
{
|
||||||
ga_init2(gap, (int)sizeof(var), 4);
|
hash_init(ht);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up a list of internal variables.
|
* Clean up a list of internal variables.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vars_clear(gap)
|
vars_clear(ht)
|
||||||
garray_T *gap;
|
hashtable *ht;
|
||||||
{
|
{
|
||||||
int i;
|
int todo;
|
||||||
|
hashitem *hi;
|
||||||
|
VAR v;
|
||||||
|
|
||||||
for (i = gap->ga_len; --i >= 0; )
|
todo = ht->ht_used;
|
||||||
clear_var(&VAR_GAP_ENTRY(i, gap));
|
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||||
ga_clear(gap);
|
{
|
||||||
|
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
|
static void
|
||||||
clear_var(v)
|
delete_var(ht, hi)
|
||||||
VAR v;
|
hashtable *ht;
|
||||||
|
hashitem *hi;
|
||||||
{
|
{
|
||||||
vim_free(v->v_name);
|
VAR v = HI2VAR(hi);
|
||||||
v->v_name = NULL;
|
|
||||||
|
hash_remove(ht, hi);
|
||||||
clear_tv(&v->tv);
|
clear_tv(&v->tv);
|
||||||
|
vim_free(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -13587,7 +13727,7 @@ set_var(name, tv, copy)
|
|||||||
int i;
|
int i;
|
||||||
VAR v;
|
VAR v;
|
||||||
char_u *varname;
|
char_u *varname;
|
||||||
garray_T *gap;
|
hashtable *ht;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle setting internal v: variables.
|
* Handle setting internal v: variables.
|
||||||
@@ -13635,8 +13775,21 @@ set_var(name, tv, copy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v = find_var(name, TRUE);
|
if (name[0] == 'a' && name[1] == ':')
|
||||||
if (v != NULL) /* existing variable, only need to free string */
|
{
|
||||||
|
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
|
if (v->tv.v_type != tv->v_type
|
||||||
&& !((v->tv.v_type == VAR_STRING
|
&& !((v->tv.v_type == VAR_STRING
|
||||||
@@ -13651,29 +13804,17 @@ set_var(name, tv, copy)
|
|||||||
}
|
}
|
||||||
else /* add a new variable */
|
else /* add a new variable */
|
||||||
{
|
{
|
||||||
gap = find_var_ga(name, &varname);
|
v = (VAR)alloc((unsigned)(sizeof(var) + STRLEN(varname)));
|
||||||
if (gap == NULL) /* illegal name */
|
if (v == NULL)
|
||||||
{
|
|
||||||
EMSG2(_("E461: Illegal variable name: %s"), name);
|
|
||||||
return;
|
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)
|
if (copy || tv->v_type == VAR_NUMBER)
|
||||||
copy_tv(tv, &v->tv);
|
copy_tv(tv, &v->tv);
|
||||||
else
|
else
|
||||||
@@ -14358,7 +14499,7 @@ ex_function(eap)
|
|||||||
*/
|
*/
|
||||||
if (fudi.fd_dict == NULL)
|
if (fudi.fd_dict == NULL)
|
||||||
{
|
{
|
||||||
v = find_var(name, FALSE);
|
v = find_var(name, NULL);
|
||||||
if (v != NULL && v->tv.v_type == VAR_FUNC)
|
if (v != NULL && v->tv.v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
EMSG2(_("E707: Function name conflicts with variable: %s"), name);
|
EMSG2(_("E707: Function name conflicts with variable: %s"), name);
|
||||||
@@ -14463,6 +14604,7 @@ ret_free:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a function name, translating "<SID>" and "<SNR>".
|
* 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.
|
* Returns the function name in allocated memory, or NULL for failure.
|
||||||
* flags:
|
* flags:
|
||||||
* TFN_INT: internal function name OK
|
* TFN_INT: internal function name OK
|
||||||
@@ -14486,11 +14628,22 @@ trans_function_name(pp, skip, flags, fdp)
|
|||||||
|
|
||||||
if (fdp != NULL)
|
if (fdp != NULL)
|
||||||
vim_memset(fdp, 0, sizeof(funcdict));
|
vim_memset(fdp, 0, sizeof(funcdict));
|
||||||
|
|
||||||
/* A name starting with "<SID>" or "<SNR>" is local to a script. */
|
|
||||||
start = *pp;
|
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);
|
lead = eval_fname_script(start);
|
||||||
if (lead > 0)
|
if (lead > 2)
|
||||||
start += lead;
|
start += lead;
|
||||||
|
|
||||||
end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET);
|
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"));
|
EMSG(_("E129: Function name required"));
|
||||||
goto theend;
|
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
|
* 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)
|
if (lv.ll_exp_name != NULL)
|
||||||
len = STRLEN(lv.ll_exp_name);
|
len = STRLEN(lv.ll_exp_name);
|
||||||
else
|
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.
|
* Copy the function name to allocated memory.
|
||||||
@@ -14590,7 +14747,7 @@ trans_function_name(pp, skip, flags, fdp)
|
|||||||
name[0] = K_SPECIAL;
|
name[0] = K_SPECIAL;
|
||||||
name[1] = KS_EXTRA;
|
name[1] = KS_EXTRA;
|
||||||
name[2] = (int)KE_SNR;
|
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);
|
STRCPY(name + 3, sid_buf);
|
||||||
}
|
}
|
||||||
mch_memmove(name + lead, lv.ll_name, (size_t)len);
|
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.level = ex_nesting_level;
|
||||||
fc.a0_var.tv.v_type = VAR_NUMBER;
|
fc.a0_var.tv.v_type = VAR_NUMBER;
|
||||||
fc.a0_var.tv.vval.v_number = argcount - fp->args.ga_len;
|
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;
|
current_funccal = &fc;
|
||||||
fc.firstline.tv.v_type = VAR_NUMBER;
|
fc.firstline.tv.v_type = VAR_NUMBER;
|
||||||
fc.firstline.tv.vval.v_number = firstline;
|
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.v_type = VAR_NUMBER;
|
||||||
fc.lastline.tv.vval.v_number = lastline;
|
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. */
|
/* Check if this function has a breakpoint. */
|
||||||
fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
|
fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
|
||||||
fc.dbg_tick = debug_tick;
|
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 != NULL)
|
||||||
if ((v->v_name = vim_strsave((char_u *)"self")) != 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.v_type = VAR_DICT;
|
||||||
v->tv.vval.v_dict = selfdict;
|
v->tv.vval.v_dict = selfdict;
|
||||||
++selfdict->dv_refcount;
|
++selfdict->dv_refcount;
|
||||||
@@ -15412,9 +15569,9 @@ read_viminfo_varlist(virp, writing)
|
|||||||
write_viminfo_varlist(fp)
|
write_viminfo_varlist(fp)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
{
|
{
|
||||||
garray_T *gap = &variables; /* global variable */
|
hashitem *hi;
|
||||||
VAR this_var;
|
VAR this_var;
|
||||||
int i;
|
int todo;
|
||||||
char *s;
|
char *s;
|
||||||
char_u *tofree;
|
char_u *tofree;
|
||||||
char_u numbuf[NUMBUFLEN];
|
char_u numbuf[NUMBUFLEN];
|
||||||
@@ -15423,11 +15580,15 @@ write_viminfo_varlist(fp)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(fp, _("\n# global variables:\n"));
|
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 (!HASHITEM_EMPTY(hi))
|
||||||
if (this_var->v_name != NULL
|
{
|
||||||
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
|
--todo;
|
||||||
|
this_var = HI2VAR(hi);
|
||||||
|
if (var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
|
||||||
{
|
{
|
||||||
switch (this_var->tv.v_type)
|
switch (this_var->tv.v_type)
|
||||||
{
|
{
|
||||||
@@ -15442,6 +15603,7 @@ write_viminfo_varlist(fp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEAT_SESSION) || defined(PROTO)
|
#if defined(FEAT_SESSION) || defined(PROTO)
|
||||||
@@ -15449,25 +15611,28 @@ write_viminfo_varlist(fp)
|
|||||||
store_session_globals(fd)
|
store_session_globals(fd)
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
{
|
{
|
||||||
garray_T *gap = &variables; /* global variable */
|
hashitem *hi;
|
||||||
VAR this_var;
|
VAR this_var;
|
||||||
int i;
|
int todo;
|
||||||
char_u *p, *t;
|
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 (!HASHITEM_EMPTY(hi))
|
||||||
if (this_var->v_name != NULL
|
{
|
||||||
&& (this_var->tv.v_type == VAR_NUMBER
|
--todo;
|
||||||
|
this_var = HI2VAR(hi);
|
||||||
|
if ((this_var->tv.v_type == VAR_NUMBER
|
||||||
|| this_var->tv.v_type == VAR_STRING)
|
|| this_var->tv.v_type == VAR_STRING)
|
||||||
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
|
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
|
||||||
{
|
{
|
||||||
/* Escape special characters with a backslash. Turn a LF and
|
/* Escape special characters with a backslash. Turn a LF and
|
||||||
* CR into \n and \r. */
|
* 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");
|
(char_u *)"\\\"\n\r");
|
||||||
if (p == NULL) /* out of memory */
|
if (p == NULL) /* out of memory */
|
||||||
continue;
|
break;
|
||||||
for (t = p; *t != NUL; ++t)
|
for (t = p; *t != NUL; ++t)
|
||||||
if (*t == '\n')
|
if (*t == '\n')
|
||||||
*t = 'n';
|
*t = 'n';
|
||||||
@@ -15486,6 +15651,7 @@ store_session_globals(fd)
|
|||||||
vim_free(p);
|
vim_free(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user