Various improvements to CliContext.
- CliContext now tracks the current stack trace and frame if applicable. - CliContext now carries a value node manager. This allows it to track the variables in the currently active frame.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, [email protected].
|
||||||
* Copyright 2012, Ingo Weinhold, [email protected].
|
* Copyright 2012, Ingo Weinhold, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -9,8 +10,9 @@
|
|||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "StackTrace.h"
|
||||||
#include "UserInterface.h"
|
#include "UserInterface.h"
|
||||||
|
#include "ValueNodeManager.h"
|
||||||
|
|
||||||
// NOTE: This is a simple work-around for EditLine not having any kind of user
|
// NOTE: This is a simple work-around for EditLine not having any kind of user
|
||||||
// data field. Hence in _GetPrompt() we don't have access to the context object.
|
// data field. Hence in _GetPrompt() we don't have access to the context object.
|
||||||
@@ -55,6 +57,7 @@ CliContext::CliContext()
|
|||||||
fLock("CliContext"),
|
fLock("CliContext"),
|
||||||
fTeam(NULL),
|
fTeam(NULL),
|
||||||
fListener(NULL),
|
fListener(NULL),
|
||||||
|
fNodeManager(NULL),
|
||||||
fEditLine(NULL),
|
fEditLine(NULL),
|
||||||
fHistory(NULL),
|
fHistory(NULL),
|
||||||
fPrompt(NULL),
|
fPrompt(NULL),
|
||||||
@@ -63,7 +66,9 @@ CliContext::CliContext()
|
|||||||
fEventsOccurred(0),
|
fEventsOccurred(0),
|
||||||
fInputLoopWaiting(false),
|
fInputLoopWaiting(false),
|
||||||
fTerminating(false),
|
fTerminating(false),
|
||||||
fCurrentThread(NULL)
|
fCurrentThread(NULL),
|
||||||
|
fCurrentStackTrace(NULL),
|
||||||
|
fCurrentStackFrameIndex(-1)
|
||||||
{
|
{
|
||||||
sCurrentContext = this;
|
sCurrentContext = this;
|
||||||
}
|
}
|
||||||
@@ -110,6 +115,10 @@ CliContext::Init(Team* team, UserInterfaceListener* listener)
|
|||||||
el_set(fEditLine, EL_EDITOR, "emacs");
|
el_set(fEditLine, EL_EDITOR, "emacs");
|
||||||
el_set(fEditLine, EL_PROMPT, &_GetPrompt);
|
el_set(fEditLine, EL_PROMPT, &_GetPrompt);
|
||||||
|
|
||||||
|
fNodeManager = new(std::nothrow) ValueNodeManager();
|
||||||
|
if (fNodeManager == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +145,11 @@ CliContext::Cleanup()
|
|||||||
fTeam->RemoveListener(this);
|
fTeam->RemoveListener(this);
|
||||||
fTeam = NULL;
|
fTeam = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fNodeManager != NULL) {
|
||||||
|
fNodeManager->ReleaseReference();
|
||||||
|
fNodeManager = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -168,8 +182,25 @@ CliContext::SetCurrentThread(Thread* thread)
|
|||||||
|
|
||||||
fCurrentThread = thread;
|
fCurrentThread = thread;
|
||||||
|
|
||||||
if (fCurrentThread != NULL)
|
if (fCurrentStackTrace != NULL) {
|
||||||
|
fCurrentStackTrace->ReleaseReference();
|
||||||
|
fCurrentStackTrace = NULL;
|
||||||
|
fCurrentStackFrameIndex = -1;
|
||||||
|
fNodeManager->SetStackFrame(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCurrentThread != NULL) {
|
||||||
fCurrentThread->AcquireReference();
|
fCurrentThread->AcquireReference();
|
||||||
|
StackTrace* stackTrace = fCurrentThread->GetStackTrace();
|
||||||
|
// if the thread's stack trace has already been loaded,
|
||||||
|
// set it, otherwise we'll set it when we process the thread's
|
||||||
|
// stack trace changed event.
|
||||||
|
if (stackTrace != NULL) {
|
||||||
|
fCurrentStackTrace = stackTrace;
|
||||||
|
fCurrentStackTrace->AcquireReference();
|
||||||
|
SetCurrentStackFrameIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -186,6 +217,24 @@ CliContext::PrintCurrentThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CliContext::SetCurrentStackFrameIndex(int32 index)
|
||||||
|
{
|
||||||
|
AutoLocker<BLocker> locker(fLock);
|
||||||
|
|
||||||
|
if (fCurrentStackTrace == NULL)
|
||||||
|
return;
|
||||||
|
else if (index < 0 || index >= fCurrentStackTrace->CountFrames())
|
||||||
|
return;
|
||||||
|
|
||||||
|
fCurrentStackFrameIndex = index;
|
||||||
|
|
||||||
|
StackFrame* frame = fCurrentStackTrace->FrameAt(index);
|
||||||
|
if (frame != NULL)
|
||||||
|
fNodeManager->SetStackFrame(fCurrentThread, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
CliContext::PromptUser(const char* prompt)
|
CliContext::PromptUser(const char* prompt)
|
||||||
{
|
{
|
||||||
@@ -253,7 +302,7 @@ CliContext::WaitForThreadOrUser()
|
|||||||
|
|
||||||
if (stoppedThread != NULL) {
|
if (stoppedThread != NULL) {
|
||||||
if (fCurrentThread == NULL)
|
if (fCurrentThread == NULL)
|
||||||
fCurrentThread = stoppedThread;
|
SetCurrentThread(stoppedThread);
|
||||||
|
|
||||||
_SignalInputLoop(EVENT_THREAD_STOPPED);
|
_SignalInputLoop(EVENT_THREAD_STOPPED);
|
||||||
}
|
}
|
||||||
@@ -300,6 +349,13 @@ CliContext::ProcessPendingEvents()
|
|||||||
printf("[thread stopped: %" B_PRId32 " \"%s\"]\n",
|
printf("[thread stopped: %" B_PRId32 " \"%s\"]\n",
|
||||||
thread->ID(), thread->Name());
|
thread->ID(), thread->Name());
|
||||||
break;
|
break;
|
||||||
|
case EVENT_THREAD_STACK_TRACE_CHANGED:
|
||||||
|
if (thread == fCurrentThread) {
|
||||||
|
fCurrentStackTrace = thread->GetStackTrace();
|
||||||
|
fCurrentStackTrace->AcquireReference();
|
||||||
|
SetCurrentStackFrameIndex(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,6 +391,19 @@ CliContext::ThreadStateChanged(const Team::ThreadEvent& threadEvent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent)
|
||||||
|
{
|
||||||
|
if (threadEvent.GetThread()->State() != THREAD_STATE_STOPPED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_QueueEvent(
|
||||||
|
new(std::nothrow) Event(EVENT_THREAD_STACK_TRACE_CHANGED,
|
||||||
|
threadEvent.GetThread()));
|
||||||
|
_SignalInputLoop(EVENT_THREAD_STACK_TRACE_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CliContext::_QueueEvent(Event* event)
|
CliContext::_QueueEvent(Event* event)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,18 +15,22 @@
|
|||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
|
||||||
|
|
||||||
|
class StackFrame;
|
||||||
|
class StackTrace;
|
||||||
class Team;
|
class Team;
|
||||||
class UserInterfaceListener;
|
class UserInterfaceListener;
|
||||||
|
class ValueNodeManager;
|
||||||
|
|
||||||
|
|
||||||
class CliContext : private Team::Listener {
|
class CliContext : private Team::Listener {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
EVENT_QUIT = 0x01,
|
EVENT_QUIT = 0x01,
|
||||||
EVENT_USER_INTERRUPT = 0x02,
|
EVENT_USER_INTERRUPT = 0x02,
|
||||||
EVENT_THREAD_ADDED = 0x04,
|
EVENT_THREAD_ADDED = 0x04,
|
||||||
EVENT_THREAD_REMOVED = 0x08,
|
EVENT_THREAD_REMOVED = 0x08,
|
||||||
EVENT_THREAD_STOPPED = 0x10,
|
EVENT_THREAD_STOPPED = 0x10,
|
||||||
|
EVENT_THREAD_STACK_TRACE_CHANGED = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -46,12 +50,20 @@ public:
|
|||||||
Team* GetTeam() const { return fTeam; }
|
Team* GetTeam() const { return fTeam; }
|
||||||
UserInterfaceListener* GetUserInterfaceListener() const
|
UserInterfaceListener* GetUserInterfaceListener() const
|
||||||
{ return fListener; }
|
{ return fListener; }
|
||||||
|
ValueNodeManager* GetValueNodeManager() const
|
||||||
|
{ return fNodeManager; }
|
||||||
|
StackTrace* GetStackTrace() const
|
||||||
|
{ return fCurrentStackTrace; }
|
||||||
|
|
||||||
Thread* CurrentThread() const { return fCurrentThread; }
|
Thread* CurrentThread() const { return fCurrentThread; }
|
||||||
thread_id CurrentThreadID() const;
|
thread_id CurrentThreadID() const;
|
||||||
void SetCurrentThread(Thread* thread);
|
void SetCurrentThread(Thread* thread);
|
||||||
void PrintCurrentThread();
|
void PrintCurrentThread();
|
||||||
|
|
||||||
|
int32 CurrentStackFrameIndex() const
|
||||||
|
{ return fCurrentStackFrameIndex; }
|
||||||
|
void SetCurrentStackFrameIndex(int32 index);
|
||||||
|
|
||||||
const char* PromptUser(const char* prompt);
|
const char* PromptUser(const char* prompt);
|
||||||
void AddLineToInputHistory(const char* line);
|
void AddLineToInputHistory(const char* line);
|
||||||
|
|
||||||
@@ -72,6 +84,8 @@ private:
|
|||||||
|
|
||||||
virtual void ThreadStateChanged(
|
virtual void ThreadStateChanged(
|
||||||
const Team::ThreadEvent& event);
|
const Team::ThreadEvent& event);
|
||||||
|
virtual void ThreadStackTraceChanged(
|
||||||
|
const Team::ThreadEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _QueueEvent(Event* event);
|
void _QueueEvent(Event* event);
|
||||||
@@ -86,6 +100,7 @@ private:
|
|||||||
BLocker fLock;
|
BLocker fLock;
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
UserInterfaceListener* fListener;
|
UserInterfaceListener* fListener;
|
||||||
|
ValueNodeManager* fNodeManager;
|
||||||
EditLine* fEditLine;
|
EditLine* fEditLine;
|
||||||
History* fHistory;
|
History* fHistory;
|
||||||
const char* fPrompt;
|
const char* fPrompt;
|
||||||
@@ -96,6 +111,8 @@ private:
|
|||||||
volatile bool fTerminating;
|
volatile bool fTerminating;
|
||||||
|
|
||||||
Thread* fCurrentThread;
|
Thread* fCurrentThread;
|
||||||
|
StackTrace* fCurrentStackTrace;
|
||||||
|
int32 fCurrentStackFrameIndex;
|
||||||
|
|
||||||
EventList fPendingEvents;
|
EventList fPendingEvents;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user