Skip to content

Commit

Permalink
Altered how Debugger works, making it PBO-Dependant
Browse files Browse the repository at this point in the history
  • Loading branch information
X39 committed Mar 2, 2020
1 parent 228217f commit c579789
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 35 deletions.
3 changes: 3 additions & 0 deletions Arma.Studio.SqfVmDebugger/Arma.Studio.SqfVmDebugger.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
<LastGenOutput>Language.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CfgFunctions.sqf" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if not exist "$(SolutionDir)Arma.Studio\$(OutDir)Plugins" mkdir ""$(SolutionDir)Arma.Studio\$(OutDir)Plugins""
Expand Down
38 changes: 38 additions & 0 deletions Arma.Studio.SqfVmDebugger/CfgFunctions.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
private _cfgFunctions = configFile >> "CfgFunctions";
private _preStart = [];
private _preInit = [];
private _postInit = [];
for "_i" from 0 to (count _cfgFunctions - 1) do
{
private _tagCfg = _cfgFunctions select _i;
private _tag = configName _tagCfg;
for "_j" from 0 to (count _tagCfg - 1) do
{
private _subCfg = _tagCfg select _j;
for "_k" from 0 to (count _subCfg - 1) do
{
private _cfg = _subCfg select _k;
private _name = configName _cfg;
private _path = getText (_cfg >> "file");
private _content = preprocessFile _path;
private _code = compile _content;
missionNamespace setVariable [
format ["%1_fnc_%2", _tag, _name],
_code
];
if (getNumber (_cfg >> "PreStart") > 0) then {
_preStart pushBack _code;
};
if (getNumber (_cfg >> "PreInit") > 0) then {
_preInit pushBack _code;
};
if (getNumber (_cfg >> "PostInit") > 0) then {
_postInit pushBack _code;
};
};
};
};

{ "PreStart" call _x; } forEach _preStart;
{ "PreInit" call _x; } forEach _preInit;
{ "PostInit" call _x; } forEach _postInit;
130 changes: 99 additions & 31 deletions Arma.Studio.SqfVmDebugger/PluginMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace Arma.Studio.SqfVmDebugger
{
public class PluginMain : IPlugin, IDebugger, ILogger
{
public string CfgFunctionsScript { get; private set; }


public Data.IO.IFileManagement FileManagement => this.GetApplication().MainWindow.FileManagement;


Expand All @@ -27,9 +30,13 @@ public Task<IUpdateInfo> CheckForUpdate(CancellationToken cancellationToken)

public Task Initialize(string pluginPath, CancellationToken cancellationToken)
{
Logger.Trace($"Creating Virtualmachine.");
this.Virtualmachine = new SqfVm.ClrVirtualmachine();
this.Virtualmachine.OnLog += this.Virtualmachine_OnLog;
Logger.Trace($"Loading CfgFunctions method.");
using (var stream = typeof(PluginMain).Assembly.GetManifestResourceStream(typeof(PluginMain).Assembly.GetName().Name + ".CfgFunctions.sqf"))
using (var reader = new System.IO.StreamReader(stream))
{
var text = reader.ReadToEnd().Trim();
this.CfgFunctionsScript = text;
}
return Task.CompletedTask;
}

Expand Down Expand Up @@ -108,24 +115,11 @@ public SqfVm.ClrVirtualmachine Virtualmachine
}
private SqfVm.ClrVirtualmachine _Virtualmachine;
#endregion

private readonly Dictionary<Data.IO.PBO, bool> IsPboAdded = new Dictionary<Data.IO.PBO, bool>();
public async Task Execute(EDebugAction action)
{
foreach (var pbo in this.FileManagement.Where((it) => it is Data.IO.PBO).Cast<Data.IO.PBO>())
if ((this.Virtualmachine == null && action != EDebugAction.Start) || (this.Virtualmachine != null && action == EDebugAction.Start))
{
if (!this.IsPboAdded.ContainsKey(pbo))
{
if (pbo.Prefix is null)
{
this.Virtualmachine.AddPhysicalBoundary(pbo.FullPath);
}
else
{
this.Virtualmachine.AddVirtualMapping(pbo.Prefix, pbo.FullPath);
}
this.IsPboAdded[pbo] = true;
}
throw new InvalidOperationException();
}
Logger.Diagnostic($"async Task Execute(action: {nameof(EDebugAction)}.{Enum.GetName(typeof(EDebugAction), action)})");
await Task.Run(() =>
Expand All @@ -134,21 +128,67 @@ await Task.Run(() =>
switch (action)
{
case EDebugAction.Start:
if (!(this.GetApplication().MainWindow.ActiveDockable is Data.UI.ITextDocument textEditorDocuments))
Logger.Trace($"Creating Virtualmachine.");
this.Virtualmachine = new SqfVm.ClrVirtualmachine();
this.Virtualmachine.OnLog += this.Virtualmachine_OnLog;
bool hasConfig = false;
// Prepare all PBO virtual paths
foreach (var pbo in this.FileManagement.Where((it) => it is Data.IO.PBO).Cast<Data.IO.PBO>())
{
Logger.Error($"Failed to receive TextDocument via this.GetApplication().MainWindow.ActiveDockable.");
return;
if (pbo.Prefix is null)
{
this.Virtualmachine.AddPhysicalBoundary(pbo.FullPath);
}
else
{
this.Virtualmachine.AddVirtualMapping(pbo.Prefix, pbo.FullPath);
}
// Parse config.cpp/description.ext
var config = pbo.GetAll((file) => file.Name == "config.cpp" || file.Name == "description.ext");
if (config.Any())
{
foreach (var file in config)
{
var fileContents = file.GetText();
var filePreprocessed = this.Virtualmachine.PreProcess(fileContents, file.FullPath);
this.Virtualmachine.ParseConfig(filePreprocessed, file.FullPath);
}
hasConfig = true;
}
else
{
Logger.Warning($"No config file located for PBO {pbo.Name}.");
}
}
var text = textEditorDocuments.GetContents();
var preprocessed = this.Virtualmachine.PreProcess(text, textEditorDocuments.TextEditorInstance.File.FullPath);
this.Virtualmachine.ParseSqf(preprocessed, textEditorDocuments.TextEditorInstance.File.FullPath);
this.State = EDebugState.Running;
execResult = this.Virtualmachine.Start();
if (!hasConfig)
{
Logger.Error("No config files available.");
break;
}
// Apply Breakpoints
foreach (var breakpoint in this.GetApplication().MainWindow.BreakpointManager.Breakpoints)
{
this.SetBreakpoint(breakpoint);
}
// Run CfgFunctions script
{
var text = this.CfgFunctionsScript;
var preprocessed = this.Virtualmachine.PreProcess(text, "SqfVmDebugger/CfgFunctions.sqf");
this.Virtualmachine.ParseSqf(preprocessed, "SqfVmDebugger/CfgFunctions.sqf");
this.State = EDebugState.Running;
execResult = this.Virtualmachine.Start();
}
//var text = textEditorDocuments.GetContents();
//var preprocessed = this.Virtualmachine.PreProcess(text, textEditorDocuments.TextEditorInstance.File.FullPath);
//this.Virtualmachine.ParseSqf(preprocessed, textEditorDocuments.TextEditorInstance.File.FullPath);
//this.State = EDebugState.Running;
//execResult = this.Virtualmachine.Start();
Logger.Diagnostic($"Result of Start: {execResult}");
break;
case EDebugAction.Stop:
execResult = this.Virtualmachine.Abort();
Logger.Diagnostic($"Result of Abort: {execResult}");
SpinWait.SpinUntil(() => !this.Virtualmachine.IsVirtualmachineRunning);
break;
case EDebugAction.Pause:
execResult = this.Virtualmachine.Stop();
Expand All @@ -167,7 +207,7 @@ await Task.Run(() =>
case EDebugAction.Step:
this.State = EDebugState.Running;
execResult = this.Virtualmachine.AssemblyStep();
Logger.Diagnostic($"Result of LeaveScope: {execResult}");
Logger.Diagnostic($"Result of AssemblyStep: {execResult}");
break;
case EDebugAction.StepInto:
this.State = EDebugState.Running;
Expand All @@ -179,7 +219,7 @@ await Task.Run(() =>
default:
throw new NotSupportedException();
}
this.State = this.Virtualmachine.IsVirtualmachineRunning ? EDebugState.Running : this.Virtualmachine.IsVirtualmachineDone ? EDebugState.NA : EDebugState.Halted;
this.State = (this.Virtualmachine?.IsVirtualmachineRunning ?? false) ? EDebugState.Running : (this.Virtualmachine?.IsVirtualmachineDone ?? true) ? EDebugState.NA : EDebugState.Halted;
if (this.State == EDebugState.Halted)
{
var callstack = this.Virtualmachine.GetCallstack();
Expand All @@ -193,11 +233,22 @@ await Task.Run(() =>
}, TaskContinuationOptions.OnlyOnRanToCompletion);
}
}
if (this.State == EDebugState.NA)
{
Logger.Trace($"Destroying Virtualmachine.");
this.Virtualmachine.OnLog -= this.Virtualmachine_OnLog;
this.Virtualmachine.Dispose();
this.Virtualmachine = null;
}
});
}

public IEnumerable<HaltInfo> GetHaltInfos()
{
if (this.Virtualmachine == null)
{
throw new InvalidOperationException();
}
Logger.Diagnostic($"IEnumerable<HaltInfo> GetHaltInfos()");
var callstack = this.Virtualmachine.GetCallstack();
var res = callstack.Select((it) => new HaltInfo(it.File)
Expand All @@ -212,19 +263,23 @@ public IEnumerable<HaltInfo> GetHaltInfos()
public Task RemoveBreakpoint(IBreakpoint breakpoint)
{
Logger.Diagnostic($"Task RemoveBreakpoint(breakpoint: {{{breakpoint}}})");
this.Virtualmachine.RemoveBreakpoint(breakpoint.Line, breakpoint.File);
this.Virtualmachine?.RemoveBreakpoint(breakpoint.Line, breakpoint.File);
return Task.CompletedTask;
}

public Task SetBreakpoint(IBreakpoint breakpoint)
{
Logger.Diagnostic($"Task SetBreakpoint(breakpoint: {{{breakpoint}}})");
this.Virtualmachine.SetBreakpoint(breakpoint.Line, breakpoint.File);
this.Virtualmachine?.SetBreakpoint(breakpoint.Line, breakpoint.File);
return Task.CompletedTask;
}

public IEnumerable<VariableInfo> GetLocalVariables()
{
if (this.Virtualmachine == null)
{
throw new InvalidOperationException();
}
Logger.Diagnostic($"IEnumerable<VariableInfo> GetLocalVariables()");
return this.Virtualmachine.GetLocalVariables().Select((it) => new VariableInfo
{
Expand All @@ -238,6 +293,10 @@ public IEnumerable<VariableInfo> GetLocalVariables()

public bool SetVariable(string variableName, string data, ENamespace @namespace)
{
if (this.Virtualmachine == null)
{
throw new InvalidOperationException();
}
Logger.Diagnostic($"bool SetVariable(variableName: {{{variableName}}}, data: {{{data}}}, @namespace: {{{@namespace}}})");
return this.Virtualmachine.SetVariable(variableName, data, @namespace switch
{
Expand All @@ -252,6 +311,10 @@ public bool SetVariable(string variableName, string data, ENamespace @namespace)

public VariableInfo GetVariable(string variableName, ENamespace @namespace)
{
if (this.Virtualmachine == null)
{
throw new InvalidOperationException();
}
Logger.Diagnostic($"bool VariableInfo(variableName: {{{variableName}}}, @namespace: {{{@namespace}}})");
var varref = this.Virtualmachine.GetVariable(variableName, @namespace switch {
ENamespace.Default => "",
Expand All @@ -273,6 +336,10 @@ public VariableInfo GetVariable(string variableName, ENamespace @namespace)

public SqfValue Evaluate(string text)
{
if (this.Virtualmachine == null)
{
throw new InvalidOperationException();
}
var res = this.Virtualmachine.Evaluate(text);
return new SqfValue { Data = res.Data, DataType = res.DataType };
}
Expand All @@ -281,6 +348,7 @@ public SqfValue Evaluate(string text)
#region ILogger
internal static Logger Logger { get; private set; }
public string TargetName => Properties.Language.LoggerName;

public void SetLogger(Logger logger)
{
Logger = logger;
Expand All @@ -299,7 +367,7 @@ protected virtual void Dispose(bool disposing)
}

// free unmanaged resources (unmanaged objects).
this.Virtualmachine.Dispose();
this.Virtualmachine?.Dispose();

this.disposedValue = true;
}
Expand Down
1 change: 0 additions & 1 deletion Arma.Studio/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ internal static void ShutdownSafe(int v)

static App()
{

using (var stream = typeof(App).Assembly.GetManifestResourceStream(typeof(App).Assembly.GetName().Name + ".git-version.txt"))
using (var reader = new System.IO.StreamReader(stream))
{
Expand Down
Loading

0 comments on commit c579789

Please sign in to comment.