/* $Id: FileStream,v 1.1.1.1 2008/11/28 17:57:26 kiesling Exp $ -*-c-*-*/

/*
  This file is part of ctalk.
  Copyright  2005 - 2008  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

/*
 *    FileStream class.
 */

#include <stdio.h>
#include <errno.h>

Stream class FileStream;

FileStream instanceVariable streamMode Integer 0;
FileStream instanceVariable streamDev Integer 0;
FileStream instanceVariable streamRdev Integer 0;
FileStream instanceVariable streamSize LongInteger 0ll;
FileStream instanceVariable streamAtime LongInteger 0ll;
FileStream instanceVariable streamMtime LongInteger 0ll;
FileStream instanceVariable streamCtime LongInteger 0ll;
FileStream instanceVariable streamPos LongInteger 0ll;
FileStream instanceVariable streamErrno Integer 0;
FileStream instanceVariable streamPath String "";

FileStream instanceMethod statStream (void) {

  FILE *file;
  int rval;
  struct stat statbuf;
  char buf[MAXLABEL];
  OBJECT *value_var, *mode_var, *dev_var, *rdev_var, *size_var, 
    *atime_var, *mtime_var, *ctime_var, *path_var, *return_val;

  returnObjectClass Integer;

  value_var = self value;
  mode_var = self streamMode;
  dev_var = self streamDev;
  rdev_var = self streamRdev;
  size_var = self streamSize;
  atime_var = self streamAtime;
  mtime_var = self streamMtime;
  ctime_var = self streamCtime;
  path_var = self streamPath;

  sscanf (value_var -> __o_value, "0x%p", &file);
  if ((rval = stat (path_var -> __o_value, &statbuf)) == SUCCESS) {

    sprintf (buf, "%d", statbuf.st_mode);
    __ctalkSetObjectValueVar (mode_var, buf);
    sprintf (buf, "%d", statbuf.st_dev);
    __ctalkSetObjectValueVar (dev_var, buf);
    sprintf (buf, "%d", statbuf.st_rdev);
    __ctalkSetObjectValueVar (rdev_var, buf);
#if defined (__sparc__) && defined(__svr4__)
    sprintf (buf, "%ld", statbuf.st_size);
    __ctalkSetObjectValueVar (size_var, buf);
#else
    sprintf (buf, "%lld", statbuf.st_size);
    __ctalkSetObjectValueVar (size_var, buf);
#endif
    sprintf (buf, "%lld", statbuf.st_atime);
    __ctalkSetObjectValueVar (atime_var, buf);
    sprintf (buf, "%lld", statbuf.st_mtime);
    __ctalkSetObjectValueVar (mtime_var, buf);
    sprintf (buf, "%lld", statbuf.st_ctime);
    __ctalkSetObjectValueVar (ctime_var, buf);
  }

  /*
   *  Return NULL for now, until rewritten to create an
   *  exception, and the library has a check to make sure
   *  that it discards the return value if the method is
   *  not on the right-hand side of an equation.
   */
  methodReturnNULL
}

FileStream instanceMethod size (void) {

  returnObjectClass LongInteger;

  self statStream;

  return self streamSize;
}

FileStream instanceMethod streamEof (void) {

  OBJECT *self_value;
  FILE *self_stream;
  int r;

  returnObjectClass Integer;

  self_value = self value;
  sscanf (self_value -> __o_value, "0x%p", &self_stream);

  if (feof (self_stream)) {
    return __ctalkCreateObjectInit ("result", "Integer",
 				  "Magnitude", LOCAL_VAR,
 				  "1");
  }

  return __ctalkCreateObjectInit ("result", "Integer",
 				  "Magnitude", LOCAL_VAR,
 				  "0");
}

FileStream instanceMethod = set_value (FileStream f) {

  OBJECT *f_value;

  f_value = __ctalkGetInstanceVariable (f, "value", FALSE);
  __ctalkSetObjectValue (__ctalk_self_internal () -> instancevars,
			 f_value -> __o_value);
  methodReturnSelf
}

extern int	fileno();

FileStream instanceMethod isDir (void) {
  FILE *file;
  int rval;
  struct stat statbuf;
  char buf[MAXLABEL];
  OBJECT *value_var;
  SystemErrnoException new e;

  returnObjectClass Integer;

  value_var = self value;

  sscanf (value_var -> __o_value, "0x%p", &file);
  if ((rval = fstat (fileno (file), &statbuf)) == SUCCESS) {
    sprintf (buf, "%d", S_ISDIR(statbuf.st_mode));
  } else {
    e raiseException;
    strcpy (buf, "0");
  }

  return __ctalkCreateObjectInit ("return_value", "Integer",
				  "Magnitude", LOCAL_VAR, buf);
}
