diff --git a/lib/modules/Array.pmod b/lib/modules/Array.pmod
index 07a8656205c0d3888413c5ba9d5deb8c2b179790..c5c405614e8d239bfb74030d8bd85533fa92aa8a 100644
--- a/lib/modules/Array.pmod
+++ b/lib/modules/Array.pmod
@@ -4,6 +4,7 @@ constant diff = __builtin.diff;
 constant diff_longest_sequence = __builtin.diff_longest_sequence;
 constant diff_compare_table = __builtin.diff_compare_table;
 constant longest_ordered_sequence = __builtin.longest_ordered_sequence;
+constant interleave_array = __builtin.interleave_array;
 
 constant sort = __builtin.sort;
 constant everynth = __builtin.everynth;
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 33bbff256ec707eb011ecb5bd82a28f52a2e9209..8100a28fa8891ff5691c1b44d06f976fbc46d04a 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.138 1998/11/13 01:28:41 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.139 1998/11/17 06:39:50 grubba Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -2169,6 +2169,176 @@ void f_glob(INT32 args)
   }
 }
 
+/* comb_merge */
+
+/* mixed interleave_array(array(mapping(int:mixed)) tab) */
+static void f_interleave_array(INT32 args)
+{
+  struct array *arr = NULL;
+  struct array *min = NULL;
+  struct array *order = NULL;
+  int max = 0;
+  int ok;
+  int nelems = 0;
+  int i;
+
+  get_all_args("interleave_array", args, "%a", &arr);
+
+  /* We're not interrested in any other arguments. */
+  pop_n_elems(args-1);
+
+  if ((ok = arr->type_field & BIT_MAPPING) &&
+      (arr->type_field & ~BIT_MAPPING)) {
+    /* Might be ok, but do some more checking... */
+    for(i = 0; i < arr->size; i++) {
+      if (ITEM(arr)[i].type != T_MAPPING) {
+	ok = 0;
+	break;
+      }
+    }
+  }
+  if (!ok) {
+    error("interleave_array(): Expected array(mapping(int:mixed))\n");
+  }
+
+  /* The order array */
+  ref_push_array(arr);
+  f_indices(1);
+  order = sp[-1].u.array;
+
+  /* The min array */
+  push_array(min = allocate_array(arr->size));
+
+  /* Initialize the min array */
+  for (i = 0; i < arr->size; i++) {
+    struct mapping *m;
+    /* e and k are used by MAPPING_LOOP() */
+    INT32 e;
+    struct keypair *k;
+    INT_TYPE low = 0x7fffffff;
+#ifdef DEBUG
+    if (ITEM(arr)[i].type != T_MAPPING) {
+      error("interleave_array(): Element %d is not a mapping!\n", i);
+    }
+#endif /* DEBUG */
+    m = ITEM(arr)[i].u.mapping;
+    MAPPING_LOOP(m) {
+      if (k->ind.type != T_INT) {
+	error("interleave_array(): Index not an integer in mapping %d!\n", i);
+      }
+      if (low > k->ind.u.integer) {
+	low = k->ind.u.integer;
+	if (low < 0) {
+	  error("interleave_array(): Index %d in mapping %d is negative!\n",
+		low, i);
+	}
+      }
+      if (max < k->ind.u.integer) {
+	max = k->ind.u.integer;
+      }
+      nelems++;
+    }
+    /* FIXME: Is this needed? Isn't T_INT default? */
+    ITEM(min)[i].u.integer = low;
+  }
+
+  ref_push_array(order);
+  f_sort(2);	/* Sort the order array on the minimum index */
+
+  /* State on stack now:
+   *
+   * array(mapping(int:mixed))	arr
+   * array(int)			order
+   * array(int)			min (now sorted)
+   */
+
+  /* Now we can start with the real work... */
+  {
+    char *tab;
+    int size;
+    int minfree = 0;
+
+    /* Initialize the lookup table */
+    max += 1;
+    max *= 2;
+    /* max will be the padding at the end. */
+    size = (nelems + max) * 8;	/* Initial size */
+    if (!(tab = malloc(size + max))) {
+      error("interleave_array(): Out of memory!\n");
+    }
+    MEMSET(tab, 0, size + max);
+
+    for (i = 0; i < order->size; i++) {
+      int low = ITEM(min)[i].u.integer;
+      int j = ITEM(order)[i].u.integer;
+      int offset = 0;
+      struct mapping *m;
+      INT32 e;
+      struct keypair *k;
+
+      if (!(m = ITEM(arr)[j].u.mapping)->size) {
+	/* Not available */
+	ITEM(min)[i].u.integer = -1;
+	continue;
+      }
+
+      if (low < minfree) {
+	offset = minfree - low;
+      } else {
+	minfree = offset;
+      }
+
+      ok = 0;
+      while (!ok) {
+	ok = 1;
+	MAPPING_LOOP(m) {
+	  int ind = k->ind.u.integer;
+	  if (tab[offset + ind]) {
+	    ok = 0;
+	    while (tab[++offset + ind])
+	      ;
+	  }
+	}
+      }
+      MAPPING_LOOP(m) {
+	tab[offset + k->ind.u.integer] = 1;
+      }
+      while(tab[minfree]) {
+	minfree++;
+      }
+      ITEM(min)[i].u.integer = offset;
+
+      /* Check need for realloc */
+      if (offset >= size) {
+	char *newtab = realloc(tab, size*2 + max);
+	if (!newtab) {
+	  free(tab);
+	  error("interleave_array(): Couldn't extend table!\n");
+	}
+	tab = newtab;
+	MEMSET(tab + size + max, 0, size);
+	size = size * 2;
+      }
+    }
+    free(tab);
+  }
+
+  /* We want these two to survive the stackpopping. */
+  add_ref(min);
+  add_ref(order);
+
+  pop_n_elems(3);
+
+  /* Return value */
+  ref_push_array(min);
+
+  /* Restore the order */
+  push_array(order);
+  push_array(min);
+  f_sort(2);
+  pop_stack();
+}
+
 /* longest_ordered_sequence */
 
 static int find_gt(struct array *a, int i, int *stack, int top)
@@ -3573,6 +3743,7 @@ void init_builtin_efuns(void)
   add_efun("decode_value", f_decode_value, "function(string,void|object:mixed)", OPT_TRY_OPTIMIZE);
   add_efun("object_variablep", f_object_variablep, "function(object,string:int)", OPT_EXTERNAL_DEPEND);
 
+  add_function("interleave_array",f_interleave_array,"function(array(mapping(int:mixed)):array(int))",OPT_TRY_OPTIMIZE);
   add_function("diff",f_diff,"function(array,array:array(array))",OPT_TRY_OPTIMIZE);
   add_function("diff_longest_sequence",f_diff_longest_sequence,"function(array,array:array(int))",OPT_TRY_OPTIMIZE);
   add_function("diff_dyn_longest_sequence",f_diff_dyn_longest_sequence,"function(array,array:array(int))",OPT_TRY_OPTIMIZE);