wasCSharpSQLite – Rev 1
?pathlinks?
/*
* BgErrorMgr --
*
* This class manages the background errors for a Tcl interpreter.
*
* 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: BgErrorMgr.java,v 1.6 2002/01/21 06:34:26 mdejong Exp $
*
*/
using System;
using System.Collections;
using System.IO;
namespace tcl.lang
{
/*
* This class manages the background errors for a Tcl interpreter. It
* stores the error information about the interpreter and use an idle
* handler to report the error when the notifier is idle.
*/
class BgErrorMgr : AssocData
{
private void InitBlock()
{
errors = new ArrayList( 10 );
}
/*
* We manage the background errors in this interp instance.
*/
internal Interp interp;
/*
* A TclObject for invoking the "bgerror" command. We use a TclObject
* instead of a String so that we don't need to look up the command
* every time.
*/
internal TclObject bgerrorCmdObj;
/*
* A list of the pending background error handlers.
*/
internal ArrayList errors;
internal BgErrorMgr( Interp i )
{
InitBlock();
interp = i;
bgerrorCmdObj = TclString.newInstance( "bgerror" );
bgerrorCmdObj.preserve();
errors = new ArrayList( 10 );
}
internal void addBgError()
{
BgError bgErr = new BgError( this, interp.getNotifier() );
// The addErrorInfo() call below (with an empty string)
// ensures that errorInfo gets properly set. It's needed in
// cases where the error came from a utility procedure like
// Interp.getVar() instead of Interp.eval(); in these cases
// errorInfo still won't have been set when this procedure is
// called.
interp.addErrorInfo( "" );
bgErr.errorMsg = interp.getResult();
bgErr.errorInfo = null;
try
{
bgErr.errorInfo = interp.getVar( "errorInfo", null, TCL.VarFlag.GLOBAL_ONLY );
}
catch ( TclException e )
{
// Do nothing if var does not exist.
}
bgErr.errorCode = null;
try
{
bgErr.errorCode = interp.getVar( "errorCode", null, TCL.VarFlag.GLOBAL_ONLY );
}
catch ( TclException e )
{
// Do nothing if var does not exist.
}
bgErr.errorMsg.preserve();
bgErr.errorInfo.preserve();
bgErr.errorCode.preserve();
errors.Add( bgErr );
}
public void disposeAssocData( Interp interp )
// The interpreter in which this AssocData
// instance is registered in.
{
for ( int i = errors.Count - 1; i >= 0; i-- )
{
BgError bgErr = (BgError)errors[i];
errors.RemoveAt( i );
bgErr.cancel();
bgErr.errorMsg.release();
bgErr.errorMsg = null;
bgErr.errorInfo.release();
bgErr.errorInfo = null;
bgErr.errorCode.release();
bgErr.errorCode = null;
}
bgerrorCmdObj.release();
bgerrorCmdObj = null;
}
internal class BgError : IdleHandler
{
private void InitBlock( BgErrorMgr enclosingInstance )
{
this.enclosingInstance = enclosingInstance;
}
private BgErrorMgr enclosingInstance;
public BgErrorMgr Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
/*
* The interp's result, errorCode and errorInfo when the bgerror happened.
*/
internal TclObject errorMsg;
internal TclObject errorCode;
internal TclObject errorInfo;
internal BgError( BgErrorMgr enclosingInstance, Notifier n )
: base( n )
{
InitBlock( enclosingInstance );
}
public override void processIdleEvent()
{
// During the execution of this method, elements may be removed from
// the errors list (because a TCL.CompletionCode.BREAK was returned by the bgerror
// command, or because the interp was deleted). We remove this
// BgError instance from the list first so that this instance won't
// be deleted twice.
SupportClass.VectorRemoveElement( Enclosing_Instance.errors, this );
// Restore important state variables to what they were at
// the time the error occurred.
try
{
Enclosing_Instance.interp.setVar( "errorInfo", null, errorInfo, TCL.VarFlag.GLOBAL_ONLY );
}
catch ( TclException e )
{
// Ignore any TclException's, possibly caused by variable traces on
// the errorInfo variable. This is compatible with the behavior of
// the Tcl C API.
}
try
{
Enclosing_Instance.interp.setVar( "errorCode", null, errorCode, TCL.VarFlag.GLOBAL_ONLY );
}
catch ( TclException e )
{
// Ignore any TclException's, possibly caused by variable traces on
// the errorCode variable. This is compatible with the behavior of
// the Tcl C API.
}
// Make sure, that the interpreter will surive the invocation
// of the bgerror command.
Enclosing_Instance.interp.preserve();
try
{
// Invoke the bgerror command.
TclObject[] argv = new TclObject[2];
argv[0] = Enclosing_Instance.bgerrorCmdObj;
argv[1] = errorMsg;
Parser.evalObjv( Enclosing_Instance.interp, argv, 0, TCL.EVAL_GLOBAL );
}
catch ( TclException e )
{
switch ( e.getCompletionCode() )
{
case TCL.CompletionCode.ERROR:
try
{
Channel chan = TclIO.getStdChannel( StdChannel.STDERR );
if ( Enclosing_Instance.interp.getResult().ToString().Equals( "\"bgerror\" is an invalid command name or ambiguous abbreviation" ) )
{
chan.write( Enclosing_Instance.interp, errorInfo );
chan.write( Enclosing_Instance.interp, "\n" );
}
else
{
chan.write( Enclosing_Instance.interp, "bgerror failed to handle background error.\n" );
chan.write( Enclosing_Instance.interp, " Original error: " );
chan.write( Enclosing_Instance.interp, errorMsg );
chan.write( Enclosing_Instance.interp, "\n" );
chan.write( Enclosing_Instance.interp, " Error in bgerror: " );
chan.write( Enclosing_Instance.interp, Enclosing_Instance.interp.getResult() );
chan.write( Enclosing_Instance.interp, "\n" );
}
chan.flush( Enclosing_Instance.interp );
}
catch ( TclException e1 )
{
// Ignore.
}
catch ( IOException e2 )
{
// Ignore, too.
}
break;
case TCL.CompletionCode.BREAK:
for ( int i = Enclosing_Instance.errors.Count - 1; i >= 0; i-- )
{
BgError bgErr = (BgError)Enclosing_Instance.errors[i];
Enclosing_Instance.errors.RemoveAt( i );
bgErr.cancel();
bgErr.errorMsg.release();
bgErr.errorMsg = null;
bgErr.errorInfo.release();
bgErr.errorInfo = null;
bgErr.errorCode.release();
bgErr.errorCode = null;
}
break;
}
}
Enclosing_Instance.interp.release();
errorMsg.release();
errorMsg = null;
errorInfo.release();
errorInfo = null;
errorCode.release();
errorCode = null;
}
} // end BgErrorMgr.BgError
} // end BgErrorMgr
}