aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Weinhold <ingo_weinhold@gmx.de>2012-07-27 23:41:11 +0200
committerIngo Weinhold <ingo_weinhold@gmx.de>2012-07-27 23:42:01 +0200
commit8fe9f8b2d0e3c8f88406f5720a1d2027638c43b6 (patch)
treea993dccfca6480a0da020296b3ea43c98239eb79
parenteba38eb503254ad8fba4466c6b983b76c3510af1 (diff)
Debugger CLI: Move more stuff to and extend CliContexthrev44417
* Move the libedit interface there and provide nicer to use methods. * Also start adding utility methods for the input loop. It is going to manage all interactions of the input loop with outside events. * Fix the "quit" command. The user is now prompted what to do with the debugged team and the input loop thread avoids reentering the input loop.
-rw-r--r--src/apps/debugger/user_interface/cli/CliContext.cpp141
-rw-r--r--src/apps/debugger/user_interface/cli/CliContext.h31
-rw-r--r--src/apps/debugger/user_interface/cli/CliQuitCommand.cpp26
-rw-r--r--src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp56
-rw-r--r--src/apps/debugger/user_interface/cli/CommandLineUserInterface.h8
5 files changed, 204 insertions, 58 deletions
diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp
index cb099bf4ae..ad14f82919 100644
--- a/src/apps/debugger/user_interface/cli/CliContext.cpp
+++ b/src/apps/debugger/user_interface/cli/CliContext.cpp
@@ -6,27 +6,160 @@
#include "CliContext.h"
+#include <AutoLocker.h>
+
#include "UserInterface.h"
+// 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.
+// ATM only one CLI is possible in Debugger, so a static variable works well
+// enough. Should that ever change, we would need a thread-safe
+// EditLine* -> CliContext* map.
+static CliContext* sCurrentContext;
+
+
CliContext::CliContext()
:
+ fLock("CliContext"),
fTeam(NULL),
- fListener(NULL)
+ fListener(NULL),
+ fEditLine(NULL),
+ fHistory(NULL),
+ fPrompt(NULL),
+ fBlockingSemaphore(-1),
+ fInputLoopWaiting(false),
+ fTerminating(false)
{
+ sCurrentContext = this;
}
+CliContext::~CliContext()
+{
+ Cleanup();
+ sCurrentContext = NULL;
+}
-void
+
+status_t
CliContext::Init(Team* team, UserInterfaceListener* listener)
{
fTeam = team;
fListener = listener;
+
+ status_t error = fLock.InitCheck();
+ if (error != B_OK)
+ return error;
+
+ fBlockingSemaphore = create_sem(0, "CliContext block");
+ if (fBlockingSemaphore < 0)
+ return fBlockingSemaphore;
+
+ fEditLine = el_init("Debugger", stdin, stdout, stderr);
+ if (fEditLine == NULL)
+ return B_ERROR;
+
+ fHistory = history_init();
+ if (fHistory == NULL)
+ return B_ERROR;
+
+ HistEvent historyEvent;
+ history(fHistory, &historyEvent, H_SETSIZE, 100);
+
+ el_set(fEditLine, EL_HIST, &history, fHistory);
+ el_set(fEditLine, EL_EDITOR, "emacs");
+ el_set(fEditLine, EL_PROMPT, &_GetPrompt);
+
+ return B_OK;
}
void
-CliContext::QuitSession()
+CliContext::Cleanup()
+{
+ Terminating();
+
+ if (fEditLine != NULL) {
+ el_end(fEditLine);
+ fEditLine = NULL;
+ }
+
+ if (fHistory != NULL) {
+ history_end(fHistory);
+ fHistory = NULL;
+ }
+}
+
+
+void
+CliContext::Terminating()
+{
+ AutoLocker<BLocker> locker(fLock);
+
+ fTerminating = true;
+
+ if (fBlockingSemaphore >= 0) {
+ delete_sem(fBlockingSemaphore);
+ fBlockingSemaphore = -1;
+ }
+
+ fInputLoopWaiting = false;
+
+ // TODO: Signal the input loop, should it be in PromptUser()!
+}
+
+
+const char*
+CliContext::PromptUser(const char* prompt)
+{
+ fPrompt = prompt;
+
+ int count;
+ const char* line = el_gets(fEditLine, &count);
+
+ fPrompt = NULL;
+
+ return line;
+}
+
+
+void
+CliContext::AddLineToInputHistory(const char* line)
+{
+ HistEvent historyEvent;
+ history(fHistory, &historyEvent, H_ENTER, line);
+}
+
+
+void
+CliContext::QuitSession(bool killTeam)
+{
+ AutoLocker<BLocker> locker(fLock);
+
+ sem_id blockingSemaphore = fBlockingSemaphore;
+ fInputLoopWaiting = true;
+
+ locker.Unlock();
+
+ fListener->UserInterfaceQuitRequested(
+ killTeam
+ ? UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM
+ : UserInterfaceListener::QUIT_OPTION_ASK_RESUME_TEAM);
+
+ while (acquire_sem(blockingSemaphore) == B_INTERRUPTED) {
+ }
+}
+
+
+void
+CliContext::WaitForThreadOrUser()
+{
+ // TODO:...
+}
+
+
+/*static*/ const char*
+CliContext::_GetPrompt(EditLine* editLine)
{
- fListener->UserInterfaceQuitRequested();
+ return sCurrentContext != NULL ? sCurrentContext->fPrompt : NULL;
}
diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h
index 93d06af3fa..e3617fe6f7 100644
--- a/src/apps/debugger/user_interface/cli/CliContext.h
+++ b/src/apps/debugger/user_interface/cli/CliContext.h
@@ -6,6 +6,13 @@
#define CLI_CONTEXT_H
+#include <sys/cdefs.h>
+ // Needed in histedit.h.
+#include <histedit.h>
+
+#include <Locker.h>
+
+
class Team;
class UserInterfaceListener;
@@ -13,18 +20,38 @@ class UserInterfaceListener;
class CliContext {
public:
CliContext();
+ ~CliContext();
- void Init(Team* team,
+ status_t Init(Team* team,
UserInterfaceListener* listener);
+ void Cleanup();
+
+ void Terminating();
+
+ // service methods for the input loop thread follow
Team* GetTeam() const { return fTeam; }
- void QuitSession();
+ const char* PromptUser(const char* prompt);
+ void AddLineToInputHistory(const char* line);
+
+ void QuitSession(bool killTeam);
+ void WaitForThreadOrUser();
+
+private:
+ static const char* _GetPrompt(EditLine* editLine);
private:
+ BLocker fLock;
Team* fTeam;
UserInterfaceListener* fListener;
+ EditLine* fEditLine;
+ History* fHistory;
+ const char* fPrompt;
+ sem_id fBlockingSemaphore;
+ bool fInputLoopWaiting;
+ volatile bool fTerminating;
};
diff --git a/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp b/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
index d3a8cb83f7..49d8d825da 100644
--- a/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
+++ b/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
@@ -6,6 +6,8 @@
#include "CliQuitCommand.h"
+#include <String.h>
+
#include "CliContext.h"
@@ -21,5 +23,27 @@ CliQuitCommand::CliQuitCommand()
void
CliQuitCommand::Execute(int argc, const char* const* argv, CliContext& context)
{
- context.QuitSession();
+ // Ask the user what to do with the debugged team.
+ printf("Kill or resume the debugged team?\n");
+ for (;;) {
+ const char* line = context.PromptUser("(k)ill, (r)esume, (c)ancel? ");
+ if (line == NULL)
+ return;
+
+ BString trimmedLine(line);
+ trimmedLine.Trim();
+
+ if (trimmedLine == "k") {
+ context.QuitSession(true);
+ break;
+ }
+
+ if (trimmedLine == "r") {
+ context.QuitSession(false);
+ break;
+ }
+
+ if (trimmedLine == "d")
+ break;
+ }
}
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
index 9e27749494..c00111291f 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
@@ -20,11 +20,7 @@
#include "CliThreadsCommand.h"
-static const char*
-get_prompt(EditLine* editLine)
-{
- return "debugger> ";
-}
+static const char* kDebuggerPrompt = "debugger> ";
// #pragma mark - CommandEntry
@@ -83,8 +79,6 @@ private:
CommandLineUserInterface::CommandLineUserInterface()
:
fCommands(20, true),
- fEditLine(NULL),
- fHistory(NULL),
fShowSemaphore(-1),
fShown(false),
fTerminating(false)
@@ -96,12 +90,6 @@ CommandLineUserInterface::~CommandLineUserInterface()
{
if (fShowSemaphore >= 0)
delete_sem(fShowSemaphore);
-
- if (fEditLine != NULL)
- el_end(fEditLine);
-
- if (fHistory != NULL)
- history_end(fHistory);
}
@@ -115,9 +103,11 @@ CommandLineUserInterface::ID() const
status_t
CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener)
{
- fContext.Init(team, listener);
+ status_t error = fContext.Init(team, listener);
+ if (error != B_OK)
+ return error;
- status_t error = _RegisterCommands();
+ error = _RegisterCommands();
if (error != B_OK)
return error;
@@ -125,21 +115,6 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener)
if (fShowSemaphore < 0)
return fShowSemaphore;
- fEditLine = el_init("Debugger", stdin, stdout, stderr);
- if (fEditLine == NULL)
- return B_ERROR;
-
- fHistory = history_init();
- if (fHistory == NULL)
- return B_ERROR;
-
- HistEvent historyEvent;
- history(fHistory, &historyEvent, H_SETSIZE, 100);
-
- el_set(fEditLine, EL_HIST, &history, fHistory);
- el_set(fEditLine, EL_EDITOR, "emacs");
- el_set(fEditLine, EL_PROMPT, &get_prompt);
-
return B_OK;
}
@@ -158,7 +133,7 @@ CommandLineUserInterface::Terminate()
fTerminating = true;
if (fShown) {
- // TODO: Signal the thread so it wakes up!
+ fContext.Terminating();
// Wait for input loop to finish.
while (acquire_sem(fShowSemaphore) == B_INTERRUPTED) {
@@ -169,15 +144,7 @@ CommandLineUserInterface::Terminate()
fShowSemaphore = -1;
}
- if (fEditLine != NULL) {
- el_end(fEditLine);
- fEditLine = NULL;
- }
-
- if (fHistory != NULL) {
- history_end(fHistory);
- fHistory = NULL;
- }
+ fContext.Cleanup();
}
@@ -241,9 +208,11 @@ status_t
CommandLineUserInterface::_InputLoop()
{
while (!fTerminating) {
+ // Wait for a thread or Ctrl-C.
+ fContext.WaitForThreadOrUser();
+
// read a command line
- int count;
- const char* line = el_gets(fEditLine, &count);
+ const char* line = fContext.PromptUser(kDebuggerPrompt);
if (line == NULL)
break;
@@ -269,8 +238,7 @@ CommandLineUserInterface::_InputLoop()
continue;
// add line to history
- HistEvent historyEvent;
- history(fHistory, &historyEvent, H_ENTER, line);
+ fContext.AddLineToInputHistory(line);
// execute command
_ExecuteCommand(args.ArgumentCount(), args.Arguments());
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
index fb5da34da9..736429b0b4 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
@@ -7,10 +7,6 @@
#define COMMAND_LINE_USER_INTERFACE_H
-#include <sys/cdefs.h>
- // Needed in histedit.h.
-#include <histedit.h>
-
#include <ObjectList.h>
#include <String.h>
@@ -73,11 +69,9 @@ private:
private:
CliContext fContext;
CommandList fCommands;
- EditLine* fEditLine;
- History* fHistory;
sem_id fShowSemaphore;
bool fShown;
- bool fTerminating;
+ volatile bool fTerminating;
};