gdb: generate the prefix name for prefix commands on demand
[binutils-gdb.git] / gdb / tui / tui-interp.c
1 /* TUI Interpreter definitions for GDB, the GNU debugger.
2
3 Copyright (C) 2003-2021 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20 #include "defs.h"
21 #include "cli/cli-interp.h"
22 #include "interps.h"
23 #include "top.h"
24 #include "event-top.h"
25 #include "gdbsupport/event-loop.h"
26 #include "ui-out.h"
27 #include "cli-out.h"
28 #include "tui/tui-data.h"
29 #include "tui/tui-win.h"
30 #include "tui/tui.h"
31 #include "tui/tui-io.h"
32 #include "infrun.h"
33 #include "observable.h"
34 #include "gdbthread.h"
35 #include "inferior.h"
36 #include "main.h"
37
38 /* Set to true when the TUI mode must be activated when we first start
39 gdb. */
40 static bool tui_start_enabled = false;
41
42 class tui_interp final : public cli_interp_base
43 {
44 public:
45 explicit tui_interp (const char *name)
46 : cli_interp_base (name)
47 {}
48
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;
54 };
55
56 /* Returns the INTERP if the INTERP is a TUI, and returns NULL
57 otherwise. */
58
59 static tui_interp *
60 as_tui_interp (struct interp *interp)
61 {
62 return dynamic_cast<tui_interp *> (interp);
63 }
64
65 /* Cleanup the tui before exiting. */
66
67 static void
68 tui_exit (void)
69 {
70 /* Disable the tui. Curses mode is left leaving the screen in a
71 clean state (see endwin()). */
72 tui_disable ();
73 }
74
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. */
78
79 /* Observer for the normal_stop notification. */
80
81 static void
82 tui_on_normal_stop (struct bpstats *bs, int print_frame)
83 {
84 if (!print_frame)
85 return;
86
87 SWITCH_THRU_ALL_UIS ()
88 {
89 struct interp *interp = top_level_interpreter ();
90 struct interp *tui = as_tui_interp (interp);
91 struct thread_info *thread;
92
93 if (tui == NULL)
94 continue;
95
96 thread = inferior_thread ();
97 if (should_print_stop_to_console (interp, thread))
98 print_stop_event (tui->interp_ui_out ());
99 }
100 }
101
102 /* Observer for the signal_received notification. */
103
104 static void
105 tui_on_signal_received (enum gdb_signal siggnal)
106 {
107 SWITCH_THRU_ALL_UIS ()
108 {
109 struct interp *tui = as_tui_interp (top_level_interpreter ());
110
111 if (tui == NULL)
112 continue;
113
114 print_signal_received_reason (tui->interp_ui_out (), siggnal);
115 }
116 }
117
118 /* Observer for the end_stepping_range notification. */
119
120 static void
121 tui_on_end_stepping_range (void)
122 {
123 SWITCH_THRU_ALL_UIS ()
124 {
125 struct interp *tui = as_tui_interp (top_level_interpreter ());
126
127 if (tui == NULL)
128 continue;
129
130 print_end_stepping_range_reason (tui->interp_ui_out ());
131 }
132 }
133
134 /* Observer for the signal_exited notification. */
135
136 static void
137 tui_on_signal_exited (enum gdb_signal siggnal)
138 {
139 SWITCH_THRU_ALL_UIS ()
140 {
141 struct interp *tui = as_tui_interp (top_level_interpreter ());
142
143 if (tui == NULL)
144 continue;
145
146 print_signal_exited_reason (tui->interp_ui_out (), siggnal);
147 }
148 }
149
150 /* Observer for the exited notification. */
151
152 static void
153 tui_on_exited (int exitstatus)
154 {
155 SWITCH_THRU_ALL_UIS ()
156 {
157 struct interp *tui = as_tui_interp (top_level_interpreter ());
158
159 if (tui == NULL)
160 continue;
161
162 print_exited_reason (tui->interp_ui_out (), exitstatus);
163 }
164 }
165
166 /* Observer for the no_history notification. */
167
168 static void
169 tui_on_no_history (void)
170 {
171 SWITCH_THRU_ALL_UIS ()
172 {
173 struct interp *tui = as_tui_interp (top_level_interpreter ());
174
175 if (tui == NULL)
176 continue;
177
178 print_no_history_reason (tui->interp_ui_out ());
179 }
180 }
181
182 /* Observer for the sync_execution_done notification. */
183
184 static void
185 tui_on_sync_execution_done (void)
186 {
187 struct interp *tui = as_tui_interp (top_level_interpreter ());
188
189 if (tui == NULL)
190 return;
191
192 display_gdb_prompt (NULL);
193 }
194
195 /* Observer for the command_error notification. */
196
197 static void
198 tui_on_command_error (void)
199 {
200 struct interp *tui = as_tui_interp (top_level_interpreter ());
201
202 if (tui == NULL)
203 return;
204
205 display_gdb_prompt (NULL);
206 }
207
208 /* Observer for the user_selected_context_changed notification. */
209
210 static void
211 tui_on_user_selected_context_changed (user_selected_what selection)
212 {
213 /* This event is suppressed. */
214 if (cli_suppress_notification.user_selected_context)
215 return;
216
217 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : NULL;
218
219 SWITCH_THRU_ALL_UIS ()
220 {
221 struct interp *tui = as_tui_interp (top_level_interpreter ());
222
223 if (tui == NULL)
224 continue;
225
226 if (selection & USER_SELECTED_INFERIOR)
227 print_selected_inferior (tui->interp_ui_out ());
228
229 if (tp != NULL
230 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
231 print_selected_thread_frame (tui->interp_ui_out (), selection);
232
233 }
234 }
235
236 /* These implement the TUI interpreter. */
237
238 void
239 tui_interp::init (bool top_level)
240 {
241 /* Install exit handler to leave the screen in a good shape. */
242 atexit (tui_exit);
243
244 tui_initialize_io ();
245 tui_initialize_win ();
246 if (gdb_stdout->isatty ())
247 tui_ensure_readline_initialized ();
248 }
249
250 /* Used as the command handler for the tui. */
251
252 static void
253 tui_command_line_handler (gdb::unique_xmalloc_ptr<char> &&rl)
254 {
255 /* When a tui enabled GDB is running in either tui mode or cli mode then
256 it is always the tui interpreter that is in use. As a result we end
257 up in here even in standard cli mode.
258
259 We only need to do any special actions when the tui is in use
260 though. When the tui is active the users return is not echoed to the
261 screen as a result the display will not automatically move us to the
262 next line. Here we manually insert a newline character and move the
263 cursor. */
264 if (tui_active)
265 tui_inject_newline_into_command_window ();
266
267 /* Now perform GDB's standard CLI command line handling. */
268 command_line_handler (std::move (rl));
269 }
270
271 void
272 tui_interp::resume ()
273 {
274 struct ui *ui = current_ui;
275 struct ui_file *stream;
276
277 /* gdb_setup_readline will change gdb_stdout. If the TUI was
278 previously writing to gdb_stdout, then set it to the new
279 gdb_stdout afterwards. */
280
281 stream = tui_old_uiout->set_stream (gdb_stdout);
282 if (stream != gdb_stdout)
283 {
284 tui_old_uiout->set_stream (stream);
285 stream = NULL;
286 }
287
288 gdb_setup_readline (1);
289
290 ui->input_handler = tui_command_line_handler;
291
292 if (stream != NULL)
293 tui_old_uiout->set_stream (gdb_stdout);
294
295 if (tui_start_enabled)
296 tui_enable ();
297 }
298
299 void
300 tui_interp::suspend ()
301 {
302 tui_start_enabled = tui_active;
303 tui_disable ();
304 }
305
306 ui_out *
307 tui_interp::interp_ui_out ()
308 {
309 if (tui_active)
310 return tui_out;
311 else
312 return tui_old_uiout;
313 }
314
315 gdb_exception
316 tui_interp::exec (const char *command_str)
317 {
318 internal_error (__FILE__, __LINE__, _("tui_exec called"));
319 }
320
321
322 /* Factory for TUI interpreters. */
323
324 static struct interp *
325 tui_interp_factory (const char *name)
326 {
327 return new tui_interp (name);
328 }
329
330 void _initialize_tui_interp ();
331 void
332 _initialize_tui_interp ()
333 {
334 interp_factory_register (INTERP_TUI, tui_interp_factory);
335
336 if (interpreter_p && strcmp (interpreter_p, INTERP_TUI) == 0)
337 tui_start_enabled = true;
338
339 if (interpreter_p && strcmp (interpreter_p, INTERP_CONSOLE) == 0)
340 {
341 xfree (interpreter_p);
342 interpreter_p = xstrdup (INTERP_TUI);
343 }
344
345 /* If changing this, remember to update cli-interp.c as well. */
346 gdb::observers::normal_stop.attach (tui_on_normal_stop, "tui-interp");
347 gdb::observers::signal_received.attach (tui_on_signal_received, "tui-interp");
348 gdb::observers::end_stepping_range.attach (tui_on_end_stepping_range,
349 "tui-interp");
350 gdb::observers::signal_exited.attach (tui_on_signal_exited, "tui-interp");
351 gdb::observers::exited.attach (tui_on_exited, "tui-interp");
352 gdb::observers::no_history.attach (tui_on_no_history, "tui-interp");
353 gdb::observers::sync_execution_done.attach (tui_on_sync_execution_done,
354 "tui-interp");
355 gdb::observers::command_error.attach (tui_on_command_error, "tui-interp");
356 gdb::observers::user_selected_context_changed.attach
357 (tui_on_user_selected_context_changed, "tui-interp");
358 }