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); }
/// <summary> /// Load the class that implements the given command and execute it. /// </summary> /// <param name="interp"> /// the current interpreter. /// </param> /// <param name="argv"> /// command arguments. /// </param> /// <exception cref=""> /// TclException if error happens inside the real command proc. /// </exception> public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv) { Type cmdClass = null; ICommand cmd; try { cmdClass = Type.GetType(className, true); } catch (Exception) { throw new TclException(interp, "ClassNotFoundException for class \"" + className + "\""); } try { cmd = (ICommand)SupportClass.CreateNewInstance(cmdClass); } catch (UnauthorizedAccessException) { throw new TclException(interp, "IllegalAccessException for class \"" + cmdClass.FullName + "\""); } catch (InvalidCastException) { throw new TclException(interp, "ClassCastException for class \"" + cmdClass.FullName + "\""); } catch (Exception) { throw new TclException(interp, "InstantiationException for class \"" + cmdClass.FullName + "\""); } interp.CreateCommand(argv[0].ToString(), cmd); TCL.CompletionCode rc = cmd.CmdProc(interp, argv); return(rc == TCL.CompletionCode.EXIT ? TCL.CompletionCode.EXIT : TCL.CompletionCode.RETURN); }
/// <summary> /// Tcl_ProcObjCmd -> ProcCmd.cmdProc /// /// Creates a new Tcl procedure. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="objv">command arguments. /// </param> /// <exception cref=""> TclException If incorrect number of arguments. /// </exception> public TCL.CompletionCode CmdProc(Interp interp, TclObject[] objv) { Procedure proc; string fullName, procName; NamespaceCmd.Namespace ns, altNs, cxtNs; ICommand cmd; StringBuilder ds; if (objv.Length != 4) { throw new TclNumArgsException(interp, 1, objv, "name args body"); } // Determine the namespace where the procedure should reside. Unless // the command name includes namespace qualifiers, this will be the // current namespace. fullName = objv[1].ToString(); // Java does not support passing an address so we pass // an array of size 1 and then assign arr[0] to the value NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1]; NamespaceCmd.Namespace[] altNsArr = new NamespaceCmd.Namespace[1]; NamespaceCmd.Namespace[] cxtNsArr = new NamespaceCmd.Namespace[1]; string[] procNameArr = new string[1]; NamespaceCmd.getNamespaceForQualName(interp, fullName, null, 0, nsArr, altNsArr, cxtNsArr, procNameArr); // Get the values out of the arrays ns = nsArr[0]; altNs = altNsArr[0]; cxtNs = cxtNsArr[0]; procName = procNameArr[0]; if (ns == null) { throw new TclException(interp, "can't create procedure \"" + fullName + "\": unknown namespace"); } if ((System.Object)procName == null) { throw new TclException(interp, "can't create procedure \"" + fullName + "\": bad procedure name"); } // FIXME : could there be a problem with a command named ":command" ? if ((ns != NamespaceCmd.getGlobalNamespace(interp)) && ((System.Object)procName != null) && ((procName.Length > 0) && (procName[0] == ':'))) { throw new TclException(interp, "can't create procedure \"" + procName + "\" in non-global namespace with name starting with \":\""); } // Create the data structure to represent the procedure. proc = new Procedure(interp, ns, procName, objv[2], objv[3], interp.ScriptFile, interp.getArgLineNumber(3)); // Now create a command for the procedure. This will initially be in // the current namespace unless the procedure's name included namespace // qualifiers. To create the new command in the right namespace, we // generate a fully qualified name for it. ds = new StringBuilder(); if (ns != NamespaceCmd.getGlobalNamespace(interp)) { ds.Append(ns.fullName); ds.Append("::"); } ds.Append(procName); interp.CreateCommand(ds.ToString(), proc); // Now initialize the new procedure's cmdPtr field. This will be used // later when the procedure is called to determine what namespace the // procedure will run in. This will be different than the current // namespace if the proc was renamed into a different namespace. // FIXME : we do not handle renaming into another namespace correctly yet! //procPtr->cmdPtr = (Command *) cmd; return(TCL.CompletionCode.RETURN); }
internal static void Init(Interp interp) // Current interpreter. { interp.CreateCommand("regexp", new Tcl.Lang.RegexpCmd()); interp.CreateCommand("regsub", new Tcl.Lang.RegsubCmd()); }
internal static Interp create(Interp interp, TclObject path, bool safe) { Interp masterInterp; string pathString; TclObject[] objv = TclList.getElements(interp, path); if (objv.Length < 2) { masterInterp = interp; pathString = path.ToString(); } else { TclObject obj = TclList.NewInstance(); TclList.insert(interp, obj, 0, objv, 0, objv.Length - 2); masterInterp = InterpCmd.getInterp(interp, obj); pathString = objv[objv.Length - 1].ToString(); } if (!safe) { safe = masterInterp._isSafe; } if (masterInterp._slaveTable.ContainsKey(pathString)) { throw new TclException(interp, "interpreter named \"" + pathString + "\" already exists, cannot create"); } Interp slaveInterp = new Interp(); InterpSlaveCmd slave = new InterpSlaveCmd(); slaveInterp._slave = slave; slaveInterp.SetAssocData("InterpSlaveCmd", slave); slave.masterInterp = masterInterp; slave.path = pathString; slave.slaveInterp = slaveInterp; masterInterp.CreateCommand(pathString, slaveInterp._slave); slaveInterp._slave.interpCmd = NamespaceCmd.findCommand(masterInterp, pathString, null, 0); SupportClass.PutElement(masterInterp._slaveTable, pathString, slaveInterp._slave); slaveInterp.SetVar("tcl_interactive", "0", TCL.VarFlag.GLOBAL_ONLY); // Inherit the recursion limit. slaveInterp._maxNestingDepth = masterInterp._maxNestingDepth; if (safe) { try { makeSafe(slaveInterp); } catch (TclException e) { SupportClass.WriteStackTrace(e, Console.Error); } } else { //Tcl_Init(slaveInterp); } return(slaveInterp); }
/// <summary> /// Create a stub command which autoloads the real command the first time the stub command is invoked. Register the stub command in the interpreter. /// </summary> /// <param name="interp"> /// current interp. /// </param> /// <param name="cmdName"> /// name of the command, e.g., "after". /// </param> /// <param name="clsName"> /// name of the Java class that implements this command, e.g. "tcl.lang.AfterCmd" /// </param> public static void LoadOnDemand(Interp interp, string cmdName, string clsName) { interp.CreateCommand(cmdName, new AutoloadStub(clsName)); }