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); }