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



Hello,

When you do "nemiver <inferior-program>", the debugger loads the
inferior program, sets a break point on its 'main' function and runs it.
That has the (possibly nice) effect of having the inferior be stopped in
the main function, showing you the source code right there, without you
needed to do anything.  I've relied on that behaviour myself and has so
far been happy with it.

However, recent history has shown that it can be a source of problems
when the inferior program has its 'main' symbol stripped out, for
instance.  In that case, setting the break point on the main function
fails and Nemiver runs the inferior nonetheless, making it proceed until
it exits without giving the user any chance to set a break point
elsewhere or do any other thing for that matter.  Frustratingly useless.

To address that issue, this patch adds a new '--just-load' command.

"nemiver --just-load <inferior-program>" with then load the inferior and
wait there.  It'll be up to the user to set a break point to the
function she wants and then explicitly run the inferior program.

The patch is less obvious than it should have ideally been because I had
to update the Nemiver state management code.  It's important to have a
precise idea of the current state of the debugger, at least so that we
can choose which menu item to activate or de-activate (grey out) or
whether to start/stop the throbber, depending on the context.

Tested and applying to master.

	* 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;
-- 
		Dodji


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