X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftui%2Ftui-interp.c;h=3e8442e7db666666c6d30e2f3c0a2af0e881921c;hb=112e8700a6fd2fed65ca70132c9cbed4132e8bd4;hp=f935ea4094ced5731da0acc51387f01146b25fdc;hpb=021e7609055e94c3b2f0ac757c9640d393ed2000;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c index f935ea4094..3e8442e7db 100644 --- a/gdb/tui/tui-interp.c +++ b/gdb/tui/tui-interp.c @@ -1,12 +1,12 @@ /* TUI Interpreter definitions for GDB, the GNU debugger. - Copyright 2003 Free Software Foundation, Inc. + Copyright (C) 2003-2016 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,44 +15,229 @@ 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 "cli/cli-interp.h" #include "interps.h" #include "top.h" #include "event-top.h" #include "event-loop.h" #include "ui-out.h" -#include "tui/tuiData.h" +#include "cli-out.h" +#include "tui/tui-data.h" #include "readline/readline.h" -#include "tui/tuiWin.h" +#include "tui/tui-win.h" #include "tui/tui.h" -#include "tui/tuiIO.h" +#include "tui/tui-io.h" +#include "infrun.h" +#include "observer.h" +#include "gdbthread.h" + +static struct ui_out *tui_ui_out (struct interp *self); + +/* Set to 1 when the TUI mode must be activated when we first start + gdb. */ +static int tui_start_enabled = 0; + +/* Returns the INTERP if the INTERP is a TUI, and returns NULL + otherwise. */ + +static struct interp * +as_tui_interp (struct interp *interp) +{ + if (strcmp (interp_name (interp), INTERP_TUI) == 0) + return interp; + return NULL; +} /* Cleanup the tui before exiting. */ static void tui_exit (void) { - /* Disable the tui. Curses mode is left leaving the screen - in a clean state (see endwin()). */ + /* Disable the tui. Curses mode is left leaving the screen in a + clean state (see endwin()). */ tui_disable (); } +/* Observers for several run control events. If the interpreter is + quiet (i.e., another interpreter is being run with + interpreter-exec), print nothing. */ + +/* Observer for the normal_stop notification. */ + +static void +tui_on_normal_stop (struct bpstats *bs, int print_frame) +{ + if (!print_frame) + return; + + SWITCH_THRU_ALL_UIS () + { + struct interp *interp = top_level_interpreter (); + struct interp *tui = as_tui_interp (interp); + struct thread_info *thread; + + if (tui == NULL) + continue; + + thread = inferior_thread (); + if (should_print_stop_to_console (interp, thread)) + print_stop_event (tui_ui_out (tui)); + } +} + +/* Observer for the signal_received notification. */ + +static void +tui_on_signal_received (enum gdb_signal siggnal) +{ + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + print_signal_received_reason (tui_ui_out (tui), siggnal); + } +} + +/* Observer for the end_stepping_range notification. */ + +static void +tui_on_end_stepping_range (void) +{ + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + print_end_stepping_range_reason (tui_ui_out (tui)); + } +} + +/* Observer for the signal_exited notification. */ + +static void +tui_on_signal_exited (enum gdb_signal siggnal) +{ + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + print_signal_exited_reason (tui_ui_out (tui), siggnal); + } +} + +/* Observer for the exited notification. */ + +static void +tui_on_exited (int exitstatus) +{ + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + print_exited_reason (tui_ui_out (tui), exitstatus); + } +} + +/* Observer for the no_history notification. */ + +static void +tui_on_no_history (void) +{ + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + print_no_history_reason (tui_ui_out (tui)); + } +} + +/* Observer for the sync_execution_done notification. */ + +static void +tui_on_sync_execution_done (void) +{ + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + return; + + display_gdb_prompt (NULL); +} + +/* Observer for the command_error notification. */ + +static void +tui_on_command_error (void) +{ + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + return; + + display_gdb_prompt (NULL); +} + +/* Observer for the user_selected_context_changed notification. */ + +static void +tui_on_user_selected_context_changed (user_selected_what selection) +{ + struct thread_info *tp; + + /* This event is suppressed. */ + if (cli_suppress_notification.user_selected_context) + return; + + tp = find_thread_ptid (inferior_ptid); + + SWITCH_THRU_ALL_UIS () + { + struct interp *tui = as_tui_interp (top_level_interpreter ()); + + if (tui == NULL) + continue; + + if (selection & USER_SELECTED_INFERIOR) + print_selected_inferior (tui_ui_out (tui)); + + if (tp != NULL + && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))) + print_selected_thread_frame (tui_ui_out (tui), selection); + + } +} + /* These implement the TUI interpreter. */ static void * -tui_init (void) +tui_init (struct interp *self, int top_level) { /* Install exit handler to leave the screen in a good shape. */ atexit (tui_exit); - initializeStaticData (); + tui_initialize_static_data (); tui_initialize_io (); - tui_initialize_readline (); + tui_initialize_win (); + if (ui_file_isatty (gdb_stdout)) + tui_initialize_readline (); return NULL; } @@ -60,121 +245,102 @@ tui_init (void) static int tui_resume (void *data) { - gdb_setup_readline (); - tui_enable (); + struct ui *ui = current_ui; + struct ui_file *stream; + + /* gdb_setup_readline will change gdb_stdout. If the TUI was + previously writing to gdb_stdout, then set it to the new + gdb_stdout afterwards. */ + + stream = tui_old_uiout->set_stream (gdb_stdout); + if (stream != gdb_stdout) + { + tui_old_uiout->set_stream (stream); + stream = NULL; + } + + gdb_setup_readline (1); + + ui->input_handler = command_line_handler; + + if (stream != NULL) + tui_old_uiout->set_stream (gdb_stdout); + + if (tui_start_enabled) + tui_enable (); return 1; } static int tui_suspend (void *data) { + tui_start_enabled = tui_active; tui_disable (); return 1; } -/* Display the prompt if we are silent. */ - -static int -tui_display_prompt_p (void *data) +static struct ui_out * +tui_ui_out (struct interp *self) { - if (interp_quiet_p (NULL)) - return 0; + if (tui_active) + return tui_out; else - return 1; + return tui_old_uiout; } -static int +static struct gdb_exception tui_exec (void *data, const char *command_str) { - internal_error (__FILE__, __LINE__, "tui_exec called"); + internal_error (__FILE__, __LINE__, _("tui_exec called")); } +/* The TUI interpreter's vtable. */ -/* Initialize all the necessary variables, start the event loop, - register readline, and stdin, start the loop. */ +static const struct interp_procs tui_interp_procs = { + tui_init, + tui_resume, + tui_suspend, + tui_exec, + tui_ui_out, + NULL, + cli_interpreter_pre_command_loop, + cli_interpreter_supports_command_editing, +}; -static void -tui_command_loop (void *data) -{ - int length; - char *a_prompt; - char *gdb_prompt = get_prompt (); - - /* If we are using readline, set things up and display the first - prompt, otherwise just print the prompt. */ - if (async_command_editing_p) - { - /* Tell readline what the prompt to display is and what function - it will need to call after a whole line is read. This also - displays the first prompt. */ - length = strlen (PREFIX (0)) + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1; - a_prompt = (char *) xmalloc (length); - strcpy (a_prompt, PREFIX (0)); - strcat (a_prompt, gdb_prompt); - strcat (a_prompt, SUFFIX (0)); - rl_callback_handler_install (a_prompt, input_handler); - } - else - display_gdb_prompt (0); - - /* Loop until there is nothing to do. This is the entry point to the - event loop engine. gdb_do_one_event, called via catch_errors() - will process one event for each invocation. It blocks waits for - an event and then processes it. >0 when an event is processed, 0 - when catch_errors() caught an error and <0 when there are no - longer any event sources registered. */ - while (1) - { - int result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); - if (result < 0) - break; - - /* Update gdb output according to TUI mode. Since catch_errors - preserves the uiout from changing, this must be done at top - level of event loop. */ - if (tui_active) - uiout = tui_out; - else - uiout = tui_old_uiout; - - if (result == 0) - { - /* FIXME: this should really be a call to a hook that is - interface specific, because interfaces can display the - prompt in their own way. */ - display_gdb_prompt (0); - /* This call looks bizarre, but it is required. If the user - entered a command that caused an error, - after_char_processing_hook won't be called from - rl_callback_read_char_wrapper. Using a cleanup there - won't work, since we want this function to be called - after a new prompt is printed. */ - if (after_char_processing_hook) - (*after_char_processing_hook) (); - /* Maybe better to set a flag to be checked somewhere as to - whether display the prompt or not. */ - } - } +/* Factory for TUI interpreters. */ - /* We are done with the event loop. There are no more event sources - to listen to. So we exit GDB. */ - return; +static struct interp * +tui_interp_factory (const char *name) +{ + return interp_new (name, &tui_interp_procs, NULL); } +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_tui_interp; + void _initialize_tui_interp (void) { - static const struct interp_procs procs = { - tui_init, - tui_resume, - tui_suspend, - tui_exec, - tui_display_prompt_p, - tui_command_loop, - }; - struct interp *tui_interp; - - /* Create a default uiout builder for the TUI. */ - tui_out = tui_out_new (gdb_stdout); - interp_add (interp_new ("tui", NULL, tui_out, &procs)); + interp_factory_register (INTERP_TUI, tui_interp_factory); + + if (interpreter_p && strcmp (interpreter_p, INTERP_TUI) == 0) + tui_start_enabled = 1; + + if (interpreter_p && strcmp (interpreter_p, INTERP_CONSOLE) == 0) + { + xfree (interpreter_p); + interpreter_p = xstrdup (INTERP_TUI); + } + + /* If changing this, remember to update cli-interp.c as well. */ + observer_attach_normal_stop (tui_on_normal_stop); + observer_attach_signal_received (tui_on_signal_received); + observer_attach_end_stepping_range (tui_on_end_stepping_range); + observer_attach_signal_exited (tui_on_signal_exited); + observer_attach_exited (tui_on_exited); + observer_attach_no_history (tui_on_no_history); + observer_attach_sync_execution_done (tui_on_sync_execution_done); + observer_attach_command_error (tui_on_command_error); + observer_attach_user_selected_context_changed + (tui_on_user_selected_context_changed); }