Change inferior thread list to be a thread map
[deliverable/binutils-gdb.git] / gdb / tui / tui-interp.c
1 /* TUI Interpreter definitions for GDB, the GNU debugger.
2
3 Copyright (C) 2003-2019 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 "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 1 when the TUI mode must be activated when we first start
39 gdb. */
40 static int tui_start_enabled = 0;
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 (ui_file_isatty (gdb_stdout))
247 tui_initialize_readline ();
248 }
249
250 void
251 tui_interp::resume ()
252 {
253 struct ui *ui = current_ui;
254 struct ui_file *stream;
255
256 /* gdb_setup_readline will change gdb_stdout. If the TUI was
257 previously writing to gdb_stdout, then set it to the new
258 gdb_stdout afterwards. */
259
260 stream = tui_old_uiout->set_stream (gdb_stdout);
261 if (stream != gdb_stdout)
262 {
263 tui_old_uiout->set_stream (stream);
264 stream = NULL;
265 }
266
267 gdb_setup_readline (1);
268
269 ui->input_handler = command_line_handler;
270
271 if (stream != NULL)
272 tui_old_uiout->set_stream (gdb_stdout);
273
274 if (tui_start_enabled)
275 tui_enable ();
276 }
277
278 void
279 tui_interp::suspend ()
280 {
281 tui_start_enabled = tui_active;
282 tui_disable ();
283 }
284
285 ui_out *
286 tui_interp::interp_ui_out ()
287 {
288 if (tui_active)
289 return tui_out;
290 else
291 return tui_old_uiout;
292 }
293
294 gdb_exception
295 tui_interp::exec (const char *command_str)
296 {
297 internal_error (__FILE__, __LINE__, _("tui_exec called"));
298 }
299
300
301 /* Factory for TUI interpreters. */
302
303 static struct interp *
304 tui_interp_factory (const char *name)
305 {
306 return new tui_interp (name);
307 }
308
309 void
310 _initialize_tui_interp (void)
311 {
312 interp_factory_register (INTERP_TUI, tui_interp_factory);
313
314 if (interpreter_p && strcmp (interpreter_p, INTERP_TUI) == 0)
315 tui_start_enabled = 1;
316
317 if (interpreter_p && strcmp (interpreter_p, INTERP_CONSOLE) == 0)
318 {
319 xfree (interpreter_p);
320 interpreter_p = xstrdup (INTERP_TUI);
321 }
322
323 /* If changing this, remember to update cli-interp.c as well. */
324 gdb::observers::normal_stop.attach (tui_on_normal_stop);
325 gdb::observers::signal_received.attach (tui_on_signal_received);
326 gdb::observers::end_stepping_range.attach (tui_on_end_stepping_range);
327 gdb::observers::signal_exited.attach (tui_on_signal_exited);
328 gdb::observers::exited.attach (tui_on_exited);
329 gdb::observers::no_history.attach (tui_on_no_history);
330 gdb::observers::sync_execution_done.attach (tui_on_sync_execution_done);
331 gdb::observers::command_error.attach (tui_on_command_error);
332 gdb::observers::user_selected_context_changed.attach
333 (tui_on_user_selected_context_changed);
334 }
This page took 0.036816 seconds and 4 git commands to generate.