diff --git a/src/builtin_efuns.c b/src/builtin_efuns.c
index c0229c9cc0f17f1a8735197068ec4828a95c7d43..d43e8809fd40710b620e9d6419309f5ddc24e4cf 100644
--- a/src/builtin_efuns.c
+++ b/src/builtin_efuns.c
@@ -23,6 +23,8 @@
 #include "call_out.h"
 #include "callback.h"
 #include "gc.h"
+#include "backend.h"
+#include "main.h"
 
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
@@ -584,7 +586,7 @@ void f_sizeof(INT32 args)
     break;
 
   case T_MAPPING:
-    tmp=sp[-1].u.mapping->ind->size;
+    tmp=m_sizeof(sp[-1].u.mapping);
     free_mapping(sp[-1].u.mapping);
     break;
 
@@ -794,7 +796,7 @@ void f_indices(INT32 args)
     break;
 
   case T_MAPPING:
-    a=copy_array(sp[-args].u.mapping->ind);
+    a=mapping_indices(sp[-args].u.mapping);
     break;
 
   case T_LIST:
@@ -818,7 +820,7 @@ void f_values(INT32 args)
   INT32 size;
   struct array *a;
   if(args < 1)
-    error("Too few arguments to indices()\n");
+    error("Too few arguments to values()\n");
 
   switch(sp[-args].type)
   {
@@ -838,7 +840,7 @@ void f_values(INT32 args)
     break;
 
   case T_MAPPING:
-    a=copy_array(sp[-args].u.mapping->val);
+    a=mapping_values(sp[-args].u.mapping);
     break;
 
   case T_LIST:
@@ -1074,7 +1076,7 @@ void f_replace(INT32 args)
 
   case T_MAPPING:
   {
-    array_replace(sp[-args].u.mapping->val,sp+1-args,sp+2-args);
+    mapping_replace(sp[-args].u.mapping,sp+1-args,sp+2-args);
     pop_n_elems(args-1);
     break;
   }
@@ -1237,10 +1239,93 @@ TYPEP(f_listp, "listp", T_LIST)
 TYPEP(f_stringp, "stringp", T_STRING)
 TYPEP(f_floatp, "floatp", T_FLOAT)
 
+void f_sort(INT32 args)
+{
+  INT32 e,*order;
+
+  if(args < 0)
+    fatal("Too few arguments to sort().\n");
+
+  for(e=0;e<args;e++)
+  {
+    if(sp[e-args].type != T_ARRAY)
+      error("Bad argument %ld to sort().\n",(long)(e+1));
+
+    if(sp[e-args].u.array->size != sp[-args].u.array->size)
+      error("Argument %ld to sort() has wrong size.\n",(long)(e+1));
+  }
+
+  order=get_alpha_order(sp[-args].u.array);
+  for(e=0;e<args;e++) order_array(sp[e-args].u.array,order);
+  free((char *)order);
+  pop_n_elems(args-1);
+}
+
+void f_rows(INT32 args)
+{
+  INT32 e;
+  struct array *a,*tmp;
+
+  if(args < 2)
+    error("Too few arguments to rows().\n");
+
+  if(sp[1-args].type!=T_ARRAY)
+    error("Bad argument 1 to rows().\n");
+
+  tmp=sp[1-args].u.array;
+  push_array(a=allocate_array(tmp->size));
+
+  for(e=0;e<a->size;e++)
+    index_no_free(ITEM(a)+e, sp-args-1, ITEM(tmp)+e);
+
+  a->refs++;
+  pop_n_elems(args+1);
+  push_array(a);
+}
+
+void f_column(INT32 args)
+{
+  INT32 e;
+  struct array *a,*tmp;
+
+  if(args < 2)
+    error("Too few arguments to column().\n");
+
+  if(sp[-args].type!=T_ARRAY)
+    error("Bad argument 1 to column().\n");
+
+  tmp=sp[-args].u.array;
+  push_array(a=allocate_array(tmp->size));
+
+  for(e=0;e<a->size;e++)
+    index_no_free(ITEM(a)+e, ITEM(tmp)+e, sp-args);
+
+  a->refs++;
+  pop_n_elems(args+1);
+  push_array(a);
+}
+
+#ifdef DEBUG
+void f__verify_internals(INT32 args)
+{
+  INT32 tmp;
+  tmp=d_flag;
+  d_flag=0x7fffffff;
+  do_debug();
+  d_flag=tmp;
+  pop_n_elems(args);
+}
+
+#endif
+
 void init_builtin_efuns()
 {
   init_operators();
 
+#ifdef DEBUG
+  add_efun("_verify_internals",f__verify_internals,"function(:void)",OPT_SIDE_EFFECT|OPT_EXTERNAL_DEPEND);
+#endif
+
   add_efun("add_efun",f_add_efun,"function(string,void|mixed:void)",OPT_SIDE_EFFECT);
   add_efun("aggregate",f_aggregate,"function(mixed ...:mixed *)",OPT_TRY_OPTIMIZE);
   add_efun("aggregate_list",f_aggregate_list,"function(mixed ...:list)",OPT_TRY_OPTIMIZE);
@@ -1299,9 +1384,168 @@ void init_builtin_efuns()
   add_efun("upper_case",f_upper_case,"function(string:string)",0);
   add_efun("values",f_values,"function(string|list:int*)|function(array|mapping|object:mixed*)",0);
   add_efun("zero_type",f_zero_type,"function(int:int)",0);
+  add_efun("sort",f_sort,"function(array(mixed),array(mixed)...:array(mixed))",OPT_SIDE_EFFECT);
+  add_efun("column",f_column,"function(array,mixed:array)",0);
+  add_efun("rows",f_rows,"function(mixed,array:array)",0);
 #ifdef GC2
   add_efun("gc",f_gc,"function(:int)",OPT_SIDE_EFFECT);
 #endif
 }
 
 
+#if 0
+/* Check if the glob s[0..len[ matches the string m[0..mlen[ */
+static int does_match(char *s, int len, char *m, int mlen)
+{
+  int i,j;
+  for (i=j=0; i<mlen && j<len; i++,j++)
+  {
+    switch (m[i])
+    {
+     case '?': break;
+
+     case '*': 
+      i++;
+      if (i==mlen) return 1;	/* slut */
+
+      for (;j<len;j++)
+	if (does_match(s+j,len-j,m+i,mlen-i))
+	  return 1;
+
+      return 0;
+
+     default: 
+      if (m[i]!=s[j]) return 0;
+    }
+  }
+  if (i==mlen && j==len) return 1;
+  return 0;
+}
+
+void f_glob(INT32 args)
+{
+  INT32 i,matches;
+  struct array *a;
+  struct svalue *sval, *tmp;
+  struct lpc_string *glob;
+
+  if(args < 2)
+    error("Too few arguments to glob().\n");
+
+  if(args > 2) pop_n_elems(args-2);
+
+  if (sp[1-args].type!=T_STRING)
+    error("Bad argument 2 to glob().\n");
+
+  glob=sp[-args].u.string;
+
+  switch(sp[-args].type)
+  {
+  case T_STRING:
+    i=do_match(sp[1-args].u.string,
+	       sp[1-args].u.string->length,
+	       glob,
+	       glob->length);
+    pop_n_elems(2);
+    push_int(i);
+    break;
+    
+  case T_ARRAY:
+    a=sp[-args].u.array;
+    for(i=0;i<a->size;i++)
+    {
+      if(do_match(ITEM(a)[i].u.string,
+		  ITEM(a)[i].u.string->length,
+		  glob,
+		  glob->length))
+      {
+	ITEM(a)[i].u.string->refs++;
+	push_string(ITEM(a)[i].u.string);
+	matches++;
+      }
+    }
+    f_aggregate(matches);
+    tmp=sp[-1];
+    sp--;
+    pop_n_elems(2);
+    sp[0]=tmp;
+    sp++;
+    break;
+
+  default:
+    error("Bad argument 2 to glob().\n");
+  }
+}
+
+
+/*
+ * add_efun("glob",f_glob,"function(string,string:string)|function(string,array(string):array(string))",0);
+ * add_efun("localtime",f_localtime,
+ * "function(int:mapping(string:int))",OPT_EXTERNAL_DEPEND);
+ */
+
+#if !HAVE_INT_TIMEZONE
+int _tz;
+#else
+extern long int timezone;
+#endif
+
+
+
+void f_localtime(INT32 args)
+{
+  struct tm *tm;
+  time_t t;
+  if (args<1||
+      sp[-1].type!=T_INT)
+    error("Illegal argument to localtime");
+  t=sp[-1].u.integer;
+  tm=localtime(&t);
+  pop_stack();
+  push_string(make_shared_string("sec"));
+  push_int(tm->tm_sec);
+  push_string(make_shared_string("min"));
+  push_int(tm->tm_min);
+  push_string(make_shared_string("hour"));
+  push_int(tm->tm_hour);
+
+  push_string(make_shared_string("mday"));
+  push_int(tm->tm_mday);
+  push_string(make_shared_string("mon"));
+  push_int(tm->tm_mon);
+  push_string(make_shared_string("year"));
+  push_int(tm->tm_year);
+
+  push_string(make_shared_string("wday"));
+  push_int(tm->tm_wday);
+  push_string(make_shared_string("yday"));
+  push_int(tm->tm_yday);
+  push_string(make_shared_string("isdst"));
+  push_int(tm->tm_isdst);
+
+  push_string(make_shared_string("timezone"));
+#if !HAVE_INT_TIMEZONE
+  push_int(_tz);
+#else
+  push_int(timezone);
+#endif
+  f_aggregate_mapping(20);
+}
+
+#ifdef HAVE_STRERROR
+void f_strerror(INT32 args)
+{
+  char *s;
+  if(!args) 
+    s=strerror(errno);
+  else
+    s=strerror(sp[-args].u.integer);
+  pop_n_elems(args);
+  if(s)
+    push_text(s);
+  else
+    push_int(0);
+}
+#endif
+
+#endif