internal static Procedure findProc(Interp interp, string procName) { WrappedCommand cmd; WrappedCommand origCmd; try { cmd = NamespaceCmd.findCommand(interp, procName, null, 0); } catch (TclException e) { // This should never happen throw new TclRuntimeError("unexpected TclException: " + e.Message); } if (cmd == null) { return(null); } origCmd = NamespaceCmd.getOriginalCommand(cmd); if (origCmd != null) { cmd = origCmd; } if (!(cmd.cmd is Procedure)) { return(null); } return((Procedure)cmd.cmd); }
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 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); }
/* *---------------------------------------------------------------------- * * InfoProcsCmd -- * * Called to implement the "info procs" command that returns the * procedures in the current namespace that match an optional pattern. * Handles the following syntax: * * info procs ?pattern? * * Results: * Returns if successful, raises TclException otherwise. * * Side effects: * Returns a result in the interpreter's result object. * *---------------------------------------------------------------------- */ private static void InfoProcsCmd(Interp interp, TclObject[] objv) { string cmdName, pattern; NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp); IDictionaryEnumerator search; WrappedCommand cmd, realCmd; TclObject list; if (objv.Length == 2) { pattern = null; } else if (objv.Length == 3) { pattern = objv[2].ToString(); } else { throw new TclNumArgsException(interp, 2, objv, "?pattern?"); } // Scan through the current namespace's command table and return a list // of all procs that match the pattern. list = TclList.newInstance(); for (search = currNs.cmdTable.GetEnumerator(); search.MoveNext();) { cmdName = ((string)search.Key); cmd = (WrappedCommand)search.Value; // If the command isn't itself a proc, it still might be an // imported command that points to a "real" proc in a different // namespace. realCmd = NamespaceCmd.getOriginalCommand(cmd); if (Procedure.isProc(cmd) || ((realCmd != null) && Procedure.isProc(realCmd))) { if (((System.Object)pattern == null) || Util.stringMatch(cmdName, pattern)) { TclList.append(interp, list, TclString.newInstance(cmdName)); } } } interp.setResult(list); return; }
/* *---------------------------------------------------------------------- * * InfoGlobalsCmd -- * * Called to implement the "info globals" command that returns the list * of global variables matching an optional pattern. Handles the * following syntax: * * info globals ?pattern?* * * Results: * Returns if successful, raises TclException otherwise. * * Side effects: * Returns a result in the interpreter's result object. * *---------------------------------------------------------------------- */ private static void InfoGlobalsCmd(Interp interp, TclObject[] objv) { string varName, pattern; NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp); IDictionaryEnumerator search; Var var; TclObject list; if (objv.Length == 2) { pattern = null; } else if (objv.Length == 3) { pattern = objv[2].ToString(); } else { throw new TclNumArgsException(interp, 2, objv, "?pattern?"); } // Scan through the global :: namespace's variable table and create a // list of all global variables that match the pattern. list = TclList.newInstance(); for (search = globalNs.varTable.GetEnumerator(); search.MoveNext();) { varName = ((string)search.Key); var = (Var)search.Value; if (var.isVarUndefined()) { continue; } if (((System.Object)pattern == null) || Util.stringMatch(varName, pattern)) { TclList.append(interp, list, TclString.newInstance(varName)); } } interp.setResult(list); 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; Command 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); }
/* *---------------------------------------------------------------------- * * InfoCommandsCmd -- * * Called to implement the "info commands" command that returns the * list of commands in the interpreter that match an optional pattern. * The pattern, if any, consists of an optional sequence of namespace * names separated by "::" qualifiers, which is followed by a * glob-style pattern that restricts which commands are returned. * Handles the following syntax: * * info commands ?pattern? * * Results: * Returns if successful, raises TclException otherwise. * * Side effects: * Returns a result in the interpreter's result object. * *---------------------------------------------------------------------- */ private static void InfoCommandsCmd(Interp interp, TclObject[] objv) { string cmdName, pattern, simplePattern; IDictionaryEnumerator search; NamespaceCmd.Namespace ns; NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp); NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp); TclObject list, elemObj; bool specificNsInPattern = false; // Init. to avoid compiler warning. WrappedCommand cmd; // Get the pattern and find the "effective namespace" in which to // list commands. if (objv.Length == 2) { simplePattern = null; ns = currNs; specificNsInPattern = false; } else if (objv.Length == 3) { // From the pattern, get the effective namespace and the simple // pattern (no namespace qualifiers or ::'s) at the end. If an // error was found while parsing the pattern, return it. Otherwise, // if the namespace wasn't found, just leave ns NULL: we will // return an empty list since no commands there can be found. pattern = objv[2].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[] dummy1Arr = new NamespaceCmd.Namespace[1]; NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1]; string[] simplePatternArr = new string[1]; NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr); // Get the values out of the arrays! ns = nsArr[0]; simplePattern = simplePatternArr[0]; if (ns != null) { // we successfully found the pattern's ns specificNsInPattern = (simplePattern.CompareTo(pattern) != 0); } } else { throw new TclNumArgsException(interp, 2, objv, "?pattern?"); } // Scan through the effective namespace's command table and create a // list with all commands that match the pattern. If a specific // namespace was requested in the pattern, qualify the command names // with the namespace name. list = TclList.newInstance(); if (ns != null) { search = ns.cmdTable.GetEnumerator(); while (search.MoveNext()) { cmdName = ((string)search.Key); if (((System.Object)simplePattern == null) || Util.stringMatch(cmdName, simplePattern)) { if (specificNsInPattern) { cmd = (WrappedCommand)search.Value; elemObj = TclString.newInstance(interp.getCommandFullName(cmd)); } else { elemObj = TclString.newInstance(cmdName); } TclList.append(interp, list, elemObj); } } // If the effective namespace isn't the global :: namespace, and a // specific namespace wasn't requested in the pattern, then add in // all global :: commands that match the simple pattern. Of course, // we add in only those commands that aren't hidden by a command in // the effective namespace. if ((ns != globalNs) && !specificNsInPattern) { search = globalNs.cmdTable.GetEnumerator(); while (search.MoveNext()) { cmdName = ((string)search.Key); if (((System.Object)simplePattern == null) || Util.stringMatch(cmdName, simplePattern)) { if (ns.cmdTable[cmdName] == null) { TclList.append(interp, list, TclString.newInstance(cmdName)); } } } } } interp.setResult(list); return; }
/* *---------------------------------------------------------------------- * * InfoVarsCmd -- * * Called to implement the "info vars" command that returns the * list of variables in the interpreter that match an optional pattern. * The pattern, if any, consists of an optional sequence of namespace * names separated by "::" qualifiers, which is followed by a * glob-style pattern that restricts which variables are returned. * Handles the following syntax: * * info vars ?pattern? * * Results: * Returns if successful, raises TclException otherwise. * * Side effects: * Returns a result in the interpreter's result object. * *---------------------------------------------------------------------- */ private static void InfoVarsCmd(Interp interp, TclObject[] objv) { string varName, pattern, simplePattern; IDictionaryEnumerator search; Var var; NamespaceCmd.Namespace ns; NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp); NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp); TclObject list, elemObj; bool specificNsInPattern = false; // Init. to avoid compiler warning. // Get the pattern and find the "effective namespace" in which to // list variables. We only use this effective namespace if there's // no active Tcl procedure frame. if (objv.Length == 2) { simplePattern = null; ns = currNs; specificNsInPattern = false; } else if (objv.Length == 3) { // From the pattern, get the effective namespace and the simple // pattern (no namespace qualifiers or ::'s) at the end. If an // error was found while parsing the pattern, return it. Otherwise, // if the namespace wasn't found, just leave ns = null: we will // return an empty list since no variables there can be found. pattern = objv[2].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[] dummy1Arr = new NamespaceCmd.Namespace[1]; NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1]; string[] simplePatternArr = new string[1]; NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr); // Get the values out of the arrays! ns = nsArr[0]; simplePattern = simplePatternArr[0]; if (ns != null) { // we successfully found the pattern's ns specificNsInPattern = (simplePattern.CompareTo(pattern) != 0); } } else { throw new TclNumArgsException(interp, 2, objv, "?pattern?"); } // If the namespace specified in the pattern wasn't found, just return. if (ns == null) { return; } list = TclList.newInstance(); if ((interp.varFrame == null) || !interp.varFrame.isProcCallFrame || specificNsInPattern) { // There is no frame pointer, the frame pointer was pushed only // to activate a namespace, or we are in a procedure call frame // but a specific namespace was specified. Create a list containing // only the variables in the effective namespace's variable table. search = ns.varTable.GetEnumerator(); while (search.MoveNext()) { varName = ((string)search.Key); var = (Var)search.Value; if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0)) { if (((System.Object)simplePattern == null) || Util.stringMatch(varName, simplePattern)) { if (specificNsInPattern) { elemObj = TclString.newInstance(Var.getVariableFullName(interp, var)); } else { elemObj = TclString.newInstance(varName); } TclList.append(interp, list, elemObj); } } } // If the effective namespace isn't the global :: namespace, and a // specific namespace wasn't requested in the pattern (i.e., the // pattern only specifies variable names), then add in all global :: // variables that match the simple pattern. Of course, add in only // those variables that aren't hidden by a variable in the effective // namespace. if ((ns != globalNs) && !specificNsInPattern) { search = globalNs.varTable.GetEnumerator(); while (search.MoveNext()) { varName = ((string)search.Key); var = (Var)search.Value; if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0)) { if (((System.Object)simplePattern == null) || Util.stringMatch(varName, simplePattern)) { // Skip vars defined in current namespace if (ns.varTable[varName] == null) { TclList.append(interp, list, TclString.newInstance(varName)); } } } } } } else { AppendLocals(interp, list, simplePattern, true); } interp.setResult(list); return; }
/// <summary> Called when the command is deleted from the interp.</summary> public void disposeCmd() { NamespaceCmd.deleteImportedCmd(this); }
/// <summary> Called when the command is invoked in the interp.</summary> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv) { NamespaceCmd.invokeImportedCmd(interp, this, objv); return(TCL.CompletionCode.RETURN); }
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> /// Called when the command is deleted from the interp. /// </summary> public void Dispose() { NamespaceCmd.DeleteImportedCmd(this); }