Replace interp_set_temp with scoped_restore_interp
[deliverable/binutils-gdb.git] / gdb / cli / cli-interp.c
CommitLineData
4a8f6654
AC
1/* CLI Definitions for GDB, the GNU debugger.
2
61baf725 3 Copyright (C) 2002-2017 Free Software Foundation, Inc.
4a8f6654
AC
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
4a8f6654
AC
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
4a8f6654
AC
19
20#include "defs.h"
3c216924 21#include "cli-interp.h"
4a8f6654 22#include "interps.h"
4a8f6654
AC
23#include "event-top.h"
24#include "ui-out.h"
25#include "cli-out.h"
26#include "top.h" /* for "execute_command" */
3c216924 27#include "event-top.h"
fd664c91
PA
28#include "infrun.h"
29#include "observer.h"
26cde2cc
PA
30#include "gdbthread.h"
31#include "thread-fsm.h"
4a8f6654 32
d6f9b0fb
PA
33cli_interp_base::cli_interp_base (const char *name)
34 : interp (name)
35{}
36
37cli_interp_base::~cli_interp_base ()
38{}
39
8322445e 40/* The console interpreter. */
d6f9b0fb
PA
41
42class cli_interp final : public cli_interp_base
8322445e 43{
d6f9b0fb
PA
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
8322445e 53 /* The ui_out for the console interpreter. */
112e8700 54 cli_ui_out *cli_uiout;
8322445e
PA
55};
56
d6f9b0fb
PA
57cli_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
4034d0ff
AT
64/* Suppress notification struct. */
65struct cli_suppress_notification cli_suppress_notification =
66 {
67 0 /* user_selected_context_changed */
68 };
69
73ab01a0
PA
70/* Returns the INTERP's data cast as cli_interp if INTERP is a CLI,
71 and returns NULL otherwise. */
72
73static struct cli_interp *
74as_cli_interp (struct interp *interp)
75{
76 if (strcmp (interp_name (interp), INTERP_CONSOLE) == 0)
d6f9b0fb 77 return (struct cli_interp *) interp;
73ab01a0
PA
78 return NULL;
79}
4a8f6654 80
4791eb66 81/* Longjmp-safe wrapper for "execute_command". */
71fff37b 82static struct gdb_exception safe_execute_command (struct ui_out *uiout,
ebcd3b23
MS
83 char *command,
84 int from_tty);
fd664c91 85
26cde2cc
PA
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
104int
105should_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)
8980e177
PA
110 || tp->thread_fsm == NULL
111 || tp->thread_fsm->command_interp == console_interp
112 || !thread_fsm_finished_p (tp->thread_fsm))
26cde2cc
PA
113 return 1;
114 return 0;
115}
116
fd664c91
PA
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
243a9253
PA
121/* Observer for the normal_stop notification. */
122
123static void
124cli_on_normal_stop (struct bpstats *bs, int print_frame)
125{
eaae60fd
PA
126 if (!print_frame)
127 return;
128
0e454242 129 SWITCH_THRU_ALL_UIS ()
243a9253 130 {
eaae60fd
PA
131 struct interp *interp = top_level_interpreter ();
132 struct cli_interp *cli = as_cli_interp (interp);
133 struct thread_info *thread;
73ab01a0
PA
134
135 if (cli == NULL)
136 continue;
137
eaae60fd
PA
138 thread = inferior_thread ();
139 if (should_print_stop_to_console (interp, thread))
73ab01a0 140 print_stop_event (cli->cli_uiout);
243a9253
PA
141 }
142}
143
fd664c91
PA
144/* Observer for the signal_received notification. */
145
146static void
147cli_on_signal_received (enum gdb_signal siggnal)
148{
0e454242 149 SWITCH_THRU_ALL_UIS ()
73ab01a0
PA
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 }
fd664c91
PA
158}
159
160/* Observer for the end_stepping_range notification. */
161
162static void
163cli_on_end_stepping_range (void)
164{
0e454242 165 SWITCH_THRU_ALL_UIS ()
73ab01a0
PA
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 }
fd664c91
PA
174}
175
176/* Observer for the signalled notification. */
177
178static void
179cli_on_signal_exited (enum gdb_signal siggnal)
180{
0e454242 181 SWITCH_THRU_ALL_UIS ()
73ab01a0
PA
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 }
fd664c91
PA
190}
191
192/* Observer for the exited notification. */
193
194static void
195cli_on_exited (int exitstatus)
196{
0e454242 197 SWITCH_THRU_ALL_UIS ()
73ab01a0
PA
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 }
fd664c91
PA
206}
207
208/* Observer for the no_history notification. */
209
210static void
211cli_on_no_history (void)
212{
0e454242 213 SWITCH_THRU_ALL_UIS ()
73ab01a0
PA
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 }
fd664c91
PA
222}
223
92bcb5f9
PA
224/* Observer for the sync_execution_done notification. */
225
226static void
227cli_on_sync_execution_done (void)
228{
73ab01a0
PA
229 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
230
231 if (cli == NULL)
232 return;
233
234 display_gdb_prompt (NULL);
92bcb5f9
PA
235}
236
237/* Observer for the command_error notification. */
238
239static void
240cli_on_command_error (void)
241{
73ab01a0
PA
242 struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
243
244 if (cli == NULL)
245 return;
246
247 display_gdb_prompt (NULL);
92bcb5f9
PA
248}
249
4034d0ff
AT
250/* Observer for the user_selected_context_changed notification. */
251
252static void
253cli_on_user_selected_context_changed (user_selected_what selection)
254{
4034d0ff
AT
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
0e454242 263 SWITCH_THRU_ALL_UIS ()
4034d0ff
AT
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
b2d86570
PA
279/* pre_command_loop implementation. */
280
281void
d6f9b0fb 282cli_interp_base::pre_command_loop ()
b2d86570
PA
283{
284 display_gdb_prompt (0);
285}
286
4a8f6654
AC
287/* These implement the cli out interpreter: */
288
d6f9b0fb
PA
289void
290cli_interp::init (bool top_level)
4a8f6654 291{
4a8f6654
AC
292}
293
d6f9b0fb
PA
294void
295cli_interp::resume ()
4a8f6654 296{
3c216924 297 struct ui *ui = current_ui;
d6f9b0fb 298 struct cli_interp *cli = this;
38caaeec
DJ
299 struct ui_file *stream;
300
4a8f6654 301 /*sync_execution = 1; */
38caaeec 302
ebcd3b23
MS
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. */
38caaeec 306
112e8700 307 stream = cli->cli_uiout->set_stream (gdb_stdout);
38caaeec
DJ
308 if (stream != gdb_stdout)
309 {
112e8700 310 cli->cli_uiout->set_stream (stream);
38caaeec
DJ
311 stream = NULL;
312 }
313
3c216924
PA
314 gdb_setup_readline (1);
315
316 ui->input_handler = command_line_handler;
38caaeec
DJ
317
318 if (stream != NULL)
112e8700 319 cli->cli_uiout->set_stream (gdb_stdout);
4a8f6654
AC
320}
321
d6f9b0fb
PA
322void
323cli_interp::suspend ()
4a8f6654
AC
324{
325 gdb_disable_readline ();
4a8f6654
AC
326}
327
d6f9b0fb
PA
328gdb_exception
329cli_interp::exec (const char *command_str)
4a8f6654 330{
d6f9b0fb 331 struct cli_interp *cli = this;
4a8f6654 332 struct ui_file *old_stream;
71fff37b 333 struct gdb_exception result;
4a8f6654
AC
334
335 /* FIXME: cagney/2003-02-01: Need to const char *propogate
336 safe_execute_command. */
224c3ddb
SM
337 char *str = (char *) alloca (strlen (command_str) + 1);
338 strcpy (str, command_str);
4a8f6654 339
ebcd3b23
MS
340 /* gdb_stdout could change between the time cli_uiout was
341 initialized and now. Since we're probably using a different
342 interpreter which has a new ui_file for gdb_stdout, use that one
343 instead of the default.
4a8f6654 344
ebcd3b23
MS
345 It is important that it gets reset everytime, since the user
346 could set gdb to use a different interpreter. */
112e8700 347 old_stream = cli->cli_uiout->set_stream (gdb_stdout);
8322445e 348 result = safe_execute_command (cli->cli_uiout, str, 1);
112e8700 349 cli->cli_uiout->set_stream (old_stream);
4a8f6654
AC
350 return result;
351}
352
d6f9b0fb
PA
353bool
354cli_interp_base::supports_command_editing ()
3c216924 355{
d6f9b0fb 356 return true;
3c216924
PA
357}
358
71fff37b 359static struct gdb_exception
f9679975 360safe_execute_command (struct ui_out *command_uiout, char *command, int from_tty)
4a8f6654 361{
7556d4a4 362 struct gdb_exception e = exception_none;
f9679975
PA
363 struct ui_out *saved_uiout;
364
365 /* Save and override the global ``struct ui_out'' builder. */
79a45e25
PA
366 saved_uiout = current_uiout;
367 current_uiout = command_uiout;
cdb27c12 368
492d29ea 369 TRY
04bd08de
TT
370 {
371 execute_command (command, from_tty);
372 }
492d29ea 373 CATCH (exception, RETURN_MASK_ALL)
7556d4a4
PA
374 {
375 e = exception;
376 }
492d29ea 377 END_CATCH
f9679975
PA
378
379 /* Restore the global builder. */
79a45e25 380 current_uiout = saved_uiout;
f9679975 381
8a076db9
AC
382 /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the
383 caller should print the exception. */
9cbc821d 384 exception_print (gdb_stderr, e);
8a076db9 385 return e;
4a8f6654
AC
386}
387
d6f9b0fb
PA
388ui_out *
389cli_interp::interp_ui_out ()
4801a9a3 390{
d6f9b0fb 391 struct cli_interp *cli = (struct cli_interp *) this;
8322445e
PA
392
393 return cli->cli_uiout;
394}
395
616268b6
PA
396/* These hold the pushed copies of the gdb output files.
397 If NULL then nothing has yet been pushed. */
398struct saved_output_files
399{
400 ui_file *out;
401 ui_file *err;
402 ui_file *log;
403 ui_file *targ;
404 ui_file *targerr;
405};
406static saved_output_files saved_output;
407
408/* See cli-interp.h. */
409
410void
d6f9b0fb 411cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect)
616268b6
PA
412{
413 if (logfile != NULL)
414 {
415 saved_output.out = gdb_stdout;
416 saved_output.err = gdb_stderr;
417 saved_output.log = gdb_stdlog;
418 saved_output.targ = gdb_stdtarg;
419 saved_output.targerr = gdb_stdtargerr;
420
421 /* A raw pointer since ownership is transferred to
422 gdb_stdout. */
423 ui_file *output = make_logging_output (gdb_stdout,
424 std::move (logfile),
425 logging_redirect);
426 gdb_stdout = output;
427 gdb_stdlog = output;
428 gdb_stderr = output;
429 gdb_stdtarg = output;
430 gdb_stdtargerr = output;
431 }
432 else
433 {
434 /* Only delete one of the files -- they are all set to the same
435 value. */
436 delete gdb_stdout;
437
438 gdb_stdout = saved_output.out;
439 gdb_stderr = saved_output.err;
440 gdb_stdlog = saved_output.log;
441 gdb_stdtarg = saved_output.targ;
442 gdb_stdtargerr = saved_output.targerr;
443
444 saved_output.out = NULL;
445 saved_output.err = NULL;
446 saved_output.log = NULL;
447 saved_output.targ = NULL;
448 saved_output.targerr = NULL;
449 }
450}
451
8322445e
PA
452/* Factory for CLI interpreters. */
453
454static struct interp *
455cli_interp_factory (const char *name)
456{
d6f9b0fb 457 return new cli_interp (name);
4801a9a3 458}
4a8f6654 459
4791eb66 460/* Standard gdb initialization hook. */
b9362cc7 461
4a8f6654
AC
462void
463_initialize_cli_interp (void)
464{
8322445e 465 interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
73ab01a0
PA
466
467 /* If changing this, remember to update tui-interp.c as well. */
468 observer_attach_normal_stop (cli_on_normal_stop);
469 observer_attach_end_stepping_range (cli_on_end_stepping_range);
470 observer_attach_signal_received (cli_on_signal_received);
471 observer_attach_signal_exited (cli_on_signal_exited);
472 observer_attach_exited (cli_on_exited);
473 observer_attach_no_history (cli_on_no_history);
474 observer_attach_sync_execution_done (cli_on_sync_execution_done);
475 observer_attach_command_error (cli_on_command_error);
4034d0ff
AT
476 observer_attach_user_selected_context_changed
477 (cli_on_user_selected_context_changed);
4a8f6654 478}
This page took 0.927386 seconds and 4 git commands to generate.