Karsten Hopp a01c6c
To: vim_dev@googlegroups.com
Karsten Hopp a01c6c
Subject: Patch 7.4.358
Karsten Hopp a01c6c
Fcc: outbox
Karsten Hopp a01c6c
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp a01c6c
Mime-Version: 1.0
Karsten Hopp a01c6c
Content-Type: text/plain; charset=UTF-8
Karsten Hopp a01c6c
Content-Transfer-Encoding: 8bit
Karsten Hopp a01c6c
------------
Karsten Hopp a01c6c
Karsten Hopp a01c6c
Patch 7.4.358 (after 7.4.351)
Karsten Hopp a01c6c
Problem:    Sort is not always stable.
Karsten Hopp a01c6c
Solution:   Add an index instead of relying on the pointer to remain the same.
Karsten Hopp a01c6c
	    Idea by Jun Takimoto.
Karsten Hopp a01c6c
Files:	    src/eval.c
Karsten Hopp a01c6c
Karsten Hopp a01c6c
Karsten Hopp a01c6c
*** ../vim-7.4.357/src/eval.c	2014-07-02 19:06:14.686326091 +0200
Karsten Hopp a01c6c
--- src/eval.c	2014-07-09 17:42:05.699813489 +0200
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17329,17334 ****
Karsten Hopp a01c6c
--- 17329,17341 ----
Karsten Hopp a01c6c
  #endif
Karsten Hopp a01c6c
  	item_compare2 __ARGS((const void *s1, const void *s2));
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
+ /* struct used in the array that's given to qsort() */
Karsten Hopp a01c6c
+ typedef struct
Karsten Hopp a01c6c
+ {
Karsten Hopp a01c6c
+     listitem_T	*item;
Karsten Hopp a01c6c
+     int		idx;
Karsten Hopp a01c6c
+ } sortItem_T;
Karsten Hopp a01c6c
+ 
Karsten Hopp a01c6c
  static int	item_compare_ic;
Karsten Hopp a01c6c
  static int	item_compare_numeric;
Karsten Hopp a01c6c
  static char_u	*item_compare_func;
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17349,17362 ****
Karsten Hopp a01c6c
      const void	*s1;
Karsten Hopp a01c6c
      const void	*s2;
Karsten Hopp a01c6c
  {
Karsten Hopp a01c6c
      char_u	*p1, *p2;
Karsten Hopp a01c6c
      char_u	*tofree1, *tofree2;
Karsten Hopp a01c6c
      int		res;
Karsten Hopp a01c6c
      char_u	numbuf1[NUMBUFLEN];
Karsten Hopp a01c6c
      char_u	numbuf2[NUMBUFLEN];
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
!     p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
Karsten Hopp a01c6c
!     p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
Karsten Hopp a01c6c
      if (p1 == NULL)
Karsten Hopp a01c6c
  	p1 = (char_u *)"";
Karsten Hopp a01c6c
      if (p2 == NULL)
Karsten Hopp a01c6c
--- 17356,17372 ----
Karsten Hopp a01c6c
      const void	*s1;
Karsten Hopp a01c6c
      const void	*s2;
Karsten Hopp a01c6c
  {
Karsten Hopp a01c6c
+     sortItem_T  *si1, *si2;
Karsten Hopp a01c6c
      char_u	*p1, *p2;
Karsten Hopp a01c6c
      char_u	*tofree1, *tofree2;
Karsten Hopp a01c6c
      int		res;
Karsten Hopp a01c6c
      char_u	numbuf1[NUMBUFLEN];
Karsten Hopp a01c6c
      char_u	numbuf2[NUMBUFLEN];
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
!     si1 = (sortItem_T *)s1;
Karsten Hopp a01c6c
!     si2 = (sortItem_T *)s2;
Karsten Hopp a01c6c
!     p1 = tv2string(&si1->item->li_tv, &tofree1, numbuf1, 0);
Karsten Hopp a01c6c
!     p2 = tv2string(&si2->item->li_tv, &tofree2, numbuf2, 0);
Karsten Hopp a01c6c
      if (p1 == NULL)
Karsten Hopp a01c6c
  	p1 = (char_u *)"";
Karsten Hopp a01c6c
      if (p2 == NULL)
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17379,17385 ****
Karsten Hopp a01c6c
      /* When the result would be zero, compare the pointers themselves.  Makes
Karsten Hopp a01c6c
       * the sort stable. */
Karsten Hopp a01c6c
      if (res == 0 && !item_compare_keep_zero)
Karsten Hopp a01c6c
! 	res = s1 > s2 ? 1 : -1;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      vim_free(tofree1);
Karsten Hopp a01c6c
      vim_free(tofree2);
Karsten Hopp a01c6c
--- 17389,17395 ----
Karsten Hopp a01c6c
      /* When the result would be zero, compare the pointers themselves.  Makes
Karsten Hopp a01c6c
       * the sort stable. */
Karsten Hopp a01c6c
      if (res == 0 && !item_compare_keep_zero)
Karsten Hopp a01c6c
! 	res = si1->idx > si2->idx ? 1 : -1;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      vim_free(tofree1);
Karsten Hopp a01c6c
      vim_free(tofree2);
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17394,17399 ****
Karsten Hopp a01c6c
--- 17404,17410 ----
Karsten Hopp a01c6c
      const void	*s1;
Karsten Hopp a01c6c
      const void	*s2;
Karsten Hopp a01c6c
  {
Karsten Hopp a01c6c
+     sortItem_T  *si1, *si2;
Karsten Hopp a01c6c
      int		res;
Karsten Hopp a01c6c
      typval_T	rettv;
Karsten Hopp a01c6c
      typval_T	argv[3];
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17403,17412 ****
Karsten Hopp a01c6c
      if (item_compare_func_err)
Karsten Hopp a01c6c
  	return 0;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      /* Copy the values.  This is needed to be able to set v_lock to VAR_FIXED
Karsten Hopp a01c6c
       * in the copy without changing the original list items. */
Karsten Hopp a01c6c
!     copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
Karsten Hopp a01c6c
!     copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      rettv.v_type = VAR_UNKNOWN;		/* clear_tv() uses this */
Karsten Hopp a01c6c
      res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
Karsten Hopp a01c6c
--- 17414,17426 ----
Karsten Hopp a01c6c
      if (item_compare_func_err)
Karsten Hopp a01c6c
  	return 0;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
+     si1 = (sortItem_T *)s1;
Karsten Hopp a01c6c
+     si2 = (sortItem_T *)s2;
Karsten Hopp a01c6c
+ 
Karsten Hopp a01c6c
      /* Copy the values.  This is needed to be able to set v_lock to VAR_FIXED
Karsten Hopp a01c6c
       * in the copy without changing the original list items. */
Karsten Hopp a01c6c
!     copy_tv(&si1->item->li_tv, &argv[0]);
Karsten Hopp a01c6c
!     copy_tv(&si2->item->li_tv, &argv[1]);
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      rettv.v_type = VAR_UNKNOWN;		/* clear_tv() uses this */
Karsten Hopp a01c6c
      res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17426,17432 ****
Karsten Hopp a01c6c
      /* When the result would be zero, compare the pointers themselves.  Makes
Karsten Hopp a01c6c
       * the sort stable. */
Karsten Hopp a01c6c
      if (res == 0 && !item_compare_keep_zero)
Karsten Hopp a01c6c
! 	res = s1 > s2 ? 1 : -1;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      return res;
Karsten Hopp a01c6c
  }
Karsten Hopp a01c6c
--- 17440,17446 ----
Karsten Hopp a01c6c
      /* When the result would be zero, compare the pointers themselves.  Makes
Karsten Hopp a01c6c
       * the sort stable. */
Karsten Hopp a01c6c
      if (res == 0 && !item_compare_keep_zero)
Karsten Hopp a01c6c
! 	res = si1->idx > si2->idx ? 1 : -1;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
      return res;
Karsten Hopp a01c6c
  }
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17442,17448 ****
Karsten Hopp a01c6c
  {
Karsten Hopp a01c6c
      list_T	*l;
Karsten Hopp a01c6c
      listitem_T	*li;
Karsten Hopp a01c6c
!     listitem_T	**ptrs;
Karsten Hopp a01c6c
      long	len;
Karsten Hopp a01c6c
      long	i;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
--- 17456,17462 ----
Karsten Hopp a01c6c
  {
Karsten Hopp a01c6c
      list_T	*l;
Karsten Hopp a01c6c
      listitem_T	*li;
Karsten Hopp a01c6c
!     sortItem_T	*ptrs;
Karsten Hopp a01c6c
      long	len;
Karsten Hopp a01c6c
      long	i;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17510,17516 ****
Karsten Hopp a01c6c
  	}
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  	/* Make an array with each entry pointing to an item in the List. */
Karsten Hopp a01c6c
! 	ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Karsten Hopp a01c6c
  	if (ptrs == NULL)
Karsten Hopp a01c6c
  	    return;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
--- 17524,17530 ----
Karsten Hopp a01c6c
  	}
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  	/* Make an array with each entry pointing to an item in the List. */
Karsten Hopp a01c6c
! 	ptrs = (sortItem_T *)alloc((int)(len * sizeof(sortItem_T)));
Karsten Hopp a01c6c
  	if (ptrs == NULL)
Karsten Hopp a01c6c
  	    return;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17519,17525 ****
Karsten Hopp a01c6c
  	{
Karsten Hopp a01c6c
  	    /* sort(): ptrs will be the list to sort */
Karsten Hopp a01c6c
  	    for (li = l->lv_first; li != NULL; li = li->li_next)
Karsten Hopp a01c6c
! 		ptrs[i++] = li;
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  	    item_compare_func_err = FALSE;
Karsten Hopp a01c6c
  	    item_compare_keep_zero = FALSE;
Karsten Hopp a01c6c
--- 17533,17543 ----
Karsten Hopp a01c6c
  	{
Karsten Hopp a01c6c
  	    /* sort(): ptrs will be the list to sort */
Karsten Hopp a01c6c
  	    for (li = l->lv_first; li != NULL; li = li->li_next)
Karsten Hopp a01c6c
! 	    {
Karsten Hopp a01c6c
! 		ptrs[i].item = li;
Karsten Hopp a01c6c
! 		ptrs[i].idx = i;
Karsten Hopp a01c6c
! 		++i;
Karsten Hopp a01c6c
! 	    }
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  	    item_compare_func_err = FALSE;
Karsten Hopp a01c6c
  	    item_compare_keep_zero = FALSE;
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17531,17537 ****
Karsten Hopp a01c6c
  	    else
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		/* Sort the array with item pointers. */
Karsten Hopp a01c6c
! 		qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Karsten Hopp a01c6c
  		    item_compare_func == NULL ? item_compare : item_compare2);
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  		if (!item_compare_func_err)
Karsten Hopp a01c6c
--- 17549,17555 ----
Karsten Hopp a01c6c
  	    else
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		/* Sort the array with item pointers. */
Karsten Hopp a01c6c
! 		qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
Karsten Hopp a01c6c
  		    item_compare_func == NULL ? item_compare : item_compare2);
Karsten Hopp a01c6c
  
Karsten Hopp a01c6c
  		if (!item_compare_func_err)
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17540,17546 ****
Karsten Hopp a01c6c
  		    l->lv_first = l->lv_last = l->lv_idx_item = NULL;
Karsten Hopp a01c6c
  		    l->lv_len = 0;
Karsten Hopp a01c6c
  		    for (i = 0; i < len; ++i)
Karsten Hopp a01c6c
! 			list_append(l, ptrs[i]);
Karsten Hopp a01c6c
  		}
Karsten Hopp a01c6c
  	    }
Karsten Hopp a01c6c
  	}
Karsten Hopp a01c6c
--- 17558,17564 ----
Karsten Hopp a01c6c
  		    l->lv_first = l->lv_last = l->lv_idx_item = NULL;
Karsten Hopp a01c6c
  		    l->lv_len = 0;
Karsten Hopp a01c6c
  		    for (i = 0; i < len; ++i)
Karsten Hopp a01c6c
! 			list_append(l, ptrs[i].item);
Karsten Hopp a01c6c
  		}
Karsten Hopp a01c6c
  	    }
Karsten Hopp a01c6c
  	}
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17559,17565 ****
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
Karsten Hopp a01c6c
  									 == 0)
Karsten Hopp a01c6c
! 		    ptrs[i++] = li;
Karsten Hopp a01c6c
  		if (item_compare_func_err)
Karsten Hopp a01c6c
  		{
Karsten Hopp a01c6c
  		    EMSG(_("E882: Uniq compare function failed"));
Karsten Hopp a01c6c
--- 17577,17583 ----
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
Karsten Hopp a01c6c
  									 == 0)
Karsten Hopp a01c6c
! 		    ptrs[i++].item = li;
Karsten Hopp a01c6c
  		if (item_compare_func_err)
Karsten Hopp a01c6c
  		{
Karsten Hopp a01c6c
  		    EMSG(_("E882: Uniq compare function failed"));
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 17571,17582 ****
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		while (--i >= 0)
Karsten Hopp a01c6c
  		{
Karsten Hopp a01c6c
! 		    li = ptrs[i]->li_next;
Karsten Hopp a01c6c
! 		    ptrs[i]->li_next = li->li_next;
Karsten Hopp a01c6c
  		    if (li->li_next != NULL)
Karsten Hopp a01c6c
! 			li->li_next->li_prev = ptrs[i];
Karsten Hopp a01c6c
  		    else
Karsten Hopp a01c6c
! 			l->lv_last = ptrs[i];
Karsten Hopp a01c6c
  		    list_fix_watch(l, li);
Karsten Hopp a01c6c
  		    listitem_free(li);
Karsten Hopp a01c6c
  		    l->lv_len--;
Karsten Hopp a01c6c
--- 17589,17600 ----
Karsten Hopp a01c6c
  	    {
Karsten Hopp a01c6c
  		while (--i >= 0)
Karsten Hopp a01c6c
  		{
Karsten Hopp a01c6c
! 		    li = ptrs[i].item->li_next;
Karsten Hopp a01c6c
! 		    ptrs[i].item->li_next = li->li_next;
Karsten Hopp a01c6c
  		    if (li->li_next != NULL)
Karsten Hopp a01c6c
! 			li->li_next->li_prev = ptrs[i].item;
Karsten Hopp a01c6c
  		    else
Karsten Hopp a01c6c
! 			l->lv_last = ptrs[i].item;
Karsten Hopp a01c6c
  		    list_fix_watch(l, li);
Karsten Hopp a01c6c
  		    listitem_free(li);
Karsten Hopp a01c6c
  		    l->lv_len--;
Karsten Hopp a01c6c
*** ../vim-7.4.357/src/version.c	2014-07-09 14:00:45.175044250 +0200
Karsten Hopp a01c6c
--- src/version.c	2014-07-09 17:23:12.791836515 +0200
Karsten Hopp a01c6c
***************
Karsten Hopp a01c6c
*** 736,737 ****
Karsten Hopp a01c6c
--- 736,739 ----
Karsten Hopp a01c6c
  {   /* Add new patch number below this line */
Karsten Hopp a01c6c
+ /**/
Karsten Hopp a01c6c
+     358,
Karsten Hopp a01c6c
  /**/
Karsten Hopp a01c6c
Karsten Hopp a01c6c
-- 
Karsten Hopp a01c6c
An indication you must be a manager:
Karsten Hopp a01c6c
You can explain to somebody the difference between "re-engineering",
Karsten Hopp a01c6c
"down-sizing", "right-sizing", and "firing people's asses".
Karsten Hopp a01c6c
Karsten Hopp a01c6c
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp a01c6c
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp a01c6c
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp a01c6c
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///