/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"source ?options? fileName\""; return(ReturnCode.Error); } ReturnCode code = ReturnCode.Ok; OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.MustHaveEncodingValue, Index.Invalid, Index.Invalid, "-encoding", null), new Option(null, OptionFlags.MustHaveBooleanValue, Index.Invalid, Index.Invalid, "-withinfo", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { if (interpreter.GetOptions( options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } } else { argumentIndex = 1; } if ((argumentIndex == Index.Invalid) || ((argumentIndex + 1) != arguments.Count)) { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption( options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"source ?options? fileName\""; } return(ReturnCode.Error); } Variant value = null; Encoding encoding = null; if (options.IsPresent("-encoding", ref value)) { encoding = (Encoding)value.Value; } bool withInfo = false; if (options.IsPresent("-withinfo", ref value)) { withInfo = (bool)value.Value; } if (code == ReturnCode.Ok) { string name = StringList.MakeList( "source", arguments[argumentIndex]); ICallFrame frame = interpreter.NewTrackingCallFrame( name, CallFrameFlags.Source); interpreter.PushAutomaticCallFrame(frame); try { #if ARGUMENT_CACHE CacheFlags savedCacheFlags = CacheFlags.None; if (withInfo) { interpreter.BeginNoArgumentCache( ref savedCacheFlags); } try { #endif #if DEBUGGER && BREAKPOINTS InterpreterFlags savedInterpreterFlags = InterpreterFlags.None; if (withInfo) { interpreter.BeginArgumentLocation( ref savedInterpreterFlags); } try { #endif code = interpreter.EvaluateFile( encoding, arguments[argumentIndex], ref result); #if DEBUGGER && BREAKPOINTS } finally { if (withInfo) { interpreter.EndArgumentLocation( ref savedInterpreterFlags); } } #endif #if ARGUMENT_CACHE } finally { if (withInfo) { interpreter.EndNoArgumentCache( ref savedCacheFlags); } } #endif } finally { // // NOTE: Pop the original call frame that we pushed above // and any intervening scope call frames that may be // leftover (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } return(code); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nobackslashes", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nocommands", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-novariables", null) /*, * new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) */ }); int argumentIndex = Index.Invalid; code = interpreter.GetOptions(options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result); if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { SubstitutionFlags substitutionFlags = SubstitutionFlags.Default; if (options.IsPresent("-nobackslashes")) { substitutionFlags &= ~SubstitutionFlags.Backslashes; } if (options.IsPresent("-nocommands")) { substitutionFlags &= ~SubstitutionFlags.Commands; } if (options.IsPresent("-novariables")) { substitutionFlags &= ~SubstitutionFlags.Variables; } string name = StringList.MakeList("subst"); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Substitute); interpreter.PushAutomaticCallFrame(frame); code = interpreter.SubstituteString( arguments[argumentIndex], substitutionFlags, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"subst\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"subst ?-nobackslashes? ?-nocommands? ?-novariables? string\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"subst ?-nobackslashes? ?-nocommands? ?-novariables? string\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (targetInterpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } ReturnCode code; string targetName = null; ArgumentList targetArguments = null; code = targetInterpreter.GetAliasArguments( this, arguments, ref targetName, ref targetArguments, ref result); if (code == ReturnCode.Ok) { // // NOTE: Grab the target of the alias (this will be null if we // are late-bound). // IExecute target = null; bool useUnknown = false; code = targetInterpreter.GetAliasTarget(this, targetName, targetArguments, LookupFlags.Default, true, ref target, ref useUnknown, ref result); // // NOTE: Do we have a valid target now (we may have already had // one or we may have just succeeded in looking it up)? // if (code == ReturnCode.Ok) { // // NOTE: Create and push a new call frame to track the // activation of this alias. // string name = StringList.MakeList("alias", this.Name); AliasFlags aliasFlags = this.AliasFlags; ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Alias); interpreter.PushAutomaticCallFrame(frame); /////////////////////////////////////////////////////////// bool targetUsable; if (useUnknown) { targetInterpreter.EnterUnknownLevel(); } try { if (FlagOps.HasFlags( aliasFlags, AliasFlags.Evaluate, true)) { code = targetInterpreter.EvaluateScript( targetArguments, 0, ref result); } else { // // NOTE: Save the current engine flags and then // enable the external execution flags. // EngineFlags savedEngineFlags = targetInterpreter.BeginExternalExecution(); code = targetInterpreter.Execute( targetName, target, clientData, targetArguments, ref result); // // NOTE: Restore the saved engine flags, masking // off the external execution flags as // necessary. // /* IGNORED */ targetInterpreter.EndAndCleanupExternalExecution( savedEngineFlags); } } finally { targetUsable = Engine.IsUsable(targetInterpreter); if (useUnknown && targetUsable) { targetInterpreter.ExitUnknownLevel(); } } /////////////////////////////////////////////////////////// // // NOTE: Pop the original call frame that we pushed above // and any intervening scope call frames that may be // leftover (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } return(code); }
private void DoShowLocals() { ICallFrame[] frames; frames = dbg.GetCallFrames(); int stackItems; if (frames.Length == 0) { io.PutString("No call frame.\n"); stackItems = dbg.StackDepth; } else { ICallFrame cf = frames[0]; if (cf.Locals.Length == 0) { io.PutString("No local variables.\n"); } else { io.PutString(string.Format("{0} local variable{1}:\n", cf.Locals.Length, cf.Locals.Length == 1 ? "" : "s")); var rtn = zm.DebugInfo != null?zm.DebugInfo.FindRoutine(dbg.CurrentPC) : null; for (int i = 0; i < cf.Locals.Length; i++) { io.PutString(" "); if (rtn != null && i < rtn.Locals.Length) { io.PutString(rtn.Locals[i]); } else { io.PutString(string.Format("local_{0}", i + 1)); } io.PutString(string.Format(" = {0} (${0:x4})\n", cf.Locals[i])); } } stackItems = dbg.StackDepth - cf.PrevStackDepth; } if (stackItems == 0) { io.PutString("No data on stack.\n"); } else { io.PutString(string.Format("{0} word{1} on stack:\n", stackItems, stackItems == 1 ? "" : "s")); Stack <short> temp = new Stack <short>(); for (int i = 0; i < stackItems; i++) { short value = dbg.StackPop(); temp.Push(value); io.PutString(string.Format(" ${0:x4} (${0})\n", value)); } while (temp.Count > 0) { dbg.StackPush(temp.Pop()); } } }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { string name = StringList.MakeList("eval"); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Evaluate); interpreter.PushAutomaticCallFrame(frame); if (arguments.Count == 2) { code = interpreter.EvaluateScript(arguments[1], ref result); } else { code = interpreter.EvaluateScript(arguments, 1, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"eval\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } else { result = "wrong # args: should be \"eval arg ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 3) { ICallFrame otherFrame = null; FrameResult frameResult = interpreter.GetCallFrame( arguments[1], ref otherFrame, ref result); if (frameResult != FrameResult.Invalid) { int count = arguments.Count - ((int)frameResult + 1); if ((count & 1) == 0) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { ICallFrame localFrame = null; code = interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result); if (code == ReturnCode.Ok) { int argumentIndex = ((int)frameResult + 1); // skip "upvar ?level?" for (; count > 0; count -= 2, argumentIndex += 2) { string otherName = arguments[argumentIndex]; string localName = arguments[argumentIndex + 1]; code = ScriptOps.LinkVariable( interpreter, localFrame, localName, otherFrame, otherName, ref result); if (code != ReturnCode.Ok) { break; } } } } } else { result = "wrong # args: should be \"upvar ?level? otherVar localVar ?otherVar localVar ...?\""; code = ReturnCode.Error; } } else { code = ReturnCode.Error; } } else { result = "wrong # args: should be \"upvar ?level? otherVar localVar ?otherVar localVar ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if ((arguments.Count < 2) || (arguments.Count > 4)) { result = ScriptOps.WrongNumberOfArguments(this, 1, arguments, "script ?resultVarName? ?optionsVarName?"); return(ReturnCode.Error); } string name = StringList.MakeList(this.Name); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Catch); interpreter.PushAutomaticCallFrame(frame); EngineFlags engineFlags = interpreter.EngineFlags; if (Engine.HasNoResetError(engineFlags)) { engineFlags |= EngineFlags.ErrorAlreadyLogged; } ReturnCode code; Result localResult = null; int errorLine = 0; /* IGNORED */ interpreter.EnterCatchLevel(); try { code = interpreter.EvaluateScript( arguments[1], engineFlags, ref localResult, ref errorLine); } finally { if (interpreter.ExitCatchLevel() == 0) { if (ScriptOps.HasFlags(interpreter, InterpreterFlags.CatchResetCancel, true)) { ReturnCode resetCode; Result resetError = null; resetCode = Engine.ResetCancel( interpreter, CancelFlags.CatchBlock, ref resetError); if (resetCode != ReturnCode.Ok) { DebugOps.Complain( interpreter, resetCode, resetError); } } if (ScriptOps.HasFlags(interpreter, InterpreterFlags.CatchResetExit, true)) { bool exit = interpreter.Exit; if (exit) { interpreter.Exit = false; } } } } // // BUGFIX: Prevent messing up the custom errorInfo from the [error] // command by checking to see if the "error already logged" // flag has been set. // engineFlags = interpreter.EngineFlags; if ((code == ReturnCode.Error) && !Engine.HasErrorAlreadyLogged(engineFlags) && !Engine.HasNoResetError(engineFlags)) { Engine.AddErrorInformation(interpreter, localResult, String.Format("{0} (\"catch\" body line {1})", Environment.NewLine, errorLine)); } // // NOTE: Pop the original call frame that we pushed above and any // intervening scope call frames that may be leftover (i.e. // they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); // // NOTE: The result of this command is the integer conversion of // the return code received from the evaluated script. // Engine.ResetResult(interpreter, ref result); result = ConversionOps.ToInt(code); result.ReturnCode = code; /* NOTE: For ease of use. */ // // NOTE: See if the caller wants to save the result and/or error // message in a variable. // if (arguments.Count >= 3) { Result error = null; code = interpreter.SetVariableValue( VariableFlags.NoReady, arguments[2], localResult, null, ref error); if (code != ReturnCode.Ok) { Engine.ResetResult(interpreter, ref result); result = String.Format( "couldn't save command result in variable: {0}", error); return(code); } } // // NOTE: See if the caller wants to save the "return options" in a // variable. // if (arguments.Count >= 4) { StringList list = new StringList(); Result error = null; if (result.ReturnCode == ReturnCode.Return) { int level = 0; code = interpreter.GetInfoLevel( null, ref level, ref error); if (code != ReturnCode.Ok) { Engine.ResetResult(interpreter, ref error); result = String.Format( "couldn't get current level: {0}", error); return(code); } list.Add("-code", ((int)interpreter.ReturnCode).ToString()); list.Add("-level", level.ToString()); } else { list.Add("-code", result.String); list.Add("-level", Value.ZeroString); } if (result.ReturnCode == ReturnCode.Error) { Result errorCode = null; Result errorInfo = null; ResultList errors = null; code = interpreter.CopyErrorInformation( VariableFlags.None, true, ref errorCode, ref errorInfo, ref errors); if (code != ReturnCode.Ok) { Engine.ResetResult(interpreter, ref result); result = errors; return(code); } list.Add("-errorcode", errorCode); list.Add("-errorinfo", errorInfo); list.Add("-errorline", errorLine.ToString()); } code = interpreter.SetVariableValue( VariableFlags.NoReady, arguments[3], list.ToString(), null, ref error); if (code != ReturnCode.Ok) { Engine.ResetResult(interpreter, ref result); result = String.Format( "couldn't save return options in variable: {0}", error); return(code); } } // // NOTE: We are "catching" (masking) the error; therefore, do not // propogate it. // return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"global varName ?varName ...?\""; return(ReturnCode.Error); } ICallFrame localFrame = null; if (interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result) == ReturnCode.Ok) { if ((localFrame != null) && !interpreter.IsGlobalCallFrame(localFrame)) { bool useNamespaces = interpreter.AreNamespacesEnabled(); for (int argumentIndex = 1; argumentIndex < arguments.Count; argumentIndex++) { string varName = arguments[argumentIndex]; ICallFrame otherFrame = interpreter.CurrentGlobalFrame; if (useNamespaces) { string qualifiers = null; string tail = null; NamespaceFlags namespaceFlags = NamespaceFlags.None; if (NamespaceOps.SplitName( varName, ref qualifiers, ref tail, ref namespaceFlags, ref result) == ReturnCode.Ok) { // // NOTE: For linking between call frames, use // the simple variable name only. // varName = tail; } else { return(ReturnCode.Error); } if (FlagOps.HasFlags(namespaceFlags, NamespaceFlags.Qualified, true)) { INamespace @namespace = NamespaceOps.Lookup( interpreter, qualifiers, false, false, ref result); if (@namespace != null) { otherFrame = @namespace.VariableFrame; } else { return(ReturnCode.Error); } } } if (ScriptOps.LinkVariable( interpreter, localFrame, varName, otherFrame, varName, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } } result = String.Empty; } else { // already in global scope... this is a NOP. result = String.Empty; } return(ReturnCode.Ok); } else { return(ReturnCode.Error); } }
/////////////////////////////////////////////////////////////////////// private /* protected virtual */ void Dispose( bool disposing ) { if (!disposed) { if (disposing) { //////////////////////////////////// // dispose managed resources here... //////////////////////////////////// if (children != null) { foreach (INamespace child in children.Values) { if (child == null) { continue; } IDisposable disposable = child as IDisposable; if (disposable != null) { disposable.Dispose(); disposable = null; } } children.Clear(); children = null; } /////////////////////////////////////////////////////////// if (exportNames != null) { exportNames.Clear(); exportNames = null; } /////////////////////////////////////////////////////////// if (imports != null) { ReturnCode removeCode; Result removeError = null; removeCode = RemoveImports( null, false, ref removeError); if (removeCode != ReturnCode.Ok) { DebugOps.Complain( interpreter, removeCode, removeError); } imports.Clear(); imports = null; } /////////////////////////////////////////////////////////// if (interpreter != null) { interpreter = null; /* NOT OWNED */ } /////////////////////////////////////////////////////////// parent = null; /* NOT OWNED */ resolve = null; /* NOT OWNED */ /////////////////////////////////////////////////////////// if (variableFrame != null) { variableFrame.Free(true); variableFrame = null; } /////////////////////////////////////////////////////////// unknown = null; /////////////////////////////////////////////////////////// qualifiedName = null; referenceCount = 0; deleted = false; /////////////////////////////////////////////////////////// kind = IdentifierKind.None; id = Guid.Empty; name = null; group = null; description = null; clientData = null; } ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = String.Format( "wrong # args: should be \"{0} option ?arg ...?\"", this.Name); return(ReturnCode.Error); } string subCommand = arguments[1]; if (!String.Equals( subCommand, this.Name, StringOps.SystemStringComparisonType)) { result = ScriptOps.BadSubCommand( interpreter, null, null, subCommand, this, null, null); return(ReturnCode.Error); } // // NOTE: Evaluate the configured script command, maybe // adding all the local arguments, and return the // results verbatim. // string name = StringList.MakeList(this.Name); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Evaluate | CallFrameFlags.SubCommand); interpreter.PushAutomaticCallFrame(frame); ReturnCode code = interpreter.EvaluateScript( ScriptOps.GetArgumentsForExecute(this, scriptCommand, GetArgumentsForExecute(arguments), 0), 0, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"{1}\" body line {2})", Environment.NewLine, ScriptOps.GetNameForExecute( arguments[0], this), Interpreter.GetErrorLine( interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; // // NOTE: *WARNING* We do NOT actually support namespaces. This // command exists for the sole purpose of improving source // code compatibility with simple stand alone scripts that // may simply wrap themselves in a "namespace eval" block, // etc. Any other (more involved) use may not work at all // or may cause undesired and/or unpredictable results. // if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { string subCommand = arguments[1]; bool tried = false; code = ScriptOps.TryExecuteSubCommandFromEnsemble( interpreter, this, clientData, arguments, true, false, ref subCommand, ref tried, ref result); if ((code == ReturnCode.Ok) && !tried) { switch (subCommand) { case "children": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { string name = null; if (arguments.Count >= 3) { name = arguments[2]; } if ((arguments.Count < 3) || NamespaceOps.IsGlobalName(name)) { result = String.Empty; code = ReturnCode.Ok; } else { if (NamespaceOps.IsAbsoluteName(name)) { result = String.Format("namespace \"{0}\" not found", name); } else { result = String.Format("namespace \"{0}\" not found in \"{1}\"", name, TclVars.GlobalNamespace); } code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace children ?name? ?pattern?\""; code = ReturnCode.Error; } break; } case "code": { if (arguments.Count == 3) { // // NOTE: We are always in the global namespace, fake it. // result = new StringList( TclVars.GlobalNamespace + this.Name, "inscope", TclVars.GlobalNamespace, arguments[2]); code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace code script\""; code = ReturnCode.Error; } break; } case "current": { if (arguments.Count == 2) { result = TclVars.GlobalNamespace; code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace current\""; code = ReturnCode.Error; } break; } case "delete": { if (arguments.Count >= 2) { code = ReturnCode.Ok; for (int index = 2; index < arguments.Count; index++) { if (!NamespaceOps.IsGlobalName(arguments[index])) { // // NOTE: We only know about the global namespace; an attempt // to delete any other namespace is an error. // result = String.Format( "unknown namespace \"{0}\" in namespace delete command", arguments[index]); code = ReturnCode.Error; break; } } if (code == ReturnCode.Ok) { for (int index = 2; index < arguments.Count; /* index++ */) { // // NOTE: Delete the one-and-only namespace (global) now (actually, // as soon as the evaluation stack unwinds). // code = interpreter.DeleteNamespace( VariableFlags.None, arguments[index], false, ref result); // // NOTE: Since we only know about the global namespace there // is no point in attempting to delete it multiple times. // break; } } if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace delete ?name name ...?\""; code = ReturnCode.Error; } break; } case "enable": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { if (arguments.Count >= 3) { bool enabled = false; code = Value.GetBoolean2( arguments[2], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref enabled, ref result); bool force = false; if ((code == ReturnCode.Ok) && (arguments.Count >= 4)) { code = Value.GetBoolean2( arguments[3], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref force, ref result); } if (code == ReturnCode.Ok) { code = NamespaceOps.Enable( interpreter, enabled, force, ref result); } } if (code == ReturnCode.Ok) { result = interpreter.AreNamespacesEnabled(); } } else { result = "wrong # args: should be \"namespace enable ?enabled? ?force?\""; code = ReturnCode.Error; } break; } case "eval": { if (arguments.Count >= 4) { string name = StringList.MakeList("namespace eval", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.Evaluate); interpreter.PushAutomaticCallFrame(frame); if (arguments.Count == 4) { code = interpreter.EvaluateScript(arguments[3], ref result); } else { code = interpreter.EvaluateScript(arguments, 3, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace eval \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } else { result = "wrong # args: should be \"namespace eval name arg ?arg ...?\""; code = ReturnCode.Error; } break; } case "exists": { if (arguments.Count == 3) { if (NamespaceOps.IsGlobalName(arguments[2])) { result = true; } else { result = false; } code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace exists name\""; code = ReturnCode.Error; } break; } case "export": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-clear", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace export ?-clear? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "forget": { if (arguments.Count >= 2) { // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // result = String.Empty; code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace forget ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "import": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } // // NOTE: We do not support importing or exporting of namespace commands // because we do not really support namespaces; therefore, we do // nothing. // if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace import ?-force? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "info": { if (arguments.Count == 3) { code = NamespaceOps.InfoSubCommand( interpreter, arguments[2], ref result); } else { result = "wrong # args: should be \"namespace info name\""; code = ReturnCode.Error; } break; } case "inscope": { if (arguments.Count >= 4) { if (NamespaceOps.IsGlobalName(arguments[2])) { if (arguments.Count > 4) { IScriptLocation location = null; #if DEBUGGER && BREAKPOINTS code = ScriptOps.GetLocation( interpreter, arguments, 3, ref location, ref result); if (code == ReturnCode.Ok) #endif { string name = StringList.MakeList("namespace inscope", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.InScope); interpreter.PushAutomaticCallFrame(frame); StringList list = new StringList(arguments, 4); code = interpreter.EvaluateScript( ListOps.Concat(arguments[3], list.ToString()), location, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } else { string name = StringList.MakeList("namespace inscope", arguments[2]); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Namespace | CallFrameFlags.InScope); interpreter.PushAutomaticCallFrame(frame); code = interpreter.EvaluateScript(arguments[3], ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, arguments[2], Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } else { result = String.Format( "unknown namespace \"{0}\" in inscope namespace command", arguments[2]); code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace inscope name arg ?arg...?\""; code = ReturnCode.Error; } break; } case "mappings": { if (arguments.Count == 2) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { StringDictionary namespaceMappings = interpreter.NamespaceMappings; if (namespaceMappings != null) { result = namespaceMappings.KeysAndValuesToString(null, false); code = ReturnCode.Ok; } else { result = "namespace mappings not available"; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace mappings\""; code = ReturnCode.Error; } break; } case "name": { if (arguments.Count == 3) { // // NOTE: We are always in the global namespace, fake it. // string name = arguments[2]; if (!NamespaceOps.IsQualifiedName(name)) { result = NamespaceOps.MakeAbsoluteName(name); code = ReturnCode.Ok; } else { result = "only non-qualified names are allowed"; code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace name name\""; code = ReturnCode.Error; } break; } case "origin": { if (arguments.Count == 3) { string executeName = arguments[2]; IExecute execute = null; code = interpreter.GetIExecuteViaResolvers( interpreter.GetResolveEngineFlags(true), executeName, null, LookupFlags.Default, ref execute, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + executeName; } } else { result = "wrong # args: should be \"namespace origin name\""; code = ReturnCode.Error; } break; } case "parent": { if ((arguments.Count == 2) || (arguments.Count == 3)) { // // NOTE: Either they did not specify a namespace argument (use current // namespace, which is always global and always exists) or they // specified a namespace which should be the global one; otherwise, // an error is reported because we do not really support namespaces. // if ((arguments.Count == 2) || NamespaceOps.IsGlobalName(arguments[2])) { result = String.Empty; code = ReturnCode.Ok; } else { // // NOTE: See if they prefixed the argument with "::" to figure out // the appropriate error message (Tcl emulation). // if (NamespaceOps.IsAbsoluteName(arguments[2])) { result = String.Format("namespace \"{0}\" not found", arguments[2]); } else { result = String.Format("namespace \"{0}\" not found in \"{1}\"", arguments[2], TclVars.GlobalNamespace); } code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace parent ?name?\""; code = ReturnCode.Error; } break; } case "qualifiers": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = qualifiers; } } else { result = "wrong # args: should be \"namespace qualifiers string\""; code = ReturnCode.Error; } break; } case "rename": { if (arguments.Count == 4) { result = "not implemented"; code = ReturnCode.Error; } else { result = "wrong # args: should be \"namespace rename oldName newName\""; code = ReturnCode.Error; } break; } case "tail": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = tail; } } else { result = "wrong # args: should be \"namespace tail string\""; code = ReturnCode.Error; } break; } case "unknown": { // // NOTE: The string is currently used as the name of the command // or procedure to execute when an unknown command is // encountered by the engine. // if ((arguments.Count == 2) || (arguments.Count == 3)) { if (arguments.Count == 3) { string unknown = StringOps.NullIfEmpty(arguments[2]); if (String.IsNullOrEmpty(unknown)) { interpreter.NamespaceUnknown = interpreter.GlobalUnknown; } else { interpreter.NamespaceUnknown = unknown; } result = unknown; } else { result = interpreter.NamespaceUnknown; } code = ReturnCode.Ok; } else { result = "wrong # args: should be \"namespace unknown ?script?\""; code = ReturnCode.Error; } break; } case "which": { // // TODO: *FIXME* Only the global namespace is supported here. // if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-command", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-variable", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, OptionBehaviorFlags.LastIsNonOption, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { string name = arguments[argumentIndex]; bool isCommand = false; if (options.IsPresent("-command")) { isCommand = true; } bool isVariable = false; if (options.IsPresent("-variable")) { isVariable = true; } if (!isCommand || !isVariable) { if (!isCommand && !isVariable) { isCommand = true; } if (isCommand) { IExecute execute = null; code = interpreter.GetIExecuteViaResolvers( interpreter.GetResolveEngineFlags(true), name, null, LookupFlags.Default, ref execute, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + ScriptOps.MakeCommandName(name); } else { result = String.Empty; code = ReturnCode.Ok; } } else { VariableFlags flags = VariableFlags.NamespaceWhichMask; IVariable variable = null; code = interpreter.GetVariableViaResolversWithSplit( name, ref flags, ref variable, ref result); if (code == ReturnCode.Ok) { result = TclVars.GlobalNamespace + ScriptOps.MakeVariableName(name); } else { result = String.Empty; code = ReturnCode.Ok; } } } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; /* COMPAT: Tcl */ code = ReturnCode.Error; } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; code = ReturnCode.Error; } break; } default: { result = ScriptOps.BadSubCommand( interpreter, null, null, subCommand, this, null, null); code = ReturnCode.Error; break; } } } } else { result = "wrong # args: should be \"namespace subcommand ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"variable ?name value...? name ?value?\""; return(ReturnCode.Error); } ICallFrame localFrame = null; if (interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } if (localFrame == null) { result = "local call frame is invalid"; return(ReturnCode.Error); } if (!localFrame.IsVariable) { result = "local call frame does not support variables"; return(ReturnCode.Error); } bool useNamespaces = interpreter.AreNamespacesEnabled(); INamespace currentNamespace = null; if (useNamespaces && interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } ICallFrame otherFrame = null; if ((currentNamespace != null) && !interpreter.IsGlobalNamespace(currentNamespace)) { otherFrame = currentNamespace.VariableFrame; } else { otherFrame = interpreter.CurrentGlobalFrame; } for (int argumentIndex = 1; argumentIndex < arguments.Count; argumentIndex += 2) { string varName = arguments[argumentIndex]; lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { VariableFlags flags = VariableFlags.NoElement; if (!useNamespaces) { flags |= VariableFlags.GlobalOnly; } IVariable otherVariable = null; Result error = null; if (interpreter.GetVariableViaResolversWithSplit( varName, ref flags, ref otherVariable, ref error) != ReturnCode.Ok) { if (FlagOps.HasFlags( flags, VariableFlags.NotFound, true)) { error = null; if (interpreter.AddVariable2( VariableFlags.Undefined | flags, varName, null, true, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } else { // // NOTE: We did not search for the variable, let // the caller know why. // result = error; return(ReturnCode.Error); } } // // NOTE: Create the variable link between the local frame // (i.e. a procedure, etc) and the other frame (i.e. // namespace or global). // if (CallFrameOps.IsLocal(localFrame)) { error = null; if (ScriptOps.LinkVariable( interpreter, localFrame, varName, otherFrame, varName, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } // // NOTE: If they provided a value, set it now. // // BUGFIX: This must be done after setting up the link // and not before; otherwise, the LinkVariable // method will detect a defined variable with // the same name in the local call frame and // refuse to overwrite it (by design). // if ((argumentIndex + 1) < arguments.Count) { error = null; if (interpreter.SetVariableValue2( VariableFlags.None, otherFrame, varName, null, arguments[argumentIndex + 1].Value, null, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } } } result = String.Empty; return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { IScriptLocation location = null; code = ScriptOps.GetAndCheckProcedureLocation( interpreter, this, ref location, ref result); if (code == ReturnCode.Ok) { string procedureName = this.Name; ArgumentList procedureArguments = this.Arguments; if (procedureArguments != null) { bool hasArgs = procedureArguments.IsVariadic(true); int totalArgs = hasArgs ? procedureArguments.Count - 1 : procedureArguments.Count; int optionalArgs = procedureArguments.GetOptionalCount(); if ((arguments.Count > 0) && ((((arguments.Count - 1) >= (totalArgs - optionalArgs)) && ((arguments.Count - 1) <= totalArgs)) || (hasArgs && ((arguments.Count - 1) >= (totalArgs - optionalArgs))))) { ICallFrame frame = null; try { frame = interpreter.NewProcedureCallFrame( procedureName, CallFrameFlags.Procedure, null, this, arguments); VariableDictionary variables = frame.Variables; frame.ProcedureArguments = new ArgumentList(arguments[0]); for (int argumentIndex = 0; argumentIndex < procedureArguments.Count; argumentIndex++) { string varName = procedureArguments[argumentIndex].Name; if (!variables.ContainsKey(varName)) { ArgumentFlags flags = ArgumentFlags.None; object varValue; if (hasArgs && (argumentIndex == (procedureArguments.Count - 1))) { // // NOTE: This argument is part of an argument list. // flags |= ArgumentFlags.ArgumentList; // // NOTE: Build the list for the final formal argument value, // which consists of all the remaining argument values. // ArgumentList argsArguments = new ArgumentList(); for (int argsArgumentIndex = argumentIndex + 1; argsArgumentIndex < arguments.Count; argsArgumentIndex++) { // // NOTE: Sync up the argument name and flags for use when // debugging (below). // Argument argsArgument = Argument.GetOrCreate( interpreter, arguments[argsArgumentIndex].Flags | flags, String.Format("{0}{1}{2}", varName, Characters.Space, argsArguments.Count), arguments[argsArgumentIndex], interpreter.HasNoCacheArgument()); argsArguments.Add(argsArgument); } varValue = argsArguments; } else { if ((argumentIndex + 1) < arguments.Count) { // // NOTE: Sync up the argument name for use when // debugging (below) and use the value // supplied by the caller. // varValue = Argument.GetOrCreate(interpreter, arguments[argumentIndex + 1].Flags | flags, varName, arguments[argumentIndex + 1], interpreter.HasNoCacheArgument()); } else { // // NOTE: We cannot sync up the argument name here // because we are out-of-bounds on that list // and it cannot be extended (i.e. it would // break [info level]); therefore, we punt // on that for now. Use the default value // for this argument, if any; otherwise, use // an empty string. // object @default = procedureArguments[argumentIndex].Default; varValue = (@default != null) ? @default : Argument.NoValue; } } code = interpreter.SetVariableValue2(VariableFlags.Argument, frame, varName, varValue, ref result); if (code != ReturnCode.Ok) { break; } // // BUGFIX: Now, also keep track of this argument in the procedure // arguments list. Primarily because we do not want to // have to redo this logic later (i.e. for [scope]). // frame.ProcedureArguments.Add(Argument.GetOrCreate( interpreter, flags, varName, varValue, interpreter.HasNoCacheArgument())); } } // // NOTE: Make sure we succeeded in creating the call frame. // if (code == ReturnCode.Ok) { ICallFrame savedFrame = null; interpreter.PushProcedureCallFrame(frame, true, ref savedFrame); try { #if DEBUGGER && DEBUGGER_EXECUTE if (DebuggerOps.CanHitBreakpoints(interpreter, EngineFlags.None, BreakpointType.BeforeProcedureBody)) { code = interpreter.CheckBreakpoints( code, BreakpointType.BeforeProcedureBody, procedureName, null, null, this, null, clientData, arguments, ref result); } #endif if (code == ReturnCode.Ok) { bool locked = false; try { bool atomic = EntityOps.IsAtomic(this); if (atomic) { interpreter.InternalTryLock(ref locked); /* TRANSACTIONAL */ } if (!atomic || locked) { #if ARGUMENT_CACHE || PARSE_CACHE EngineFlags savedEngineFlags = EngineFlags.None; bool nonCaching = EntityOps.IsNonCaching(this); if (nonCaching) { interpreter.BeginProcedureBodyNoCaching( ref savedEngineFlags); } try { #endif string body = this.Body; interpreter.ReturnCode = ReturnCode.Ok; code = interpreter.EvaluateScript( body, location, ref result); #if ARGUMENT_CACHE || PARSE_CACHE } finally { if (nonCaching) { interpreter.EndProcedureBodyNoCaching( ref savedEngineFlags); } } #endif } else { result = "could not lock interpreter"; code = ReturnCode.Error; } } finally { interpreter.InternalExitLock(ref locked); /* TRANSACTIONAL */ } #if DEBUGGER && DEBUGGER_EXECUTE if (DebuggerOps.CanHitBreakpoints(interpreter, EngineFlags.None, BreakpointType.AfterProcedureBody)) { code = interpreter.CheckBreakpoints( code, BreakpointType.AfterProcedureBody, procedureName, null, null, this, null, clientData, arguments, ref result); } #endif // // BUGFIX: If an opaque object handle is being returned, add // a reference to it now. // if ((code == ReturnCode.Ok) || (code == ReturnCode.Return)) { code = interpreter.AddObjectReference( code, result, ObjectReferenceType.Return, ref result); } if (code == ReturnCode.Return) { code = Engine.UpdateReturnInformation(interpreter); } else if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (procedure \"{1}\" line {2})", Environment.NewLine, FormatOps.Ellipsis(procedureName), Interpreter.GetErrorLine(interpreter))); } } } finally { /* IGNORED */ interpreter.PopProcedureCallFrame(frame, ref savedFrame); } } } finally { if (frame != null) { IDisposable disposable = frame as IDisposable; if (disposable != null) { disposable.Dispose(); disposable = null; } frame = null; } } } else { if (procedureArguments.Count > 0) { result = String.Format( "wrong # args: should be \"{0} {1}\"", Parser.Quote(procedureName), procedureArguments.ToRawString(ToStringFlags.Decorated, Characters.Space.ToString())); } else { result = String.Format( "wrong # args: should be \"{0}\"", Parser.Quote(procedureName)); } code = ReturnCode.Error; } } else { result = "invalid procedure argument list"; code = ReturnCode.Error; } } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code = ReturnCode.Ok; if (interpreter != null) { if (arguments != null) { if ((arguments.Count == 5) || (arguments.Count == 6)) { /////////////////////////////////////////////////////////////////////////////////////////////// // // test name description ?constraints? body result // /////////////////////////////////////////////////////////////////////////////////////////////// string name = arguments[1]; #if DEBUGGER if (DebuggerOps.CanHitBreakpoints(interpreter, EngineFlags.None, BreakpointType.Test)) { code = interpreter.CheckBreakpoints( code, BreakpointType.Test, name, null, null, this, null, clientData, arguments, ref result); } if (code == ReturnCode.Ok) #endif { string description = arguments[2]; string constraints; string body; IScriptLocation bodyLocation; string expectedResult; if (arguments.Count == 6) { constraints = arguments[3]; body = arguments[4]; bodyLocation = arguments[4]; expectedResult = arguments[5]; } else { constraints = null; body = arguments[3]; bodyLocation = arguments[3]; expectedResult = arguments[4]; } ReturnCodeList returnCodes = new ReturnCodeList(new ReturnCode[] { ReturnCode.Ok, ReturnCode.Return }); MatchMode mode = StringOps.DefaultResultMatchMode; bool noCase = false; /////////////////////////////////////////////////////////////////////////////////////////////// int testLevels = interpreter.EnterTestLevel(); try { // // NOTE: Create a place to put all the output of the this command. // StringBuilder testData = StringOps.NewStringBuilder(); // // NOTE: Are we going to skip this test? // bool skip = false; bool fail = true; code = TestOps.CheckConstraints( interpreter, testLevels, name, constraints, false, false, testData, ref skip, ref fail, ref result); // // NOTE: Track the fact that we handled this test. // int[] testStatistics = null; if (code == ReturnCode.Ok) { testStatistics = interpreter.TestStatistics; if ((testStatistics != null) && (testLevels == 1) && skip) { Interlocked.Increment(ref testStatistics[ (int)TestInformationType.Total]); } } if ((code == ReturnCode.Ok) && !skip) { code = TestOps.RecordInformation( interpreter, TestInformationType.Counts, name, null, true, ref result); } // // NOTE: Check test constraints to see if we should run the test. // if ((code == ReturnCode.Ok) && !skip) { ReturnCode bodyCode = ReturnCode.Ok; Result bodyResult = null; // // NOTE: Only run the test body if the setup is successful. // if (body != null) { TestOps.AppendFormat( interpreter, testData, TestOutputType.Start, "---- {0} start", name); TestOps.AppendLine( interpreter, testData, TestOutputType.Start); int savedPreviousLevels = interpreter.BeginNestedExecution(); try { ICallFrame frame = interpreter.NewTrackingCallFrame( StringList.MakeList(this.Name, "body", name), CallFrameFlags.Test); interpreter.PushAutomaticCallFrame(frame); try { bodyCode = interpreter.EvaluateScript( body, bodyLocation, ref bodyResult); if ((bodyResult == null) && ScriptOps.HasFlags( interpreter, InterpreterFlags.TestNullIsEmpty, true)) { bodyResult = String.Empty; } if (bodyCode == ReturnCode.Error) { /* IGNORED */ interpreter.CopyErrorInformation( VariableFlags.None, ref bodyResult); } } finally { // // NOTE: Pop the original call frame that we pushed above // and any intervening scope call frames that may be // leftover (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } } catch (Exception e) { bodyResult = e; bodyCode = ReturnCode.Error; } finally { interpreter.EndNestedExecution(savedPreviousLevels); } } // // NOTE: Did we fail to match the return code? // bool codeFailure = !returnCodes.Contains(bodyCode); // // NOTE: Does the actual result match the expected result? // bool scriptFailure = false; ReturnCode scriptCode = ReturnCode.Ok; Result scriptResult = null; if (!codeFailure) { if (expectedResult != null) { scriptCode = TestOps.Match( interpreter, mode, bodyResult, expectedResult, noCase, null, TestOps.RegExOptions, false, ref scriptFailure, ref scriptResult); if (scriptCode == ReturnCode.Ok) { scriptFailure = !scriptFailure; } else { scriptFailure = true; } } } // // NOTE: If any of the important things failed, the test fails. // if (!(codeFailure || scriptFailure)) { // // PASS: Test ran with no errors and the results match // what we expected. // if ((testStatistics != null) && (testLevels == 1)) { Interlocked.Increment(ref testStatistics[ (int)TestInformationType.Passed]); Interlocked.Increment(ref testStatistics[ (int)TestInformationType.Total]); } TestOps.AppendFormat( interpreter, testData, TestOutputType.Pass, "++++ {0} PASSED", name); TestOps.AppendLine( interpreter, testData, TestOutputType.Pass); } else { // // FAIL: Test ran with errors or the result does not match // what we expected. // if ((testStatistics != null) && (testLevels == 1)) { if (fail) { Interlocked.Increment(ref testStatistics[ (int)TestInformationType.Failed]); Interlocked.Increment(ref testStatistics[ (int)TestInformationType.Total]); } } // // NOTE: Keep track of each test that fails. // if (testLevels == 1) { TestOps.RecordInformation( interpreter, TestInformationType.FailedNames, name, null, true); } TestOps.AppendLine( interpreter, testData, TestOutputType.Fail); TestOps.AppendFormat( interpreter, testData, TestOutputType.Fail, "==== {0} {1} {2}", name, description.Trim(), fail ? "FAILED" : "IGNORED"); TestOps.AppendLine( interpreter, testData, TestOutputType.Fail); if (body != null) { TestOps.AppendLine( interpreter, testData, TestOutputType.Body, "==== Contents of test case:"); TestOps.AppendLine( interpreter, testData, TestOutputType.Body, body); } if (scriptFailure) { if (scriptCode == ReturnCode.Ok) { TestOps.AppendLine( interpreter, testData, TestOutputType.Reason, "---- Result was:"); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason, bodyResult); TestOps.AppendFormat( interpreter, testData, TestOutputType.Reason, "---- Result should have been ({0} matching):", mode); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason, expectedResult); } else { TestOps.Append( interpreter, testData, TestOutputType.Reason, "---- Error testing result: "); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason, scriptResult); if ((scriptResult != null) && (scriptResult.ErrorInfo != null)) { TestOps.Append( interpreter, testData, TestOutputType.Error, "---- errorInfo(matchResult): "); TestOps.AppendLine( interpreter, testData, TestOutputType.Error, scriptResult.ErrorInfo); TestOps.Append( interpreter, testData, TestOutputType.Error, "---- errorCode(matchResult): "); TestOps.AppendLine( interpreter, testData, TestOutputType.Error, scriptResult.ErrorCode); } } } if (codeFailure) { ReturnCodeDictionary returnCodeMessages = interpreter.TestReturnCodeMessages; string codeMessage; if ((returnCodeMessages == null) || (!returnCodeMessages.TryGetValue( bodyCode, out codeMessage) && !returnCodeMessages.TryGetValue( ReturnCode.Invalid, out codeMessage))) { codeMessage = "Unknown"; } TestOps.AppendFormat( interpreter, testData, TestOutputType.Reason, "---- {0}; Return code was: {1}", codeMessage, bodyCode); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason); TestOps.Append( interpreter, testData, TestOutputType.Reason, "---- Return code should have been one of: "); TestOps.AppendLine( interpreter, testData, TestOutputType.Reason, returnCodes.ToString()); if ((bodyResult != null) && (bodyResult.ErrorInfo != null) && !returnCodes.Contains(ReturnCode.Error)) { TestOps.Append( interpreter, testData, TestOutputType.Error, "---- errorInfo(body): "); TestOps.AppendLine( interpreter, testData, TestOutputType.Error, bodyResult.ErrorInfo); TestOps.Append( interpreter, testData, TestOutputType.Error, "---- errorCode(body): "); TestOps.AppendLine( interpreter, testData, TestOutputType.Error, bodyResult.ErrorCode); } } TestOps.AppendFormat( interpreter, testData, TestOutputType.Fail, "==== {0} {1}", name, fail ? "FAILED" : "IGNORED"); TestOps.AppendLine( interpreter, testData, TestOutputType.Fail); } } // // NOTE: Did the above code succeed? // if (code == ReturnCode.Ok) { // // NOTE: The result is the complete output produced by the // entire test. // if (testData != null) { result = testData; } else { result = String.Empty; } } } catch (Exception e) { Engine.SetExceptionErrorCode(interpreter, e); result = e; code = ReturnCode.Error; } finally { interpreter.ExitTestLevel(); } } } else { result = String.Format( "wrong # args: should be \"{0} name description constraints body result\"", this.Name); code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region INotify Members public override ReturnCode Notify( Interpreter interpreter, IScriptEventArgs eventArgs, IClientData clientData, ArgumentList arguments, ref Result result ) { if (eventArgs == null) { return(ReturnCode.Ok); } if (!FlagOps.HasFlags( eventArgs.NotifyTypes, NotifyType.CallFrame, false)) { return(ReturnCode.Ok); } NotifyFlags notifyFlags = eventArgs.NotifyFlags; if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Popped | NotifyFlags.Deleted, false)) { return(ReturnCode.Ok); } IClientData eventClientData = eventArgs.ClientData; if (eventClientData == null) { return(ReturnCode.Ok); } ICallFrame newFrame = eventClientData.Data as ICallFrame; if (newFrame == null) { return(ReturnCode.Ok); } // // NOTE: Make sure the variables in this frame actually BELONG // to this frame. Also, we do not handle the global call // frame. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Force, true) && !CallFrameOps.IsNonGlobalVariable(newFrame)) { return(ReturnCode.Ok); } // // NOTE: If this is a [scope] created call frame, we do NOT want // to change any reference counts unless the call frame is // being deleted, not simply popped. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Deleted, true) && CallFrameOps.IsScope(newFrame)) { return(ReturnCode.Ok); } // // NOTE: Grab the variables for this call frame. If there are // none, we are done. // VariableDictionary variables = newFrame.Variables; if (variables == null) { return(ReturnCode.Ok); } // // NOTE: Process each variable in the call frame to adjust all // all the reference counts. After this point, we need // the interpreter context for the event. // Interpreter eventInterpreter = eventArgs.Interpreter; if (eventInterpreter == null) { return(ReturnCode.Ok); } foreach (KeyValuePair <string, IVariable> pair in variables) { // // NOTE: Grab the variable and make sure the variable it is // valid. // IVariable variable = pair.Value; if (variable == null) { continue; } // // NOTE: For unset operations, ObjectTraceCallback uses only // the "traceInfo.Variable" and "traceInfo.oldValue" // members of the ITraceInfo object instance. If the // number of trace and/or watch levels exceeds one, // force creation of a new TraceInfo object here; // otherwise, we may interfere with the setting of an // unrelated variable value. // ITraceInfo traceInfo = ScriptOps.NewTraceInfo( interpreter, null, BreakpointType.BeforeVariableUnset, newFrame, variable, pair.Key, null, VariableFlags.None, variable.Value, null, null, null, null, interpreter.NeedNewTraceInfo(VariableFlags.None), false, !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok); // // HACK: Manually invoke the Interpreter.ObjectTraceCallback // static (trace callback) method, in order to handle // contained object reference(s), if any. After this // method returns, the entire call frame will be going // away, along with any object references contained // within it. // ReturnCode code = Interpreter.ObjectTraceCallback( traceInfo.BreakpointType, eventInterpreter, traceInfo, ref result); if (code != ReturnCode.Ok) { return(code); } } return(ReturnCode.Ok); }
public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; if (interpreter != null) { if (arguments != null) { // // try {<tryBody>} // [finally {<finallyBody>}] // if ((arguments.Count == 2) || (arguments.Count == 4)) { if ((arguments.Count < 3) || (String.Compare(arguments[2], Try.Finally, StringOps.SystemStringComparisonType) == 0)) { string name = StringList.MakeList("try"); ICallFrame frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Try); interpreter.PushAutomaticCallFrame(frame); ReturnCode tryCode; Result tryResult = null; tryCode = interpreter.EvaluateScript(arguments[1], ref tryResult); if (tryCode == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, tryResult, String.Format("{0} (\"try\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); Result finallyResult = null; ReturnCode finallyCode = ReturnCode.Ok; if (arguments.Count == 4) { name = StringList.MakeList("finally"); frame = interpreter.NewTrackingCallFrame(name, CallFrameFlags.Finally); interpreter.PushAutomaticCallFrame(frame); // // BUGFIX: Preserve any and all existing error related // information during evaluation of the finally // block. // Engine.SetNoResetError(interpreter, true); // // NOTE: If there was an error during the try block as well, // keep them somewhat organized in the final error // information. // if (tryCode == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, null, String.Format("{0} ... continued ...", Environment.NewLine)); } // // NOTE: If the appropriate flag is set, call into the // Engine.ResetCancel method (with "force" enabled) // prior to evaluating the finally block script. // It should be noted here that even though the // return code of this call is checked by the code, // it basically cannot fail at this point. // Result canceledResult = null; bool canceled = false; bool unwound = false; bool resetCancel = false; // // NOTE: If the appropriate flag is set, reset the Exit // property prior to evaluating the finally block // script. // bool exit = false; bool resetExit = false; try { if (ScriptOps.HasFlags(interpreter, InterpreterFlags.FinallyResetCancel, true)) { ReturnCode resetCode; Result resetError = null; resetCode = Engine.ResetCancel( interpreter, CancelFlags.TryBlock, ref canceledResult, ref canceled, ref unwound, ref resetCancel, ref resetError); if (resetCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, resetCode, resetError); } } if (ScriptOps.HasFlags(interpreter, InterpreterFlags.FinallyResetExit, true)) { exit = interpreter.Exit; if (exit) { interpreter.Exit = false; resetExit = true; } } ReturnCode timeoutCode; Result timeoutResult = null; timeoutCode = Interpreter.StartFinallyTimeoutThread( interpreter, false, true, ref timeoutResult); if (timeoutCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, timeoutCode, timeoutResult); } try { // // NOTE: Evaluate the finally block. // finallyCode = interpreter.EvaluateScript( arguments[3], ref finallyResult); } finally { timeoutCode = Interpreter.InterruptFinallyTimeoutThread( interpreter, false, ref timeoutResult); if (timeoutCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, timeoutCode, timeoutResult); } } } finally { if (exit && resetExit) { if (ScriptOps.HasFlags(interpreter, InterpreterFlags.FinallyRestoreExit, true)) { interpreter.Exit = true; } } if ((canceled || unwound) && resetCancel) { if (ScriptOps.HasFlags(interpreter, InterpreterFlags.FinallyRestoreCancel, true)) { CancelFlags cancelFlags = CancelFlags.FinallyBlock; if (unwound) { cancelFlags |= CancelFlags.Unwind; } ReturnCode cancelCode; Result cancelError = null; cancelCode = Engine.CancelEvaluate( interpreter, canceledResult, cancelFlags, ref cancelError); if (cancelCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, cancelCode, cancelError); } } } } if (finallyCode == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, finallyResult, String.Format("{0} (\"finally\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Restore normal result reset semantics. // Engine.SetNoResetError(interpreter, false); // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopScopeCallFramesAndOneMore(); } // // NOTE: Initially, the overall command return code and result // is that of the try block; however, if the finally block // fails, that will be the return code and result. // if (finallyCode == ReturnCode.Ok) { result = tryResult; code = tryCode; } else { result = finallyResult; code = finallyCode; } } else { result = String.Format( "expected \"finally\" but got \"{0}\"", arguments[2]); code = ReturnCode.Error; } } else { result = "wrong # args: should be \"try script ?finally script?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; return(ReturnCode.Error); } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { ReturnCode code; // // NOTE: *WARNING* We do NOT actually support namespaces. This // command exists for the sole purpose of improving source // code compatibility with simple stand alone scripts that // may simply wrap themselves in a "namespace eval" block, // etc. Any other (more involved) use may not work at all // or may cause undesired and/or unpredictable results. // if (interpreter != null) { if (arguments != null) { if (arguments.Count >= 2) { string subCommand = arguments[1]; bool tried = false; code = ScriptOps.TryExecuteSubCommandFromEnsemble( interpreter, this, clientData, arguments, true, false, ref subCommand, ref tried, ref result); if ((code == ReturnCode.Ok) && !tried) { switch (subCommand) { case "children": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { string name = null; if (arguments.Count >= 3) { name = arguments[2]; } string pattern = null; if (arguments.Count >= 4) { pattern = arguments[3]; } IEnumerable <INamespace> children = NamespaceOps.Children( interpreter, name, pattern, false, ref result); if (children != null) { StringList list = new StringList(); foreach (INamespace child in children) { list.Add(child.QualifiedName); } result = list; } else { code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace children ?name? ?pattern?\""; code = ReturnCode.Error; } break; } case "code": { if (arguments.Count == 3) { string text = arguments[2]; if (!NamespaceOps.IsSubCommand(interpreter, text, "inscope")) { INamespace currentNamespace = null; code = interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result); if (code == ReturnCode.Ok) { StringList list = new StringList(); list.Add(NamespaceOps.MakeAbsoluteName( this.Name)); list.Add("inscope"); list.Add(NamespaceOps.MakeAbsoluteName( currentNamespace.QualifiedName)); list.Add(text); result = list; } } else { result = text; /* COMPAT: Tcl. */ } } else { result = "wrong # args: should be \"namespace code script\""; code = ReturnCode.Error; } break; } case "current": { if (arguments.Count == 2) { INamespace currentNamespace = null; code = interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result); if (code == ReturnCode.Ok) { if (currentNamespace != null) { result = currentNamespace.QualifiedName; } else { result = "current namespace is invalid"; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace current\""; code = ReturnCode.Error; } break; } case "delete": { if (arguments.Count >= 2) { for (int index = 2; index < arguments.Count; index++) { code = interpreter.DeleteNamespace( VariableFlags.None, arguments[index], false, ref result); if (code != ReturnCode.Ok) { break; } } if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = "wrong # args: should be \"namespace delete ?name name ...?\""; code = ReturnCode.Error; } break; } case "enable": { if ((arguments.Count >= 2) && (arguments.Count <= 4)) { if (arguments.Count >= 3) { bool enabled = false; code = Value.GetBoolean2( arguments[2], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref enabled, ref result); bool force = false; if ((code == ReturnCode.Ok) && (arguments.Count >= 4)) { code = Value.GetBoolean2( arguments[3], ValueFlags.AnyBoolean, interpreter.CultureInfo, ref force, ref result); } if (code == ReturnCode.Ok) { code = NamespaceOps.Enable( interpreter, enabled, force, ref result); } } if (code == ReturnCode.Ok) { result = interpreter.AreNamespacesEnabled(); } } else { result = "wrong # args: should be \"namespace enable ?enabled? ?force?\""; code = ReturnCode.Error; } break; } case "eval": { if (arguments.Count >= 4) { string namespaceName = NamespaceOps.MapName( interpreter, arguments[2]); INamespace @namespace = NamespaceOps.Lookup( interpreter, namespaceName, false, true, ref result); if (@namespace != null) { string name = StringList.MakeList("namespace eval", @namespace.QualifiedName); ICallFrame frame = interpreter.NewNamespaceCallFrame( name, CallFrameFlags.Evaluate | CallFrameFlags.UseNamespace, arguments, @namespace, false); interpreter.PushNamespaceCallFrame(frame); if (arguments.Count == 4) { code = interpreter.EvaluateScript(arguments[3], ref result); } else { code = interpreter.EvaluateScript(arguments, 3, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace eval \"{1}\" script line {2})", Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace, true), Interpreter.GetErrorLine(interpreter))); } /* IGNORED */ interpreter.PopNamespaceCallFrame(frame); /* NO RESULT */ Engine.CleanupNamespacesOrComplain(interpreter); } else { code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace eval name arg ?arg ...?\""; code = ReturnCode.Error; } break; } case "exists": { if (arguments.Count == 3) { result = ConversionOps.ToInt(NamespaceOps.Lookup( interpreter, arguments[2], false, false) != null); } else { result = "wrong # args: should be \"namespace exists name\""; code = ReturnCode.Error; } break; } case "export": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-clear", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { bool clear = false; if (options.IsPresent("-clear")) { clear = true; } StringList patterns = new StringList(); if (argumentIndex != Index.Invalid) { patterns.AddObjects(ArgumentList.GetRange(arguments, argumentIndex)); } code = NamespaceOps.Export(interpreter, null, patterns, clear, ref result); } } else { result = "wrong # args: should be \"namespace export ?-clear? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "forget": { if (arguments.Count >= 2) { if (arguments.Count >= 3) { code = NamespaceOps.Forget(interpreter, new StringList(ArgumentList.GetRange(arguments, 2)), ref result); if (code == ReturnCode.Ok) { result = String.Empty; } } else { result = String.Empty; code = ReturnCode.Ok; } } else { result = "wrong # args: should be \"namespace forget ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "import": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-force", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { bool force = false; if (options.IsPresent("-force")) { force = true; } StringList patterns = new StringList(); if (argumentIndex != Index.Invalid) { patterns.AddObjects(ArgumentList.GetRange(arguments, argumentIndex)); } code = NamespaceOps.Import(interpreter, patterns, force, ref result); } } else { result = "wrong # args: should be \"namespace import ?-force? ?pattern pattern ...?\""; code = ReturnCode.Error; } break; } case "info": { if (arguments.Count == 3) { code = NamespaceOps.InfoSubCommand( interpreter, arguments[2], ref result); } else { result = "wrong # args: should be \"namespace info name\""; code = ReturnCode.Error; } break; } case "inscope": { if (arguments.Count >= 4) { string namespaceName = NamespaceOps.MapName( interpreter, arguments[2]); INamespace @namespace = NamespaceOps.Lookup( interpreter, namespaceName, false, false, ref result); if (@namespace != null) { if (arguments.Count > 4) { IScriptLocation location = null; #if DEBUGGER && BREAKPOINTS code = ScriptOps.GetLocation( interpreter, arguments, 3, ref location, ref result); if (code == ReturnCode.Ok) #endif { string name = StringList.MakeList("namespace inscope", @namespace.QualifiedName); ICallFrame frame = interpreter.NewNamespaceCallFrame( name, CallFrameFlags.InScope | CallFrameFlags.UseNamespace, arguments, @namespace, false); interpreter.PushNamespaceCallFrame(frame); StringList list = new StringList(arguments, 4); code = interpreter.EvaluateScript( ListOps.Concat(arguments[3], list.ToString()), location, ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace, true), Interpreter.GetErrorLine(interpreter))); } /* IGNORED */ interpreter.PopNamespaceCallFrame(frame); /* NO RESULT */ Engine.CleanupNamespacesOrComplain(interpreter); } } else { string name = StringList.MakeList("namespace inscope", @namespace.QualifiedName); ICallFrame frame = interpreter.NewNamespaceCallFrame( name, CallFrameFlags.InScope | CallFrameFlags.UseNamespace, arguments, @namespace, false); interpreter.PushNamespaceCallFrame(frame); code = interpreter.EvaluateScript(arguments[3], ref result); if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (in namespace inscope \"{1}\" script line {2})", Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace, true), Interpreter.GetErrorLine(interpreter))); } /* IGNORED */ interpreter.PopNamespaceCallFrame(frame); /* NO RESULT */ Engine.CleanupNamespacesOrComplain(interpreter); } } else { code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace inscope name arg ?arg...?\""; code = ReturnCode.Error; } break; } case "mappings": { if (arguments.Count == 2) { lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { StringDictionary namespaceMappings = interpreter.NamespaceMappings; if (namespaceMappings != null) { result = namespaceMappings.KeysAndValuesToString(null, false); code = ReturnCode.Ok; } else { result = "namespace mappings not available"; code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace mappings\""; code = ReturnCode.Error; } break; } case "name": { if (arguments.Count == 3) { string name = arguments[2]; if (!NamespaceOps.IsQualifiedName(name)) { result = NamespaceOps.MakeQualifiedName(interpreter, name, true); code = ReturnCode.Ok; } else { result = "only non-qualified names are allowed"; code = ReturnCode.Error; } } else { result = "wrong # args: should be \"namespace name name\""; code = ReturnCode.Error; } break; } case "origin": { if (arguments.Count == 3) { code = NamespaceOps.Origin(interpreter, null, arguments[2], ref result); } else { result = "wrong # args: should be \"namespace origin name\""; code = ReturnCode.Error; } break; } case "parent": { if ((arguments.Count == 2) || (arguments.Count == 3)) { code = NamespaceOps.Parent( interpreter, (arguments.Count == 3) ? arguments[2] : null, ref result); } else { result = "wrong # args: should be \"namespace parent ?name?\""; code = ReturnCode.Error; } break; } case "qualifiers": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = qualifiers; } } else { result = "wrong # args: should be \"namespace qualifiers string\""; code = ReturnCode.Error; } break; } case "rename": { if (arguments.Count == 4) { code = interpreter.RenameNamespace( arguments[2], arguments[3], RenameGlobalOk, RenameInUseOk, ref result); } else { result = "wrong # args: should be \"namespace rename oldName newName\""; code = ReturnCode.Error; } break; } case "tail": { if (arguments.Count == 3) { string qualifiers = null; string tail = null; code = NamespaceOps.SplitName( arguments[2], ref qualifiers, ref tail, ref result); if (code == ReturnCode.Ok) { result = tail; } } else { result = "wrong # args: should be \"namespace tail string\""; code = ReturnCode.Error; } break; } case "unknown": { if ((arguments.Count == 2) || (arguments.Count == 3)) { INamespace currentNamespace = null; code = interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result); if (code == ReturnCode.Ok) { if (currentNamespace != null) { if (arguments.Count == 3) { string unknown = StringOps.NullIfEmpty(arguments[2]); if (String.IsNullOrEmpty(unknown) && NamespaceOps.IsGlobal(interpreter, currentNamespace)) { currentNamespace.Unknown = interpreter.GlobalUnknown; } else { currentNamespace.Unknown = unknown; } result = unknown; } else { result = currentNamespace.Unknown; } } else { if (arguments.Count == 3) { string unknown = StringOps.NullIfEmpty(arguments[2]); if (String.IsNullOrEmpty(unknown)) { interpreter.GlobalUnknown = TclVars.Unknown; } else { interpreter.GlobalUnknown = unknown; } result = unknown; } else { result = interpreter.GlobalUnknown; } } } } else { result = "wrong # args: should be \"namespace unknown ?script?\""; code = ReturnCode.Error; } break; } case "which": { if (arguments.Count >= 2) { OptionDictionary options = new OptionDictionary( new IOption[] { new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-command", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-variable", null), new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null) }); int argumentIndex = Index.Invalid; if (arguments.Count > 2) { code = interpreter.GetOptions(options, arguments, 0, 2, Index.Invalid, OptionBehaviorFlags.LastIsNonOption, false, ref argumentIndex, ref result); } else { code = ReturnCode.Ok; } if (code == ReturnCode.Ok) { if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) == arguments.Count)) { string name = arguments[argumentIndex]; bool isCommand = false; if (options.IsPresent("-command")) { isCommand = true; } bool isVariable = false; if (options.IsPresent("-variable")) { isVariable = true; } if (!isCommand || !isVariable) { NamespaceFlags flags = NamespaceFlags.None; if (isCommand) { flags |= NamespaceFlags.Command; } else if (isVariable) { flags |= NamespaceFlags.Variable; } else { flags |= NamespaceFlags.Command; } code = NamespaceOps.Which(interpreter, null, name, flags, ref result); } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; code = ReturnCode.Error; } } else { if ((argumentIndex != Index.Invalid) && Option.LooksLikeOption(arguments[argumentIndex])) { result = OptionDictionary.BadOption(options, arguments[argumentIndex]); } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; } code = ReturnCode.Error; } } } else { result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\""; code = ReturnCode.Error; } break; } default: { result = ScriptOps.BadSubCommand( interpreter, null, null, subCommand, this, null, null); code = ReturnCode.Error; break; } } } } else { result = "wrong # args: should be \"namespace subcommand ?arg ...?\""; code = ReturnCode.Error; } } else { result = "invalid argument list"; code = ReturnCode.Error; } } else { result = "invalid interpreter"; code = ReturnCode.Error; } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"uplevel ?level? arg ?arg ...?\""; return(ReturnCode.Error); } ReturnCode code; int currentLevel = 0; code = interpreter.GetInfoLevel( CallFrameOps.InfoLevelSubCommand, ref currentLevel, ref result); if (code != ReturnCode.Ok) { return(code); } bool mark = false; bool absolute = false; bool super = false; int level = 0; ICallFrame currentFrame = null; ICallFrame otherFrame = null; FrameResult frameResult = interpreter.GetCallFrame( arguments[1], ref mark, ref absolute, ref super, ref level, ref currentFrame, ref otherFrame, ref result); if (frameResult == FrameResult.Invalid) { return(ReturnCode.Error); } int argumentIndex = ((int)frameResult + 1); // // BUGFIX: The argument count needs to be checked again here. // if (argumentIndex >= arguments.Count) { result = "wrong # args: should be \"uplevel ?level? arg ?arg ...?\""; return(ReturnCode.Error); } if (mark) { code = CallFrameOps.MarkMatching( interpreter.CallStack, interpreter.CurrentFrame, absolute, level, CallFrameFlags.Variables, CallFrameFlags.Invisible | CallFrameFlags.NoVariables, CallFrameFlags.Invisible, false, false, true, ref result); } if (code == ReturnCode.Ok) { try { string name = StringList.MakeList("uplevel", arguments[1]); ICallFrame newFrame = interpreter.NewUplevelCallFrame( name, currentLevel, CallFrameFlags.None, mark, currentFrame, otherFrame); ICallFrame savedFrame = null; interpreter.PushUplevelCallFrame( currentFrame, newFrame, true, ref savedFrame); if ((argumentIndex + 1) >= arguments.Count) { code = interpreter.EvaluateScript( arguments[argumentIndex], ref result); } else { code = interpreter.EvaluateScript( arguments, argumentIndex, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"uplevel\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopUplevelCallFrame( currentFrame, newFrame, ref savedFrame); } finally { if (mark) { // // NOTE: We should not get an error at this point from // unmarking the call frames; however, if we do get // one, we need to complain loudly about it because // that means the interpreter state has probably been // corrupted somehow. // ReturnCode markCode; Result markResult = null; markCode = CallFrameOps.MarkMatching( interpreter.CallStack, interpreter.CurrentFrame, absolute, level, CallFrameFlags.Variables, CallFrameFlags.NoVariables, CallFrameFlags.Invisible, false, false, false, ref markResult); if (markCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, markCode, markResult); } } } } return(code); }
/////////////////////////////////////////////////////////////////////// public void Free( bool global ) { TraceOps.DebugTrace(String.Format( "Free: called, global = {0}, interpreter = {1}, disposed = {2}", global, FormatOps.InterpreterNoThrow(interpreter), disposed), typeof(VariableContext).Name, TracePriority.CleanupDebug); /////////////////////////////////////////////////////////////////// interpreter = null; /* NOT OWNED: Do not dispose. */ threadId = 0; /////////////////////////////////////////////////////////////////// if (traceInfo != null) { traceInfo = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the current call stack // unless we are [also] disposing of the interpreter itself; // therefore, use the special Free method here instead of the // Dispose method. The Free method is guaranteed to do the // right thing with regard to the global call frame (assuming // the "global" paramter is correct). // if (callStack != null) { callStack.Free(global); callStack = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the uplevel call frame // unless we are [also] disposing of the interpreter itself. // if (uplevelFrame != null) { uplevelFrame.Free(global); uplevelFrame = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the procedure call frame // unless we are [also] disposing of the interpreter itself. // if (procedureFrame != null) { procedureFrame.Free(global); procedureFrame = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the current call frame // unless we are [also] disposing of the interpreter itself. // if (currentFrame != null) { currentFrame.Free(global); currentFrame = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the uplevel call frame // unless we are [also] disposing of the interpreter itself. // If this is really a named scope call frame -AND- we are // being disposed, it should have already been cleaned up by // this point; therefore, this should be a no-op. // if (globalScopeFrame != null) { globalScopeFrame.Free(global); globalScopeFrame = null; } /////////////////////////////////////////////////////////////////// // // HACK: *SPECIAL CASE* We cannot dispose the global call frame // unless we are [also] disposing of the interpreter itself. // if (globalFrame != null) { globalFrame.Free(global); globalFrame = null; } }
/////////////////////////////////////////////////////////////////////// public void Free( bool global ) { // // HACK: *SPECIAL CASE* We cannot dispose the global call frame // unless we are [also] disposing of the interpreter itself. // if (global || !FlagOps.HasFlags(flags, CallFrameFlags.NoFree, true)) { kind = IdentifierKind.None; id = Guid.Empty; name = null; group = null; description = null; clientData = null; frameId = 0; frameLevel = 0; flags = CallFrameFlags.None; /////////////////////////////////////////////////////////////// if (tags != null) { tags.Clear(); tags = null; } /////////////////////////////////////////////////////////////// index = 0; level = 0; /////////////////////////////////////////////////////////////// if (arguments != null) { // // BUGFIX: We can only mutate argument lists that we own. // if (ownArguments) { arguments.Clear(); } arguments = null; } /////////////////////////////////////////////////////////////// ownArguments = false; /////////////////////////////////////////////////////////////// if (procedureArguments != null) { procedureArguments.Clear(); procedureArguments = null; } /////////////////////////////////////////////////////////////// if (variables != null) { variables.Clear(); variables = null; } /////////////////////////////////////////////////////////////// other = null; /* NOTE: Not owned, do not dispose. */ previous = null; /* NOTE: Not owned, do not dispose. */ next = null; /* NOTE: Not owned, do not dispose. */ /////////////////////////////////////////////////////////////// engineData = null; /* NOTE: Not owned, do not dispose. */ auxiliaryData = null; /* NOTE: Not owned, do not dispose. */ resolveData = null; /* NOTE: Not owned, do not dispose. */ extraData = null; /* NOTE: Not owned, do not dispose. */ } }