1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Embedded console / terminal support

This commit is contained in:
Brian Fiete 2024-07-23 07:56:23 +02:00
parent 60817eec48
commit 20a8e3327c
28 changed files with 2317 additions and 690 deletions

View file

@ -10,6 +10,7 @@ namespace System.Diagnostics
bool mRedirectStandardOutput = false;
bool mRedirectStandardError = false;
bool mCreateNoWindow = false;
bool mActivateWindow = false;
public bool ErrorDialog;
//public Windows.Handle ErrorDialogParentHandle;
//public ProcessWindowStyle WindowStyle;
@ -26,6 +27,7 @@ namespace System.Diagnostics
public bool RedirectStandardOutput { get { return mRedirectStandardOutput; } set { mRedirectStandardOutput = value; } };
public bool RedirectStandardError { get { return mRedirectStandardError; } set { mRedirectStandardError = value; } };
public bool CreateNoWindow { get { return mCreateNoWindow; } set { mCreateNoWindow = value; } };
public bool ActivateWindow { get { return mActivateWindow; } set { mActivateWindow = value; } };
Encoding StandardOutputEncoding;
Encoding StandardErrorEncoding;

View file

@ -70,6 +70,8 @@ namespace System.Diagnostics
}
if (startInfo.CreateNoWindow)
spawnFlags |= .NoWindow;
if (!startInfo.ActivateWindow)
spawnFlags |= .NoActivateWindow;
if (startInfo.RedirectStandardInput)
spawnFlags |= .RedirectStdInput;
if (startInfo.RedirectStandardOutput)

View file

@ -24,6 +24,7 @@ namespace System.IO
case OpenError(FileOpenError);
case ReadError(FileReadError);
case SeekError;
case PipeListening;
}
static class File

View file

@ -72,6 +72,8 @@ namespace System.IO
{
case .Timeout:
return .Err(.ReadError(.Timeout));
case .PipeListening:
return .Err(.PipeListening);
default:
return .Err(.ReadError(.Unknown));
}

View file

@ -109,5 +109,11 @@ namespace System.IO
return .Ok;
}
public void Clear()
{
mMemory.Clear();
mPosition = 0;
}
}
}

View file

@ -26,6 +26,8 @@ namespace System.IO
public Result<void, FileOpenError> Create(StringView machineName, StringView pipeName, PipeOptions options)
{
Close();
Runtime.Assert(mBfpFile == null);
String path = scope String();
@ -64,6 +66,8 @@ namespace System.IO
public Result<void, FileOpenError> Open(StringView machineName, StringView pipeName, PipeOptions options)
{
Close();
Runtime.Assert(mBfpFile == null);
String path = scope String();

View file

@ -31,7 +31,8 @@ namespace System
PartialData,
TempFileError,
Timeout,
NotEmpty
NotEmpty,
PipeListening
};
public struct BfpSpawn {}
@ -263,6 +264,7 @@ namespace System
ErrorDialog = 0x400,
Window_Hide = 0x800,
Window_Maximized = 0x1000,
NoActivateWindow = 0x2000
};
public enum BfpKillFlags : int32
@ -455,6 +457,7 @@ namespace System
InsufficientBuffer = (int)Result.InsufficientBuffer,
Timeout = (int)Result.Timeout,
NotEmpty = (int)Result.NotEmpty,
PipeListening = (int)Result.PipeListening,
};
#if !BF_RUNTIME_DISABLE

View file

@ -0,0 +1,21 @@
FileVersion = 1
Dependencies = {corlib = "*", Beefy2D = "*"}
[Project]
Name = "BeefCon"
TargetType = "BeefGUIApplication"
StartupObject = "BeefCon.Program"
[Configs.Debug.Win64]
TargetDirectory = "$(WorkspaceDir)\\..\\..\\IDE\\dist"
TargetName = "$(ProjectName)_d"
BeefLibType = "DynamicDebug"
DebugCommandArguments = "123 1 Powershell"
[Configs.Release.Win64]
TargetDirectory = "$(WorkspaceDir)\\..\\..\\IDE\\dist"
DebugCommandArguments = "123 1 Powershell"
[[ProjectFolder.Items]]
Type = "Source"
Path = "../../IDE/src/util/ConsoleProvider.bf"

View file

@ -0,0 +1,8 @@
FileVersion = 1
Projects = {BeefCon = {Path = "."}, Beefy2D = "*"}
[Workspace]
StartupProject = "BeefCon"
[Configs.Release.Win64]
BfOptimizationLevel = "OgPlus"

View file

@ -0,0 +1,167 @@
using System;
using System.Threading;
using System.IO;
using IDE.util;
using System.Diagnostics;
using Beefy.widgets;
namespace BeefCon;
class Program
{
BeefConConsoleProvider.Pipe mPipe ~ delete _;
WinNativeConsoleProvider mProvider ~ delete _;
int32 mPid;
int32 mConid;
String mExecStr = new .() ~ delete _;
SpawnedProcess mSpawnedProcess ~ delete _;
public ~this()
{
mSpawnedProcess.Kill();
mSpawnedProcess.WaitFor();
}
static mixin GET<T>(var ptr)
{
*((T*)(ptr += sizeof(T)) - 1)
}
public void MessageLoop()
{
while (true)
{
switch (mPipe.ReadMessage(-1))
{
case .Ok(let msg):
uint8* ptr = msg.Ptr + 1;
switch (*(BeefConConsoleProvider.Message*)msg.Ptr)
{
case .GetData:
mPipe.StartMessage(BeefConConsoleProvider.Message.Data);
mPipe.Stream.Write((int32)mProvider.Width);
mPipe.Stream.Write((int32)mProvider.Height);
mPipe.Stream.Write((int32)mProvider.BufferHeight);
mPipe.Stream.Write((int32)mProvider.ScrollTop);
mPipe.Stream.Write(mProvider.CursorVisible);
mPipe.Stream.Write(mProvider.CursorHeight);
mPipe.Stream.Write(mProvider.CursorPos);
for (int i < 16)
mPipe.Stream.Write(mProvider.GetColor(i));
for (int row < mProvider.Height)
{
for (int col < mProvider.Width)
{
var cell = mProvider.GetCell(col, row);
mPipe.Stream.Write(cell.mChar);
mPipe.Stream.Write(cell.mAttributes);
}
}
mPipe.EndMessage();
case .Resize:
int32 cols = GET!<int32>(ptr);
int32 rows = GET!<int32>(ptr);
bool resizeContent = GET!<bool>(ptr);
mProvider.Resize(cols, rows, resizeContent);
case .KeyDown:
KeyCode keyCode = GET!<KeyCode>(ptr);
KeyFlags keyFlags = GET!<KeyFlags>(ptr);
mProvider.KeyDown(keyCode, keyFlags);
case .KeyUp:
KeyCode keyCode = GET!<KeyCode>(ptr);
mProvider.KeyUp(keyCode);
case .InputString:
int32 strLen = GET!<int32>(ptr);
StringView str = .((.)ptr, strLen);
mProvider.SendInput(str);
case .MouseDown:
int32 col = GET!<int32>(ptr);
int32 row = GET!<int32>(ptr);
int32 btnState = GET!<int32>(ptr);
int32 btnCount = GET!<int32>(ptr);
KeyFlags keyFlags = GET!<KeyFlags>(ptr);
mProvider.MouseDown(col, row, btnState, btnCount, keyFlags);
case .MouseMove:
int32 col = GET!<int32>(ptr);
int32 row = GET!<int32>(ptr);
int32 btnState = GET!<int32>(ptr);
KeyFlags keyFlags = GET!<KeyFlags>(ptr);
mProvider.MouseMove(col, row, btnState, keyFlags);
case .MouseUp:
int32 col = GET!<int32>(ptr);
int32 row = GET!<int32>(ptr);
int32 btnState = GET!<int32>(ptr);
KeyFlags keyFlags = GET!<KeyFlags>(ptr);
mProvider.MouseUp(col, row, btnState, keyFlags);
case .MouseWheel:
int32 col = GET!<int32>(ptr);
int32 row = GET!<int32>(ptr);
int32 dy = GET!<int32>(ptr);
mProvider.MouseWheel(col, row, dy);
default:
}
case .Err(let err):
return;
}
}
}
public void Run()
{
mPipe = new .();
mPipe.Listen(mPid, mConid);
mProvider = new .();
//mProvider.mHideNativeConsole = false;
mProvider.Attach();
ProcessStartInfo procInfo = scope ProcessStartInfo();
procInfo.UseShellExecute = false;
procInfo.SetFileName(mExecStr);
mSpawnedProcess = new SpawnedProcess();
if (mSpawnedProcess.Start(procInfo) case .Err)
return;
while (true)
{
mProvider.Update();
var process = Platform.BfpProcess_GetById(null, mPid, null);
if (process == null)
{
Console.Error.WriteLine("Process closed");
return;
}
Platform.BfpProcess_Release(process);
MessageLoop();
if (mPipe.mFailed)
return;
if (!mPipe.mConnected)
Thread.Sleep(20);
if (mSpawnedProcess.WaitFor(0))
return;
}
}
public static int Main(String[] args)
{
if (args.Count < 2)
{
Console.Error.WriteLine("Usage: BeefCon <pid> <conid> <exe>");
return 1;
}
Program pg = scope .();
pg.mPid = int32.Parse(args[0]);
pg.mConid = int32.Parse(args[1]);
pg.mExecStr.Set(args[2]);
pg.Run();
return 0;
}
}

View file

@ -54,7 +54,8 @@ enum BfpResult
BfpResult_PartialData,
BfpResult_TempFileError,
BfpResult_Timeout,
BfpResult_NotEmpty
BfpResult_NotEmpty,
BfpResult_PipeListening
};
enum BfpSystemResult
@ -77,7 +78,8 @@ enum BfpFileResult
BfpFileResult_PartialData = BfpResult_PartialData,
BfpFileResult_InsufficientBuffer = BfpResult_InsufficientBuffer,
BfpFileResult_Timeout = BfpResult_Timeout,
BfpFileResult_NotEmpty = BfpResult_NotEmpty
BfpFileResult_NotEmpty = BfpResult_NotEmpty,
BfpFileResult_PipeListening = BfpResult_PipeListening
};
typedef void(*BfpCrashInfoFunc)();
@ -197,6 +199,7 @@ enum BfpSpawnFlags
BfpSpawnFlag_ErrorDialog = 0x400,
BfpSpawnFlag_Window_Hide = 0x800,
BfpSpawnFlag_Window_Maximized = 0x1000,
BfpSpawnFlag_NoActivateWindow = 0x2000,
};
enum BfpSpawnResult
@ -420,7 +423,7 @@ enum BfpFileStdKind
BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttr, BfpFileResult* outResult);
BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult);
BFP_EXPORT intptr BFP_CALLTYPE BfpFile_GetSystemHandle(BfpFile* file);
BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_GetFromHandle(intptr handle, BfpFileResult* outResult);
BFP_EXPORT void BFP_CALLTYPE BfpFile_Release(BfpFile* file);
BFP_EXPORT void BFP_CALLTYPE BfpFile_Close(BfpFile* file, BfpFileResult* outResult);
BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Write(BfpFile* file, const void* buffer, intptr size, int timeoutMS, BfpFileResult* outResult);

View file

@ -1689,6 +1689,13 @@ public:
creationFlags |= CREATE_NO_WINDOW;
// set up the environment block parameter
if ((flags & BfpSpawnFlag_NoActivateWindow) != 0)
{
startupInfo.dwFlags |= STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_SHOWNOACTIVATE;
}
// set up the environment block parameter
WCHAR* targetStrPtr = NULL;
UTF16String targetStrW;
if ((flags & BfpSpawnFlag_ArgsIncludesTarget) != 0)
@ -1726,7 +1733,7 @@ public:
String str8(env, envSize);
envW = UTF8Decode(str8);
envVoidPtr = (void*)envW.c_str();
startupInfo.dwFlags |= CREATE_UNICODE_ENVIRONMENT;
creationFlags |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
@ -2998,6 +3005,11 @@ BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* path, BfpFileCreateK
return bfpFile;
}
BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_GetFromHandle(intptr handle, BfpFileResult* outResult)
{
return new BfpFile((HANDLE)handle);
}
BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult)
{
HANDLE h = INVALID_HANDLE_VALUE;
@ -3235,6 +3247,9 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
int lastError = ::GetLastError();
switch (lastError)
{
case ERROR_PIPE_LISTENING:
OUTRESULT(BfpFileResult_PipeListening);
break;
case ERROR_BROKEN_PIPE: // Just an EOF
OUTRESULT(BfpFileResult_Ok);
break;

View file

@ -138,6 +138,14 @@ namespace IDE.Debugger
Allocations = 2
}
public enum OpenFileFlags
{
None,
RedirectStdInput = 1,
RedirectStdOutput = 2,
RedirectStdError = 4
}
public List<Breakpoint> mBreakpointList = new List<Breakpoint>();
public Dictionary<String, StepFilter> mStepFilterList = new Dictionary<String, StepFilter>();
@ -157,7 +165,7 @@ namespace IDE.Debugger
static extern bool Debugger_OpenMiniDump(char8* filename);
[CallingConvention(.Stdcall),CLink]
static extern bool Debugger_OpenFile(char8* launchPath, char8* targetPath, char8* args, char8* workingDir, void* envBlockPtr, int32 envBlockLen, bool hotSwapEnabled);
static extern bool Debugger_OpenFile(char8* launchPath, char8* targetPath, char8* args, char8* workingDir, void* envBlockPtr, int32 envBlockLen, bool hotSwapEnabled, OpenFileFlags openFileFlags);
[CallingConvention(.Stdcall),CLink]
static extern bool Debugger_ComptimeAttach(void* bfCompiler);
@ -165,6 +173,9 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall),CLink]
static extern bool Debugger_Attach(int32 processId, AttachFlags attachFlags);
[CallingConvention(.Stdcall),CLink]
public static extern void Debugger_GetStdHandles(Platform.BfpFile** outStdIn, Platform.BfpFile** outStdOut, Platform.BfpFile** outStdErr);
[CallingConvention(.Stdcall),CLink]
static extern void Debugger_Run();
@ -473,7 +484,7 @@ namespace IDE.Debugger
Debugger_FullReportMemory();
}
public bool OpenFile(String launchPath, String targetPath, String args, String workingDir, Span<char8> envBlock, bool isCompiled, bool hotSwapEnabled)
public bool OpenFile(String launchPath, String targetPath, String args, String workingDir, Span<char8> envBlock, bool isCompiled, bool hotSwapEnabled, OpenFileFlags openFileFlags)
{
DeleteAndNullify!(mRunningPath);
mRunningPath = new String(launchPath);
@ -481,7 +492,7 @@ namespace IDE.Debugger
mIsComptimeDebug = false;
mIsRunningCompiled = isCompiled;
mIsRunningWithHotSwap = hotSwapEnabled;
return Debugger_OpenFile(launchPath, targetPath, args, workingDir, envBlock.Ptr, (int32)envBlock.Length, hotSwapEnabled);
return Debugger_OpenFile(launchPath, targetPath, args, workingDir, envBlock.Ptr, (int32)envBlock.Length, hotSwapEnabled, openFileFlags);
}
public bool ComptimeAttach(BfCompiler compiler)
@ -1175,6 +1186,11 @@ namespace IDE.Debugger
return Debugger_Attach(process.Id, attachFlags);
}
public void GetStdHandles(Platform.BfpFile** outStdIn, Platform.BfpFile** outStdOut, Platform.BfpFile** outStdErr)
{
Debugger_GetStdHandles(outStdIn, outStdOut, outStdErr);
}
public DbgProfiler StartProfiling(int threadId, String desc, int sampleRate)
{
DbgProfiler profiler = new DbgProfiler(Debugger_StartProfiling(threadId, desc, (.)sampleRate));

View file

@ -345,6 +345,9 @@ namespace IDE
bool mProfileCompile = false;
ProfileInstance mProfileCompileProfileId;
Monitor mDebugOutputMonitor = new .() ~ delete _;
String mDebugOutput = new .() ~ delete _;
#if !CLI
public IPCHelper mIPCHelper ~ delete _;
public bool mIPCHadFocus;
@ -3779,7 +3782,7 @@ namespace IDE
}
// Always write to STDOUT even if we're running as a GUI, allowing cases like RunAndWait to pass us a stdout handle
Console.Error.WriteLine("ERROR: {0}", text);
Console.Error.WriteLine("ERROR: {0}", text).IgnoreError();
#if CLI
mFailed = true;
@ -3806,7 +3809,7 @@ namespace IDE
mFailed = true;
OutputLineSmart("ERROR: {0}", text);
Console.Error.WriteLine("ERROR: {0}", text);
Console.Error.WriteLine("ERROR: {0}", text).IgnoreError();
return null;
}
@ -8250,8 +8253,11 @@ namespace IDE
NOP!();
}
if (!evt.mKeyFlags.HeldKeys.HasFlag(.Alt))
{
mConsolePanel.SysKeyDown(evt);
//mTerminalPanel.SysKeyDown(evt);
mTerminalPanel.SysKeyDown(evt);
}
if (evt.mHandled)
return;
@ -8426,8 +8432,8 @@ namespace IDE
void SysKeyUp(KeyCode keyCode)
{
//mTerminalPanel.SysKeyUp(keyCode);
mConsolePanel.SysKeyUp(keyCode);
mTerminalPanel.SysKeyUp(keyCode);
}
void ShowOpenFileInSolutionDialog()
@ -8786,8 +8792,10 @@ namespace IDE
return;
StreamReader streamReader = scope StreamReader(fileStream, null, false, 4096);
int count = 0;
while (true)
{
count++;
var buffer = scope String();
if (streamReader.ReadLine(buffer) case .Err)
break;
@ -8816,6 +8824,60 @@ namespace IDE
}
}
void ReadDebugOutputThread(Object obj)
{
FileStream fileStream = (.)obj;
int count = 0;
Loop: while (true)
{
uint8[4096] data = ?;
switch (fileStream.TryRead(data, -1))
{
case .Ok(let len):
if (len == 0)
break Loop;
using (mDebugOutputMonitor.Enter())
{
for (int i < len)
mDebugOutput.Append((char8)data[i]);
}
case .Err:
break Loop;
}
/*var buffer = scope String();
if (streamReader.Read(buffer) case .Err)
break;
using (mDebugOutputMonitor.Enter())
mDebugOutput.Add(new String(buffer));*/
count++;
}
delete fileStream;
}
/*static void ReadDebugErrorThread(Object obj)
{
ExecutionInstance executionInstance = (ExecutionInstance)obj;
FileStream fileStream = scope FileStream();
if (executionInstance.mProcess.AttachStandardError(fileStream) case .Err)
return;
StreamReader streamReader = scope StreamReader(fileStream, null, false, 4096);
while (true)
{
var buffer = scope String();
if (streamReader.ReadLine(buffer) case .Err)
break;
using (IDEApp.sApp.mMonitor.Enter())
executionInstance.mDeferredOutput.Add(new String(buffer));
}
}*/
public enum RunFlags
{
None,
@ -11943,8 +12005,26 @@ namespace IDE
return true;
}
if (!mDebugger.OpenFile(launchPath, targetPath, arguments, workingDir, envBlock, wasCompiled, workspaceOptions.mAllowHotSwapping))
if (mSettings.mDebugConsoleKind == .Embedded)
{
ShowConsole();
mConsolePanel.Attach();
}
if (mSettings.mDebugConsoleKind == .RedirectToImmediate)
{
ShowImmediatePanel();
}
DebugManager.OpenFileFlags openFileFlags = .None;
if ((mSettings.mDebugConsoleKind == .RedirectToImmediate) || (mSettings.mDebugConsoleKind == .RedirectToOutput))
openFileFlags |= .RedirectStdOutput | .RedirectStdError;
if (!mDebugger.OpenFile(launchPath, targetPath, arguments, workingDir, envBlock, wasCompiled, workspaceOptions.mAllowHotSwapping, openFileFlags))
{
if (!mSettings.mAlwaysEnableConsole)
mConsolePanel.Detach();
DeleteAndNullify!(mCompileAndRunStopwatch);
return false;
}
@ -12301,8 +12381,10 @@ namespace IDE
mOutputPanel = new OutputPanel(true);
mOutputPanel.mAutoDelete = false;
mTerminalPanel = new TerminalPanel();
mTerminalPanel .Init();
mTerminalPanel.mAutoDelete = false;
mConsolePanel = new ConsolePanel();
mConsolePanel.Init();
mConsolePanel.mAutoDelete = false;
mImmediatePanel = new ImmediatePanel();
mImmediatePanel.mAutoDelete = false;
@ -12963,6 +13045,37 @@ namespace IDE
{
mDebugger.Update();
Platform.BfpFile* stdOut = null;
Platform.BfpFile* stdError = null;
mDebugger.GetStdHandles(null, &stdOut, &stdError);
if (stdOut != null)
{
FileStream fileStream = new FileStream();
fileStream.Attach(stdOut);
Thread thread = new Thread(new => ReadDebugOutputThread);
thread.Start(fileStream, true);
}
if (stdError != null)
{
FileStream fileStream = new FileStream();
fileStream.Attach(stdError);
Thread thread = new Thread(new => ReadDebugOutputThread);
thread.Start(fileStream, true);
}
using (mDebugOutputMonitor.Enter())
{
if (!mDebugOutput.IsEmpty)
{
mDebugOutput.Replace("\r", "");
if (mSettings.mDebugConsoleKind == .RedirectToOutput)
mOutputPanel.Write(mDebugOutput);
if (mSettings.mDebugConsoleKind == .RedirectToImmediate)
mImmediatePanel.Write(mDebugOutput);
mDebugOutput.Clear();
}
}
runState = mDebugger.GetRunState();
mDebuggerPerformingTask = (runState == .DebugEval) || (runState == .DebugEval_Done) || (runState == .SearchingSymSrv);
@ -13514,6 +13627,8 @@ namespace IDE
var disassemblyPanel = TryGetDisassemblyPanel(false);
if (disassemblyPanel != null)
disassemblyPanel.Disable();
if (!mSettings.mAlwaysEnableConsole)
mConsolePanel.Detach();
mDebugger.DisposeNativeBreakpoints();
mDebugger.Detach();
mDebugger.mIsRunning = false;
@ -14539,6 +14654,16 @@ namespace IDE
RefreshRate = 60;
}
if (mTerminalPanel != null)
{
// Detach terminal if the panel is closed
var terminalTabButton = GetTab(mTerminalPanel);
if (terminalTabButton == null)
{
mTerminalPanel.Detach();
}
}
bool hasFocus = false;
for (let window in mWindows)
{
@ -14622,6 +14747,15 @@ namespace IDE
if (mScriptManager != null)
mScriptManager.Update();
if (mConsolePanel != null)
{
if ((mSettings.mAlwaysEnableConsole) ||
((mSettings.mDebugConsoleKind == .Embedded) && (mDebugger.mIsRunning)))
mConsolePanel.Attach();
else
mConsolePanel.Detach();
}
if (mTestManager != null)
{
mTestManager.Update();

View file

@ -898,8 +898,10 @@ namespace IDE
Add("Show Output", "Ctrl+Alt+O");
Add("Show Profiler", "Ctrl+Alt+P");
Add("Show QuickWatch", "Shift+Alt+W");
Add("Show Threads", "Ctrl+Alt+T");
Add("Show Threads", "Ctrl+Alt+H");
Add("Show Watches", "Ctrl+Alt+W");
Add("Show Console", "Ctrl+Alt+N");
Add("Show Terminal", "Ctrl+Alt+T");
Add("Show Workspace Explorer", "Ctrl+Alt+S");
Add("Start Debugging", "F5");
Add("Start Without Debugging", "Ctrl+F5");
@ -1097,6 +1099,14 @@ namespace IDE
public bool mDependencies;
}
public enum ConsoleKind
{
Native,
Embedded,
RedirectToOutput,
RedirectToImmediate,
}
public bool mLoadedSettings;
public String mSettingFileText ~ delete _;
public DateTime mSettingFileDateTime;
@ -1110,6 +1120,8 @@ namespace IDE
public RecentFiles mRecentFiles = new RecentFiles() ~ delete _;
public String mWakaTimeKey = new .() ~ delete _;
public String mWindowsTerminal = new .("Powershell") ~ delete _;
public ConsoleKind mDebugConsoleKind;
public bool mAlwaysEnableConsole;
public String mEmscriptenPath = new .() ~ delete _;
public bool mEnableDevMode;
public TutorialsFinished mTutorialsFinished = .();
@ -1167,8 +1179,12 @@ namespace IDE
mDebuggerSettings.Serialize(sd);
using (sd.CreateObject("VisualStudio"))
mVSSettings.Serialize(sd);
using (sd.CreateObject("Terminal"))
using (sd.CreateObject("Console"))
{
sd.Add("WindowsTerminal", mWindowsTerminal);
sd.Add("DebugConsole", mDebugConsoleKind);
sd.Add("AlwaysEnableConsole", mAlwaysEnableConsole);
}
using (sd.CreateObject("Wasm"))
sd.Add("EmscriptenPath", mEmscriptenPath);
@ -1258,8 +1274,12 @@ namespace IDE
mDebuggerSettings.Deserialize(sd);
using (sd.Open("VisualStudio"))
mVSSettings.Deserialize(sd);
using (sd.Open("Terminal"))
using (sd.Open("Console"))
{
sd.Get("WindowsTerminal", mWindowsTerminal);
mDebugConsoleKind = sd.GetEnum<ConsoleKind>("DebugConsole", .Native);
mAlwaysEnableConsole = sd.GetBool("AlwaysEnableConsole");
}
using (sd.Open("Wasm"))
sd.Get("EmscriptenPath", mEmscriptenPath);

View file

@ -614,7 +614,7 @@ namespace IDE
var envBlock = scope List<char8>();
Environment.EncodeEnvironmentVariables(envVars, envBlock);
if (!gApp.mDebugger.OpenFile(curProjectInfo.mTestExePath, curProjectInfo.mTestExePath, mTestInstance.mArgs, mTestInstance.mWorkingDir, envBlock, true, false))
if (!gApp.mDebugger.OpenFile(curProjectInfo.mTestExePath, curProjectInfo.mTestExePath, mTestInstance.mArgs, mTestInstance.mWorkingDir, envBlock, true, false, .None))
{
QueueOutputLine("ERROR: Failed debug '{0}'", curProjectInfo.mTestExePath);
TestFailed();

File diff suppressed because it is too large Load diff

View file

@ -332,7 +332,7 @@ namespace IDE.ui
var envBlock = scope List<char8>();
Environment.EncodeEnvironmentVariables(envVars, envBlock);
if (!gApp.mDebugger.OpenFile(targetPath, targetPath, arguments, workingDir, envBlock, false, false))
if (!gApp.mDebugger.OpenFile(targetPath, targetPath, arguments, workingDir, envBlock, false, false, .None))
{
gApp.Fail(scope String()..AppendF("Unable to open executable for debugging: {0}", targetPath));
return;

View file

@ -2991,7 +2991,7 @@ namespace IDE.ui
}
});
item = folderItem.AddItem("Terminal");
item = folderItem.AddItem("External Terminal");
item.mOnMenuItemSelected.Add(new (menu) =>
{
let projectItem = GetSelectedProjectItem();
@ -3023,6 +3023,34 @@ namespace IDE.ui
process.Start(psi).IgnoreError();
}
});
item = folderItem.AddItem("Embedded Terminal");
item.mOnMenuItemSelected.Add(new (menu) =>
{
let projectItem = GetSelectedProjectItem();
String path = scope String();
if (projectItem == null)
{
path.Set(gApp.mWorkspace.mDir);
}
else if (let projectFolder = projectItem as ProjectFolder)
{
if (projectFolder.mParentFolder == null)
{
path.Set(projectFolder.mProject.mProjectDir);
}
else
projectFolder.GetFullImportPath(path);
}
else
projectItem.mParentFolder.GetFullImportPath(path);
if (!path.IsWhiteSpace)
{
gApp.ShowTerminal();
gApp.mTerminalPanel.OpenDirectory(path);
}
});
}
if (projectItem == null)

View file

@ -62,7 +62,7 @@ namespace IDE.ui
AddCategoryItem(root, "Compiler");
AddCategoryItem(root, "Debugger");
AddCategoryItem(root, "Visual Studio");
AddCategoryItem(root, "Terminal");
AddCategoryItem(root, "Console");
AddCategoryItem(root, "Wasm");
if (!gApp.mSettings.mVSSettings.IsConfigured())
@ -170,7 +170,7 @@ namespace IDE.ui
category.Open(true, true);
}
void PopulateTerminalOptions()
void PopulateConsoleOptions()
{
mCurPropertiesTarget = gApp.mSettings;
@ -179,6 +179,8 @@ namespace IDE.ui
category.mIsBold = true;
category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, cHeaderColor);
AddPropertiesItem(category, "Windows Terminal", "mWindowsTerminal");
AddPropertiesItem(category, "Debug Console", "mDebugConsoleKind");
AddPropertiesItem(category, "Always Enable Console", "mAlwaysEnableConsole");
category.Open(true, true);
}
@ -438,7 +440,7 @@ namespace IDE.ui
case .VisualStudio:
PopulateVSOptions();
case .Terminal:
PopulateTerminalOptions();
PopulateConsoleOptions();
case .Wasm:
PopulateWasmOptions();
default:

View file

@ -10,15 +10,51 @@ using Beefy.widgets;
using Beefy.events;
using System.Diagnostics;
using Beefy.utils;
using IDE.util;
namespace IDE.ui;
class TerminalPanel : Panel
class TerminalPanel : ConsolePanel
{
public override void Serialize(StructuredData data)
{
base.Serialize(data);
data.Add("Type", "TerminalPanel");
}
public override void Init()
{
var consoleProvider = new BeefConConsoleProvider();
consoleProvider.mBeefConExePath = new $"{gApp.mInstallDir}/BeefCon.exe";
consoleProvider.mTerminalExe = new .(gApp.mSettings.mWindowsTerminal);
mConsoleProvider = consoleProvider;
}
public override void AddedToParent()
{
var consoleProvider = (BeefConConsoleProvider)mConsoleProvider;
consoleProvider.mTerminalExe.Set(gApp.mSettings.mWindowsTerminal);
consoleProvider.mWorkingDir.Set(gApp.mWorkspace.mDir);
mConsoleProvider.Attach();
}
public override void RemovedFromParent(Widget previousParent, WidgetWindow window)
{
}
public override void Update()
{
base.Update();
}
public void OpenDirectory(StringView path)
{
var consoleProvider = (BeefConConsoleProvider)mConsoleProvider;
consoleProvider.mWorkingDir.Set(path);
consoleProvider.Detach();
consoleProvider.Attach();
}
}

File diff suppressed because it is too large Load diff

View file

@ -328,7 +328,7 @@ bool CeDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
return false;
}
void CeDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled)
void CeDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags)
{
}
@ -337,6 +337,10 @@ bool CeDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
return false;
}
void CeDebugger::GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr)
{
}
void CeDebugger::Run()
{
}

View file

@ -314,8 +314,9 @@ public:
virtual void OutputRawMessage(const StringImpl& msg) override;
virtual int GetAddrSize() override;
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) override;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags) override;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
virtual void GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr) override;
virtual void Run() override;
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;
virtual void InitiateHotResolve(DbgHotResolveFlags flags) override;

View file

@ -754,7 +754,7 @@ BF_EXPORT int BF_CALLTYPE Debugger_GetAddrSize()
return gDebugger->GetAddrSize();
}
BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char* targetPath, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize, bool hotSwapEnabled)
BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char* targetPath, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags)
{
BF_ASSERT(gDebugger == NULL);
@ -784,7 +784,7 @@ BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char*
envBlock.Insert(0, (uint8*)envBlockPtr, envBlockSize);
}
gDebugger->OpenFile(launchPath, targetPath, args, workingDir, envBlock, hotSwapEnabled);
gDebugger->OpenFile(launchPath, targetPath, args, workingDir, envBlock, hotSwapEnabled, openFileFlags);
return true;
}
@ -911,6 +911,12 @@ BF_EXPORT bool BF_CALLTYPE Debugger_Attach(int processId, BfDbgAttachFlags attac
return false;
}
BF_EXPORT void Debugger_GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr)
{
if (gDebugger != NULL)
gDebugger->GetStdHandles(outStdIn, outStdOut, outStdErr);
}
BF_EXPORT void BF_CALLTYPE Debugger_Run()
{
gDebugger->Run();

View file

@ -200,6 +200,14 @@ enum DbgMemoryFlags : uint8
DbgMemoryFlags_Execute = 4
};
enum DbgOpenFileFlags : uint8
{
DbgOpenFileFlag_None = 0,
DbgOpenFileFlag_RedirectStdInput = 1,
DbgOpenFileFlag_RedirectStdOutput = 2,
DbgOpenFileFlag_RedirectStdError = 4
};
class DbgModuleMemoryCache
{
public:
@ -266,8 +274,9 @@ public:
virtual void OutputRawMessage(const StringImpl& msg) = 0;
virtual int GetAddrSize() = 0;
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) = 0;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) = 0;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags) = 0;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) = 0;
virtual void GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr) = 0;
virtual void Run() = 0;
virtual bool HasLoadedTargetBinary() { return true; }
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) = 0;

View file

@ -79,6 +79,11 @@ static void FilterThreadName(String& name)
}
}
static bool IsHandleValid(HANDLE handle)
{
return (handle != NULL) && (handle != INVALID_HANDLE_VALUE);
}
//////////////////////////////////////////////////////////////////////////
WdBreakpointCondition::~WdBreakpointCondition()
@ -508,6 +513,9 @@ WinDebugger::WinDebugger(DebugManager* debugManager) : mDbgSymSrv(this)
mOrigStepType = StepType_None;
mLastValidStepIntoPC = 0;
mActiveSymSrvRequest = NULL;
mStdInputPipe = INVALID_HANDLE_VALUE;
mStdOutputPipe = INVALID_HANDLE_VALUE;
mStdErrorPipe = INVALID_HANDLE_VALUE;
mStoredReturnValueAddr = 0;
#ifdef BF_DBG_32
@ -528,6 +536,8 @@ WinDebugger::WinDebugger(DebugManager* debugManager) : mDbgSymSrv(this)
mDbgProcessId = 0;
mDbgHeapData = NULL;
mIsPartialCallStack = true;
mHotSwapEnabled = false;
mOpenFileFlags = DbgOpenFileFlag_None;
for (int i = 0; i < 4; i++)
{
@ -919,7 +929,7 @@ void WinDebugger::DebugThreadProc()
if (!IsMiniDumpDebugger())
{
if (!DoOpenFile(mLaunchPath, mArgs, mWorkingDir, mEnvBlock))
if (!DoOpenFile(mLaunchPath, mArgs, mWorkingDir, mEnvBlock, mOpenFileFlags))
{
if (mDbgProcessId != 0)
OutputRawMessage("error Unable to attach to process");
@ -1005,7 +1015,7 @@ bool WinDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
return canRead;
}
void WinDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled)
void WinDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags)
{
BF_ASSERT(!mIsRunning);
mLaunchPath = launchPath;
@ -1014,6 +1024,7 @@ void WinDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targe
mWorkingDir = workingDir;
mEnvBlock = envBlock;
mHotSwapEnabled = hotSwapEnabled;
mOpenFileFlags = openFileFlags;
mDebugTarget = new DebugTarget(this);
}
@ -1059,6 +1070,29 @@ bool WinDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
return true;
}
void WinDebugger::GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
if ((outStdIn != NULL) && (IsHandleValid(mStdInputPipe)))
{
*outStdIn = BfpFile_GetFromHandle((intptr)mStdInputPipe, NULL);
mStdInputPipe = 0;
}
if ((outStdOut != NULL) && (IsHandleValid(mStdOutputPipe)))
{
*outStdOut = BfpFile_GetFromHandle((intptr)mStdOutputPipe, NULL);
mStdOutputPipe = 0;
}
if ((outStdErr != NULL) && (IsHandleValid(mStdErrorPipe)))
{
*outStdErr = BfpFile_GetFromHandle((intptr)mStdErrorPipe, NULL);
mStdErrorPipe = 0;
}
}
void WinDebugger::Run()
{
mIsRunning = true;
@ -1262,7 +1296,50 @@ String WinDebugger::GetDbgAllocInfo()
return result;
}
bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
static bool CreatePipeWithSecurityAttributes(HANDLE& hReadPipe, HANDLE& hWritePipe, SECURITY_ATTRIBUTES* lpPipeAttributes, int32 nSize)
{
hReadPipe = 0;
hWritePipe = 0;
bool ret = ::CreatePipe(&hReadPipe, &hWritePipe, lpPipeAttributes, nSize);
if (!ret || (hReadPipe == INVALID_HANDLE_VALUE) || (hWritePipe == INVALID_HANDLE_VALUE))
return false;
return true;
}
static bool CreatePipe(HANDLE& parentHandle, HANDLE& childHandle, bool parentInputs)
{
SECURITY_ATTRIBUTES securityAttributesParent = { 0 };
securityAttributesParent.bInheritHandle = 1;
HANDLE hTmp = INVALID_HANDLE_VALUE;
if (parentInputs)
CreatePipeWithSecurityAttributes(childHandle, hTmp, &securityAttributesParent, 0);
else
CreatePipeWithSecurityAttributes(hTmp, childHandle, &securityAttributesParent, 0);
HANDLE dupHandle = 0;
// Duplicate the parent handle to be non-inheritable so that the child process
// doesn't have access. This is done for correctness sake, exact reason is unclear.
// One potential theory is that child process can do something brain dead like
// closing the parent end of the pipe and there by getting into a blocking situation
// as parent will not be draining the pipe at the other end anymore.
if (!::DuplicateHandle(GetCurrentProcess(), hTmp,
GetCurrentProcess(), &dupHandle,
0, false, DUPLICATE_SAME_ACCESS))
{
return false;
}
parentHandle = dupHandle;
if (hTmp != INVALID_HANDLE_VALUE)
::CloseHandle(hTmp);
return true;
}
bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, DbgOpenFileFlags openFileFlags)
{
BP_ZONE("WinDebugger::DoOpenFile");
@ -1274,6 +1351,33 @@ bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args,
si.cb = sizeof(si);
ZeroMemory(&mProcessInfo, sizeof(mProcessInfo));
DWORD flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_DEFAULT_ERROR_MODE;
BOOL inheritHandles = false;
// set up the streams
if ((openFileFlags & (DbgOpenFileFlag_RedirectStdInput | DbgOpenFileFlag_RedirectStdOutput | DbgOpenFileFlag_RedirectStdError)) != 0)
{
if ((openFileFlags & DbgOpenFileFlag_RedirectStdInput) != 0)
CreatePipe(mStdInputPipe, si.hStdInput, true);
else if (::GetConsoleWindow() != NULL)
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
else
si.hStdInput = INVALID_HANDLE_VALUE;
if ((openFileFlags & DbgOpenFileFlag_RedirectStdOutput) != 0)
CreatePipe(mStdOutputPipe, si.hStdOutput, false);
else
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if ((openFileFlags & DbgOpenFileFlag_RedirectStdError) != 0)
CreatePipe(mStdErrorPipe, si.hStdError, false);
else
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
flags |= CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESTDHANDLES;
inheritHandles = true;
}
if (mDbgProcessId != 0)
{
BOOL success = ::DebugActiveProcess(mDbgProcessId);
@ -1288,7 +1392,6 @@ bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args,
UTF16String envW;
DWORD flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_DEFAULT_ERROR_MODE;
void* envPtr = NULL;
if (!envBlock.IsEmpty())
{
@ -1318,11 +1421,34 @@ bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args,
cmdLine += args;
}
BOOL worked = CreateProcessW(NULL, (WCHAR*)UTF8Decode(cmdLine).c_str(), NULL, NULL, FALSE,
BOOL worked = CreateProcessW(NULL, (WCHAR*)UTF8Decode(cmdLine).c_str(), NULL, NULL, inheritHandles,
flags, envPtr, (WCHAR*)UTF8Decode(workingDir).c_str(), &si, &mProcessInfo);
if ((openFileFlags & DbgOpenFileFlag_RedirectStdInput) != 0)
::CloseHandle(si.hStdInput);
if ((openFileFlags & DbgOpenFileFlag_RedirectStdOutput) != 0)
::CloseHandle(si.hStdOutput);
if ((openFileFlags & DbgOpenFileFlag_RedirectStdError) != 0)
::CloseHandle(si.hStdError);
if (!worked)
{
if (IsHandleValid(mStdInputPipe))
{
::CloseHandle(mStdInputPipe);
mStdInputPipe = 0;
}
if (IsHandleValid(mStdOutputPipe))
{
::CloseHandle(mStdOutputPipe);
mStdOutputPipe = 0;
}
if (IsHandleValid(mStdErrorPipe))
{
::CloseHandle(mStdErrorPipe);
mStdErrorPipe = 0;
}
auto lastError = ::GetLastError();
if (lastError == ERROR_DIRECTORY)
{
@ -1503,6 +1629,18 @@ void WinDebugger::Detach()
mBreakpointAddrMap.Clear();
gDebugUpdateCnt = 0;
if (IsHandleValid(mStdInputPipe))
::CloseHandle(mStdInputPipe);
mStdInputPipe = INVALID_HANDLE_VALUE;
if (IsHandleValid(mStdOutputPipe))
::CloseHandle(mStdOutputPipe);
mStdOutputPipe = INVALID_HANDLE_VALUE;
if (IsHandleValid(mStdErrorPipe))
::CloseHandle(mStdErrorPipe);
mStdErrorPipe = INVALID_HANDLE_VALUE;
}
Profiler* WinDebugger::StartProfiling()
@ -2927,12 +3065,32 @@ static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
if (processId != ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId)
return TRUE;
while (true)
{
HWND parentHWnd = GetParent(hwnd);
if (parentHWnd != NULL)
{
hwnd = parentHWnd;
continue;
}
SetForegroundWindow(hwnd);
break;
}
return TRUE;
}
void WinDebugger::ForegroundTarget()
{
HWND hwnd = ::GetForegroundWindow();
if (hwnd != INVALID_HANDLE_VALUE)
{
DWORD processId = 0;
GetWindowThreadProcessId(hwnd, &processId);
if (processId == ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId)
return; // Already good
}
EnumWindows(WdEnumWindowsProc, 0);
}

View file

@ -389,6 +389,7 @@ public:
String mArgs;
String mWorkingDir;
bool mHotSwapEnabled;
DbgOpenFileFlags mOpenFileFlags;
Array<uint8> mEnvBlock;
DebugTarget* mEmptyDebugTarget;
DebugTarget* mDebugTarget;
@ -400,6 +401,11 @@ public:
DWORD mDbgProcessId;
HANDLE mDbgProcessHandle;
HANDLE mDbgThreadHandle;
HANDLE mStdInputPipe;
HANDLE mStdOutputPipe;
HANDLE mStdErrorPipe;
bool mIsDebuggerWaiting;
bool mWantsDebugContinue;
bool mNeedsRehupBreakpoints;
@ -553,7 +559,7 @@ public:
void ModuleChanged(DbgModule* dbgModule);
bool DoUpdate();
void DebugThreadProc();
bool DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock);
bool DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, DbgOpenFileFlags openFileFlags);
DbgTypedValue GetRegister(const StringImpl& regName, DbgLanguage language, CPURegisters* registers, Array<RegForm>* regForms = NULL);
void FixupLineData(DbgCompileUnit* compileUnit);
@ -581,8 +587,9 @@ public:
virtual void OutputRawMessage(const StringImpl& msg) override;
virtual int GetAddrSize() override;
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) override;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags) override;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
virtual void GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr) override;
virtual void Run() override;
virtual bool HasLoadedTargetBinary() override;
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;