mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
updated for version 7.3.603
Problem: It is possible to add replace builtin functions by calling extend() on g:. Solution: Add a flag to a dict to indicate it is a scope. Check for existing functions. (ZyX)
This commit is contained in:
@@ -1747,7 +1747,8 @@ buflist_new(ffname, sfname, lnum, flags)
|
|||||||
buf->b_wininfo->wi_win = curwin;
|
buf->b_wininfo->wi_win = curwin;
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */
|
/* init b: variables */
|
||||||
|
init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
hash_init(&buf->b_s.b_keywtab);
|
hash_init(&buf->b_s.b_keywtab);
|
||||||
|
54
src/eval.c
54
src/eval.c
@@ -850,8 +850,8 @@ eval_init()
|
|||||||
int i;
|
int i;
|
||||||
struct vimvar *p;
|
struct vimvar *p;
|
||||||
|
|
||||||
init_var_dict(&globvardict, &globvars_var);
|
init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
|
||||||
init_var_dict(&vimvardict, &vimvars_var);
|
init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
|
||||||
vimvardict.dv_lock = VAR_FIXED;
|
vimvardict.dv_lock = VAR_FIXED;
|
||||||
hash_init(&compat_hashtab);
|
hash_init(&compat_hashtab);
|
||||||
hash_init(&func_hashtab);
|
hash_init(&func_hashtab);
|
||||||
@@ -2725,14 +2725,26 @@ get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
|
|||||||
lp->ll_dict = lp->ll_tv->vval.v_dict;
|
lp->ll_dict = lp->ll_tv->vval.v_dict;
|
||||||
lp->ll_di = dict_find(lp->ll_dict, key, len);
|
lp->ll_di = dict_find(lp->ll_dict, key, len);
|
||||||
|
|
||||||
/* When assigning to g: check that a function and variable name is
|
/* When assigning to a scope dictionary check that a function and
|
||||||
* valid. */
|
* variable name is valid (only variable name unless it is l: or
|
||||||
if (rettv != NULL && lp->ll_dict == &globvardict)
|
* g: dictionary). Disallow overwriting a builtin function. */
|
||||||
|
if (rettv != NULL && lp->ll_dict->dv_scope != 0)
|
||||||
{
|
{
|
||||||
if (rettv->v_type == VAR_FUNC
|
int prevval;
|
||||||
|
int wrong;
|
||||||
|
|
||||||
|
if (len != -1)
|
||||||
|
{
|
||||||
|
prevval = key[len];
|
||||||
|
key[len] = NUL;
|
||||||
|
}
|
||||||
|
wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
|
||||||
|
&& rettv->v_type == VAR_FUNC
|
||||||
&& var_check_func_name(key, lp->ll_di == NULL))
|
&& var_check_func_name(key, lp->ll_di == NULL))
|
||||||
return NULL;
|
|| !valid_varname(key);
|
||||||
if (!valid_varname(key))
|
if (len != -1)
|
||||||
|
key[len] = prevval;
|
||||||
|
if (wrong)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6951,7 +6963,7 @@ dict_alloc()
|
|||||||
d = (dict_T *)alloc(sizeof(dict_T));
|
d = (dict_T *)alloc(sizeof(dict_T));
|
||||||
if (d != NULL)
|
if (d != NULL)
|
||||||
{
|
{
|
||||||
/* Add the list to the list of dicts for garbage collection. */
|
/* Add the dict to the list of dicts for garbage collection. */
|
||||||
if (first_dict != NULL)
|
if (first_dict != NULL)
|
||||||
first_dict->dv_used_prev = d;
|
first_dict->dv_used_prev = d;
|
||||||
d->dv_used_next = first_dict;
|
d->dv_used_next = first_dict;
|
||||||
@@ -6960,6 +6972,7 @@ dict_alloc()
|
|||||||
|
|
||||||
hash_init(&d->dv_hashtab);
|
hash_init(&d->dv_hashtab);
|
||||||
d->dv_lock = 0;
|
d->dv_lock = 0;
|
||||||
|
d->dv_scope = 0;
|
||||||
d->dv_refcount = 0;
|
d->dv_refcount = 0;
|
||||||
d->dv_copyID = 0;
|
d->dv_copyID = 0;
|
||||||
}
|
}
|
||||||
@@ -10203,6 +10216,19 @@ f_extend(argvars, rettv)
|
|||||||
{
|
{
|
||||||
--todo;
|
--todo;
|
||||||
di1 = dict_find(d1, hi2->hi_key, -1);
|
di1 = dict_find(d1, hi2->hi_key, -1);
|
||||||
|
if (d1->dv_scope != 0)
|
||||||
|
{
|
||||||
|
/* Disallow replacing a builtin function in l: and g:.
|
||||||
|
* Check the key to be valid when adding to any
|
||||||
|
* scope. */
|
||||||
|
if (d1->dv_scope == VAR_DEF_SCOPE
|
||||||
|
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
|
||||||
|
&& var_check_func_name(hi2->hi_key,
|
||||||
|
di1 == NULL))
|
||||||
|
break;
|
||||||
|
if (!valid_varname(hi2->hi_key))
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (di1 == NULL)
|
if (di1 == NULL)
|
||||||
{
|
{
|
||||||
di1 = dictitem_copy(HI2DI(hi2));
|
di1 = dictitem_copy(HI2DI(hi2));
|
||||||
@@ -20027,7 +20053,7 @@ new_script_vars(id)
|
|||||||
{
|
{
|
||||||
sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
|
sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
|
||||||
(scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
|
(scriptvar_T *)alloc_clear(sizeof(scriptvar_T));
|
||||||
init_var_dict(&sv->sv_dict, &sv->sv_var);
|
init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
|
||||||
++ga_scripts.ga_len;
|
++ga_scripts.ga_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20038,12 +20064,14 @@ new_script_vars(id)
|
|||||||
* point to it.
|
* point to it.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
init_var_dict(dict, dict_var)
|
init_var_dict(dict, dict_var, scope)
|
||||||
dict_T *dict;
|
dict_T *dict;
|
||||||
dictitem_T *dict_var;
|
dictitem_T *dict_var;
|
||||||
|
int scope;
|
||||||
{
|
{
|
||||||
hash_init(&dict->dv_hashtab);
|
hash_init(&dict->dv_hashtab);
|
||||||
dict->dv_lock = 0;
|
dict->dv_lock = 0;
|
||||||
|
dict->dv_scope = scope;
|
||||||
dict->dv_refcount = DO_NOT_FREE_CNT;
|
dict->dv_refcount = DO_NOT_FREE_CNT;
|
||||||
dict->dv_copyID = 0;
|
dict->dv_copyID = 0;
|
||||||
dict_var->di_tv.vval.v_dict = dict;
|
dict_var->di_tv.vval.v_dict = dict;
|
||||||
@@ -22304,7 +22332,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
/*
|
/*
|
||||||
* Init l: variables.
|
* Init l: variables.
|
||||||
*/
|
*/
|
||||||
init_var_dict(&fc->l_vars, &fc->l_vars_var);
|
init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE);
|
||||||
if (selfdict != NULL)
|
if (selfdict != NULL)
|
||||||
{
|
{
|
||||||
/* Set l:self to "selfdict". Use "name" to avoid a warning from
|
/* Set l:self to "selfdict". Use "name" to avoid a warning from
|
||||||
@@ -22325,7 +22353,7 @@ call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
|
|||||||
* Set a:0 to "argcount".
|
* Set a:0 to "argcount".
|
||||||
* Set a:000 to a list with room for the "..." arguments.
|
* Set a:000 to a list with room for the "..." arguments.
|
||||||
*/
|
*/
|
||||||
init_var_dict(&fc->l_avars, &fc->l_avars_var);
|
init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE);
|
||||||
add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
|
add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0",
|
||||||
(varnumber_T)(argcount - fp->uf_args.ga_len));
|
(varnumber_T)(argcount - fp->uf_args.ga_len));
|
||||||
/* Use "name" to avoid a warning from some compiler that checks the
|
/* Use "name" to avoid a warning from some compiler that checks the
|
||||||
|
@@ -93,7 +93,7 @@ long get_tv_number_chk __ARGS((typval_T *varp, int *denote));
|
|||||||
char_u *get_tv_string_chk __ARGS((typval_T *varp));
|
char_u *get_tv_string_chk __ARGS((typval_T *varp));
|
||||||
char_u *get_var_value __ARGS((char_u *name));
|
char_u *get_var_value __ARGS((char_u *name));
|
||||||
void new_script_vars __ARGS((scid_T id));
|
void new_script_vars __ARGS((scid_T id));
|
||||||
void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var));
|
void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope));
|
||||||
void vars_clear __ARGS((hashtab_T *ht));
|
void vars_clear __ARGS((hashtab_T *ht));
|
||||||
void copy_tv __ARGS((typval_T *from, typval_T *to));
|
void copy_tv __ARGS((typval_T *from, typval_T *to));
|
||||||
void ex_echo __ARGS((exarg_T *eap));
|
void ex_echo __ARGS((exarg_T *eap));
|
||||||
|
@@ -1106,6 +1106,11 @@ typedef struct
|
|||||||
#define VAR_DICT 5 /* "v_dict" is used */
|
#define VAR_DICT 5 /* "v_dict" is used */
|
||||||
#define VAR_FLOAT 6 /* "v_float" is used */
|
#define VAR_FLOAT 6 /* "v_float" is used */
|
||||||
|
|
||||||
|
/* Values for "dv_scope". */
|
||||||
|
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||||
|
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||||
|
allowed to mask existing functions */
|
||||||
|
|
||||||
/* Values for "v_lock". */
|
/* Values for "v_lock". */
|
||||||
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
|
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
|
||||||
#define VAR_FIXED 2 /* locked forever */
|
#define VAR_FIXED 2 /* locked forever */
|
||||||
@@ -1181,6 +1186,7 @@ struct dictvar_S
|
|||||||
int dv_copyID; /* ID used by deepcopy() */
|
int dv_copyID; /* ID used by deepcopy() */
|
||||||
dict_T *dv_copydict; /* copied dict used by deepcopy() */
|
dict_T *dv_copydict; /* copied dict used by deepcopy() */
|
||||||
char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
|
char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
|
||||||
|
char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */
|
||||||
dict_T *dv_used_next; /* next dict in used dicts list */
|
dict_T *dv_used_next; /* next dict in used dicts list */
|
||||||
dict_T *dv_used_prev; /* previous dict in used dicts list */
|
dict_T *dv_used_prev; /* previous dict in used dicts list */
|
||||||
};
|
};
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
Test for user functions.
|
Test for user functions.
|
||||||
Also test an <expr> mapping calling a function.
|
Also test an <expr> mapping calling a function.
|
||||||
|
Also test that a builtin function cannot be replaced.
|
||||||
|
|
||||||
STARTTEST
|
STARTTEST
|
||||||
:so small.vim
|
:so small.vim
|
||||||
@@ -58,7 +59,10 @@ XX+-XX
|
|||||||
---*---
|
---*---
|
||||||
(one
|
(one
|
||||||
(two
|
(two
|
||||||
[(one again:$-5,$w! test.out
|
[(one again:call append(line('$'), max([1, 2, 3]))
|
||||||
|
:call extend(g:, {'max': function('min')})
|
||||||
|
:call append(line('$'), max([1, 2, 3]))
|
||||||
|
:$-7,$w! test.out
|
||||||
:delfunc Table
|
:delfunc Table
|
||||||
:delfunc Compute
|
:delfunc Compute
|
||||||
:delfunc Expr1
|
:delfunc Expr1
|
||||||
|
@@ -4,3 +4,5 @@ XX111-XX
|
|||||||
1. one
|
1. one
|
||||||
2. two
|
2. two
|
||||||
1. one again
|
1. one again
|
||||||
|
3
|
||||||
|
3
|
||||||
|
@@ -714,6 +714,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
603,
|
||||||
/**/
|
/**/
|
||||||
602,
|
602,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -3468,7 +3468,7 @@ alloc_tabpage()
|
|||||||
# endif
|
# endif
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
/* init t: variables */
|
/* init t: variables */
|
||||||
init_var_dict(&tp->tp_vars, &tp->tp_winvar);
|
init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
|
||||||
#endif
|
#endif
|
||||||
tp->tp_ch_used = p_ch;
|
tp->tp_ch_used = p_ch;
|
||||||
}
|
}
|
||||||
@@ -4410,7 +4410,7 @@ win_alloc(after, hidden)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
/* init w: variables */
|
/* init w: variables */
|
||||||
init_var_dict(&new_wp->w_vars, &new_wp->w_winvar);
|
init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
foldInitWin(new_wp);
|
foldInitWin(new_wp);
|
||||||
|
Reference in New Issue
Block a user