/* * InterpCmd.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: InterpCmd.java,v 1.1 2000/08/20 06:08:43 mo Exp $ * */ using System; using System.Collections; namespace tcl.lang { /// This class implements the built-in "interp" command in Tcl. class InterpCmd : Command { private static readonly string[] options = new string[] { "alias", "aliases", "create", "delete", "eval", "exists", "expose", "hide", "hidden", "issafe", "invokehidden", "marktrusted", "slaves", "share", "target", "transfer" }; private const int OPT_ALIAS = 0; private const int OPT_ALIASES = 1; private const int OPT_CREATE = 2; private const int OPT_DELETE = 3; private const int OPT_EVAL = 4; private const int OPT_EXISTS = 5; private const int OPT_EXPOSE = 6; private const int OPT_HIDE = 7; private const int OPT_HIDDEN = 8; private const int OPT_ISSAFE = 9; private const int OPT_INVOKEHIDDEN = 10; private const int OPT_MARKTRUSTED = 11; private const int OPT_SLAVES = 12; private const int OPT_SHARE = 13; private const int OPT_TARGET = 14; private const int OPT_TRANSFER = 15; private static readonly string[] createOptions = new string[] { "-safe", "--" }; private const int OPT_CREATE_SAFE = 0; private const int OPT_CREATE_LAST = 1; private static readonly string[] hiddenOptions = new string[] { "-global", "--" }; private const int OPT_HIDDEN_GLOBAL = 0; private const int OPT_HIDDEN_LAST = 1; public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv ) { if ( objv.Length < 2 ) { throw new TclNumArgsException( interp, 1, objv, "cmd ?arg ...?" ); } int cmd = TclIndex.get( interp, objv[1], options, "option", 0 ); switch ( cmd ) { case OPT_ALIAS: { if ( objv.Length >= 4 ) { Interp slaveInterp = getInterp( interp, objv[2] ); if ( objv.Length == 4 ) { InterpAliasCmd.describe( interp, slaveInterp, objv[3] ); return TCL.CompletionCode.RETURN; } if ( ( objv.Length == 5 ) && ( "".Equals( objv[4].ToString() ) ) ) { InterpAliasCmd.delete( interp, slaveInterp, objv[3] ); return TCL.CompletionCode.RETURN; } if ( objv.Length > 5 ) { Interp masterInterp = getInterp( interp, objv[4] ); if ( "".Equals( objv[5].ToString() ) ) { if ( objv.Length == 6 ) { InterpAliasCmd.delete( interp, slaveInterp, objv[3] ); return TCL.CompletionCode.RETURN; } } else { InterpAliasCmd.create( interp, slaveInterp, masterInterp, objv[3], objv[5], 6, objv ); return TCL.CompletionCode.RETURN; } } } throw new TclNumArgsException( interp, 2, objv, "slavePath slaveCmd ?masterPath masterCmd? ?args ..?" ); } case OPT_ALIASES: { Interp slaveInterp = getInterp( interp, objv ); InterpAliasCmd.list( interp, slaveInterp ); break; } case OPT_CREATE: { // Weird historical rules: "-safe" is accepted at the end, too. bool safe = interp.isSafe; TclObject slaveNameObj = null; bool last = false; for ( int i = 2; i < objv.Length; i++ ) { if ( ( !last ) && ( objv[i].ToString()[0] == '-' ) ) { int index = TclIndex.get( interp, objv[i], createOptions, "option", 0 ); if ( index == OPT_CREATE_SAFE ) { safe = true; continue; } i++; last = true; } if ( slaveNameObj != null ) { throw new TclNumArgsException( interp, 2, objv, "?-safe? ?--? ?path?" ); } slaveNameObj = objv[i]; } if ( slaveNameObj == null ) { // Create an anonymous interpreter -- we choose its name and // the name of the command. We check that the command name // that we use for the interpreter does not collide with an // existing command in the master interpreter. int i = 0; while ( interp.getCommand( "interp" + i ) != null ) { i++; } slaveNameObj = TclString.newInstance( "interp" + i ); } InterpSlaveCmd.create( interp, slaveNameObj, safe ); interp.setResult( slaveNameObj ); break; } case OPT_DELETE: { for ( int i = 2; i < objv.Length; i++ ) { Interp slaveInterp = getInterp( interp, objv[i] ); if ( slaveInterp == interp ) { throw new TclException( interp, "cannot delete the current interpreter" ); } InterpSlaveCmd slave = slaveInterp.slave; slave.masterInterp.deleteCommandFromToken( slave.interpCmd ); } break; } case OPT_EVAL: { if ( objv.Length < 4 ) { throw new TclNumArgsException( interp, 2, objv, "path arg ?arg ...?" ); } Interp slaveInterp = getInterp( interp, objv[2] ); InterpSlaveCmd.eval( interp, slaveInterp, 3, objv ); break; } case OPT_EXISTS: { bool exists = true; try { getInterp( interp, objv ); } catch ( TclException e ) { if ( objv.Length > 3 ) { throw; } exists = false; } interp.setResult( exists ); break; } case OPT_EXPOSE: { if ( objv.Length < 4 || objv.Length > 5 ) { throw new TclNumArgsException( interp, 2, objv, "path hiddenCmdName ?cmdName?" ); } Interp slaveInterp = getInterp( interp, objv[2] ); InterpSlaveCmd.expose( interp, slaveInterp, 3, objv ); break; } case OPT_HIDE: { if ( objv.Length < 4 || objv.Length > 5 ) { throw new TclNumArgsException( interp, 2, objv, "path cmdName ?hiddenCmdName?" ); } Interp slaveInterp = getInterp( interp, objv[2] ); InterpSlaveCmd.hide( interp, slaveInterp, 3, objv ); break; } case OPT_HIDDEN: { Interp slaveInterp = getInterp( interp, objv ); InterpSlaveCmd.hidden( interp, slaveInterp ); break; } case OPT_ISSAFE: { Interp slaveInterp = getInterp( interp, objv ); interp.setResult( slaveInterp.isSafe ); break; } case OPT_INVOKEHIDDEN: { bool global = false; int i; for ( i = 3; i < objv.Length; i++ ) { if ( objv[i].ToString()[0] != '-' ) { break; } int index = TclIndex.get( interp, objv[i], hiddenOptions, "option", 0 ); if ( index == OPT_HIDDEN_GLOBAL ) { global = true; } else { i++; break; } } if ( objv.Length - i < 1 ) { throw new TclNumArgsException( interp, 2, objv, "path ?-global? ?--? cmd ?arg ..?" ); } Interp slaveInterp = getInterp( interp, objv[2] ); InterpSlaveCmd.invokeHidden( interp, slaveInterp, global, i, objv ); break; } case OPT_MARKTRUSTED: { if ( objv.Length != 3 ) { throw new TclNumArgsException( interp, 2, objv, "path" ); } Interp slaveInterp = getInterp( interp, objv[2] ); InterpSlaveCmd.markTrusted( interp, slaveInterp ); break; } case OPT_SLAVES: { Interp slaveInterp = getInterp( interp, objv ); TclObject result = TclList.newInstance(); interp.setResult( result ); IEnumerator keys = slaveInterp.slaveTable.Keys.GetEnumerator(); while ( keys.MoveNext() ) { string inString = (string)keys.Current; TclList.append( interp, result, TclString.newInstance( inString ) ); } break; } case OPT_SHARE: { if ( objv.Length != 5 ) { throw new TclNumArgsException( interp, 2, objv, "srcPath channelId destPath" ); } Interp masterInterp = getInterp( interp, objv[2] ); Channel chan = TclIO.getChannel( masterInterp, objv[3].ToString() ); if ( chan == null ) { throw new TclException( interp, "can not find channel named \"" + objv[3].ToString() + "\"" ); } Interp slaveInterp = getInterp( interp, objv[4] ); TclIO.registerChannel( slaveInterp, chan ); break; } case OPT_TARGET: { if ( objv.Length != 4 ) { throw new TclNumArgsException( interp, 2, objv, "path alias" ); } Interp slaveInterp = getInterp( interp, objv[2] ); string aliasName = objv[3].ToString(); Interp targetInterp = InterpAliasCmd.getTargetInterp( slaveInterp, aliasName ); if ( targetInterp == null ) { throw new TclException( interp, "alias \"" + aliasName + "\" in path \"" + objv[2].ToString() + "\" not found" ); } if ( !getInterpPath( interp, targetInterp ) ) { throw new TclException( interp, "target interpreter for alias \"" + aliasName + "\" in path \"" + objv[2].ToString() + "\" is not my descendant" ); } break; } case OPT_TRANSFER: { if ( objv.Length != 5 ) { throw new TclNumArgsException( interp, 2, objv, "srcPath channelId destPath" ); } Interp masterInterp = getInterp( interp, objv[2] ); Channel chan = TclIO.getChannel( masterInterp, objv[3].ToString() ); if ( chan == null ) { throw new TclException( interp, "can not find channel named \"" + objv[3].ToString() + "\"" ); } Interp slaveInterp = getInterp( interp, objv[4] ); TclIO.registerChannel( slaveInterp, chan ); TclIO.unregisterChannel( masterInterp, chan ); break; } } return TCL.CompletionCode.RETURN; } private static Interp getInterp( Interp interp, TclObject[] objv ) { if ( objv.Length == 2 ) { return interp; } else if ( objv.Length == 3 ) { return getInterp( interp, objv[2] ); } else { throw new TclNumArgsException( interp, 2, objv, "?path?" ); } } private static bool getInterpPath( Interp askingInterp, Interp targetInterp ) { if ( targetInterp == askingInterp ) { return true; } if ( targetInterp == null || targetInterp.slave == null ) { return false; } if ( !getInterpPath( askingInterp, targetInterp.slave.masterInterp ) ) { return false; } askingInterp.appendElement( targetInterp.slave.path ); return true; } internal static Interp getInterp( Interp interp, TclObject path ) { TclObject[] objv = TclList.getElements( interp, path ); Interp searchInterp = interp; //Interim storage for interp. to find. for ( int i = 0; i < objv.Length; i++ ) { string name = objv[i].ToString(); if ( !searchInterp.slaveTable.ContainsKey( name ) ) { searchInterp = null; break; } InterpSlaveCmd slave = (InterpSlaveCmd)searchInterp.slaveTable[name]; searchInterp = slave.slaveInterp; if ( searchInterp == null ) { break; } } if ( searchInterp == null ) { throw new TclException( interp, "could not find interpreter \"" + path.ToString() + "\"" ); } return searchInterp; } } // end InterpCmd }