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