1 /* TUI Interpreter definitions for GDB, the GNU debugger.
3 Copyright (C) 2003-2022 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "cli/cli-interp.h"
24 #include "event-top.h"
25 #include "gdbsupport/event-loop.h"
28 #include "tui/tui-data.h"
29 #include "tui/tui-win.h"
31 #include "tui/tui-io.h"
33 #include "observable.h"
34 #include "gdbthread.h"
38 /* Set to true when the TUI mode must be activated when we first start
40 static bool tui_start_enabled
= false;
42 class tui_interp final
: public cli_interp_base
45 explicit tui_interp (const char *name
)
46 : cli_interp_base (name
)
49 void init (bool top_level
) override
;
50 void resume () override
;
51 void suspend () override
;
52 gdb_exception
exec (const char *command_str
) override
;
53 ui_out
*interp_ui_out () override
;
56 /* Returns the INTERP if the INTERP is a TUI, and returns NULL
60 as_tui_interp (struct interp
*interp
)
62 return dynamic_cast<tui_interp
*> (interp
);
65 /* Cleanup the tui before exiting. */
70 /* Disable the tui. Curses mode is left leaving the screen in a
71 clean state (see endwin()). */
75 /* Observers for several run control events. If the interpreter is
76 quiet (i.e., another interpreter is being run with
77 interpreter-exec), print nothing. */
79 /* Observer for the normal_stop notification. */
82 tui_on_normal_stop (struct bpstat
*bs
, int print_frame
)
87 /* This event is suppressed. */
88 if (cli_suppress_notification
.normal_stop
)
91 SWITCH_THRU_ALL_UIS ()
93 struct interp
*interp
= top_level_interpreter ();
94 struct interp
*tui
= as_tui_interp (interp
);
95 struct thread_info
*thread
;
100 thread
= inferior_thread ();
101 if (should_print_stop_to_console (interp
, thread
))
102 print_stop_event (tui
->interp_ui_out ());
106 /* Observer for the signal_received notification. */
109 tui_on_signal_received (enum gdb_signal siggnal
)
111 SWITCH_THRU_ALL_UIS ()
113 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
118 print_signal_received_reason (tui
->interp_ui_out (), siggnal
);
122 /* Observer for the end_stepping_range notification. */
125 tui_on_end_stepping_range (void)
127 SWITCH_THRU_ALL_UIS ()
129 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
134 print_end_stepping_range_reason (tui
->interp_ui_out ());
138 /* Observer for the signal_exited notification. */
141 tui_on_signal_exited (enum gdb_signal siggnal
)
143 SWITCH_THRU_ALL_UIS ()
145 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
150 print_signal_exited_reason (tui
->interp_ui_out (), siggnal
);
154 /* Observer for the exited notification. */
157 tui_on_exited (int exitstatus
)
159 SWITCH_THRU_ALL_UIS ()
161 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
166 print_exited_reason (tui
->interp_ui_out (), exitstatus
);
170 /* Observer for the no_history notification. */
173 tui_on_no_history (void)
175 SWITCH_THRU_ALL_UIS ()
177 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
182 print_no_history_reason (tui
->interp_ui_out ());
186 /* Observer for the sync_execution_done notification. */
189 tui_on_sync_execution_done (void)
191 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
196 display_gdb_prompt (NULL
);
199 /* Observer for the command_error notification. */
202 tui_on_command_error (void)
204 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
209 display_gdb_prompt (NULL
);
212 /* Observer for the user_selected_context_changed notification. */
215 tui_on_user_selected_context_changed (user_selected_what selection
)
217 /* This event is suppressed. */
218 if (cli_suppress_notification
.user_selected_context
)
221 thread_info
*tp
= inferior_ptid
!= null_ptid
? inferior_thread () : NULL
;
223 SWITCH_THRU_ALL_UIS ()
225 struct interp
*tui
= as_tui_interp (top_level_interpreter ());
230 if (selection
& USER_SELECTED_INFERIOR
)
231 print_selected_inferior (tui
->interp_ui_out ());
234 && ((selection
& (USER_SELECTED_THREAD
| USER_SELECTED_FRAME
))))
235 print_selected_thread_frame (tui
->interp_ui_out (), selection
);
240 /* These implement the TUI interpreter. */
243 tui_interp::init (bool top_level
)
245 /* Install exit handler to leave the screen in a good shape. */
248 tui_initialize_io ();
249 if (gdb_stdout
->isatty ())
251 tui_ensure_readline_initialized ();
253 /* This installs the SIGWINCH signal handler. The handler needs to do
254 readline calls (to rl_resize_terminal), so it must not be installed
255 unless readline is properly initialized. */
256 tui_initialize_win ();
260 /* Used as the command handler for the tui. */
263 tui_command_line_handler (gdb::unique_xmalloc_ptr
<char> &&rl
)
265 /* When a tui enabled GDB is running in either tui mode or cli mode then
266 it is always the tui interpreter that is in use. As a result we end
267 up in here even in standard cli mode.
269 We only need to do any special actions when the tui is in use
270 though. When the tui is active the users return is not echoed to the
271 screen as a result the display will not automatically move us to the
272 next line. Here we manually insert a newline character and move the
275 tui_inject_newline_into_command_window ();
277 /* Now perform GDB's standard CLI command line handling. */
278 command_line_handler (std::move (rl
));
282 tui_interp::resume ()
284 struct ui
*ui
= current_ui
;
285 struct ui_file
*stream
;
287 /* gdb_setup_readline will change gdb_stdout. If the TUI was
288 previously writing to gdb_stdout, then set it to the new
289 gdb_stdout afterwards. */
291 stream
= tui_old_uiout
->set_stream (gdb_stdout
);
292 if (stream
!= gdb_stdout
)
294 tui_old_uiout
->set_stream (stream
);
298 gdb_setup_readline (1);
300 ui
->input_handler
= tui_command_line_handler
;
303 tui_old_uiout
->set_stream (gdb_stdout
);
305 if (tui_start_enabled
)
310 tui_interp::suspend ()
312 tui_start_enabled
= tui_active
;
317 tui_interp::interp_ui_out ()
322 return tui_old_uiout
;
326 tui_interp::exec (const char *command_str
)
328 internal_error (__FILE__
, __LINE__
, _("tui_exec called"));
332 /* Factory for TUI interpreters. */
334 static struct interp
*
335 tui_interp_factory (const char *name
)
337 return new tui_interp (name
);
340 void _initialize_tui_interp ();
342 _initialize_tui_interp ()
344 interp_factory_register (INTERP_TUI
, tui_interp_factory
);
346 if (interpreter_p
&& strcmp (interpreter_p
, INTERP_TUI
) == 0)
347 tui_start_enabled
= true;
349 if (interpreter_p
&& strcmp (interpreter_p
, INTERP_CONSOLE
) == 0)
351 xfree (interpreter_p
);
352 interpreter_p
= xstrdup (INTERP_TUI
);
355 /* If changing this, remember to update cli-interp.c as well. */
356 gdb::observers::normal_stop
.attach (tui_on_normal_stop
, "tui-interp");
357 gdb::observers::signal_received
.attach (tui_on_signal_received
, "tui-interp");
358 gdb::observers::end_stepping_range
.attach (tui_on_end_stepping_range
,
360 gdb::observers::signal_exited
.attach (tui_on_signal_exited
, "tui-interp");
361 gdb::observers::exited
.attach (tui_on_exited
, "tui-interp");
362 gdb::observers::no_history
.attach (tui_on_no_history
, "tui-interp");
363 gdb::observers::sync_execution_done
.attach (tui_on_sync_execution_done
,
365 gdb::observers::command_error
.attach (tui_on_command_error
, "tui-interp");
366 gdb::observers::user_selected_context_changed
.attach
367 (tui_on_user_selected_context_changed
, "tui-interp");