Karsten Hopp 1ffe1d
To: vim-dev@vim.org
Karsten Hopp 1ffe1d
Subject: Patch 7.0.135
Karsten Hopp 1ffe1d
Fcc: outbox
Karsten Hopp 1ffe1d
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 1ffe1d
Mime-Version: 1.0
Karsten Hopp 1ffe1d
Content-Type: text/plain; charset=ISO-8859-1
Karsten Hopp 1ffe1d
Content-Transfer-Encoding: 8bit
Karsten Hopp 1ffe1d
------------
Karsten Hopp 1ffe1d
Karsten Hopp 1ffe1d
Patch 7.0.135
Karsten Hopp 1ffe1d
Problem:    Crash when garbage collecting list or dict with loop.
Karsten Hopp 1ffe1d
Solution:   Don't use DEL_REFCOUNT but don't recurse into Lists and
Karsten Hopp 1ffe1d
	    Dictionaries when freeing them in the garbage collector.
Karsten Hopp 1ffe1d
	    Also add allocated Dictionaries to the list of Dictionaries to
Karsten Hopp 1ffe1d
	    avoid leaking memory.
Karsten Hopp 1ffe1d
Files:	    src/eval.c, src/proto/eval.pro, src/tag.c
Karsten Hopp 1ffe1d
Karsten Hopp 1ffe1d
Karsten Hopp 1ffe1d
*** ../vim-7.0.134/src/eval.c	Sun Oct 15 15:10:08 2006
Karsten Hopp 1ffe1d
--- src/eval.c	Sun Oct 15 22:30:09 2006
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 191,198 ****
Karsten Hopp 1ffe1d
  #define FC_RANGE    2		/* function accepts range */
Karsten Hopp 1ffe1d
  #define FC_DICT	    4		/* Dict function, uses "self" */
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
- #define DEL_REFCOUNT	999999	/* list/dict is being deleted */
Karsten Hopp 1ffe1d
- 
Karsten Hopp 1ffe1d
  /*
Karsten Hopp 1ffe1d
   * All user-defined functions are found in this hashtable.
Karsten Hopp 1ffe1d
   */
Karsten Hopp 1ffe1d
--- 191,196 ----
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 435,441 ****
Karsten Hopp 1ffe1d
  static void set_ref_in_list __ARGS((list_T *l, int copyID));
Karsten Hopp 1ffe1d
  static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Karsten Hopp 1ffe1d
  static void dict_unref __ARGS((dict_T *d));
Karsten Hopp 1ffe1d
! static void dict_free __ARGS((dict_T *d));
Karsten Hopp 1ffe1d
  static dictitem_T *dictitem_alloc __ARGS((char_u *key));
Karsten Hopp 1ffe1d
  static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
Karsten Hopp 1ffe1d
  static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
Karsten Hopp 1ffe1d
--- 433,439 ----
Karsten Hopp 1ffe1d
  static void set_ref_in_list __ARGS((list_T *l, int copyID));
Karsten Hopp 1ffe1d
  static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Karsten Hopp 1ffe1d
  static void dict_unref __ARGS((dict_T *d));
Karsten Hopp 1ffe1d
! static void dict_free __ARGS((dict_T *d, int recurse));
Karsten Hopp 1ffe1d
  static dictitem_T *dictitem_alloc __ARGS((char_u *key));
Karsten Hopp 1ffe1d
  static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
Karsten Hopp 1ffe1d
  static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 4899,4905 ****
Karsten Hopp 1ffe1d
  		    {
Karsten Hopp 1ffe1d
  			if (list_append_tv(l, &item->li_tv) == FAIL)
Karsten Hopp 1ffe1d
  			{
Karsten Hopp 1ffe1d
! 			    list_free(l);
Karsten Hopp 1ffe1d
  			    return FAIL;
Karsten Hopp 1ffe1d
  			}
Karsten Hopp 1ffe1d
  			item = item->li_next;
Karsten Hopp 1ffe1d
--- 4897,4903 ----
Karsten Hopp 1ffe1d
  		    {
Karsten Hopp 1ffe1d
  			if (list_append_tv(l, &item->li_tv) == FAIL)
Karsten Hopp 1ffe1d
  			{
Karsten Hopp 1ffe1d
! 			    list_free(l, TRUE);
Karsten Hopp 1ffe1d
  			    return FAIL;
Karsten Hopp 1ffe1d
  			}
Karsten Hopp 1ffe1d
  			item = item->li_next;
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 5299,5305 ****
Karsten Hopp 1ffe1d
  	EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Karsten Hopp 1ffe1d
  failret:
Karsten Hopp 1ffe1d
  	if (evaluate)
Karsten Hopp 1ffe1d
! 	    list_free(l);
Karsten Hopp 1ffe1d
  	return FAIL;
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
--- 5297,5303 ----
Karsten Hopp 1ffe1d
  	EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Karsten Hopp 1ffe1d
  failret:
Karsten Hopp 1ffe1d
  	if (evaluate)
Karsten Hopp 1ffe1d
! 	    list_free(l, TRUE);
Karsten Hopp 1ffe1d
  	return FAIL;
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 5363,5370 ****
Karsten Hopp 1ffe1d
  list_unref(l)
Karsten Hopp 1ffe1d
      list_T *l;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
!     if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0)
Karsten Hopp 1ffe1d
! 	list_free(l);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  /*
Karsten Hopp 1ffe1d
--- 5361,5368 ----
Karsten Hopp 1ffe1d
  list_unref(l)
Karsten Hopp 1ffe1d
      list_T *l;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
!     if (l != NULL && --l->lv_refcount <= 0)
Karsten Hopp 1ffe1d
! 	list_free(l, TRUE);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  /*
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 5372,5385 ****
Karsten Hopp 1ffe1d
   * Ignores the reference count.
Karsten Hopp 1ffe1d
   */
Karsten Hopp 1ffe1d
      void
Karsten Hopp 1ffe1d
! list_free(l)
Karsten Hopp 1ffe1d
!     list_T *l;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
      listitem_T *item;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
-     /* Avoid that recursive reference to the list frees us again. */
Karsten Hopp 1ffe1d
-     l->lv_refcount = DEL_REFCOUNT;
Karsten Hopp 1ffe1d
- 
Karsten Hopp 1ffe1d
      /* Remove the list from the list of lists for garbage collection. */
Karsten Hopp 1ffe1d
      if (l->lv_used_prev == NULL)
Karsten Hopp 1ffe1d
  	first_list = l->lv_used_next;
Karsten Hopp 1ffe1d
--- 5370,5381 ----
Karsten Hopp 1ffe1d
   * Ignores the reference count.
Karsten Hopp 1ffe1d
   */
Karsten Hopp 1ffe1d
      void
Karsten Hopp 1ffe1d
! list_free(l, recurse)
Karsten Hopp 1ffe1d
!     list_T  *l;
Karsten Hopp 1ffe1d
!     int	    recurse;	/* Free Lists and Dictionaries recursively. */
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
      listitem_T *item;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
      /* Remove the list from the list of lists for garbage collection. */
Karsten Hopp 1ffe1d
      if (l->lv_used_prev == NULL)
Karsten Hopp 1ffe1d
  	first_list = l->lv_used_next;
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 5392,5398 ****
Karsten Hopp 1ffe1d
      {
Karsten Hopp 1ffe1d
  	/* Remove the item before deleting it. */
Karsten Hopp 1ffe1d
  	l->lv_first = item->li_next;
Karsten Hopp 1ffe1d
! 	listitem_free(item);
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
      vim_free(l);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
--- 5388,5397 ----
Karsten Hopp 1ffe1d
      {
Karsten Hopp 1ffe1d
  	/* Remove the item before deleting it. */
Karsten Hopp 1ffe1d
  	l->lv_first = item->li_next;
Karsten Hopp 1ffe1d
! 	if (recurse || (item->li_tv.v_type != VAR_LIST
Karsten Hopp 1ffe1d
! 					   && item->li_tv.v_type != VAR_DICT))
Karsten Hopp 1ffe1d
! 	    clear_tv(&item->li_tv);
Karsten Hopp 1ffe1d
! 	vim_free(item);
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
      vim_free(l);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6113,6119 ****
Karsten Hopp 1ffe1d
      for (dd = first_dict; dd != NULL; )
Karsten Hopp 1ffe1d
  	if (dd->dv_copyID != copyID)
Karsten Hopp 1ffe1d
  	{
Karsten Hopp 1ffe1d
! 	    dict_free(dd);
Karsten Hopp 1ffe1d
  	    did_free = TRUE;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	    /* restart, next dict may also have been freed */
Karsten Hopp 1ffe1d
--- 6118,6127 ----
Karsten Hopp 1ffe1d
      for (dd = first_dict; dd != NULL; )
Karsten Hopp 1ffe1d
  	if (dd->dv_copyID != copyID)
Karsten Hopp 1ffe1d
  	{
Karsten Hopp 1ffe1d
! 	    /* Free the Dictionary and ordinary items it contains, but don't
Karsten Hopp 1ffe1d
! 	     * recurse into Lists and Dictionaries, they will be in the list
Karsten Hopp 1ffe1d
! 	     * of dicts or list of lists. */
Karsten Hopp 1ffe1d
! 	    dict_free(dd, FALSE);
Karsten Hopp 1ffe1d
  	    did_free = TRUE;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	    /* restart, next dict may also have been freed */
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6130,6136 ****
Karsten Hopp 1ffe1d
      for (ll = first_list; ll != NULL; )
Karsten Hopp 1ffe1d
  	if (ll->lv_copyID != copyID && ll->lv_watch == NULL)
Karsten Hopp 1ffe1d
  	{
Karsten Hopp 1ffe1d
! 	    list_free(ll);
Karsten Hopp 1ffe1d
  	    did_free = TRUE;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	    /* restart, next list may also have been freed */
Karsten Hopp 1ffe1d
--- 6138,6147 ----
Karsten Hopp 1ffe1d
      for (ll = first_list; ll != NULL; )
Karsten Hopp 1ffe1d
  	if (ll->lv_copyID != copyID && ll->lv_watch == NULL)
Karsten Hopp 1ffe1d
  	{
Karsten Hopp 1ffe1d
! 	    /* Free the List and ordinary items it contains, but don't recurse
Karsten Hopp 1ffe1d
! 	     * into Lists and Dictionaries, they will be in the list of dicts
Karsten Hopp 1ffe1d
! 	     * or list of lists. */
Karsten Hopp 1ffe1d
! 	    list_free(ll, FALSE);
Karsten Hopp 1ffe1d
  	    did_free = TRUE;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	    /* restart, next list may also have been freed */
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6223,6233 ****
Karsten Hopp 1ffe1d
      d = (dict_T *)alloc(sizeof(dict_T));
Karsten Hopp 1ffe1d
      if (d != NULL)
Karsten Hopp 1ffe1d
      {
Karsten Hopp 1ffe1d
! 	/* Add the list to the hashtable for garbage collection. */
Karsten Hopp 1ffe1d
  	if (first_dict != NULL)
Karsten Hopp 1ffe1d
  	    first_dict->dv_used_prev = d;
Karsten Hopp 1ffe1d
  	d->dv_used_next = first_dict;
Karsten Hopp 1ffe1d
  	d->dv_used_prev = NULL;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	hash_init(&d->dv_hashtab);
Karsten Hopp 1ffe1d
  	d->dv_lock = 0;
Karsten Hopp 1ffe1d
--- 6234,6245 ----
Karsten Hopp 1ffe1d
      d = (dict_T *)alloc(sizeof(dict_T));
Karsten Hopp 1ffe1d
      if (d != NULL)
Karsten Hopp 1ffe1d
      {
Karsten Hopp 1ffe1d
! 	/* Add the list to the list of dicts for garbage collection. */
Karsten Hopp 1ffe1d
  	if (first_dict != NULL)
Karsten Hopp 1ffe1d
  	    first_dict->dv_used_prev = d;
Karsten Hopp 1ffe1d
  	d->dv_used_next = first_dict;
Karsten Hopp 1ffe1d
  	d->dv_used_prev = NULL;
Karsten Hopp 1ffe1d
+ 	first_dict = d;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  	hash_init(&d->dv_hashtab);
Karsten Hopp 1ffe1d
  	d->dv_lock = 0;
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6245,6252 ****
Karsten Hopp 1ffe1d
  dict_unref(d)
Karsten Hopp 1ffe1d
      dict_T *d;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
!     if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0)
Karsten Hopp 1ffe1d
! 	dict_free(d);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  /*
Karsten Hopp 1ffe1d
--- 6257,6264 ----
Karsten Hopp 1ffe1d
  dict_unref(d)
Karsten Hopp 1ffe1d
      dict_T *d;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
!     if (d != NULL && --d->dv_refcount <= 0)
Karsten Hopp 1ffe1d
! 	dict_free(d, TRUE);
Karsten Hopp 1ffe1d
  }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  /*
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6254,6269 ****
Karsten Hopp 1ffe1d
   * Ignores the reference count.
Karsten Hopp 1ffe1d
   */
Karsten Hopp 1ffe1d
      static void
Karsten Hopp 1ffe1d
! dict_free(d)
Karsten Hopp 1ffe1d
!     dict_T *d;
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
      int		todo;
Karsten Hopp 1ffe1d
      hashitem_T	*hi;
Karsten Hopp 1ffe1d
      dictitem_T	*di;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
-     /* Avoid that recursive reference to the dict frees us again. */
Karsten Hopp 1ffe1d
-     d->dv_refcount = DEL_REFCOUNT;
Karsten Hopp 1ffe1d
- 
Karsten Hopp 1ffe1d
      /* Remove the dict from the list of dicts for garbage collection. */
Karsten Hopp 1ffe1d
      if (d->dv_used_prev == NULL)
Karsten Hopp 1ffe1d
  	first_dict = d->dv_used_next;
Karsten Hopp 1ffe1d
--- 6266,6279 ----
Karsten Hopp 1ffe1d
   * Ignores the reference count.
Karsten Hopp 1ffe1d
   */
Karsten Hopp 1ffe1d
      static void
Karsten Hopp 1ffe1d
! dict_free(d, recurse)
Karsten Hopp 1ffe1d
!     dict_T  *d;
Karsten Hopp 1ffe1d
!     int	    recurse;	/* Free Lists and Dictionaries recursively. */
Karsten Hopp 1ffe1d
  {
Karsten Hopp 1ffe1d
      int		todo;
Karsten Hopp 1ffe1d
      hashitem_T	*hi;
Karsten Hopp 1ffe1d
      dictitem_T	*di;
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
      /* Remove the dict from the list of dicts for garbage collection. */
Karsten Hopp 1ffe1d
      if (d->dv_used_prev == NULL)
Karsten Hopp 1ffe1d
  	first_dict = d->dv_used_next;
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6283,6289 ****
Karsten Hopp 1ffe1d
  	     * something recursive causing trouble. */
Karsten Hopp 1ffe1d
  	    di = HI2DI(hi);
Karsten Hopp 1ffe1d
  	    hash_remove(&d->dv_hashtab, hi);
Karsten Hopp 1ffe1d
! 	    dictitem_free(di);
Karsten Hopp 1ffe1d
  	    --todo;
Karsten Hopp 1ffe1d
  	}
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
--- 6293,6302 ----
Karsten Hopp 1ffe1d
  	     * something recursive causing trouble. */
Karsten Hopp 1ffe1d
  	    di = HI2DI(hi);
Karsten Hopp 1ffe1d
  	    hash_remove(&d->dv_hashtab, hi);
Karsten Hopp 1ffe1d
! 	    if (recurse || (di->di_tv.v_type != VAR_LIST
Karsten Hopp 1ffe1d
! 					     && di->di_tv.v_type != VAR_DICT))
Karsten Hopp 1ffe1d
! 		clear_tv(&di->di_tv);
Karsten Hopp 1ffe1d
! 	    vim_free(di);
Karsten Hopp 1ffe1d
  	    --todo;
Karsten Hopp 1ffe1d
  	}
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 6734,6740 ****
Karsten Hopp 1ffe1d
  	EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Karsten Hopp 1ffe1d
  failret:
Karsten Hopp 1ffe1d
  	if (evaluate)
Karsten Hopp 1ffe1d
! 	    dict_free(d);
Karsten Hopp 1ffe1d
  	return FAIL;
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
--- 6747,6753 ----
Karsten Hopp 1ffe1d
  	EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Karsten Hopp 1ffe1d
  failret:
Karsten Hopp 1ffe1d
  	if (evaluate)
Karsten Hopp 1ffe1d
! 	    dict_free(d, TRUE);
Karsten Hopp 1ffe1d
  	return FAIL;
Karsten Hopp 1ffe1d
      }
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
*** ../vim-7.0.134/src/proto/eval.pro	Fri Mar 24 23:16:28 2006
Karsten Hopp 1ffe1d
--- src/proto/eval.pro	Sun Oct 15 22:08:11 2006
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 44,50 ****
Karsten Hopp 1ffe1d
  extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx));
Karsten Hopp 1ffe1d
  extern list_T *list_alloc __ARGS((void));
Karsten Hopp 1ffe1d
  extern void list_unref __ARGS((list_T *l));
Karsten Hopp 1ffe1d
! extern void list_free __ARGS((list_T *l));
Karsten Hopp 1ffe1d
  extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
Karsten Hopp 1ffe1d
  extern int list_append_dict __ARGS((list_T *list, dict_T *dict));
Karsten Hopp 1ffe1d
  extern int garbage_collect __ARGS((void));
Karsten Hopp 1ffe1d
--- 44,50 ----
Karsten Hopp 1ffe1d
  extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx));
Karsten Hopp 1ffe1d
  extern list_T *list_alloc __ARGS((void));
Karsten Hopp 1ffe1d
  extern void list_unref __ARGS((list_T *l));
Karsten Hopp 1ffe1d
! extern void list_free __ARGS((list_T *l, int recurse));
Karsten Hopp 1ffe1d
  extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
Karsten Hopp 1ffe1d
  extern int list_append_dict __ARGS((list_T *list, dict_T *dict));
Karsten Hopp 1ffe1d
  extern int garbage_collect __ARGS((void));
Karsten Hopp 1ffe1d
*** ../vim-7.0.134/src/tag.c	Sun Sep 10 13:56:06 2006
Karsten Hopp 1ffe1d
--- src/tag.c	Sun Oct 15 21:44:56 2006
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 911,917 ****
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  		set_errorlist(curwin, list, ' ');
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
! 		list_free(list);
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  		cur_match = 0;		/* Jump to the first tag */
Karsten Hopp 1ffe1d
  	    }
Karsten Hopp 1ffe1d
--- 911,917 ----
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  		set_errorlist(curwin, list, ' ');
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
! 		list_free(list, TRUE);
Karsten Hopp 1ffe1d
  
Karsten Hopp 1ffe1d
  		cur_match = 0;		/* Jump to the first tag */
Karsten Hopp 1ffe1d
  	    }
Karsten Hopp 1ffe1d
*** ../vim-7.0.134/src/version.c	Sun Oct 15 15:10:08 2006
Karsten Hopp 1ffe1d
--- src/version.c	Sun Oct 15 22:01:53 2006
Karsten Hopp 1ffe1d
***************
Karsten Hopp 1ffe1d
*** 668,669 ****
Karsten Hopp 1ffe1d
--- 668,671 ----
Karsten Hopp 1ffe1d
  {   /* Add new patch number below this line */
Karsten Hopp 1ffe1d
+ /**/
Karsten Hopp 1ffe1d
+     135,
Karsten Hopp 1ffe1d
  /**/
Karsten Hopp 1ffe1d
Karsten Hopp 1ffe1d
-- 
Karsten Hopp 1ffe1d
Well, you come from nothing, you go back to nothing...  What have you
Karsten Hopp 1ffe1d
lost?  Nothing!
Karsten Hopp 1ffe1d
				-- Monty Python: The life of Brian
Karsten Hopp 1ffe1d
Karsten Hopp 1ffe1d
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 1ffe1d
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 1ffe1d
\\\        download, build and distribute -- http://www.A-A-P.org        ///
Karsten Hopp 1ffe1d
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///