ODR warnings for "struct coff_symbol"
[binutils-gdb.git] / gdb / tui / tui-interp.c
1 /* TUI Interpreter definitions for GDB, the GNU debugger.
2
3 Copyright (C) 2003-2022 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 bpstat *bs, int print_frame)
83 {
84 if (!print_frame)
85 return;
86
87 /* This event is suppressed. */
88 if (cli_suppress_notification.normal_stop)
89 return;
90
91 SWITCH_THRU_ALL_UIS ()
92 {
93 struct interp *interp = top_level_interpreter ();
94 struct interp *tui = as_tui_interp (interp);
95 struct thread_info *thread;
96
97 if (tui == NULL)
98 continue;
99
100 thread = inferior_thread ();
101 if (should_print_stop_to_console (interp, thread))
102 print_stop_event (tui->interp_ui_out ());
103 }
104 }
105
106 /* Observer for the signal_received notification. */
107
108 static void
109 tui_on_signal_received (enum gdb_signal siggnal)
110 {
111 SWITCH_THRU_ALL_UIS ()
112 {
113 struct interp *tui = as_tui_interp (top_level_interpreter ());
114
115 if (tui == NULL)
116 continue;
117
118 print_signal_received_reason (tui->interp_ui_out (), siggnal);
119 }
120 }
121
122 /* Observer for the end_stepping_range notification. */
123
124 static void
125 tui_on_end_stepping_range (void)
126 {
127 SWITCH_THRU_ALL_UIS ()
128 {
129 struct interp *tui = as_tui_interp (top_level_interpreter ());
130
131 if (tui == NULL)
132 continue;
133
134 print_end_stepping_range_reason (tui->interp_ui_out ());
135 }
136 }
137
138 /* Observer for the signal_exited notification. */
139
140 static void
141 tui_on_signal_exited (enum gdb_signal siggnal)
142 {
143 SWITCH_THRU_ALL_UIS ()
144 {
145 struct interp *tui = as_tui_interp (top_level_interpreter ());
146
147 if (tui == NULL)
148 continue;
149
150 print_signal_exited_reason (tui->interp_ui_out (), siggnal);
151 }
152 }
153
154 /* Observer for the exited notification. */
155
156 static void
157 tui_on_exited (int exitstatus)
158 {
159 SWITCH_THRU_ALL_UIS ()
160 {
161 struct interp *tui = as_tui_interp (top_level_interpreter ());
162
163 if (tui == NULL)
164 continue;
165
166 print_exited_reason (tui->interp_ui_out (), exitstatus);
167 }
168 }
169
170 /* Observer for the no_history notification. */
171
172 static void
173 tui_on_no_history (void)
174 {
175 SWITCH_THRU_ALL_UIS ()
176 {
177 struct interp *tui = as_tui_interp (top_level_interpreter ());
178
179 if (tui == NULL)
180 continue;
181
182 print_no_history_reason (tui->interp_ui_out ());
183 }
184 }
185
186 /* Observer for the sync_execution_done notification. */
187
188 static void
189 tui_on_sync_execution_done (void)
190 {
191 struct interp *tui = as_tui_interp (top_level_interpreter ());
192
193 if (tui == NULL)
194 return;
195
196 display_gdb_prompt (NULL);
197 }
198
199 /* Observer for the command_error notification. */
200
201 static void
202 tui_on_command_error (void)
203 {
204 struct interp *tui = as_tui_interp (top_level_interpreter ());
205
206 if (tui == NULL)
207 return;
208
209 display_gdb_prompt (NULL);
210 }
211
212 /* Observer for the user_selected_context_changed notification. */
213
214 static void
215 tui_on_user_selected_context_changed (user_selected_what selection)
216 {
217 /* This event is suppressed. */
218 if (cli_suppress_notification.user_selected_context)
219 return;
220
221 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : NULL;
222
223 SWITCH_THRU_ALL_UIS ()
224 {
225 struct interp *tui = as_tui_interp (top_level_interpreter ());
226
227 if (tui == NULL)
228 continue;
229
230 if (selection & USER_SELECTED_INFERIOR)
231 print_selected_inferior (tui->interp_ui_out ());
232
233 if (tp != NULL
234 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
235 print_selected_thread_frame (tui->interp_ui_out (), selection);
236
237 }
238 }
239
240 /* These implement the TUI interpreter. */
241
242 void
243 tui_interp::init (bool top_level)
244 {
245 /* Install exit handler to leave the screen in a good shape. */
246 atexit (tui_exit);
247
248 tui_initialize_io ();
249 if (gdb_stdout->isatty ())
250 {
251 tui_ensure_readline_initialized ();
252
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 ();
257 }
258 }
259
260 /* Used as the command handler for the tui. */
261
262 static void
263 tui_command_line_handler (gdb::unique_xmalloc_ptr<char> &&rl)
264 {
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.
268
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
273 cursor. */
274 if (tui_active)
275 tui_inject_newline_into_command_window ();
276
277 /* Now perform GDB's standard CLI command line handling. */
278 command_line_handler (std::move (rl));
279 }
280
281 void
282 tui_interp::resume ()
283 {
284 struct ui *ui = current_ui;
285 struct ui_file *stream;
286
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. */
290
291 stream = tui_old_uiout->set_stream (gdb_stdout);
292 if (stream != gdb_stdout)
293 {
294 tui_old_uiout->set_stream (stream);
295 stream = NULL;
296 }
297
298 gdb_setup_readline (1);
299
300 ui->input_handler = tui_command_line_handler;
301
302 if (stream != NULL)
303 tui_old_uiout->set_stream (gdb_stdout);
304
305 if (tui_start_enabled)
306 tui_enable ();
307 }
308
309 void
310 tui_interp::suspend ()
311 {
312 tui_start_enabled = tui_active;
313 tui_disable ();
314 }
315
316 ui_out *
317 tui_interp::interp_ui_out ()
318 {
319 if (tui_active)
320 return tui_out;
321 else
322 return tui_old_uiout;
323 }
324
325 gdb_exception
326 tui_interp::exec (const char *command_str)
327 {
328 internal_error (__FILE__, __LINE__, _("tui_exec called"));
329 }
330
331
332 /* Factory for TUI interpreters. */
333
334 static struct interp *
335 tui_interp_factory (const char *name)
336 {
337 return new tui_interp (name);
338 }
339
340 void _initialize_tui_interp ();
341 void
342 _initialize_tui_interp ()
343 {
344 interp_factory_register (INTERP_TUI, tui_interp_factory);
345
346 if (interpreter_p && strcmp (interpreter_p, INTERP_TUI) == 0)
347 tui_start_enabled = true;
348
349 if (interpreter_p && strcmp (interpreter_p, INTERP_CONSOLE) == 0)
350 {
351 xfree (interpreter_p);
352 interpreter_p = xstrdup (INTERP_TUI);
353 }
354
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,
359 "tui-interp");
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,
364 "tui-interp");
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");
368 }