@@ -18790,16 +18790,21 @@ typedef struct
1879018790 int idx;
1879118791} sortItem_T;
1879218792
18793- static int item_compare_ic;
18794- static int item_compare_numeric;
18795- static int item_compare_numbers;
18793+ /* struct storing information about current sort */
18794+ typedef struct
18795+ {
18796+ int item_compare_ic;
18797+ int item_compare_numeric;
18798+ int item_compare_numbers;
1879618799#ifdef FEAT_FLOAT
18797- static int item_compare_float;
18798- #endif
18799- static char_u *item_compare_func;
18800- static dict_T *item_compare_selfdict;
18801- static int item_compare_func_err;
18802- static int item_compare_keep_zero;
18800+ int item_compare_float;
18801+ #endif
18802+ char_u *item_compare_func;
18803+ dict_T *item_compare_selfdict;
18804+ int item_compare_func_err;
18805+ int item_compare_keep_zero;
18806+ } sortinfo_T;
18807+ static sortinfo_T *sortinfo = NULL;
1880318808static void do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort);
1880418809#define ITEM_COMPARE_FAIL 999
1880518810
@@ -18825,7 +18830,7 @@ item_compare(const void *s1, const void *s2)
1882518830 tv1 = &si1->item->li_tv;
1882618831 tv2 = &si2->item->li_tv;
1882718832
18828- if (item_compare_numbers)
18833+ if (sortinfo-> item_compare_numbers)
1882918834 {
1883018835 long v1 = get_tv_number(tv1);
1883118836 long v2 = get_tv_number(tv2);
@@ -18834,7 +18839,7 @@ item_compare(const void *s1, const void *s2)
1883418839 }
1883518840
1883618841#ifdef FEAT_FLOAT
18837- if (item_compare_float)
18842+ if (sortinfo-> item_compare_float)
1883818843 {
1883918844 float_T v1 = get_tv_float(tv1);
1884018845 float_T v2 = get_tv_float(tv2);
@@ -18848,7 +18853,7 @@ item_compare(const void *s1, const void *s2)
1884818853 * non-string to do what the docs promise. */
1884918854 if (tv1->v_type == VAR_STRING)
1885018855 {
18851- if (tv2->v_type != VAR_STRING || item_compare_numeric)
18856+ if (tv2->v_type != VAR_STRING || sortinfo-> item_compare_numeric)
1885218857 p1 = (char_u *)"'";
1885318858 else
1885418859 p1 = tv1->vval.v_string;
@@ -18857,7 +18862,7 @@ item_compare(const void *s1, const void *s2)
1885718862 p1 = tv2string(tv1, &tofree1, numbuf1, 0);
1885818863 if (tv2->v_type == VAR_STRING)
1885918864 {
18860- if (tv1->v_type != VAR_STRING || item_compare_numeric)
18865+ if (tv1->v_type != VAR_STRING || sortinfo-> item_compare_numeric)
1886118866 p2 = (char_u *)"'";
1886218867 else
1886318868 p2 = tv2->vval.v_string;
@@ -18868,9 +18873,9 @@ item_compare(const void *s1, const void *s2)
1886818873 p1 = (char_u *)"";
1886918874 if (p2 == NULL)
1887018875 p2 = (char_u *)"";
18871- if (!item_compare_numeric)
18876+ if (!sortinfo-> item_compare_numeric)
1887218877 {
18873- if (item_compare_ic)
18878+ if (sortinfo-> item_compare_ic)
1887418879 res = STRICMP(p1, p2);
1887518880 else
1887618881 res = STRCMP(p1, p2);
@@ -18885,7 +18890,7 @@ item_compare(const void *s1, const void *s2)
1888518890
1888618891 /* When the result would be zero, compare the item indexes. Makes the
1888718892 * sort stable. */
18888- if (res == 0 && !item_compare_keep_zero)
18893+ if (res == 0 && !sortinfo-> item_compare_keep_zero)
1888918894 res = si1->idx > si2->idx ? 1 : -1;
1889018895
1889118896 vim_free(tofree1);
@@ -18906,7 +18911,7 @@ item_compare2(const void *s1, const void *s2)
1890618911 int dummy;
1890718912
1890818913 /* shortcut after failure in previous call; compare all items equal */
18909- if (item_compare_func_err)
18914+ if (sortinfo-> item_compare_func_err)
1891018915 return 0;
1891118916
1891218917 si1 = (sortItem_T *)s1;
@@ -18918,23 +18923,24 @@ item_compare2(const void *s1, const void *s2)
1891818923 copy_tv(&si2->item->li_tv, &argv[1]);
1891918924
1892018925 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
18921- res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
18926+ res = call_func(sortinfo->item_compare_func,
18927+ (int)STRLEN(sortinfo->item_compare_func),
1892218928 &rettv, 2, argv, 0L, 0L, &dummy, TRUE,
18923- item_compare_selfdict);
18929+ sortinfo-> item_compare_selfdict);
1892418930 clear_tv(&argv[0]);
1892518931 clear_tv(&argv[1]);
1892618932
1892718933 if (res == FAIL)
1892818934 res = ITEM_COMPARE_FAIL;
1892918935 else
18930- res = get_tv_number_chk(&rettv, &item_compare_func_err);
18931- if (item_compare_func_err)
18936+ res = get_tv_number_chk(&rettv, &sortinfo-> item_compare_func_err);
18937+ if (sortinfo-> item_compare_func_err)
1893218938 res = ITEM_COMPARE_FAIL; /* return value has wrong type */
1893318939 clear_tv(&rettv);
1893418940
1893518941 /* When the result would be zero, compare the pointers themselves. Makes
1893618942 * the sort stable. */
18937- if (res == 0 && !item_compare_keep_zero)
18943+ if (res == 0 && !sortinfo-> item_compare_keep_zero)
1893818944 res = si1->idx > si2->idx ? 1 : -1;
1893918945
1894018946 return res;
@@ -18949,9 +18955,16 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1894918955 list_T *l;
1895018956 listitem_T *li;
1895118957 sortItem_T *ptrs;
18958+ sortinfo_T *old_sortinfo;
18959+ sortinfo_T info;
1895218960 long len;
1895318961 long i;
1895418962
18963+ /* Pointer to current info struct used in compare function. Save and
18964+ * restore the current one for nested calls. */
18965+ old_sortinfo = sortinfo;
18966+ sortinfo = &info;
18967+
1895518968 if (argvars[0].v_type != VAR_LIST)
1895618969 EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
1895718970 else
@@ -18960,62 +18973,62 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1896018973 if (l == NULL || tv_check_lock(l->lv_lock,
1896118974 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")),
1896218975 TRUE))
18963- return ;
18976+ goto theend ;
1896418977 rettv->vval.v_list = l;
1896518978 rettv->v_type = VAR_LIST;
1896618979 ++l->lv_refcount;
1896718980
1896818981 len = list_len(l);
1896918982 if (len <= 1)
18970- return ; /* short list sorts pretty quickly */
18983+ goto theend ; /* short list sorts pretty quickly */
1897118984
18972- item_compare_ic = FALSE;
18973- item_compare_numeric = FALSE;
18974- item_compare_numbers = FALSE;
18985+ info. item_compare_ic = FALSE;
18986+ info. item_compare_numeric = FALSE;
18987+ info. item_compare_numbers = FALSE;
1897518988#ifdef FEAT_FLOAT
18976- item_compare_float = FALSE;
18989+ info. item_compare_float = FALSE;
1897718990#endif
18978- item_compare_func = NULL;
18979- item_compare_selfdict = NULL;
18991+ info. item_compare_func = NULL;
18992+ info. item_compare_selfdict = NULL;
1898018993 if (argvars[1].v_type != VAR_UNKNOWN)
1898118994 {
1898218995 /* optional second argument: {func} */
1898318996 if (argvars[1].v_type == VAR_FUNC)
18984- item_compare_func = argvars[1].vval.v_string;
18997+ info. item_compare_func = argvars[1].vval.v_string;
1898518998 else
1898618999 {
1898719000 int error = FALSE;
1898819001
1898919002 i = get_tv_number_chk(&argvars[1], &error);
1899019003 if (error)
18991- return; /* type error; errmsg already given */
19004+ goto theend; /* type error; errmsg already given */
1899219005 if (i == 1)
18993- item_compare_ic = TRUE;
19006+ info. item_compare_ic = TRUE;
1899419007 else
18995- item_compare_func = get_tv_string(&argvars[1]);
18996- if (item_compare_func != NULL)
19008+ info. item_compare_func = get_tv_string(&argvars[1]);
19009+ if (info. item_compare_func != NULL)
1899719010 {
18998- if (STRCMP(item_compare_func, "n") == 0)
19011+ if (STRCMP(info. item_compare_func, "n") == 0)
1899919012 {
19000- item_compare_func = NULL;
19001- item_compare_numeric = TRUE;
19013+ info. item_compare_func = NULL;
19014+ info. item_compare_numeric = TRUE;
1900219015 }
19003- else if (STRCMP(item_compare_func, "N") == 0)
19016+ else if (STRCMP(info. item_compare_func, "N") == 0)
1900419017 {
19005- item_compare_func = NULL;
19006- item_compare_numbers = TRUE;
19018+ info. item_compare_func = NULL;
19019+ info. item_compare_numbers = TRUE;
1900719020 }
1900819021#ifdef FEAT_FLOAT
19009- else if (STRCMP(item_compare_func, "f") == 0)
19022+ else if (STRCMP(info. item_compare_func, "f") == 0)
1901019023 {
19011- item_compare_func = NULL;
19012- item_compare_float = TRUE;
19024+ info. item_compare_func = NULL;
19025+ info. item_compare_float = TRUE;
1901319026 }
1901419027#endif
19015- else if (STRCMP(item_compare_func, "i") == 0)
19028+ else if (STRCMP(info. item_compare_func, "i") == 0)
1901619029 {
19017- item_compare_func = NULL;
19018- item_compare_ic = TRUE;
19030+ info. item_compare_func = NULL;
19031+ info. item_compare_ic = TRUE;
1901919032 }
1902019033 }
1902119034 }
@@ -19026,16 +19039,16 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1902619039 if (argvars[2].v_type != VAR_DICT)
1902719040 {
1902819041 EMSG(_(e_dictreq));
19029- return ;
19042+ goto theend ;
1903019043 }
19031- item_compare_selfdict = argvars[2].vval.v_dict;
19044+ info. item_compare_selfdict = argvars[2].vval.v_dict;
1903219045 }
1903319046 }
1903419047
1903519048 /* Make an array with each entry pointing to an item in the List. */
1903619049 ptrs = (sortItem_T *)alloc((int)(len * sizeof(sortItem_T)));
1903719050 if (ptrs == NULL)
19038- return ;
19051+ goto theend ;
1903919052
1904019053 i = 0;
1904119054 if (sort)
@@ -19048,20 +19061,21 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1904819061 ++i;
1904919062 }
1905019063
19051- item_compare_func_err = FALSE;
19052- item_compare_keep_zero = FALSE;
19064+ info. item_compare_func_err = FALSE;
19065+ info. item_compare_keep_zero = FALSE;
1905319066 /* test the compare function */
19054- if (item_compare_func != NULL
19067+ if (info. item_compare_func != NULL
1905519068 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
1905619069 == ITEM_COMPARE_FAIL)
1905719070 EMSG(_("E702: Sort compare function failed"));
1905819071 else
1905919072 {
1906019073 /* Sort the array with item pointers. */
1906119074 qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
19062- item_compare_func == NULL ? item_compare : item_compare2);
19075+ info.item_compare_func == NULL
19076+ ? item_compare : item_compare2);
1906319077
19064- if (!item_compare_func_err)
19078+ if (!info. item_compare_func_err)
1906519079 {
1906619080 /* Clear the List and append the items in sorted order. */
1906719081 l->lv_first = l->lv_last = l->lv_idx_item = NULL;
@@ -19076,9 +19090,9 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1907619090 int (*item_compare_func_ptr)(const void *, const void *);
1907719091
1907819092 /* f_uniq(): ptrs will be a stack of items to remove */
19079- item_compare_func_err = FALSE;
19080- item_compare_keep_zero = TRUE;
19081- item_compare_func_ptr = item_compare_func
19093+ info. item_compare_func_err = FALSE;
19094+ info. item_compare_keep_zero = TRUE;
19095+ item_compare_func_ptr = info. item_compare_func
1908219096 ? item_compare2 : item_compare;
1908319097
1908419098 for (li = l->lv_first; li != NULL && li->li_next != NULL;
@@ -19087,14 +19101,14 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1908719101 if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
1908819102 == 0)
1908919103 ptrs[i++].item = li;
19090- if (item_compare_func_err)
19104+ if (info. item_compare_func_err)
1909119105 {
1909219106 EMSG(_("E882: Uniq compare function failed"));
1909319107 break;
1909419108 }
1909519109 }
1909619110
19097- if (!item_compare_func_err)
19111+ if (!info. item_compare_func_err)
1909819112 {
1909919113 while (--i >= 0)
1910019114 {
@@ -19113,6 +19127,8 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
1911319127
1911419128 vim_free(ptrs);
1911519129 }
19130+ theend:
19131+ sortinfo = old_sortinfo;
1911619132}
1911719133
1911819134/*
0 commit comments