[nemiver/console: 2/11] WIP - Nemiver's console
- From: Fabien Parent <fparent src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/console: 2/11] WIP - Nemiver's console
- Date: Fri, 2 Mar 2012 16:58:07 +0000 (UTC)
commit aac4fc153cd336be210c9fe8aab5e5a1bba5dcdc
Author: Fabien Parent <parent f gmail com>
Date: Sat Jan 21 18:58:05 2012 +0100
WIP - Nemiver's console
configure.ac | 3 +-
src/common/Makefile.am | 3 +-
src/common/nmv-console.cc | 452 +++++++++++++++
src/common/nmv-console.h | 112 ++++
src/common/nmv-str-utils.h | 20 +
src/dbgengine/Makefile.am | 11 +-
src/dbgengine/nmv-dbg-console.cc | 684 +++++++++++++++++++++++
src/dbgengine/nmv-dbg-console.h | 58 ++
src/persp/dbgperspective/nmv-dbg-perspective.cc | 74 +++
src/persp/dbgperspective/nmv-dbg-perspective.h | 4 +-
src/uicommon/nmv-terminal.cc | 6 +
src/uicommon/nmv-terminal.h | 1 +
12 files changed, 1423 insertions(+), 5 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1d45c0c..68430b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -337,8 +337,9 @@ DEP_COMMON="gmodule-2.0 >= $LIBGMODULE_VERSION \
glibmm-2.4 >= $LIBGLIBMM_VERSION"
PKG_CHECK_MODULES(NEMIVERCOMMON, $DEP_COMMON)
+AC_CHECK_FUNCS(readline)
NEMIVERCOMMON_CFLAGS="$NEMIVERCOMMON_CFLAGS $CPPUNIT_CFLAGS"
-NEMIVERCOMMON_LIBS="$NEMIVERCOMMON_LIBS $LIBGTOP_LIBS $CPPUNIT_LIBS"
+NEMIVERCOMMON_LIBS="$NEMIVERCOMMON_LIBS $LIBGTOP_LIBS $CPPUNIT_LIBS -lreadline"
AC_SUBST(NEMIVERCOMMON_LIBS)
AC_SUBST(NEMIVERCOMMON_CFLAGS)
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 5b61d90..8318d34 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -71,7 +71,8 @@ $(h)/nmv-sql-statement.cc \
$(h)/nmv-insert-statement.cc \
$(h)/nmv-delete-statement.cc \
$(h)/nmv-proc-utils.cc \
-$(h)/nmv-proc-mgr.cc
+$(h)/nmv-proc-mgr.cc \
+$(h)/nmv-console.cc
publicheaders_DATA=$(headers)
publicheadersdir=$(NEMIVER_INCLUDE_DIR)/common
diff --git a/src/common/nmv-console.cc b/src/common/nmv-console.cc
new file mode 100644
index 0000000..8df71b9
--- /dev/null
+++ b/src/common/nmv-console.cc
@@ -0,0 +1,452 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+
+#define USE_VARARGS
+#define PREFER_STDARG
+
+#include "nmv-console.h"
+#include "nmv-str-utils.h"
+#include <map>
+#include <vector>
+#include <cstring>
+#include <cctype>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+NEMIVER_BEGIN_NAMESPACE(common)
+
+const char *const CONSOLE_PROMPT = "> ";
+const unsigned int COMMAND_EXECUTION_TIMEOUT_IN_SECONDS = 10;
+
+struct Console::Stream::Priv {
+ int fd;
+
+ Priv (int a_fd) :
+ fd (a_fd)
+ {
+ }
+
+ void
+ write (const std::string &a_msg) const
+ {
+ THROW_IF_FAIL (fd);
+ ::write (fd, a_msg.c_str (), a_msg.size ());
+ }
+};
+
+Console::Stream::Stream (int a_fd) :
+ m_priv (new Priv (a_fd))
+{
+}
+
+Console::Stream&
+Console::Stream::operator<< (const char *const a_string)
+{
+ THROW_IF_FAIL (m_priv);
+ m_priv->write (a_string);
+ return *this;
+}
+
+Console::Stream&
+Console::Stream::operator<< (const std::string &a_string)
+{
+ THROW_IF_FAIL (m_priv);
+ m_priv->write (a_string);
+ return *this;
+}
+
+Console::Stream&
+Console::Stream::operator<< (unsigned int a_uint)
+{
+ THROW_IF_FAIL (m_priv);
+ m_priv->write (str_utils::to_string (a_uint));
+ return *this;
+}
+
+Console::Stream&
+Console::Stream::operator<< (int a_int)
+{
+ THROW_IF_FAIL (m_priv);
+ m_priv->write (str_utils::to_string (a_int));
+ return *this;
+}
+
+struct Console::Priv {
+ std::map<std::string, Console::Command&> commands;
+ std::vector<Console::Command*> commands_vector;
+
+ int fd;
+ struct readline_state console_state;
+ struct readline_state saved_state;
+
+ Console::Stream stream;
+ Glib::RefPtr<Glib::IOSource> io_source;
+ sigc::connection cmd_execution_done_connection;
+ sigc::connection cmd_execution_timeout_connection;
+
+ Priv (int a_fd) :
+ fd (a_fd),
+ stream (a_fd),
+ io_source (Glib::IOSource::create (a_fd, Glib::IO_IN))
+ {
+ init ();
+ }
+
+ void
+ init ()
+ {
+ THROW_IF_FAIL (fd);
+ THROW_IF_FAIL (io_source);
+
+ if (consoles ().count (fd)) {
+ THROW ("Cannot create two consoles from the same file descriptor.");
+ }
+ consoles ()[fd] = this;
+
+ io_source->connect (sigc::mem_fun (*this, &Console::Priv::read_char));
+ io_source->attach ();
+
+ rl_save_state (&saved_state);
+ rl_instream = fdopen (fd, "r");
+ rl_outstream = fdopen (fd, "w");
+ rl_bind_key ('\t', &Console::Priv::on_tab_key_pressed);
+ rl_callback_handler_install (CONSOLE_PROMPT,
+ &Console::Priv::process_command);
+ rl_already_prompted = true;
+ rl_save_state (&console_state);
+ rl_restore_state (&saved_state);
+ }
+
+ bool
+ read_char (Glib::IOCondition)
+ {
+ NEMIVER_TRY
+
+ if (cmd_execution_done_connection.connected ())
+ return false;
+
+ rl_restore_state (&console_state);
+ rl_callback_read_char ();
+ rl_save_state (&console_state);
+ rl_restore_state (&saved_state);
+
+ NEMIVER_CATCH_NOX
+
+ return true;
+ }
+
+ void
+ do_completion (const std::string &a_completion)
+ {
+ size_t buffer_length = std::strlen (rl_line_buffer);
+ rl_extend_line_buffer (buffer_length + a_completion.size ());
+ std::memcpy (rl_line_buffer + rl_point + a_completion.size (),
+ rl_line_buffer + rl_point,
+ a_completion.size ());
+ for (size_t i = 0; i < a_completion.size(); i++) {
+ rl_line_buffer[rl_point + i] = a_completion[i];
+ }
+ rl_end += a_completion.size ();
+ rl_point += a_completion.size ();
+ }
+
+ void
+ do_command_completion (const std::string &a_line)
+ {
+ std::vector<Console::Command*> matches;
+ for (std::vector<Console::Command*>::const_iterator iter =
+ commands_vector.begin ();
+ iter != commands_vector.end ();
+ ++iter) {
+ if (*iter && !(*iter)->name ().find (a_line)) {
+ matches.push_back (*iter);
+ }
+ }
+
+ if (matches.size () == 1) {
+ std::string completion =
+ matches[0]->name ().substr (a_line.size ());
+ do_completion (completion);
+ } else if (matches.size () > 1) {
+ std::string msg;
+ std::string completion =
+ matches[0]->name ().substr (a_line.size ());
+ for (size_t i = 0; i < matches.size (); i++) {
+ size_t j = a_line.size ();
+ for (; j < matches[i]->name ().size ()
+ && j < completion.size ()
+ && matches[i]->name ()[j] == completion[j];
+ j++) {
+ }
+ completion = completion.substr (0, j);
+ msg += matches[i]->name () + "\t";
+ }
+
+ rl_save_prompt ();
+ rl_message ("%s%s\n%s\n%s",
+ rl_display_prompt,
+ std::string (rl_line_buffer, rl_end).c_str (),
+ msg.c_str (),
+ rl_display_prompt);
+ rl_clear_message ();
+ rl_restore_prompt ();
+ do_completion (completion);
+ }
+ }
+
+ void
+ do_param_completion (std::vector<UString> &a_tokens)
+ {
+ if (!a_tokens.size ()) {
+ return;
+ }
+
+ Console::Command* command = 0;
+ for (std::vector<Console::Command*>::const_iterator iter =
+ commands_vector.begin ();
+ iter != commands_vector.end ();
+ ++iter) {
+ if (*iter && (*iter)->name () == a_tokens[0]) {
+ command = *iter;
+ break;
+ }
+ }
+
+ if (!command) {
+ return;
+ }
+
+ a_tokens.erase (a_tokens.begin ());
+ std::string line (rl_line_buffer, rl_point);
+ if (std::isspace (line[line.size () - 1])) {
+ stream << "\n";
+ command->display_usage (a_tokens, stream);
+ rl_forced_update_display ();
+ } else {
+ UString token = a_tokens.back ();
+ a_tokens.pop_back ();
+
+ std::vector<UString> completions;
+ std::vector<UString> matches;
+ command->completions (a_tokens, completions);
+ for (std::vector<UString>::iterator iter = completions.begin ();
+ iter != completions.end ();
+ ++iter) {
+ if (!iter->find (token)) {
+ matches.push_back (*iter);
+ }
+ }
+
+ if (matches.size () == 1) {
+ std::string completion = matches[0].substr (token.size ());
+ do_completion (completion);
+ } else if (matches.size () > 1) {
+ std::string msg;
+ UString completion = matches[0].substr (token.size ());
+ for (size_t i = 0; i < matches.size (); i++) {
+ size_t j = token.size ();
+ for (; j < matches[i].size ()
+ && j < completion.size ()
+ && matches[i][j] == completion[j];
+ j++) {
+ }
+ completion = completion.substr (0, j);
+ msg += matches[i] + "\t";
+ }
+ rl_save_prompt ();
+ rl_message ("%s%s\n%s\n%s",
+ rl_display_prompt,
+ std::string (rl_line_buffer, rl_end).c_str (),
+ msg.c_str (),
+ rl_display_prompt);
+ rl_clear_message ();
+ rl_restore_prompt ();
+ do_completion (completion);
+ } else {
+ rl_complete (0, '\t');
+ }
+ }
+ }
+
+ void
+ execute_command (char *a_buffer)
+ {
+ std::string command_name;
+ std::vector<std::string> cmd_argv;
+
+ int size = std::strlen (a_buffer);
+ for (int i = 0, local_index = 0; i <= size; ++i, ++local_index) {
+ if (!std::isspace (a_buffer[local_index]) && i != size) {
+ continue;
+ }
+
+ a_buffer[local_index] = '\0';
+ if (command_name.empty ()) {
+ command_name = a_buffer;
+ } else {
+ cmd_argv.push_back (a_buffer);
+ }
+ a_buffer += local_index + 1;
+ local_index = 0;
+ }
+
+ if (command_name.empty ()) {
+ stream << CONSOLE_PROMPT;
+ return;
+ }
+
+ if (!commands.count (command_name)) {
+ stream << "Undefined command: " << command_name << ".\n"
+ << CONSOLE_PROMPT;
+ return;
+ }
+
+ Command &command = commands.at (command_name);
+ cmd_execution_done_connection = command.done_signal ().connect
+ (sigc::mem_fun (*this, &Console::Priv::on_done_signal));
+ commands.at (command_name) (cmd_argv, stream);
+ cmd_execution_timeout_connection =
+ Glib::signal_timeout().connect_seconds
+ (sigc::mem_fun
+ (*this, &Console::Priv::on_cmd_execution_timeout_signal),
+ COMMAND_EXECUTION_TIMEOUT_IN_SECONDS);
+ }
+
+ bool
+ on_cmd_execution_timeout_signal ()
+ {
+ NEMIVER_TRY
+ on_done_signal ();
+ NEMIVER_CATCH_NOX
+
+ return true;
+ }
+
+ void
+ on_done_signal ()
+ {
+ NEMIVER_TRY
+
+ stream << CONSOLE_PROMPT;
+ cmd_execution_timeout_connection.disconnect();
+ cmd_execution_done_connection.disconnect ();
+
+ NEMIVER_CATCH_NOX
+ }
+
+ static int
+ on_tab_key_pressed (int, int)
+ {
+ NEMIVER_TRY
+
+ std::string line (rl_line_buffer, rl_point);
+ std::vector<UString> tokens_raw = str_utils::split (line, " ");
+ std::vector<UString> tokens;
+ for (size_t i = 0; i < tokens_raw.size (); i++) {
+ if (tokens_raw[i].size ()) {
+ tokens.push_back (tokens_raw[i]);
+ }
+ }
+
+ if (std::isspace (line[line.size () - 1]) || tokens.size () > 1) {
+ self ().do_param_completion (tokens);
+ } else {
+ self ().do_command_completion (line);
+ }
+
+ NEMIVER_CATCH_NOX
+
+ return 0;
+ }
+
+ static std::map<int, Console::Priv*>& consoles ()
+ {
+ static std::map<int, Console::Priv*> s_consoles;
+ return s_consoles;
+ }
+
+ static Console::Priv& self ()
+ {
+ int fd = fileno (rl_instream);
+ THROW_IF_FAIL (fd);
+ THROW_IF_FAIL (consoles ().count (fd));
+ Console::Priv *self = consoles ()[fd];
+ THROW_IF_FAIL (self);
+ return *self;
+ }
+
+ static void
+ process_command (char *a_command)
+ {
+ NEMIVER_TRY
+
+ THROW_IF_FAIL (a_command);
+ add_history (a_command);
+ self ().execute_command (a_command);
+
+ NEMIVER_CATCH_NOX
+
+ free (a_command);
+ }
+};
+
+Console::Console (int a_fd) :
+ m_priv (new Priv (a_fd))
+{
+}
+
+Console::~Console ()
+{
+}
+
+void
+Console::register_command (Console::Command &a_command)
+{
+ THROW_IF_FAIL (m_priv);
+
+ if (m_priv->commands.count (a_command.name ())) {
+ LOG ("Command '" << a_command.name () << "' is already registered in"
+ " the console. The previous command will be overwritten");
+ }
+
+ m_priv->commands.insert (std::make_pair<std::string, Command&>
+ (a_command.name (), a_command));
+ m_priv->commands_vector.push_back (&a_command);
+
+ const char **aliases = a_command.aliases ();
+ for (int i = 0; aliases && aliases[i]; i++) {
+ if (m_priv->commands.count (aliases[i])) {
+ LOG ("Command '" << aliases[i] << "' is already registered in"
+ " the console. The previous command will be overwritten");
+ }
+ m_priv->commands.insert (std::make_pair<std::string, Command&>
+ (aliases[i], a_command));
+ }
+}
+
+NEMIVER_END_NAMESPACE(common)
+NEMIVER_END_NAMESPACE(nemiver)
+
diff --git a/src/common/nmv-console.h b/src/common/nmv-console.h
new file mode 100644
index 0000000..0ac41cf
--- /dev/null
+++ b/src/common/nmv-console.h
@@ -0,0 +1,112 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_CONSOLE_H__
+#define __NMV_CONSOLE_H__
+
+#include "nmv-safe-ptr.h"
+#include "nmv-namespace.h"
+#include "nmv-exception.h"
+#include <string>
+#include <vector>
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+NEMIVER_BEGIN_NAMESPACE(common)
+
+class Console {
+ struct Priv;
+ SafePtr<Priv> m_priv;
+
+public:
+ class Stream {
+ struct Priv;
+ SafePtr<Priv> m_priv;
+
+ public:
+ explicit Stream (int a_fd);
+ Stream& operator<< (const char *const a_string);
+ Stream& operator<< (const std::string &a_string);
+ Stream& operator<< (unsigned int a_uint);
+ Stream& operator<< (int a_int);
+ };
+
+ class Command {
+ sigc::signal<void> m_done_signal;
+
+public:
+ sigc::signal<void>& done_signal ()
+ {
+ return m_done_signal;
+ }
+
+ virtual const std::string& name () const = 0;
+
+ virtual const char** aliases () const
+ {
+ return 0;
+ }
+
+ virtual void completions (const std::vector<UString>&,
+ std::vector<UString>&) const
+ {
+ }
+
+ virtual void display_usage (const std::vector<UString>&, Stream&) const
+ {
+ }
+
+ virtual void execute (const std::vector<std::string> &a_argv,
+ Stream &a_output) = 0;
+
+ virtual void operator() (const std::vector<std::string> &a_argv,
+ Stream &a_output)
+ {
+ execute (a_argv, a_output);
+ }
+
+ virtual ~Command ()
+ {
+ }
+ };
+
+ typedef Command AsynchronousCommand;
+ struct SynchronousCommand : public Command{
+ virtual void operator() (const std::vector<std::string> &a_argv,
+ Stream &a_output)
+ {
+ execute (a_argv, a_output);
+ done_signal ().emit ();
+ }
+ };
+
+ explicit Console (int a_fd);
+ virtual ~Console ();
+ void register_command (Console::Command &a_command);
+};
+
+NEMIVER_END_NAMESPACE(common)
+NEMIVER_END_NAMESPACE(nemiver)
+
+#endif /* __NMV_CONSOLE_H__ */
+
diff --git a/src/common/nmv-str-utils.h b/src/common/nmv-str-utils.h
index 8c72b8c..9a9f856 100644
--- a/src/common/nmv-str-utils.h
+++ b/src/common/nmv-str-utils.h
@@ -25,6 +25,7 @@
#ifndef __NMV_STR_UTILS_H__
#define __NMV_STR_UTILS_H__
#include "nmv-ustring.h"
+#include <sstream>
NEMIVER_BEGIN_NAMESPACE (nemiver)
NEMIVER_BEGIN_NAMESPACE (str_utils)
@@ -52,6 +53,25 @@ UString join (vector<UString>::const_iterator &a_from,
vector<UString>::const_iterator &a_to,
const UString &a_delim=" ");
+template<typename T>
+T
+from_string (const std::string &a_string)
+{
+ std::istringstream is (a_string);
+ T out;
+ is >> out;
+ return out;
+}
+
+template<typename T>
+std::string
+to_string (const T &a_value)
+{
+ std::ostringstream os;
+ os << a_value;
+ return os.str ();
+}
+
template<typename S>
void
chomp (S &a_string)
diff --git a/src/dbgengine/Makefile.am b/src/dbgengine/Makefile.am
index d1cd044..a271197 100644
--- a/src/dbgengine/Makefile.am
+++ b/src/dbgengine/Makefile.am
@@ -20,7 +20,8 @@ noinst_LTLIBRARIES=\
libgdbmiparser.la \
libdbgcommon.la \
libdebuggerutils.la \
-libgdbengine.la
+libgdbengine.la \
+libdbgconsole.la
h=$(abs_srcdir)
@@ -85,6 +86,12 @@ $(h)/nmv-debugger-utils.cc
libdebuggerutils_la_CFLAGS=-fPIC -DPIC
+libdbgconsole_la_SOURCES= \
+$(h)/nmv-dbg-console.cc \
+$(h)/nmv-dbg-console.h
+
+libdbgconsole_la_CFLAGS=-fPIC -DPIC
+
libgdbengine_la_SOURCES= \
$(h)/nmv-gdb-engine.cc \
$(h)/nmv-gdb-engine.h
@@ -96,7 +103,7 @@ publicheadersdir=$(NEMIVER_INCLUDE_DIR)/dynmods
libgdbmod_la_LDFLAGS=-module -avoid-version -Wl,--as-needed
libgdbmod_la_LIBADD=libgdbmiparser.la \
-libgdbengine.la libdebuggerutils.la @NEMIVERCOMMON_LIBS@ \
+libgdbengine.la libdebuggerutils.la libdbgconsole.la @NEMIVERCOMMON_LIBS@ \
$(abs_top_builddir)/src/langs/libnemivercparser.la \
$(abs_top_builddir)/src/common/libnemivercommon.la
diff --git a/src/dbgengine/nmv-dbg-console.cc b/src/dbgengine/nmv-dbg-console.cc
new file mode 100644
index 0000000..85de1ec
--- /dev/null
+++ b/src/dbgengine/nmv-dbg-console.cc
@@ -0,0 +1,684 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+
+#include "nmv-dbg-console.h"
+#include "nmv-i-debugger.h"
+#include "uicommon/nmv-terminal.h"
+#include "common/nmv-exception.h"
+#include "common/nmv-str-utils.h"
+#include "common/nmv-ustring.h"
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+
+const char *const NEMIVER_DBG_CONSOLE_COOKIE = "nemiver-dbg-console";
+
+using namespace common;
+
+struct DebuggingData {
+ IDebugger &debugger;
+ IDebugger::Frame current_frame;
+ UString current_file_path;
+ std::vector<UString> source_files;
+
+ DebuggingData (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+};
+
+struct CommandContinue : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandContinue (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "continue";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "c",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.do_continue ();
+ }
+};
+
+struct CommandNext : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandNext (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "next";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "n",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.step_over ();
+ }
+};
+
+struct CommandStep : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandStep (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "step";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "s",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void
+ execute (const std::vector<std::string>&,
+ Console::Stream&)
+ {
+ debugger.step_in ();
+ }
+};
+
+struct CommandNexti : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandNexti (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "nexti";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "ni",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.step_over_asm ();
+ }
+};
+
+struct CommandStepi : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandStepi (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "stepi";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "si",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.step_in_asm ();
+ }
+};
+
+struct CommandStop : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandStop (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "stop";
+ return s_name;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.stop_target ();
+ }
+};
+
+struct CommandFinish : public Console::SynchronousCommand {
+ IDebugger &debugger;
+
+ CommandFinish (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "finish";
+ return s_name;
+ }
+
+ void
+ execute (const std::vector<std::string>&, Console::Stream&)
+ {
+ debugger.step_out ();
+ }
+};
+
+struct CommandCall : public Console::SynchronousCommand {
+ IDebugger &debugger;
+ std::string cmd;
+
+ CommandCall (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "call";
+ return s_name;
+ }
+
+ void
+ execute (const std::vector<std::string> &a_argv, Console::Stream &a_stream)
+ {
+ if (a_argv.size ()) {
+ cmd.clear ();
+ }
+
+ for (std::vector<std::string>::const_iterator iter = a_argv.begin ();
+ iter != a_argv.end ();
+ ++iter) {
+ cmd += *iter;
+ }
+
+ if (cmd.empty ()) {
+ a_stream << "The history is empty.\n";
+ } else {
+ debugger.call_function (cmd);
+ }
+ }
+};
+
+struct CommandThread : public Console::AsynchronousCommand {
+ IDebugger &debugger;
+
+ CommandThread (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "thread";
+ return s_name;
+ }
+
+ void completions (const std::vector<UString> &a_argv,
+ std::vector<UString> &a_completion_vector) const
+ {
+ if (a_argv.size () == 0) {
+ a_completion_vector.push_back ("list");
+ }
+ }
+
+ void display_usage (const std::vector<UString> &a_argv,
+ Console::Stream &a_stream) const
+ {
+ if (a_argv.size ()) {
+ return;
+ }
+
+ a_stream << "Usage:\n"
+ << "\tthread\n"
+ << "\tthread [THREAD ID]\n"
+ << "\tthread list\n";
+ }
+
+ void
+ threads_listed_signal (const std::list<int> a_thread_ids,
+ const UString &a_cookie,
+ Console::Stream &a_stream)
+ {
+ NEMIVER_TRY
+
+ if (a_cookie != NEMIVER_DBG_CONSOLE_COOKIE) {
+ return;
+ }
+
+ a_stream << "Threads:\n";
+ for (std::list<int>::const_iterator iter = a_thread_ids.begin ();
+ iter != a_thread_ids.end ();
+ ++iter) {
+ a_stream << *iter << "\n";
+ }
+ done_signal().emit ();
+
+ NEMIVER_CATCH_NOX
+ }
+
+ void
+ execute (const std::vector<std::string> &a_argv, Console::Stream &a_stream)
+ {
+ if (a_argv.size () > 1) {
+ a_stream << "Too much parameters.\n";
+ } else if (!a_argv.size ()) {
+ a_stream << "Current thread ID: " << debugger.get_current_thread ()
+ << ".\n";
+ } else if (str_utils::string_is_number (a_argv[0])) {
+ debugger.select_thread
+ (str_utils::from_string<unsigned int> (a_argv[0]));
+ } else if (a_argv[0] == "list") {
+ debugger.threads_listed_signal ().connect
+ (sigc::bind<Console::Stream&> (sigc::mem_fun
+ (*this, &CommandThread::threads_listed_signal),
+ a_stream));
+ debugger.list_threads (NEMIVER_DBG_CONSOLE_COOKIE);
+ return;
+ } else {
+ a_stream << "Invalid argument: " << a_argv[0] << ".\n";
+ }
+
+ done_signal().emit ();
+ }
+};
+
+struct CommandBreak : public Console::SynchronousCommand {
+ DebuggingData &dbg_data;
+
+ CommandBreak (DebuggingData &a_dbg_data) :
+ dbg_data (a_dbg_data)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "break";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "b",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void display_usage (const std::vector<UString>&,
+ Console::Stream &a_stream) const
+ {
+ a_stream << "Usage:\n"
+ << "\tbreak\n"
+ << "\tbreak [LINE]\n"
+ << "\tbreak [FUNCTION]\n"
+ << "\tbreak *[ADDRESS]\n"
+ << "\tbreak +[OFFSET]\n"
+ << "\tbreak -[OFFSET]\n";
+ }
+
+ void
+ execute (const std::vector<std::string> &a_argv, Console::Stream &a_stream)
+ {
+ IDebugger::Frame &frame = dbg_data.current_frame;
+ IDebugger &debugger = dbg_data.debugger;
+
+ if (frame.file_full_name ().empty () ||
+ dbg_data.current_file_path.empty ()) {
+ a_stream << "Cannot set a breakpoint at this position.\n";
+ }
+
+ if (a_argv.size () > 1) {
+ a_stream << "Too much parameters.\n";
+ } else if (a_argv.size () == 0) {
+ debugger.set_breakpoint (frame.file_full_name (), frame.line ());
+ }
+
+ const char first_param_char = a_argv[0][0];
+ if (str_utils::string_is_number (a_argv[0])) {
+ debugger.set_breakpoint (dbg_data.current_file_path,
+ str_utils::from_string<int> (a_argv[0]));
+ } else if ((first_param_char >= 'a' && first_param_char <= 'z')
+ || first_param_char == '_') {
+ debugger.set_breakpoint (a_argv[0]);
+ } else if (first_param_char == '*') {
+ std::string addr (a_argv[0].substr (1));
+ if (str_utils::string_is_hexa_number (addr)) {
+ Address address (addr);
+ debugger.set_breakpoint (address);
+ } else {
+ a_stream << "Invalid address: " << addr << ".\n";
+ }
+ } else if (first_param_char == '+' || first_param_char == '-') {
+ std::string offset (a_argv[0].substr (1));
+ if (str_utils::string_is_decimal_number (offset)) {
+ int line = frame.line ();
+ if (first_param_char == '+') {
+ line += str_utils::from_string<int> (offset);
+ } else {
+ line -= str_utils::from_string<int> (offset);
+ }
+ debugger.set_breakpoint (frame.file_full_name (), line);
+ } else {
+ a_stream << "Invalid offset: " << offset << ".\n";
+ }
+ } else {
+ a_stream << "Invalid argument: " << a_argv[0] << ".\n";
+ }
+ }
+};
+
+struct CommandPrint : public Console::AsynchronousCommand {
+ IDebugger &debugger;
+ std::string expression;
+
+ CommandPrint (IDebugger &a_debugger) :
+ debugger (a_debugger)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "print";
+ return s_name;
+ }
+
+ void
+ on_variable_created_signal (const IDebugger::VariableSafePtr a_var,
+ Console::Stream &a_stream)
+ {
+ NEMIVER_TRY
+
+ THROW_IF_FAIL (a_var);
+ a_stream << a_var->name () << " = " << a_var->value () << "\n";
+ debugger.delete_variable (a_var);
+ done_signal ().emit ();
+
+ NEMIVER_CATCH_NOX
+ }
+
+ void
+ execute (const std::vector<std::string> &a_argv, Console::Stream &a_stream)
+ {
+ if (a_argv.size ()) {
+ expression.clear ();
+ }
+
+ for (std::vector<std::string>::const_iterator iter = a_argv.begin ();
+ iter != a_argv.end ();
+ ++iter) {
+ expression += *iter;
+ }
+
+ if (expression.empty ()) {
+ a_stream << "No history\n";
+ done_signal ().emit ();
+ return;
+ }
+
+ debugger.create_variable
+ (expression, sigc::bind<Console::Stream&>
+ (sigc::mem_fun
+ (*this, &CommandPrint::on_variable_created_signal),
+ a_stream));
+ }
+};
+
+struct CommandOpen : public Console::SynchronousCommand {
+ DebuggingData &dbg_data;
+ sigc::signal<void, UString> file_opened_signal;
+
+ CommandOpen (DebuggingData &a_dbg_data) :
+ dbg_data (a_dbg_data)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "open";
+ return s_name;
+ }
+
+ const char**
+ aliases () const
+ {
+ static const char *s_aliases[] =
+ {
+ "o",
+ 0
+ };
+ return s_aliases;
+ }
+
+ void completions (const std::vector<UString>&,
+ std::vector<UString> &a_completion_vector) const
+ {
+ a_completion_vector.insert (a_completion_vector.begin (),
+ dbg_data.source_files.begin (),
+ dbg_data.source_files.end ());
+ }
+
+ void
+ execute (const std::vector<std::string> &a_argv, Console::Stream&)
+ {
+ for (std::vector<std::string>::const_iterator iter = a_argv.begin ();
+ iter != a_argv.end ();
+ ++iter) {
+ UString path = *iter;
+ if (path.size () && path[0] == '~') {
+ path = path.replace (0, 1, Glib::get_home_dir ());
+ }
+ file_opened_signal.emit (path);
+ }
+ }
+};
+
+struct DBGConsole::Priv {
+ DebuggingData data;
+
+ CommandContinue cmd_continue;
+ CommandNext cmd_next;
+ CommandStep cmd_step;
+ CommandBreak cmd_break;
+ CommandPrint cmd_print;
+ CommandCall cmd_call;
+ CommandFinish cmd_finish;
+ CommandThread cmd_thread;
+ CommandStop cmd_stop;
+ CommandNexti cmd_nexti;
+ CommandStepi cmd_stepi;
+ CommandOpen cmd_open;
+
+ Priv (IDebugger &a_debugger) :
+ data (a_debugger),
+ cmd_continue (a_debugger),
+ cmd_next (a_debugger),
+ cmd_step (a_debugger),
+ cmd_break (data),
+ cmd_print (a_debugger),
+ cmd_call (a_debugger),
+ cmd_finish (a_debugger),
+ cmd_thread (a_debugger),
+ cmd_stop (a_debugger),
+ cmd_nexti (a_debugger),
+ cmd_stepi (a_debugger),
+ cmd_open (data)
+ {
+ init_signals ();
+ }
+
+ void
+ on_stopped_signal (IDebugger::StopReason,
+ bool,
+ const IDebugger::Frame &a_frame,
+ int,
+ int,
+ const UString&)
+ {
+ data.current_frame = a_frame;
+ data.current_file_path = a_frame.file_full_name ();
+ }
+
+ void
+ on_files_listed_signal (const std::vector<UString> &a_files, const UString&)
+ {
+ data.source_files = a_files;
+ }
+
+ void
+ init_signals ()
+ {
+ data.debugger.stopped_signal ().connect
+ (sigc::mem_fun (*this, &DBGConsole::Priv::on_stopped_signal));
+ data.debugger.files_listed_signal ().connect (sigc::mem_fun
+ (*this, &DBGConsole::Priv::on_files_listed_signal));
+ }
+};
+
+DBGConsole::DBGConsole (int a_fd, IDebugger &a_debugger) :
+ Console (a_fd),
+ m_priv (new Priv (a_debugger))
+{
+ register_command (m_priv->cmd_continue);
+ register_command (m_priv->cmd_next);
+ register_command (m_priv->cmd_step);
+ register_command (m_priv->cmd_break);
+ register_command (m_priv->cmd_print);
+ register_command (m_priv->cmd_call);
+ register_command (m_priv->cmd_finish);
+ register_command (m_priv->cmd_thread);
+ register_command (m_priv->cmd_stop);
+ register_command (m_priv->cmd_nexti);
+ register_command (m_priv->cmd_stepi);
+ register_command (m_priv->cmd_open);
+}
+
+void
+DBGConsole::current_file_path (const UString &a_file_path)
+{
+ THROW_IF_FAIL (m_priv);
+ m_priv->data.current_file_path = a_file_path;
+}
+
+const UString&
+DBGConsole::current_file_path () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->data.current_file_path;
+}
+
+DBGConsole::~DBGConsole ()
+{
+}
+
+sigc::signal<void, UString>
+DBGConsole::file_opened_signal () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->cmd_open.file_opened_signal;
+}
+
+NEMIVER_END_NAMESPACE(nemiver)
+
diff --git a/src/dbgengine/nmv-dbg-console.h b/src/dbgengine/nmv-dbg-console.h
new file mode 100644
index 0000000..d2a8b6b
--- /dev/null
+++ b/src/dbgengine/nmv-dbg-console.h
@@ -0,0 +1,58 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_DBG_CONSOLE_H__
+#define __NMV_DBG_CONSOLE_H__
+
+#include "common/nmv-console.h"
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+
+namespace common {
+ class UString;
+}
+
+class IDebugger;
+
+using common::SafePtr;
+using common::UString;
+
+class DBGConsole : public common::Console {
+ struct Priv;
+ SafePtr<Priv> m_priv;
+
+public:
+ DBGConsole (int a_fd, IDebugger &a_debugger);
+ ~DBGConsole ();
+
+ void current_file_path (const UString &a_file_path);
+ const UString& current_file_path () const;
+
+ sigc::signal<void, UString> file_opened_signal () const;
+};
+
+NEMIVER_END_NAMESPACE(nemiver)
+
+#endif /* __NMV_DBG_CONSOLE_H__ */
+
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 48cf7bb..e3b68da 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -53,6 +53,7 @@
#include "common/nmv-str-utils.h"
#include "common/nmv-address.h"
#include "common/nmv-loc.h"
+#include "nmv-dbg-console.h"
#include "nmv-sess-mgr.h"
#include "nmv-dbg-perspective.h"
#include "nmv-source-editor.h"
@@ -118,6 +119,7 @@ const char *TARGET_TERMINAL_VIEW_TITLE = _("Target Terminal");
const char *BREAKPOINTS_VIEW_TITLE = _("Breakpoints");
const char *REGISTERS_VIEW_TITLE = _("Registers");
const char *MEMORY_VIEW_TITLE = _("Memory");
+const char *CONSOLE_VIEW_TITLE = _("Console");
const char *CAPTION_SESSION_NAME = "captionname";
const char *SESSION_NAME = "sessionname";
@@ -412,6 +414,7 @@ private:
void on_notebook_tabs_reordered(Gtk::Widget* a_page, guint a_page_num);
void on_layout_changed ();
+ void on_file_opened (UString a_path);
void on_activate_context_view ();
void on_activate_target_terminal_view ();
void on_activate_breakpoints_view ();
@@ -739,6 +742,10 @@ public:
Gtk::ScrolledWindow& get_local_vars_inspector_scrolled_win ();
+ Terminal& console_terminal ();
+
+ Gtk::Box& console_box ();
+
Terminal& get_terminal ();
Gtk::Box& get_terminal_box ();
@@ -897,6 +904,9 @@ struct DBGPerspective::Priv {
Path2MonitorMap path_2_monitor_map;
SafePtr<LocalVarsInspector> variables_editor;
SafePtr<Gtk::ScrolledWindow> variables_editor_scrolled_win;
+ SafePtr<Terminal> console_terminal;
+ SafePtr<DBGConsole> dbg_console;
+ SafePtr<Gtk::Box> console_box;
SafePtr<Terminal> terminal;
SafePtr<Gtk::Box> terminal_box;
SafePtr<Gtk::ScrolledWindow> breakpoints_scrolled_win;
@@ -1761,6 +1771,17 @@ DBGPerspective::on_switch_page_signal (Gtk::Widget *a_page,
NEMIVER_TRY
m_priv->current_page_num = a_page_num;
LOG_DD ("current_page_num: " << m_priv->current_page_num);
+
+ map<int, SourceEditor*>::iterator iter, nil;
+ nil = m_priv->pagenum_2_source_editor_map.end ();
+ iter = m_priv->pagenum_2_source_editor_map.find (m_priv->current_page_num);
+ if (iter != nil) {
+ SourceEditor *editor = get_current_source_editor ();
+ if (editor) {
+ THROW_IF_FAIL (m_priv->dbg_console);
+ m_priv->dbg_console->current_file_path (editor->get_path ());
+ }
+ }
NEMIVER_CATCH
}
@@ -2811,6 +2832,14 @@ DBGPerspective::on_layout_changed ()
}
void
+DBGPerspective::on_file_opened (UString a_file)
+{
+ NEMIVER_TRY
+ open_file (a_file, -1);
+ NEMIVER_CATCH
+}
+
+void
DBGPerspective::on_activate_context_view ()
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -3685,6 +3714,11 @@ DBGPerspective::init_body ()
(sigc::mem_fun (this, &DBGPerspective::on_notebook_tabs_reordered));
#endif
+ IDebuggerSafePtr& dbg = debugger ();
+ THROW_IF_FAIL (dbg);
+ m_priv->dbg_console.reset
+ (new DBGConsole (console_terminal ().slave_fd (), *dbg));
+
UString layout = DBG_PERSPECTIVE_DEFAULT_LAYOUT;
NEMIVER_TRY
conf_mgr.get_key_value (CONF_KEY_DBG_PERSPECTIVE_LAYOUT, layout);
@@ -3732,6 +3766,10 @@ DBGPerspective::init_signals ()
m_priv->layout_mgr.layout_changed_signal ().connect (sigc::mem_fun
(*this, &DBGPerspective::on_layout_changed));
+
+ THROW_IF_FAIL (m_priv->dbg_console);
+ m_priv->dbg_console->file_opened_signal ().connect (sigc::mem_fun
+ (*this, &DBGPerspective::on_file_opened));
}
/// Connect slots (callbacks) to the signals emitted by the
@@ -4928,6 +4966,9 @@ DBGPerspective::add_views_to_layout ()
{
THROW_IF_FAIL (m_priv);
+ m_priv->layout ().add_view (console_box (),
+ CONSOLE_VIEW_TITLE,
+ CONSOLE_VIEW_INDEX);
#ifdef WITH_MEMORYVIEW
m_priv->layout ().add_view (get_memory_view ().widget (),
MEMORY_VIEW_TITLE,
@@ -8011,6 +8052,39 @@ DBGPerspective::get_local_vars_inspector_scrolled_win ()
return *m_priv->variables_editor_scrolled_win;
}
+Terminal&
+DBGPerspective::console_terminal ()
+{
+ THROW_IF_FAIL (m_priv);
+ if (!m_priv->console_terminal) {
+ string relative_path = Glib::build_filename ("menus",
+ "terminalmenu.xml");
+ string absolute_path;
+ THROW_IF_FAIL (build_absolute_resource_path
+ (Glib::filename_to_utf8 (relative_path), absolute_path));
+
+ m_priv->console_terminal.reset (new Terminal
+ (absolute_path, workbench ().get_ui_manager ()));
+ }
+ THROW_IF_FAIL (m_priv->console_terminal);
+ return *m_priv->console_terminal;
+}
+
+Gtk::Box&
+DBGPerspective::console_box ()
+{
+ THROW_IF_FAIL (m_priv);
+ if (!m_priv->console_box) {
+ m_priv->console_box.reset (new Gtk::HBox);
+ THROW_IF_FAIL (m_priv->console_box);
+ Gtk::VScrollbar *scrollbar = Gtk::manage (new Gtk::VScrollbar);
+ m_priv->console_box->pack_end (*scrollbar, false, false, 0);
+ m_priv->console_box->pack_start (console_terminal ().widget ());
+ scrollbar->set_adjustment (console_terminal ().adjustment ());
+ }
+ THROW_IF_FAIL (m_priv->console_box);
+ return *m_priv->console_box;
+}
Terminal&
DBGPerspective::get_terminal ()
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index ddb00ff..cc0ea7b 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -39,6 +39,7 @@ extern const char *TARGET_TERMINAL_VIEW_TITLE;
extern const char *BREAKPOINTS_VIEW_TITLE;
extern const char *REGISTERS_VIEW_TITLE;
extern const char *MEMORY_VIEW_TITLE;
+extern const char *CONSOLE_VIEW_TITLE;
enum ViewsIndex
{
@@ -47,8 +48,9 @@ enum ViewsIndex
BREAKPOINTS_VIEW_INDEX,
REGISTERS_VIEW_INDEX,
#ifdef WITH_MEMORYVIEW
- MEMORY_VIEW_INDEX
+ MEMORY_VIEW_INDEX,
#endif // WITH_MEMORYVIEW
+ CONSOLE_VIEW_INDEX
};
class SourceEditor;
diff --git a/src/uicommon/nmv-terminal.cc b/src/uicommon/nmv-terminal.cc
index 5222bd1..3ae6da1 100644
--- a/src/uicommon/nmv-terminal.cc
+++ b/src/uicommon/nmv-terminal.cc
@@ -335,6 +335,12 @@ Terminal::feed (const UString &a_text)
vte_terminal_feed (m_priv->vte, a_text.c_str (), a_text.size ());
}
+int
+Terminal::slave_fd () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->slave_pty;
+}
NEMIVER_END_NAMESPACE(nemiver)
diff --git a/src/uicommon/nmv-terminal.h b/src/uicommon/nmv-terminal.h
index 6f5b9ed..13d8818 100644
--- a/src/uicommon/nmv-terminal.h
+++ b/src/uicommon/nmv-terminal.h
@@ -67,6 +67,7 @@ public:
Gtk::Widget& widget () const;
Glib::RefPtr<Gtk::Adjustment> adjustment () const;
UString slave_pts_name () const;
+ int slave_fd () const;
void modify_font (const Pango::FontDescription &font_desc);
void feed (const UString &a_text);
};//end class Terminal
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]