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