/////////////////////////////////////////////////////////////////////// // // NOTE: For use by InteractiveOps.Commands._break() and // Engine.CheckBreakpoints() only. // internal InteractiveLoopData( ReturnCode code, BreakpointType breakpointType, string breakpointName, IToken token, ITraceInfo traceInfo, EngineFlags engineFlags, SubstitutionFlags substitutionFlags, EventFlags eventFlags, ExpressionFlags expressionFlags, HeaderFlags headerFlags, IClientData clientData, ArgumentList arguments ) : this() { this.code = code; this.breakpointType = breakpointType; this.breakpointName = breakpointName; this.token = token; this.traceInfo = traceInfo; this.engineFlags = engineFlags; this.substitutionFlags = substitutionFlags; this.eventFlags = eventFlags; this.expressionFlags = expressionFlags; this.headerFlags = headerFlags; this.clientData = clientData; this.arguments = arguments; }
//////////////////////////////////////////////////////////////////////// #region IExecuteTrace Members public virtual ReturnCode Execute( BreakpointType breakpointType, Interpreter interpreter, ITraceInfo traceInfo, ref Result result ) { return(ReturnCode.Ok); }
public void TraceState(ITraceInfo traceInfo) { _ = traceInfo ?? throw new ArgumentNullException(nameof(traceInfo)); logger.LogInformation("{0:HH:mm:ss} {1}{2} [{3}] {4}", DateTime.Now, new string(' ', (traceInfo.ExecuteContext.ExecutePath.Depth - 1) * 4), traceInfo.ExecuteContext.ExecutePath.ExecuteId, traceInfo.ExecuteContext.ActionFullName, traceInfo.State); }
/////////////////////////////////////////////////////////////////////// // // NOTE: For Interpreter class use only. // internal InteractiveLoopData( InteractiveLoopData loopData, IToken token, ITraceInfo traceInfo, HeaderFlags headerFlags ) : this(loopData) { this.token = token; this.traceInfo = traceInfo; this.headerFlags = headerFlags; }
private ReturnCode PluginTraceCallback( BreakpointType breakpointType, /* in */ Interpreter interpreter, /* in */ ITraceInfo traceInfo, /* in */ ref Result result /* out */ ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (traceInfo == null) { result = "invalid trace"; return(ReturnCode.Error); } // // NOTE: Intercept attempted get operations on variables // that we are monitoring. // if (breakpointType == BreakpointType.BeforeVariableGet) { // // NOTE: Demonstrate that we can return a value that is // totally dynamic and totally unrelated to the // actual variable itself. // result = Utility.GetUtcNow(); traceInfo.Cancel = true; traceInfo.ReturnCode = ReturnCode.Ok; } else if (breakpointType == BreakpointType.BeforeVariableUnset) { // // NOTE: Demonstrate that we can forbid operations from // taking place. // result = String.Format( "cannot unset \"{0}\", it is logically read-only", traceInfo.Name); traceInfo.Cancel = true; traceInfo.ReturnCode = ReturnCode.Error; } return(traceInfo.ReturnCode); }
/////////////////////////////////////////////////////////////////////// #region IExecuteTrace Members public ReturnCode Execute( BreakpointType breakpointType, Interpreter interpreter, ITraceInfo traceInfo, ref Result result ) { if (trace != null) { return(trace.Execute( breakpointType, interpreter, traceInfo, ref result)); } else { return(ReturnCode.Error); } }
//////////////////////////////////////////////////////////////////////// #region IExecuteTrace Members public override ReturnCode Execute( BreakpointType breakpointType, Interpreter interpreter, ITraceInfo traceInfo, ref Result result ) { TraceCallback callback = this.Callback; if (callback != null) { return(callback(breakpointType, interpreter, traceInfo, ref result)); } else { return(ReturnCode.Error); } }
/////////////////////////////////////////////////////////////////////// public ITraceInfo Update( ITraceInfo traceInfo ) { if (traceInfo != null) { Update( traceInfo.Trace, traceInfo.BreakpointType, traceInfo.Frame, traceInfo.Variable, traceInfo.Name, traceInfo.Index, traceInfo.Flags, traceInfo.OldValue, traceInfo.NewValue, traceInfo.OldValues, traceInfo.NewValues, traceInfo.List, traceInfo.Cancel, traceInfo.PostProcess, traceInfo.ReturnCode); } return(traceInfo); }
public VariableContext( Interpreter interpreter, int threadId, CallStack callStack, ICallFrame globalFrame, ICallFrame globalScopeFrame, ICallFrame currentFrame, ICallFrame procedureFrame, ICallFrame uplevelFrame, ITraceInfo traceInfo ) { this.interpreter = interpreter; this.threadId = threadId; this.callStack = callStack; this.globalFrame = globalFrame; this.globalScopeFrame = globalScopeFrame; this.currentFrame = currentFrame; this.procedureFrame = procedureFrame; this.uplevelFrame = uplevelFrame; this.traceInfo = traceInfo; }
private InteractiveLoopData( bool debug, IEnumerable <string> args, ReturnCode code, BreakpointType breakpointType, string breakpointName, IToken token, ITraceInfo traceInfo, EngineFlags engineFlags, SubstitutionFlags substitutionFlags, EventFlags eventFlags, ExpressionFlags expressionFlags, HeaderFlags headerFlags, IClientData clientData, ArgumentList arguments, bool exit ) { this.kind = IdentifierKind.InteractiveLoopData; this.id = AttributeOps.GetObjectId(this); this.debug = debug; this.args = args; this.code = code; this.breakpointType = breakpointType; this.breakpointName = breakpointName; this.token = token; this.traceInfo = traceInfo; this.engineFlags = engineFlags; this.substitutionFlags = substitutionFlags; this.eventFlags = eventFlags; this.expressionFlags = expressionFlags; this.headerFlags = headerFlags; this.clientData = clientData; this.arguments = arguments; this.exit = exit; }
/////////////////////////////////////////////////////////////////////// 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; } }
/////////////////////////////////////////////////////////////////////// #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); }
private static ReturnCode TraceCallback( BreakpointType breakpointType, /* in */ Interpreter interpreter, /* in */ ITraceInfo traceInfo, /* in */ ref Result result /* out */ ) { if (interpreter == null) { // // NOTE: We require a valid interpreter context. Most custom // variable trace methods will want to do this because it // is a fairly standard safety check (HIGHLY RECOMMENDED). // result = "invalid interpreter"; return(ReturnCode.Error); } if (traceInfo == null) { // // NOTE: This parameter should contain the information about // the current variable access being processed. If it // is null, we cannot continue (HIGHLY RECOMMENDED). // result = "invalid trace"; return(ReturnCode.Error); } // // NOTE: This trace method intercepts and show all variable access // for the interpreter. We could do practically anything // inside this method, including monitoring and/or modifying // the values to be fetched and/or set, changing the state of // the interpreter, or aborting the operation altogether. // /////////////////////////////////////////////////////////////////// // ******************* BEGIN CUSTOM TRACE CODE ******************** /////////////////////////////////////////////////////////////////// // // NOTE: This particular variable trace method requires a valid // interpreter host; however, in practice, such a requirement // would be very rare. // IHost host = interpreter.Host; if (host == null) { result = "interpreter host not available"; return(ReturnCode.Error); } // // NOTE: The try block here is optional; however, custom variable // trace methods are "officially" discouraged from raising // exceptions. // ReturnCode code = ReturnCode.Ok; switch (traceInfo.BreakpointType) { case BreakpointType.BeforeVariableUnset: { try { // // NOTE: Query the configured foreground and // background colors used by the host // to display variable trace information. // ConsoleColor foregroundColor = _ConsoleColor.None; ConsoleColor backgroundColor = _ConsoleColor.None; code = host.GetColors(null, "TraceInfo", true, true, ref foregroundColor, ref backgroundColor, ref result); if (code == ReturnCode.Ok) { // // NOTE: Clear the interpreter host and reset // its output position as well. // host.Clear(); host.ResetPosition(); // // NOTE: Write the variable trace information // received by this method to the // interpreter host. // host.WriteTraceInfo( interpreter, traceInfo, DetailFlags.EmptyContent, true, foregroundColor, backgroundColor); host.RestorePosition(false); int left = 0; int top = 0; host.GetPosition(ref left, ref top); left = 0; /* NOTE: Left aligned. */ top++; /* NOTE: On next line. */ host.WriteBox(null, "Press any key to continue...", null, false, false, ref left, ref top); host.Pause(); } } catch (Exception e) { result = e; code = ReturnCode.Error; } unsetTraces++; break; } case BreakpointType.BeforeVariableGet: { getTraces++; break; } case BreakpointType.BeforeVariableSet: { setTraces++; break; } } // // NOTE: Finally, return one of the standard status codes that // indicate success / failure of this variable access. // return(code); /////////////////////////////////////////////////////////////////// // ******************** END CUSTOM TRACE CODE ********************* /////////////////////////////////////////////////////////////////// }
public static bool Validate(this ITraceInfo traceInfo, Type ownerType, MethodBase methodBase) { return(ownerType == traceInfo.Info.Key && methodBase.Name == traceInfo.Info.Value); }
/////////////////////////////////////////////////////////////////////// public ReturnCode FireTraces( BreakpointType breakpointType, Interpreter interpreter, ITraceInfo traceInfo, ref Result result ) { ReturnCode code = ReturnCode.Ok; if (traces != null) { // // NOTE: Save the current variable flags. // VariableFlags savedFlags = flags; // // NOTE: Prevent endless trace recursion. // flags |= VariableFlags.NoTrace; try { // // NOTE: Process each trace (as long as they all continue // to succeed). // foreach (ITrace trace in traces) { if ((trace != null) && !EntityOps.IsDisabled(trace)) { // // NOTE: If possible, set the Trace property of the // TraceInfo to the one we are about to execute. // if (traceInfo != null) { traceInfo.Trace = trace; } // // NOTE: Since variable traces can basically do anything // they want, we wrap them in a try block to prevent // exceptions from escaping. // interpreter.EnterTraceLevel(); try { code = trace.Execute( breakpointType, interpreter, traceInfo, ref result); } catch (Exception e) { // // NOTE: Translate exceptions to a failure return. // result = String.Format( "caught exception while firing variable trace: {0}", e); code = ReturnCode.Error; } finally { interpreter.ExitTraceLevel(); } // // NOTE: Check for exception results specially because we // treat "Break" different from other return codes. // if (code == ReturnCode.Break) { // // NOTE: Success; however, skip processing further // traces for this variable operation. // code = ReturnCode.Ok; break; } else if (code != ReturnCode.Ok) { // // NOTE: Some type of failure (or exception), stop // processing for this variable operation. // break; } } } } finally { // // NOTE: Restore the saved variable flags. // flags = savedFlags; } } return(code); }
internal TraceInfo( ITraceInfo traceInfo ) { Update(traceInfo); }