diff --git a/src/array.c b/src/array.c
index aee1a4f9e06212cee72a5038eab0a9e32da083ec..887ec3277ddcd93039a23b04870afd07de078c0d 100644
--- a/src/array.c
+++ b/src/array.c
@@ -23,7 +23,7 @@
 #include "stuff.h"
 #include "bignum.h"
 
-RCSID("$Id: array.c,v 1.92 2000/10/20 10:05:40 grubba Exp $");
+RCSID("$Id: array.c,v 1.93 2000/11/08 20:03:45 hubbe Exp $");
 
 PMOD_EXPORT struct array empty_array=
 {
@@ -404,9 +404,6 @@ PMOD_EXPORT struct array *array_remove(struct array *v,INT32 index)
   struct array *a;
 
 #ifdef PIKE_DEBUG
-  if(v->refs>1)
-    fatal("Array remove on array with many references.\n");
-
   if(index<0 || index >= v->size)
     fatal("Illegal argument to array_remove.\n");
 #endif
@@ -660,54 +657,121 @@ INT32 *get_order(struct array *v, cmpfun fun)
   return current_order;
 }
 
-static int set_svalue_cmpfun(struct svalue *a, struct svalue *b)
+static INLINE int set_svalue_cmpfun(struct svalue *a, struct svalue *b)
 {
-  INT32 tmp;
-  if((tmp=(a->type - b->type))) return tmp;
-  switch(a->type)
+  INT32 def,fun;
+  if(a->type == b->type)
   {
-  case T_FLOAT:
-    if(a->u.float_number < b->u.float_number) return -1;
-    if(a->u.float_number > b->u.float_number) return 1;
-    return 0;
+    switch(a->type)
+    {
+      case T_FLOAT:
+	if(a->u.float_number < b->u.float_number) return -1;
+	if(a->u.float_number > b->u.float_number) return 1;
+	return 0;
+	
+      case T_FUNCTION:
+	if(a->u.refs < b->u.refs) return -1;
+	if(a->u.refs > b->u.refs) return 1;
+	return a->subtype - b->subtype;
+	
+      case T_INT:
+	if(a->u.integer < b->u.integer) return -1;
+	if(a->u.integer > b->u.integer) return 1;
+	return 0;
+	
+      default:
+	if(a->u.refs < b->u.refs) return -1;
+	if(a->u.refs > b->u.refs) return 1;
+	return 0;
 
-  case T_FUNCTION:
-    if(a->u.refs < b->u.refs) return -1;
-    if(a->u.refs > b->u.refs) return 1;
-    return a->subtype - b->subtype;
+      case T_OBJECT:
+	if(a->u.object == b->u.object) return 0;
+	if(a->u.refs < b->u.refs) { def=-1; break; }
+	if(a->u.refs > b->u.refs) { def=1; break; }
+	def=0;
+	break;
+    }
+  }else{
+    def=a->type - b->type;
+  }
 
-  case T_INT:
-    if(a->u.integer < b->u.integer) return -1;
-    if(a->u.integer > b->u.integer) return 1;
+  if(a->type == T_OBJECT && a->u.object->prog && 
+     FIND_LFUN(a->u.object->prog,LFUN_LT) != -1)
+  {
+    push_svalue(b);
+    apply_lfun(a->u.object,LFUN_LT,1);
+    if(!IS_ZERO(sp-1))
+    {
+      pop_stack();
+      return -1;
+    }else{
+      pop_stack();
+    }
+    
+    push_svalue(b);
+    apply_lfun(a->u.object,LFUN_GT,1);
+    if(!IS_ZERO(sp-1))
+    {
+      pop_stack();
+      return 1;
+    }else{
+      pop_stack();
+    }
     return 0;
+  }
 
-  default:
-    if(a->u.refs < b->u.refs) return -1;
-    if(a->u.refs > b->u.refs) return 1;
+  if(b->type == T_OBJECT && b->u.object->prog && 
+     FIND_LFUN(b->u.object->prog,LFUN_LT) != -1)
+  {
+    push_svalue(a);
+    apply_lfun(b->u.object,LFUN_LT,1);
+    if(!IS_ZERO(sp-1))
+    {
+      pop_stack();
+      return 1;
+    }else{
+      pop_stack();
+    }
+    
+    push_svalue(a);
+    apply_lfun(b->u.object,LFUN_GT,1);
+    if(!IS_ZERO(sp-1))
+    {
+      pop_stack();
+      return -1;
+    }else{
+      pop_stack();
+    }
     return 0;
   }
+
+  return def;
 }
 
 static int switch_svalue_cmpfun(struct svalue *a, struct svalue *b)
 {
-  if(a->type != b->type) return a->type - b->type;
-  switch(a->type)
+  if(a->type == b->type)
   {
-  case T_INT:
-    if(a->u.integer < b->u.integer) return -1;
-    if(a->u.integer > b->u.integer) return 1;
-    return 0;
-
-  case T_FLOAT:
-    if(a->u.float_number < b->u.float_number) return -1;
-    if(a->u.float_number > b->u.float_number) return 1;
-    return 0;
-
-  case T_STRING:
-    return DO_NOT_WARN((int)my_quick_strcmp(a->u.string, b->u.string));
-    
-  default:
-    return set_svalue_cmpfun(a,b);
+    switch(a->type)
+    {
+      case T_INT:
+	if(a->u.integer < b->u.integer) return -1;
+	if(a->u.integer > b->u.integer) return 1;
+	return 0;
+	
+      case T_FLOAT:
+	if(a->u.float_number < b->u.float_number) return -1;
+	if(a->u.float_number > b->u.float_number) return 1;
+	return 0;
+	
+      case T_STRING:
+	return DO_NOT_WARN((int)my_quick_strcmp(a->u.string, b->u.string));
+	
+      default:
+	return set_svalue_cmpfun(a,b);
+    }
+  }else{
+    return a->type - b->type;
   }
 }
 
@@ -826,13 +890,18 @@ INT32 set_lookup(struct array *a, struct svalue *s)
 #ifdef PIKE_DEBUG
   if(d_flag > 1)  array_check_type_field(a);
 #endif
-  /* face it, it's not there */
-  if( (((2 << s->type) -1) & a->type_field) == 0)
-    return -1;
 
+  /* objects may have `< `> operators, evil stuff! */
+  if(s->type != T_OBJECT && !(a->flags & BIT_OBJECT))
+  {
+    /* face it, it's not there */
+    if( (((2 << s->type) -1) & a->type_field) == 0)
+      return -1;
+    
   /* face it, it's not there */
-  if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0)
-    return ~a->size;
+    if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0)
+      return ~a->size;
+  }
 
   return low_lookup(a,s,set_svalue_cmpfun);
 }
@@ -843,12 +912,16 @@ INT32 switch_lookup(struct array *a, struct svalue *s)
 #ifdef PIKE_DEBUG
   if(d_flag > 1)  array_check_type_field(a);
 #endif
-  if( (((2 << s->type) -1) & a->type_field) == 0)
-    return -1;
+  /* objects may have `< `> operators, evil stuff! */
+  if(s->type != T_OBJECT && !(a->flags & BIT_OBJECT))
+  {
+    if( (((2 << s->type) -1) & a->type_field) == 0)
+      return -1;
 
-  /* face it, it's not there */
-  if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0)
-    return ~a->size;
+    /* face it, it's not there */
+    if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0)
+      return ~a->size;
+  }
 
   return low_lookup(a,s,switch_svalue_cmpfun);
 }
@@ -982,6 +1055,7 @@ union anything *array_get_item_ptr(struct array *a,
  */
 INT32 * merge(struct array *a,struct array *b,INT32 opcode)
 {
+  ONERROR r;
   INT32 ap,bp,i,*ret,*ptr;
   
   ap=bp=0;
@@ -1011,6 +1085,7 @@ INT32 * merge(struct array *a,struct array *b,INT32 opcode)
   }
 
   ptr=ret=(INT32 *)xalloc(sizeof(INT32)*(a->size + b->size + 1));
+  SET_ONERROR(r, free,ret);
   ptr++;
 
   while(ap < a->size && bp < b->size)
@@ -1034,6 +1109,8 @@ INT32 * merge(struct array *a,struct array *b,INT32 opcode)
 
   *ret = DO_NOT_WARN((INT32)(ptr-ret-1));
 
+  UNSET_ONERROR(r);
+
   return ret;
 }
 
@@ -1169,6 +1246,7 @@ static int array_merge_fun(INT32 *a, INT32 *b)
  */
 PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *b,INT32 op)
 {
+  ONERROR r1,r2,r3;
   INT32 *zipper;
   struct array *tmpa,*tmpb,*ret;
 
@@ -1176,21 +1254,27 @@ PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *
   if(orderb) { free((char *)orderb); orderb=0; }
 
   ordera=get_set_order(a);
+  orderb=get_set_order(b);
+
   tmpa=reorder_and_copy_array(a,ordera);
+  SET_ONERROR(r1,do_free_array,tmpa);
 
-  orderb=get_set_order(b);
   tmpb=reorder_and_copy_array(b,orderb);
+  SET_ONERROR(r2,do_free_array,tmpb);
 
   zipper=merge(tmpa,tmpb,op);
+  SET_ONERROR(r3,free,zipper);
 
   fsort((char *)(zipper+1),*zipper,sizeof(INT32),(fsortfun)array_merge_fun);
-  free((char *)ordera);
+
   free((char *)orderb);
+  free((char *)ordera);
   orderb=ordera=0;
+
   ret=array_zip(tmpa,tmpb,zipper);
-  free_array(tmpa);
-  free_array(tmpb);
-  free((char *)zipper);
+  UNSET_ONERROR(r3);  free((char *)zipper);
+  UNSET_ONERROR(r2);  free_array(tmpb);
+  UNSET_ONERROR(r1);  free_array(tmpa);
   return ret;
 }
 
@@ -1211,6 +1295,7 @@ PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *
  */
 PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op)
 {
+  ONERROR r1,r2,r3,r4,r5;
   INT32 ap,bp,i;
   struct svalue *arra,*arrb;
   struct array *ret;
@@ -1223,12 +1308,16 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr
   }
 #endif
 
+  SET_ONERROR(r1,do_free_array,a);
+  SET_ONERROR(r2,do_free_array,b);
+
   if(a->refs==1 || !a->size)
   {
     arra=ITEM(a);
   }else{
     arra=(struct svalue *)xalloc(a->size*sizeof(struct svalue));
     MEMCPY(arra,ITEM(a),a->size*sizeof(struct svalue));
+    SET_ONERROR(r3,free,arra);
   }
 
   if(b->refs==1 || !b->size)
@@ -1237,12 +1326,14 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr
   }else{
     arrb=(struct svalue *)xalloc(b->size*sizeof(struct svalue));
     MEMCPY(arrb,ITEM(b),b->size*sizeof(struct svalue));
+    SET_ONERROR(r4,free,arrb);
   }
 
   set_sort_svalues(arra,arra+a->size-1);
   set_sort_svalues(arrb,arrb+b->size-1);
 
   ret=low_allocate_array(0,32);
+  SET_ONERROR(r5,do_free_array,ret);
   ap=bp=0;
 
   while(ap < a->size && bp < b->size)
@@ -1269,12 +1360,26 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr
     while(bp<b->size)
       ret=append_array(ret,arrb + bp++);
 
-  if(arra != ITEM(a)) free((char *)arra);
-  if(arrb != ITEM(b)) free((char *)arrb);
+  UNSET_ONERROR(r5);
 
-  free_array(a);
+  if(arrb != ITEM(b))
+  {
+    UNSET_ONERROR(r4);
+    free((char *)arrb);
+  }
+
+  if(arra != ITEM(a))
+  {
+    UNSET_ONERROR(r3);
+    free((char *)arra);
+  }
+
+  UNSET_ONERROR(r2);
   free_array(b);
 
+  UNSET_ONERROR(r1);
+  free_array(a);
+
   return ret;
 }
 
@@ -1287,6 +1392,9 @@ PMOD_EXPORT struct array *merge_array_without_order(struct array *a,
 					INT32 op)
 {
 #if 0
+  /* FIXME: If this routine is ever reinstated, it has to be
+   * fixed to use ONERROR
+   */
   INT32 *zipper;
   struct array *tmpa,*tmpb,*ret;
 
@@ -1318,6 +1426,7 @@ PMOD_EXPORT struct array *merge_array_without_order(struct array *a,
 }
 
 /* subtract an array from another */
+
 PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b)
 {
 #ifdef PIKE_DEBUG
diff --git a/src/docode.c b/src/docode.c
index 8f4d879fd17025d84ac4240f8bc25fc3562992d6..0a3023e43094b1e035ac0bc86fd47a6a3ceacc96 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.83 2000/09/26 22:19:02 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.84 2000/11/08 20:03:45 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "pike_types.h"
@@ -958,6 +958,10 @@ static int do_docode2(node *n, INT16 flags)
 #endif
 
     f_aggregate(cases);
+
+    /* FIXME: get_switch_order might possibly be able to
+     * throw errors, add a catch around this! -Hubbe
+     */
     order=get_switch_order(Pike_sp[-1].u.array);
 
     if (!Pike_compiler->num_parse_error) {
diff --git a/src/encode.c b/src/encode.c
index e199eba38e809356ab0fea7fa6fcd58cb5356a2e..48a11fd929ba06105e2f1bf8c826b6833bbca59f 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -25,7 +25,7 @@
 #include "version.h"
 #include "bignum.h"
 
-RCSID("$Id: encode.c,v 1.76 2000/10/04 05:12:12 hubbe Exp $");
+RCSID("$Id: encode.c,v 1.77 2000/11/08 20:03:45 hubbe Exp $");
 
 /* #define ENCODE_DEBUG */
 
@@ -468,6 +468,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
 	    /* This doesn't let bignums through. That's necessary as
 	     * long as they aren't handled deterministically by the
 	     * sort function. */
+	    /* They should be hanled deterministically now - Hubbe */
 	    error("Canonical encoding requires basic types in indices.\n");
 	}
 	order = get_switch_order(Pike_sp[-2].u.array);
diff --git a/src/mapping.c b/src/mapping.c
index 7d3368664b7461df0a1315fbbc0f49f1783685c2..ba9da14492e3f28d50f0ee937758cdb2028c2f41 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.110 2000/11/01 23:30:36 grubba Exp $");
+RCSID("$Id: mapping.c,v 1.111 2000/11/08 20:03:45 hubbe Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -1321,6 +1321,7 @@ PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m)
 
 PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)
 {
+  ONERROR r1,r2,r3,r4,r5;
   struct array *ai, *av;
   struct array *bi, *bv;
   struct array *ci, *cv;
@@ -1335,7 +1336,11 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b,
 #endif
 
   ai=mapping_indices(a);
+  SET_ONERROR(r1,do_free_array,ai);
+
   av=mapping_values(a);
+  SET_ONERROR(r2,do_free_array,av);
+
   if(ai->size > 1)
   {
     zipper=get_set_order(ai);
@@ -1345,7 +1350,11 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b,
   }
 
   bi=mapping_indices(b);
+  SET_ONERROR(r3,do_free_array,bi);
+
   bv=mapping_values(b);
+  SET_ONERROR(r4,do_free_array,bv);
+
   if(bi->size > 1)
   {
     zipper=get_set_order(bi);
@@ -1357,13 +1366,15 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b,
   zipper=merge(ai,bi,op);
 
   ci=array_zip(ai,bi,zipper);
-  free_array(ai);
-  free_array(bi);
+
+  UNSET_ONERROR(r4); free_array(bi);
+  UNSET_ONERROR(r3); free_array(ai);
 
   cv=array_zip(av,bv,zipper);
-  free_array(av);
-  free_array(bv);
-  
+
+  UNSET_ONERROR(r2); free_array(bv);
+  UNSET_ONERROR(r1); free_array(av);
+
   free((char *)zipper);
 
   m=mkmapping(ci, cv);
@@ -1376,13 +1387,16 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b,
 PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a, 
 					    struct array *b, INT32 op)
 {
+  ONERROR r1,r2;
   struct array *ai, *av;
   struct array *ci = NULL, *cv = NULL;
   INT32 *zipper = NULL;
   struct mapping *m;
 
   ai=mapping_indices(a);
+  SET_ONERROR(r1,do_free_array,ai);
   av=mapping_values(a);
+  SET_ONERROR(r2,do_free_array,av);
   if(ai->size > 1)
   {
     zipper=get_set_order(ai);
@@ -1407,8 +1421,8 @@ PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,
 	fatal("merge_mapping_array on other than AND or SUB\n");
   }
 
-  free_array(ai);
-  free_array(av);
+  UNSET_ONERROR(r2); free_array(av);
+  UNSET_ONERROR(r1); free_array(ai);
   
   free((char *)zipper);
 
@@ -1422,6 +1436,7 @@ PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,
 PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a, 
 					      struct array *b, INT32 op)
 {
+  ONERROR r1;
   struct array *b_temp;
   INT32 *zipper;
   struct mapping *m;
@@ -1430,8 +1445,9 @@ PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a,
   {
     zipper=get_set_order(b);
     b_temp=reorder_and_copy_array(b,zipper);
+    SET_ONERROR(r1,do_free_array,b_temp);
     m=merge_mapping_array_ordered(a,b_temp,op);
-    free_array(b_temp);
+    UNSET_ONERROR(r1); free_array(b_temp);
   }
   else
     m=merge_mapping_array_ordered(a,b,op);
diff --git a/src/multiset.c b/src/multiset.c
index d916baa318c26057f62d735798773567b896784a..e0510d29eed27034f7579f3552c0f29b5f30cd40 100644
--- a/src/multiset.c
+++ b/src/multiset.c
@@ -17,7 +17,7 @@
 #include "gc.h"
 #include "security.h"
 
-RCSID("$Id: multiset.c,v 1.28 2000/09/14 19:58:43 mast Exp $");
+RCSID("$Id: multiset.c,v 1.29 2000/11/08 20:03:46 hubbe Exp $");
 
 struct multiset *first_multiset;
 
@@ -26,7 +26,11 @@ static struct multiset *gc_mark_multiset_pos = 0;
 
 PMOD_EXPORT int multiset_member(struct multiset *l, struct svalue *ind)
 {
-  return set_lookup(l->ind, ind) >= 0;
+  int i;
+  add_ref(l->ind);
+  i=set_lookup(l->ind, ind) >= 0;
+  free_array(l->ind);
+  return i;
 }
 
 /*
@@ -77,17 +81,51 @@ PMOD_EXPORT void do_free_multiset(struct multiset *l)
     free_multiset(l);
 }
 
+#define BEGIN() do{				\
+  struct array *ind=l->ind;			\
+  struct array *ind_bak=ind;                    \
+  if(ind->refs > 1)				\
+  {						\
+    ind=copy_array(l->ind);			\
+    free_array(l->ind);				\
+    l->ind=ind;					\
+  }						\
+  add_ref(ind)
+
+#define END()					\
+  if(l->ind == ind_bak)				\
+  {						\
+    free_array(l->ind);				\
+    l->ind=ind;					\
+  }else{					\
+    free_array(ind);				\
+  }						\
+}while(0)
+
 
 PMOD_EXPORT void order_multiset(struct multiset *l)
 {
   INT32 *order;
   int flags;
   if(l->ind->size < 2) return;
-  order = get_set_order(l->ind);
-  flags = l->ind->flags;
-  l->ind = order_array(l->ind, order);
-  l->ind->flags = flags;
+
+  BEGIN();
+
+#if 0
+
+  order = get_set_order(ind);
+  flags = ind->flags;
+  ind = order_array(ind, order);
+  ind->flags = flags;
   free((char *)order);
+#else
+  {
+    extern void set_sort_svalues(struct svalue *, struct svalue *);
+    set_sort_svalues(ITEM(ind),ITEM(ind)+ind->size-1);
+  }
+#endif
+
+  END();
 }
 
 PMOD_EXPORT struct multiset *mkmultiset(struct array *ind)
@@ -99,16 +137,18 @@ PMOD_EXPORT struct multiset *mkmultiset(struct array *ind)
 }
 
 PMOD_EXPORT void multiset_insert(struct multiset *l,
-		 struct svalue *ind)
+		 struct svalue *v)
 {
   INT32 i;
-  i=set_lookup(l->ind, ind);
+  BEGIN();
+  i=set_lookup(ind, v);
   if(i < 0)
   {
-    int flags = l->ind->flags;
-    l->ind=array_insert(l->ind, ind, ~i);
-    l->ind->flags = flags;
+    int flags = ind->flags;
+    ind=array_insert(ind, v, ~i);
+    ind->flags = flags;
   }
+  END();
 }
 
 #if 0
@@ -118,27 +158,33 @@ struct array *multiset_indices(struct multiset *l)
 }
 #endif
 
-PMOD_EXPORT void multiset_delete(struct multiset *l,struct svalue *ind)
+PMOD_EXPORT void multiset_delete(struct multiset *l,struct svalue *v)
 {
   INT32 i;
-  i=set_lookup(l->ind, ind);
+  BEGIN();
+  i=set_lookup(ind, v);
 
   if(i >= 0)
   {
-    int flags = l->ind->flags;
-    l->ind=array_remove(l->ind, i);
-    l->ind->flags = flags;
+    int flags = ind->flags;
+    ind=array_remove(ind, i);
+    ind->flags = flags;
   }
+  END();
 }
 
 PMOD_EXPORT void check_multiset_for_destruct(struct multiset *l)
 {
 /* Horrifying worst case!!!!! */
   INT32 i;
-  int flags = l->ind->flags;
-  while( (i=array_find_destructed_object(l->ind)) >= 0)
-    l->ind=array_remove(l->ind, i);
-  l->ind->flags = flags;
+  BEGIN();
+  {
+    int flags = ind->flags;
+    while( (i=array_find_destructed_object(ind)) >= 0)
+      ind=array_remove(ind, i);
+    ind->flags = flags;
+  }
+  END();
 }
 
 PMOD_EXPORT struct multiset *copy_multiset(struct multiset *tmp)