DWARF-5: .debug_names index consumer
[deliverable/binutils-gdb.git] / gdb / tui / tui-hooks.c
index f0f2060d87b27422e6a063d4898b1d619b0fd4b5..2dd1bc02d04a1cf261502c52085df54fe522b96b 100644 (file)
@@ -1,12 +1,12 @@
 /* GDB hooks for TUI.
 
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "symtab.h"
 #include "event-top.h"
 #include "frame.h"
 #include "breakpoint.h"
-#include "gdb-events.h"
 #include "ui-out.h"
 #include "top.h"
-#include <readline/readline.h>
+#include "observer.h"
 #include <unistd.h>
 #include <fcntl.h>
 
 #include "tui/tui.h"
+#include "tui/tui-hooks.h"
 #include "tui/tui-data.h"
 #include "tui/tui-layout.h"
 #include "tui/tui-io.h"
 #include "tui/tui-windata.h"
 #include "tui/tui-winsource.h"
 
-#ifdef HAVE_NCURSES_H
-#include <ncurses.h>
-#else
-#ifdef HAVE_CURSES_H
-#include <curses.h>
-#endif
-#endif
+#include "gdb_curses.h"
 
-int tui_target_has_run = 0;
-
-static void (* tui_target_new_objfile_chain) (struct objfile*);
+/* This redefines CTRL if it is not already defined, so it must come
+   after terminal state releated include files like <term.h> and
+   "gdb_curses.h".  */
+#include "readline/readline.h"
 
 static void
 tui_new_objfile_hook (struct objfile* objfile)
 {
   if (tui_active)
     tui_display_main ();
-  
-  if (tui_target_new_objfile_chain)
-    tui_target_new_objfile_chain (objfile);
 }
 
-static int
-tui_query_hook (const char * msg, va_list argp)
-{
-  int retval;
-  int ans2;
-  int answer;
-
-  /* Automatically answer "yes" if input is not from a terminal.  */
-  if (!input_from_terminal_p ())
-    return 1;
-
-  echo ();
-  while (1)
-    {
-      wrap_here ("");          /* Flush any buffered output */
-      gdb_flush (gdb_stdout);
-
-      vfprintf_filtered (gdb_stdout, msg, argp);
-      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 ();
-  return retval;
-}
-
-/* Prevent recursion of registers_changed_hook().  */
+/* Prevent recursion of deprecated_register_changed_hook().  */
 static int tui_refreshing_registers = 0;
 
-static void
-tui_registers_changed_hook (void)
-{
-  struct frame_info *fi;
-
-  fi = deprecated_selected_frame;
-  if (fi && tui_refreshing_registers == 0)
-    {
-      tui_refreshing_registers = 1;
-#if 0
-      tuiCheckDataValues (fi);
-#endif
-      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;
 
-  fi = deprecated_selected_frame;
-  if (fi && tui_refreshing_registers == 0)
+  /* 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;
-      tuiCheckDataValues (fi);
+      tui_check_data_values (fi);
       tui_refreshing_registers = 0;
     }
 }
@@ -164,7 +88,7 @@ tui_register_changed_hook (int regno)
 /* Breakpoint creation hook.
    Update the screen to show the new breakpoint.  */
 static void
-tui_event_create_breakpoint (int number)
+tui_event_create_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }
@@ -172,154 +96,176 @@ tui_event_create_breakpoint (int number)
 /* Breakpoint deletion hook.
    Refresh the screen to update the breakpoint marks.  */
 static void
-tui_event_delete_breakpoint (int number)
+tui_event_delete_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }
 
 static void
-tui_event_modify_breakpoint (int number)
+tui_event_modify_breakpoint (struct breakpoint *b)
 {
   tui_update_all_breakpoint_info ();
 }
 
+/* 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.
+
+   REGISTERS_TOO_P controls whether to refresh our register information even
+   if frame information hasn't changed.  */
+
 static void
-tui_event_default (int number)
+tui_refresh_frame_and_register_information (int registers_too_p)
 {
-  ;
-}
+  struct frame_info *fi;
+  CORE_ADDR pc;
+  int frame_info_changed_p;
 
-static struct gdb_events *tui_old_event_hooks;
+  if (!has_stack_frames ())
+    return;
 
-static struct gdb_events tui_event_hooks =
-{
-  tui_event_create_breakpoint,
-  tui_event_delete_breakpoint,
-  tui_event_modify_breakpoint,
-  tui_event_default,
-  tui_event_default,
-  tui_event_default
-};
-
-/* 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)
-{
-  ptid_t res;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-  /* Leave tui mode (optional).  */
-#if 0
-  if (tui_active)
+  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
+     desired.  */
+  if (get_frame_pc_if_available (fi, &pc))
     {
-      target_terminal_ours ();
-      endwin ();
-      target_terminal_inferior ();
+      struct symtab *s;
+
+      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
+        abort the command by calling the 'error' function.  */
+      if (s)
+       select_source_symtab (s);
     }
-#endif
-  tui_target_has_run = 1;
-  res = target_wait (pid, status);
 
-  if (tui_active)
+  /* Display the frame position (even if there is no symbols or the PC
+     is not known).  */
+  frame_info_changed_p = tui_show_frame_info (fi);
+
+  /* Refresh the register window if it's visible.  */
+  if (tui_is_window_visible (DATA_WIN)
+      && (frame_info_changed_p || registers_too_p))
     {
-      /* TODO: need to refresh (optional).  */
+      tui_refreshing_registers = 1;
+      tui_check_data_values (fi);
+      tui_refreshing_registers = 0;
     }
-  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/...).  */
+/* Dummy callback for deprecated_print_frame_info_listing_hook which is called
+   from print_frame_info.  */
+
 static void
-tui_selected_frame_level_changed_hook (int level)
+tui_dummy_print_frame_info_listing_hook (struct symtab *s,
+                                        int line,
+                                        int stopline, 
+                                        int noerror)
 {
-  struct frame_info *fi;
+}
 
-  fi = deprecated_selected_frame;
-  /* Ensure that symbols for this frame are read in.  Also, determine the
-     source language of this frame, and switch to it if desired.  */
-  if (fi)
-    {
-      struct symtab *s;
-      
-      s = find_pc_symtab (get_frame_pc (fi));
-      /* 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 abort the
-         command by calling the 'error' function */
-      if (s)
-        select_source_symtab (s);
-
-      /* Display the frame position (even if there is no symbols).  */
-      tuiShowFrameInfo (fi);
-
-      /* Refresh the register window if it's visible.  */
-      if (tui_is_window_visible (DATA_WIN))
-        {
-          tui_refreshing_registers = 1;
-          tuiCheckDataValues (fi);
-          tui_refreshing_registers = 0;
-        }
-    }
+/* Perform all necessary cleanups regarding our module's inferior data
+   that is required after the inferior INF just exited.  */
+
+static 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 ();
 }
 
-/* Called from print_frame_info to list the line we stopped in.  */
+/* Observer for the before_prompt notification.  */
+
 static void
-tui_print_frame_info_listing_hook (struct symtab *s, int line,
-                                   int stopline, int noerror)
+tui_before_prompt (const char *current_gdb_prompt)
 {
-  select_source_symtab (s);
-  tuiShowFrameInfo (deprecated_selected_frame);
+  /* 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);
 }
 
-/* Called when the target process died or is detached.
-   Update the status line.  */
+/* Observer for the normal_stop notification.  */
+
 static void
-tui_detach_hook (void)
+tui_normal_stop (struct bpstats *bs, int print_frame)
 {
-  tuiShowFrameInfo (0);
-  tui_display_main ();
+  /* 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);
 }
 
+/* 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;
+static struct observer *tui_inferior_exit_observer;
+static struct observer *tui_before_prompt_observer;
+static struct observer *tui_normal_stop_observer;
+static struct observer *tui_register_changed_observer;
+
 /* Install the TUI specific hooks.  */
 void
 tui_install_hooks (void)
 {
-  target_wait_hook = tui_target_wait_hook;
-  selected_frame_level_changed_hook = tui_selected_frame_level_changed_hook;
-  print_frame_info_listing_hook = tui_print_frame_info_listing_hook;
-
-  query_hook = tui_query_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_dummy_print_frame_info_listing_hook;
 
   /* Install the event hooks.  */
-  tui_old_event_hooks = set_gdb_event_hooks (&tui_event_hooks);
-
-  registers_changed_hook = tui_registers_changed_hook;
-  register_changed_hook = tui_register_changed_hook;
-  detach_hook = tui_detach_hook;
+  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);
+  tui_inferior_exit_observer
+    = observer_attach_inferior_exit (tui_inferior_exit);
+  tui_before_prompt_observer
+    = observer_attach_before_prompt (tui_before_prompt);
+  tui_normal_stop_observer
+    = observer_attach_normal_stop (tui_normal_stop);
+  tui_register_changed_observer
+    = observer_attach_register_changed (tui_register_changed);
 }
 
 /* Remove the TUI specific hooks.  */
 void
 tui_remove_hooks (void)
 {
-  target_wait_hook = 0;
-  selected_frame_level_changed_hook = 0;
-  print_frame_info_listing_hook = 0;
-  query_hook = 0;
-  registers_changed_hook = 0;
-  register_changed_hook = 0;
-  detach_hook = 0;
-
-  /* Restore the previous event hooks.  */
-  set_gdb_event_hooks (tui_old_event_hooks);
+  deprecated_print_frame_info_listing_hook = 0;
+  deprecated_query_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;
+  observer_detach_inferior_exit (tui_inferior_exit_observer);
+  tui_inferior_exit_observer = NULL;
+  observer_detach_before_prompt (tui_before_prompt_observer);
+  tui_before_prompt_observer = NULL;
+  observer_detach_normal_stop (tui_normal_stop_observer);
+  tui_normal_stop_observer = NULL;
+  observer_detach_register_changed (tui_register_changed_observer);
+  tui_register_changed_observer = NULL;
 }
 
-void _initialize_tui_hooks (void);
-
 void
 _initialize_tui_hooks (void)
 {
   /* Install the permanent hooks.  */
-  tui_target_new_objfile_chain = target_new_objfile_hook;
-  target_new_objfile_hook = tui_new_objfile_hook;
+  observer_attach_new_objfile (tui_new_objfile_hook);
 }
This page took 0.038663 seconds and 4 git commands to generate.