[nemiver] 665274 - Support --just-load command line



commit 999aa2a8ad09fa486225879b4be65a20ae7a3d3d
Author: Dodji Seketeli <dodji seketeli org>
Date:   Sun Jun 17 18:35:17 2012 +0200

    665274 - Support --just-load command line
    
    	* src/dbgengine/nmv-i-debugger.h (enum IDebugger::State): Add
    	comments.  Add a new INFERIOR_LOADED enumerator.
    	(IDebugger::state_to_string): Re-indent.  Add support for new
    	INFERIOR_LOADED enumerator of IDebugger::State.
    	(IDebugger::is_running): New entry point.
    	* src/dbgengine/nmv-gdb-engine.h (GDBEngine::is_running): New
    	entry point.
    	* src/dbgengine/nmv-gdb-engine.cc (GDBEngine::Priv::is_running):
    	New member.
    	(GDBEngine::Priv::on_running_signal): New signal handler ...
    	(GDBEngine::Priv::Priv): ... connected to the running_signal event.
    	(GDBEngine::Priv::set_tty_path):  Take a new command name parm.
    	Use it when emitting the underlying command.
    	(GDBEngine::Priv::on_stopped_signal): Set
    	GDBEngine::Priv::is_running to false when the debugger exits.
    	Style cleanup.
    	(GDBEngine::OnCommandDoneHandler::do_handle): Fix state management
    	logic.  Include the new IDebugger::INFERIOR_LOADED state for when
    	the inferior is loaded but not yet run.
    	(GDBEngine::load_program): Use a proper command name for
    	underlying commands issued.  Update the "attached_to_target"
    	property.
    	(GDBEngine::attach_to_target): Adjust call to m_priv->set_tty_path.
    	(GDBEngine::is_running): New definition.
    	* src/persp/dbgperspective/nmv-dbg-perspective.h
    	(DBGPerspective::execute_program): Add a parameter for
    	'break_in_main_run'.
    	(DBGPerspective::debugger_ready_signal): Remove.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc
    	(DBGPerspective::on_debugger_ready_signal): Removed.
    	(DBGPerspective::update_action_group_sensitivity)
    	(DBGPerspective::run_real): New functions.
    	(DBGPerspective::attached_to_target): Take a IDebugger::State in
    	parameter.
    	(DBGPerspective::Priv::inferior_loaded_action_group): Renamed
    	target_connected_action_group into this.
    	(DBGPerspective::Priv::detach_action_group): New action
    	group.
    	(DBGPerspective::Priv::attached_to_target_signal): Remove.
    	(DBGPerspective::on_debugger_not_started_signal)
    	(DBGPerspective::debugger_not_started_signal): Remove.
    	(DBGPerspective::on_attached_to_target_signal): Take the debugger
    	state in parameter.  Call the new update_action_group_sensitivity.
    	(DBGPerspective::on_debugger_inferior_re_run_signal): Don't emit
    	attach_to_target_signal anymore.
    	(DBGPerspective::on_debugger_detached_from_target_signal): Rename
    	target_connected_action_group in to inferior_loaded_action_group.
    	(DBGPerspective::on_program_finished_signal): Don't emit
    	attached_to_target_signal.  Call update_action_group_sensitivity.
    	(DBGPerspective::on_debugger_state_changed_signal): Call
    	update_action_group_sensitivity.
    	(DBGPerspective::init_actions): Renamed
    	s_target_connected_action_entries into
    	s_inferior_loaded_action_entries.  Added new action group
    	s_detach_action_entries.  Re-arranged groups containing actions.
    	(DBGPerspective::restart_inferior)
    	(DBGPerspective::restart_local_inferior): Add logging.
    	(DBGPerspective::execute_program): Take a flag to break in main
    	and run.
    	(DBGPerspective::attach_to_program): Cleanup logic.
    	(DBGPerspective::run):  Use the new run_real function.
    	(DBGPerspective::do_continue): Start the inferior if it not yet
    	started.
    	(DBGPerspective::attached_to_target_signal):  Take an instance of
    	IDebugger::State as the event parameter.
    	* src/persp/dbgperspective/menus/menus.xml: Re-organized some menu
    	items.
    	* src/main.cc: Add a new --just-load option to just load the
    	inferior without trying to set a breakpoint in main and run.
    	(process_gui_options):  Adjust call to
    	DBGPerspective::execute_program.

 src/dbgengine/nmv-gdb-engine.cc                 |   96 +++--
 src/dbgengine/nmv-gdb-engine.h                  |    2 +
 src/dbgengine/nmv-i-debugger.h                  |   36 +-
 src/main.cc                                     |   15 +-
 src/persp/dbgperspective/menus/menus.xml        |   12 +-
 src/persp/dbgperspective/nmv-dbg-perspective.cc |  536 ++++++++++++-----------
 src/persp/dbgperspective/nmv-dbg-perspective.h  |   14 +-
 7 files changed, 395 insertions(+), 316 deletions(-)
---
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index ebee5eb..8140bf5 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -221,6 +221,7 @@ public:
 
     OutputHandlerList output_handler_list;
     IDebugger::State state;
+    bool is_running;
     int cur_frame_level;
     int cur_thread_num;
     Address cur_frame_address;
@@ -563,6 +564,7 @@ public:
         line_busy (false),
         error_buffer_status (DEFAULT),
         state (IDebugger::NOT_STARTED),
+        is_running (false),
         cur_frame_level (0),
         cur_thread_num (1),
         follow_fork_mode ("parent"),
@@ -582,6 +584,9 @@ public:
         gdb_stderr_signal.connect (sigc::mem_fun
                 (*this, &Priv::on_gdb_stderr_signal));
 
+        running_signal.connect
+            (sigc::mem_fun (*this, &Priv::on_running_signal));
+
         state_changed_signal.connect (sigc::mem_fun
                 (*this, &Priv::on_state_changed_signal));
 
@@ -1001,11 +1006,20 @@ public:
         queue_command (command);
     }
 
-    void set_tty_path (const UString &a_tty_path)
+    /// Sets the path to the tty used to communicate between us and GDB (or the
+    /// inferior).
+    ///
+    /// \param a_tty_path the to the tty
+    ///
+    /// \param a_command the name of the debugging command during
+    /// which we are setting the tty path.
+    void set_tty_path (const UString &a_tty_path,
+                       const UString &a_command = "")
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
         if (!a_tty_path.empty ())
-            queue_command (Command ("set inferior-tty " + a_tty_path));
+            queue_command (Command (a_command,
+                                    "set inferior-tty " + a_tty_path));
     }
 
     bool on_gdb_stdout_has_data_signal (Glib::IOCondition a_cond)
@@ -1143,6 +1157,12 @@ public:
         return true;
     }
 
+    /// Callback invoked whenever the running_signal event is fired.
+    void on_running_signal ()
+    {
+        is_running = true;
+    }
+
     void on_state_changed_signal (IDebugger::State a_state)
     {
         state = a_state;
@@ -1162,7 +1182,9 @@ public:
         NEMIVER_CATCH_NOX
     }
 
-    void on_stopped_signal (IDebugger::StopReason,
+    /// Callback function invoked when the IDebugger::stopped_signal
+    /// event is fired.
+    void on_stopped_signal (IDebugger::StopReason a_reason,
                             bool a_has_frame,
                             const IDebugger::Frame &,
                             int,
@@ -1170,13 +1192,17 @@ public:
                             const UString &a_cookie)
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
-        NEMIVER_TRY
+
+        NEMIVER_TRY;
+
+        if (IDebugger::is_exited (a_reason))
+            is_running = false;
 
         if (a_has_frame)
             // List frames so that we can get the @ of the current frame.
             list_frames (0, 0, a_cookie);
 
-        NEMIVER_CATCH_NOX
+        NEMIVER_CATCH_NOX;
     }
 
     void on_frames_listed_signal (const vector<IDebugger::Frame> &a_frames,
@@ -1756,9 +1782,21 @@ struct OnCommandDoneHandler : OutputHandler {
     {
         LOG_FUNCTION_SCOPE_NORMAL_DD;
 
+        LOG_DD ("command name: '" << a_in.command ().name () << "'");
+
         if (a_in.command ().name () == "attach-to-program") {
             m_engine->set_attached_to_target (true);
+            m_engine->set_state (IDebugger::READY);
+        } else if (a_in.command ().name () == "load-program") {
+            m_engine->set_attached_to_target (true);
+            m_engine->set_state (IDebugger::INFERIOR_LOADED);
+        } else if (a_in.command ().name () == "detach-from-target") {
+            m_engine->set_attached_to_target (false);
+            m_engine->set_state (IDebugger::NOT_STARTED);
+        } else {
+            m_engine->set_state (IDebugger::READY);
         }
+
         if (a_in.command ().name () == "select-frame") {
             m_engine->set_current_frame_level (a_in.command ().tag2 ());
         }
@@ -1775,9 +1813,6 @@ struct OnCommandDoneHandler : OutputHandler {
                  a_in.command ().cookie ());
         }
 
-        m_engine->command_done_signal ().emit (a_in.command ().name (),
-                                               a_in.command ().cookie ());
-
         if (a_in.command ().name () == "query-variable-path-expr"
             && a_in.command ().variable ()
             && a_in.output ().result_record ().has_path_expression ()) {
@@ -1813,20 +1848,8 @@ struct OnCommandDoneHandler : OutputHandler {
             }
         }
 
-        // 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
-        // inferior just completed its execution or we did attached to
-        // an already inferior and we detached from it -- then we should
-        // not pretend we are in the READY state.
-        // Even if we are attached and this GDB response comes right
-        // after we sent the "detach-from-target" command, the
-        // OnDetachHandler output handler should have already taken care
-        // of updating our state, so let that state alone.
-        if (m_engine->is_attached_to_target ()
-            && (a_in.command ().name () != "detach-from-target")) {
-            m_engine->set_state (IDebugger::READY);
-        }
+        m_engine->command_done_signal ().emit (a_in.command ().name (),
+                                               a_in.command ().cookie ());
     }
 };//struct OnCommandDoneHandler
 
@@ -3128,10 +3151,12 @@ GDBEngine::load_program (const UString &a_prog,
             m_priv->reset_command_queue ();
         }
 
-        queue_command (Command ("set breakpoint pending on"));
+        queue_command (Command ("load-program",
+                                "set breakpoint pending on"));
 
         // tell gdb not to pass the SIGINT signal to the target.
-        queue_command (Command ("handle SIGINT stop print nopass"));
+        queue_command (Command ("load-program",
+                                "handle SIGINT stop print nopass"));
 
 	// Tell gdb not to pass the SIGHUP signal to the target.  This
 	// is useful when the debugger follows a child during a
@@ -3139,7 +3164,8 @@ GDBEngine::load_program (const UString &a_prog,
 	// has some controlling term attached to the target.. Make
 	// sure the signal is not not passed to the target and the
 	// debugger doesn't stop upon that signal.
-	queue_command (Command ("handle SIGHUP nostop print nopass"));
+	queue_command (Command ("load-program",
+                                "handle SIGHUP nostop print nopass"));
 
         // tell the linker to do all relocations at program load
         // time so that some "step into" don't take for ever.
@@ -3148,12 +3174,15 @@ GDBEngine::load_program (const UString &a_prog,
         const char *nmv_ld_bind_now = g_getenv ("NMV_LD_BIND_NOW");
         if (nmv_ld_bind_now && atoi (nmv_ld_bind_now)) {
             LOG_DD ("setting LD_BIND_NOW=1");
-            queue_command (Command ("set env LD_BIND_NOW 1"));
+            queue_command (Command ("load-program",
+                                    "set env LD_BIND_NOW 1"));
         } else {
             LOG_DD ("not setting LD_BIND_NOW environment variable ");
         }
         if (m_priv->enable_pretty_printing)
-            queue_command (Command ("-enable-pretty-printing"));
+            queue_command (Command ("load-program",
+                                    "-enable-pretty-printing"));
+        set_attached_to_target (true);
     } else {
         Command command ("load-program",
                          UString ("-file-exec-and-symbols ") + a_prog);
@@ -3165,7 +3194,7 @@ GDBEngine::load_program (const UString &a_prog,
             queue_command (command);
         }
     }
-    set_tty_path (a_tty_path);
+    m_priv->set_tty_path (a_tty_path, "load-program");
     return true;
 }
 
@@ -3219,7 +3248,7 @@ GDBEngine::attach_to_target (unsigned int a_pid,
     queue_command (Command ("attach-to-program",
                             "attach " + UString::from_int (a_pid)));
     queue_command (Command ("info proc"));
-    set_tty_path (a_tty_path);
+    m_priv->set_tty_path (a_tty_path, "attach-to-program");
     return true;
 }
 
@@ -4304,6 +4333,15 @@ GDBEngine::is_variable_editable (const VariableSafePtr a_var) const
     return false;
 }
 
+/// Return true iff the inferior is "running".  Running here means
+/// that it has received the "run" command once, and hasn't yet
+/// exited.  It might be stopped, though.
+bool
+GDBEngine::is_running () const
+{
+    return m_priv->is_running;
+}
+
 bool
 GDBEngine::stop_target ()
 {
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index 8eb1233..c027968 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -341,6 +341,8 @@ public:
 
     bool is_variable_editable (const VariableSafePtr) const;
 
+    bool is_running () const;
+
     IDebugger::State get_state () const;
 
     int get_current_frame_level () const;
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index b9890f5..f9fa525 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -933,9 +933,16 @@ public:
     };//end class Variable
 
     enum State {
+        // The inferior hasn't been loaded.
         NOT_STARTED=0,
+        // The inferior has been loaded, but hasn't been run yet.
+        INFERIOR_LOADED,
+        // The inferior has started its execution, but is currently
+        // stopped.
         READY,
+        // The inferior is currently busy running.
         RUNNING,
+        // The inferior has exited.
         PROGRAM_EXITED
     };//enum State
 
@@ -943,18 +950,21 @@ public:
     {
         UString str;
         switch (a_state) {
-            case NOT_STARTED:
-                str = "NOT_STARTED";
-                break;
-            case READY:
-                str = "READY";
-                break;
-            case RUNNING:
-                str = "RUNNING";
-                break;
-            case PROGRAM_EXITED:
-                str = "PROGRAM_EXITED";
-                break;
+        case NOT_STARTED:
+            str = "NOT_STARTED";
+            break;
+        case INFERIOR_LOADED:
+            str = "INFERIOR_LOADED";
+            break;
+        case READY:
+            str = "READY";
+            break;
+        case RUNNING:
+            str = "RUNNING";
+            break;
+        case PROGRAM_EXITED:
+            str = "PROGRAM_EXITED";
+            break;
         }
         return str;
     }
@@ -1297,6 +1307,8 @@ public:
 
     virtual bool is_variable_editable (const VariableSafePtr a_var) const = 0;
 
+    virtual bool is_running () const = 0;
+
     virtual void do_continue (const UString &a_cookie="") = 0;
 
     virtual void run (const UString &a_cookie="") = 0;
diff --git a/src/main.cc b/src/main.cc
index 3114fb1..2ce9320 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -65,6 +65,7 @@ static gchar *gv_remote = 0;
 static gchar *gv_solib_prefix = 0;
 static gchar *gv_gdb_binary_filepath = 0;
 static gchar *gv_core_path = 0;
+static bool gv_just_load = false;
 
 static GOptionEntry entries[] =
 {
@@ -179,6 +180,15 @@ static GOptionEntry entries[] =
         _("Set the path of the GDB binary to use to debug the inferior"),
         "</path/to/gdb>"
     },
+    {
+        "just-load",
+        0,
+        0,
+        G_OPTION_ARG_NONE,
+        &gv_just_load,
+        _("Do not set a breakpoint in 'main' and do not run the inferior either"),
+        0
+    },
     { 
         "version",
         0,
@@ -649,7 +659,10 @@ process_gui_options (int& a_argc, char** a_argv)
             debug_persp->uses_launch_terminal (gv_use_launch_terminal);
             debug_persp->execute_program (prog_path,
                                           prog_args,
-                                          env);
+                                          env,
+                                          /*a_cwd=*/".",
+                                          /*a_clone_opened_files=*/false,
+                                          /*a_break_in_main_run=*/!gv_just_load);
         }
     } else {
         cerr << "Could not find the debugger perspective plugin\n";
diff --git a/src/persp/dbgperspective/menus/menus.xml b/src/persp/dbgperspective/menus/menus.xml
index a790750..fa4dd70 100644
--- a/src/persp/dbgperspective/menus/menus.xml
+++ b/src/persp/dbgperspective/menus/menus.xml
@@ -63,16 +63,16 @@
 	    <menuitem action="JumpToLocationMenuItemAction"
                       name="JumpToLocationMenuItem"/>
             <separator/>
-            <menuitem action="ToggleBreakpointMenuItemAction"
+	    <menuitem action="SetBreakpointUsingDialogMenuItemAction"
+                name="SetBreakUsingDialogMenuItem"/>
+	    <menuitem action="SetBreakpointMenuItemAction"
+                name="SetBreakMenuItem"/>
+	    <menuitem action="ToggleBreakpointMenuItemAction"
                 name="ToggleBreakMenuItem"/>
             <menuitem action="ToggleEnableBreakpointMenuItemAction"
                 name="ToggleEnableBreakMenuItem"/>
 	    <menuitem action="ToggleCountpointMenuItemAction"
-                name="ToggleCountpointMenuItem"/>
-            <menuitem action="SetBreakpointMenuItemAction"
-                name="SetBreakMenuItem"/>
-            <menuitem action="SetBreakpointUsingDialogMenuItemAction"
-                name="SetBreakUsingDialogMenuItem"/>
+                name="ToggleCountpointMenuItem"/>           
             <menuitem action="SetWatchPointUsingDialogMenuItemAction"
                 name="SetWatchUsingDialogMenuItem"/>
             <separator/>
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 4d92b79..b2cc7c6 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -296,11 +296,7 @@ private:
 
     void on_switch_page_signal (Gtk::Widget *a_page, guint a_page_num);
 
-    void on_attached_to_target_signal (bool a_is_attached);
-
-    void on_debugger_ready_signal (bool a_is_ready);
-
-    void on_debugger_not_started_signal ();
+    void on_attached_to_target_signal (IDebugger::State a_state);
 
     void on_going_to_run_target_signal (bool);
 
@@ -432,6 +428,7 @@ private:
     //</signal slots>
     //************
 
+    void update_action_group_sensitivity (IDebugger::State a_state);
     string build_resource_path (const UString &a_dir, const UString &a_name);
     void add_stock_icon (const UString &a_stock_id,
                          const UString &icon_dir,
@@ -573,16 +570,18 @@ public:
     void execute_program (const UString &a_prog,
                           const vector<UString> &a_args,
                           const map<UString, UString> &a_env,
-                          const UString &a_cwd,
-                          bool a_close_opened_files);
+                          const UString &a_cwd = ".",
+                          bool a_close_opened_files = false,
+                          bool a_break_in_main_run = true);
 
     void execute_program (const UString &a_prog,
                           const vector<UString> &a_args,
                           const map<UString, UString> &a_env,
                           const UString &a_cwd,
                           const vector<IDebugger::Breakpoint> &a_breaks,
-                          bool a_restarting = false,
-                          bool a_close_opened_files = false);
+                          bool a_restarting = true,
+                          bool a_close_opened_files = false,
+                          bool a_break_in_main_run = true);
 
     void attach_to_program ();
     void attach_to_program (unsigned int a_pid,
@@ -615,6 +614,7 @@ public:
     void edit_preferences ();
 
     void run ();
+    void run_real (bool a_restarting);
     void stop ();
     void step_over ();
     void step_into ();
@@ -806,10 +806,8 @@ public:
     bool agree_to_shutdown ();
 
     sigc::signal<void, bool>& activated_signal ();
-    sigc::signal<void, bool>& attached_to_target_signal ();
-    sigc::signal<void, bool>& debugger_ready_signal ();
+    sigc::signal<void, IDebugger::State>& attached_to_target_signal ();
     sigc::signal<void>& layout_changed_signal ();
-    sigc::signal<void>& debugger_not_started_signal ();
     sigc::signal<void, bool>& going_to_run_target_signal ();
     sigc::signal<void>& default_config_read_signal ();
 };//end class DBGPerspective
@@ -873,13 +871,14 @@ struct DBGPerspective::Priv {
     SafePtr<Gtk::ScrolledWindow> thread_list_scrolled_win;
     SafePtr<Gtk::HPaned> call_stack_paned;
     SafePtr<Gtk::HPaned> context_paned;
-
-    Glib::RefPtr<Gtk::ActionGroup> target_connected_action_group;
+   
+    Glib::RefPtr<Gtk::ActionGroup> default_action_group;
     Glib::RefPtr<Gtk::ActionGroup> target_not_started_action_group;
+    Glib::RefPtr<Gtk::ActionGroup> inferior_loaded_action_group;
+    Glib::RefPtr<Gtk::ActionGroup> detach_action_group;
+    Glib::RefPtr<Gtk::ActionGroup> opened_file_action_group;
     Glib::RefPtr<Gtk::ActionGroup> debugger_ready_action_group;
     Glib::RefPtr<Gtk::ActionGroup> debugger_busy_action_group;
-    Glib::RefPtr<Gtk::ActionGroup> default_action_group;
-    Glib::RefPtr<Gtk::ActionGroup> opened_file_action_group;
     Glib::RefPtr<Gtk::UIManager> ui_manager;
     Glib::RefPtr<Gtk::IconFactory> icon_factory;
     Gtk::UIManager::ui_merge_id menubar_merge_id;
@@ -893,9 +892,7 @@ struct DBGPerspective::Priv {
     SafePtr<Gtk::Notebook> sourceviews_notebook;
     SafePtr<SpinnerToolItem> throbber;
     sigc::signal<void, bool> activated_signal;
-    sigc::signal<void, bool> attached_to_target_signal;
-    sigc::signal<void, bool> debugger_ready_signal;
-    sigc::signal<void> debugger_not_started_signal;
+    sigc::signal<void, IDebugger::State> attached_to_target_signal;
     sigc::signal<void, bool> going_to_run_target_signal;
     sigc::signal<void> default_config_read_signal;
     map<UString, int> path_2_pagenum_map;
@@ -1791,63 +1788,6 @@ DBGPerspective::on_switch_page_signal (Gtk::Widget *a_page,
 }
 
 void
-DBGPerspective::on_debugger_ready_signal (bool a_is_ready)
-{
-    LOG_FUNCTION_SCOPE_NORMAL_DD;
-    NEMIVER_TRY
-
-    THROW_IF_FAIL (m_priv);
-    THROW_IF_FAIL (m_priv->debugger_ready_action_group);
-    THROW_IF_FAIL (m_priv->throbber);
-
-    LOG_DD ("a_is_ready: " << (int)a_is_ready);
-
-    if (a_is_ready) {
-        // reset to default cursor
-        workbench ().get_root_window ().get_window ()->set_cursor ();
-        m_priv->throbber->stop ();
-        m_priv->debugger_ready_action_group->set_sensitive (true);
-        m_priv->target_not_started_action_group->set_sensitive (true);
-        m_priv->debugger_busy_action_group->set_sensitive (false);
-        if (debugger ()->is_attached_to_target ()) {
-            attached_to_target_signal ().emit (true);
-        }
-    } else {
-        m_priv->target_not_started_action_group->set_sensitive (false);
-        m_priv->debugger_ready_action_group->set_sensitive (false);
-        m_priv->debugger_busy_action_group->set_sensitive (true);
-    }
-
-    NEMIVER_CATCH
-}
-
-void
-DBGPerspective::on_debugger_not_started_signal ()
-{
-    THROW_IF_FAIL (m_priv);
-    THROW_IF_FAIL (m_priv->throbber);
-    THROW_IF_FAIL (m_priv->default_action_group);
-    THROW_IF_FAIL (m_priv->target_connected_action_group);
-    THROW_IF_FAIL (m_priv->target_not_started_action_group);
-    THROW_IF_FAIL (m_priv->debugger_ready_action_group);
-    THROW_IF_FAIL (m_priv->debugger_busy_action_group);
-    THROW_IF_FAIL (m_priv->opened_file_action_group);
-
-    // reset to default cursor
-    workbench ().get_root_window ().get_window ()->set_cursor ();
-    m_priv->throbber->stop ();
-    m_priv->default_action_group->set_sensitive (true);
-    m_priv->target_connected_action_group->set_sensitive (false);
-    m_priv->target_not_started_action_group->set_sensitive (false);
-    m_priv->debugger_ready_action_group->set_sensitive (false);
-    m_priv->debugger_busy_action_group->set_sensitive (false);
-
-    if (get_num_notebook_pages ()) {
-        close_opened_files ();
-    }
-}
-
-void
 DBGPerspective::on_going_to_run_target_signal (bool a_restarting)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -1862,25 +1802,15 @@ DBGPerspective::on_going_to_run_target_signal (bool a_restarting)
 }
 
 void
-DBGPerspective::on_attached_to_target_signal (bool a_is_ready)
+DBGPerspective::on_attached_to_target_signal (IDebugger::State a_state)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
-    NEMIVER_TRY
 
-    if (a_is_ready) {
-        m_priv->target_connected_action_group->set_sensitive (true);
-    } else {
-        //reset to default cursor, in case the busy cursor was spinning
-        workbench ().get_root_window ().get_window ()->set_cursor ();
-        m_priv->throbber->stop ();
-        m_priv->target_connected_action_group->set_sensitive (false);
-        m_priv->default_action_group->set_sensitive (true);
-        m_priv->target_not_started_action_group->set_sensitive (false);
-        m_priv->debugger_ready_action_group->set_sensitive (false);
-        m_priv->debugger_busy_action_group->set_sensitive (false);
-    }
+    NEMIVER_TRY;
 
-    NEMIVER_CATCH
+    update_action_group_sensitivity (a_state);
+
+    NEMIVER_CATCH;
 }
 
 void
@@ -2343,7 +2273,6 @@ DBGPerspective::on_debugger_inferior_re_run_signal ()
     NEMIVER_TRY;
 
     m_priv->debugger_has_just_run = true;
-    attached_to_target_signal ().emit (true);
 
     NEMIVER_CATCH;
 }
@@ -2365,7 +2294,7 @@ DBGPerspective::on_debugger_detached_from_target_signal ()
     THROW_IF_FAIL (m_priv);
     m_priv->debugger_ready_action_group->set_sensitive (false);
     m_priv->debugger_busy_action_group->set_sensitive (false);
-    m_priv->target_connected_action_group->set_sensitive (false);
+    m_priv->inferior_loaded_action_group->set_sensitive (false);
     m_priv->target_not_started_action_group->set_sensitive (true);
 
     NEMIVER_CATCH
@@ -2485,7 +2414,7 @@ DBGPerspective::on_program_finished_signal ()
     NEMIVER_TRY
 
     unset_where ();
-    attached_to_target_signal ().emit (false);
+
     display_info (_("Program exited"));
     workbench ().set_title_extension ("");
 
@@ -2494,11 +2423,7 @@ DBGPerspective::on_program_finished_signal ()
     //items but those to
     //to restart the debugger etc
     //***************************
-    THROW_IF_FAIL (m_priv);
-    m_priv->target_not_started_action_group->set_sensitive (true);
-    m_priv->debugger_ready_action_group->set_sensitive (false);
-    m_priv->debugger_busy_action_group->set_sensitive (false);
-    m_priv->target_connected_action_group->set_sensitive (false);
+    update_action_group_sensitivity (IDebugger::PROGRAM_EXITED);
 
     //**********************
     //clear threads list and
@@ -2518,7 +2443,7 @@ DBGPerspective::on_engine_died_signal ()
     m_priv->target_not_started_action_group->set_sensitive (true);
     m_priv->debugger_ready_action_group->set_sensitive (false);
     m_priv->debugger_busy_action_group->set_sensitive (false);
-    m_priv->target_connected_action_group->set_sensitive (false);
+    m_priv->inferior_loaded_action_group->set_sensitive (false);
 
     ui_utils::display_info (_("The underlying debugger engine process died."));
 
@@ -2634,15 +2559,10 @@ void
 DBGPerspective::on_debugger_state_changed_signal (IDebugger::State a_state)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
-    NEMIVER_TRY
 
-    LOG_DD ("state is '" << IDebugger::state_to_string (a_state) << "'");
+    NEMIVER_TRY;
 
-    if (a_state == IDebugger::READY) {
-        debugger_ready_signal ().emit (true);
-    } else {
-        debugger_ready_signal ().emit (false);
-    }
+    update_action_group_sensitivity (a_state);
 
     NEMIVER_CATCH
 }
@@ -2972,6 +2892,71 @@ DBGPerspective::on_default_config_read ()
 //<private methods>
 //*******************
 
+/// Given a debugger state, update the sensitivity of the various menu
+/// actions of the graphical debugger.
+///
+/// \param a_state the debugger state.
+void
+DBGPerspective::update_action_group_sensitivity (IDebugger::State a_state)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    LOG_DD ("state is '" << IDebugger::state_to_string (a_state) << "'");
+
+    THROW_IF_FAIL (m_priv);
+    THROW_IF_FAIL (m_priv->debugger_ready_action_group);
+    THROW_IF_FAIL (m_priv->target_not_started_action_group);
+    THROW_IF_FAIL (m_priv->debugger_busy_action_group);
+    THROW_IF_FAIL (m_priv->throbber);
+
+    if (a_state == IDebugger::NOT_STARTED) {
+        m_priv->throbber->stop ();
+        // reset to default cursor
+        workbench ().get_root_window ().get_window ()->set_cursor ();
+        m_priv->default_action_group->set_sensitive (true);
+        m_priv->detach_action_group->set_sensitive (false);
+        m_priv->target_not_started_action_group->set_sensitive (true);
+        m_priv->inferior_loaded_action_group->set_sensitive (false);
+        m_priv->debugger_busy_action_group->set_sensitive (false);
+        m_priv->debugger_ready_action_group->set_sensitive (false);
+        if (get_num_notebook_pages ()) {
+            close_opened_files ();
+        }
+    } else if (a_state == IDebugger::INFERIOR_LOADED) {
+        // reset to default cursor
+        workbench ().get_root_window ().get_window ()->set_cursor ();
+        m_priv->detach_action_group->set_sensitive (false);
+        m_priv->target_not_started_action_group->set_sensitive (true);
+        m_priv->inferior_loaded_action_group->set_sensitive (true);
+        m_priv->debugger_busy_action_group->set_sensitive (false);
+        m_priv->debugger_ready_action_group->set_sensitive (false);
+        m_priv->throbber->stop ();
+    } else if (a_state == IDebugger::READY) {
+        m_priv->throbber->stop ();
+        // reset to default cursor
+        workbench ().get_root_window ().get_window ()->set_cursor ();
+        m_priv->detach_action_group->set_sensitive (true);
+        m_priv->target_not_started_action_group->set_sensitive (true);
+        m_priv->inferior_loaded_action_group->set_sensitive (true);
+        m_priv->debugger_ready_action_group->set_sensitive (true);
+        m_priv->debugger_busy_action_group->set_sensitive (false);
+    } else if (a_state == IDebugger::RUNNING){
+        m_priv->detach_action_group->set_sensitive (true);
+        m_priv->target_not_started_action_group->set_sensitive (false);
+        m_priv->inferior_loaded_action_group->set_sensitive (false);
+        m_priv->debugger_ready_action_group->set_sensitive (false);
+        m_priv->debugger_busy_action_group->set_sensitive (true);
+    } else if (a_state == IDebugger::PROGRAM_EXITED) {
+        m_priv->throbber->stop ();
+        // reset to default cursor
+        workbench ().get_root_window ().get_window ()->set_cursor ();
+        m_priv->target_not_started_action_group->set_sensitive (true);
+        m_priv->inferior_loaded_action_group->set_sensitive (true);
+        m_priv->debugger_ready_action_group->set_sensitive (false);
+        m_priv->debugger_busy_action_group->set_sensitive (false);
+        m_priv->inferior_loaded_action_group->set_sensitive (false);
+    }
+}
 
 string
 DBGPerspective::build_resource_path (const UString &a_dir,
@@ -3064,17 +3049,21 @@ DBGPerspective::init_actions ()
 {
     Gtk::StockID nil_stock_id ("");
     sigc::slot<void> nil_slot;
-    ui_utils::ActionEntry s_target_connected_action_entries [] = {
+
+    static ui_utils::ActionEntry s_target_not_started_action_entries [] = {
         {
-            "SaveSessionMenuItemAction",
-            Gtk::Stock::SAVE,
-            _("_Save Session to Disk"),
-            _("Save the current debugging session to disk"),
-            sigc::mem_fun (*this, &DBGPerspective::on_save_session_action),
+            "RunMenuItemAction",
+            Gtk::Stock::REFRESH,
+            _("_Run or Restart"),
+            _("Run or Restart the target"),
+            sigc::mem_fun (*this, &DBGPerspective::on_run_action),
             ActionEntry::DEFAULT,
-            "",
-            false
-        },
+            "<shift>F5",
+            true
+        }
+    };
+
+    static ui_utils::ActionEntry s_detach_action_entries [] = {
         {
             "DetachFromProgramMenuItemAction",
             Gtk::Stock::DISCONNECT,
@@ -3089,20 +3078,112 @@ DBGPerspective::init_actions ()
         },
     };
 
-    static ui_utils::ActionEntry s_target_not_started_action_entries [] = {
+
+    ui_utils::ActionEntry s_inferior_loaded_action_entries [] = {
         {
-            "RunMenuItemAction",
-            Gtk::Stock::REFRESH,
-            _("_Restart"),
-            _("Restart the target, killing this process "
-              "and starting a new one"),
-            sigc::mem_fun (*this, &DBGPerspective::on_run_action),
+            "SaveSessionMenuItemAction",
+            Gtk::Stock::SAVE,
+            _("_Save Session to Disk"),
+            _("Save the current debugging session to disk"),
+            sigc::mem_fun (*this, &DBGPerspective::on_save_session_action),
             ActionEntry::DEFAULT,
-            "<shift>F5",
-            true
-        }
+            "",
+            false
+        },
+        {
+            "SetBreakpointUsingDialogMenuItemAction",
+            nil_stock_id,
+            _("Set Breakpoint with Dialog..."),
+            _("Set a breakpoint at the current line using a dialog"),
+            sigc::mem_fun
+                (*this,
+                 &DBGPerspective::on_set_breakpoint_using_dialog_action),
+            ActionEntry::DEFAULT,
+            "<control><shift>B",
+            false
+        },
+        {
+            "SetBreakpointMenuItemAction",
+            nil_stock_id,
+            _("Set Breakpoint..."),
+            _("Set a breakpoint at a function or line number"),
+            sigc::mem_fun (*this, &DBGPerspective::on_set_breakpoint_action),
+            ActionEntry::DEFAULT,
+            "<control>B",
+            false
+        },
+        {
+            "ToggleBreakpointMenuItemAction",
+            nil_stock_id,
+            // Depending on the context we will want this string to be
+            // either "Set Breakpoint", or "Remove Breakpoint". Hence
+            // this string is updated by
+            // DBGPerspective::update_toggle_menu_text when needed. So
+            // this initial value is going to be displayed only when
+            // Nemiver is launched with no executable on the command
+            // line.
+            _("Toggle _Breakpoint"),
+            _("Set/Unset a breakpoint at the current cursor location"),
+            sigc::mem_fun (*this,
+                           &DBGPerspective::on_toggle_breakpoint_action),
+            ActionEntry::DEFAULT,
+            "F8",
+            false
+        },
+        {
+            "ToggleEnableBreakpointMenuItemAction",
+            nil_stock_id,
+            // Depending on the context we will want this string to be
+            // either "Enable Breakpoint", or "Disable
+            // Breakpoint". Hence this string is updated by
+            // DBGPerspective::update_toggle_menu_text when needed. So
+            // this initial value is going to be displayed only when
+            // Nemiver is launched with no executable on the command
+            // line.
+            _("Enable/Disable Breakpoint"),
+            _("Enable or disable the breakpoint that is set at "
+              "the current cursor location"),
+            sigc::mem_fun
+                    (*this,
+                     &DBGPerspective::on_toggle_breakpoint_enabled_action),
+            ActionEntry::DEFAULT,
+            "<shift>F8",
+            false
+        },
+        {
+            "ToggleCountpointMenuItemAction",
+            nil_stock_id,
+            // Depending on the context we will want this string to be
+            // either "Set Countpoint", or "Change to Countpoint", or
+            // "Change to Standard Breakpoint". Hence
+            // this string is updated by
+            // DBGPerspective::update_toggle_menu_text when needed. So
+            // this initial value is going to be displayed only when
+            // Nemiver is launched with no executable on the command
+            // line.
+            _("Toggle _Countpoint"),
+            _("Set/Unset a countpoint at the current cursor location"),
+            sigc::mem_fun (*this,
+                           &DBGPerspective::on_toggle_countpoint_action),
+            ActionEntry::DEFAULT,
+            "",
+            false
+        },
+        {
+            "SetWatchPointUsingDialogMenuItemAction",
+            nil_stock_id,
+            _("Set Watchpoint with Dialog..."),
+            _("Set a watchpoint using a dialog"),
+            sigc::mem_fun
+                (*this,
+                 &DBGPerspective::on_set_watchpoint_using_dialog_action),
+            ActionEntry::DEFAULT,
+            "<control>T",
+            false
+        },
     };
 
+
     static ui_utils::ActionEntry s_debugger_ready_action_entries [] = {
         {
             "NextMenuItemAction",
@@ -3157,8 +3238,8 @@ DBGPerspective::init_actions ()
         {
             "ContinueMenuItemAction",
             Gtk::Stock::EXECUTE,
-            _("_Continue"),
-            _("Continue program execution until the next breakpoint"),
+            _("_Continue or start"),
+            _("Start or continue program execution until the next breakpoint"),
             sigc::mem_fun (*this, &DBGPerspective::on_continue_action),
             ActionEntry::DEFAULT,
             "F5",
@@ -3212,97 +3293,6 @@ DBGPerspective::init_actions ()
             false
         },
         {
-            "ToggleBreakpointMenuItemAction",
-            nil_stock_id,
-            // Depending on the context we will want this string to be
-            // either "Set Breakpoint", or "Remove Breakpoint". Hence
-            // this string is updated by
-            // DBGPerspective::update_toggle_menu_text when needed. So
-            // this initial value is going to be displayed only when
-            // Nemiver is launched with no executable on the command
-            // line.
-            _("Toggle _Breakpoint"),
-            _("Set/Unset a breakpoint at the current cursor location"),
-            sigc::mem_fun (*this,
-                           &DBGPerspective::on_toggle_breakpoint_action),
-            ActionEntry::DEFAULT,
-            "F8",
-            false
-        },
-        {
-            "ToggleEnableBreakpointMenuItemAction",
-            nil_stock_id,
-            // Depending on the context we will want this string to be
-            // either "Enable Breakpoint", or "Disable
-            // Breakpoint". Hence this string is updated by
-            // DBGPerspective::update_toggle_menu_text when needed. So
-            // this initial value is going to be displayed only when
-            // Nemiver is launched with no executable on the command
-            // line.
-            _("Enable/Disable Breakpoint"),
-            _("Enable or disable the breakpoint that is set at "
-              "the current cursor location"),
-            sigc::mem_fun
-                    (*this,
-                     &DBGPerspective::on_toggle_breakpoint_enabled_action),
-            ActionEntry::DEFAULT,
-            "<shift>F8",
-            false
-        },
-        {
-            "ToggleCountpointMenuItemAction",
-            nil_stock_id,
-            // Depending on the context we will want this string to be
-            // either "Set Countpoint", or "Change to Countpoint", or
-            // "Change to Standard Breakpoint". Hence
-            // this string is updated by
-            // DBGPerspective::update_toggle_menu_text when needed. So
-            // this initial value is going to be displayed only when
-            // Nemiver is launched with no executable on the command
-            // line.
-            _("Toggle _Countpoint"),
-            _("Set/Unset a countpoint at the current cursor location"),
-            sigc::mem_fun (*this,
-                           &DBGPerspective::on_toggle_countpoint_action),
-            ActionEntry::DEFAULT,
-            "",
-            false
-        },
-        {
-            "SetBreakpointMenuItemAction",
-            nil_stock_id,
-            _("Set Breakpoint..."),
-            _("Set a breakpoint at a function or line number"),
-            sigc::mem_fun (*this, &DBGPerspective::on_set_breakpoint_action),
-            ActionEntry::DEFAULT,
-            "<control>B",
-            false
-        },
-        {
-            "SetBreakpointUsingDialogMenuItemAction",
-            nil_stock_id,
-            _("Set Breakpoint with Dialog..."),
-            _("Set a breakpoint at the current line using a dialog"),
-            sigc::mem_fun
-                (*this,
-                 &DBGPerspective::on_set_breakpoint_using_dialog_action),
-            ActionEntry::DEFAULT,
-            "<control><shift>B",
-            false
-        },
-        {
-            "SetWatchPointUsingDialogMenuItemAction",
-            nil_stock_id,
-            _("Set Watchpoint with Dialog..."),
-            _("Set a watchpoint using a dialog"),
-            sigc::mem_fun
-                (*this,
-                 &DBGPerspective::on_set_watchpoint_using_dialog_action),
-            ActionEntry::DEFAULT,
-            "<control>T",
-            false
-        },
-        {
             "InspectExpressionMenuItemAction",
             nil_stock_id,
             _("Inspect an Expression"),
@@ -3595,9 +3585,13 @@ DBGPerspective::init_actions ()
         }
     };
 
-    m_priv->target_connected_action_group =
-                Gtk::ActionGroup::create ("target-connected-action-group");
-    m_priv->target_connected_action_group->set_sensitive (false);
+    m_priv->detach_action_group =
+        Gtk::ActionGroup::create ("detach-action-group");
+    m_priv->detach_action_group->set_sensitive (false);
+
+    m_priv->inferior_loaded_action_group =
+        Gtk::ActionGroup::create ("inferior-loaded-action-group");
+    m_priv->inferior_loaded_action_group->set_sensitive (false);
 
     m_priv->target_not_started_action_group =
                 Gtk::ActionGroup::create ("target-not-started-action-group");
@@ -3620,13 +3614,20 @@ DBGPerspective::init_actions ()
     m_priv->opened_file_action_group->set_sensitive (false);
 
     int num_actions =
-     sizeof (s_target_connected_action_entries)
+        sizeof (s_detach_action_entries) / sizeof (ui_utils::ActionEntry);
+    ui_utils::add_action_entries_to_action_group
+        (s_detach_action_entries,
+         num_actions,
+         m_priv->detach_action_group);
+
+    num_actions =
+     sizeof (s_inferior_loaded_action_entries)
              /
              sizeof (ui_utils::ActionEntry);
     ui_utils::add_action_entries_to_action_group
-                        (s_target_connected_action_entries,
+                        (s_inferior_loaded_action_entries,
                          num_actions,
-                         m_priv->target_connected_action_group);
+                         m_priv->inferior_loaded_action_group);
 
     num_actions =
      sizeof (s_target_not_started_action_entries)
@@ -3674,7 +3675,9 @@ DBGPerspective::init_actions ()
                          m_priv->opened_file_action_group);
 
     workbench ().get_ui_manager ()->insert_action_group
-                                    (m_priv->target_connected_action_group);
+        (m_priv->detach_action_group);
+    workbench ().get_ui_manager ()->insert_action_group
+                                    (m_priv->inferior_loaded_action_group);
     workbench ().get_ui_manager ()->insert_action_group
                                 (m_priv->target_not_started_action_group);
     workbench ().get_ui_manager ()->insert_action_group
@@ -3772,12 +3775,6 @@ DBGPerspective::init_signals ()
     m_priv->sourceviews_notebook->signal_switch_page ().connect
         (sigc::mem_fun (*this, &DBGPerspective::on_switch_page_signal));
 
-    debugger_ready_signal ().connect (sigc::mem_fun
-            (*this, &DBGPerspective::on_debugger_ready_signal));
-
-    debugger_not_started_signal ().connect (sigc::mem_fun
-            (*this, &DBGPerspective::on_debugger_not_started_signal));
-
     going_to_run_target_signal ().connect (sigc::mem_fun
             (*this, &DBGPerspective::on_going_to_run_target_signal));
 
@@ -5889,6 +5886,8 @@ DBGPerspective::execute_program ()
 void
 DBGPerspective::restart_inferior ()
 {
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
     if (!is_connected_to_remote_target ()) {
         // Restarting a local program
         restart_local_inferior ();
@@ -5914,6 +5913,8 @@ DBGPerspective::restart_inferior ()
 void
 DBGPerspective::restart_local_inferior ()
 {
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
     THROW_IF_FAIL (!is_connected_to_remote_target ());
     
     if (debugger ()->is_attached_to_target ()
@@ -5944,12 +5945,14 @@ DBGPerspective::execute_program (const UString &a_prog,
                                  const vector<UString> &a_args,
                                  const map<UString, UString> &a_env,
                                  const UString &a_cwd,
-                                 bool a_close_opened_files)
+                                 bool a_close_opened_files,
+                                 bool a_break_in_main_run)
 {
     vector<IDebugger::Breakpoint> bps;
     execute_program (a_prog, a_args, a_env,
                      a_cwd, bps, /*a_restarting=*/false,
-                     a_close_opened_files);
+                     a_close_opened_files,
+                     a_break_in_main_run);
 }
 
 /// Loads and executes a program (called an inferior) under the debugger.
@@ -5969,6 +5972,11 @@ DBGPerspective::execute_program (const UString &a_prog,
 ///        things that have been done already, e.g. re set breakpoints etc.
 ///        Otherwise, just ignore the fact that the program might have been
 ///        run previously and just redo all the necessary things.
+/// \param a_close_opened_files if true, close all the opened files
+///        before executing the inferior.
+/// \param a_break_in_main_run if true, set a breakpoint in the "main"
+///        function of the inferior and run it.  The inferior will
+///        then run and stop at the beginning of the main function.
 void
 DBGPerspective::execute_program
                         (const UString &a_prog,
@@ -5977,7 +5985,8 @@ DBGPerspective::execute_program
                          const UString &a_cwd,
                          const vector<IDebugger::Breakpoint> &a_breaks,
                          bool a_restarting,
-                         bool a_close_opened_files)
+                         bool a_close_opened_files,
+                         bool a_break_in_main_run)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD
 
@@ -6091,7 +6100,7 @@ DBGPerspective::execute_program
                  ++it) {
                 set_breakpoint (it->second);
             }
-        } else {
+        } else if (a_break_in_main_run) {
             dbg_engine->set_breakpoint ("main");
         }
     } else {
@@ -6101,11 +6110,8 @@ DBGPerspective::execute_program
         }
     }
 
-    going_to_run_target_signal ().emit (a_restarting);
-    dbg_engine->run ();
-    m_priv->debugger_has_just_run = true;
-
-    attached_to_target_signal ().emit (true);
+    if (a_break_in_main_run)
+        run_real (a_restarting);
 
     m_priv->prog_path = prog;
     m_priv->prog_args = a_args;
@@ -6139,12 +6145,7 @@ void
 DBGPerspective::attach_to_program (unsigned int a_pid,
                                    bool a_close_opened_files)
 {
-    LOG_FUNCTION_SCOPE_NORMAL_DD
-    save_current_session ();
-
-    if (a_close_opened_files && get_num_notebook_pages ()) {
-        close_opened_files ();
-    }
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
 
     LOG_DD ("a_pid: " << (int) a_pid);
 
@@ -6152,8 +6153,16 @@ DBGPerspective::attach_to_program (unsigned int a_pid,
         ui_utils::display_warning (_("You cannot attach to Nemiver itself"));
         return;
     }
+
+    save_current_session ();
+
+    if (a_close_opened_files && get_num_notebook_pages ()) {
+        close_opened_files ();
+    }
+
     if (!debugger ()->attach_to_target (a_pid,
                                         get_terminal_name ())) {
+
         ui_utils::display_warning (_("You cannot attach to the "
                                      "underlying debugger engine"));
         return;
@@ -6391,11 +6400,23 @@ DBGPerspective::run ()
         LOG_DD ("Yes, it seems we were running a program before. "
                 "Will try to restart it");
         restart_inferior ();
+    } else if (m_priv->debugger_engine_alive) {
+        run_real (/*a_restarting=*/false);
     } else {
         LOG_ERROR ("No program got previously loaded");
     }
 }
 
+/// Really run the inferior (invoking IDebugger).  This is sub-routine
+/// of the run and execute_program methods.
+void
+DBGPerspective::run_real (bool a_restarting)
+{
+    going_to_run_target_signal ().emit (a_restarting);
+    debugger ()->run ();
+    m_priv->debugger_has_just_run = true;
+}
+
 void
 DBGPerspective::load_core_file ()
 {
@@ -6471,10 +6492,15 @@ DBGPerspective::step_over_asm ()
     debugger ()->step_over_asm ();
 }
 
+// Start the inferior if it has not started yet, or make it continue
+// its execution.
 void
 DBGPerspective::do_continue ()
 {
-    debugger ()->do_continue ();
+    if (!debugger ()->is_running ())
+        debugger ()->run ();
+    else
+        debugger ()->do_continue ();
 }
 
 void
@@ -8246,18 +8272,12 @@ DBGPerspective::activated_signal ()
     return m_priv->activated_signal;
 }
 
-sigc::signal<void, bool>&
+sigc::signal<void, IDebugger::State>&
 DBGPerspective::attached_to_target_signal ()
 {
     return m_priv->attached_to_target_signal;
 }
 
-sigc::signal<void, bool>&
-DBGPerspective::debugger_ready_signal ()
-{
-    return m_priv->debugger_ready_signal;
-}
-
 sigc::signal<void>&
 DBGPerspective::layout_changed_signal ()
 {
@@ -8265,12 +8285,6 @@ DBGPerspective::layout_changed_signal ()
     return m_priv->layout_mgr.layout_changed_signal ();
 }
 
-sigc::signal<void>&
-DBGPerspective::debugger_not_started_signal ()
-{
-    return m_priv->debugger_not_started_signal;
-}
-
 sigc::signal<void, bool>&
 DBGPerspective::going_to_run_target_signal ()
 {
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index efa0b3f..2cc4c47 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -102,10 +102,11 @@ public:
     virtual void execute_program () = 0;
 
     virtual void execute_program (const UString &a_prog,
-                          const vector<UString> &a_args,
-                          const map<UString, UString> &a_env,
-                          const UString &a_cwd = ".",
-                          bool a_close_opened_files = false) = 0;
+				  const vector<UString> &a_args,
+				  const map<UString, UString> &a_env,
+				  const UString &a_cwd = ".",
+				  bool a_close_opened_files = false,
+				  bool a_break_in_main_run = true) = 0;
 
     virtual void execute_program (const UString &a_prog,
                                   const vector<UString> &a_args,
@@ -114,7 +115,8 @@ public:
                                   const vector<IDebugger::Breakpoint>
                                                                   &a_breaks,
                                   bool a_check_is_new_program = true,
-                                  bool a_close_opened_files = false) = 0;
+                                  bool a_close_opened_files = false,
+				  bool a_break_in_main_run = true) = 0;
 
     virtual void attach_to_program (unsigned int a_pid,
                                     bool a_close_open_files = false) = 0;
@@ -182,8 +184,6 @@ public:
 
     virtual sigc::signal<void, bool>& activated_signal () = 0;
 
-    virtual sigc::signal<void, bool>& debugger_ready_signal () = 0;
-
     virtual sigc::signal<void>& layout_changed_signal () = 0;
 
     virtual bool agree_to_shutdown () = 0;



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