/*
 *  sli_io.cc
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/* 
   SLI's i/o functions
*/
#include "config.h"
#include <typeinfo>
#include <iostream>
#include <fstream>
#include <iomanip>

// sstream has functions std::?stringstream
// strstream has functions std::?strstream
// HEP 2002-10-06
#ifdef HAVE_SSTREAM   
#include <sstream>    
#else
#include <strstream>
#endif

#include <cstdio>

#include "fdstream.h"
#include "sli_io.h"
#include "stringdatum.h"
#include "iostreamdatum.h"
#include "integerdatum.h"
#include "doubledatum.h"
#include "arraydatum.h"
#include "namedatum.h"
#include "dictstack.h"
#include "tokenutils.h"



using namespace std;

// The i/o facilities defined in this file shall map the C++ stream i/o
// facilities to SLI. The PS compatible i/o operations shall be implemented
// in terms of the c++ compatible operators.

// Note: As of GNU libstdc++ 2.7.2, most of the ANSI/ISO manipulators
// are not yet supportet, thus the flags are set and unset explicitely.

// String stream operations are not yet (as of Nov 7 1997) defined
// due to the lack of sstream support in libstdc++-2.7.2.x
// This will change in the future.

extern int SLIsignalflag; 


void MathLinkPutStringFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);

  // call: string  -> 

  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL)
    {
      StringDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  std::cout << "sending (" << *sd << ") to Mathematica" << std::endl;    

  i->EStack.pop();
  i->OStack.pop();
}




/*BeginDocumentation
  Name: xifstream - Create an executable input-stream.
  Synopsis: (filename) xifstream -> file true
  -> false
  Description: xifstream first tries to open a file
  by the given name. If this was successful, it creates
  an executable stream-handle.
  If an executable stream is executed (e.g. with exec),
  the interpreter parses this file according to SLI syntax
  and evaluates all contained objects.
  SeeAlso: run
*/
void XIfstreamFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);
  // call: string -> ifstreamhandle true
  //              -> false
  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL)
    {
      StringDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  std::istream *in = new ifdstream(sd->c_str());
  i->OStack.pop();
  if(in->good())
    {
      Token handle_token(new XIstreamDatum(in));
        
      i->OStack.push_move(handle_token);
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}

void IfstreamFunction::execute(SLIInterpreter *i) const
{ 
  /* BeginDocumentation
     Name: ifstream - Open file for reading.
     Synopsis: string ifstream -> ifstreamhandle true
     -> false
     Description: 
     Tries to open the named file for reading. 
     If successful an ifstream handle object
     and the boolean true is returned. In case of failure only the boolean
     false is returned. This function provides a direct interface to the
     C++ ifstream constructor. SLI's search path mechanism is not used. 
     Remarks: commented 26.3.1999, Diesmann
     SeeAlso: xifstream, ofstream  
  */     
  i->assert_stack_load(1);

  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL)
    {
      StringDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  //    std::ifstream *in = new std::ifstream(sd->c_str());
  std::istream *in = new ifdstream(sd->c_str());
  i->OStack.pop();
  if(in->good())
    {
      Token handle_token(new IstreamDatum(in));
        
      i->OStack.push_move(handle_token);
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}

/* BeginDocumentation
   Name: ofstream - Open a file stream for writing.
   Synopsis: string ofstream -> ofstreamhandle true
   -> false
   Description: 
   Open the file by the supplied name for writing. 
   If successful an ofstream handle object
   and the boolean true is returned. In case of failure, only the boolean
   false is returned. This function provides a direct interface to the
   C++ ofstream constructor. SLI's search path mechanism is not used. 
   Remarks: commented 26.3.1999, Diesmann
   SeeAlso: ofsopen  
*/     

void OfstreamFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);

  // call: string -> ofstream true
  //              -> false
  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL)
    {
      StringDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  //    std::ofstream *out = new std::ofstream(sd->c_str());
  std::ostream *out = new ofdstream(sd->c_str());
  i->OStack.pop();
  if(out->good())
    {
      Token handle_token(new OstreamDatum(out));
        
      i->OStack.push_move(handle_token);
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}


// This is the ofstream constructor
// with open mode arguments.
// In the sli we do not implement the ios_base flags
// and rather use the c-mode notation

/* BeginDocumentation
   Name: ofsopen - Open an existing file for appending or writing.
   Synopsis: (name) (mode) ofsopen -> ofstreamhandle true
   -> false
   Parameters: (name) - name of the file.
   (mode) - string with either (w) or (a) to identify
   the access mode. (w) corresponds to writing
   and (a) to appending.								
   Description: 
   Open the named file according to the access mode. If the file
   is not existing, it will be created in the current working directory.
   If the file does exists, the access mode decides whether the file will
   be overwritten (w) or whether the new data will be appended (a). 
   If successful an ofstream handle object and the boolean true is returned. 
   In case of failure, only the boolean
   false is returned. This function provides a direct interface to the
   C++ ofstream constructor. SLI's search path mechanism is not used. 
   Remarks: commented 26.3.1999, Diesmann
   SeeAlso: ofstream  
*/     
void OfsopenFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(2);
  // call: string string -> ofstream true
  //                     -> false

  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.pick(1).datum());

  StringDatum  *md= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL || md == NULL)
    {
      StringDatum const d;
      Token t1 = i->OStack.pick(1);
      Token t2 = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t1.datum()->gettypename().toString() + " or " +
			 t2.datum()->gettypename().toString());
    }

  std::ostream *out=NULL;

  if (static_cast<string>(*md) == "w")
    out = new ofdstream(sd->c_str(), ios::out);
  else if (static_cast<string>(*md) == "a")
    out = new ofdstream(sd->c_str(), ios::out | ios::app);
  else
    {
      i->raiseerror(Name("UnknownFileOpenMode"));
      return;
    }

  if (out!=NULL)
    {
      i->OStack.pop(2);
      if(out->good())
	{
	  Token handle_token(new OstreamDatum(out));
        
	  i->OStack.push_move(handle_token);
	  i->OStack.push(true);
	}
      else
        i->OStack.push(false);
    }

  i->EStack.pop();
}

#ifdef HAVE_SSTREAM


void IsstreamFunction::execute(SLIInterpreter *i) const
{
  // This operator does not work yet, due to the fact that
  // the string, used to initialize the stringstream is not copied
  // but is used as the actual buffer. Thus, in our
  // context this leads to a loss of the buffer, as
  // the string object is destroyed at the end of the function!!
    
  // call: string isstream -> isstream true
  //                       -> false

  i->assert_stack_load(1);

  StringDatum  *sd= dynamic_cast<StringDatum *>(i->OStack.top().datum());

  if(sd == NULL)
    {
      StringDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

#ifdef HAVE_SSTREAM
  std::istringstream *in = new std::istringstream(sd->c_str());
#else
  std::istrstream *in = new std::istrstream(sd->c_str());
#endif
  i->OStack.pop();
  if(in->good())
    {
      i->OStack.push(new IstreamDatum(in));
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}

// old style output string stream
/*BeginDocumentation
  Name: osstream - Create a string-stream object.
  Synopsis:
  osstream -> osstream-handle true
  -> false           
  Description:
  osstream creates a stream object which can later be turned into a
  string. If creation of a usable string-stream object failed for any
  reason, false is returned. Replaces obsolete ostrstream.
  Remarks: commented 6.11.2003, Diesmann
  SeeAlso: str, ofstream, ofsopen 
*/ 
void OsstreamFunction::execute(SLIInterpreter *i) const
{
  // call: osstream -> osstream true
  //                -> false
  
#ifdef HAVE_SSTREAM
  std::ostringstream *out = new std::ostringstream();
#else
  std::ostrtream *out = new std::ostrstream();
#endif
  
  if(out->good())
    {
      i->OStack.push(new OstreamDatum(out));
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}


void StrSStreamFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);

  // call: ostrstream str -> string
  
  OstreamDatum *ostreamdatum = dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == NULL)
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

#ifdef HAVE_SSTREAM
  std::ostringstream *out = dynamic_cast<std::ostringstream *>(ostreamdatum->get());
#else
  std::ostrstream *out = dynamic_cast<std::ostrstream *>(ostreamdatum->get());
#endif
  assert(out !=NULL);
  ostreamdatum->unlock();

  if (out !=NULL)
    {
      if(out->good())
	{                             
	  // *out << ends;  // this causes a 0 as the last character of the string
	  // on the alpha compiler. It is probably a bug to 
	  // use this command with <sstream>. 25.2.02 Diesmann 

	  string s=out->str();            // following Stroustrup 
	  Token t(new StringDatum(s));    //
    
      
	  i->OStack.pop();
	  i->OStack.push_move(t);
	  i->EStack.pop();
	}
      else    
	i->raiseerror(i->BadIOError);  // new style more throw like 
    }
  else    
    i->raiseerror(i->StringStreamExpectedError);   
}

#else

// old style output string stream
/*BeginDocumentation
  Name: ostrstream - Create a string-stream object.
  Synopsis:
  ostrstream -> ostreamhandle true
  -> false           
  Description:
  Obsolete, use osstream instead.
  SeeAlso: str, osstream
*/ 
void OstrstreamFunction::execute(SLIInterpreter *i) const
{
  // call: ostrstream -> ostrstream true
  //                  -> false
 
#ifdef HAVE_SSTREAM
  std::ostringstream *out = new std::ostringstream();
#else
  std::ostrstream *out = new std::ostrstream();
#endif
  assert(out !=NULL);
  
  if(out->good())
    {
      i->OStack.push(new OstreamDatum(out));
      i->OStack.push(true);
    }
  else
    i->OStack.push(false);

  i->EStack.pop();
}

/*BeginDocumentation
  Name: str - Retrieve a string from a string-stream.
  Synopsis: osstream str -> string
  Description: Retrieves the string data from a string-stream object
  SeeAlso: osstream
*/
void StrFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);
  // call: std::ostrstream str -> string
  
  OstreamDatum *ostreamdatum = dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == NULL)
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

#ifdef HAVE_SSTREAM
  std::ostringstream *out = dynamic_cast<std::ostringstream *>(ostreamdatum->get());
#else
  std::ostrstream *out = dynamic_cast<std::ostrstream *>(ostreamdatum->get());
#endif
  assert(out !=NULL);
  ostreamdatum->unlock();

  if (out !=NULL)
    {
      if(out->good())
	{
	  *out << ends;                  // following Josuttis, Nicolai 1996
	  char *s=out->str();            // sec. 13.11.2 page 493 
	  Token t(new StringDatum(s));   //
	  delete [] s;                   //
      
	  i->OStack.pop();
	  i->OStack.push_move(t);
	  i->EStack.pop();
	}
      else    
	i->raiseerror(i->BadIOError);  // new style more throw like 
    }
  else    
    i->raiseerror(i->StringStreamExpectedError);   
}

#endif


/*BeginDocumentation
  Name: print - Print object to a stream

  Synopsis: ostream any <- -> ostream

  Description: Alternatives: You can use <- (undocumented), 
  which is the same as print. 

  Examples: 
  cerr [1 2 3] print endl ; -> <arraytype>

  Author: docu by Marc Oliver Gewaltig and Sirko Straube

  SeeAlso: pprint, =, ==
*/
void PrintFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(2);
    
  // call: ostream obj -> ostream

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(1).datum());
  
  if(ostreamdatum == NULL)
    {
      i->raiseerror(i->ArgumentTypeError);
      return;
    }

  assert(ostreamdatum->valid());
  
  if((*ostreamdatum)->good())
    {
      i->OStack.top()->print(**ostreamdatum);
      if(SLIsignalflag != 0)
	(*ostreamdatum)->clear();
    
      i->OStack.pop();
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

/*BeginDocumentation
  Name: pprint - pretty print: Print object to a stream

  Synopsis: ostream any <- -> ostream

  Description: Alternatives: You can use <-- (undocumented), 
  which is the same as pprint. 

  Examples: 
  cerr [1 2 3] pprint endl ; -> [1 2 3]

  Author: docu by Marc Oliver Gewaltig and Sirko Straube

  SeeAlso: print, =, ==
*/

void PrettyprintFunction::execute(SLIInterpreter *i) const
{
  // call: ostream obj -> ostream

  i->assert_stack_load(2);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(1).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.pick(1);
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      i->OStack.top()->pprint(**ostreamdatum);
      if(SLIsignalflag != 0)
	(*ostreamdatum)->clear();
      i->OStack.pop();
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}
 
/*BeginDocumentation
  Name: flush - Force the buffer of a stream to be flushed.
  Synopsis: ostream flush -> ostream
*/   
void FlushFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);
  // call: ostream -> ostream

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->flush();
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

/*BeginDocumentation
  Name: endl - line break

  Examples: Watch the difference:
  cerr (hello) print
  cerr (hello) print endl

  Author: docu by Sirko Straube

  SeeAlso: print, pprint, cout, cerr
*/

void EndlFunction::execute(SLIInterpreter *i) const
{
    
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      **ostreamdatum << std::endl;
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void EndsFunction::execute(SLIInterpreter *i) const
{
    
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(1).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.pick(1);
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      **ostreamdatum << ends;
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void EatwhiteFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == NULL || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*istreamdatum)->good())
    {
      if(!(*istreamdatum)->eof())
	(**istreamdatum) >>  ws;
      i->EStack.pop();
    }  
  else
    i->raiseerror(i->BadIOError);
}



void CloseistreamFunction::execute(SLIInterpreter *i) const
{
  // call: istream -> -

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == NULL || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if(istreamdatum->get() != &std::cin)
    {     
      istreamdatum->unlock();
      
      // The following dynamic cast yields a seg-fault if
      // the datum conatains &std::cin !!
      ifdstream *ifs= dynamic_cast<ifdstream *>(istreamdatum->get());
      istreamdatum->unlock();
      if(ifs != NULL)
	{
	  ifs->close();
	  // iostreamhandle->destroy();
	  i->OStack.pop();
	  i->EStack.pop();
	}
      else
	i->raiseerror(i->ArgumentTypeError);
    }
  else
    i->raiseerror(i->BadIOError);
}


void CloseostreamFunction::execute(SLIInterpreter *i) const
{
  // This function causes a segmentation fault on linux systems.
  // There the problem is that you cannot close an ofstream over
  // its base-class ostream pointer.
  // This applies to g++ 2.7.2.x

  // call: ostream -> -

  i->assert_stack_load(1);
    
  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == NULL)
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if(ostreamdatum->get() != &std::cout)
    {
      ostreamdatum->unlock();
      // The following dynamic cast yields a seg-fault if
      // the datum conatains &std::cout !!
      ofdstream *ofs= dynamic_cast<ofdstream *>(ostreamdatum->get());
      ostreamdatum->unlock();

      if(ofs != NULL)
	{
	  ofs->close();
	  i->OStack.pop();
	  i->EStack.pop();
	}
      else i->raiseerror(i->ArgumentTypeError);
    }
  else
    i->raiseerror(i->BadIOError);
}

void SetwFunction::execute(SLIInterpreter *i) const
{
  // call: ostreamhandle num -> ostreamhandle

  i->assert_stack_load(2);
  
  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(1).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.pick(1);
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  IntegerDatum *id= dynamic_cast<IntegerDatum *>(i->OStack.top().datum());

  if(id == NULL)
    {
      IntegerDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
    
  if((*ostreamdatum)->good())
    {
      **ostreamdatum << setw(id->get())  ;
      i->OStack.pop();
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

/* BeginDocumentation
   Name: setprecision - set precision for decimal place of a stream

   Synopsis: ostream int setprecision -> ostream

   Examples: 
   cerr 3 setprecision 3.12345678901 pprint endl -> 3.123
   cerr 9 setprecision 3.12345678901 pprint endl -> 3.123456789

   Author: docu by Sirko Straube

   SeeAlso: cerr, endl, pprint
*/

void SetprecisionFunction::execute(SLIInterpreter *i) const
{
  // call: ostream num -> ostream

  i->assert_stack_load(2);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(1).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.pick(1);
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  IntegerDatum *id= dynamic_cast<IntegerDatum *>(i->OStack.top().datum());

  if(id == NULL)
    {
      IntegerDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
    
  if((*ostreamdatum)->good())
    {
      **ostreamdatum << std::setprecision(id->get())  ;
      i->OStack.pop();
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSFixedFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.pick(1);
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->setf(ios::fixed);
      (*ostreamdatum)->unsetf(ios::scientific);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSScientificFunction::execute(SLIInterpreter *i) const
{
  // call: ostreamhandle -> ostreamhandle

  i->assert_stack_load(1);
  
  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::fixed);
      (*ostreamdatum)->setf(ios::scientific);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSDefaultFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::fixed);
      (*ostreamdatum)->unsetf(ios::scientific);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSShowpointFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->setf(ios::showpoint);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSNoshowpointFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream
  
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::showpoint);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}


void IOSOctFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);
  
  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      **ostreamdatum << oct;
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSHexFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream
  
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      **ostreamdatum << hex;
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSDecFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      **ostreamdatum << dec;
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSShowbaseFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->setf(ios::showbase);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSNoshowbaseFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::showbase);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSLeftFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->setf(ios::left);
      (*ostreamdatum)->unsetf(ios::right);
      (*ostreamdatum)->unsetf(ios::internal);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSRightFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream

  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::left);
      (*ostreamdatum)->setf(ios::right);
      (*ostreamdatum)->unsetf(ios::internal);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

void IOSInternalFunction::execute(SLIInterpreter *i) const
{
  // call: ostream -> ostream
  
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.pick(0).datum());

  if(ostreamdatum == NULL || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*ostreamdatum)->good())
    {
      (*ostreamdatum)->unsetf(ios::left);
      (*ostreamdatum)->unsetf(ios::right);
      (*ostreamdatum)->setf(ios::internal);
      i->EStack.pop();
    }
  else
    i->raiseerror(i->BadIOError);
}

/* BeginDocumentation
   Name: getc - Read single character from input stream.
   Synopsis: istream getc -> istream integer
   Description: getc reads a single character from the
   supplied input stream. The character is
   returned as integer. The mapping between
   characters and its numerical value is
   determined by the C++ compiler.
   Diagnostics: Raises BadIOError
   SeeAlso: gets, getline
*/

void GetcFunction::execute(SLIInterpreter *i) const
{
  // call: istream -> istream char

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == NULL || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  char c;
  if((*istreamdatum)->get(c))
    {
      Token int_token(new IntegerDatum(c));
        
      i->OStack.push_move(int_token);
      i->EStack.pop();
    }
  else
    {
      if(SLIsignalflag != 0)
	{
	  // else a SignalError will be raised by the interpreter cycle
	  (*istreamdatum)->clear();
	  i->EStack.pop();
	}
      else
	i->raiseerror(i->BadIOError);
    }
}

/* BeginDocumentation
   Name: gets - Read white space terminated string from stream
   Synopsis: istream gets -> istream string
   Description: gets reads a single string from the istream.
   The stream argument is not removed from the stack
   to support successive application of gets.
   Diagnostics: Raises BadIOError if the read was not successful.
   SeeAlso: getline, getc
*/

void GetsFunction::execute(SLIInterpreter *i) const
{
  // call: istream -> istream string

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  //    char buffer[256];
  string s;

  if( *(*istreamdatum) >> s)
    {
      Token str_token(new StringDatum(s));
        
      i->OStack.push_move(str_token);
      i->EStack.pop();
    }
  else
    {
      if(SLIsignalflag == 0)
	{
	  i->raiseerror(i->BadIOError);
	}
      else
	{
	  // else a SignalError will be raised by the interpreter cycle
	  (*istreamdatum)->clear();
	  i->EStack.pop();
	}
    }

}


void GetlineFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: getline - Read a newline terminated string from an input stream.
     Synopsis: istreamhandle getline -> istreamhandle string true
     -> istreamhandle false
     Description: getline reads a line from the supplied stream.
     If the read process was successful, a result string and
     the boolean true are returned. 
     If an error occured while reading from the stream, only the
     stream and boolean false is returned. 
     Diagnostics: No errors are raised. If getline is applied to an
     invalid stream, the return value is false. The return value
     false indicates that the state of the stream is no longer
     "good".

     Author: Diesmann & Gewaltig
     Remarks: commented 26.3.1999, Diesmann
     SeeAlso: getc, gets, file
  */ 
  i->assert_stack_load(1);
  
  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*istreamdatum)->good() && !(*istreamdatum)->eof() )
    {
      string s;
      getline(**istreamdatum, s);
      if(!(*istreamdatum)->good())
	{
	  if(SLIsignalflag == 0)
	    {
	      i->OStack.push(false);
	    }
	  else
	    {
	      // else a SignalError will be raised by the interpreter cycle
	      (*istreamdatum)->clear();
	      return;
	    }
	}
      else
	{
	  Token string_token( new StringDatum(s));
	
	  i->OStack.push_move(string_token);         
	  i->OStack.push(true);
	}
    }    
  else
    i->OStack.push(false);

  i->EStack.pop();
    
}

void IGoodFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: igood - check the "good"-flag of a stream.
     Synopsis: istreamhandle igood -> istreamhandle true
     -> istreamhandle false
     Description:
     This function provides a direct interface to
     the C++ istream::good() member function. 
     Parameters: 
     Examples: 
     Bugs: 
     Author: Diesmann
     FirstVersion: 26.3.1999
     Remarks: 
     SeeAlso: ogood, good
  */ 

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*istreamdatum)->good())
    i->OStack.push(true); 
  else    
    i->OStack.push(false); 

  i->EStack.pop();
}

void IClearFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: iclear - Clear the state-flags of input stream.
     Synopsis: istream iclear -> istream

     Description:
     This function provides a direct interface to
     the C++ istream::clear() member function. 

     Bugs: 
     Author: Gewaltig

     Remarks: 
     SeeAlso: oclear, good
  */ 

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
        
  (*istreamdatum)->clear();

  i->EStack.pop();

}

void OClearFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: oclear - Clear the state-flags of an output stream.
     Synopsis: ostream oclear -> ostream

     Description:
     This function provides a direct interface to
     the C++ ostream::clear() member function. 

     Bugs: 
     Author: Gewaltig

     Remarks: 
     SeeAlso: iclear, good
  */ 
  
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum = dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == 0 || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
          
  (*ostreamdatum)->clear();
  i->EStack.pop();

}

void IFailFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: ifail - Check the "fail"-flag of an input stream.
     Synopsis: istreamhandle ifail -> istreamhandle true
     -> istreamhandle false
     Description:
     This function provides a direct interface to
     the C++ istream::fail() member function. 
     If true, the next operation on the stream will fail.
     Parameters: 
     Examples: 
     Bugs: 
     Author: Gewaltig
     FirstVersion: 21.5.1999
     Remarks: 
     SeeAlso: ogood, good
  */ 

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
          
  if((*istreamdatum)->fail())
    i->OStack.push(true); 
  else    
    i->OStack.push(false); 

  i->EStack.pop();
}


void OGoodFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: ogood - Check the "good"-flag of an output stream.
     Synopsis: ostreamhandle ogood -> ostreamhandle true
     -> ostreamhandle false
     Description:
     This function provides a direct interface to
     the C++ ostream::good() member function. 
     Parameters: 
     Examples: 
     Bugs: 
     Author: Diesmann
     FirstVersion: 26.3.1999
     Remarks: 
     SeeAlso: igood, good
  */ 
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == 0 || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
          
  if((*ostreamdatum)->good())
    i->OStack.push(true); 
  else    
    i->OStack.push(false); 

  i->EStack.pop();
}

void IEofFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: ieof - Check the "eof"-flag of an input stream.
     Synopsis: istreamhandle ieof -> istreamhandle true
     -> istreamhandle false
     Description:
     This function provides a direct interface to
     the C++ istream::eof() member function. 
     Parameters: 
     Examples: 
     Bugs: 
     Author: Diesmann, Hehl
     FirstVersion: 19.4.1999
     Remarks: 
     SeeAlso: oeof, eof
  */ 
  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());
  
  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }

  if((*istreamdatum)->eof())
    i->OStack.push(true); 
  else    
    i->OStack.push(false); 
  
  i->EStack.pop();
}


void OEofFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: oeof - Check the "eof"-flag of an output stream.
     Synopsis: ostreamhandle oeof -> ostreamhandle true
     -> ostreamhandle false
     Description:
     This function provides a direct interface to
     the C++ ostream::eof() member function. 
     Parameters: 
     Examples: 
     Bugs: 
     Author: Diesmann, Hehl
     FirstVersion: 19.4.1999
     Remarks: 
     SeeAlso: ieof, eof
  */ 
  i->assert_stack_load(1);

  OstreamDatum *ostreamdatum=
    dynamic_cast<OstreamDatum *>(i->OStack.top().datum());

  if(ostreamdatum == 0 || !ostreamdatum->valid())
    {
      OstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
  
  if((*ostreamdatum)->eof())
    i->OStack.push(true); 
  else    
    i->OStack.push(false); 

  i->EStack.pop();
}



void Cvx_fFunction::execute(SLIInterpreter *i) const
{
  i->assert_stack_load(1);

  IstreamDatum  *sd= dynamic_cast<IstreamDatum *>(i->OStack.top().datum());
  if(sd !=NULL)
    {
      Token handle_token(new XIstreamDatum(*sd));
      i->OStack.pop();
      
      i->OStack.push_move(handle_token);
    }

  i->EStack.pop();
}

void In_AvailFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: in_avail - Return the number of available in an input stream's buffer.
     Synopsis: istreamhandle in_avail -> istreamhandle available_characters
     Description:
     This function provides a direct interface to
     the C++ istream::rdbuf()->in_avail() member function. 
     Author: R Kupper
     FirstVersion: May 05 1999
     SeeAlso:
  */ 
  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());
  
  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
    
  Token result_t ( new IntegerDatum( (*istreamdatum)->rdbuf()->in_avail() ) );
  i->OStack.push_move(result_t); 

  i->EStack.pop();
}

void ReadDoubleFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: ReadDouble - Read a double number from an input stream.
     Synopsis: istream ReadDouble -> istream double true
     -> istream false
     SeeAlso: ReadInt, ReadWord
  */ 
  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0)
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
  
  if(istreamdatum->valid())
    {
      double d;
      if(*(*istreamdatum) >> d)
	{
	  Token result_t ( new DoubleDatum(d ) );
	  i->OStack.push_move(result_t);
	  i->OStack.push(true);
	  i->EStack.pop();
	}
      else
	{
	  if(SLIsignalflag == 0)
	    {
	      i->OStack.push(false);
	      i->EStack.pop();
	
	    }
	  else
	    {
	      // else a SignalError will be raised by the interpreter cycle
	      (*istreamdatum)->clear();
	    }
	}
    } 
  else i->raiseerror(i->BadIOError);
}

void ReadIntFunction::execute(SLIInterpreter *i) const
{
  /* BeginDocumentation
     Name: ReadInt - Read an integer number from an input stream.
     Synopsis: istream ReadInt -> istream int true
     -> istream false
     SeeAlso: ReadDouble, ReadWord
  */ 
  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0)
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
  
  if(istreamdatum->valid())
    {
      long val;
      if(*(*istreamdatum) >> val)
	{
	  Token result_t ( new IntegerDatum(val) );
	  i->OStack.push_move(result_t);
	  i->OStack.push(true);
	  i->EStack.pop();
	}
      else
	{
	  if(SLIsignalflag == 0)
	    {
	      i->OStack.push(false);
	      i->EStack.pop();
	
	    }
	  else
	    {
	      // else a SignalError will be raised by the interpreter cycle
	      (*istreamdatum)->clear();
	    }
	}
    } 
  else i->raiseerror(i->BadIOError);
}


/* BeginDocumentation
   Name: ReadWord - read white space terminated string from stream
   Synopsis: istream ReadWord -> istream string true
   -> istream false
   Description: ReadWord reads a single word from the istream.
   The stream argument is not removed from the stack
   to support successive application of gets.
   SeeAlso: getline, gets, getc, ReadInt, ReadDouble
*/

void ReadWordFunction::execute(SLIInterpreter *i) const
{
  // call: istream -> istream string

  i->assert_stack_load(1);

  IstreamDatum *istreamdatum=
    dynamic_cast<IstreamDatum *>(i->OStack.top().datum());

  if(istreamdatum == 0 || !istreamdatum->valid())
    {
      IstreamDatum const d;
      Token t = i->OStack.top();
      throw TypeMismatch(d.gettypename().toString(), 
			 t.datum()->gettypename().toString());
    }
  
  //    char buffer[256];
  string s;

  if( *(*istreamdatum) >> s)
    {
      Token str_token(s);
        
      i->OStack.push_move(str_token);
      i->OStack.push(true);
      i->EStack.pop();
    }
  else
    {
      if(SLIsignalflag == 0)
	{
	  i->OStack.push(false);
	  i->EStack.pop();
	
	}
      else
	{
	  // else a SignalError will be raised by the interpreter cycle
	  (*istreamdatum)->clear();
	}
    }

}



const MathLinkPutStringFunction mathlinkputstringfunction;

const XIfstreamFunction   xifstreamfunction;
const IfstreamFunction    ifstreamfunction;
const OfstreamFunction    ofstreamfunction;
const OfsopenFunction    ofsopenfunction;
const Cvx_fFunction       cvx_ffunction;

#ifdef HAVE_SSTREAM
const IsstreamFunction  isstreamfunction;
const OsstreamFunction  osstreamfunction;

const StrSStreamFunction  strsstreamfunction;
#else
const OstrstreamFunction  ostrstreamfunction;
const StrFunction  strfunction;
#endif

const CloseistreamFunction closeistreamfunction;
const CloseostreamFunction closeostreamfunction;
const PrintFunction       printfunction;
const PrettyprintFunction prettyprintfunction;

const FlushFunction       flushfunction;
const EndlFunction        endlfunction;
const EndsFunction        endsfunction;
const EatwhiteFunction    eatwhitefunction;
const SetwFunction        setwfunction;
const SetprecisionFunction setprecisionfunction;
const IOSScientificFunction iosscientificfunction;
const IOSFixedFunction    iosfixedfunction;
const IOSDefaultFunction  iosdefaultfunction;
const IOSShowpointFunction iosshowpointfunction;
const IOSNoshowpointFunction iosnoshowpointfunction;

const IOSShowbaseFunction   iosshowbasefunction;
const IOSNoshowbaseFunction iosnoshowbasefunction;
const IOSDecFunction        iosdecfunction;
const IOSHexFunction        ioshexfunction;
const IOSOctFunction        iosoctfunction;

const IOSLeftFunction       iosleftfunction;
const IOSRightFunction      iosrightfunction;
const IOSInternalFunction   iosinternalfunction;

const GetcFunction          getcfunction;
const GetsFunction          getsfunction;
const GetlineFunction       getlinefunction;

const OClearFunction        oclearfunction;
const IClearFunction        iclearfunction;
const IFailFunction          ifailfunction;
const IGoodFunction          igoodfunction;
const OGoodFunction          ogoodfunction;

const IEofFunction          ieoffunction;
const OEofFunction          oeoffunction;

const In_AvailFunction      in_availfunction;

const ReadDoubleFunction    readdoublefunction;
const ReadIntFunction       readintfunction;
const ReadWordFunction      readwordfunction;
// const ReadListFunction      readlistfunction;



void init_sli_io(SLIInterpreter *i)
{
  // the following objects should be placed in the
  // ios dictionary.
  Token t_cin ( new IstreamDatum(std::cin ));
  Token t_cout( new OstreamDatum(std::cout));
  Token t_cerr( new OstreamDatum(std::cerr));
    
  /*BeginDocumentation
    Name: cin - Standard input stream
    Synopsis: cin -> istream
    Description: cin corresponds to the C++ object with the
    same name.
    SeeAlso: cout, cerr
  */

  i->def_move("cin",t_cin);
  /*BeginDocumentation
    Name: cout - Standard output stream
    Synopsis: cout -> ostream
    Description: cout corresponds to the C++ object with the
    same name.
    SeeAlso: cin, cerr
  */
  i->def_move("cout",t_cout);
  /*BeginDocumentation
    Name: cerr - Standard error output stream
    Synopsis: cerr -> ostream
    Description: cerr corresponds to the C++ object with the
    same name.
    SeeAlso: cin, cout
  */
  i->def_move("cerr",t_cerr);

  // these objects belong to the system dictionary

  i->createcommand("MathLinkPutString", &mathlinkputstringfunction);

  i->createcommand("ifstream", &ifstreamfunction);
  i->createcommand("xifstream", &xifstreamfunction);
  i->createcommand("ofstream", &ofstreamfunction);
  i->createcommand("ofsopen", &ofsopenfunction);
  i->createcommand("cvx_f", &cvx_ffunction);
    
#ifdef HAVE_SSTREAM
  i->createcommand("isstream", &isstreamfunction);
  i->createcommand("osstream", &osstreamfunction);

  i->createcommand("ostrstream", &osstreamfunction);   
  i->createcommand("str", &strsstreamfunction);   
#else
  i->createcommand("ostrstream", &ostrstreamfunction);   
  i->createcommand("str", &strfunction);     
#endif


  i->createcommand("closeistream", &closeistreamfunction);
  i->createcommand("closeostream", &closeostreamfunction);
  i->createcommand("<-", &printfunction);
  i->createcommand("<--", &prettyprintfunction);
  i->createcommand("print", &printfunction);
  i->createcommand("pprint", &prettyprintfunction);

  i->createcommand("flush", &flushfunction);
  i->createcommand("endl", &endlfunction);
  i->createcommand("ends", &endsfunction);
  i->createcommand("ws",   &eatwhitefunction);
  i->createcommand("setw", &setwfunction);
  i->createcommand("setprecision", &setprecisionfunction);
  i->createcommand("fixed", &iosfixedfunction);
  i->createcommand("scientific", &iosscientificfunction);
  i->createcommand("default", &iosdefaultfunction);
  i->createcommand("showpoint", &iosshowpointfunction);
  i->createcommand("noshowpoint", &iosnoshowpointfunction);

  i->createcommand("noshowbase", &iosnoshowbasefunction);
  i->createcommand("showbase",   &iosshowbasefunction);
  i->createcommand("dec",   &iosdecfunction);
  i->createcommand("hex",   &ioshexfunction);
  i->createcommand("oct",   &iosoctfunction);
  i->createcommand("left",    &iosleftfunction);
  i->createcommand("right",   &iosrightfunction);
  i->createcommand("internal",&iosinternalfunction);
  i->createcommand("getc",   &getcfunction);
  i->createcommand("gets",   &getsfunction);
  i->createcommand("getline_is",&getlinefunction);
  i->createcommand("ifail",&ifailfunction);    
  i->createcommand("iclear",&iclearfunction);    
  i->createcommand("oclear",&oclearfunction);    
  i->createcommand("igood",&igoodfunction);    
  i->createcommand("ogood",&ogoodfunction);
  i->createcommand("ieof",&ieoffunction);    
  i->createcommand("oeof",&oeoffunction);
  i->createcommand("in_avail",&in_availfunction);
  i->createcommand("ReadDouble",&readdoublefunction);
  i->createcommand("ReadInt",&readintfunction);
  i->createcommand("ReadWord",&readwordfunction);
  //    i->createcommand("ReadList",&readlistfunction);
}