property bool canBeMonitored { get { return (this == hit || this == breakEvent || this == signal || this == stepEnd || this == functionEnd); } };
};
enum DebuggerAction { none, internal, restart, stop, selectFrame }; //, bpValidation
+enum DebuggerReason
+{
+ unknown, endSteppingRange, functionFinished, signalReceived, breakpointHit
+ //watchpointTrigger, readWatchpointTrigger, accessWatchpointTrigger, watchpointScope, locationReached,
+ //exited, exitedNormally, exitedSignalled;
+};
enum BreakpointType
{
none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor, internalModuleLoad;
property bool isUser { get { return (this == user || this == runToCursor); } };
};
enum DebuggerEvaluationError { none, symbolNotFound, memoryCantBeRead, unknown };
+enum DebuggerUserAction { none, start, resume, _break, stop, restart, selectThread, selectFrame, stepInto, stepOver, stepOut, runToCursor };
FileDialog debuggerFileDialog { type = selectDir };
char * targetDir;
char * targetFile;
+ DebuggerUserAction userAction;
DebuggerState state;
DebuggerEvent event;
DebuggerAction breakType;
void Resume()
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::Resume");
+ userAction = resume;
GdbExecContinue(true);
}
void Break()
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::Break");
+ userAction = _break;
if(state == running)
{
if(targetProcessId)
void Stop()
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::Stop");
+ userAction = stop;
switch(state)
{
case running:
void Restart(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool useValgrind)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::Restart");
+ userAction = restart;
if(StartSession(compiler, config, bitDepth, useValgrind, true, false, false/*, false*/) == loaded)
GdbExecRun();
}
void SelectThread(int thread)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::SelectThread(", thread, ")");
+ userAction = selectThread;
if(state == stopped)
{
if(thread != activeThread)
void SelectFrame(int frame)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::SelectFrame(", frame, ")");
+ userAction = selectFrame; // not always user action, right? doesn't matter for now.
if(state == stopped)
{
if(frame != activeFrameLevel || !codeEditor || !codeEditor.visible)
}
this.ignoreBreakpoints = ignoreBreakpoints;
this.userBreakOnInternalBreakpoint = userBreakOnInternalBreakpoint;
- if(ignoreBreakpoints && (result == loaded || result == stopped))
- GdbBreakpointsDelete(false, false);
+ if(result == loaded || result == stopped)
+ GdbBreakpointsDelete(false, (userAction == stepOver || userAction == stepOut), ignoreBreakpoints);
}
return result;
}
void Start(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool useValgrind)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::Start()");
+ userAction = start;
if(StartSession(compiler, config, bitDepth, useValgrind, true, false, false/*, false*/) == loaded)
GdbExecRun();
}
void StepInto(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool useValgrind)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::StepInto()");
+ userAction = stepInto;
switch(StartSession(compiler, config, bitDepth, useValgrind, false, true, false/*, false*/))
{
case loaded: GdbExecRun(); break;
void StepOver(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool useValgrind, bool ignoreBreakpoints)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::StepOver()");
+ userAction = stepOver;
switch(StartSession(compiler, config, bitDepth, useValgrind, false, true, ignoreBreakpoints/*, false*/))
{
case loaded: GdbExecRun(); break;
void StepOut(bool ignoreBreakpoints)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::StepOut()");
+ userAction = stepOut;
if(state == stopped)
{
this.ignoreBreakpoints = ignoreBreakpoints;
- if(ignoreBreakpoints)
- GdbBreakpointsDelete(true, false);
- GdbExecFinish();
+ GdbBreakpointsDelete(true, true, ignoreBreakpoints);
+ if(frameCount > 1)
+ GdbExecFinish();
+ else
+ GdbExecContinue(true);
}
}
char relativeFilePath[MAX_LOCATION];
DebuggerState st = state;
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::RunToCursor()");
+ userAction = runToCursor;
//if(st == loaded)
//{
// ide.outputView.ShowClearSelectTab(debug);
//_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::GdbBreakpointsInsert()");
if(symbols)
{
- DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig, bitDepth);
- for(bp : sysBPs; !bp.inserted)
+ if(userAction != stepOut && (userAction != stepOver || state == loaded))
{
- bool insert = false;
- if(bp.type == internalModulesLoaded)
+ DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig, bitDepth);
+ for(bp : sysBPs; !bp.inserted)
{
- char path[MAX_LOCATION];
- char name[MAX_LOCATION];
- char fixedModuleName[MAX_FILENAME];
- char line[16384];
- int lineNumber;
- bool moduleLoadBlock = false;
- File f;
- ReplaceSpaces(fixedModuleName, ide.project.moduleName);
- snprintf(name, sizeof(name),"%s.main.ec", fixedModuleName);
- name[sizeof(name)-1] = 0;
- strcpy(path, ide.workspace.projectDir);
- PathCatSlash(path, objDir.dir);
- PathCatSlash(path, name);
- f = FileOpen(path, read);
- if(f)
+ bool insert = false;
+ if(bp.type == internalModulesLoaded)
{
- for(lineNumber = 1; !f.Eof(); lineNumber++)
+ char path[MAX_LOCATION];
+ char name[MAX_LOCATION];
+ char fixedModuleName[MAX_FILENAME];
+ char line[16384];
+ int lineNumber;
+ bool moduleLoadBlock = false;
+ File f;
+ ReplaceSpaces(fixedModuleName, ide.project.moduleName);
+ snprintf(name, sizeof(name),"%s.main.ec", fixedModuleName);
+ name[sizeof(name)-1] = 0;
+ strcpy(path, ide.workspace.projectDir);
+ PathCatSlash(path, objDir.dir);
+ PathCatSlash(path, name);
+ f = FileOpen(path, read);
+ if(f)
{
- if(f.GetLine(line, sizeof(line) - 1))
+ for(lineNumber = 1; !f.Eof(); lineNumber++)
{
- bool moduleLoadLine;
- TrimLSpaces(line, line);
- moduleLoadLine = !strncmp(line, "eModule_Load", strlen("eModule_Load"));
- if(!moduleLoadBlock && moduleLoadLine)
- moduleLoadBlock = true;
- else if(moduleLoadBlock && !moduleLoadLine && strlen(line) > 0)
- break;
+ if(f.GetLine(line, sizeof(line) - 1))
+ {
+ bool moduleLoadLine;
+ TrimLSpaces(line, line);
+ moduleLoadLine = !strncmp(line, "eModule_Load", strlen("eModule_Load"));
+ if(!moduleLoadBlock && moduleLoadLine)
+ moduleLoadBlock = true;
+ else if(moduleLoadBlock && !moduleLoadLine && strlen(line) > 0)
+ break;
+ }
}
+ if(!f.Eof())
+ {
+ char relative[MAX_LOCATION];
+ bp.absoluteFilePath = path;
+ MakePathRelative(path, ide.workspace.projectDir, relative);
+ bp.relativeFilePath = relative;
+ bp.line = lineNumber;
+ insert = true;
+ }
+ delete f;
}
- if(!f.Eof())
- {
- char relative[MAX_LOCATION];
- bp.absoluteFilePath = path;
- MakePathRelative(path, ide.workspace.projectDir, relative);
- bp.relativeFilePath = relative;
- bp.line = lineNumber;
- insert = true;
- }
- delete f;
}
- }
- else if(bp.type == internalModuleLoad)
- {
- if(modules)
+ else if(bp.type == internalModuleLoad)
{
- for(prj : ide.workspace.projects)
+ if(modules)
{
- if(!strcmp(prj.moduleName, "ecere"))
+ for(prj : ide.workspace.projects)
{
- ProjectNode node = prj.topNode.Find("instance.c", false);
- if(node)
+ if(!strcmp(prj.moduleName, "ecere"))
{
- char path[MAX_LOCATION];
- char relative[MAX_LOCATION];
- node.GetFullFilePath(path);
- bp.absoluteFilePath = path;
- MakePathRelative(path, prj.topNode.path, relative);
- bp.relativeFilePath = relative;
- insert = true;
- break;
+ ProjectNode node = prj.topNode.Find("instance.c", false);
+ if(node)
+ {
+ char path[MAX_LOCATION];
+ char relative[MAX_LOCATION];
+ node.GetFullFilePath(path);
+ bp.absoluteFilePath = path;
+ MakePathRelative(path, prj.topNode.path, relative);
+ bp.relativeFilePath = relative;
+ insert = true;
+ break;
+ }
}
}
}
}
+ else
+ insert = true;
+ if(insert)
+ SetBreakpoint(bp, false);
}
- else
- insert = true;
- if(insert)
- SetBreakpoint(bp, false);
+ delete objDir;
}
- delete objDir;
if(bpRunToCursor && !bpRunToCursor.inserted)
SetBreakpoint(bpRunToCursor, false);
return !breakpointError;
}
- void GdbBreakpointsDelete(bool deleteRunToCursor, bool deleteInternalBreakpoints)
+ void GdbBreakpointsDelete(bool deleteRunToCursor, bool deleteInternalBreakpoints, bool deleteUserBreakpoints)
{
_dpl2(_dpct, dplchan::debuggerCall, 0, "Debugger::GdbBreakpointsDelete(deleteRunToCursor(", deleteRunToCursor, "))");
if(symbols)
for(bp : sysBPs)
UnsetBreakpoint(bp);
}
- for(bp : ide.workspace.breakpoints)
- UnsetBreakpoint(bp);
+ if(deleteUserBreakpoints)
+ {
+ for(bp : ide.workspace.breakpoints)
+ UnsetBreakpoint(bp);
+ }
if(deleteRunToCursor && bpRunToCursor)
UnsetBreakpoint(bpRunToCursor);
}
{
if(targeted)
{
- GdbBreakpointsDelete(true, true);
+ GdbBreakpointsDelete(true, true, true);
GdbCommand(false, "file"); //GDB/MI Missing Implementation -target-detach
targeted = false;
symbols = true;
if(bpInternal.type == internalModulesLoaded)
modules = true;
if(!bpUser && !userBreakOnInternalBreakpoint)
- GdbExecContinue(false);
+ {
+ if(userAction == stepOut)//if(prevStopItem.reason == functionFinished)
+ StepOut(ignoreBreakpoints);
+ else
+ GdbExecContinue(false);
+ }
}
if(bpUser)
{
_dpl(0, "problem");
#endif
stopItem = GdbDataStop { };
+ stopItem.reason = breakpointHit;
for(i = tk+1; i < outTokens.count; i++)
{
_dpl(0, "problem");
#endif
stopItem = GdbDataStop { };
+ stopItem.reason = endSteppingRange;
for(i = tk+1; i < outTokens.count; i++)
{
_dpl(0, "problem");
#endif
stopItem = GdbDataStop { };
- stopItem.reason = CopyString(reason);
+ stopItem.reason = functionFinished;
for(i = tk+1; i < outTokens.count; i++)
{
_dpl(0, "problem");
#endif
stopItem = GdbDataStop { };
- stopItem.reason = CopyString(reason);
+ stopItem.reason = signalReceived;
for(i = tk+1; i < outTokens.count; i++)
{
class GdbDataStop : struct
{
- char * reason;
+ DebuggerReason reason;
int threadid;
union
{
{
if(reason)
{
- if(!strcmp(reason, "signal-received"))
+ if(reason == signalReceived)
{
delete name;
delete meaning;
}
- else if(!strcmp(reason, "function-finished"))
+ else if(reason == functionFinished)
{
delete gdbResultVar;
delete returnValue;
}
- delete reason;
}
if(frame) frame.Free();
}