Karsten Hopp bc8f15
To: vim_dev@googlegroups.com
Karsten Hopp bc8f15
Subject: Patch 7.4.698
Karsten Hopp bc8f15
Fcc: outbox
Karsten Hopp bc8f15
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp bc8f15
Mime-Version: 1.0
Karsten Hopp bc8f15
Content-Type: text/plain; charset=UTF-8
Karsten Hopp bc8f15
Content-Transfer-Encoding: 8bit
Karsten Hopp bc8f15
------------
Karsten Hopp bc8f15
Karsten Hopp bc8f15
Patch 7.4.698
Karsten Hopp bc8f15
Problem:    Various problems with locked and fixed lists and dictionaries.
Karsten Hopp bc8f15
Solution:   Disallow changing locked items, fix a crash, add tests. (Olaf
Karsten Hopp bc8f15
            Dabrunz)
Karsten Hopp bc8f15
Files:      src/structs.h, src/eval.c, src/testdir/test55.in,
Karsten Hopp bc8f15
            src/testdir/test55.ok
Karsten Hopp bc8f15
Karsten Hopp bc8f15
Karsten Hopp bc8f15
*** ../vim-7.4.697/src/structs.h	2015-03-20 18:11:44.971196311 +0100
Karsten Hopp bc8f15
--- src/structs.h	2015-04-13 16:06:51.999274650 +0200
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 1203,1212 ****
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  typedef struct dictitem_S dictitem_T;
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
! #define DI_FLAGS_RO	1 /* "di_flags" value: read-only variable */
Karsten Hopp bc8f15
! #define DI_FLAGS_RO_SBX 2 /* "di_flags" value: read-only in the sandbox */
Karsten Hopp bc8f15
! #define DI_FLAGS_FIX	4 /* "di_flags" value: fixed variable, not allocated */
Karsten Hopp bc8f15
! #define DI_FLAGS_LOCK	8 /* "di_flags" value: locked variable */
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  /*
Karsten Hopp bc8f15
   * Structure to hold info about a Dictionary.
Karsten Hopp bc8f15
--- 1203,1213 ----
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  typedef struct dictitem_S dictitem_T;
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
! #define DI_FLAGS_RO	1  /* "di_flags" value: read-only variable */
Karsten Hopp bc8f15
! #define DI_FLAGS_RO_SBX 2  /* "di_flags" value: read-only in the sandbox */
Karsten Hopp bc8f15
! #define DI_FLAGS_FIX	4  /* "di_flags" value: fixed: no :unlet or remove() */
Karsten Hopp bc8f15
! #define DI_FLAGS_LOCK	8  /* "di_flags" value: locked variable */
Karsten Hopp bc8f15
! #define DI_FLAGS_ALLOC	16 /* "di_flags" value: separately allocated */
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  /*
Karsten Hopp bc8f15
   * Structure to hold info about a Dictionary.
Karsten Hopp bc8f15
*** ../vim-7.4.697/src/eval.c	2015-03-31 13:33:00.793524956 +0200
Karsten Hopp bc8f15
--- src/eval.c	2015-04-13 16:16:12.045295929 +0200
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 3658,3664 ****
Karsten Hopp bc8f15
  	    ret = FAIL;
Karsten Hopp bc8f15
  	*name_end = cc;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
!     else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
Karsten Hopp bc8f15
  	return FAIL;
Karsten Hopp bc8f15
      else if (lp->ll_range)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
--- 3658,3667 ----
Karsten Hopp bc8f15
  	    ret = FAIL;
Karsten Hopp bc8f15
  	*name_end = cc;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
!     else if ((lp->ll_list != NULL
Karsten Hopp bc8f15
! 			  && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name))
Karsten Hopp bc8f15
! 	    || (lp->ll_dict != NULL
Karsten Hopp bc8f15
! 			 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name)))
Karsten Hopp bc8f15
  	return FAIL;
Karsten Hopp bc8f15
      else if (lp->ll_range)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 3709,3725 ****
Karsten Hopp bc8f15
      hashtab_T	*ht;
Karsten Hopp bc8f15
      hashitem_T	*hi;
Karsten Hopp bc8f15
      char_u	*varname;
Karsten Hopp bc8f15
      dictitem_T	*di;
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
      ht = find_var_ht(name, &varname);
Karsten Hopp bc8f15
      if (ht != NULL && *varname != NUL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	hi = hash_find(ht, varname);
Karsten Hopp bc8f15
  	if (!HASHITEM_EMPTY(hi))
Karsten Hopp bc8f15
  	{
Karsten Hopp bc8f15
  	    di = HI2DI(hi);
Karsten Hopp bc8f15
  	    if (var_check_fixed(di->di_flags, name)
Karsten Hopp bc8f15
! 		    || var_check_ro(di->di_flags, name))
Karsten Hopp bc8f15
  		return FAIL;
Karsten Hopp bc8f15
  	    delete_var(ht, hi);
Karsten Hopp bc8f15
  	    return OK;
Karsten Hopp bc8f15
--- 3712,3740 ----
Karsten Hopp bc8f15
      hashtab_T	*ht;
Karsten Hopp bc8f15
      hashitem_T	*hi;
Karsten Hopp bc8f15
      char_u	*varname;
Karsten Hopp bc8f15
+     dict_T	*d;
Karsten Hopp bc8f15
      dictitem_T	*di;
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
      ht = find_var_ht(name, &varname);
Karsten Hopp bc8f15
      if (ht != NULL && *varname != NUL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
+ 	if (ht == &globvarht)
Karsten Hopp bc8f15
+ 	    d = &globvardict;
Karsten Hopp bc8f15
+ 	else if (current_funccal != NULL
Karsten Hopp bc8f15
+ 				 && ht == &current_funccal->l_vars.dv_hashtab)
Karsten Hopp bc8f15
+ 	    d = &current_funccal->l_vars;
Karsten Hopp bc8f15
+ 	else
Karsten Hopp bc8f15
+ 	{
Karsten Hopp bc8f15
+ 	    di = find_var_in_ht(ht, *name, (char_u *)"", FALSE);
Karsten Hopp bc8f15
+ 	    d = di->di_tv.vval.v_dict;
Karsten Hopp bc8f15
+ 	}
Karsten Hopp bc8f15
  	hi = hash_find(ht, varname);
Karsten Hopp bc8f15
  	if (!HASHITEM_EMPTY(hi))
Karsten Hopp bc8f15
  	{
Karsten Hopp bc8f15
  	    di = HI2DI(hi);
Karsten Hopp bc8f15
  	    if (var_check_fixed(di->di_flags, name)
Karsten Hopp bc8f15
! 		    || var_check_ro(di->di_flags, name)
Karsten Hopp bc8f15
! 		    || tv_check_lock(d->dv_lock, name))
Karsten Hopp bc8f15
  		return FAIL;
Karsten Hopp bc8f15
  	    delete_var(ht, hi);
Karsten Hopp bc8f15
  	    return OK;
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 7269,7275 ****
Karsten Hopp bc8f15
      if (di != NULL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	STRCPY(di->di_key, key);
Karsten Hopp bc8f15
! 	di->di_flags = 0;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      return di;
Karsten Hopp bc8f15
  }
Karsten Hopp bc8f15
--- 7284,7290 ----
Karsten Hopp bc8f15
      if (di != NULL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	STRCPY(di->di_key, key);
Karsten Hopp bc8f15
! 	di->di_flags = DI_FLAGS_ALLOC;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      return di;
Karsten Hopp bc8f15
  }
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 7288,7294 ****
Karsten Hopp bc8f15
      if (di != NULL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	STRCPY(di->di_key, org->di_key);
Karsten Hopp bc8f15
! 	di->di_flags = 0;
Karsten Hopp bc8f15
  	copy_tv(&org->di_tv, &di->di_tv);
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      return di;
Karsten Hopp bc8f15
--- 7303,7309 ----
Karsten Hopp bc8f15
      if (di != NULL)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	STRCPY(di->di_key, org->di_key);
Karsten Hopp bc8f15
! 	di->di_flags = DI_FLAGS_ALLOC;
Karsten Hopp bc8f15
  	copy_tv(&org->di_tv, &di->di_tv);
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      return di;
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 7320,7326 ****
Karsten Hopp bc8f15
      dictitem_T *item;
Karsten Hopp bc8f15
  {
Karsten Hopp bc8f15
      clear_tv(&item->di_tv);
Karsten Hopp bc8f15
!     vim_free(item);
Karsten Hopp bc8f15
  }
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  /*
Karsten Hopp bc8f15
--- 7335,7342 ----
Karsten Hopp bc8f15
      dictitem_T *item;
Karsten Hopp bc8f15
  {
Karsten Hopp bc8f15
      clear_tv(&item->di_tv);
Karsten Hopp bc8f15
!     if (item->di_flags & DI_FLAGS_ALLOC)
Karsten Hopp bc8f15
! 	vim_free(item);
Karsten Hopp bc8f15
  }
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  /*
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10481,10486 ****
Karsten Hopp bc8f15
--- 10497,10503 ----
Karsten Hopp bc8f15
      dictitem_T	*di1;
Karsten Hopp bc8f15
      hashitem_T	*hi2;
Karsten Hopp bc8f15
      int		todo;
Karsten Hopp bc8f15
+     char	*arg_errmsg = N_("extend() argument");
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
      todo = (int)d2->dv_hashtab.ht_used;
Karsten Hopp bc8f15
      for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10515,10520 ****
Karsten Hopp bc8f15
--- 10532,10540 ----
Karsten Hopp bc8f15
  	    }
Karsten Hopp bc8f15
  	    else if (*action == 'f' && HI2DI(hi2) != di1)
Karsten Hopp bc8f15
  	    {
Karsten Hopp bc8f15
+ 		if (tv_check_lock(di1->di_tv.v_lock, (char_u *)_(arg_errmsg))
Karsten Hopp bc8f15
+ 		      || var_check_ro(di1->di_flags, (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
+ 		    break;
Karsten Hopp bc8f15
  		clear_tv(&di1->di_tv);
Karsten Hopp bc8f15
  		copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
Karsten Hopp bc8f15
  	    }
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10805,10817 ****
Karsten Hopp bc8f15
      if (argvars[0].v_type == VAR_LIST)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	if ((l = argvars[0].vval.v_list) == NULL
Karsten Hopp bc8f15
! 		|| tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      else if (argvars[0].v_type == VAR_DICT)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	if ((d = argvars[0].vval.v_dict) == NULL
Karsten Hopp bc8f15
! 		|| tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      else
Karsten Hopp bc8f15
--- 10825,10837 ----
Karsten Hopp bc8f15
      if (argvars[0].v_type == VAR_LIST)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	if ((l = argvars[0].vval.v_list) == NULL
Karsten Hopp bc8f15
! 	      || (!map && tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))))
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      else if (argvars[0].v_type == VAR_DICT)
Karsten Hopp bc8f15
      {
Karsten Hopp bc8f15
  	if ((d = argvars[0].vval.v_dict) == NULL
Karsten Hopp bc8f15
! 	      || (!map && tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))))
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
      else
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10850,10857 ****
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  		    --todo;
Karsten Hopp bc8f15
  		    di = HI2DI(hi);
Karsten Hopp bc8f15
! 		    if (tv_check_lock(di->di_tv.v_lock,
Karsten Hopp bc8f15
! 						     (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  			break;
Karsten Hopp bc8f15
  		    vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Karsten Hopp bc8f15
  		    r = filter_map_one(&di->di_tv, expr, map, &rem;;
Karsten Hopp bc8f15
--- 10870,10880 ----
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  		    --todo;
Karsten Hopp bc8f15
  		    di = HI2DI(hi);
Karsten Hopp bc8f15
! 		    if (map &&
Karsten Hopp bc8f15
! 			    (tv_check_lock(di->di_tv.v_lock,
Karsten Hopp bc8f15
! 						     (char_u *)_(arg_errmsg))
Karsten Hopp bc8f15
! 			    || var_check_ro(di->di_flags,
Karsten Hopp bc8f15
! 						     (char_u *)_(arg_errmsg))))
Karsten Hopp bc8f15
  			break;
Karsten Hopp bc8f15
  		    vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Karsten Hopp bc8f15
  		    r = filter_map_one(&di->di_tv, expr, map, &rem;;
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10859,10865 ****
Karsten Hopp bc8f15
--- 10882,10895 ----
Karsten Hopp bc8f15
  		    if (r == FAIL || did_emsg)
Karsten Hopp bc8f15
  			break;
Karsten Hopp bc8f15
  		    if (!map && rem)
Karsten Hopp bc8f15
+ 		    {
Karsten Hopp bc8f15
+ 			if (var_check_fixed(di->di_flags,
Karsten Hopp bc8f15
+ 						     (char_u *)_(arg_errmsg))
Karsten Hopp bc8f15
+ 			    || var_check_ro(di->di_flags,
Karsten Hopp bc8f15
+ 						     (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
+ 			    break;
Karsten Hopp bc8f15
  			dictitem_remove(d, di);
Karsten Hopp bc8f15
+ 		    }
Karsten Hopp bc8f15
  		}
Karsten Hopp bc8f15
  	    }
Karsten Hopp bc8f15
  	    hash_unlock(ht);
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 10870,10876 ****
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  	    for (li = l->lv_first; li != NULL; li = nli)
Karsten Hopp bc8f15
  	    {
Karsten Hopp bc8f15
! 		if (tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  		    break;
Karsten Hopp bc8f15
  		nli = li->li_next;
Karsten Hopp bc8f15
  		vimvars[VV_KEY].vv_nr = idx;
Karsten Hopp bc8f15
--- 10900,10907 ----
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
  	    for (li = l->lv_first; li != NULL; li = nli)
Karsten Hopp bc8f15
  	    {
Karsten Hopp bc8f15
! 		if (map && tv_check_lock(li->li_tv.v_lock,
Karsten Hopp bc8f15
! 						     (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  		    break;
Karsten Hopp bc8f15
  		nli = li->li_next;
Karsten Hopp bc8f15
  		vimvars[VV_KEY].vv_nr = idx;
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 15819,15825 ****
Karsten Hopp bc8f15
  		di = dict_find(d, key, -1);
Karsten Hopp bc8f15
  		if (di == NULL)
Karsten Hopp bc8f15
  		    EMSG2(_(e_dictkey), key);
Karsten Hopp bc8f15
! 		else
Karsten Hopp bc8f15
  		{
Karsten Hopp bc8f15
  		    *rettv = di->di_tv;
Karsten Hopp bc8f15
  		    init_tv(&di->di_tv);
Karsten Hopp bc8f15
--- 15850,15858 ----
Karsten Hopp bc8f15
  		di = dict_find(d, key, -1);
Karsten Hopp bc8f15
  		if (di == NULL)
Karsten Hopp bc8f15
  		    EMSG2(_(e_dictkey), key);
Karsten Hopp bc8f15
! 		else if (!var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg))
Karsten Hopp bc8f15
! 			    && !var_check_ro(di->di_flags,
Karsten Hopp bc8f15
! 						     (char_u *)_(arg_errmsg)))
Karsten Hopp bc8f15
  		{
Karsten Hopp bc8f15
  		    *rettv = di->di_tv;
Karsten Hopp bc8f15
  		    init_tv(&di->di_tv);
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 21303,21309 ****
Karsten Hopp bc8f15
  	    v = HI2DI(hi);
Karsten Hopp bc8f15
  	    if (free_val)
Karsten Hopp bc8f15
  		clear_tv(&v->di_tv);
Karsten Hopp bc8f15
! 	    if ((v->di_flags & DI_FLAGS_FIX) == 0)
Karsten Hopp bc8f15
  		vim_free(v);
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
--- 21336,21342 ----
Karsten Hopp bc8f15
  	    v = HI2DI(hi);
Karsten Hopp bc8f15
  	    if (free_val)
Karsten Hopp bc8f15
  		clear_tv(&v->di_tv);
Karsten Hopp bc8f15
! 	    if (v->di_flags & DI_FLAGS_ALLOC)
Karsten Hopp bc8f15
  		vim_free(v);
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 21502,21508 ****
Karsten Hopp bc8f15
  	    vim_free(v);
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
! 	v->di_flags = 0;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
      if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Karsten Hopp bc8f15
--- 21535,21541 ----
Karsten Hopp bc8f15
  	    vim_free(v);
Karsten Hopp bc8f15
  	    return;
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
! 	v->di_flags = DI_FLAGS_ALLOC;
Karsten Hopp bc8f15
      }
Karsten Hopp bc8f15
  
Karsten Hopp bc8f15
      if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 23656,23662 ****
Karsten Hopp bc8f15
  							     + STRLEN(name)));
Karsten Hopp bc8f15
  	    if (v == NULL)
Karsten Hopp bc8f15
  		break;
Karsten Hopp bc8f15
! 	    v->di_flags = DI_FLAGS_RO;
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
  	STRCPY(v->di_key, name);
Karsten Hopp bc8f15
  	hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Karsten Hopp bc8f15
--- 23689,23695 ----
Karsten Hopp bc8f15
  							     + STRLEN(name)));
Karsten Hopp bc8f15
  	    if (v == NULL)
Karsten Hopp bc8f15
  		break;
Karsten Hopp bc8f15
! 	    v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
Karsten Hopp bc8f15
  	}
Karsten Hopp bc8f15
  	STRCPY(v->di_key, name);
Karsten Hopp bc8f15
  	hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
Karsten Hopp bc8f15
*** ../vim-7.4.697/src/testdir/test55.in	2014-12-07 00:18:27.528202992 +0100
Karsten Hopp bc8f15
--- src/testdir/test55.in	2015-04-13 16:03:46.981252486 +0200
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 282,287 ****
Karsten Hopp bc8f15
--- 282,447 ----
Karsten Hopp bc8f15
  :    $put =ps
Karsten Hopp bc8f15
  :  endfor
Karsten Hopp bc8f15
  :endfor
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :" Unletting locked variables
Karsten Hopp bc8f15
+ :$put ='Unletting:'
Karsten Hopp bc8f15
+ :for depth in range(5)
Karsten Hopp bc8f15
+ :  $put ='depth is ' . depth
Karsten Hopp bc8f15
+ :  for u in range(3)
Karsten Hopp bc8f15
+ :    unlet l
Karsten Hopp bc8f15
+ :    let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}]
Karsten Hopp bc8f15
+ :    exe "lockvar " . depth . " l"
Karsten Hopp bc8f15
+ :    if u == 1
Karsten Hopp bc8f15
+ :      exe "unlockvar l"
Karsten Hopp bc8f15
+ :    elseif u == 2
Karsten Hopp bc8f15
+ :      exe "unlockvar " . depth . " l"
Karsten Hopp bc8f15
+ :    endif
Karsten Hopp bc8f15
+ :    let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
Karsten Hopp bc8f15
+ :    $put =ps
Karsten Hopp bc8f15
+ :    let ps = ''
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[2]['6'][7]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[2][6]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[2]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[1][1][0]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[1][1]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l[1]
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    try
Karsten Hopp bc8f15
+ :      unlet l
Karsten Hopp bc8f15
+ :      let ps .= 'p'
Karsten Hopp bc8f15
+ :    catch
Karsten Hopp bc8f15
+ :      let ps .= 'F'
Karsten Hopp bc8f15
+ :    endtry
Karsten Hopp bc8f15
+ :    $put =ps
Karsten Hopp bc8f15
+ :  endfor
Karsten Hopp bc8f15
+ :endfor
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :" Locked variables and :unlet or list / dict functions
Karsten Hopp bc8f15
+ :$put ='Locks and commands or functions:'
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='No :unlet after lock on dict:'
Karsten Hopp bc8f15
+ :unlet! d
Karsten Hopp bc8f15
+ :let d = {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :lockvar 1 d
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  unlet d.a
Karsten Hopp bc8f15
+ :  $put ='did :unlet'
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:16]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :$put =string(d)
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put =':unlet after lock on dict item:'
Karsten Hopp bc8f15
+ :unlet! d
Karsten Hopp bc8f15
+ :let d = {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :lockvar d.a
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  unlet d.a
Karsten Hopp bc8f15
+ :  $put ='did :unlet'
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:16]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :$put =string(d)
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='filter() after lock on dict item:'
Karsten Hopp bc8f15
+ :unlet! d
Karsten Hopp bc8f15
+ :let d = {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :lockvar d.a
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  call filter(d, 'v:key != "a"')
Karsten Hopp bc8f15
+ :  $put ='did filter()'
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:16]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :$put =string(d)
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='map() after lock on dict:'
Karsten Hopp bc8f15
+ :unlet! d
Karsten Hopp bc8f15
+ :let d = {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :lockvar 1 d
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  call map(d, 'v:val + 200')
Karsten Hopp bc8f15
+ :  $put ='did map()'
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:16]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :$put =string(d)
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='No extend() after lock on dict item:'
Karsten Hopp bc8f15
+ :unlet! d
Karsten Hopp bc8f15
+ :let d = {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :lockvar d.a
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  $put =string(extend(d, {'a': 123}))
Karsten Hopp bc8f15
+ :  $put ='did extend()'
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:14]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :$put =string(d)
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='No remove() of write-protected scope-level variable:'
Karsten Hopp bc8f15
+ :fun! Tfunc(this_is_a_loooooooooong_parameter_name)
Karsten Hopp bc8f15
+ :  try
Karsten Hopp bc8f15
+ :    $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name'))
Karsten Hopp bc8f15
+ :    $put ='did remove()'
Karsten Hopp bc8f15
+ :  catch
Karsten Hopp bc8f15
+ :    $put =v:exception[:14]
Karsten Hopp bc8f15
+ :  endtry
Karsten Hopp bc8f15
+ :endfun
Karsten Hopp bc8f15
+ :call Tfunc('testval')
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='No extend() of write-protected scope-level variable:'
Karsten Hopp bc8f15
+ :fun! Tfunc(this_is_a_loooooooooong_parameter_name)
Karsten Hopp bc8f15
+ :  try
Karsten Hopp bc8f15
+ :    $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234}))
Karsten Hopp bc8f15
+ :    $put ='did extend()'
Karsten Hopp bc8f15
+ :  catch
Karsten Hopp bc8f15
+ :    $put =v:exception[:14]
Karsten Hopp bc8f15
+ :  endtry
Karsten Hopp bc8f15
+ :endfun
Karsten Hopp bc8f15
+ :call Tfunc('testval')
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
+ :$put ='No :unlet of variable in locked scope:'
Karsten Hopp bc8f15
+ :let b:testvar = 123
Karsten Hopp bc8f15
+ :lockvar 1 b:
Karsten Hopp bc8f15
+ :try
Karsten Hopp bc8f15
+ :  unlet b:testvar
Karsten Hopp bc8f15
+ :  $put ='b:testvar was :unlet: '. (!exists('b:testvar'))
Karsten Hopp bc8f15
+ :catch
Karsten Hopp bc8f15
+ :  $put =v:exception[:16]
Karsten Hopp bc8f15
+ :endtry
Karsten Hopp bc8f15
+ :unlockvar 1 b:
Karsten Hopp bc8f15
+ :unlet! b:testvar
Karsten Hopp bc8f15
+ :"
Karsten Hopp bc8f15
  :unlet l
Karsten Hopp bc8f15
  :let l = [1, 2, 3, 4]
Karsten Hopp bc8f15
  :lockvar! l
Karsten Hopp bc8f15
*** ../vim-7.4.697/src/testdir/test55.ok	2014-12-07 00:18:27.528202992 +0100
Karsten Hopp bc8f15
--- src/testdir/test55.ok	2015-04-13 16:03:46.981252486 +0200
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 86,91 ****
Karsten Hopp bc8f15
--- 86,149 ----
Karsten Hopp bc8f15
  FFpFFpp
Karsten Hopp bc8f15
  0000-000
Karsten Hopp bc8f15
  ppppppp
Karsten Hopp bc8f15
+ Unletting:
Karsten Hopp bc8f15
+ depth is 0
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ depth is 1
Karsten Hopp bc8f15
+ 1000-000
Karsten Hopp bc8f15
+ ppFppFp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ depth is 2
Karsten Hopp bc8f15
+ 1100-100
Karsten Hopp bc8f15
+ pFFpFFp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ depth is 3
Karsten Hopp bc8f15
+ 1110-110
Karsten Hopp bc8f15
+ FFFFFFp
Karsten Hopp bc8f15
+ 0010-010
Karsten Hopp bc8f15
+ FppFppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ depth is 4
Karsten Hopp bc8f15
+ 1111-111
Karsten Hopp bc8f15
+ FFFFFFp
Karsten Hopp bc8f15
+ 0011-011
Karsten Hopp bc8f15
+ FppFppp
Karsten Hopp bc8f15
+ 0000-000
Karsten Hopp bc8f15
+ ppppppp
Karsten Hopp bc8f15
+ Locks and commands or functions:
Karsten Hopp bc8f15
+ No :unlet after lock on dict:
Karsten Hopp bc8f15
+ Vim(unlet):E741: 
Karsten Hopp bc8f15
+ {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ :unlet after lock on dict item:
Karsten Hopp bc8f15
+ did :unlet
Karsten Hopp bc8f15
+ {'b': 100}
Karsten Hopp bc8f15
+ filter() after lock on dict item:
Karsten Hopp bc8f15
+ did filter()
Karsten Hopp bc8f15
+ {'b': 100}
Karsten Hopp bc8f15
+ map() after lock on dict:
Karsten Hopp bc8f15
+ did map()
Karsten Hopp bc8f15
+ {'a': 299, 'b': 300}
Karsten Hopp bc8f15
+ No extend() after lock on dict item:
Karsten Hopp bc8f15
+ Vim(put):E741: 
Karsten Hopp bc8f15
+ {'a': 99, 'b': 100}
Karsten Hopp bc8f15
+ No remove() of write-protected scope-level variable:
Karsten Hopp bc8f15
+ Vim(put):E795: 
Karsten Hopp bc8f15
+ No extend() of write-protected scope-level variable:
Karsten Hopp bc8f15
+ Vim(put):E742: 
Karsten Hopp bc8f15
+ No :unlet of variable in locked scope:
Karsten Hopp bc8f15
+ Vim(unlet):E741: 
Karsten Hopp bc8f15
  [1, 2, 3, 4]
Karsten Hopp bc8f15
  [1, 2, 3, 4]
Karsten Hopp bc8f15
  [1, 2, 3, 4]
Karsten Hopp bc8f15
*** ../vim-7.4.697/src/version.c	2015-04-13 15:37:48.342074267 +0200
Karsten Hopp bc8f15
--- src/version.c	2015-04-13 16:06:31.439494486 +0200
Karsten Hopp bc8f15
***************
Karsten Hopp bc8f15
*** 743,744 ****
Karsten Hopp bc8f15
--- 743,746 ----
Karsten Hopp bc8f15
  {   /* Add new patch number below this line */
Karsten Hopp bc8f15
+ /**/
Karsten Hopp bc8f15
+     698,
Karsten Hopp bc8f15
  /**/
Karsten Hopp bc8f15
Karsten Hopp bc8f15
-- 
Karsten Hopp bc8f15
To keep milk from turning sour: Keep it in the cow.
Karsten Hopp bc8f15
Karsten Hopp bc8f15
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp bc8f15
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp bc8f15
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp bc8f15
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///