int i;
struct vimvar *p;
- init_var_dict(&globvardict, &globvars_var);
- init_var_dict(&vimvardict, &vimvars_var);
+ init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
+ init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
vimvardict.dv_lock = VAR_FIXED;
hash_init(&compat_hashtab);
hash_init(&func_hashtab);
lp->ll_dict = lp->ll_tv->vval.v_dict;
lp->ll_di = dict_find(lp->ll_dict, key, len);
- /* When assigning to g: check that a function and variable name is
- * valid. */
- if (rettv != NULL && lp->ll_dict == &globvardict)
+ /* When assigning to a scope dictionary check that a function and
+ * variable name is valid (only variable name unless it is l: or
+ * 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))
- return NULL;
- if (!valid_varname(key))
+ || !valid_varname(key);
+ if (len != -1)
+ key[len] = prevval;
+ if (wrong)
return NULL;
}
d = (dict_T *)alloc(sizeof(dict_T));
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)
first_dict->dv_used_prev = d;
d->dv_used_next = first_dict;
hash_init(&d->dv_hashtab);
d->dv_lock = 0;
+ d->dv_scope = 0;
d->dv_refcount = 0;
d->dv_copyID = 0;
}
{
--todo;
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)
{
di1 = dictitem_copy(HI2DI(hi2));
{
sv = SCRIPT_SV(ga_scripts.ga_len + 1) =
(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;
}
}
* point to it.
*/
void
-init_var_dict(dict, dict_var)
+init_var_dict(dict, dict_var, scope)
dict_T *dict;
dictitem_T *dict_var;
+ int scope;
{
hash_init(&dict->dv_hashtab);
dict->dv_lock = 0;
+ dict->dv_scope = scope;
dict->dv_refcount = DO_NOT_FREE_CNT;
dict->dv_copyID = 0;
dict_var->di_tv.vval.v_dict = dict;
/*
* 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)
{
/* Set l:self to "selfdict". Use "name" to avoid a warning from
* Set a:0 to "argcount".
* 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",
(varnumber_T)(argcount - fp->uf_args.ga_len));
/* Use "name" to avoid a warning from some compiler that checks the
#define VAR_DICT 5 /* "v_dict" 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". */
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
#define VAR_FIXED 2 /* locked forever */
int dv_copyID; /* ID used by deepcopy() */
dict_T *dv_copydict; /* copied dict used by deepcopy() */
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_prev; /* previous dict in used dicts list */
};