diff --git a/src/array.c b/src/array.c
index 3eb0512864a12b48760c29d3ecd36f73e7cef8a0..75695d7203dd650f4a0530fdecddc77fe1546f33 100644
--- a/src/array.c
+++ b/src/array.c
@@ -19,7 +19,7 @@
 #include "gc.h"
 #include "main.h"
 
-RCSID("$Id: array.c,v 1.34 1998/04/23 23:58:52 hubbe Exp $");
+RCSID("$Id: array.c,v 1.35 1998/04/27 22:33:17 hubbe Exp $");
 
 struct array empty_array=
 {
@@ -554,33 +554,43 @@ INT32 array_find_destructed_object(struct array *v)
   return -1;
 }
 
-static struct svalue *current_array_p;
-static cmpfun current_cmpfun;
-
-static int internal_cmpfun(INT32 *a,INT32 *b)
+static int internal_cmpfun(INT32 *a,
+			   INT32 *b,
+			   cmpfun current_cmpfun,
+			   struct svalue *current_array_p)
 {
   return current_cmpfun(current_array_p + *a, current_array_p + *b);
 }
 
+#define CMP(X,Y) internal_cmpfun((X),(Y),current_cmpfun, current_array_p)
+#define TYPE INT32
+#define ID get_order_fsort
+#define EXTRA_ARGS ,cmpfun current_cmpfun, struct svalue *current_array_p
+#define XARGS ,current_cmpfun, current_array_p
+#include "fsort_template.h"
+#undef CMP
+#undef TYPE
+#undef ID
+#undef EXTRA_ARGS
+#undef XARGS
+
 INT32 *get_order(struct array *v, cmpfun fun)
 {
   INT32 e, *current_order;
+  ONERROR tmp;
 
   if(!v->size) return 0;
 
-  current_cmpfun = fun;
   current_order=(INT32 *)xalloc(v->size * sizeof(INT32));
+  SET_ONERROR(tmp, free, current_order);
   for(e=0; e<v->size; e++) current_order[e]=e;
 
-  if(current_array_p) free((char *)current_array_p);
-  current_array_p = ITEM(v);
-  current_cmpfun = fun;
-  fsort((char *)current_order,
-	v->size,
-	sizeof(INT32),
-	(fsortfun)internal_cmpfun);
+  get_order_fsort(current_order,
+		  current_order+v->size-1,
+		  fun,
+		  ITEM(v));
 
-  current_array_p=0;
+  UNSET_ONERROR(tmp);
   return current_order;
 }
 
@@ -673,13 +683,19 @@ static int alpha_svalue_cmpfun(struct svalue *a, struct svalue *b)
   return is_gt(a,b);
 }
 
+#define CMP(X,Y) alpha_svalue_cmpfun(X,Y)
+#define TYPE struct svalue
+#define ID low_sort_svalues
+#include "fsort_template.h"
+#undef CMP
+#undef TYPE
+#undef ID
+
+
 void sort_array_destructively(struct array *v)
 {
   if(!v->size) return;
-  fsort((char *)ITEM(v),
-	v->size,
-	sizeof(struct svalue),
-	(fsortfun)alpha_svalue_cmpfun);
+  low_sort_svalues(ITEM(v), ITEM(v)+v->size-1);
 }
 
 
diff --git a/src/encode.c b/src/encode.c
index dbfacd50d7d46219addb11758a3ffd97c3435f46..82067c3180436ffd37deeaf42cdf03e95d609524 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -19,8 +19,9 @@
 #include "builtin_functions.h"
 #include "module_support.h"
 #include "fsort.h"
+#include "threads.h"
 
-RCSID("$Id: encode.c,v 1.20 1998/04/24 00:32:08 hubbe Exp $");
+RCSID("$Id: encode.c,v 1.21 1998/04/27 22:33:17 hubbe Exp $");
 
 #ifdef _AIX
 #include <net/nh.h>
@@ -133,6 +134,14 @@ static void code_number(INT32 num, struct encode_data *data)
   code_entry(num & 15, num >> 4, data);
 }
 
+#ifdef _REENTRANT
+static void do_enable_threads(void)
+{
+  if(!--threads_disabled)
+    co_broadcast(&threads_disabled_change);
+}
+#endif
+
 static int encode_type(char *t, struct encode_data *data)
 {
   char *q=t;
@@ -887,6 +896,12 @@ static void decode_value2(struct decode_data *data)
 	  char *dat;
 	  struct program *p;
 
+#ifdef _REENTRANT
+	  ONERROR err;
+	  threads_disabled++;
+	  SET_ONERROR(err, do_enable_threads, 0);
+#endif
+
 	  p=low_allocate_program();
 	  debug_malloc_touch(p);
 	  tmp.type=T_PROGRAM;
@@ -1045,6 +1060,12 @@ static void decode_value2(struct decode_data *data)
 	  }
 	  p->flags |= PROGRAM_FINISHED;
 	  ref_push_program(p);
+
+#ifdef _REENTRANT
+	  UNSET_ONERROR(err);
+	  if(!--threads_disabled)
+	    co_broadcast(&threads_disabled_change);
+#endif
 	  return;
 	}
 
diff --git a/src/fsort.c b/src/fsort.c
index 259a839d98d83693200f18c116f2551a1d6654d8..5c0763edaa91950e4fed45045328926de8f54a85 100644
--- a/src/fsort.c
+++ b/src/fsort.c
@@ -9,14 +9,11 @@
 #include "global.h"
 #include "fsort.h"
 
-RCSID("$Id: fsort.c,v 1.9 1998/03/28 15:29:54 grubba Exp $");
+RCSID("$Id: fsort.c,v 1.10 1998/04/27 22:33:17 hubbe Exp $");
 
-static fsortfun cmpfun;
-static long size;
-static char *tmp_area;
-
-#define SWAP(X,Y) { tmp=*(X); *(X)=*(Y); *(Y)=tmp; }
-#define STEP(X,Y) (&((X)[(Y)]))
+#define CMP(X,Y) ( (*cmpfun)((void *)(X),(void *)(Y)) )
+#define EXTRA_ARGS ,fsortfun cmpfun
+#define XARGS ,cmpfun
 
 #define ID fsort_1
 #define TYPE B1_T
@@ -58,9 +55,12 @@ static char *tmp_area;
 #undef TYPE
 #endif
 
-#undef SWAP
-#undef STEP
 
+#undef EXTRA_ARGS
+#undef XARGS
+
+#define EXTRA_ARGS ,fsortfun cmpfun,long size, char *tmp_area
+#define XARGS ,cmpfun,size,tmp_area
 
 #define SWAP(X,Y) do { \
     MEMCPY(tmp_area,X,size); \
@@ -71,11 +71,12 @@ static char *tmp_area;
 #define STEP(X,Y) ((X)+(Y)*size)
 #define TYPE char
 #define ID fsort_n
+#define TMP_AREA
 #include "fsort_template.h"
 #undef ID
 #undef TYPE
-#undef SWAP
-#undef STEP
+#undef EXTRA_ARGS
+#undef XARGS
 
 void fsort(void *base,
 	   long elms,
@@ -84,8 +85,6 @@ void fsort(void *base,
 {
 
   if(elms<=0) return;
-  cmpfun=cmpfunc;
-  size=elmSize;
 
 #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS
   switch(elmSize)
@@ -93,22 +92,21 @@ void fsort(void *base,
   switch( (((unsigned long)base) % elmSize) ? 0 : size )
 #endif
   {
-  case  1:  fsort_1(( B1_T *)base,(elms-1)+( B1_T *)base); break;
+  case  1:  fsort_1(( B1_T *)base,(elms-1)+( B1_T *)base, cmpfunc); break;
 #ifdef B2_T
-  case  2:  fsort_2(( B2_T *)base,(elms-1)+( B2_T *)base); break;
+  case  2:  fsort_2(( B2_T *)base,(elms-1)+( B2_T *)base, cmpfunc); break;
 #endif
 #ifdef B4_T
-  case  4:  fsort_4(( B4_T *)base,(elms-1)+( B4_T *)base); break;
+  case  4:  fsort_4(( B4_T *)base,(elms-1)+( B4_T *)base, cmpfunc); break;
 #endif
 #ifdef B8_T
-  case  8:  fsort_8(( B8_T *)base,(elms-1)+( B8_T *)base); break;
+  case  8:  fsort_8(( B8_T *)base,(elms-1)+( B8_T *)base, cmpfunc); break;
 #endif
 #ifdef B16_T
-  case 16: fsort_16((B16_T *)base,(elms-1)+(B16_T *)base); break;
+  case 16: fsort_16((B16_T *)base,(elms-1)+(B16_T *)base, cmpfunc); break;
 #endif
   default:
-    tmp_area=(char *)alloca(elmSize);
-    fsort_n((char *)base,((char *)base) + size * (elms - 1));
+    fsort_n((char *)base,((char *)base) + elmSize * (elms - 1), cmpfunc, elmSize, (char *)alloca(elmSize));
   }
 
 }
diff --git a/src/fsort_template.h b/src/fsort_template.h
index 13a6ddc12cd61c1b5ab807b9f431f71348f62c7f..375bbfe3b47369574390ccf75acb92ce8016b59a 100644
--- a/src/fsort_template.h
+++ b/src/fsort_template.h
@@ -1,19 +1,37 @@
 /*
- * $Id: fsort_template.h,v 1.3 1998/03/28 15:16:12 grubba Exp $
+ * $Id: fsort_template.h,v 1.4 1998/04/27 22:33:17 hubbe Exp $
  */
 
+#ifndef SWAP
+#define UNDEF_SWAP
+#define SWAP(X,Y) { tmp=*(X); *(X)=*(Y); *(Y)=tmp; }
+#endif
+
+#ifndef STEP
+#define UNDEF_STEP
+#define STEP(X,Y) (&((X)[(Y)]))
+#endif
+
 #define INC(X) X=STEP(X,1)
 #define DEC(X) X=STEP(X,-1)
 #define SIZE ((long)(char *)STEP((TYPE *)0,1))
 
-static void ID(register TYPE *bas, register TYPE *last)
+static void ID(register TYPE *bas,
+	       register TYPE *last
+#ifdef EXTRA_ARGS
+	       EXTRA_ARGS
+#else
+#define UNDEF_XARGS
+#define XARGS
+#endif
+  )
 {
   register TYPE *a,*b, tmp;
   if(bas >= last) return;
   a = STEP(bas,1);
   if(a == last)
   {
-    if( (*cmpfun)((void *)bas,(void *)last) > 0) SWAP(bas,last); 
+    if( CMP(bas,last) > 0) SWAP(bas,last); 
   }else{
     b=STEP(bas,((((char *)last)-((char *)bas))/SIZE)>>1);
     SWAP(bas,b);
@@ -25,18 +43,18 @@ static void ID(register TYPE *bas, register TYPE *last)
       {
 	while(1)
 	{
-	  if(a<=b && (*cmpfun)((void *)a,(void *)bas) <= 0)
+	  if(a<=b && CMP(a,bas) <= 0)
 	    INC(a);
 	  else
 	  {
-	    while(a< b && (*cmpfun)((void *)bas,(void *)b) <= 0) DEC(b);
+	    while(a< b && CMP(bas,b) <= 0) DEC(b);
 	    break;
 	  }
-	  if(a< b && (*cmpfun)((void *)bas,(void *)b) <= 0)
+	  if(a< b && CMP(bas,b) <= 0)
 	    DEC(b);
 	  else
 	  {
-	    while(a<=b && (*cmpfun)((void *)a,(void *)bas) <= 0) INC(a);
+	    while(a<=b && CMP(a,bas) <= 0) INC(a);
 	    break;
 	  }
 	}
@@ -49,8 +67,8 @@ static void ID(register TYPE *bas, register TYPE *last)
 	}
       }
 #else
-      while(a<=b && (*cmpfun)((void *)a,(void *)bas) < 0) INC(a);
-      while(a< b && (*cmpfun)((void *)bas,(void *)b) < 0) DEC(b);
+      while(a<=b && CMP(a,bas) < 0) INC(a);
+      while(a< b && CMP(bas,b) < 0) DEC(b);
       if(a<b)
       {
         SWAP(a,b);
@@ -62,11 +80,25 @@ static void ID(register TYPE *bas, register TYPE *last)
     DEC(a);
     SWAP(a,bas);
     DEC(a);
-    ID(bas,a);
-    ID(b,last);
+    ID(bas,a XARGS);
+    ID(b,last XARGS);
   }
 }
 
 #undef INC
 #undef DEC
-#undef SIZE
+
+#ifdef UNDEF_XARGS
+#undef XARGS
+#undef UNDEF_XARGS
+#endif
+
+#ifdef UNDEF_SWAP
+#undef SWAP
+#undef UNDEF_SWAP
+#endif
+
+#ifdef UNDEF_STEP
+#undef STEP
+#undef UNDEF_STEP
+#endif