X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftui%2Ftui-hooks.c;h=9bac4a883aa7975b09e52e1de00f6d2fc622dbea;hb=268a13a5a3f7c6b9b6ffc5ac2d1b24eb41f3fbdc;hp=fbdf5bf56ac12c5024b71710c869afbbbc827d9a;hpb=6a83354a43c2dc48a253ee15eb62ccd1a8cd1b48;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c
index fbdf5bf56a..9bac4a883a 100644
--- a/gdb/tui/tui-hooks.c
+++ b/gdb/tui/tui-hooks.c
@@ -1,12 +1,12 @@
/* GDB hooks for TUI.
- Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 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 . */
#include "defs.h"
#include "symtab.h"
@@ -32,10 +30,10 @@
#include "event-top.h"
#include "frame.h"
#include "breakpoint.h"
-#include "gdb-events.h"
#include "ui-out.h"
#include "top.h"
-#include
+#include "observable.h"
+#include "source.h"
#include
#include
@@ -52,106 +50,38 @@
#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 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
- tui_check_data_values (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;
- tui_check_data_values (fi);
+ tui_check_register_values (fi);
tui_refreshing_registers = 0;
}
}
@@ -159,7 +89,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 ();
}
@@ -167,154 +97,193 @@ 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_register_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;
+}
+
+/* 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 ();
+}
+
+/* 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);
+}
- 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)
+/* Observer for source_cache_cleared. */
+
+static void
+tui_redisplay_source ()
+{
+ if (tui_is_window_visible (SRC_WIN))
{
- 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). */
- tui_show_frame_info (fi);
-
- /* Refresh the register window if it's visible. */
- if (tui_is_window_visible (DATA_WIN))
- {
- tui_refreshing_registers = 1;
- tui_check_data_values (fi);
- tui_refreshing_registers = 0;
- }
+ /* Force redisplay. */
+ TUI_SRC_WIN->refill ();
}
}
-/* Called from print_frame_info to list the line we stopped in. */
+/* 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
static void
-tui_print_frame_info_listing_hook (struct symtab *s, int line,
- int stopline, int noerror)
+attach_or_detach (T &observable, typename T::func_type func, bool attach)
{
- select_source_symtab (s);
- tui_show_frame_info (deprecated_selected_frame);
+ if (attach)
+ observable.attach (func, tui_observers_token);
+ else
+ observable.detach (tui_observers_token);
}
-/* Called when the target process died or is detached.
- Update the status line. */
+/* Attach or detach TUI observers, according to ATTACH. */
+
static void
-tui_detach_hook (void)
+tui_attach_detach_observers (bool attach)
{
- tui_show_frame_info (0);
- tui_display_main ();
+ 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)
{
- 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_attach_detach_observers (true);
}
/* 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;
-void _initialize_tui_hooks (void);
+ /* Remove our observers. */
+ tui_attach_detach_observers (false);
+}
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;
+ gdb::observers::new_objfile.attach (tui_new_objfile_hook);
}