diff --git a/.gitattributes b/.gitattributes
index c7abbe7f3325eaf056b8011f33e0d531d51b88a9..c809f66f05862a289fd4b1fc8784909a97a7476a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -471,6 +471,7 @@ testfont binary
 /src/modules/files/sendfiletest.pike foreign_ident
 /src/modules/files/socket.c foreign_ident
 /src/modules/files/socktest.pike foreign_ident
+/src/modules/files/stat.c foreign_ident
 /src/modules/files/termios.c foreign_ident
 /src/modules/files/udp.c foreign_ident
 /src/modules/math/Makefile.in foreign_ident
diff --git a/lib/master.pike.in b/lib/master.pike.in
index 2e2c2c8480cb7573009a47bcd32e413479e3ad23..9739c01a2de519673e213ac7826d6e04c3988e5d 100644
--- a/lib/master.pike.in
+++ b/lib/master.pike.in
@@ -1,6 +1,6 @@
 /* -*- Pike -*-
  *	
- * $Id: master.pike.in,v 1.125 2000/08/22 02:15:46 mast Exp $
+ * $Id: master.pike.in,v 1.126 2000/08/27 18:29:26 mirar Exp $
  * 
  * Master-file for Pike.
  *
@@ -182,7 +182,8 @@ string combine_path_with_cwd(string path)
 int invalidate_time;
 mapping(string:multiset(string)) dir_cache = ([]);
 
-array master_file_stat(string x)
+#define Stat _static_modules.files.Stat
+Stat master_file_stat(string x)
 {
   string file, dir=combine_path_with_cwd(x);
 
@@ -322,7 +323,7 @@ object compilation_mutex = _static_modules.Builtin()->mutex();
 static program low_findprog(string pname, string ext, object|void handler)
 {
   program ret;
-  array s;
+  Stat s;
   string fname=pname+ext;
 
 #ifdef THREADED
@@ -375,7 +376,7 @@ static program low_findprog(string pname, string ext, object|void handler)
     case "":
     case ".pike":
       foreach(query_precompiled_names(fname), string oname) {
-	if(array s2=master_file_stat(fakeroot(oname)))
+	if(Stat s2=master_file_stat(fakeroot(oname)))
 	{	
 	  if(s2[1]>=0 && s2[3]>=s[3])
 	  {
@@ -873,7 +874,7 @@ object findmodule(string fullname)
     return o;
   }
 
-  if(array stat=master_file_stat(fakeroot(fullname+".pmod")))
+  if(Stat stat=master_file_stat(fakeroot(fullname+".pmod")))
   {
     if(stat[1]==-2)
       return fc[fullname]=dirnode(fullname+".pmod");
diff --git a/lib/modules/Stdio.pmod/Terminfo.pmod b/lib/modules/Stdio.pmod/Terminfo.pmod
index b51d0e0e1890a21d39a609bc087195c8f0c786bf..b001625f07e17346160fdbd618f315edd3654fdd 100644
--- a/lib/modules/Stdio.pmod/Terminfo.pmod
+++ b/lib/modules/Stdio.pmod/Terminfo.pmod
@@ -1,4 +1,4 @@
-// $Id: Terminfo.pmod,v 1.8 2000/03/30 21:21:10 grubba Exp $
+// $Id: Terminfo.pmod,v 1.9 2000/08/27 18:29:27 mirar Exp $
 
 
 #if constant(thread_create)
@@ -650,8 +650,8 @@ class TerminfoDB {
       foreach (({"/usr/share/lib/terminfo", "/usr/share/termcap",
 		 "/usr/lib/terminfo", "/usr/share/misc/terminfo"}), string dn)
       {
-	array(int) s = file_stat(dn);
-	if (arrayp(s) && sizeof(s)>1 && s[1]==-2)
+	.Stat s = file_stat(dn);
+	if (s && s->type=="dir")
 	{
 	  dirname = dn;
 	  break;
diff --git a/lib/modules/Stdio.pmod/module.pmod b/lib/modules/Stdio.pmod/module.pmod
index 7e2afa2af035739e3ad6524963c17fd2e4e3aee0..46206f1a215ef8f931509c794c693849dbe14d5f 100644
--- a/lib/modules/Stdio.pmod/module.pmod
+++ b/lib/modules/Stdio.pmod/module.pmod
@@ -1,4 +1,4 @@
-// $Id: module.pmod,v 1.82 2000/08/06 14:54:16 js Exp $
+// $Id: module.pmod,v 1.83 2000/08/27 18:29:27 mirar Exp $
 
 import String;
 
@@ -620,8 +620,8 @@ string read_file(string filename,void|int start,void|int len)
   if(!f->open(filename,"r")) return 0;
 
   // Disallow devices and directories.
-  array st;
-  if (f->stat && (st = f->stat()) && (st[1] < 0)) {
+  Stat st;
+  if (f->stat && (st = f->stat()) && !st->isreg) {
     throw(({ sprintf("Stdio.read_file(): File %O is not a regular file!\n",
 		     filename),
 	     backtrace()
@@ -661,8 +661,8 @@ string read_bytes(string filename,void|int start,void|int len)
     return 0;
   
   // Disallow devices and directories.
-  array st;
-  if (f->stat && (st = f->stat()) && (st[1] < 0)) {
+  Stat st;
+  if (f->stat && (st = f->stat()) && !st->isreg) {
     throw(({sprintf("Stdio.read_bytes(): File \"%s\" is not a regular file!\n",
 		    filename),
 	    backtrace()
@@ -719,7 +719,7 @@ int append_file(string filename, string what, int|void access)
 
 int file_size(string s)
 {
-  array(int) stat;
+  Stat stat;
   stat=file_stat(s);
   if(!stat) return -1;
   return stat[1]; 
@@ -749,26 +749,26 @@ void perror(string s)
  * The macro is used instead of file_size since
  * is_link requires a special stat mode.
  */
-#define FILE_STAT_SIZE(path) ((file_stat path)||({0,-1}))[1]
+#define FILE_STAT_SIZE(path) ((file_stat path)||([]))
 
 int is_file(string path)
 {
-  return FILE_STAT_SIZE((path)) >= 0;
+  return FILE_STAT_SIZE((path))->isreg;
 }
 
 int is_dir(string path)
 {
-  return FILE_STAT_SIZE((path)) == -2;
+  return FILE_STAT_SIZE((path))->isdir;
 }
 
 int is_link(string path)
 {
-  return FILE_STAT_SIZE((path, 1)) == -3;
+  return FILE_STAT_SIZE((path, 1))->islnk;
 }
 
 int exist(string path)
 {
-   return FILE_STAT_SIZE((path)) != -1;
+   return !!file_stat(path);
 }
 
 mixed `[](string index)
@@ -850,7 +850,7 @@ int mkdirhier (string dir, void|int mode)
 int recursive_rm (string path)
 {
   int res = 1;
-  array a = file_stat(path, 1);
+  Stat a = file_stat(path, 1);
   if(!a)
     return 0;
   if(a[1] == -2)
diff --git a/src/modules/files/Makefile.in b/src/modules/files/Makefile.in
index d71cf830c777da9412ceb87fdb63a50b5c935a9d..ec533dfecf5b17f7ee99c4a15ae2af861af9ca28 100644
--- a/src/modules/files/Makefile.in
+++ b/src/modules/files/Makefile.in
@@ -1,7 +1,7 @@
-# $Id: Makefile.in,v 1.11 1999/11/18 08:02:59 hubbe Exp $
+# $Id: Makefile.in,v 1.12 2000/08/27 18:29:27 mirar Exp $
 @make_variables@
 VPATH=@srcdir@:@srcdir@/../..:../..
-OBJS=file.o efuns.o socket.o termios.o sendfile.o udp.o
+OBJS=file.o efuns.o socket.o termios.o sendfile.o udp.o stat.o
 MODULE_LDFLAGS=@LIBS@
 MODULE_TESTS=local_tests
 
diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index 6c8836d71950c85e7ec2112914a0dcbc16479776..c130326267cc52ad731cc238a11368eda3eb24a4 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -25,7 +25,7 @@
 #include "file_machine.h"
 #include "file.h"
 
-RCSID("$Id: efuns.c,v 1.85 2000/08/23 12:16:22 grubba Exp $");
+RCSID("$Id: efuns.c,v 1.86 2000/08/27 18:29:27 mirar Exp $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -147,7 +147,7 @@ void f_file_stat(INT32 args)
   {
     push_int(0);
   }else{
-    push_array(encode_stat(&st));
+    push_stat(&st);
   }
 }
 
@@ -1046,7 +1046,7 @@ void init_files_efuns(void)
 
   
 /* function(string,int|void:int *) */
-  ADD_EFUN("file_stat",f_file_stat,tFunc(tStr tOr(tInt,tVoid),tArr(tInt)), OPT_EXTERNAL_DEPEND);
+  ADD_EFUN("file_stat",f_file_stat,tFunc(tStr tOr(tInt,tVoid),tObj), OPT_EXTERNAL_DEPEND);
 
   ADD_EFUN("file_truncate",f_file_truncate,tFunc(tStr tInt,tInt),0);
 
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index bb980a6b3a7529e4cdd05179f0632456576290d4..67a64a7e2f70124eb52d65091468af1f47ca651a 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 /**/
 #define NO_PIKE_SHORTHAND
 #include "global.h"
-RCSID("$Id: file.c,v 1.195 2000/08/27 18:20:37 grubba Exp $");
+RCSID("$Id: file.c,v 1.196 2000/08/27 18:29:27 mirar Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -1502,8 +1502,6 @@ static void file_truncate(INT32 args)
   push_int(!res);
 }
 
-struct array *encode_stat(struct stat *);
-
 static void file_stat(INT32 args)
 {
   int fd;
@@ -1532,7 +1530,7 @@ static void file_stat(INT32 args)
     push_int(0);
   }else{
     ERRNO=0;
-    push_array(encode_stat(&s));
+    push_stat(&s);
   }
 }
 
@@ -2447,7 +2445,6 @@ static struct program * file_lock_key_program;
 struct file_lock_key_storage
 {
   struct my_file *f;
-  struct object *file;
 #ifdef _REENTRANT
   struct object *owner;
 #endif
@@ -2499,9 +2496,8 @@ static void low_file_lock(INT32 args, int flags)
     pop_n_elems(args);
     push_int(0);
   }else{
-    THIS->key = o;
+    THIS->key=o;
     OB2KEY(o)->f=THIS;
-    add_ref(OB2KEY(o)->file = Pike_fp->current_object);
     pop_n_elems(args);
     push_object(o);
   }
@@ -2509,7 +2505,7 @@ static void low_file_lock(INT32 args, int flags)
 
 static void file_lock(INT32 args)
 {
-  low_file_lock(args, fd_LOCK_EX);
+  low_file_lock(args,fd_LOCK_EX);
 }
 
 /* If (fd_LOCK_EX | fd_LOCK_NB) is used with lockf, the result will be
@@ -2518,7 +2514,7 @@ static void file_lock(INT32 args)
 #ifdef HAVE_FD_FLOCK
 static void file_trylock(INT32 args)
 {
-  low_file_lock(args, fd_LOCK_EX | fd_LOCK_NB);
+  low_file_lock(args,fd_LOCK_EX | fd_LOCK_NB);
 }
 #else
 static void file_trylock(INT32 args)
@@ -2569,10 +2565,8 @@ static void exit_file_lock_key(struct object *o)
       THIS_KEY->owner=0;
     }
 #endif
-    THIS_KEY->f->key = 0;
-    THIS_KEY->f = 0;
-    free_object(THIS_KEY->file);
-    THIS_KEY->file = NULL;
+    THIS_KEY->f->key=0;
+    THIS_KEY->f=0;
   }
 }
 
@@ -2631,6 +2625,8 @@ void pike_module_exit(void)
 }
 
 void init_files_efuns(void);
+void init_files_stat(void);
+void exit_files_stat(void);
 
 #define REF (*((struct object **)(Pike_fp->current_storage)))
 
@@ -2708,6 +2704,7 @@ void pike_module_init(void)
   int e;
 
   init_files_efuns();
+  init_files_stat();
 
   START_NEW_PROGRAM_ID(STDIO_FD);
   ADD_STORAGE(struct my_file);
diff --git a/src/modules/files/file.h b/src/modules/files/file.h
index d1febff926c3a182d4869fcf2c2f4ea6e1ce249d..1c97a3c73a3ec9536d904fddef0e4711cb500ad9 100644
--- a/src/modules/files/file.h
+++ b/src/modules/files/file.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: file.h,v 1.18 2000/08/22 14:10:40 mast Exp $
+ * $Id: file.h,v 1.19 2000/08/27 18:29:27 mirar Exp $
  */
 
 #ifndef FILE_H
@@ -132,6 +132,7 @@ void pike_module_init(void);
 int pike_make_pipe(int *fds);
 int fd_from_object(struct object *o);
 void f_strerror(INT32 args);
+void push_stat(struct stat *s);
 /* Prototypes end here */
 
 #define FILE_READ               0x1000
diff --git a/src/modules/files/file_functions.h b/src/modules/files/file_functions.h
index 75cddcaa9e36abebd24c9f58b63e11c4183b9e5a..9bcbc138d867f5957da489c12422dc9d82e735e0 100644
--- a/src/modules/files/file_functions.h
+++ b/src/modules/files/file_functions.h
@@ -13,7 +13,7 @@
   FILE_FUNC("seek",file_seek,"function(int,int|void,int|void:int)")
   FILE_FUNC("tell",file_tell,"function(:int)")
   FILE_FUNC("truncate",file_truncate,"function(int:int)")
-  FILE_FUNC("stat",file_stat,"function(:int *)")
+  FILE_FUNC("stat",file_stat,"function(:object)")
   FILE_FUNC("errno",file_errno,"function(:int)")
   FILE_FUNC("mode",file_mode,"function(:int)")
 
diff --git a/src/modules/files/stat.c b/src/modules/files/stat.c
new file mode 100644
index 0000000000000000000000000000000000000000..34b888f37f2fcd7abe91556561ee47cb68d10ec3
--- /dev/null
+++ b/src/modules/files/stat.c
@@ -0,0 +1,498 @@
+#include <sys/stat.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#include "global.h"
+RCSID("$Id: stat.c,v 1.1 2000/08/27 18:29:28 mirar Exp $");
+#include "fdlib.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "bignum.h"
+#include "mapping.h"
+#include "object.h"
+#include "builtin_functions.h"
+
+void f_index(INT32 args);
+void f_add(INT32 args);
+
+struct program *stat_program=NULL;
+
+struct stat_storage
+{
+   struct stat s;
+};
+
+static struct mapping *stat_map=NULL;
+
+enum stat_query
+{STAT_DEV=1, STAT_INO, STAT_MODE, STAT_NLINK, STAT_UID, STAT_GID, STAT_RDEV, 
+ STAT_SIZE, STAT_BLKSIZE, STAT_BLOCKS, STAT_ATIME, STAT_MTIME, STAT_CTIME,
+/* is... */
+ STAT_ISLNK, STAT_ISREG, STAT_ISDIR, STAT_ISCHR, 
+ STAT_ISBLK, STAT_ISFIFO, STAT_ISSOCK,
+/* special */
+ STAT_TYPE, STAT_MODE_STRING};
+
+#define THIS ((struct stat_storage*)(fp->current_storage))
+
+static void stat_push_compat(INT_TYPE n)
+{
+   switch (n)
+   {
+      case 0: push_int(THIS->s.st_mode); break;
+      case 1: 
+	 switch(S_IFMT & THIS->s.st_mode)
+	 {
+	    case S_IFREG:
+	       push_int64((INT64)THIS->s.st_size);
+	       break;
+    
+	    case S_IFDIR: push_int(-2); break;
+#ifdef S_IFLNK
+	    case S_IFLNK: push_int(-3); break;
+#endif
+	    default:
+#ifdef DEBUG_FILE
+	       fprintf(stderr, "encode_stat(): mode:%ld\n", 
+		       (long)S_IFMT & THIS->s.st_mode);
+#endif /* DEBUG_FILE */
+	       push_int(-4);
+	       break;
+	 }
+	 break;
+      case 2: push_int(THIS->s.st_atime); break;
+      case 3: push_int(THIS->s.st_mtime); break;
+      case 4: push_int(THIS->s.st_ctime); break;
+      case 5: push_int(THIS->s.st_uid); break;
+      case 6: push_int(THIS->s.st_gid); break;
+      default:
+      {
+	 INT32 args=1;
+	 SIMPLE_BAD_ARG_ERROR("Stat `[]",1,"int(0..6)");
+      }
+   }
+}
+
+void f_min(INT32 args);
+void f_max(INT32 args);
+
+static void stat_index(INT32 args)
+{
+   if (!args) 
+      SIMPLE_TOO_FEW_ARGS_ERROR("Stat `[]",1);
+   else if (args==1)
+   {
+      if (sp[-args].type==T_INT)
+      {
+	 stat_push_compat(sp[-args].u.integer);
+      }
+      else if (sp[-args].type==T_STRING)
+      {
+	 ref_push_mapping(stat_map);
+	 stack_swap();
+	 f_index(2);
+	 
+	 switch (sp[-1].u.integer) /* always integer there now */
+	 {
+	    case STAT_DEV: push_int(THIS->s.st_dev); break;
+	    case STAT_INO: push_int(THIS->s.st_ino); break;
+	    case STAT_MODE: push_int(THIS->s.st_mode); break;
+	    case STAT_NLINK: push_int(THIS->s.st_nlink); break;
+	    case STAT_UID: push_int(THIS->s.st_uid); break;
+	    case STAT_GID: push_int(THIS->s.st_gid); break;
+	    case STAT_RDEV: push_int(THIS->s.st_rdev); break;
+	    case STAT_SIZE: push_int(THIS->s.st_size); break;
+#ifdef STAT_BLKSIZE
+	    case STAT_BLKSIZE: push_int(THIS->s.st_blksize); break;
+#endif
+#ifdef STAT_BLOCKS
+	    case STAT_BLOCKS: push_int(THIS->s.st_blocks); break;
+#endif
+	    case STAT_ATIME: push_int(THIS->s.st_atime); break;
+	    case STAT_MTIME: push_int(THIS->s.st_mtime); break;
+	    case STAT_CTIME: push_int(THIS->s.st_ctime); break;
+
+	    case STAT_ISREG: 
+	       push_int(S_ISREG(THIS->s.st_mode));
+	       break;
+	    case STAT_ISLNK:
+#ifdef S_ISLNK
+	       push_int(S_ISLNK(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+	    case STAT_ISDIR: 
+#ifdef S_ISDIR
+	       push_int(S_ISDIR(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+	    case STAT_ISCHR: 
+#ifdef S_ISCHR
+	       push_int(S_ISCHR(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+	    case STAT_ISBLK: 
+#ifdef S_ISBLK
+	       push_int(S_ISBLK(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+	    case STAT_ISFIFO: 
+#ifdef S_ISFIFO
+	       push_int(S_ISFIFO(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+	    case STAT_ISSOCK: 
+#ifdef S_ISSOCK
+	       push_int(S_ISSOCK(THIS->s.st_mode));
+#else
+	       push_int(0);
+#endif
+	       break;
+
+	    case STAT_TYPE:
+	       switch (THIS->s.st_mode & S_IFMT)
+	       {
+		  case S_IFREG:
+		     push_constant_text("reg");
+		     break;
+#ifdef S_IFDIR
+		  case S_IFDIR:
+		     push_constant_text("dir");
+		     break;
+#endif
+#ifdef S_IFLNK
+		  case S_IFLNK:
+		     push_constant_text("lnk");
+		     break;
+#endif
+#ifdef S_IFCHR
+		  case S_IFCHR:
+		     push_constant_text("chr");
+		     break;
+#endif
+#ifdef S_IFBLK
+		  case S_IFBLK:
+		     push_constant_text("blk");
+		     break;
+#endif
+#ifdef S_IFFIFO
+		  case S_IFFIFO:
+		     push_constant_text("fifo");
+		     break;
+#endif
+#ifdef S_IFSOCK
+		  case S_IFSOCK:
+		     push_constant_text("sock");
+		     break;
+#endif
+		  default:
+		     push_constant_text("unknown");
+		     break;
+	       }
+	       break;
+	       
+	    case STAT_MODE_STRING:
+	       switch (THIS->s.st_mode & S_IFMT)
+	       {
+		  case S_IFREG:
+		     push_constant_text("-");
+		     break;
+#ifdef S_IFDIR
+		  case S_IFDIR:
+		     push_constant_text("d");
+		     break;
+#endif
+#ifdef S_IFLNK
+		  case S_IFLNK:
+		     push_constant_text("l");
+		     break;
+#endif
+#ifdef S_IFCHR
+		  case S_IFCHR:
+		     push_constant_text("c");
+		     break;
+#endif
+#ifdef S_IFBLK
+		  case S_IFBLK:
+		     push_constant_text("b");
+		     break;
+#endif
+#ifdef S_IFFIFO
+		  case S_IFFIFO:
+		     push_constant_text("f");
+		     break;
+#endif
+#ifdef S_IFSOCK
+		  case S_IFSOCK:
+		     push_constant_text("s");
+		     break;
+#endif
+		  default:
+		     push_constant_text("?");
+		     break;
+	       }
+
+	       if ( (THIS->s.st_mode & S_IRUSR) )
+		  push_constant_text("r");
+	       else
+		  push_constant_text("-");
+		  
+	       if ( (THIS->s.st_mode & S_IWUSR) )
+		  push_constant_text("w");
+	       else
+		  push_constant_text("-");
+		  
+#ifdef S_ISVTX
+	       if ( (THIS->s.st_mode & S_ISVTX) )
+		  push_constant_text("S");
+	       else 
+#endif
+#ifdef S_ISUID
+		  if ( (THIS->s.st_mode & S_ISUID) )
+		     push_constant_text("s");
+		  else 
+#endif
+		     if ( (THIS->s.st_mode & S_IXUSR) )
+			push_constant_text("x");
+		     else
+			push_constant_text("-");
+		  
+	       if ( (THIS->s.st_mode & S_IRGRP) )
+		  push_constant_text("r");
+	       else
+		  push_constant_text("-");
+		  
+	       if ( (THIS->s.st_mode & S_IWGRP) )
+		  push_constant_text("w");
+	       else
+		  push_constant_text("-");
+		  
+#ifdef S_ISUID
+	       if ( (THIS->s.st_mode & S_ISGID) )
+		  push_constant_text("s");
+	       else 
+#endif
+		  if ( (THIS->s.st_mode & S_IXGRP) )
+		     push_constant_text("x");
+		  else
+		     push_constant_text("-");
+
+	       if ( (THIS->s.st_mode & S_IROTH) )
+		  push_constant_text("r");
+	       else
+		  push_constant_text("-");
+		  
+	       if ( (THIS->s.st_mode & S_IWOTH) )
+		  push_constant_text("w");
+	       else
+		  push_constant_text("-");
+		  
+	       if ( (THIS->s.st_mode & S_IXOTH) )
+		  push_constant_text("x");
+	       else
+		  push_constant_text("-");
+		  
+	       f_add(10);
+
+	       break;
+	       
+	       
+	 }
+      }
+      else
+	 SIMPLE_BAD_ARG_ERROR("Stat `[]",1,"int(0..6)|string");
+   }
+   else if (args>=2) /* range */
+   {
+      INT_TYPE from,to,n=0;
+
+/* make in range 0..6 */
+      push_int(6);
+      f_min(2);
+      stack_swap();
+      push_int(0);
+      f_max(2);
+      stack_swap();
+      
+      if (sp[-2].type!=T_INT)
+	 SIMPLE_BAD_ARG_ERROR("Stat `[..]",1,"int(0..6)");
+      if (sp[-1].type!=T_INT)
+	 SIMPLE_BAD_ARG_ERROR("Stat `[..]",1,"int(0..6)");
+
+      from=sp[-2].u.integer;
+      to=sp[-1].u.integer;
+      
+      while (from<=to)
+      {
+	 stat_push_compat(from++);
+	 n++;
+      }
+      f_aggregate(n);
+   }
+
+   stack_pop_n_elems_keep_top(args);
+}
+
+static void stat_cast(INT32 args)
+{
+   if (!args)
+      SIMPLE_TOO_FEW_ARGS_ERROR("Image.Colortable->cast",1);
+   if (sp[-args].type==T_STRING && !sp[-args].u.string->size_shift)
+   {
+      if (strncmp(sp[-args].u.string->str,"array",5)==0)
+      {
+	 pop_n_elems(args);
+	 push_int(0);
+	 push_int(6);
+	 stat_index(2);
+	 return;
+      }
+   }
+   SIMPLE_BAD_ARG_ERROR("Stat cast",1,
+			"string(\"array\")");
+}
+
+static void stat__sprintf(INT32 args)
+{
+   int n=0,x;
+
+   if (args<1)
+      SIMPLE_TOO_FEW_ARGS_ERROR("_sprintf",2);
+
+   if (sp[-args].type!=T_INT)
+      SIMPLE_BAD_ARG_ERROR("_sprintf",0,"integer");
+
+   x=sp[-args].u.integer;
+   pop_n_elems(args);
+   switch (x)
+   {
+      case 'O':
+	 n++; push_constant_text("Stat(");
+	 
+	 ref_push_object(fp->current_object);
+	 push_constant_text("mode_string");
+	 n++; f_index(2);
+
+	 n++; push_constant_text(" ");
+	 
+	 ref_push_object(fp->current_object);
+	 push_constant_text("size");
+	 n++; f_index(2);
+	 n++; push_constant_text("b)");
+	 f_add(n);
+	 return;
+      default:
+	 push_int(0);
+	 return;
+   }
+}
+
+static void stat_indices(INT32 args)
+{
+   pop_n_elems(args);
+   ref_push_mapping(stat_map);
+   f_indices(1);
+}
+
+static void stat_values(INT32 args)
+{
+   int i,z;
+   struct array *a;
+
+   pop_n_elems(args);
+   ref_push_mapping(stat_map);
+   f_indices(1);
+   z=(a=sp[-1].u.array)->size;
+   for (i=0; i<z; i++)
+   {
+      ref_push_object(fp->current_object);
+      push_svalue(a->item+i);
+      f_index(2);
+   }
+   f_aggregate(z);
+   stack_pop_n_elems_keep_top(1);
+}
+
+#undef THIS
+
+void push_stat(struct stat *s)
+{
+   struct object *o;
+   struct stat_storage *stor;
+   o=clone_object(stat_program,0);
+   stor=(struct stat_storage*)get_storage(o,stat_program);
+   stor->s=*s;
+   push_object(o);
+}
+
+/* ---------------------------------------------------------------- */
+
+void init_files_stat()
+{
+   INT_TYPE n=0;
+
+   n++; push_text("dev"); push_int(STAT_DEV);
+   n++; push_text("ino"); push_int(STAT_INO);
+   n++; push_text("mode"); push_int(STAT_MODE);
+   n++; push_text("nlink"); push_int(STAT_NLINK);
+   n++; push_text("uid"); push_int(STAT_UID);
+   n++; push_text("gid"); push_int(STAT_GID);
+   n++; push_text("rdev"); push_int(STAT_RDEV);
+   n++; push_text("size"); push_int(STAT_SIZE);
+   n++; push_text("blksize"); push_int(STAT_BLKSIZE);
+   n++; push_text("blocks"); push_int(STAT_BLOCKS);
+   n++; push_text("atime"); push_int(STAT_ATIME);
+   n++; push_text("mtime"); push_int(STAT_MTIME);
+   n++; push_text("ctime"); push_int(STAT_CTIME);
+
+   n++; push_text("islnk"); push_int(STAT_ISLNK);
+   n++; push_text("isreg"); push_int(STAT_ISREG);
+   n++; push_text("isdir"); push_int(STAT_ISDIR);
+   n++; push_text("ischr"); push_int(STAT_ISCHR);
+   n++; push_text("isblk"); push_int(STAT_ISBLK);
+   n++; push_text("isfifo"); push_int(STAT_ISFIFO);
+   n++; push_text("issock"); push_int(STAT_ISSOCK);
+
+   n++; push_text("type"); push_int(STAT_TYPE);
+   n++; push_text("mode_string"); push_int(STAT_MODE_STRING);
+     
+   f_aggregate_mapping(n*2);
+   stat_map=sp[-1].u.mapping;
+   sp--;
+
+   start_new_program();
+   ADD_STORAGE(struct stat_storage);
+
+   ADD_FUNCTION("`[]",stat_index,
+		tOr(tFunc(tOr(tStr,tIntPos),tOr3(tStr,tInt,tFunction)),
+		    tFunc(tInt tInt,tArr(tInt))),0);
+
+   ADD_FUNCTION("`->",stat_index,
+		tOr(tFunc(tOr(tStr,tIntPos),tOr3(tStr,tInt,tFunction)),
+		    tFunc(tInt tInt,tArr(tInt))),0);
+
+   ADD_FUNCTION("cast",stat_cast,tFunc(tStr,tArray),0);
+   ADD_FUNCTION("_sprintf",stat__sprintf,
+		tFunc(tInt tOr(tVoid,tMapping),tString),0);
+   ADD_FUNCTION("_indices",stat_indices,
+		tFunc(tNone,tArr(tOr(tString,tInt))),0);
+   ADD_FUNCTION("_values",stat_values,
+		tFunc(tNone,tArr(tOr(tString,tInt))),0);
+
+   stat_program=end_program();
+   add_program_constant("Stat",stat_program,0);
+}
+
+void exit_files_stat()
+{
+   free_program(stat_program);
+}
diff --git a/src/version.h b/src/version.h
index 9d5f73692b5e06c030a1935b9ce62a2887057482..443cb7453ae72d2ba776d1bb8aa3343caa82786c 100644
--- a/src/version.h
+++ b/src/version.h
@@ -4,11 +4,11 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 
-/* $Id: version.h,v 1.196 2000/07/04 12:18:20 noring Exp $ */
+/* $Id: version.h,v 1.197 2000/08/27 18:29:28 mirar Exp $ */
 
 #define PIKE_MAJOR_VERSION 7
 #define PIKE_MINOR_VERSION 1
-#define PIKE_BUILD_VERSION 5
+#define PIKE_BUILD_VERSION 6
 
 /* Prototypes begin here */
 void f_version(INT32 args);