Move some declarations to source.h
[deliverable/binutils-gdb.git] / gdb / target.c
index b01e1ac64569101bdbc28f199ed07ac53de186cb..db7c09ba0f3b0ed3996cc8ecc79764eff6ddfdf8 100644 (file)
@@ -47,6 +47,7 @@
 #include "event-top.h"
 #include <algorithm>
 #include "byte-vector.h"
+#include "terminal.h"
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -431,8 +432,8 @@ target_load (const char *arg, int from_tty)
 
 /* Define it.  */
 
-enum target_terminal::terminal_state target_terminal::terminal_state
-  = target_terminal::terminal_is_ours;
+target_terminal_state target_terminal::m_terminal_state
+  = target_terminal_state::is_ours;
 
 /* See target/target.h.  */
 
@@ -441,7 +442,7 @@ target_terminal::init (void)
 {
   (*current_target.to_terminal_init) (&current_target);
 
-  terminal_state = terminal_is_ours;
+  m_terminal_state = target_terminal_state::is_ours;
 }
 
 /* See target/target.h.  */
@@ -463,13 +464,18 @@ target_terminal::inferior (void)
   if (ui != main_ui)
     return;
 
-  if (terminal_state == terminal_is_inferior)
-    return;
-
   /* If GDB is resuming the inferior in the foreground, install
      inferior's terminal modes.  */
-  (*current_target.to_terminal_inferior) (&current_target);
-  terminal_state = terminal_is_inferior;
+
+  struct inferior *inf = current_inferior ();
+
+  if (inf->terminal_state != target_terminal_state::is_inferior)
+    {
+      (*current_target.to_terminal_inferior) (&current_target);
+      inf->terminal_state = target_terminal_state::is_inferior;
+    }
+
+  m_terminal_state = target_terminal_state::is_inferior;
 
   /* If the user hit C-c before, pretend that it was hit right
      here.  */
@@ -479,6 +485,88 @@ target_terminal::inferior (void)
 
 /* See target/target.h.  */
 
+void
+target_terminal::restore_inferior (void)
+{
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior().  */
+  if (ui->prompt_state != PROMPT_BLOCKED || ui != main_ui)
+    return;
+
+  /* Restore the terminal settings of inferiors that were in the
+     foreground but are now ours_for_output due to a temporary
+     target_target::ours_for_output() call.  */
+
+  {
+    scoped_restore_current_inferior restore_inferior;
+    struct inferior *inf;
+
+    ALL_INFERIORS (inf)
+      {
+       if (inf->terminal_state == target_terminal_state::is_ours_for_output)
+         {
+           set_current_inferior (inf);
+           (*current_target.to_terminal_inferior) (&current_target);
+           inf->terminal_state = target_terminal_state::is_inferior;
+         }
+      }
+  }
+
+  m_terminal_state = target_terminal_state::is_inferior;
+
+  /* If the user hit C-c before, pretend that it was hit right
+     here.  */
+  if (check_quit_flag ())
+    target_pass_ctrlc ();
+}
+
+/* Switch terminal state to DESIRED_STATE, either is_ours, or
+   is_ours_for_output.  */
+
+static void
+target_terminal_is_ours_kind (target_terminal_state desired_state)
+{
+  scoped_restore_current_inferior restore_inferior;
+  struct inferior *inf;
+
+  /* Must do this in two passes.  First, have all inferiors save the
+     current terminal settings.  Then, after all inferiors have add a
+     chance to safely save the terminal settings, restore GDB's
+     terminal settings.  */
+
+  ALL_INFERIORS (inf)
+    {
+      if (inf->terminal_state == target_terminal_state::is_inferior)
+       {
+         set_current_inferior (inf);
+         (*current_target.to_terminal_save_inferior) (&current_target);
+       }
+    }
+
+  ALL_INFERIORS (inf)
+    {
+      /* Note we don't check is_inferior here like above because we
+        need to handle 'is_ours_for_output -> is_ours' too.  Careful
+        to never transition from 'is_ours' to 'is_ours_for_output',
+        though.  */
+      if (inf->terminal_state != target_terminal_state::is_ours
+         && inf->terminal_state != desired_state)
+       {
+         set_current_inferior (inf);
+         if (desired_state == target_terminal_state::is_ours)
+           (*current_target.to_terminal_ours) (&current_target);
+         else if (desired_state == target_terminal_state::is_ours_for_output)
+           (*current_target.to_terminal_ours_for_output) (&current_target);
+         else
+           gdb_assert_not_reached ("unhandled desired state");
+         inf->terminal_state = desired_state;
+       }
+    }
+}
+
+/* See target/target.h.  */
+
 void
 target_terminal::ours ()
 {
@@ -488,11 +576,11 @@ target_terminal::ours ()
   if (ui != main_ui)
     return;
 
-  if (terminal_state == terminal_is_ours)
+  if (m_terminal_state == target_terminal_state::is_ours)
     return;
 
-  (*current_target.to_terminal_ours) (&current_target);
-  terminal_state = terminal_is_ours;
+  target_terminal_is_ours_kind (target_terminal_state::is_ours);
+  m_terminal_state = target_terminal_state::is_ours;
 }
 
 /* See target/target.h.  */
@@ -506,10 +594,11 @@ target_terminal::ours_for_output ()
   if (ui != main_ui)
     return;
 
-  if (terminal_state != terminal_is_inferior)
+  if (!target_terminal::is_inferior ())
     return;
-  (*current_target.to_terminal_ours_for_output) (&current_target);
-  terminal_state = terminal_is_ours_for_output;
+
+  target_terminal_is_ours_kind (target_terminal_state::is_ours_for_output);
+  target_terminal::m_terminal_state = target_terminal_state::is_ours_for_output;
 }
 
 /* See target/target.h.  */
@@ -2108,7 +2197,7 @@ dispose_inferior (struct inferior *inf, void *args)
       if (target_has_execution)
        target_kill ();
       else
-       target_detach (0);
+       target_detach (inf, 0);
     }
 
   return 0;
@@ -2144,8 +2233,15 @@ target_preopen (int from_tty)
 /* See target.h.  */
 
 void
-target_detach (int from_tty)
+target_detach (inferior *inf, int from_tty)
 {
+  /* As long as some to_detach implementations rely on the current_inferior
+     (either directly, or indirectly, like through target_gdbarch or by
+     reading memory), INF needs to be the current inferior.  When that
+     requirement will become no longer true, then we can remove this
+     assertion.  */
+  gdb_assert (inf == current_inferior ());
+
   if (gdbarch_has_global_breakpoints (target_gdbarch ()))
     /* Don't remove global breakpoints here.  They're removed on
        disconnection from the target.  */
@@ -2157,7 +2253,7 @@ target_detach (int from_tty)
 
   prepare_for_detach ();
 
-  current_target.to_detach (&current_target, from_tty);
+  current_target.to_detach (&current_target, inf, from_tty);
 }
 
 void
@@ -3325,7 +3421,7 @@ target_stop (ptid_t ptid)
 }
 
 void
-target_interrupt (ptid_t ptid)
+target_interrupt ()
 {
   if (!may_stop)
     {
@@ -3333,7 +3429,7 @@ target_interrupt (ptid_t ptid)
       return;
     }
 
-  (*current_target.to_interrupt) (&current_target, ptid);
+  (*current_target.to_interrupt) (&current_target);
 }
 
 /* See target.h.  */
@@ -3349,7 +3445,7 @@ target_pass_ctrlc (void)
 void
 default_target_pass_ctrlc (struct target_ops *ops)
 {
-  target_interrupt (inferior_ptid);
+  target_interrupt ();
 }
 
 /* See target/target.h.  */
@@ -3549,14 +3645,6 @@ target_ranged_break_num_registers (void)
 
 /* See target.h.  */
 
-int
-target_supports_btrace (enum btrace_format format)
-{
-  return current_target.to_supports_btrace (&current_target, format);
-}
-
-/* See target.h.  */
-
 struct btrace_target_info *
 target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 {
This page took 0.027005 seconds and 4 git commands to generate.