Rename common to gdbsupport
[deliverable/binutils-gdb.git] / gdb / tui / tui-hooks.c
index 4d1e06346f4244bfd0f548733be7baa531a8847a..9bac4a883aa7975b09e52e1de00f6d2fc622dbea 100644 (file)
@@ -1,6 +1,6 @@
 /* GDB hooks for TUI.
 
-   Copyright (C) 2001-2012 Free Software Foundation, Inc.
+   Copyright (C) 2001-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -32,7 +32,8 @@
 #include "breakpoint.h"
 #include "ui-out.h"
 #include "top.h"
-#include "observer.h"
+#include "observable.h"
+#include "source.h"
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -54,8 +55,6 @@
    "gdb_curses.h".  */
 #include "readline/readline.h"
 
-int tui_target_has_run = 0;
-
 static void
 tui_new_objfile_hook (struct objfile* objfile)
 {
@@ -63,81 +62,26 @@ tui_new_objfile_hook (struct objfile* objfile)
     tui_display_main ();
 }
 
-static int ATTRIBUTE_PRINTF (1, 0)
-tui_query_hook (const char *msg, va_list argp)
-{
-  int retval;
-  int ans2;
-  int answer;
-  char *question;
-  struct cleanup *old_chain;
-
-  /* Format the question outside of the loop, to avoid reusing
-     ARGP.  */
-  question = xstrvprintf (msg, argp);
-  old_chain = make_cleanup (xfree, question);
-
-  echo ();
-  while (1)
-    {
-      wrap_here ("");          /* Flush any buffered output.  */
-      gdb_flush (gdb_stdout);
-
-      fputs_filtered (question, gdb_stdout);
-      printf_filtered (_("(y or n) "));
-
-      wrap_here ("");
-      gdb_flush (gdb_stdout);
-
-      answer = tui_getc (stdin);
-      clearerr (stdin);                /* in case of C-d */
-      if (answer == EOF)       /* C-d */
-       {
-         retval = 1;
-         break;
-       }
-      /* Eat rest of input line, to EOF or newline.  */
-      if (answer != '\n')
-       do
-         {
-            ans2 = tui_getc (stdin);
-           clearerr (stdin);
-         }
-       while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
-
-      if (answer >= 'a')
-       answer -= 040;
-      if (answer == 'Y')
-       {
-         retval = 1;
-         break;
-       }
-      if (answer == 'N')
-       {
-         retval = 0;
-         break;
-       }
-      printf_filtered (_("Please answer y or n.\n"));
-    }
-  noecho ();
-
-  do_cleanups (old_chain);
-  return retval;
-}
-
 /* Prevent recursion of deprecated_register_changed_hook().  */
 static int tui_refreshing_registers = 0;
 
+/* Observer for the register_changed notification.  */
+
 static void
-tui_register_changed_hook (int regno)
+tui_register_changed (struct frame_info *frame, int regno)
 {
   struct frame_info *fi;
 
+  /* The frame of the register that was changed may differ from the selected
+     frame, but we only want to show the register values of the selected frame.
+     And even if the frames differ a register change made in one can still show
+     up in the other.  So we always use the selected frame here, and ignore
+     FRAME.  */
   fi = get_selected_frame (NULL);
   if (tui_refreshing_registers == 0)
     {
       tui_refreshing_registers = 1;
-      tui_check_data_values (fi);
+      tui_check_register_values (fi);
       tui_refreshing_registers = 0;
     }
 }
@@ -164,46 +108,25 @@ tui_event_modify_breakpoint (struct breakpoint *b)
   tui_update_all_breakpoint_info ();
 }
 
-/* Called when going to wait for the target.
-   Leave curses mode and setup program mode.  */
-static ptid_t
-tui_target_wait_hook (ptid_t pid, 
-                     struct target_waitstatus *status, int options)
-{
-  ptid_t res;
+/* Refresh TUI's frame and register information.  This is a hook intended to be
+   used to update the screen after potential frame and register changes.
 
-  /* Leave tui mode (optional).  */
-#if 0
-  if (tui_active)
-    {
-      target_terminal_ours ();
-      endwin ();
-      target_terminal_inferior ();
-    }
-#endif
-  tui_target_has_run = 1;
-  res = target_wait (pid, status, options);
+   REGISTERS_TOO_P controls whether to refresh our register information even
+   if frame information hasn't changed.  */
 
-  if (tui_active)
-    {
-      /* TODO: need to refresh (optional).  */
-    }
-  return res;
-}
-
-/* The selected frame has changed.  This is happens after a target
-   stop or when the user explicitly changes the frame
-   (up/down/thread/...).  */
 static void
-tui_selected_frame_level_changed_hook (int level)
+tui_refresh_frame_and_register_information (int registers_too_p)
 {
   struct frame_info *fi;
   CORE_ADDR pc;
+  int frame_info_changed_p;
 
-  /* Negative level means that the selected frame was cleared.  */
-  if (level < 0)
+  if (!has_stack_frames ())
     return;
 
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
+
   fi = get_selected_frame (NULL);
   /* Ensure that symbols for this frame are read in.  Also, determine
      the source language of this frame, and switch to it if
@@ -212,7 +135,7 @@ tui_selected_frame_level_changed_hook (int level)
     {
       struct symtab *s;
 
-      s = find_pc_symtab (pc);
+      s = find_pc_line_symtab (pc);
       /* elz: This if here fixes the problem with the pc not being
         displayed in the tui asm layout, with no debug symbols.  The
         value of s would be 0 here, and select_source_symtab would
@@ -223,91 +146,144 @@ tui_selected_frame_level_changed_hook (int level)
 
   /* Display the frame position (even if there is no symbols or the PC
      is not known).  */
-  tui_show_frame_info (fi);
+  frame_info_changed_p = tui_show_frame_info (fi);
 
   /* Refresh the register window if it's visible.  */
-  if (tui_is_window_visible (DATA_WIN))
+  if (tui_is_window_visible (DATA_WIN)
+      && (frame_info_changed_p || registers_too_p))
     {
       tui_refreshing_registers = 1;
-      tui_check_data_values (fi);
+      tui_check_register_values (fi);
       tui_refreshing_registers = 0;
     }
 }
 
-/* Called from print_frame_info to list the line we stopped in.  */
+/* Dummy callback for deprecated_print_frame_info_listing_hook which is called
+   from print_frame_info.  */
+
 static void
-tui_print_frame_info_listing_hook (struct symtab *s,
-                                  int line,
-                                   int stopline, 
-                                  int noerror)
+tui_dummy_print_frame_info_listing_hook (struct symtab *s,
+                                        int line,
+                                        int stopline, 
+                                        int noerror)
 {
-  select_source_symtab (s);
-  tui_show_frame_info (get_selected_frame (NULL));
 }
 
-/* Called when the target process died or is detached.
-   Update the status line.  */
+/* Perform all necessary cleanups regarding our module's inferior data
+   that is required after the inferior INF just exited.  */
+
 static void
-tui_detach_hook (void)
+tui_inferior_exit (struct inferior *inf)
 {
+  /* Leave the SingleKey mode to make sure the gdb prompt is visible.  */
+  tui_set_key_mode (TUI_COMMAND_MODE);
   tui_show_frame_info (0);
   tui_display_main ();
 }
 
-/* Observers created when installing TUI hooks.  */
-static struct observer *tui_bp_created_observer;
-static struct observer *tui_bp_deleted_observer;
-static struct observer *tui_bp_modified_observer;
+/* Observer for the before_prompt notification.  */
+
+static void
+tui_before_prompt (const char *current_gdb_prompt)
+{
+  /* This refresh is intended to catch changes to the selected frame following
+     a call to "up", "down" or "frame".  As such we don't necessarily want to
+     refresh registers here unless the frame actually changed by one of these
+     commands.  Registers will otherwise be refreshed after a normal stop or by
+     our tui_register_changed_hook.  */
+  tui_refresh_frame_and_register_information (/*registers_too_p=*/0);
+}
+
+/* Observer for the normal_stop notification.  */
+
+static void
+tui_normal_stop (struct bpstats *bs, int print_frame)
+{
+  /* This refresh is intended to catch changes to the selected frame and to
+     registers following a normal stop.  */
+  tui_refresh_frame_and_register_information (/*registers_too_p=*/1);
+}
+
+/* Observer for source_cache_cleared.  */
+
+static void
+tui_redisplay_source ()
+{
+  if (tui_is_window_visible (SRC_WIN))
+    {
+      /* Force redisplay.  */
+      TUI_SRC_WIN->refill ();
+    }
+}
+
+/* Token associated with observers registered while TUI hooks are
+   installed.  */
+static const gdb::observers::token tui_observers_token {};
+
+/* Attach or detach a single observer, according to ATTACH.  */
+
+template<typename T>
+static void
+attach_or_detach (T &observable, typename T::func_type func, bool attach)
+{
+  if (attach)
+    observable.attach (func, tui_observers_token);
+  else
+    observable.detach (tui_observers_token);
+}
+
+/* Attach or detach TUI observers, according to ATTACH.  */
+
+static void
+tui_attach_detach_observers (bool attach)
+{
+  attach_or_detach (gdb::observers::breakpoint_created,
+                   tui_event_create_breakpoint, attach);
+  attach_or_detach (gdb::observers::breakpoint_deleted,
+                   tui_event_delete_breakpoint, attach);
+  attach_or_detach (gdb::observers::breakpoint_modified,
+                   tui_event_modify_breakpoint, attach);
+  attach_or_detach (gdb::observers::inferior_exit,
+                   tui_inferior_exit, attach);
+  attach_or_detach (gdb::observers::before_prompt,
+                   tui_before_prompt, attach);
+  attach_or_detach (gdb::observers::normal_stop,
+                   tui_normal_stop, attach);
+  attach_or_detach (gdb::observers::register_changed,
+                   tui_register_changed, attach);
+  attach_or_detach (gdb::observers::source_styling_changed,
+                   tui_redisplay_source, attach);
+}
 
 /* Install the TUI specific hooks.  */
 void
 tui_install_hooks (void)
 {
-  deprecated_target_wait_hook = tui_target_wait_hook;
-  deprecated_selected_frame_level_changed_hook
-    = tui_selected_frame_level_changed_hook;
+  /* If this hook is not set to something then print_frame_info will
+     assume that the CLI, not the TUI, is active, and will print the frame info
+     for us in such a way that we are not prepared to handle.  This hook is
+     otherwise effectively obsolete.  */
   deprecated_print_frame_info_listing_hook
-    = tui_print_frame_info_listing_hook;
-
-  deprecated_query_hook = tui_query_hook;
+    = tui_dummy_print_frame_info_listing_hook;
 
   /* Install the event hooks.  */
-  tui_bp_created_observer
-    = observer_attach_breakpoint_created (tui_event_create_breakpoint);
-  tui_bp_deleted_observer
-    = observer_attach_breakpoint_deleted (tui_event_delete_breakpoint);
-  tui_bp_modified_observer
-    = observer_attach_breakpoint_modified (tui_event_modify_breakpoint);
-
-  deprecated_register_changed_hook = tui_register_changed_hook;
-  deprecated_detach_hook = tui_detach_hook;
+  tui_attach_detach_observers (true);
 }
 
 /* Remove the TUI specific hooks.  */
 void
 tui_remove_hooks (void)
 {
-  deprecated_target_wait_hook = 0;
-  deprecated_selected_frame_level_changed_hook = 0;
   deprecated_print_frame_info_listing_hook = 0;
   deprecated_query_hook = 0;
-  deprecated_register_changed_hook = 0;
-  deprecated_detach_hook = 0;
 
   /* Remove our observers.  */
-  observer_detach_breakpoint_created (tui_bp_created_observer);
-  tui_bp_created_observer = NULL;
-  observer_detach_breakpoint_deleted (tui_bp_deleted_observer);
-  tui_bp_deleted_observer = NULL;
-  observer_detach_breakpoint_modified (tui_bp_modified_observer);
-  tui_bp_modified_observer = NULL;
+  tui_attach_detach_observers (false);
 }
 
-void _initialize_tui_hooks (void);
-
 void
 _initialize_tui_hooks (void)
 {
   /* Install the permanent hooks.  */
-  observer_attach_new_objfile (tui_new_objfile_hook);
+  gdb::observers::new_objfile.attach (tui_new_objfile_hook);
 }
This page took 0.0289 seconds and 4 git commands to generate.