From 6807378d31ddb6290ea6890440015e7d8bdccfc0 Mon Sep 17 00:00:00 2001
From: Martin Stjernholm <mast@lysator.liu.se>
Date: Sun, 17 Oct 2010 01:44:09 +0200
Subject: [PATCH] Introduced a special value for unorderedness from cmpfuns.

The stable sort function masks it out, so that stable sorting work together
with the previous commit.
---
 .gitattributes |  1 -
 src/array.c    | 27 +++++++++++++++------------
 src/array.h    |  8 +++++++-
 3 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index 913bd7130d..44d4880815 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -319,7 +319,6 @@ testfont binary
 /src/aclocal.m4 foreign_ident
 /src/alloca.c foreign_ident
 /src/apply_low.h foreign_ident
-/src/array.h foreign_ident
 /src/backend.h foreign_ident
 /src/bignum.h foreign_ident
 /src/block_alloc_h.h foreign_ident
diff --git a/src/array.c b/src/array.c
index f6ffdf9057..e1e44b60b5 100644
--- a/src/array.c
+++ b/src/array.c
@@ -910,12 +910,13 @@ INT32 *get_order(struct array *v, cmpfun fun)
   return current_order;
 }
 
-/* Returns 2 if no relation is established through lfun calls, or 3 if
- * no order defining lfuns (i.e. `< or `>) were found. */
+/* Returns CMPFUN_UNORDERED if no relation is established through lfun
+ * calls, or -CMPFUN_UNORDERED if no order defining lfuns (i.e. `< or
+ * `>) were found. */
 static int lfun_cmp (const struct svalue *a, const struct svalue *b)
 {
   struct program *p;
-  int default_res = 3, fun;
+  int default_res = -CMPFUN_UNORDERED, fun;
 
   if (a->type == T_OBJECT && (p = a->u.object->prog)) {
     if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_LT)) != -1) {
@@ -928,7 +929,7 @@ static int lfun_cmp (const struct svalue *a, const struct svalue *b)
 	return -1;
       }
       pop_stack();
-      default_res = 2;
+      default_res = CMPFUN_UNORDERED;
     }
 
     if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_GT)) != -1) {
@@ -941,7 +942,7 @@ static int lfun_cmp (const struct svalue *a, const struct svalue *b)
 	return 1;
       }
       pop_stack();
-      default_res = 2;
+      default_res = CMPFUN_UNORDERED;
     }
 
     if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_EQ)) != -1) {
@@ -967,7 +968,7 @@ static int lfun_cmp (const struct svalue *a, const struct svalue *b)
 	return 1;
       }
       pop_stack();
-      default_res = 2;
+      default_res = CMPFUN_UNORDERED;
     }
 
     if ((fun = FIND_LFUN(p->inherits[b->subtype].prog, LFUN_GT)) != -1) {
@@ -980,7 +981,7 @@ static int lfun_cmp (const struct svalue *a, const struct svalue *b)
 	return -1;
       }
       pop_stack();
-      default_res = 2;
+      default_res = CMPFUN_UNORDERED;
     }
 
     if ((fun = FIND_LFUN(p->inherits[b->subtype].prog, LFUN_EQ)) != -1) {
@@ -1046,7 +1047,7 @@ static int obj_or_func_cmp (const struct svalue *a, const struct svalue *b)
 
   res = lfun_cmp (a, b);
 
-  if (res == 3) {
+  if (res == -CMPFUN_UNORDERED) {
     /* If the objects had no inequality comparison lfuns to call, use
      * their pointers to get a well defined internal sort order. Let's
      * also group objects cloned from the same program. */
@@ -1056,7 +1057,7 @@ static int obj_or_func_cmp (const struct svalue *a, const struct svalue *b)
       return a->u.object->prog < b->u.object->prog ? -1 : 1;
   }
 
-  return res == 2 ? -1 : res;
+  return res;
 }
 
 int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b)
@@ -1065,7 +1066,7 @@ int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b)
   if (typediff) {
     if (a->type == T_OBJECT || b->type == T_OBJECT) {
       int res = lfun_cmp (a, b);
-      if (res < 2) return res;
+      if (res != -CMPFUN_UNORDERED) return res;
     }
     return typediff;
   }
@@ -1133,7 +1134,7 @@ int alpha_svalue_cmpfun(const struct svalue *a, const struct svalue *b)
   if (typediff) {
     if (a->type == T_OBJECT || b->type == T_OBJECT) {
       int res = lfun_cmp (a, b);
-      if (res < 2) return res;
+      if (res != -CMPFUN_UNORDERED) return res;
     }
     return typediff;
   }
@@ -1242,7 +1243,9 @@ PMOD_EXPORT void sort_array_destructively(struct array *v)
 
 #define SORT_BY_INDEX
 #define EXTRA_LOCALS int cmpfun_res;
-#define CMP(X,Y) ((cmpfun_res = alpha_svalue_cmpfun(svals + X, svals + Y)) ? \
+#define CMP(X,Y) ((cmpfun_res =						\
+		     (alpha_svalue_cmpfun(svals + X, svals + Y) &	\
+		      ~CMPFUN_UNORDERED)) ?				\
 		  cmpfun_res : pos[X] - pos[Y])
 #define SWAP(X,Y) {							\
   {struct svalue tmp = svals[X]; svals[X] = svals[Y]; svals[Y] = tmp;}	\
diff --git a/src/array.h b/src/array.h
index 15c3b6cb49..1094a17ada 100644
--- a/src/array.h
+++ b/src/array.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: array.h,v 1.84 2009/11/28 13:13:30 mast Exp $
+|| $Id$
 */
 
 #ifndef ARRAY_H
@@ -94,6 +94,12 @@ extern struct array *gc_internal_array;
 #define allocate_array(X) low_allocate_array((X),0)
 #define allocate_array_no_init(X,Y) low_allocate_array((X),(Y))
 
+/* Special value used for cmpfuns to signify that two values aren't
+ * equal and have no order relation, i.e. one is neither greater nor
+ * lesser than the other. It consists of the largest bit (under the
+ * sign bit) set. */
+#define CMPFUN_UNORDERED (INT_MAX - (INT_MAX >> 1))
+
 typedef int (*cmpfun)(const struct svalue *, const struct svalue *);
 typedef int (*short_cmpfun)(union anything *, union anything *);
 typedef short_cmpfun (*cmpfun_getter)(TYPE_T);
-- 
GitLab