[nemiver/jump-to] 560235 Initial support of "jump to"



commit 4b3d4116fd9fe7f24f6625810175d6ca36d6b8df
Author: Dodji Seketeli <dodji seketeli org>
Date:   Fri Mar 25 09:50:50 2011 +0100

    560235 Initial support of "jump to"
    
    	* src/common/nmv-loc.h: New location type declarations.
    	* src/common/Makefile.am: Add it to build system.
    	* src/dbgengine/nmv-i-debugger.h (IDebugger::DefaultSlot)
    	(IDebugger::BreakpointsSlot, IDebugger::LocSlot): New slot
    	typedefs.
    	(IDebugger::jump_to_position): New entry point.
    	(IDebugger::set_breakpoint, IDebugger::enable_breakpoint): New
    	overloads taking callback slots.
    	* src/dbgengine/nmv-gdb-engine.h (GDBEngine::jump_to_position)
    	(GDBEngine::set_breakpoint, GDBEngine::enable_breakpoint): Declare
    	these functions.
    	* src/dbgengine/nmv-gdb-engine.cc (location_to_string): New
    	function overloads to generate a GDB location string for each type
    	of location.
    	(OnBreakpointHandler::do_handle): Support callback slots for
    	commands 'set-breakpoint', '-break-enable' and 'jump-to-position'.
    	(GDBEngine::jump_to_position): Define new function.
    	(GDBEngine::set_breakpoint): Add new overload that takes a
    	callback slot and an instance of location type.
    	(GDBEngine::enable_breakpoint): Likewise.  Rewrite the other
    	overload in terms of this one.
    	(null_disass_slot): Move this to nmv-debugger-utils.cc
    	* src/dbgengine/nmv-debugger-utils.h ((null_default_slot,
    	null_disass_slot, null_breakpoints_slot): Declare new functions.
    	* src/dbgengine/nmv-debugger-utils.cc (null_default_slot)
    	(null_disass_slot, null_breakpoints_slot): Define new functions.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc
    	(DBGPerspective::on_jump_to_current_location_action)
    	(DBGPerspective::on_jump_and_break_to_current_location_action)
    	(DBGPerspective::on_break_before_jump)
    	(DBGPerspective::do_jump_to_current_location)
    	(DBGPerspective::do_jump_and_break_to_current_location)
    	(DBGPerspective::jump_to_location): New functions.
    	(DBGPerspective::on_debugger_breakpoints_set_signal): Minor style
    	cleanup.
    	(DBGPerspective::init_actions): Add
    	JumpToCurrentLocationMenuItemAction and
    	JumpAndBreakToCurrentLocationMenuItemAction actions.
    	(DBGPerspective::get_contextual_menu): Add two new menu items for
    	actions JumpToCurrentLocationMenuItemAction and
    	JumpAndBreakToCurrentLocationMenuItemAction.

 src/common/Makefile.am                          |    3 +-
 src/common/nmv-loc.h                            |  136 +++++++++++++
 src/dbgengine/nmv-debugger-utils.cc             |   21 ++
 src/dbgengine/nmv-debugger-utils.h              |   12 ++
 src/dbgengine/nmv-gdb-engine.cc                 |  231 +++++++++++++++++++++-
 src/dbgengine/nmv-gdb-engine.h                  |   15 ++-
 src/dbgengine/nmv-i-debugger.h                  |   19 ++
 src/persp/dbgperspective/nmv-dbg-perspective.cc |  177 +++++++++++++++++-
 8 files changed, 597 insertions(+), 17 deletions(-)
---
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index eaa09d0..5b61d90 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -41,7 +41,8 @@ $(h)/nmv-sql-statement.h \
 $(h)/nmv-insert-statement.h \
 $(h)/nmv-delete-statement.h \
 $(h)/nmv-proc-utils.h \
-$(h)/nmv-proc-mgr.h
+$(h)/nmv-proc-mgr.h \
+$(h)/nmv-loc.h
 
 libnemivercommon_la_SOURCES= $(headers) \
 $(h)/nmv-ustring.cc \
diff --git a/src/common/nmv-loc.h b/src/common/nmv-loc.h
new file mode 100644
index 0000000..67749a9
--- /dev/null
+++ b/src/common/nmv-loc.h
@@ -0,0 +1,136 @@
+//Author: Dodji Seketeli
+/*
+ *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 __NEMIVER_LOC_H__
+#define __NEMIVER_LOC_H__
+
+#include "nmv-ustring.h"
+#include "nmv-address.h"
+#include "nmv-api-macros.h"
+
+/// \file
+/// The declaration of source, function and addresses related location
+/// types.  For now, it's only the debugging engine backend that knows
+/// how to serialize a location into a location string.
+
+NEMIVER_BEGIN_NAMESPACE (nemiver)
+NEMIVER_BEGIN_NAMESPACE (common)
+
+///  The base type presenting a location.
+class NEMIVER_API Loc
+{
+ public:
+    /// The different possible kinds of locations.
+    enum Kind
+    {
+        UNDEFINED_LOC_KIND,
+        SOURCE_LOC_KIND,
+        FUNCTION_LOC_KIND,
+        ADDRESS_LOC_KIND
+    };
+
+ protected:
+    Kind m_kind;
+
+    Loc ()
+        : m_kind (UNDEFINED_LOC_KIND)
+    {
+    }
+    
+    Loc (const Loc &a)
+    {
+        m_kind = a.kind ();
+    }
+
+ public:
+    Kind kind () const {return m_kind;}
+    virtual ~Loc () {};
+}; // end class Loc
+
+/// A source location.
+/// 
+/// It encapsulates a file name and a line number
+/// in that file.
+class NEMIVER_API SourceLoc : public Loc
+{
+    UString m_file_path;
+    int m_line_number;
+
+ public:
+    SourceLoc (const UString &a_file_path,
+               int a_line_number)
+        : m_file_path (a_file_path),
+        m_line_number (a_line_number)
+    {
+        m_kind = SOURCE_LOC_KIND;
+    }
+
+    const UString& file_path () const {return m_file_path;}
+    void file_path (const UString &a) {m_file_path = a;}
+    int line_number () const {return m_line_number;}
+    void line_number (int a) {m_line_number = a;}
+};// end class SourceLoc;
+
+/// A function location.
+///
+/// It encapsulates the location of a function.
+class NEMIVER_API FunctionLoc : public Loc
+{
+    UString m_function_name;
+
+ public:
+    FunctionLoc (const UString &a_function_name)
+        : m_function_name (a_function_name)
+    {
+        m_kind = FUNCTION_LOC_KIND;
+
+    }
+
+    const UString& function_name () const {return m_function_name;}
+    void function_name (const UString &a) {m_function_name = a;}
+};
+
+/// An address location.
+///
+/// It encapslates an address.
+class NEMIVER_API AddressLoc : public Loc
+{
+    Address m_address;
+
+ public:
+    AddressLoc (const Address &a)
+        : m_address (a)
+    {
+        m_kind = ADDRESS_LOC_KIND;
+    }
+
+    const Address& address () const {return m_address;}
+    void address (const Address &a) {m_address = a;}
+};
+
+NEMIVER_END_NAMESPACE (common)
+NEMIVER_END_NAMESPACE (nemiver)
+
+#endif //__NEMIVER_LOC_H__
diff --git a/src/dbgengine/nmv-debugger-utils.cc b/src/dbgengine/nmv-debugger-utils.cc
index 4e78dd1..9c97815 100644
--- a/src/dbgengine/nmv-debugger-utils.cc
+++ b/src/dbgengine/nmv-debugger-utils.cc
@@ -29,6 +29,10 @@
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 NEMIVER_BEGIN_NAMESPACE (debugger_utils)
 
+/// \name Definitions of no-op callback slots that can used by client
+/// code.
+/// 
+/// @{
 void
 null_const_variable_slot (const IDebugger::VariableSafePtr &)
 {
@@ -54,6 +58,23 @@ null_frame_args_slot (const map<int, IDebugger::VariableList> &)
 {
 }
 
+void
+null_default_slot ()
+{
+}
+
+void
+null_disass_slot (const common::DisassembleInfo &,
+                  const std::list<common::Asm> &)
+{
+}
+
+void
+null_breakpoints_slot (const map<int, IDebugger::Breakpoint>&)
+{
+}
+///@}
+
 /// Generate a string of of white spaces.
 /// \param a_nb_ws the number of white spaces to generate
 /// \param a_ws_str the output string the white spaces are
diff --git a/src/dbgengine/nmv-debugger-utils.h b/src/dbgengine/nmv-debugger-utils.h
index 75026d7..479d13c 100644
--- a/src/dbgengine/nmv-debugger-utils.h
+++ b/src/dbgengine/nmv-debugger-utils.h
@@ -32,6 +32,9 @@
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 NEMIVER_BEGIN_NAMESPACE (debugger_utils)
 
+/// \name Declarations of no-op callback slots
+///
+/// @{
 void null_const_variable_slot (const IDebugger::VariableSafePtr &);
 
 void null_const_variable_list_slot (const IDebugger::VariableList &);
@@ -42,6 +45,15 @@ void null_frame_vector_slot (const vector<IDebugger::Frame> &);
 
 void null_frame_args_slot (const map<int, IDebugger::VariableList> &);
 
+void null_default_slot ();
+
+void null_disass_slot (const common::DisassembleInfo &,
+		       const std::list<common::Asm> &);
+
+void null_breakpoints_slot (const map<int, IDebugger::Breakpoint>&);
+
+/// @}
+
 void dump_variable_value (IDebugger::VariableSafePtr a_var,
                           int a_indent_num,
                           std::ostringstream &a_os,
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 3f7b184..7123bd5 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -57,6 +57,8 @@ using nemiver::debugger_utils::null_const_variable_slot;
 using nemiver::debugger_utils::null_const_variable_list_slot;
 using nemiver::debugger_utils::null_frame_vector_slot;
 using nemiver::debugger_utils::null_frame_args_slot;
+using nemiver::debugger_utils::null_disass_slot;
+using nemiver::debugger_utils::null_breakpoints_slot;
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
@@ -79,6 +81,88 @@ quote_args (const vector<UString> &a_prog_args)
     return args;
 }
 
+//**************************************************************
+// <Helper functions to generate a serialized form of location>
+//**************************************************************
+
+/// Generate a location string from a an instance of source location
+/// type.
+///
+/// \param a_loc the source input location
+///
+/// \param a_str the resulting location string
+static void
+location_to_string (const SourceLoc &a_loc,
+                    UString &a_str)
+{
+    a_str =
+        a_loc.file_path ()
+        + ":" + UString::from_int (a_loc.line_number ());
+}
+
+/// Generate a location string from a an instance of address location
+/// type.
+///
+/// \param a_loc the input address location
+///
+/// \param a_str the resulting location string
+static void
+location_to_string (const AddressLoc &a_loc,
+                    UString &a_str)
+{
+    a_str = "*" + a_loc.address ().to_string ();
+}
+
+/// Generate a location string from a an instance of function location
+/// type.
+///
+/// \param a_loc the input function location
+///
+/// \param a_str the resulting location string
+static void
+location_to_string (const FunctionLoc &a_loc,
+                    UString &a_str)
+{
+    a_str = a_loc.function_name ();
+}
+
+/// Generate a location string from a generic instance of location
+/// type.
+///
+/// \param a_loc the input location
+///
+/// \param a_str the resulting location string
+static void
+location_to_string (const Loc &a_loc,
+                    UString &a_str)
+{
+    switch (a_loc.kind ()) {
+    case Loc::UNDEFINED_LOC_KIND:
+        THROW ("Should not be reached");
+
+    case Loc::SOURCE_LOC_KIND: {
+        const SourceLoc *loc = static_cast<const SourceLoc*> (&a_loc);
+        location_to_string (*loc, a_str);
+    }
+        break;
+
+    case Loc::FUNCTION_LOC_KIND: {
+        const FunctionLoc *loc = static_cast<const FunctionLoc*> (&a_loc);
+        location_to_string (*loc, a_str);
+    }
+        break;
+
+    case Loc::ADDRESS_LOC_KIND: {
+        const AddressLoc *loc = static_cast<const AddressLoc*> (&a_loc);
+        location_to_string (*loc, a_str);
+    }
+        break;
+    }
+}
+
+//**************************************************************
+// </Helper functions to generate a serialized form of location>
+//**************************************************************
 
 //*************************
 //<GDBEngine::Priv struct>
@@ -1330,6 +1414,12 @@ struct OnBreakpointHandler: OutputHandler {
             }
         } else if (has_breaks) {
             LOG_DD ("firing IDebugger::breakpoint_set_signal()");
+            Command &c = a_in.command ();
+            if (c.name () == "set-breakpoint"
+                && c.has_slot ()) {
+                IDebugger::BreakpointsSlot slot = c.get_slot<IDebugger::BreakpointsSlot> ();
+                slot (m_engine->get_cached_breakpoints ());
+            }
             m_engine->breakpoints_set_signal ().emit
                 (m_engine->get_cached_breakpoints (),
                  a_in.command ().cookie ());
@@ -1614,6 +1704,13 @@ struct OnCommandDoneHandler : OutputHandler {
             }
         }
 
+        if (a_in.command ().name () == "-break-enable"
+            && a_in.command ().has_slot ()) {
+            IDebugger::BreakpointsSlot slot =
+                a_in.command ().get_slot<IDebugger::BreakpointsSlot> ();
+            slot (m_engine->get_cached_breakpoints ());
+        }
+
         // So, if we are still attached to the target and we receive
         // a "DONE" response from GDB, it means we are READY.
         // But if we are not attached -- which can mean that the
@@ -1652,7 +1749,13 @@ struct OnRunningHandler : OutputHandler {
     void do_handle (CommandAndOutput &a_in)
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
-        if (a_in.has_command ()) {}
+
+        Command &c = a_in.command ();
+        if (c.name () == "jump-to-position"
+            && c.has_slot ()) {
+            IDebugger::DefaultSlot s = c.get_slot<IDebugger::DefaultSlot> ();
+            s ();
+        }
         m_engine->running_signal ().emit ();
     }
 };//struct OnRunningHandler
@@ -3778,6 +3881,85 @@ GDBEngine::continue_to_position (const UString &a_path,
                             a_cookie));
 }
 
+/// Jump to a location in the inferior.
+///
+/// Execution is then resumed from the new location.
+///
+/// \param a_loc the location to jump to
+///
+/// \param a_slot a callback function that is invoked once the jump is
+/// done.
+void
+GDBEngine::jump_to_position (const Loc &a_loc,
+                             const DefaultSlot &a_slot)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    UString location;
+
+    location_to_string (a_loc, location);
+
+    Command command ("jump-to-position",
+                     "-exec-jump " + location);
+    command.set_slot (a_slot);
+    queue_command (command);
+}
+
+/// Set a breakpoint at a location in the inferior.
+///
+/// \param a_loc the location of the breakpoint.
+///
+/// \param a_condition the condition of the breakpoin.  If there is no
+/// condition, the argument should be "".
+///
+/// \param a_ignore_count the number of time the breakpoint should be
+/// hit before execution of the inferior is stopped.
+///
+/// \param a_slot a callback slot to be invoked once the breakpoint is
+/// set.
+///
+/// \param a_cookie a string to be passed to
+/// IDebugger::breakpoints_set_signals once that signal emitted as a
+/// result of the breakpoint being set.  Note both a_slot and
+/// IDebugger::breakpoint_set_signals are 'called' upon breakpoint
+/// actual setting.  Eventually, IDebugger::breakpoints_set_signals
+/// should be dropped, so this whole cookie business would disapear.
+/// We are still in a transitional period.
+void
+GDBEngine::set_breakpoint (const Loc &a_loc,
+                           const UString &a_condition,
+                           gint a_ignore_count,
+                           const BreakpointsSlot &a_slot,
+                           const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    THROW_IF_FAIL (a_loc.kind () != Loc::UNDEFINED_LOC_KIND);
+
+    UString loc_str;
+
+    location_to_string (a_loc, loc_str);
+
+    UString break_cmd = "-break-insert -f ";
+    if (!a_condition.empty ()) {
+        LOG_DD ("setting breakpoint with condition: " << a_condition);
+        break_cmd += " -c \"" + a_condition + "\"";
+    } else {
+        LOG_DD ("setting breakpoint without condition");
+    }
+
+    bool count_point = (a_ignore_count < 0);
+    if (!count_point)
+        break_cmd += " -i " + UString::from_int (a_ignore_count);
+
+    break_cmd += " " + loc_str;
+    string cmd_name = count_point ? "set-countpoint" : "set-breakpoint";
+    
+    Command command (cmd_name, break_cmd, a_cookie);
+    command.set_slot (a_slot);
+    queue_command (command);
+}
+
 void
 GDBEngine::set_breakpoint (const UString &a_path,
                            gint a_line_num,
@@ -3837,18 +4019,51 @@ GDBEngine::set_breakpoint (const Address &a_address,
     queue_command (Command (cmd_name, break_cmd, a_cookie));
 }
 
+/// Enable a given breakpoint
+///
+/// \param a_break_num the ID of the breakpoint to enable.
+///
+/// \param a_slot a callback slot invoked upon completion of the
+/// command by GDB.
+///
+/// \param a_cookie a string passed as an argument to
+/// IDebugger::breakpoints_set_signal upon completion of the command
+/// by GDB.  Note that both a_slot and
+/// IDebugger::breakpoints_set_signal are invoked upon completion of
+/// the command by GDB for now.  Eventually only a_slot will be kept;
+/// IDebugger::breakpoints_set_signal will be dropped.  We in a
+/// transitional period at the moment.
 void
 GDBEngine::enable_breakpoint (gint a_break_num,
+                              const BreakpointsSlot &a_slot,
                               const UString &a_cookie)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
-    queue_command (Command ("enable-breakpoint",
-                            "-break-enable "
-                             + UString::from_int (a_break_num),
-                            a_cookie));
+    
+    Command command ("enable-breakpoint",
+                     "-break-enable "
+                     + UString::from_int (a_break_num));
+    command.set_slot (a_slot);
+    queue_command (command);
     list_breakpoints (a_cookie);
 }
 
+/// Enable a given breakpoint
+///
+/// \param a_break_num the ID of the breakpoint to enable.
+///
+/// \param a_cookie a string passed as an argument to
+/// IDebugger::breakpoints_set_signal upon completion of the command
+/// by GDB.  Eventually this function should be dropped and we should
+/// keep the one above.
+void
+GDBEngine::enable_breakpoint (gint a_break_num,
+                              const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+    enable_breakpoint (a_break_num, &null_breakpoints_slot, a_cookie);
+}
+
 void
 GDBEngine::disable_breakpoint (gint a_break_num,
                                const UString &a_cookie)
@@ -4861,12 +5076,6 @@ GDBEngine::set_memory (size_t a_addr,
 }
 
 void
-null_disass_slot (const common::DisassembleInfo &,
-                  const std::list<common::Asm> &)
-{
-}
-
-void
 GDBEngine::disassemble (size_t a_start_addr,
                         bool a_start_addr_relative_to_pc,
                         size_t a_end_addr,
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index 964a641..89e9cb9 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -328,11 +328,20 @@ public:
                                gint a_line_num,
                                const UString &a_cookie) ;
 
+    void jump_to_position (const Loc &a_loc,
+			   const DefaultSlot &a_slot);
+
+    void set_breakpoint (const Loc &a_loc,
+			 const UString &a_condition,
+			 gint a_ignore_count,
+			 const BreakpointsSlot &a_slot,
+			 const UString &a_cookie);
+
     void set_breakpoint (const UString &a_path,
                          gint a_line_num,
                          const UString &a_condition,
                          gint a_ignore_count,
-                         const UString &a_cookie) ;
+                         const UString &a_cookie);
 
     void set_breakpoint (const UString &a_func_name,
                          const UString &a_condition,
@@ -345,6 +354,10 @@ public:
                          const UString &a_cookie);
 
     void enable_breakpoint (gint a_break_num,
+			    const BreakpointsSlot &a_slot,
+			    const UString &a_cookie = "");
+
+    void enable_breakpoint (gint a_break_num,
                             const UString &a_cookie="");
 
     void disable_breakpoint (gint a_break_num,
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 55823a8..99be184 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -37,6 +37,7 @@
 #include "common/nmv-safe-ptr-utils.h"
 #include "common/nmv-address.h"
 #include "common/nmv-asm-instr.h"
+#include "common/nmv-loc.h"
 #include "nmv-i-conf-mgr.h"
 
 using nemiver::common::SafePtr;
@@ -52,6 +53,7 @@ using nemiver::common::AsmInstr;
 using nemiver::common::MixedAsmInstr;
 using nemiver::common::Asm;
 using nemiver::common::DisassembleInfo;
+using nemiver::common::Loc;
 using std::vector;
 using std::string;
 using std::map;
@@ -819,6 +821,10 @@ public:
         return false;
     }
 
+    typedef sigc::slot<void> DefaultSlot;
+    typedef sigc::slot<void, const map<int, IDebugger::Breakpoint>&> BreakpointsSlot;
+    typedef sigc::slot<void, Loc&> LocSlot;
+    
     virtual ~IDebugger () {}
 
     /// \name events you can connect to.
@@ -1115,6 +1121,15 @@ public:
                                        gint a_line_num,
                                        const UString &a_cookie="") = 0;
 
+    virtual void jump_to_position (const Loc &a_loc,
+                                   const DefaultSlot &a_slot) = 0;
+
+    virtual void set_breakpoint (const common::Loc &a_loc,
+                                 const UString &a_condition,
+                                 gint a_ignore_count,
+                                 const BreakpointsSlot &a_slot,
+                                 const UString &a_cookie = "") = 0;
+
     virtual void set_breakpoint (const UString &a_path,
                                  gint a_line_num,
                                  const UString &a_condition= "",
@@ -1132,6 +1147,10 @@ public:
                                  const UString &a_cookie = "") = 0;
 
     virtual void enable_breakpoint (gint a_break_num,
+                                    const BreakpointsSlot &a_slot,
+                                    const UString &a_cookie="") = 0;
+
+    virtual void enable_breakpoint (gint a_break_num,
                                     const UString &a_cookie="") = 0;
 
     virtual void disable_breakpoint (gint a_break_num,
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 88ef7d0..d1f5131 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -64,6 +64,7 @@
 #include "common/nmv-date-utils.h"
 #include "common/nmv-str-utils.h"
 #include "common/nmv-address.h"
+#include "common/nmv-loc.h"
 #include "nmv-sess-mgr.h"
 #include "nmv-dbg-perspective.h"
 #include "nmv-source-editor.h"
@@ -102,6 +103,7 @@
 
 using namespace std;
 using namespace nemiver::common;
+using namespace nemiver::debugger_utils;
 using namespace nemiver::ui_utils;
 using namespace gtksourceview;
 
@@ -236,6 +238,10 @@ private:
     void on_step_over_asm_action ();
     void on_continue_action ();
     void on_continue_until_action ();
+    void on_jump_to_current_location_action ();
+    void on_jump_and_break_to_current_location_action ();
+    void on_break_before_jump (const map<int, IDebugger::Breakpoint>&,
+                               const Loc &a_loc);
     void on_set_breakpoint_action ();
     void on_set_breakpoint_using_dialog_action ();
     void on_set_watchpoint_using_dialog_action ();
@@ -597,6 +603,9 @@ public:
     void step_over_asm ();
     void do_continue ();
     void do_continue_until ();
+    void do_jump_to_current_location ();
+    void do_jump_and_break_to_current_location ();
+    void jump_to_location (const map<int, IDebugger::Breakpoint>&, const SourceLoc &);
     void set_breakpoint_at_current_line_using_dialog ();
     void set_breakpoint ();
     void set_breakpoint (const UString &a_file,
@@ -1008,7 +1017,6 @@ struct DBGPerspective::Priv {
     list<UString> call_expr_history;
     list<UString> var_inspector_dialog_history;
 
-
     Priv () :
         initialized (false),
         reused_session (false),
@@ -1544,6 +1552,56 @@ DBGPerspective::on_continue_until_action ()
     NEMIVER_CATCH
 }
 
+/// Callback function invoked when the menu item action "jump to
+/// current location" is activated.
+///
+/// It jumps to the location selected by the user in the source
+/// editor.
+void
+DBGPerspective::on_jump_to_current_location_action ()
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    NEMIVER_TRY
+    do_jump_to_current_location ();
+    NEMIVER_CATCH
+}
+
+/// Callback function invoked when the menu item action "setting a
+/// breakpoint to current lcoation and jump here" is activated.
+///
+/// It sets a breakpoint to the current location and jumps here.  So
+/// is transfered to the location selected by the user in the source
+/// editor and is stopped there.
+void
+DBGPerspective::on_jump_and_break_to_current_location_action ()
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    NEMIVER_TRY
+    do_jump_and_break_to_current_location ();
+    NEMIVER_CATCH
+}
+
+/// This callback is invoked right after a breakpoint is set as part
+/// of a "set a breakpoint and jump there" process.
+///
+/// So this function jumps to the position given in parameter.
+///
+/// \param a_loc the location to jump to.  This is also the location
+/// of the breakpoint that was set previously and which triggered this
+/// callback.
+void
+DBGPerspective::on_break_before_jump (const map<int, IDebugger::Breakpoint> &,
+                                      const Loc &a_loc)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+    
+    NEMIVER_TRY;
+    debugger ()->jump_to_position (a_loc, &null_default_slot);
+    NEMIVER_CATCH;
+}
+
 void
 DBGPerspective::on_toggle_breakpoint_action ()
 {
@@ -2518,6 +2576,13 @@ DBGPerspective::on_debugger_command_done_signal (const UString &a_command,
     NEMIVER_CATCH
 }
 
+/// Callback function invoked once a breakpoint was set.
+///
+/// \param a_breaks the list of all breakpoints currently set in the inferior.
+///
+/// \param a_cookie a string passed to the IDebugger::set_breakpoint
+/// call that triggered this callback.
+///
 void
 DBGPerspective::on_debugger_breakpoints_set_signal
                             (const map<int, IDebugger::Breakpoint> &a_breaks,
@@ -2532,9 +2597,9 @@ DBGPerspective::on_debugger_breakpoints_set_signal
     // When the breakpoint is set, it
     // will send a 'cookie' along of the form
     // "initiallly-disabled#filename.cc#123"
-    if (a_cookie.find("initially-disabled") != UString::npos) {
-        UString::size_type start_of_file = a_cookie.find('#') + 1;
-        UString::size_type start_of_line = a_cookie.rfind('#') + 1;
+    if (a_cookie.find ("initially-disabled") != UString::npos) {
+        UString::size_type start_of_file = a_cookie.find ('#') + 1;
+        UString::size_type start_of_line = a_cookie.rfind ('#') + 1;
         UString file = a_cookie.substr (start_of_file,
                                         (start_of_line - 1) - start_of_file);
         int line = atoi
@@ -3391,6 +3456,27 @@ DBGPerspective::init_actions ()
             false
         },
         {
+            "JumpToCurrentLocationMenuItemAction",
+            nil_stock_id,
+            _("Jump to cursor"),
+            _("Jump to  the currently selected line"),
+            sigc::mem_fun (*this, &DBGPerspective::on_jump_to_current_location_action),
+            ActionEntry::DEFAULT,
+            "",
+            false
+        },
+        {
+            "JumpAndBreakToCurrentLocationMenuItemAction",
+            nil_stock_id,
+            _("Jump and stop to cursor"),
+            _("Sets a breakpoint to the current currently selected line and jump there"),
+            sigc::mem_fun (*this,
+                           &DBGPerspective::on_jump_and_break_to_current_location_action),
+            ActionEntry::DEFAULT,
+            "",
+            false
+        },
+        {
             "ToggleBreakpointMenuItemAction",
             nil_stock_id,
             // Depending on the context we will want this string to be
@@ -4763,6 +4849,22 @@ DBGPerspective::get_contextual_menu ()
         workbench ().get_ui_manager ()->add_ui
             (m_priv->contextual_menu_merge_id,
              "/ContextualMenu",
+             "JumpToCurrentLocationMenuItem",
+             "JumpToCurrentLocationMenuItemAction",
+             Gtk::UI_MANAGER_AUTO,
+             false);
+
+        workbench ().get_ui_manager ()->add_ui
+            (m_priv->contextual_menu_merge_id,
+             "/ContextualMenu",
+             "JumpAndBreakToCurrentLocationMenuItem",
+             "JumpAndBreakToCurrentLocationMenuItemAction",
+             Gtk::UI_MANAGER_AUTO,
+             false);
+
+        workbench ().get_ui_manager ()->add_ui
+            (m_priv->contextual_menu_merge_id,
+             "/ContextualMenu",
              "StopMenuItem",
              "StopMenuItemAction",
              Gtk::UI_MANAGER_AUTO,
@@ -6698,6 +6800,73 @@ DBGPerspective::do_continue_until ()
     debugger ()->continue_to_position (file_path, current_line);
 }
 
+/// Jump (transfer execution of the inferior) to the location selected
+/// by the user in the source editor.
+void
+DBGPerspective::do_jump_to_current_location ()
+{
+    SourceEditor *editor = get_current_source_editor ();
+    THROW_IF_FAIL (editor);
+
+    int current_line = editor->current_line ();
+    UString file_path;
+    editor->get_file_name (file_path);
+    SourceLoc loc (file_path, current_line);
+    debugger ()->jump_to_position (loc, &null_default_slot);
+}
+
+/// Set a breakpoint to the location selected by the user in the
+/// source editor and jump (transfer execution of the inferior) there.
+void
+DBGPerspective::do_jump_and_break_to_current_location ()
+{
+    THROW_IF_FAIL (m_priv);
+    SourceEditor *editor = get_current_source_editor ();
+    THROW_IF_FAIL (editor);
+
+    int current_line = editor->current_line ();
+    UString file_path;
+    editor->get_file_name (file_path);
+
+    SourceLoc loc (file_path, current_line);
+    bool bp_enabled = false;
+    if (is_breakpoint_set_at_line (file_path,
+                                   current_line,
+                                   bp_enabled)) {
+        if (bp_enabled) {
+            debugger ()->jump_to_position (loc, &null_default_slot);
+        } else {
+            const IDebugger::Breakpoint *bp =
+                get_breakpoint (file_path, current_line);
+            debugger ()->enable_breakpoint
+                (bp->number (),
+                 sigc::bind
+                 (sigc::mem_fun
+                  (*this,
+                   &DBGPerspective::jump_to_location),
+                  loc));
+        }
+    } else {
+        debugger ()->set_breakpoint (loc,
+                                     /*a_condition=*/"",/*a_ignore_count=*/0,
+                                     sigc::bind
+                                     (sigc::mem_fun
+                                      (*this,
+                                       &DBGPerspective::on_break_before_jump),
+                                      loc));
+    }
+}
+
+/// Jump (transfert execution of the inferior) to a given source
+/// location.  This is a callback for the
+/// IDebugger::breakpoint_set_signal signal.
+void
+DBGPerspective::jump_to_location (const map<int, IDebugger::Breakpoint>&,
+                                  const SourceLoc &a_loc)
+{
+    debugger ()->jump_to_position (a_loc, &null_default_slot);
+}
+
 void
 DBGPerspective::set_breakpoint ()
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]