Hey,

    Attached is a patch which replaces the use of libc's quicksort
    and uses our own custom quicksort for quicksort sorting, giving
    the immediate benefit of allowing us to pass TSRMLS_CC to the callbacks,
    and avoid a TSRMLS_FETCH().  The patch also applies the changes to
    our mergesort implementation.

    I've put the function in a seperate file in Zend, zend_qsort.c
    (instead of as a file in php4/main) for two reasons:

    1) qsort() is used by Zend
    2) its a fairly common function, and re-implemented in order to play
    nice with Zend's TS mechanism, this should be made available to all
    programs using Zend.

    Comments are appreciated and welcome...  I'll commit after an
    appropriate mourning period if no one speaks up.

    -Sterling

Index: ext/hyperwave/hg_comm.c
===================================================================
RCS file: /repository/php4/ext/hyperwave/hg_comm.c,v
retrieving revision 1.44
diff -u -r1.44 hg_comm.c
--- ext/hyperwave/hg_comm.c     11 Aug 2001 16:38:32 -0000      1.44
+++ ext/hyperwave/hg_comm.c     17 Sep 2001 14:16:59 -0000
@@ -287,7 +287,7 @@
 * Return: As strcmp                                                    *
 ***********************************************************************/
 #ifdef newlist
-int fnCmpAnchors(const void *e1, const void *e2)
+int fnCmpAnchors(const void *e1, const void *e2 TSRMLS_DC)
 {
        ANCHOR *a1, **aa1, *a2, **aa2;
        zend_llist_element **ee1, **ee2;
@@ -298,7 +298,7 @@
        a1 = *aa1;
        a2 = *aa2;
 #else
-int fnCmpAnchors(ANCHOR *a1, ANCHOR *a2)
+int fnCmpAnchors(ANCHOR *a1, ANCHOR *a2 TSRMLS_DC)
 {
 #endif
        if(a1->start < a2->start)
Index: ext/hyperwave/hg_comm.h
===================================================================
RCS file: /repository/php4/ext/hyperwave/hg_comm.h,v
retrieving revision 1.16
diff -u -r1.16 hg_comm.h
--- ext/hyperwave/hg_comm.h     11 Aug 2001 16:38:39 -0000      1.16
+++ ext/hyperwave/hg_comm.h     17 Sep 2001 14:17:00 -0000
@@ -154,14 +154,14 @@
 void fnListAnchor(zend_llist *pAnchorList);
 zend_llist *fnCreateAnchorList(hw_objectID objID, char **anchors, char 
**docofanchorrec, char **reldestrec, int ancount, int anchormode);
 char *fnInsAnchorsIntoText(char *text, zend_llist *pAnchorList, char **bodytag, char 
**urlprefix);
-int fnCmpAnchors(const void *e1, const void *e2);
+int fnCmpAnchors(const void *e1, const void *e2 TSRMLS_DC);
 ANCHOR *fnAddAnchor(zend_llist *pAnchorList, int objectID, int start, int end);
 #else
 void fnDeleteAnchor(ANCHOR *ptr);
 void fnListAnchor(DLIST *pAnchorList);
 DLIST *fnCreateAnchorList(hw_objectID objID, char **anchors, char **docofanchorrec, 
char **reldestrec, int ancount, int anchormode);
 char *fnInsAnchorsIntoText(char *text, DLIST *pAnchorList, char **bodytag, char 
**urlprefix);
-int fnCmpAnchors(ANCHOR *a1, ANCHOR *a2);
+int fnCmpAnchors(ANCHOR *a1, ANCHOR *a2 TSRMLS_DC);
 ANCHOR *fnAddAnchor(DLIST *pAnchorList, int objectID, int start, int end);
 #endif
 extern void set_swap(int do_swap);
Index: ext/standard/array.c
===================================================================
RCS file: /repository/php4/ext/standard/array.c,v
retrieving revision 1.136
diff -u -r1.136 array.c
--- ext/standard/array.c        16 Sep 2001 20:49:57 -0000      1.136
+++ ext/standard/array.c        17 Sep 2001 14:17:08 -0000
@@ -114,14 +114,13 @@
        }
 }
 
-static int array_key_compare(const void *a, const void *b)
+static int array_key_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
-       pval result;
-       pval first;
-       pval second;
-       TSRMLS_FETCH();
+       zval result;
+       zval first;
+       zval second;
  
        f = *((Bucket **) a);
        s = *((Bucket **) b);
@@ -169,9 +168,9 @@
        return 0;
 }
 
-static int array_reverse_key_compare(const void *a, const void *b)
+static int array_reverse_key_compare(const void *a, const void *b TSRMLS_DC)
 {
-       return array_key_compare(a, b)*-1;
+       return array_key_compare(a, b TSRMLS_CC) * -1;
 }
 
 /* {{{ proto int krsort(array array_arg [, int sort_flags])
@@ -196,7 +195,7 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_reverse_key_compare, 0) == 
FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_reverse_key_compare, 0 
+TSRMLS_CC) == FAILURE) {
                return;
        }
        RETURN_TRUE;
@@ -225,7 +224,7 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_key_compare, 0) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_key_compare, 0 TSRMLS_CC) == 
+FAILURE) {
                return;
        }
        RETURN_TRUE;
@@ -261,14 +260,13 @@
  *
  * This is not correct any more, depends on what compare_func is set to.
  */
-static int array_data_compare(const void *a, const void *b)
+static int array_data_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
        pval result;
        pval *first;
        pval *second;
-       TSRMLS_FETCH();
  
        f = *((Bucket **) a);
        s = *((Bucket **) b);
@@ -301,9 +299,9 @@
        return 0;
 }
 
-static int array_reverse_data_compare(const void *a, const void *b)
+static int array_reverse_data_compare(const void *a, const void *b TSRMLS_DC)
 {
-       return array_data_compare(a, b)*-1;
+       return array_data_compare(a, b TSRMLS_CC)*-1;
 }
 
 static int array_natural_general_compare(const void *a, const void *b, int fold_case)
@@ -340,12 +338,12 @@
        return result;
 }
 
-static int array_natural_compare(const void *a, const void *b)
+static int array_natural_compare(const void *a, const void *b TSRMLS_DC)
 {
        return array_natural_general_compare(a, b, 0);
 }
 
-static int array_natural_case_compare(const void *a, const void *b)
+static int array_natural_case_compare(const void *a, const void *b TSRMLS_DC)
 {
        return array_natural_general_compare(a, b, 1);
 }
@@ -367,11 +365,11 @@
        }
 
        if (fold_case) {
-               if (zend_hash_sort(target_hash, qsort, array_natural_case_compare, 0) 
== FAILURE) {
+               if (zend_hash_sort(target_hash, zend_qsort, 
+array_natural_case_compare, 0 TSRMLS_CC) == FAILURE) {
                        return;
                }
        } else {
-               if (zend_hash_sort(target_hash, qsort, array_natural_compare, 0) == 
FAILURE) {
+               if (zend_hash_sort(target_hash, zend_qsort, array_natural_compare, 0 
+TSRMLS_CC) == FAILURE) {
                        return;
                }
        }
@@ -420,7 +418,7 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_data_compare, 0) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 0 TSRMLS_CC) 
+== FAILURE) {
                return;
        }
        RETURN_TRUE;
@@ -449,7 +447,7 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_reverse_data_compare, 0) == 
FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 0 
+TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -478,7 +476,7 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_data_compare, 1) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_data_compare, 1 TSRMLS_CC) 
+== FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -507,26 +505,25 @@
                sort_type_val = Z_LVAL_PP(sort_type);
        }
        set_compare_func(sort_type_val TSRMLS_CC);
-       if (zend_hash_sort(target_hash, qsort, array_reverse_data_compare, 1) == 
FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_reverse_data_compare, 1 
+TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
 }
 
 
-static int array_user_compare(const void *a, const void *b)
+static int array_user_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
-       pval **args[2];
-       pval *retval_ptr;
-       TSRMLS_FETCH();
+       zval **args[2];
+       zval *retval_ptr;
 
        f = *((Bucket **) a);
        s = *((Bucket **) b);
 
-       args[0] = (pval **) f->pData;
-       args[1] = (pval **) s->pData;
+       args[0] = (zval **) f->pData;
+       args[1] = (zval **) s->pData;
 
        if (call_user_function_ex(EG(function_table), NULL, 
*BG(user_compare_func_name), &retval_ptr, 2, args, 0, NULL TSRMLS_CC)==SUCCESS
                && retval_ptr) {
@@ -560,7 +557,7 @@
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
-       if (zend_hash_sort(target_hash, qsort, array_user_compare, 1) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 1 TSRMLS_CC) 
+== FAILURE) {
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
@@ -588,7 +585,7 @@
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
-       if (zend_hash_sort(target_hash, qsort, array_user_compare, 0) == FAILURE) {
+       if (zend_hash_sort(target_hash, zend_qsort, array_user_compare, 0 TSRMLS_CC) 
+== FAILURE) {
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
@@ -597,7 +594,7 @@
 }
 /* }}} */
 
-static int array_user_key_compare(const void *a, const void *b)
+static int array_user_key_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
@@ -605,7 +602,6 @@
        pval *args[2];
        pval retval;
        int status;
-       TSRMLS_FETCH();
 
        args[0] = &key1;
        args[1] = &key2;
@@ -664,7 +660,7 @@
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
-       if (zend_hash_sort(target_hash, qsort, array_user_key_compare, 0) == FAILURE) 
{
+       if (zend_hash_sort(target_hash, zend_qsort, array_user_key_compare, 0 
+TSRMLS_CC) == FAILURE) {
                BG(user_compare_func_name) = old_compare_func;
                RETURN_FALSE;
        }
@@ -856,7 +852,7 @@
                if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != 
IS_ARRAY) {
                        WRONG_PARAM_COUNT;
                }
-               if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 0, (void 
**) &result)==SUCCESS) {
+               if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 0, (void 
+**) &result TSRMLS_CC)==SUCCESS) {
                        *return_value = **result;
                        zval_copy_ctor(return_value);
                } else {
@@ -908,7 +904,7 @@
                if (zend_get_parameters_ex(1, &arr) == FAILURE || Z_TYPE_PP(arr) != 
IS_ARRAY) {
                        WRONG_PARAM_COUNT;
                }
-               if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 1, (void 
**) &result)==SUCCESS) {
+               if (zend_hash_minmax(Z_ARRVAL_PP(arr), array_data_compare, 1, (void 
+**) &result TSRMLS_CC)==SUCCESS) {
                        *return_value = **result;
                        zval_copy_ctor(return_value);
                } else {
@@ -1376,8 +1372,8 @@
 /* }}} */
 
 
-static int array_data_shuffle(const void *a, const void*b) {
-       TSRMLS_FETCH();
+static int array_data_shuffle(const void *a, const void *b TSRMLS_DC) 
+{
        return (php_rand(TSRMLS_C) % 2) ? 1 : -1;
 }
 
@@ -1395,7 +1391,7 @@
                php_error(E_WARNING, "Wrong datatype in shuffle() call");
                RETURN_FALSE;
        }
-       if (zend_hash_sort(Z_ARRVAL_PP(array), (sort_func_t)php_mergesort, 
array_data_shuffle, 1) == FAILURE) {
+       if (zend_hash_sort(Z_ARRVAL_PP(array), (sort_func_t)php_mergesort, 
+array_data_shuffle, 1 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -2276,12 +2272,12 @@
                arTmp[i] = p;
        arTmp[i] = NULL;
     set_compare_func(SORT_STRING TSRMLS_CC);
-       qsort((void *) arTmp, i, sizeof(Bucket *), array_data_compare);
+       zend_qsort((void *) arTmp, i, sizeof(Bucket *), array_data_compare TSRMLS_CC);
 
        /* go through the sorted array and delete duplicates from the copy */
        lastkept = arTmp;
        for (cmpdata = arTmp + 1; *cmpdata; cmpdata++) {
-               if (array_data_compare(lastkept, cmpdata)) {
+               if (array_data_compare(lastkept, cmpdata TSRMLS_CC)) {
                        lastkept = cmpdata;
                } else {
                        p = *cmpdata;
@@ -2334,7 +2330,7 @@
                for (p = hash->pListHead; p; p = p->pListNext)
                        *list++ = p;
                *list = NULL;
-               qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), 
array_data_compare);
+               zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), 
+array_data_compare TSRMLS_CC);
        }
 
        /* copy the argument array */
@@ -2344,7 +2340,7 @@
        /* go through the lists and look for common values */
        while (*ptrs[0]) {
                for (i=1; i<argc; i++) {
-                       while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], 
ptrs[i]))))
+                       while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], 
+ptrs[i] TSRMLS_CC))))
                                ptrs[i]++;
                        if (!*ptrs[i]) {
                                /* delete any values corresponding to remains of 
ptrs[0] */
@@ -2374,7 +2370,7 @@
                                        zend_hash_index_del(Z_ARRVAL_P(return_value), 
p->h);  
                                if (!*++ptrs[0])
                                        goto out;
-                               if (0 <= array_data_compare(ptrs[0], ptrs[i]))
+                               if (0 <= array_data_compare(ptrs[0], ptrs[i] 
+TSRMLS_CC))
                                        break;
                        }
                } else {
@@ -2383,7 +2379,7 @@
                        for (;;) {
                                if (!*++ptrs[0])
                                        goto out;
-                               if (array_data_compare(ptrs[0]-1, ptrs[0]))
+                               if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC))
                                        break;
                        }
                }
@@ -2439,7 +2435,7 @@
                for (p = hash->pListHead; p; p = p->pListNext)
                        *list++ = p;
                *list = NULL;
-               qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), 
array_data_compare);
+               zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), 
+array_data_compare TSRMLS_CC);
        }
 
        /* copy the argument array */
@@ -2451,7 +2447,7 @@
        while (*ptrs[0]) {
                c = 1;
                for (i=1; i<argc; i++) {
-                       while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], 
ptrs[i]))))
+                       while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], 
+ptrs[i] TSRMLS_CC))))
                                ptrs[i]++;
                        if (!c) {
                                if (*ptrs[i])
@@ -2470,7 +2466,7 @@
                                        zend_hash_index_del(Z_ARRVAL_P(return_value), 
p->h);  
                                if (!*++ptrs[0])
                                        goto out;
-                               if (array_data_compare(ptrs[0]-1, ptrs[0]))
+                               if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC))
                                        break;
                        }
                } else {
@@ -2479,7 +2475,7 @@
                        for (;;) {
                                if (!*++ptrs[0])
                                        goto out;
-                               if (array_data_compare(ptrs[0]-1, ptrs[0]))
+                               if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC))
                                        break;
                        }
                }
@@ -2499,14 +2495,13 @@
 #define MULTISORT_TYPE 1
 #define MULTISORT_LAST 2
 
-int multisort_compare(const void *a, const void *b)
+int multisort_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket**          ab = *(Bucket ***)a;
        Bucket**          bb = *(Bucket ***)b;
        int                       r;
        int                       result = 0;
        zval              temp;
-       TSRMLS_FETCH();
        
        r = 0;
        do {
@@ -2670,7 +2665,7 @@
                indirect[k][num_arrays] = NULL;
 
        /* Do the actual sort magic - bada-bim, bada-boom. */
-       qsort(indirect, array_size, sizeof(Bucket **), multisort_compare);
+       zend_qsort(indirect, array_size, sizeof(Bucket **), multisort_compare 
+TSRMLS_CC);
        
        /* Restructure the arrays based on sorted indirect - this is mostly
           taken from zend_hash_sort() function. */
@@ -2791,7 +2786,7 @@
        }  
 
        if (num_req_val == num_avail) {
-               if (zend_hash_sort(Z_ARRVAL_P(return_value), 
(sort_func_t)php_mergesort, array_data_shuffle, 1) == FAILURE) {
+               if (zend_hash_sort(Z_ARRVAL_P(return_value), 
+(sort_func_t)php_mergesort, array_data_shuffle, 1 TSRMLS_CC) == FAILURE) {
                        zval_dtor(return_value);
                        RETURN_FALSE;
                }
Index: ext/standard/php_array.h
===================================================================
RCS file: /repository/php4/ext/standard/php_array.h,v
retrieving revision 1.27
diff -u -r1.27 php_array.h
--- ext/standard/php_array.h    30 Jul 2001 04:58:05 -0000      1.27
+++ ext/standard/php_array.h    17 Sep 2001 14:17:09 -0000
@@ -81,7 +81,7 @@
 
 HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **);
 PHPAPI void php_array_merge(HashTable *dest, HashTable *src, int recursive);
-int multisort_compare(const void *a, const void *b);
+int multisort_compare(const void *a, const void *b TSRMLS_DC);
 
 typedef struct {
        int *multisort_flags[2];
Index: main/mergesort.c
===================================================================
RCS file: /repository/php4/main/mergesort.c,v
retrieving revision 1.10
diff -u -r1.10 mergesort.c
--- main/mergesort.c    9 Sep 2001 13:29:28 -0000       1.10
+++ main/mergesort.c    17 Sep 2001 14:17:11 -0000
@@ -64,8 +64,8 @@
 #include <winsock.h> /* Includes definition for u_char */
 #endif
 
-static void setup(u_char *list1, u_char *list2, size_t n, size_t size, int 
(*cmp)(const void *, const void *));
-static void insertionsort(u_char *a, size_t n, size_t size, int (*cmp)(const void *, 
const void *));
+static void setup(u_char *list1, u_char *list2, size_t n, size_t size, int 
+(*cmp)(const void *, const void * TSRMLS_DC) TSRMLS_DC);
+static void insertionsort(u_char *a, size_t n, size_t size, int (*cmp)(const void *, 
+const void * TSRMLS_DC) TSRMLS_DC);
 
 #define ISIZE sizeof(int)
 #define PSIZE sizeof(u_char *)
@@ -100,7 +100,7 @@
 /* {{{ php_mergesort
  * Arguments are as for qsort.
  */
-int php_mergesort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, 
const void *))
+int php_mergesort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, 
+const void * TSRMLS_DC) TSRMLS_DC)
 {
        register unsigned int i;
        register int sense;
@@ -128,7 +128,7 @@
                return (-1);
 
        list1 = base;
-       setup(list1, list2, nmemb, size, cmp);
+       setup(list1, list2, nmemb, size, cmp TSRMLS_CC);
        last = list2 + nmemb * size;
        i = big = 0;
        while (*EVAL(list2) != last) {
@@ -142,7 +142,7 @@
                        p2 = *EVAL(p2);
                l2 = list1 + (p2 - list2);
                while (f1 < l1 && f2 < l2) {
-                       if ((*cmp)(f1, f2) <= 0) {
+                       if ((*cmp)(f1, f2 TSRMLS_CC) <= 0) {
                                q = f2;
                                b = f1, t = l1;
                                sense = -1;
@@ -152,7 +152,7 @@
                                sense = 0;
                        }
                        if (!big) {     /* here i = 0 */
-                               while ((b += size) < t && cmp(q, b) >sense)
+                               while ((b += size) < t && cmp(q, b TSRMLS_CC) >sense)
                                        if (++i == 6) {
                                                big = 1;
                                                goto EXPONENTIAL;
@@ -161,12 +161,12 @@
 EXPONENTIAL:                   for (i = size; ; i <<= 1)
                                        if ((p = (b + i)) >= t) {
                                                if ((p = t - size) > b &&
-                                                   (*cmp)(q, p) <= sense)
+                                                   (*cmp)(q, p TSRMLS_CC) <= sense)
                                                        t = p;
                                                else
                                                        b = p;
                                                break;
-                                       } else if ((*cmp)(q, p) <= sense) {
+                                       } else if ((*cmp)(q, p TSRMLS_CC) <= sense) {
                                                t = p;
                                                if (i == size)
                                                        big = 0;
@@ -175,7 +175,7 @@
                                                b = p;
                                while (t > b+size) {
                                        i = (((t - b) / size) >> 1) * size;
-                                       if ((*cmp)(q, p = b + i) <= sense)
+                                       if ((*cmp)(q, p = b + i TSRMLS_CC) <= sense)
                                                t = p;
                                        else
                                                b = p;
@@ -183,7 +183,7 @@
                                goto COPY;
 FASTCASE:                      while (i > size)
                                        if ((*cmp)(q,
-                                               p = b + (i >>= 1)) <= sense)
+                                               p = b + (i >>= 1) TSRMLS_CC) <= sense)
                                                t = p;
                                        else
                                                b = p;
@@ -260,14 +260,14 @@
  * when THRESHOLD/2 pairs compare with same sense.  (Only used when NATURAL
  * is defined.  Otherwise simple pairwise merging is used.)
  */
-static void setup(u_char *list1, u_char *list2, size_t n, size_t size, int 
(*cmp)(const void *, const void *))
+static void setup(u_char *list1, u_char *list2, size_t n, size_t size, int 
+(*cmp)(const void *, const void * TSRMLS_DC) TSRMLS_DC)
 {
        int i, length, size2, tmp, sense;
        u_char *f1, *f2, *s, *l2, *last, *p2;
 
        size2 = size*2;
        if (n <= 5) {
-               insertionsort(list1, n, size, cmp);
+               insertionsort(list1, n, size, cmp TSRMLS_CC);
                *EVAL(list2) = (u_char*) list2 + n*size;
                return;
        }
@@ -276,19 +276,19 @@
         * for simplicity.
         */
        i = 4 + (n & 1);
-       insertionsort(list1 + (n - i) * size, i, size, cmp);
+       insertionsort(list1 + (n - i) * size, i, size, cmp TSRMLS_CC);
        last = list1 + size * (n - i);
        *EVAL(list2 + (last - list1)) = list2 + n * size;
 
 #ifdef NATURAL
        p2 = list2;
        f1 = list1;
-       sense = (cmp(f1, f1 + size) > 0);
+       sense = (cmp(f1, f1 + size TSRMLS_CC) > 0);
        for (; f1 < last; sense = !sense) {
                length = 2;
                                        /* Find pairs with same sense. */
                for (f2 = f1 + size2; f2 < last; f2 += size2) {
-                       if ((cmp(f2, f2+ size) > 0) != sense)
+                       if ((cmp(f2, f2+ size TSRMLS_CC) > 0) != sense)
                                break;
                        length += 2;
                }
@@ -301,7 +301,7 @@
                } else {                                /* Natural merge */
                        l2 = f2;
                        for (f2 = f1 + size2; f2 < l2; f2 += size2) {
-                               if ((cmp(f2-size, f2) > 0) != sense) {
+                               if ((cmp(f2-size, f2 TSRMLS_CC) > 0) != sense) {
                                        p2 = *EVAL(p2) = f2 - list1 + list2;
                                        if (sense > 0)
                                                reverse(f1, f2-size);
@@ -311,7 +311,7 @@
                        if (sense > 0)
                                reverse (f1, f2-size);
                        f1 = f2;
-                       if (f2 < last || cmp(f2 - size, f2) > 0)
+                       if (f2 < last || cmp(f2 - size, f2 TSRMLS_CC) > 0)
                                p2 = *EVAL(p2) = f2 - list1 + list2;
                        else
                                p2 = *EVAL(p2) = list2 + n*size;
@@ -320,7 +320,7 @@
 #else          /* pairwise merge only. */
        for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
                p2 = *EVAL(p2) = p2 + size2;
-               if (cmp (f1, f1 + size) > 0)
+               if (cmp (f1, f1 + size TSRMLS_CC) > 0)
                        swap(f1, f1 + size);
        }
 #endif /* NATURAL */
@@ -331,7 +331,7 @@
  * This is to avoid out-of-bounds addresses in sorting the
  * last 4 elements.
  */
-static void insertionsort(u_char *a, size_t n, size_t size, int (*cmp)(const void *, 
const void *))
+static void insertionsort(u_char *a, size_t n, size_t size, int (*cmp)(const void *, 
+const void * TSRMLS_DC) TSRMLS_DC)
 {
        u_char *ai, *s, *t, *u, tmp;
        int i;
@@ -339,7 +339,7 @@
        for (ai = a+size; --n >= 1; ai += size)
                for (t = ai; t > a; t -= size) {
                        u = t - size;
-                       if (cmp(u, t) <= 0)
+                       if (cmp(u, t TSRMLS_CC) <= 0)
                                break;
                        swap(u, t);
                }
@@ -351,6 +351,6 @@
  * tab-width: 4
  * c-basic-offset: 4
  * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
  */
Index: main/php.h
===================================================================
RCS file: /repository/php4/main/php.h,v
retrieving revision 1.156
diff -u -r1.156 php.h
--- main/php.h  9 Sep 2001 13:29:28 -0000       1.156
+++ main/php.h  17 Sep 2001 14:17:11 -0000
@@ -32,6 +32,7 @@
 
 #include "php_version.h"
 #include "zend.h"
+#include "zend_qsort.h"
 #include "php_compat.h"
 
 #include "zend_API.h"
@@ -240,7 +241,7 @@
 /* functions */
 int php_startup_internal_extensions(void);
 
-int php_mergesort(void *base, size_t nmemb, register size_t size, int (*cmp) (const 
void *, const void *));
+int php_mergesort(void *base, size_t nmemb, register size_t size, int (*cmp)(const 
+void *, const void * TSRMLS_DC) TSRMLS_DC);
 
 PHPAPI void php_register_pre_request_shutdown(void (*func)(void *), void *userdata);
 
? Zend/zend_qsort.c
? Zend/zend_qsort.h
Index: Zend/Makefile.am
===================================================================
RCS file: /repository/Zend/Makefile.am,v
retrieving revision 1.41
diff -u -r1.41 Makefile.am
--- Zend/Makefile.am    2001/08/06 13:48:51     1.41
+++ Zend/Makefile.am    2001/09/17 14:18:09
@@ -13,7 +13,7 @@
        zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
        zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
        zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
-       zend_ini.c
+       zend_ini.c zend_qsort.c
 
 libZend_la_LDFLAGS = @EXTRA_LIBS@
 
Index: Zend/zend_hash.c
===================================================================
RCS file: /repository/Zend/zend_hash.c,v
retrieving revision 1.79
diff -u -r1.79 zend_hash.c
--- Zend/zend_hash.c    2001/08/20 11:15:17     1.79
+++ Zend/zend_hash.c    2001/09/17 14:18:13
@@ -1088,7 +1088,7 @@
 
 
 ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
-                                                       compare_func_t compar, int 
renumber)
+                                                       compare_func_t compar, int 
+renumber TSRMLS_DC)
 {
        Bucket **arTmp;
        Bucket *p;
@@ -1111,7 +1111,7 @@
                i++;
        }
 
-       (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar);
+       (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC);
 
        HANDLE_BLOCK_INTERRUPTIONS();
        ht->pListHead = arTmp[0];
@@ -1134,7 +1134,7 @@
                i=0;
                while (p != NULL) {
                        p->nKeyLength = 0;
-                       p->h = i++;
+                       ;
                        p = p->pListNext;
                }
                ht->nNextFreeElement = i;
@@ -1212,7 +1212,7 @@
                                }
                        }
                }
-               result = compar(p1->pData, pData2);
+               result = compar(p1->pData, pData2 TSRMLS_CC);
                if (result!=0) {
                        HASH_UNPROTECT_RECURSION(ht1); 
                        HASH_UNPROTECT_RECURSION(ht2); 
@@ -1230,7 +1230,7 @@
 }
 
 
-ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar) (const void *, const void 
*), int flag, void **pData)
+ZEND_API int zend_hash_minmax(HashTable *ht, compare_func_t compar, int flag, void 
+**pData TSRMLS_DC)
 {
        Bucket *p, *res;
 
@@ -1244,11 +1244,11 @@
        res = p = ht->pListHead;
        while ((p = p->pListNext)) {
                if (flag) {
-                       if (compar(&res, &p) < 0) { /* max */
+                       if (compar(&res, &p TSRMLS_CC) < 0) { /* max */
                                res = p;
                        }
                } else {
-                       if (compar(&res, &p) > 0) { /* min */
+                       if (compar(&res, &p TSRMLS_CC) > 0) { /* min */
                                res = p;
                        }
                }
Index: Zend/zend_hash.h
===================================================================
RCS file: /repository/Zend/zend_hash.h,v
retrieving revision 1.52
diff -u -r1.52 zend_hash.h
--- Zend/zend_hash.h    2001/08/20 11:15:17     1.52
+++ Zend/zend_hash.h    2001/09/17 14:18:13
@@ -34,8 +34,8 @@
 #define HASH_DEL_INDEX 1
 
 typedef ulong (*hash_func_t)(char *arKey, uint nKeyLength);
-typedef int  (*compare_func_t)(const void *, const void *);
-typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t);
+typedef int  (*compare_func_t)(const void *, const void * TSRMLS_DC);
+typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t 
+TSRMLS_DC);
 typedef void (*dtor_func_t)(void *pDest);
 typedef void (*copy_ctor_func_t)(void *pElement);
 
@@ -179,9 +179,9 @@
 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t 
pCopyConstructor, void *tmp, uint size);
 ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t 
pCopyConstructor, void *tmp, uint size, int overwrite);
 ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, 
copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, 
void *p_new));
-ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t 
compare_func, int renumber);
+ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t 
+compare_func, int renumber TSRMLS_DC);
 ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, 
zend_bool ordered TSRMLS_DC);
-ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar)(const void *, const void 
*), int flag, void **pData);
+ZEND_API int zend_hash_minmax(HashTable *ht, compare_func_t compar, int flag, void 
+**pData TSRMLS_DC);
 
 ZEND_API int zend_hash_num_elements(HashTable *ht);
 
Index: Zend/zend_ini.c
===================================================================
RCS file: /repository/Zend/zend_ini.c,v
retrieving revision 1.15
diff -u -r1.15 zend_ini.c
--- Zend/zend_ini.c     2001/07/31 06:07:25     1.15
+++ Zend/zend_ini.c     2001/09/17 14:18:14
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include "zend.h"
+#include "zend_qsort.h"
 #include "zend_API.h"
 #include "zend_ini.h"
 #include "zend_alloc.h"
@@ -97,7 +98,7 @@
 }
 
 
-static int ini_key_compare(const void *a, const void *b)
+static int ini_key_compare(const void *a, const void *b TSRMLS_DC)
 {
        Bucket *f;
        Bucket *s;
@@ -119,7 +120,7 @@
 
 ZEND_API void zend_ini_sort_entries(TSRMLS_D)
 {
-       zend_hash_sort(&EG(ini_directives), qsort, ini_key_compare, 0);
+       zend_hash_sort(&EG(ini_directives), zend_qsort, ini_key_compare, 0 TSRMLS_CC);
 }
 
 /*
Index: Zend/zend_llist.c
===================================================================
RCS file: /repository/Zend/zend_llist.c,v
retrieving revision 1.28
diff -u -r1.28 zend_llist.c
--- Zend/zend_llist.c   2001/08/31 20:42:24     1.28
+++ Zend/zend_llist.c   2001/09/17 14:18:15
@@ -186,7 +186,7 @@
        }
 }
 
-ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func)
+ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func 
+TSRMLS_DC)
 {
        size_t i;
 
@@ -205,7 +205,7 @@
                *ptr++ = element;
        }
 
-       qsort(elements, l->count, sizeof(zend_llist_element *), (int (*)(const void *, 
const void *)) comp_func);
+       zend_qsort(elements, l->count, sizeof(zend_llist_element *), (compare_func_t) 
+comp_func TSRMLS_CC);
 
        l->head = elements[0];
        elements[0]->prev = NULL;
Index: Zend/zend_llist.h
===================================================================
RCS file: /repository/Zend/zend_llist.h,v
retrieving revision 1.22
diff -u -r1.22 zend_llist.h
--- Zend/zend_llist.h   2001/08/31 20:18:43     1.22
+++ Zend/zend_llist.h   2001/09/17 14:18:15
@@ -30,7 +30,7 @@
 } zend_llist_element;
 
 typedef void (*llist_dtor_func_t)(void *);
-typedef int (*llist_compare_func_t)(const zend_llist_element *, const 
zend_llist_element *);
+typedef int (*llist_compare_func_t)(const zend_llist_element *, const 
+zend_llist_element * TSRMLS_DC);
 typedef void (*llist_apply_with_args_func_t)(void *data, int num_args, va_list args 
TSRMLS_DC);
 typedef void (*llist_apply_with_arg_func_t)(void *data, void *arg TSRMLS_DC);
 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
@@ -61,7 +61,7 @@
 ZEND_API void zend_llist_apply_with_argument(zend_llist *l, 
llist_apply_with_arg_func_t func, void *arg TSRMLS_DC);
 ZEND_API void zend_llist_apply_with_arguments(zend_llist *l, 
llist_apply_with_args_func_t func TSRMLS_DC, int num_args, ...);
 ZEND_API int zend_llist_count(zend_llist *l);
-ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func);
+ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func 
+TSRMLS_DC);
 
 /* traversal */
 ZEND_API void *zend_llist_get_first_ex(zend_llist *l, zend_llist_position *pos);
/*
   +----------------------------------------------------------------------+
   | Zend Engine                                                          |
   +----------------------------------------------------------------------+
   | Copyright (c) 1998-2001 Zend Technologies Ltd. (http://www.zend.com) |
   +----------------------------------------------------------------------+
   | This source file is subject to version 0.92 of the Zend license,     |
   | that is bundled with this package in the file LICENSE, and is        | 
   | available at through the world-wide-web at                           |
   | http://www.zend.com/license/0_92.txt.                                |
   | If you did not receive a copy of the Zend license and are unable to  |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.              |
   +----------------------------------------------------------------------+
   | Authors: Sterling Hughes <[EMAIL PROTECTED]>                          |
   +----------------------------------------------------------------------+
*/

#include "zend.h"

#include <limits.h>

#define QSORT_STACK_SIZE (sizeof(size_t) * CHAR_BIT)

static void _zend_qsort_swap(void *a, void *b, size_t siz)
{
        register size_t i;
        register int    t_i;
        register char   t_c;
        
        for (i = sizeof(int); i <= siz; i += sizeof(int)) {
                t_i = *(int *) a;
                *((int *) a)++ = *(int *) b;
                *((int *) b)++ = t_i;
        }

        for (i = i - sizeof(int) + 1; i <= siz; ++i) {
                t_c = *(char *) a;
                *((char *) a)++ = *(char *) b;
                *((char *) b)++ = t_c;
        }
}

ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare 
TSRMLS_DC)
{
        void           *begin_stack[QSORT_STACK_SIZE];
        void           *end_stack[QSORT_STACK_SIZE];
        register char  *begin;
        register char  *end;
        register char  *seg1;
        register char  *seg2;
        register char  *seg2p;
        register int    loop;
        uint            offset;

        begin_stack[0] = (char *) base;
        end_stack[0]   = (char *) base + ((nmemb - 1) * siz);

        for (loop = 0; loop >= 0; --loop) {
                begin = begin_stack[loop];
                end   = end_stack[loop];

                while (begin < end) {
                        offset = (end - begin) >> 1;
                        _zend_qsort_swap(begin, begin + (offset - (offset % siz)), 
siz);

                        seg1 = begin + siz;
                        seg2 = end;

                        while (1) {
                                for (; seg1 < seg2 && compare(begin, seg1 TSRMLS_CC) > 
0;
                                     seg1 += siz);

                                for (; seg2 >= seg1 && compare(seg2, begin TSRMLS_CC) 
> 0;
                                     seg2 -= siz);
                                
                                if (seg1 >= seg2)
                                        break;
                                
                                _zend_qsort_swap(seg1, seg2, siz);

                                seg1 += siz;
                                seg2 -= siz;
                        }

                        _zend_qsort_swap(begin, seg2, siz);

                        seg2p = seg2;
                        
                        if ((seg2p - begin) <= (end - seg2p)) {
                                if ((seg2p + siz) < end) {
                                        begin_stack[loop] = seg2p + siz;
                                        end_stack[loop++] = end;
                                }
                                end = seg2p - siz;
                        }
                        else {
                                if ((seg2p - siz) > begin) {
                                        begin_stack[loop] = begin;
                                        end_stack[loop++] = seg2p - siz;
                                }
                                begin = seg2p + siz;
                        }
                }
        }
}
/*
   +----------------------------------------------------------------------+
   | Zend Engine                                                          |
   +----------------------------------------------------------------------+
   | Copyright (c) 1998-2001 Zend Technologies Ltd. (http://www.zend.com) |
   +----------------------------------------------------------------------+
   | This source file is subject to version 0.92 of the Zend license,     |
   | that is bundled with this package in the file LICENSE, and is        | 
   | available at through the world-wide-web at                           |
   | http://www.zend.com/license/0_92.txt.                                |
   | If you did not receive a copy of the Zend license and are unable to  |
   | obtain it through the world-wide-web, please send a note to          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.              |
   +----------------------------------------------------------------------+
   | Authors: Sterling Hughes <[EMAIL PROTECTED]>                          |
   +----------------------------------------------------------------------+
*/

#ifndef ZEND_QSORT_H
#define ZEND_QSORT_H

BEGIN_EXTERN_C()
ZEND_API void zend_qsort(void *base, size_t nmemb, size_t siz, compare_func_t compare 
TSRMLS_DC);
END_EXTERN_C()

#endif       /* ZEND_QSORT_H */
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to