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 init(Interp interp) // Current interpreter. { interp.createCommand("regexp", new tcl.lang.RegexpCmd()); interp.createCommand("regsub", new tcl.lang.RegsubCmd()); }
/// <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 ) ); }
/// <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; Command cmd; try { cmdClass = System.Type.GetType( className, true ); } catch ( System.Exception e ) { throw new TclException( interp, "ClassNotFoundException for class \"" + className + "\"" ); } try { cmd = (Command)SupportClass.CreateNewInstance( cmdClass ); } catch ( System.UnauthorizedAccessException e1 ) { throw new TclException( interp, "IllegalAccessException for class \"" + cmdClass.FullName + "\"" ); } catch ( System.InvalidCastException e3 ) { throw new TclException( interp, "ClassCastException for class \"" + cmdClass.FullName + "\"" ); } catch ( System.Exception e2 ) { 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; }
/* *---------------------------------------------------------------------- * * Tcl_Import -> importList * * Imports all of the commands matching a pattern into the namespace * specified by namespace (or the current namespace if namespace * is null). This is done by creating a new command (the "imported * command") that points to the real command in its original namespace. * * If matching commands are on the autoload path but haven't been * loaded yet, this command forces them to be loaded, then creates * the links to them. * * Results: * Returns if successful, raises TclException if something goes wrong. * * Side effects: * Creates new commands in the importing namespace. These indirect * calls back to the real command and are deleted if the real commands * are deleted. * *---------------------------------------------------------------------- */ internal static void importList(Interp interp, Namespace namespace_Renamed, string pattern, bool allowOverwrite) { Namespace ns, importNs; Namespace currNs = getCurrentNamespace(interp); string simplePattern, cmdName; IEnumerator search; WrappedCommand cmd, realCmd; ImportRef ref_Renamed; WrappedCommand autoCmd, importedCmd; ImportedCmdData data; bool wasExported; int i, result; // If the specified namespace is null, use the current namespace. if (namespace_Renamed == null) { ns = currNs; } else { ns = namespace_Renamed; } // First, invoke the "auto_import" command with the pattern // being imported. This command is part of the Tcl library. // It looks for imported commands in autoloaded libraries and // loads them in. That way, they will be found when we try // to create links below. autoCmd = findCommand(interp, "auto_import", null, TCL.VarFlag.GLOBAL_ONLY); if (autoCmd != null) { TclObject[] objv = new TclObject[2]; objv[0] = TclString.newInstance("auto_import"); objv[0].preserve(); objv[1] = TclString.newInstance(pattern); objv[1].preserve(); cmd = autoCmd; try { // Invoke the command with the arguments cmd.cmd.cmdProc(interp, objv); } finally { objv[0].release(); objv[1].release(); } interp.resetResult(); } // From the pattern, find the namespace from which we are importing // and get the simple pattern (no namespace qualifiers or ::'s) at // the end. if (pattern.Length == 0) { throw new TclException(interp, "empty import pattern"); } // Java does not support passing an address so we pass // an array of size 1 and then assign arr[0] to the value Namespace[] importNsArr = new Namespace[1]; Namespace[] dummyArr = new Namespace[1]; string[] simplePatternArr = new string[1]; getNamespaceForQualName(interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, importNsArr, dummyArr, dummyArr, simplePatternArr); importNs = importNsArr[0]; simplePattern = simplePatternArr[0]; if (importNs == null) { throw new TclException(interp, "unknown namespace in import pattern \"" + pattern + "\""); } if (importNs == ns) { if ((System.Object) pattern == (System.Object) simplePattern) { throw new TclException(interp, "no namespace specified in import pattern \"" + pattern + "\""); } else { throw new TclException(interp, "import pattern \"" + pattern + "\" tries to import from namespace \"" + importNs.name + "\" into itself"); } } // Scan through the command table in the source namespace and look for // exported commands that match the string pattern. Create an "imported // command" in the current namespace for each imported command; these // commands redirect their invocations to the "real" command. for (search = importNs.cmdTable.Keys.GetEnumerator(); search.MoveNext(); ) { cmdName = ((string) search.Current); if (Util.stringMatch(cmdName, simplePattern)) { // The command cmdName in the source namespace matches the // pattern. Check whether it was exported. If it wasn't, // we ignore it. wasExported = false; for (i = 0; i < importNs.numExportPatterns; i++) { if (Util.stringMatch(cmdName, importNs.exportArray[i])) { wasExported = true; break; } } if (!wasExported) { continue; } // Unless there is a name clash, create an imported command // in the current namespace that refers to cmdPtr. if ((ns.cmdTable[cmdName] == null) || allowOverwrite) { // Create the imported command and its client data. // To create the new command in the current namespace, // generate a fully qualified name for it. System.Text.StringBuilder ds; ds = new System.Text.StringBuilder(); ds.Append(ns.fullName); if (ns != interp.globalNs) { ds.Append("::"); } ds.Append(cmdName); // Check whether creating the new imported command in the // current namespace would create a cycle of imported->real // command references that also would destroy an existing // "real" command already in the current namespace. cmd = (WrappedCommand) importNs.cmdTable[cmdName]; if (cmd.cmd is ImportedCmdData) { // This is actually an imported command, find // the real command it references realCmd = getOriginalCommand(cmd); if ((realCmd != null) && (realCmd.ns == currNs) && (currNs.cmdTable[cmdName] != null)) { throw new TclException(interp, "import pattern \"" + pattern + "\" would create a loop containing command \"" + ds.ToString() + "\""); } } data = new ImportedCmdData(); // Create the imported command inside the interp interp.createCommand(ds.ToString(), data); // Lookup in the namespace for the new WrappedCommand importedCmd = findCommand(interp, ds.ToString(), ns, (TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.LEAVE_ERR_MSG)); data.realCmd = cmd; data.self = importedCmd; // Create an ImportRef structure describing this new import // command and add it to the import ref list in the "real" // command. ref_Renamed = new ImportRef(); ref_Renamed.importedCmd = importedCmd; ref_Renamed.next = cmd.importRef; cmd.importRef = ref_Renamed; } else { throw new TclException(interp, "can't import command \"" + cmdName + "\": already exists"); } } } 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; System.Text.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 System.Text.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; }