/* * InterpAliasCmd.java -- * * Implements the built-in "interp" Tcl command. * * Copyright (c) 2000 Christian Krone. * * 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: InterpAliasCmd.java,v 1.1 2000/08/20 06:08:42 mo Exp $ * */ using System; using System.Collections; namespace tcl.lang { /// This class implements the alias commands, which are created /// in response to the built-in "interp alias" command in Tcl. /// /// class InterpAliasCmd : CommandWithDispose { // Name of alias command in slave interp. internal TclObject name; // Interp in which target command will be invoked. private Interp targetInterp; // Tcl list making up the prefix of the target command to be invoked in // the target interpreter. Additional arguments specified when calling // the alias in the slave interp will be appended to the prefix before // the command is invoked. private TclObject prefix; // Source command in slave interpreter, bound to command that invokes // the target command in the target interpreter. private WrappedCommand slaveCmd; // Entry for the alias hash table in slave. // This is used by alias deletion to remove the alias from the slave // interpreter alias table. private string aliasEntry; // Interp in which the command is defined. // This is the interpreter with the aliasTable in Slave. private Interp slaveInterp; public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { targetInterp.preserve(); targetInterp.nestLevel++; targetInterp.resetResult(); targetInterp.allowExceptions(); // Append the arguments to the command prefix and invoke the command // in the target interp's global namespace. TclObject[] prefv = TclList.getElements( interp, prefix ); TclObject cmd = TclList.newInstance(); cmd.preserve(); TclList.replace( interp, cmd, 0, 0, prefv, 0, prefv.Length - 1 ); TclList.replace( interp, cmd, prefv.Length, 0, argv, 1, argv.Length - 1 ); TclObject[] cmdv = TclList.getElements( interp, cmd ); TCL.CompletionCode result = targetInterp.invoke( cmdv, Interp.INVOKE_NO_TRACEBACK ); cmd.release(); targetInterp.nestLevel--; // Check if we are at the bottom of the stack for the target interpreter. // If so, check for special return codes. if ( targetInterp.nestLevel == 0 ) { if ( result == TCL.CompletionCode.RETURN ) { result = targetInterp.updateReturnInfo(); } if ( result != TCL.CompletionCode.OK && result != TCL.CompletionCode.ERROR ) { try { targetInterp.processUnexpectedResult( result ); } catch ( TclException e ) { result = e.getCompletionCode(); } } } targetInterp.release(); interp.transferResult( targetInterp, result ); return TCL.CompletionCode.RETURN; } public void disposeCmd() { if ( (System.Object)aliasEntry != null ) { SupportClass.HashtableRemove( slaveInterp.aliasTable, aliasEntry ); } if ( slaveCmd != null ) { SupportClass.HashtableRemove( targetInterp.targetTable, slaveCmd ); } name.release(); prefix.release(); } internal static void create( Interp interp, Interp slaveInterp, Interp masterInterp, TclObject name, TclObject targetName, int objIx, TclObject[] objv ) { string inString = name.ToString(); InterpAliasCmd alias = new InterpAliasCmd(); alias.name = name; name.preserve(); alias.slaveInterp = slaveInterp; alias.targetInterp = masterInterp; alias.prefix = TclList.newInstance(); alias.prefix.preserve(); TclList.append( interp, alias.prefix, targetName ); TclList.insert( interp, alias.prefix, 1, objv, objIx, objv.Length - 1 ); slaveInterp.createCommand( inString, alias ); alias.slaveCmd = NamespaceCmd.findCommand( slaveInterp, inString, null, 0 ); try { interp.preventAliasLoop( slaveInterp, alias.slaveCmd ); } catch ( TclException e ) { // Found an alias loop! The last call to Tcl_CreateObjCommand made // the alias point to itself. Delete the command and its alias // record. Be careful to wipe out its client data first, so the // command doesn't try to delete itself. slaveInterp.deleteCommandFromToken( alias.slaveCmd ); throw; } // Make an entry in the alias table. If it already exists delete // the alias command. Then retry. if ( slaveInterp.aliasTable.ContainsKey( inString ) ) { InterpAliasCmd oldAlias = (InterpAliasCmd)slaveInterp.aliasTable[inString]; slaveInterp.deleteCommandFromToken( oldAlias.slaveCmd ); } alias.aliasEntry = inString; SupportClass.PutElement( slaveInterp.aliasTable, inString, alias ); // Create the new command. We must do it after deleting any old command, // because the alias may be pointing at a renamed alias, as in: // // interp alias {} foo {} bar # Create an alias "foo" // rename foo zop # Now rename the alias // interp alias {} foo {} zop # Now recreate "foo"... SupportClass.PutElement( masterInterp.targetTable, alias.slaveCmd, slaveInterp ); interp.setResult( name ); } internal static void delete( Interp interp, Interp slaveInterp, TclObject name ) { // If the alias has been renamed in the slave, the master can still use // the original name (with which it was created) to find the alias to // delete it. string inString = name.ToString(); if ( !slaveInterp.aliasTable.ContainsKey( inString ) ) { throw new TclException( interp, "alias \"" + inString + "\" not found" ); } InterpAliasCmd alias = (InterpAliasCmd)slaveInterp.aliasTable[inString]; slaveInterp.deleteCommandFromToken( alias.slaveCmd ); } internal static void describe( Interp interp, Interp slaveInterp, TclObject name ) { // If the alias has been renamed in the slave, the master can still use // the original name (with which it was created) to find the alias to // describe it. string inString = name.ToString(); if ( slaveInterp.aliasTable.ContainsKey( inString ) ) { InterpAliasCmd alias = (InterpAliasCmd)slaveInterp.aliasTable[inString]; interp.setResult( alias.prefix ); } } internal static void list( Interp interp, Interp slaveInterp ) { TclObject result = TclList.newInstance(); interp.setResult( result ); IEnumerator aliases = slaveInterp.aliasTable.Values.GetEnumerator(); while ( aliases.MoveNext() ) { InterpAliasCmd alias = (InterpAliasCmd)aliases.Current; TclList.append( interp, result, alias.name ); } } internal WrappedCommand getTargetCmd( Interp interp ) { TclObject[] objv = TclList.getElements( interp, prefix ); string targetName = objv[0].ToString(); return NamespaceCmd.findCommand( targetInterp, targetName, null, 0 ); } internal static Interp getTargetInterp( Interp slaveInterp, string aliasName ) { if ( !slaveInterp.aliasTable.ContainsKey( aliasName ) ) { return null; } InterpAliasCmd alias = (InterpAliasCmd)slaveInterp.aliasTable[aliasName]; return alias.targetInterp; } } // end InterpAliasCmd }