[haiku-commits] haiku: hrev44469 - src/apps/debugger/user_interface/cli

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 5 Aug 2012 01:07:34 +0200 (CEST)

hrev44469 adds 5 changesets to branch 'master'
old head: 147d65c26dad4ac6db6c2e9936d40382434ce065
new head: 9b008d31ffa35bb2c98bb2accf83e16fb7f2f9ad

----------------------------------------------------------------------------

a7580a8: Debugger: Add CliCommand::PrintUsage()

d458618: Debugger CLI: Improve "help" command
  
  Given a command name it prints the command's usage.

59dbbd1: Debugger: CliQuitCommand: Fix cancel shortcut

86b1039: Debugger CliContext: More event handling, current thread
  
  * Introduce the notion of a current thread. That's the one certain
    commands will target (by default).
  * Add more event handling in CliContext. There's now a queue of pending
    events which are printed in the input loop at convenient times to
    inform the user about what happened (new/deleted/stopped threads,
    etc.).

9b008d3: Debugger CLI: Add a bunch of new commands
  
  * "thread": prints/sets the current thread.
  * "continue", "stop": continue/stop the current thread.
  * "sc"/"bt": Print a stack trace for the current thread. Very basic yet.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

16 files changed, 606 insertions(+), 30 deletions(-)
src/apps/debugger/Jamfile                          |    4 +
.../debugger/user_interface/cli/CliCommand.cpp     |   11 +
src/apps/debugger/user_interface/cli/CliCommand.h  |    2 +
.../debugger/user_interface/cli/CliContext.cpp     |  175 +++++++++++++++-
src/apps/debugger/user_interface/cli/CliContext.h  |   28 ++-
.../user_interface/cli/CliContinueCommand.cpp      |   45 ++++
.../user_interface/cli/CliContinueCommand.h        |   20 ++
.../debugger/user_interface/cli/CliQuitCommand.cpp |    2 +-
.../user_interface/cli/CliStackTraceCommand.cpp    |   86 ++++++++
.../user_interface/cli/CliStackTraceCommand.h      |   20 ++
.../debugger/user_interface/cli/CliStopCommand.cpp |   45 ++++
.../debugger/user_interface/cli/CliStopCommand.h   |   20 ++
.../user_interface/cli/CliThreadCommand.cpp        |   58 +++++
.../debugger/user_interface/cli/CliThreadCommand.h |   20 ++
.../cli/CommandLineUserInterface.cpp               |   97 +++++++--
.../user_interface/cli/CommandLineUserInterface.h  |    3 +-

############################################################################

Commit:      a7580a8299aacd5d09ce12534f0409144ccfd95a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a7580a8
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Aug  4 22:55:43 2012 UTC

Debugger: Add CliCommand::PrintUsage()

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/user_interface/cli/CliCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliCommand.cpp
index c83c8cf..2df3b38 100644
--- a/src/apps/debugger/user_interface/cli/CliCommand.cpp
+++ b/src/apps/debugger/user_interface/cli/CliCommand.cpp
@@ -6,6 +6,8 @@
 
 #include "CliCommand.h"
 
+#include <stdio.h>
+
 
 CliCommand::CliCommand(const char* summary, const char* usage)
        :
@@ -18,3 +20,12 @@ CliCommand::CliCommand(const char* summary, const char* 
usage)
 CliCommand::~CliCommand()
 {
 }
+
+
+void
+CliCommand::PrintUsage(const char* commandName) const
+{
+       printf("Usage: ");
+       printf(Usage(), commandName);
+       printf("\n");
+}
diff --git a/src/apps/debugger/user_interface/cli/CliCommand.h 
b/src/apps/debugger/user_interface/cli/CliCommand.h
index 2a65e19..d04d235 100644
--- a/src/apps/debugger/user_interface/cli/CliCommand.h
+++ b/src/apps/debugger/user_interface/cli/CliCommand.h
@@ -21,6 +21,8 @@ public:
                        const char*                     Summary() const { 
return fSummary; }
                        const char*                     Usage() const   { 
return fUsage; }
 
+                       void                            PrintUsage(const char* 
commandName) const;
+
        virtual void                            Execute(int argc, const char* 
const* argv,
                                                                        
CliContext& context) = 0;
 

############################################################################

Commit:      d4586180a674df11cbfbea1cf2ce527bf1ed4117
URL:         http://cgit.haiku-os.org/haiku/commit/?id=d458618
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Aug  4 22:57:57 2012 UTC

Debugger CLI: Improve "help" command

Given a command name it prints the command's usage.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
index c001112..0d1c92b 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
@@ -56,16 +56,23 @@ private:
 struct CommandLineUserInterface::HelpCommand : CliCommand {
        HelpCommand(CommandLineUserInterface* userInterface)
                :
-               CliCommand("print a list of all commands",
-                       "%s\n"
-                       "Prints a list of all commands."),
+               CliCommand("print help for a command or a list of all commands",
+                       "%s [ <command> ]\n"
+                       "Prints help for command <command>, if given, or a list 
of all "
+                               "commands\n"
+                       "otherwise."),
                fUserInterface(userInterface)
        {
        }
 
        virtual void Execute(int argc, const char* const* argv, CliContext& 
context)
        {
-               fUserInterface->_PrintHelp();
+               if (argc > 2) {
+                       PrintUsage(argv[0]);
+                       return;
+               }
+
+               fUserInterface->_PrintHelp(argc == 2 ? argv[1] : NULL);
        }
 
 private:
@@ -282,33 +289,63 @@ CommandLineUserInterface::_RegisterCommand(const BString& 
name,
 void
 CommandLineUserInterface::_ExecuteCommand(int argc, const char* const* argv)
 {
-       const char* commandName = argv[0];
+       CommandEntry* commandEntry = _FindCommand(argv[0]);
+       if (commandEntry != NULL)
+               commandEntry->Command()->Execute(argc, argv, fContext);
+}
+
+
+CommandLineUserInterface::CommandEntry*
+CommandLineUserInterface::_FindCommand(const char* commandName)
+{
        size_t commandNameLength = strlen(commandName);
 
-       CommandEntry* firstEntry = NULL;
+       // try to find an exact match first
+       CommandEntry* commandEntry = NULL;
        for (int32 i = 0; CommandEntry* entry = fCommands.ItemAt(i); i++) {
-               if (entry->Name().Compare(commandName, commandNameLength) == 0) 
{
-                       if (firstEntry != NULL) {
-                               printf("Ambiguous command \"%s\".\n", 
commandName);
-                               return;
-                       }
+               if (entry->Name() == commandName) {
+                       commandEntry = entry;
+                       break;
+               }
+       }
 
-                       firstEntry = entry;
+       // If nothing found yet, try partial matches, but only, if they are
+       // unambiguous.
+       if (commandEntry == NULL) {
+               for (int32 i = 0; CommandEntry* entry = fCommands.ItemAt(i); 
i++) {
+                       if (entry->Name().Compare(commandName, 
commandNameLength) == 0) {
+                               if (commandEntry != NULL) {
+                                       printf("Error: Ambiguous command 
\"%s\".\n", commandName);
+                                       return NULL;
+                               }
+
+                               commandEntry = entry;
+                       }
                }
        }
 
-       if (firstEntry == NULL) {
-               printf("Unknown command \"%s\".\n", commandName);
-               return;
+       if (commandEntry == NULL) {
+               printf("Error: Unknown command \"%s\".\n", commandName);
+               return NULL;
        }
 
-       firstEntry->Command()->Execute(argc, argv, fContext);
+       return commandEntry;
 }
 
 
 void
-CommandLineUserInterface::_PrintHelp()
+CommandLineUserInterface::_PrintHelp(const char* commandName)
 {
+       // If a command name is given, print the usage for that one.
+       if (commandName != NULL) {
+               CommandEntry* commandEntry = _FindCommand(commandName);
+               if (commandEntry != NULL)
+                       
commandEntry->Command()->PrintUsage(commandEntry->Name().String());
+               return;
+       }
+
+       // No command name given -- print a list of all commands.
+
        // determine longest command name
        int32 longestCommandName = 0;
        for (int32 i = 0; CommandEntry* entry = fCommands.ItemAt(i); i++) {
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
index 736429b..6bede60 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
@@ -64,7 +64,8 @@ private:
                                                                        
CliCommand* command);
                        void                            _ExecuteCommand(int 
argc,
                                                                        const 
char* const* argv);
-                       void                            _PrintHelp();
+                       CommandEntry*           _FindCommand(const char* 
commandName);
+                       void                            _PrintHelp(const char* 
commandName);
 
 private:
                        CliContext                      fContext;

############################################################################

Commit:      59dbbd147e91766f53359835c1a7448fac1e36c3
URL:         http://cgit.haiku-os.org/haiku/commit/?id=59dbbd1
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Aug  4 22:58:30 2012 UTC

Debugger: CliQuitCommand: Fix cancel shortcut

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
index 49d8d82..def9368 100644
--- a/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
+++ b/src/apps/debugger/user_interface/cli/CliQuitCommand.cpp
@@ -43,7 +43,7 @@ CliQuitCommand::Execute(int argc, const char* const* argv, 
CliContext& context)
                        break;
                }
 
-               if (trimmedLine == "d")
+               if (trimmedLine == "c")
                        break;
        }
 }

############################################################################

Commit:      86b1039b4240746ffe42bd8563b5333751bd2456
URL:         http://cgit.haiku-os.org/haiku/commit/?id=86b1039
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Aug  4 23:04:44 2012 UTC

Debugger CliContext: More event handling, current thread

* Introduce the notion of a current thread. That's the one certain
  commands will target (by default).
* Add more event handling in CliContext. There's now a queue of pending
  events which are printed in the input loop at convenient times to
  inform the user about what happened (new/deleted/stopped threads,
  etc.).

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp 
b/src/apps/debugger/user_interface/cli/CliContext.cpp
index 68b8e77..6623300 100644
--- a/src/apps/debugger/user_interface/cli/CliContext.cpp
+++ b/src/apps/debugger/user_interface/cli/CliContext.cpp
@@ -6,6 +6,7 @@
 
 #include "CliContext.h"
 
+#include <AutoDeleter.h>
 #include <AutoLocker.h>
 
 #include "UserInterface.h"
@@ -19,6 +20,36 @@
 static CliContext* sCurrentContext;
 
 
+// #pragma mark - Event
+
+
+struct CliContext::Event : DoublyLinkedListLinkImpl<CliContext::Event> {
+       Event(int type, Thread* thread = NULL)
+               :
+               fType(type),
+               fThreadReference(thread)
+       {
+       }
+
+       int Type() const
+       {
+               return fType;
+       }
+
+       Thread* GetThread() const
+       {
+               return fThreadReference.Get();
+       }
+
+private:
+       int                                     fType;
+       BReference<Thread>      fThreadReference;
+};
+
+
+// #pragma mark - CliContext
+
+
 CliContext::CliContext()
        :
        fLock("CliContext"),
@@ -31,7 +62,8 @@ CliContext::CliContext()
        fInputLoopWaitingForEvents(0),
        fEventsOccurred(0),
        fInputLoopWaiting(false),
-       fTerminating(false)
+       fTerminating(false),
+       fCurrentThread(NULL)
 {
        sCurrentContext = this;
 }
@@ -87,6 +119,9 @@ CliContext::Cleanup()
 {
        Terminating();
 
+       while (Event* event = fPendingEvents.RemoveHead())
+               delete event;
+
        if (fEditLine != NULL) {
                el_end(fEditLine);
                fEditLine = NULL;
@@ -116,6 +151,41 @@ CliContext::Terminating()
 }
 
 
+thread_id
+CliContext::CurrentThreadID() const
+{
+       return fCurrentThread != NULL ? fCurrentThread->ID() : -1;
+}
+
+
+void
+CliContext::SetCurrentThread(Thread* thread)
+{
+       AutoLocker<BLocker> locker(fLock);
+
+       if (fCurrentThread != NULL)
+               fCurrentThread->ReleaseReference();
+
+       fCurrentThread = thread;
+
+       if (fCurrentThread != NULL)
+               fCurrentThread->AcquireReference();
+}
+
+
+void
+CliContext::PrintCurrentThread()
+{
+       AutoLocker<Team> teamLocker(fTeam);
+
+       if (fCurrentThread != NULL) {
+               printf("current thread: %" B_PRId32 " \"%s\"\n", 
fCurrentThread->ID(),
+                       fCurrentThread->Name());
+       } else
+               printf("no current thread\n");
+}
+
+
 const char*
 CliContext::PromptUser(const char* prompt)
 {
@@ -126,6 +196,8 @@ CliContext::PromptUser(const char* prompt)
 
        fPrompt = NULL;
 
+       ProcessPendingEvents();
+
        return line;
 }
 
@@ -155,39 +227,124 @@ CliContext::QuitSession(bool killTeam)
 void
 CliContext::WaitForThreadOrUser()
 {
+       ProcessPendingEvents();
+
 // TODO: Deal with SIGINT as well!
        for (;;) {
                _PrepareToWaitForEvents(
-                       EVENT_USER_INTERRUPT | EVENT_THREAD_STATE_CHANGED);
+                       EVENT_USER_INTERRUPT | EVENT_THREAD_STOPPED);
 
                // check whether there are any threads stopped already
-               thread_id stoppedThread = -1;
+               Thread* stoppedThread = NULL;
+               BReference<Thread> stoppedThreadReference;
+
                AutoLocker<Team> teamLocker(fTeam);
 
                for (ThreadList::ConstIterator it = 
fTeam->Threads().GetIterator();
                                Thread* thread = it.Next();) {
                        if (thread->State() == THREAD_STATE_STOPPED) {
-                               stoppedThread = thread->ID();
+                               stoppedThread = thread;
+                               stoppedThreadReference.SetTo(thread);
                                break;
                        }
                }
 
                teamLocker.Unlock();
 
-               if (stoppedThread >= 0)
-                       _SignalInputLoop(EVENT_THREAD_STATE_CHANGED);
+               if (stoppedThread != NULL) {
+                       if (fCurrentThread == NULL)
+                               fCurrentThread = stoppedThread;
+
+                       _SignalInputLoop(EVENT_THREAD_STOPPED);
+               }
 
                uint32 events = _WaitForEvents();
-               if ((events & EVENT_QUIT) != 0 || stoppedThread >= 0)
+               if ((events & EVENT_QUIT) != 0 || stoppedThread != NULL) {
+                       ProcessPendingEvents();
                        return;
+               }
        }
 }
 
 
 void
-CliContext::ThreadStateChanged(const Team::ThreadEvent& event)
+CliContext::ProcessPendingEvents()
 {
-       _SignalInputLoop(EVENT_THREAD_STATE_CHANGED);
+       AutoLocker<Team> teamLocker(fTeam);
+
+       for (;;) {
+               // get the next event
+               AutoLocker<BLocker> locker(fLock);
+               Event* event = fPendingEvents.RemoveHead();
+               locker.Unlock();
+               if (event == NULL)
+                       break;
+               ObjectDeleter<Event> eventDeleter(event);
+
+               // process the event
+               Thread* thread = event->GetThread();
+
+               switch (event->Type()) {
+                       case EVENT_QUIT:
+                       case EVENT_USER_INTERRUPT:
+                               break;
+                       case EVENT_THREAD_ADDED:
+                               printf("[new thread: %" B_PRId32 " \"%s\"]\n", 
thread->ID(),
+                                       thread->Name());
+                               break;
+                       case EVENT_THREAD_REMOVED:
+                               printf("[thread terminated: %" B_PRId32 " 
\"%s\"]\n",
+                                       thread->ID(), thread->Name());
+                               break;
+                       case EVENT_THREAD_STOPPED:
+                               printf("[thread stopped: %" B_PRId32 " 
\"%s\"]\n",
+                                       thread->ID(), thread->Name());
+                               break;
+               }
+       }
+}
+
+
+void
+CliContext::ThreadAdded(const Team::ThreadEvent& threadEvent)
+{
+       _QueueEvent(
+               new(std::nothrow) Event(EVENT_THREAD_ADDED, 
threadEvent.GetThread()));
+       _SignalInputLoop(EVENT_THREAD_ADDED);
+}
+
+
+void
+CliContext::ThreadRemoved(const Team::ThreadEvent& threadEvent)
+{
+       _QueueEvent(
+               new(std::nothrow) Event(EVENT_THREAD_REMOVED, 
threadEvent.GetThread()));
+       _SignalInputLoop(EVENT_THREAD_REMOVED);
+}
+
+
+void
+CliContext::ThreadStateChanged(const Team::ThreadEvent& threadEvent)
+{
+       if (threadEvent.GetThread()->State() != THREAD_STATE_STOPPED)
+               return;
+
+       _QueueEvent(
+               new(std::nothrow) Event(EVENT_THREAD_STOPPED, 
threadEvent.GetThread()));
+       _SignalInputLoop(EVENT_THREAD_STOPPED);
+}
+
+
+void
+CliContext::_QueueEvent(Event* event)
+{
+       if (event == NULL) {
+               // no memory -- can't do anything about it
+               return;
+       }
+
+       AutoLocker<BLocker> locker(fLock);
+       fPendingEvents.Add(event);
 }
 
 
diff --git a/src/apps/debugger/user_interface/cli/CliContext.h 
b/src/apps/debugger/user_interface/cli/CliContext.h
index 0d5771e..3a7c98d 100644
--- a/src/apps/debugger/user_interface/cli/CliContext.h
+++ b/src/apps/debugger/user_interface/cli/CliContext.h
@@ -24,7 +24,9 @@ public:
                        enum {
                                EVENT_QUIT                                      
= 0x01,
                                EVENT_USER_INTERRUPT            = 0x02,
-                               EVENT_THREAD_STATE_CHANGED      = 0x04,
+                               EVENT_THREAD_ADDED                      = 0x04,
+                               EVENT_THREAD_REMOVED            = 0x08,
+                               EVENT_THREAD_STOPPED            = 0x10,
                        };
 
 public:
@@ -37,9 +39,18 @@ public:
 
                        void                            Terminating();
 
+                       bool                            IsTerminating() const   
{ return fTerminating; }
+
                        // service methods for the input loop thread follow
 
                        Team*                           GetTeam() const { 
return fTeam; }
+                       UserInterfaceListener* GetUserInterfaceListener() const
+                                                                       { 
return fListener; }
+
+                       Thread*                         CurrentThread() const { 
return fCurrentThread; }
+                       thread_id                       CurrentThreadID() const;
+                       void                            
SetCurrentThread(Thread* thread);
+                       void                            PrintCurrentThread();
 
                        const char*                     PromptUser(const char* 
prompt);
                        void                            
AddLineToInputHistory(const char* line);
@@ -47,13 +58,24 @@ public:
                        void                            QuitSession(bool 
killTeam);
 
                        void                            WaitForThreadOrUser();
+                       void                            ProcessPendingEvents();
+
+private:
+                       struct Event;
+
+                       typedef DoublyLinkedList<Event> EventList;
 
 private:
        // Team::Listener
+       virtual void                            ThreadAdded(const 
Team::ThreadEvent& event);
+       virtual void                            ThreadRemoved(const 
Team::ThreadEvent& event);
+
        virtual void                            ThreadStateChanged(
                                                                        const 
Team::ThreadEvent& event);
 
 private:
+                       void                            _QueueEvent(Event* 
event);
+
                        void                            
_PrepareToWaitForEvents(uint32 eventMask);
                        uint32                          _WaitForEvents();
                        void                            _SignalInputLoop(uint32 
events);
@@ -72,6 +94,10 @@ private:
                        uint32                          fEventsOccurred;
                        bool                            fInputLoopWaiting;
        volatile bool                           fTerminating;
+
+                       Thread*                         fCurrentThread;
+
+                       EventList                       fPendingEvents;
 };
 
 
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
index 0d1c92b..dcf2c6c 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
@@ -214,9 +214,19 @@ CommandLineUserInterface::_InputLoopEntry(void* data)
 status_t
 CommandLineUserInterface::_InputLoop()
 {
+       thread_id currentThread = -1;
+
        while (!fTerminating) {
                // Wait for a thread or Ctrl-C.
                fContext.WaitForThreadOrUser();
+               if (fContext.IsTerminating())
+                       break;
+
+               // Print the active thread, if it changed.
+               if (fContext.CurrentThreadID() != currentThread) {
+                       fContext.PrintCurrentThread();
+                       currentThread = fContext.CurrentThreadID();
+               }
 
                // read a command line
                const char* line = fContext.PromptUser(kDebuggerPrompt);

############################################################################

Revision:    hrev44469
Commit:      9b008d31ffa35bb2c98bb2accf83e16fb7f2f9ad
URL:         http://cgit.haiku-os.org/haiku/commit/?id=9b008d3
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Aug  4 23:06:37 2012 UTC

Debugger CLI: Add a bunch of new commands

* "thread": prints/sets the current thread.
* "continue", "stop": continue/stop the current thread.
* "sc"/"bt": Print a stack trace for the current thread. Very basic yet.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index 335827b..fca0a83 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -174,6 +174,10 @@ Application Debugger :
        # user_interface/cli
        CliCommand.cpp
        CliContext.cpp
+       CliContinueCommand.cpp
+       CliStackTraceCommand.cpp
+       CliStopCommand.cpp
+       CliThreadCommand.cpp
        CliThreadsCommand.cpp
        CliQuitCommand.cpp
        CommandLineUserInterface.cpp
diff --git a/src/apps/debugger/user_interface/cli/CliContinueCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliContinueCommand.cpp
new file mode 100644
index 0000000..887b770
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliContinueCommand.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "CliContinueCommand.h"
+
+#include <stdio.h>
+
+#include <AutoLocker.h>
+
+#include "CliContext.h"
+#include "MessageCodes.h"
+#include "Team.h"
+#include "UserInterface.h"
+
+CliContinueCommand::CliContinueCommand()
+       :
+       CliCommand("continue the current thread",
+               "%s\n"
+               "Continues the current thread.")
+{
+}
+
+
+void
+CliContinueCommand::Execute(int argc, const char* const* argv,
+       CliContext& context)
+{
+       AutoLocker<Team> teamLocker(context.GetTeam());
+       Thread* thread = context.CurrentThread();
+       if (thread == NULL) {
+               printf("Error: No current thread.\n");
+               return;
+       }
+
+       if (thread->State() != THREAD_STATE_STOPPED) {
+               printf("Error: The current thread is not stopped.\n");
+               return;
+       }
+
+       context.GetUserInterfaceListener()->ThreadActionRequested(thread->ID(),
+               MSG_THREAD_RUN);
+}
diff --git a/src/apps/debugger/user_interface/cli/CliContinueCommand.h 
b/src/apps/debugger/user_interface/cli/CliContinueCommand.h
new file mode 100644
index 0000000..d826d28
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliContinueCommand.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef CLI_CONTINUE_COMMAND_H
+#define CLI_CONTINUE_COMMAND_H
+
+
+#include "CliCommand.h"
+
+
+class CliContinueCommand : public CliCommand {
+public:
+                                                               
CliContinueCommand();
+       virtual void                            Execute(int argc, const char* 
const* argv,
+                                                                       
CliContext& context);
+};
+
+
+#endif // CLI_CONTINUE_COMMAND_H
diff --git a/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp
new file mode 100644
index 0000000..5b5b2e1
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "CliStackTraceCommand.h"
+
+#include <stdio.h>
+
+#include <AutoLocker.h>
+
+#include "CliContext.h"
+#include "FunctionInstance.h"
+#include "StackTrace.h"
+#include "Team.h"
+
+
+CliStackTraceCommand::CliStackTraceCommand()
+       :
+       CliCommand("print a stack trace of the current thread",
+               "%s\n"
+               "Prints a stack trace for the current thread.")
+{
+}
+
+
+void
+CliStackTraceCommand::Execute(int argc, const char* const* argv,
+       CliContext& context)
+{
+       // get the current thread
+       Team* team = context.GetTeam();
+       AutoLocker<Team> teamLocker(team);
+       Thread* thread = context.CurrentThread();
+       if (thread == NULL) {
+               printf("no current thread\n");
+               return;
+       }
+
+       if (thread->State() != THREAD_STATE_STOPPED) {
+               printf("Current thread is not stopped. Can't get stack 
trace.\n");
+               return;
+       }
+
+       // get its stack trace
+       StackTrace* stackTrace = thread->GetStackTrace();
+       if (stackTrace == NULL) {
+               // TODO: Wait for stack trace!
+               printf("Current thread doesn't have a stack trace. Waiting not "
+                       "implemented yet\n");
+               return;
+       }
+       BReference<StackTrace> stackTraceReference(stackTrace);
+               // hold a reference until we're done
+
+       teamLocker.Unlock();
+
+       // print the stack trace
+       int32 frameCount = stackTrace->CountFrames();
+       for (int32 i = 0; i < frameCount; i++) {
+               StackFrame* frame = stackTrace->FrameAt(i);
+               printf("%3" B_PRId32 "  %#" B_PRIx64 "  %#" B_PRIx64, i,
+                       (uint64)frame->FrameAddress(), 
(uint64)frame->InstructionPointer());
+
+               Image* image = frame->GetImage();
+               FunctionInstance* function = frame->Function();
+               if (image == NULL && function == NULL) {
+                       printf("  ???\n");
+                       continue;
+               }
+
+               BString name;
+               target_addr_t baseAddress;
+               if (function != NULL) {
+                       name = function->PrettyName();
+                       baseAddress = function->Address();
+               } else {
+                       name = image->Name();
+                       baseAddress = image->Info().TextBase();
+               }
+
+               printf("  %s + %#" B_PRIx64 "\n", name.String(),
+                       uint64(frame->InstructionPointer() - baseAddress));
+       }
+}
diff --git a/src/apps/debugger/user_interface/cli/CliStackTraceCommand.h 
b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.h
new file mode 100644
index 0000000..bf8db06
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliStackTraceCommand.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef CLI_STACK_TRACE_COMMAND_H
+#define CLI_STACK_TRACE_COMMAND_H
+
+
+#include "CliCommand.h"
+
+
+class CliStackTraceCommand : public CliCommand {
+public:
+                                                               
CliStackTraceCommand();
+       virtual void                            Execute(int argc, const char* 
const* argv,
+                                                                       
CliContext& context);
+};
+
+
+#endif // CLI_STACK_TRACE_COMMAND_H
diff --git a/src/apps/debugger/user_interface/cli/CliStopCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliStopCommand.cpp
new file mode 100644
index 0000000..40961b4
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliStopCommand.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "CliStopCommand.h"
+
+#include <stdio.h>
+
+#include <AutoLocker.h>
+
+#include "CliContext.h"
+#include "MessageCodes.h"
+#include "Team.h"
+#include "UserInterface.h"
+
+CliStopCommand::CliStopCommand()
+       :
+       CliCommand("stop the current thread",
+               "%s\n"
+               "Stops the current thread.")
+{
+}
+
+
+void
+CliStopCommand::Execute(int argc, const char* const* argv,
+       CliContext& context)
+{
+       AutoLocker<Team> teamLocker(context.GetTeam());
+       Thread* thread = context.CurrentThread();
+       if (thread == NULL) {
+               printf("Error: No current thread.\n");
+               return;
+       }
+
+       if (thread->State() == THREAD_STATE_STOPPED) {
+               printf("Error: The current thread is already stopped.\n");
+               return;
+       }
+
+       context.GetUserInterfaceListener()->ThreadActionRequested(thread->ID(),
+               MSG_THREAD_STOP);
+}
diff --git a/src/apps/debugger/user_interface/cli/CliStopCommand.h 
b/src/apps/debugger/user_interface/cli/CliStopCommand.h
new file mode 100644
index 0000000..f069712
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliStopCommand.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef CLI_STOP_COMMAND_H
+#define CLI_STOP_COMMAND_H
+
+
+#include "CliCommand.h"
+
+
+class CliStopCommand : public CliCommand {
+public:
+                                                               
CliStopCommand();
+       virtual void                            Execute(int argc, const char* 
const* argv,
+                                                                       
CliContext& context);
+};
+
+
+#endif // CLI_STOP_COMMAND_H
diff --git a/src/apps/debugger/user_interface/cli/CliThreadCommand.cpp 
b/src/apps/debugger/user_interface/cli/CliThreadCommand.cpp
new file mode 100644
index 0000000..6e8163b
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliThreadCommand.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "CliThreadCommand.h"
+
+#include <stdio.h>
+
+#include <AutoLocker.h>
+
+#include "CliContext.h"
+#include "Team.h"
+
+
+CliThreadCommand::CliThreadCommand()
+       :
+       CliCommand("set or print the current thread",
+               "%s [ <thread ID> ]\n"
+               "Sets the current thread to <thread ID>, if supplied. Otherwise 
prints "
+                       "the\n"
+               "current thread.")
+{
+}
+
+
+void
+CliThreadCommand::Execute(int argc, const char* const* argv,
+       CliContext& context)
+{
+       if (argc > 2) {
+               PrintUsage(argv[0]);
+               return;
+       }
+
+       if (argc < 2) {
+               // no arguments -- print the current thread
+               context.PrintCurrentThread();
+               return;
+       }
+
+       // parse the argument
+       char* endPointer;
+       long threadID = strtol(argv[1], &endPointer, 0);
+       if (*endPointer != '\0' || threadID < 0) {
+               printf("Error: Invalid parameter \"%s\"\n", argv[1]);
+               return;
+       }
+
+       // get the thread and change the current thread
+       Team* team = context.GetTeam();
+       AutoLocker<Team> teamLocker(team);
+       if (Thread* thread = team->ThreadByID(threadID))
+               context.SetCurrentThread(thread);
+       else
+               printf("Error: No thread with ID %ld\n", threadID);
+}
diff --git a/src/apps/debugger/user_interface/cli/CliThreadCommand.h 
b/src/apps/debugger/user_interface/cli/CliThreadCommand.h
new file mode 100644
index 0000000..d778909
--- /dev/null
+++ b/src/apps/debugger/user_interface/cli/CliThreadCommand.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef CLI_THREAD_COMMAND_H
+#define CLI_THREAD_COMMAND_H
+
+
+#include "CliCommand.h"
+
+
+class CliThreadCommand : public CliCommand {
+public:
+                                                               
CliThreadCommand();
+       virtual void                            Execute(int argc, const char* 
const* argv,
+                                                                       
CliContext& context);
+};
+
+
+#endif // CLI_THREAD_COMMAND_H
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
index dcf2c6c..1871c45 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
@@ -16,7 +16,11 @@
 #include <Referenceable.h>
 
 #include "CliContext.h"
+#include "CliContinueCommand.h"
 #include "CliQuitCommand.h"
+#include "CliStackTraceCommand.h"
+#include "CliStopCommand.h"
+#include "CliThreadCommand.h"
 #include "CliThreadsCommand.h"
 
 
@@ -268,8 +272,18 @@ CommandLineUserInterface::_InputLoop()
 status_t
 CommandLineUserInterface::_RegisterCommands()
 {
-       if (_RegisterCommand("help", new(std::nothrow) HelpCommand(this)) &&
+       BReference<CliCommand> stackTraceCommandReference(
+               new(std::nothrow) CliStackTraceCommand, true);
+       BReference<CliCommand> stackTraceCommandReference2(
+               stackTraceCommandReference.Get());
+
+       if (_RegisterCommand("bt", stackTraceCommandReference.Detach()) &&
+               _RegisterCommand("continue", new(std::nothrow) 
CliContinueCommand) &&
+               _RegisterCommand("help", new(std::nothrow) HelpCommand(this)) &&
                _RegisterCommand("quit", new(std::nothrow) CliQuitCommand) &&
+               _RegisterCommand("sc", stackTraceCommandReference2.Detach()) &&
+               _RegisterCommand("stop", new(std::nothrow) CliStopCommand) &&
+               _RegisterCommand("thread", new(std::nothrow) CliThreadCommand) 
&&
                _RegisterCommand("threads", new(std::nothrow) 
CliThreadsCommand)) {
                return B_OK;
        }


Other related posts:

  • » [haiku-commits] haiku: hrev44469 - src/apps/debugger/user_interface/cli - ingo_weinhold