/*
* TclIO.java --
*
* Copyright (c) 1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*
* Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
*
* RCS @(#) $Id: TclIO.java,v 1.9 2003/03/06 22:53:07 mdejong Exp $
*
*/
using System;
using System.Collections;
using System.IO;
namespace tcl.lang
{
public class TclIO
{
public const int READ_ALL = 1;
public const int READ_LINE = 2;
public const int READ_N_BYTES = 3;
public const int SEEK_SET = 1;
public const int SEEK_CUR = 2;
public const int SEEK_END = 3;
public const int RDONLY = 1;
public const int WRONLY = 2;
public const int RDWR = 4;
public const int APPEND = 8;
public const int CREAT = 16;
public const int EXCL = 32;
public const int TRUNC = 64;
public const int BUFF_FULL = 0;
public const int BUFF_LINE = 1;
public const int BUFF_NONE = 2;
public const int TRANS_AUTO = 0;
public const int TRANS_BINARY = 1;
public const int TRANS_LF = 2;
public const int TRANS_CR = 3;
public const int TRANS_CRLF = 4;
public static int TRANS_PLATFORM;
/// Table of channels currently registered for all interps. The
/// interpChanTable has "" references into this table that
/// stores the registered channels for the individual interp.
///
private static StdChannel stdinChan = null;
private static StdChannel stdoutChan = null;
private static StdChannel stderrChan = null;
public static Channel getChannel( Interp interp, string chanName )
{
return ( (Channel)getInterpChanTable( interp )[chanName] );
}
internal static void registerChannel( Interp interp, Channel chan )
{
if ( interp != null )
{
Hashtable chanTable = getInterpChanTable( interp );
SupportClass.PutElement( chanTable, chan.ChanName, chan );
chan.refCount++;
}
}
internal static void unregisterChannel( Interp interp, Channel chan )
{
Hashtable chanTable = getInterpChanTable( interp );
SupportClass.HashtableRemove( chanTable, chan.ChanName );
if ( --chan.refCount <= 0 )
{
try
{
chan.close();
}
catch ( IOException e )
{
throw new TclRuntimeError( "TclIO.unregisterChannel() Error: IOException when closing " + chan.ChanName + ": " + e.Message, e );
}
}
}
public static Hashtable getInterpChanTable( Interp interp )
{
Channel chan;
if ( interp.interpChanTable == null )
{
interp.interpChanTable = new Hashtable();
chan = getStdChannel( StdChannel.STDIN );
registerChannel( interp, chan );
chan = getStdChannel( StdChannel.STDOUT );
registerChannel( interp, chan );
chan = getStdChannel( StdChannel.STDERR );
registerChannel( interp, chan );
}
return interp.interpChanTable;
}
public static Channel getStdChannel( int type )
{
Channel chan = null;
switch ( type )
{
case StdChannel.STDIN:
if ( stdinChan == null )
{
stdinChan = new StdChannel( StdChannel.STDIN );
}
chan = stdinChan;
break;
case StdChannel.STDOUT:
if ( stdoutChan == null )
{
stdoutChan = new StdChannel( StdChannel.STDOUT );
}
chan = stdoutChan;
break;
case StdChannel.STDERR:
if ( stderrChan == null )
{
stderrChan = new StdChannel( StdChannel.STDERR );
}
chan = stderrChan;
break;
default:
throw new TclRuntimeError( "Invalid type for StdChannel" );
}
return ( chan );
}
/// Really ugly function that attempts to get the next available
/// channelId name. In C the FD returned in the native open call
/// returns this value, but we don't have that so we need to do
/// this funky iteration over the Hashtable.
///
///
/// currrent interpreter.
///
/// the next integer to use in the channelId name.
///
internal static string getNextDescriptor( Interp interp, string prefix )
{
int i;
Hashtable htbl = getInterpChanTable( interp );
// The first available file identifier in Tcl is "file3"
if ( prefix.Equals( "file" ) )
i = 3;
else
i = 0;
for ( ; ( htbl[prefix + i] ) != null; i++ )
{
// Do nothing...
}
return prefix + i;
}
/*
* Return a string description for a translation id defined above.
*/
internal static string getTranslationString( int translation )
{
switch ( translation )
{
case TRANS_AUTO:
return "auto";
case TRANS_CR:
return "cr";
case TRANS_CRLF:
return "crlf";
case TRANS_LF:
return "lf";
case TRANS_BINARY:
return "lf";
default:
throw new TclRuntimeError( "bad translation id" );
}
}
/*
* Return a numerical identifier for the given -translation string.
*/
internal static int getTranslationID( string translation )
{
if ( translation.Equals( "auto" ) )
return TRANS_AUTO;
else if ( translation.Equals( "cr" ) )
return TRANS_CR;
else if ( translation.Equals( "crlf" ) )
return TRANS_CRLF;
else if ( translation.Equals( "lf" ) )
return TRANS_LF;
else if ( translation.Equals( "binary" ) )
return TRANS_LF;
else if ( translation.Equals( "platform" ) )
return TRANS_PLATFORM;
else
return -1;
}
/*
* Return a string description for a -buffering id defined above.
*/
internal static string getBufferingString( int buffering )
{
switch ( buffering )
{
case BUFF_FULL:
return "full";
case BUFF_LINE:
return "line";
case BUFF_NONE:
return "none";
default:
throw new TclRuntimeError( "bad buffering id" );
}
}
/*
* Return a numerical identifier for the given -buffering string.
*/
internal static int getBufferingID( string buffering )
{
if ( buffering.Equals( "full" ) )
return BUFF_FULL;
else if ( buffering.Equals( "line" ) )
return BUFF_LINE;
else if ( buffering.Equals( "none" ) )
return BUFF_NONE;
else
return -1;
}
static TclIO()
{
{
if ( Util.Windows )
TRANS_PLATFORM = TRANS_CRLF;
else if ( Util.Mac )
TRANS_PLATFORM = TRANS_CR;
else
TRANS_PLATFORM = TRANS_LF;
}
}
}
}