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:
Rene Gollent
2012-12-16 22:03:35 -05:00
parent 74f911be74
commit 1325ad5fe8
2 changed files with 95 additions and 9 deletions
@@ -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;
}; };