Use thread_info and inferior pointers more throughout
[deliverable/binutils-gdb.git] / gdb / cli / cli-interp.c
1 /* CLI Definitions for GDB, the GNU debugger.
2
3 Copyright (C) 2002-2018 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-interp.h"
22 #include "interps.h"
23 #include "event-top.h"
24 #include "ui-out.h"
25 #include "cli-out.h"
26 #include "top.h" /* for "execute_command" */
27 #include "event-top.h"
28 #include "infrun.h"
29 #include "observable.h"
30 #include "gdbthread.h"
31 #include "thread-fsm.h"
32 #include "inferior.h"
33
34 cli_interp_base::cli_interp_base (const char *name)
35 : interp (name)
36 {}
37
38 cli_interp_base::~cli_interp_base ()
39 {}
40
41 /* The console interpreter. */
42
43 class cli_interp final : public cli_interp_base
44 {
45 public:
46 explicit cli_interp (const char *name);
47
48 void init (bool top_level) override;
49 void resume () override;
50 void suspend () override;
51 gdb_exception exec (const char *command_str) override;
52 ui_out *interp_ui_out () override;
53
54 /* The ui_out for the console interpreter. */
55 cli_ui_out *cli_uiout;
56 };
57
58 cli_interp::cli_interp (const char *name)
59 : cli_interp_base (name)
60 {
61 /* Create a default uiout builder for the CLI. */
62 this->cli_uiout = cli_out_new (gdb_stdout);
63 }
64
65 /* Suppress notification struct. */
66 struct cli_suppress_notification cli_suppress_notification =
67 {
68 0 /* user_selected_context_changed */
69 };
70
71 /* Returns the INTERP's data cast as cli_interp if INTERP is a CLI,
72 and returns NULL otherwise. */
73
74 static struct cli_interp *
75 as_cli_interp (struct interp *interp)
76 {
77 return dynamic_cast<cli_interp *> (interp);
78 }
79
80 /* Longjmp-safe wrapper for "execute_command". */
81 static struct gdb_exception safe_execute_command (struct ui_out *uiout,
82 const char *command,
83 int from_tty);
84
85 /* See cli-interp.h.
86
87 Breakpoint hits should always be mirrored to a console. Deciding
88 what to mirror to a console wrt to breakpoints and random stops
89 gets messy real fast. E.g., say "s" trips on a breakpoint. We'd
90 clearly want to mirror the event to the console in this case. But
91 what about more complicated cases like "s&; thread n; s&", and one
92 of those steps spawning a new thread, and that thread hitting a
93 breakpoint? It's impossible in general to track whether the thread
94 had any relation to the commands that had been executed. So we
95 just simplify and always mirror breakpoints and random events to
96 all consoles.
97
98 OTOH, we should print the source line to the console when stepping
99 or other similar commands, iff the step was started by that console
100 (or in MI's case, by a console command), but not if it was started
101 with MI's -exec-step or similar. */
102
103 int
104 should_print_stop_to_console (struct interp *console_interp,
105 struct thread_info *tp)
106 {
107 if ((bpstat_what (tp->control.stop_bpstat).main_action
108 == BPSTAT_WHAT_STOP_NOISY)
109 || tp->thread_fsm == NULL
110 || tp->thread_fsm->command_interp == console_interp
111 || !thread_fsm_finished_p (tp->thread_fsm))
112 return 1;
113 return 0;
114 }
115
116 /* Observers for several run control events. If the interpreter is
117 quiet (i.e., another interpreter is being run with
118 interpreter-exec), print nothing. */
119
120 /* Observer for the normal_stop notification. */
121
122 static void
123 cli_on_normal_stop (struct bpstats *bs, int print_frame)
124 {
125 if (!print_frame)
126 return;
127
128 SWITCH_THRU_ALL_UIS ()
129 {
130 struct interp *interp = top_level_interpreter ();
131 struct cli_interp *cli = as_cli_interp (interp);
132 struct thread_info *thread;
133
134 if (cli == NULL)
135 continue;
136
137 thread = inferior_thread ();
138 if (should_print_stop_to_console (interp, thread))
139 print_stop_event (cli->cli_uiout);
140 }
141 }
142
143 /* Observer for the signal_received notification. */
144
145 static void
146 cli_on_signal_received (enum gdb_signal siggnal)
147 {
148 SWITCH_THRU_ALL_UIS ()
149 {
150 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
151
152 if (cli == NULL)
153 continue;
154
155 print_signal_received_reason (cli->cli_uiout, siggnal);
156 }
157 }
158
159 /* Observer for the end_stepping_range notification. */
160
161 static void
162 cli_on_end_stepping_range (void)
163 {
164 SWITCH_THRU_ALL_UIS ()
165 {
166 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
167
168 if (cli == NULL)
169 continue;
170
171 print_end_stepping_range_reason (cli->cli_uiout);
172 }
173 }
174
175 /* Observer for the signalled notification. */
176
177 static void
178 cli_on_signal_exited (enum gdb_signal siggnal)
179 {
180 SWITCH_THRU_ALL_UIS ()
181 {
182 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
183
184 if (cli == NULL)
185 continue;
186
187 print_signal_exited_reason (cli->cli_uiout, siggnal);
188 }
189 }
190
191 /* Observer for the exited notification. */
192
193 static void
194 cli_on_exited (int exitstatus)
195 {
196 SWITCH_THRU_ALL_UIS ()
197 {
198 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
199
200 if (cli == NULL)
201 continue;
202
203 print_exited_reason (cli->cli_uiout, exitstatus);
204 }
205 }
206
207 /* Observer for the no_history notification. */
208
209 static void
210 cli_on_no_history (void)
211 {
212 SWITCH_THRU_ALL_UIS ()
213 {
214 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
215
216 if (cli == NULL)
217 continue;
218
219 print_no_history_reason (cli->cli_uiout);
220 }
221 }
222
223 /* Observer for the sync_execution_done notification. */
224
225 static void
226 cli_on_sync_execution_done (void)
227 {
228 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
229
230 if (cli == NULL)
231 return;
232
233 display_gdb_prompt (NULL);
234 }
235
236 /* Observer for the command_error notification. */
237
238 static void
239 cli_on_command_error (void)
240 {
241 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
242
243 if (cli == NULL)
244 return;
245
246 display_gdb_prompt (NULL);
247 }
248
249 /* Observer for the user_selected_context_changed notification. */
250
251 static void
252 cli_on_user_selected_context_changed (user_selected_what selection)
253 {
254 struct thread_info *tp;
255
256 /* This event is suppressed. */
257 if (cli_suppress_notification.user_selected_context)
258 return;
259
260 tp = find_thread_ptid (inferior_ptid);
261
262 SWITCH_THRU_ALL_UIS ()
263 {
264 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
265
266 if (cli == NULL)
267 continue;
268
269 if (selection & USER_SELECTED_INFERIOR)
270 print_selected_inferior (cli->cli_uiout);
271
272 if (tp != NULL
273 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
274 print_selected_thread_frame (cli->cli_uiout, selection);
275 }
276 }
277
278 /* pre_command_loop implementation. */
279
280 void
281 cli_interp_base::pre_command_loop ()
282 {
283 display_gdb_prompt (0);
284 }
285
286 /* These implement the cli out interpreter: */
287
288 void
289 cli_interp::init (bool top_level)
290 {
291 }
292
293 void
294 cli_interp::resume ()
295 {
296 struct ui *ui = current_ui;
297 struct cli_interp *cli = this;
298 struct ui_file *stream;
299
300 /*sync_execution = 1; */
301
302 /* gdb_setup_readline will change gdb_stdout. If the CLI was
303 previously writing to gdb_stdout, then set it to the new
304 gdb_stdout afterwards. */
305
306 stream = cli->cli_uiout->set_stream (gdb_stdout);
307 if (stream != gdb_stdout)
308 {
309 cli->cli_uiout->set_stream (stream);
310 stream = NULL;
311 }
312
313 gdb_setup_readline (1);
314
315 ui->input_handler = command_line_handler;
316
317 if (stream != NULL)
318 cli->cli_uiout->set_stream (gdb_stdout);
319 }
320
321 void
322 cli_interp::suspend ()
323 {
324 gdb_disable_readline ();
325 }
326
327 gdb_exception
328 cli_interp::exec (const char *command_str)
329 {
330 struct cli_interp *cli = this;
331 struct ui_file *old_stream;
332 struct gdb_exception result;
333
334 /* gdb_stdout could change between the time cli_uiout was
335 initialized and now. Since we're probably using a different
336 interpreter which has a new ui_file for gdb_stdout, use that one
337 instead of the default.
338
339 It is important that it gets reset everytime, since the user
340 could set gdb to use a different interpreter. */
341 old_stream = cli->cli_uiout->set_stream (gdb_stdout);
342 result = safe_execute_command (cli->cli_uiout, command_str, 1);
343 cli->cli_uiout->set_stream (old_stream);
344 return result;
345 }
346
347 bool
348 cli_interp_base::supports_command_editing ()
349 {
350 return true;
351 }
352
353 static struct gdb_exception
354 safe_execute_command (struct ui_out *command_uiout, const char *command,
355 int from_tty)
356 {
357 struct gdb_exception e = exception_none;
358
359 /* Save and override the global ``struct ui_out'' builder. */
360 scoped_restore saved_uiout = make_scoped_restore (&current_uiout,
361 command_uiout);
362
363 TRY
364 {
365 execute_command (command, from_tty);
366 }
367 CATCH (exception, RETURN_MASK_ALL)
368 {
369 e = exception;
370 }
371 END_CATCH
372
373 /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the
374 caller should print the exception. */
375 exception_print (gdb_stderr, e);
376 return e;
377 }
378
379 ui_out *
380 cli_interp::interp_ui_out ()
381 {
382 struct cli_interp *cli = (struct cli_interp *) this;
383
384 return cli->cli_uiout;
385 }
386
387 /* These hold the pushed copies of the gdb output files.
388 If NULL then nothing has yet been pushed. */
389 struct saved_output_files
390 {
391 ui_file *out;
392 ui_file *err;
393 ui_file *log;
394 ui_file *targ;
395 ui_file *targerr;
396 };
397 static saved_output_files saved_output;
398
399 /* See cli-interp.h. */
400
401 void
402 cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect)
403 {
404 if (logfile != NULL)
405 {
406 saved_output.out = gdb_stdout;
407 saved_output.err = gdb_stderr;
408 saved_output.log = gdb_stdlog;
409 saved_output.targ = gdb_stdtarg;
410 saved_output.targerr = gdb_stdtargerr;
411
412 /* A raw pointer since ownership is transferred to
413 gdb_stdout. */
414 ui_file *output = make_logging_output (gdb_stdout,
415 std::move (logfile),
416 logging_redirect);
417 gdb_stdout = output;
418 gdb_stdlog = output;
419 gdb_stderr = output;
420 gdb_stdtarg = output;
421 gdb_stdtargerr = output;
422 }
423 else
424 {
425 /* Only delete one of the files -- they are all set to the same
426 value. */
427 delete gdb_stdout;
428
429 gdb_stdout = saved_output.out;
430 gdb_stderr = saved_output.err;
431 gdb_stdlog = saved_output.log;
432 gdb_stdtarg = saved_output.targ;
433 gdb_stdtargerr = saved_output.targerr;
434
435 saved_output.out = NULL;
436 saved_output.err = NULL;
437 saved_output.log = NULL;
438 saved_output.targ = NULL;
439 saved_output.targerr = NULL;
440 }
441 }
442
443 /* Factory for CLI interpreters. */
444
445 static struct interp *
446 cli_interp_factory (const char *name)
447 {
448 return new cli_interp (name);
449 }
450
451 /* Standard gdb initialization hook. */
452
453 void
454 _initialize_cli_interp (void)
455 {
456 interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
457
458 /* If changing this, remember to update tui-interp.c as well. */
459 gdb::observers::normal_stop.attach (cli_on_normal_stop);
460 gdb::observers::end_stepping_range.attach (cli_on_end_stepping_range);
461 gdb::observers::signal_received.attach (cli_on_signal_received);
462 gdb::observers::signal_exited.attach (cli_on_signal_exited);
463 gdb::observers::exited.attach (cli_on_exited);
464 gdb::observers::no_history.attach (cli_on_no_history);
465 gdb::observers::sync_execution_done.attach (cli_on_sync_execution_done);
466 gdb::observers::command_error.attach (cli_on_command_error);
467 gdb::observers::user_selected_context_changed.attach
468 (cli_on_user_selected_context_changed);
469 }
This page took 0.038572 seconds and 4 git commands to generate.