public override void eventuallyDispose() { if ( deleted ) { return; } deleted = true; if ( nestLevel > 0 ) { //-- TODO -- Determine why this is an error throw new TclRuntimeError("dispose() called with active evals"); } // Remove our association with the notifer (if we had one). if ( notifier != null ) { notifier.release(); notifier = null; } // Dismantle everything in the global namespace except for the // "errorInfo" and "errorCode" variables. These might be needed // later on if errors occur while deleting commands. We are careful // to destroy and recreate the "errorInfo" and "errorCode" // variables, in case they had any traces on them. // // Dismantle the namespace here, before we clear the assocData. If any // background errors occur here, they will be deleted below. // FIXME : check impl of TclTeardownNamespace NamespaceCmd.teardownNamespace( globalNs ); // Delete all variables. TclObject errorInfoObj = null, errorCodeObj = null; try { errorInfoObj = getVar( "errorInfo", null, TCL.VarFlag.GLOBAL_ONLY ); } catch ( TclException e ) { // Do nothing when var does not exist. } if ( errorInfoObj != null ) { errorInfoObj.preserve(); } try { errorCodeObj = getVar( "errorCode", null, TCL.VarFlag.GLOBAL_ONLY ); } catch ( TclException e ) { // Do nothing when var does not exist. } if ( errorCodeObj != null ) { errorCodeObj.preserve(); } frame = null; varFrame = null; try { if ( errorInfoObj != null ) { setVar( "errorInfo", null, errorInfoObj, TCL.VarFlag.GLOBAL_ONLY ); errorInfoObj.release(); } if ( errorCodeObj != null ) { setVar( "errorCode", null, errorCodeObj, TCL.VarFlag.GLOBAL_ONLY ); errorCodeObj.release(); } } catch ( TclException e ) { // Ignore it -- same behavior as Tcl 8.0. } // Tear down the math function table. expr = null; // Remove all the assoc data tied to this interp and invoke // deletion callbacks; note that a callback can create new // callbacks, so we iterate. // ATK The java code was somethink strong if ( assocData != null ) { foreach ( AssocData data in assocData.Values ) { data.disposeAssocData( this ); } assocData.Clear(); } // Close any remaining channels for ( IDictionaryEnumerator e = interpChanTable.GetEnumerator(); e.MoveNext(); ) { Object key = e.Key; Channel chan = (Channel)e.Value; try { chan.close(); } catch ( IOException ex ) { // Ignore any IO errors } } // Finish deleting the global namespace. // FIXME : check impl of Tcl_DeleteNamespace NamespaceCmd.deleteNamespace( globalNs ); globalNs = null; // Free up the result *after* deleting variables, since variable // deletion could have transferred ownership of the result string // to Tcl. frame = null; varFrame = null; resolvers = null; resetResult(); }
public Interp() { InitBlock(); //freeProc = null; errorLine = 0; // An empty result is used pretty often. We will use a shared // TclObject instance to represent the empty result so that we // don't need to create a new TclObject instance every time the // interpreter result is set to empty. m_nullResult = TclString.newInstance( "" ); m_nullResult.preserve(); // Increment refCount to 1 m_nullResult.preserve(); // Increment refCount to 2 (shared) m_result = TclString.newInstance( "" ); //m_nullResult; // correcponds to iPtr->objResultPtr m_result.preserve(); expr = new Expression(); nestLevel = 0; maxNestingDepth = 1000; frame = null; varFrame = null; returnCode = TCL.CompletionCode.OK; errorInfo = null; errorCode = null; packageTable = new Hashtable(); packageUnknown = null; cmdCount = 0; termOffset = 0; resolvers = null; evalFlags = 0; scriptFile = null; flags = 0; isSafe = false; assocData = null; globalNs = null; // force creation of global ns below globalNs = NamespaceCmd.createNamespace( this, null, null ); if ( globalNs == null ) { throw new TclRuntimeError( "Interp(): can't create global namespace" ); } // Init things that are specific to the Jacl implementation workingDir = new FileInfo( System.Environment.CurrentDirectory ); noEval = 0; notifier = Notifier.getNotifierForThread( System.Threading.Thread.CurrentThread ); notifier.preserve(); randSeedInit = false; deleted = false; errInProgress = false; errAlreadyLogged = false; errCodeSet = false; dbg = initDebugInfo(); slaveTable = new Hashtable(); targetTable = new Hashtable(); aliasTable = new Hashtable(); // init parser variables Parser.init( this ); TclParse.init( this ); // Initialize the Global (static) channel table and the local // interp channel table. interpChanTable = TclIO.getInterpChanTable( this ); // Sets up the variable trace for tcl_precision. Util.setupPrecisionTrace( this ); // Create the built-in commands. createCommands(); try { // Set up tcl_platform, tcl_version, tcl_library and other // global variables. setVar( "tcl_platform", "platform", "windows", TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "byteOrder", "bigEndian", TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "os", Environment.OSVersion.Platform.ToString(), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "osVersion", Environment.OSVersion.Version.ToString(), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_platform", "machine", Util.tryGetSystemProperty( "os.arch", "?" ), TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_version", TCL_VERSION, TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_patchLevel", TCL_PATCH_LEVEL, TCL.VarFlag.GLOBAL_ONLY ); setVar( "tcl_library", "resource:/tcl/lang/library", TCL.VarFlag.GLOBAL_ONLY ); if ( Util.Windows ) { setVar( "tcl_platform", "host_platform", "windows", TCL.VarFlag.GLOBAL_ONLY ); } else if ( Util.Mac ) { setVar( "tcl_platform", "host_platform", "macintosh", TCL.VarFlag.GLOBAL_ONLY ); } else { setVar( "tcl_platform", "host_platform", "unix", TCL.VarFlag.GLOBAL_ONLY ); } // Create the env array an populated it with proper // values. Env.initialize( this ); // Register Tcl's version number. Note: This MUST be // done before the call to evalResource, otherwise // calls to "package require tcl" will fail. pkgProvide( "Tcl", TCL_VERSION ); // Source the init.tcl script to initialize auto-loading. evalResource( "/tcl/lang/library/init.tcl" ); } catch ( TclException e ) { System.Diagnostics.Debug.WriteLine( getResult().ToString() ); SupportClass.WriteStackTrace( e, Console.Error ); throw new TclRuntimeError( "unexpected TclException: " + e.Message, e ); } }