15796c8dcSSimon Schubert /* GDB hooks for TUI.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2001-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "symtab.h"
225796c8dcSSimon Schubert #include "inferior.h"
235796c8dcSSimon Schubert #include "command.h"
245796c8dcSSimon Schubert #include "bfd.h"
255796c8dcSSimon Schubert #include "symfile.h"
265796c8dcSSimon Schubert #include "objfiles.h"
275796c8dcSSimon Schubert #include "target.h"
285796c8dcSSimon Schubert #include "gdbcore.h"
295796c8dcSSimon Schubert #include "event-loop.h"
305796c8dcSSimon Schubert #include "event-top.h"
315796c8dcSSimon Schubert #include "frame.h"
325796c8dcSSimon Schubert #include "breakpoint.h"
335796c8dcSSimon Schubert #include "ui-out.h"
345796c8dcSSimon Schubert #include "top.h"
355796c8dcSSimon Schubert #include "observer.h"
365796c8dcSSimon Schubert #include <unistd.h>
375796c8dcSSimon Schubert #include <fcntl.h>
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert #include "tui/tui.h"
405796c8dcSSimon Schubert #include "tui/tui-hooks.h"
415796c8dcSSimon Schubert #include "tui/tui-data.h"
425796c8dcSSimon Schubert #include "tui/tui-layout.h"
435796c8dcSSimon Schubert #include "tui/tui-io.h"
445796c8dcSSimon Schubert #include "tui/tui-regs.h"
455796c8dcSSimon Schubert #include "tui/tui-win.h"
465796c8dcSSimon Schubert #include "tui/tui-stack.h"
475796c8dcSSimon Schubert #include "tui/tui-windata.h"
485796c8dcSSimon Schubert #include "tui/tui-winsource.h"
495796c8dcSSimon Schubert
505796c8dcSSimon Schubert #include "gdb_curses.h"
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert /* This redefines CTRL if it is not already defined, so it must come
535796c8dcSSimon Schubert after terminal state releated include files like <term.h> and
545796c8dcSSimon Schubert "gdb_curses.h". */
555796c8dcSSimon Schubert #include "readline/readline.h"
565796c8dcSSimon Schubert
575796c8dcSSimon Schubert int tui_target_has_run = 0;
585796c8dcSSimon Schubert
595796c8dcSSimon Schubert static void
tui_new_objfile_hook(struct objfile * objfile)605796c8dcSSimon Schubert tui_new_objfile_hook (struct objfile* objfile)
615796c8dcSSimon Schubert {
625796c8dcSSimon Schubert if (tui_active)
635796c8dcSSimon Schubert tui_display_main ();
645796c8dcSSimon Schubert }
655796c8dcSSimon Schubert
66cf7f2e2dSJohn Marino static int ATTRIBUTE_PRINTF (1, 0)
tui_query_hook(const char * msg,va_list argp)675796c8dcSSimon Schubert tui_query_hook (const char *msg, va_list argp)
685796c8dcSSimon Schubert {
695796c8dcSSimon Schubert int retval;
705796c8dcSSimon Schubert int ans2;
715796c8dcSSimon Schubert int answer;
72*ef5ccd6cSJohn Marino char *question;
73*ef5ccd6cSJohn Marino struct cleanup *old_chain;
74*ef5ccd6cSJohn Marino
75*ef5ccd6cSJohn Marino /* Format the question outside of the loop, to avoid reusing
76*ef5ccd6cSJohn Marino ARGP. */
77*ef5ccd6cSJohn Marino question = xstrvprintf (msg, argp);
78*ef5ccd6cSJohn Marino old_chain = make_cleanup (xfree, question);
795796c8dcSSimon Schubert
805796c8dcSSimon Schubert echo ();
815796c8dcSSimon Schubert while (1)
825796c8dcSSimon Schubert {
835796c8dcSSimon Schubert wrap_here (""); /* Flush any buffered output. */
845796c8dcSSimon Schubert gdb_flush (gdb_stdout);
855796c8dcSSimon Schubert
86*ef5ccd6cSJohn Marino fputs_filtered (question, gdb_stdout);
875796c8dcSSimon Schubert printf_filtered (_("(y or n) "));
885796c8dcSSimon Schubert
895796c8dcSSimon Schubert wrap_here ("");
905796c8dcSSimon Schubert gdb_flush (gdb_stdout);
915796c8dcSSimon Schubert
925796c8dcSSimon Schubert answer = tui_getc (stdin);
935796c8dcSSimon Schubert clearerr (stdin); /* in case of C-d */
945796c8dcSSimon Schubert if (answer == EOF) /* C-d */
955796c8dcSSimon Schubert {
965796c8dcSSimon Schubert retval = 1;
975796c8dcSSimon Schubert break;
985796c8dcSSimon Schubert }
995796c8dcSSimon Schubert /* Eat rest of input line, to EOF or newline. */
1005796c8dcSSimon Schubert if (answer != '\n')
1015796c8dcSSimon Schubert do
1025796c8dcSSimon Schubert {
1035796c8dcSSimon Schubert ans2 = tui_getc (stdin);
1045796c8dcSSimon Schubert clearerr (stdin);
1055796c8dcSSimon Schubert }
1065796c8dcSSimon Schubert while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
1075796c8dcSSimon Schubert
1085796c8dcSSimon Schubert if (answer >= 'a')
1095796c8dcSSimon Schubert answer -= 040;
1105796c8dcSSimon Schubert if (answer == 'Y')
1115796c8dcSSimon Schubert {
1125796c8dcSSimon Schubert retval = 1;
1135796c8dcSSimon Schubert break;
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert if (answer == 'N')
1165796c8dcSSimon Schubert {
1175796c8dcSSimon Schubert retval = 0;
1185796c8dcSSimon Schubert break;
1195796c8dcSSimon Schubert }
1205796c8dcSSimon Schubert printf_filtered (_("Please answer y or n.\n"));
1215796c8dcSSimon Schubert }
1225796c8dcSSimon Schubert noecho ();
123*ef5ccd6cSJohn Marino
124*ef5ccd6cSJohn Marino do_cleanups (old_chain);
1255796c8dcSSimon Schubert return retval;
1265796c8dcSSimon Schubert }
1275796c8dcSSimon Schubert
1285796c8dcSSimon Schubert /* Prevent recursion of deprecated_register_changed_hook(). */
1295796c8dcSSimon Schubert static int tui_refreshing_registers = 0;
1305796c8dcSSimon Schubert
1315796c8dcSSimon Schubert static void
tui_register_changed_hook(int regno)1325796c8dcSSimon Schubert tui_register_changed_hook (int regno)
1335796c8dcSSimon Schubert {
1345796c8dcSSimon Schubert struct frame_info *fi;
1355796c8dcSSimon Schubert
1365796c8dcSSimon Schubert fi = get_selected_frame (NULL);
1375796c8dcSSimon Schubert if (tui_refreshing_registers == 0)
1385796c8dcSSimon Schubert {
1395796c8dcSSimon Schubert tui_refreshing_registers = 1;
1405796c8dcSSimon Schubert tui_check_data_values (fi);
1415796c8dcSSimon Schubert tui_refreshing_registers = 0;
1425796c8dcSSimon Schubert }
1435796c8dcSSimon Schubert }
1445796c8dcSSimon Schubert
1455796c8dcSSimon Schubert /* Breakpoint creation hook.
1465796c8dcSSimon Schubert Update the screen to show the new breakpoint. */
1475796c8dcSSimon Schubert static void
tui_event_create_breakpoint(struct breakpoint * b)148a45ae5f8SJohn Marino tui_event_create_breakpoint (struct breakpoint *b)
1495796c8dcSSimon Schubert {
1505796c8dcSSimon Schubert tui_update_all_breakpoint_info ();
1515796c8dcSSimon Schubert }
1525796c8dcSSimon Schubert
1535796c8dcSSimon Schubert /* Breakpoint deletion hook.
1545796c8dcSSimon Schubert Refresh the screen to update the breakpoint marks. */
1555796c8dcSSimon Schubert static void
tui_event_delete_breakpoint(struct breakpoint * b)156a45ae5f8SJohn Marino tui_event_delete_breakpoint (struct breakpoint *b)
1575796c8dcSSimon Schubert {
1585796c8dcSSimon Schubert tui_update_all_breakpoint_info ();
1595796c8dcSSimon Schubert }
1605796c8dcSSimon Schubert
1615796c8dcSSimon Schubert static void
tui_event_modify_breakpoint(struct breakpoint * b)162a45ae5f8SJohn Marino tui_event_modify_breakpoint (struct breakpoint *b)
1635796c8dcSSimon Schubert {
1645796c8dcSSimon Schubert tui_update_all_breakpoint_info ();
1655796c8dcSSimon Schubert }
1665796c8dcSSimon Schubert
167*ef5ccd6cSJohn Marino /* Called when a command is about to proceed the inferior. */
1685796c8dcSSimon Schubert
169*ef5ccd6cSJohn Marino static void
tui_about_to_proceed(void)170*ef5ccd6cSJohn Marino tui_about_to_proceed (void)
171*ef5ccd6cSJohn Marino {
1725796c8dcSSimon Schubert /* Leave tui mode (optional). */
1735796c8dcSSimon Schubert #if 0
1745796c8dcSSimon Schubert if (tui_active)
1755796c8dcSSimon Schubert {
1765796c8dcSSimon Schubert target_terminal_ours ();
1775796c8dcSSimon Schubert endwin ();
1785796c8dcSSimon Schubert target_terminal_inferior ();
1795796c8dcSSimon Schubert }
1805796c8dcSSimon Schubert #endif
1815796c8dcSSimon Schubert tui_target_has_run = 1;
1825796c8dcSSimon Schubert }
1835796c8dcSSimon Schubert
1845796c8dcSSimon Schubert /* The selected frame has changed. This is happens after a target
1855796c8dcSSimon Schubert stop or when the user explicitly changes the frame
1865796c8dcSSimon Schubert (up/down/thread/...). */
1875796c8dcSSimon Schubert static void
tui_selected_frame_level_changed_hook(int level)1885796c8dcSSimon Schubert tui_selected_frame_level_changed_hook (int level)
1895796c8dcSSimon Schubert {
1905796c8dcSSimon Schubert struct frame_info *fi;
191c50c785cSJohn Marino CORE_ADDR pc;
1925796c8dcSSimon Schubert
1935796c8dcSSimon Schubert /* Negative level means that the selected frame was cleared. */
1945796c8dcSSimon Schubert if (level < 0)
1955796c8dcSSimon Schubert return;
1965796c8dcSSimon Schubert
1975796c8dcSSimon Schubert fi = get_selected_frame (NULL);
1985796c8dcSSimon Schubert /* Ensure that symbols for this frame are read in. Also, determine
1995796c8dcSSimon Schubert the source language of this frame, and switch to it if
2005796c8dcSSimon Schubert desired. */
201c50c785cSJohn Marino if (get_frame_pc_if_available (fi, &pc))
2025796c8dcSSimon Schubert {
2035796c8dcSSimon Schubert struct symtab *s;
2045796c8dcSSimon Schubert
205c50c785cSJohn Marino s = find_pc_symtab (pc);
2065796c8dcSSimon Schubert /* elz: This if here fixes the problem with the pc not being
2075796c8dcSSimon Schubert displayed in the tui asm layout, with no debug symbols. The
2085796c8dcSSimon Schubert value of s would be 0 here, and select_source_symtab would
2095796c8dcSSimon Schubert abort the command by calling the 'error' function. */
2105796c8dcSSimon Schubert if (s)
2115796c8dcSSimon Schubert select_source_symtab (s);
212c50c785cSJohn Marino }
2135796c8dcSSimon Schubert
214c50c785cSJohn Marino /* Display the frame position (even if there is no symbols or the PC
215c50c785cSJohn Marino is not known). */
2165796c8dcSSimon Schubert tui_show_frame_info (fi);
2175796c8dcSSimon Schubert
2185796c8dcSSimon Schubert /* Refresh the register window if it's visible. */
2195796c8dcSSimon Schubert if (tui_is_window_visible (DATA_WIN))
2205796c8dcSSimon Schubert {
2215796c8dcSSimon Schubert tui_refreshing_registers = 1;
2225796c8dcSSimon Schubert tui_check_data_values (fi);
2235796c8dcSSimon Schubert tui_refreshing_registers = 0;
2245796c8dcSSimon Schubert }
2255796c8dcSSimon Schubert }
2265796c8dcSSimon Schubert
2275796c8dcSSimon Schubert /* Called from print_frame_info to list the line we stopped in. */
2285796c8dcSSimon Schubert static void
tui_print_frame_info_listing_hook(struct symtab * s,int line,int stopline,int noerror)2295796c8dcSSimon Schubert tui_print_frame_info_listing_hook (struct symtab *s,
2305796c8dcSSimon Schubert int line,
2315796c8dcSSimon Schubert int stopline,
2325796c8dcSSimon Schubert int noerror)
2335796c8dcSSimon Schubert {
2345796c8dcSSimon Schubert select_source_symtab (s);
2355796c8dcSSimon Schubert tui_show_frame_info (get_selected_frame (NULL));
2365796c8dcSSimon Schubert }
2375796c8dcSSimon Schubert
238*ef5ccd6cSJohn Marino /* Perform all necessary cleanups regarding our module's inferior data
239*ef5ccd6cSJohn Marino that is required after the inferior INF just exited. */
240*ef5ccd6cSJohn Marino
2415796c8dcSSimon Schubert static void
tui_inferior_exit(struct inferior * inf)242*ef5ccd6cSJohn Marino tui_inferior_exit (struct inferior *inf)
2435796c8dcSSimon Schubert {
244*ef5ccd6cSJohn Marino /* Leave the SingleKey mode to make sure the gdb prompt is visible. */
245*ef5ccd6cSJohn Marino tui_set_key_mode (TUI_COMMAND_MODE);
2465796c8dcSSimon Schubert tui_show_frame_info (0);
2475796c8dcSSimon Schubert tui_display_main ();
2485796c8dcSSimon Schubert }
2495796c8dcSSimon Schubert
2505796c8dcSSimon Schubert /* Observers created when installing TUI hooks. */
2515796c8dcSSimon Schubert static struct observer *tui_bp_created_observer;
2525796c8dcSSimon Schubert static struct observer *tui_bp_deleted_observer;
2535796c8dcSSimon Schubert static struct observer *tui_bp_modified_observer;
254*ef5ccd6cSJohn Marino static struct observer *tui_inferior_exit_observer;
255*ef5ccd6cSJohn Marino static struct observer *tui_about_to_proceed_observer;
2565796c8dcSSimon Schubert
2575796c8dcSSimon Schubert /* Install the TUI specific hooks. */
2585796c8dcSSimon Schubert void
tui_install_hooks(void)2595796c8dcSSimon Schubert tui_install_hooks (void)
2605796c8dcSSimon Schubert {
261c50c785cSJohn Marino deprecated_selected_frame_level_changed_hook
262c50c785cSJohn Marino = tui_selected_frame_level_changed_hook;
263c50c785cSJohn Marino deprecated_print_frame_info_listing_hook
264c50c785cSJohn Marino = tui_print_frame_info_listing_hook;
2655796c8dcSSimon Schubert
2665796c8dcSSimon Schubert deprecated_query_hook = tui_query_hook;
2675796c8dcSSimon Schubert
2685796c8dcSSimon Schubert /* Install the event hooks. */
2695796c8dcSSimon Schubert tui_bp_created_observer
2705796c8dcSSimon Schubert = observer_attach_breakpoint_created (tui_event_create_breakpoint);
2715796c8dcSSimon Schubert tui_bp_deleted_observer
2725796c8dcSSimon Schubert = observer_attach_breakpoint_deleted (tui_event_delete_breakpoint);
2735796c8dcSSimon Schubert tui_bp_modified_observer
2745796c8dcSSimon Schubert = observer_attach_breakpoint_modified (tui_event_modify_breakpoint);
275*ef5ccd6cSJohn Marino tui_inferior_exit_observer
276*ef5ccd6cSJohn Marino = observer_attach_inferior_exit (tui_inferior_exit);
277*ef5ccd6cSJohn Marino tui_about_to_proceed_observer
278*ef5ccd6cSJohn Marino = observer_attach_about_to_proceed (tui_about_to_proceed);
2795796c8dcSSimon Schubert
2805796c8dcSSimon Schubert deprecated_register_changed_hook = tui_register_changed_hook;
2815796c8dcSSimon Schubert }
2825796c8dcSSimon Schubert
2835796c8dcSSimon Schubert /* Remove the TUI specific hooks. */
2845796c8dcSSimon Schubert void
tui_remove_hooks(void)2855796c8dcSSimon Schubert tui_remove_hooks (void)
2865796c8dcSSimon Schubert {
2875796c8dcSSimon Schubert deprecated_selected_frame_level_changed_hook = 0;
2885796c8dcSSimon Schubert deprecated_print_frame_info_listing_hook = 0;
2895796c8dcSSimon Schubert deprecated_query_hook = 0;
2905796c8dcSSimon Schubert deprecated_register_changed_hook = 0;
2915796c8dcSSimon Schubert
2925796c8dcSSimon Schubert /* Remove our observers. */
2935796c8dcSSimon Schubert observer_detach_breakpoint_created (tui_bp_created_observer);
2945796c8dcSSimon Schubert tui_bp_created_observer = NULL;
2955796c8dcSSimon Schubert observer_detach_breakpoint_deleted (tui_bp_deleted_observer);
2965796c8dcSSimon Schubert tui_bp_deleted_observer = NULL;
2975796c8dcSSimon Schubert observer_detach_breakpoint_modified (tui_bp_modified_observer);
2985796c8dcSSimon Schubert tui_bp_modified_observer = NULL;
299*ef5ccd6cSJohn Marino observer_detach_inferior_exit (tui_inferior_exit_observer);
300*ef5ccd6cSJohn Marino tui_inferior_exit_observer = NULL;
301*ef5ccd6cSJohn Marino observer_detach_about_to_proceed (tui_about_to_proceed_observer);
302*ef5ccd6cSJohn Marino tui_about_to_proceed_observer = NULL;
3035796c8dcSSimon Schubert }
3045796c8dcSSimon Schubert
3055796c8dcSSimon Schubert void _initialize_tui_hooks (void);
3065796c8dcSSimon Schubert
3075796c8dcSSimon Schubert void
_initialize_tui_hooks(void)3085796c8dcSSimon Schubert _initialize_tui_hooks (void)
3095796c8dcSSimon Schubert {
3105796c8dcSSimon Schubert /* Install the permanent hooks. */
3115796c8dcSSimon Schubert observer_attach_new_objfile (tui_new_objfile_hook);
3125796c8dcSSimon Schubert }
313