]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/cli/cli-interp.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / cli / cli-interp.c
CommitLineData
4a8f6654
AC
1/* CLI Definitions for GDB, the GNU debugger.
2
1d506c26 3 Copyright (C) 2002-2024 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"
ef0f16cc 26#include "top.h"
13d03262 27#include "ui.h"
fd664c91 28#include "infrun.h"
76727919 29#include "observable.h"
26cde2cc
PA
30#include "gdbthread.h"
31#include "thread-fsm.h"
00431a78 32#include "inferior.h"
4a8f6654 33
d6f9b0fb
PA
34cli_interp_base::cli_interp_base (const char *name)
35 : interp (name)
36{}
37
38cli_interp_base::~cli_interp_base ()
39{}
40
8322445e 41/* The console interpreter. */
d6f9b0fb
PA
42
43class cli_interp final : public cli_interp_base
8322445e 44{
d6f9b0fb
PA
45 public:
46 explicit cli_interp (const char *name);
083aca0c 47 ~cli_interp () = default;
d6f9b0fb
PA
48
49 void init (bool top_level) override;
50 void resume () override;
51 void suspend () override;
b885aea1 52 void exec (const char *command_str) override;
d6f9b0fb
PA
53 ui_out *interp_ui_out () override;
54
083aca0c
TT
55private:
56
8322445e 57 /* The ui_out for the console interpreter. */
083aca0c 58 std::unique_ptr<cli_ui_out> m_cli_uiout;
8322445e
PA
59};
60
d6f9b0fb 61cli_interp::cli_interp (const char *name)
083aca0c
TT
62 : cli_interp_base (name),
63 m_cli_uiout (new cli_ui_out (gdb_stdout))
d6f9b0fb 64{
ba543ca5
GB
65}
66
4034d0ff 67/* Suppress notification struct. */
f36c8918 68struct cli_suppress_notification cli_suppress_notification;
4034d0ff 69
26cde2cc
PA
70/* See cli-interp.h.
71
72 Breakpoint hits should always be mirrored to a console. Deciding
73 what to mirror to a console wrt to breakpoints and random stops
74 gets messy real fast. E.g., say "s" trips on a breakpoint. We'd
75 clearly want to mirror the event to the console in this case. But
76 what about more complicated cases like "s&; thread n; s&", and one
77 of those steps spawning a new thread, and that thread hitting a
78 breakpoint? It's impossible in general to track whether the thread
79 had any relation to the commands that had been executed. So we
80 just simplify and always mirror breakpoints and random events to
81 all consoles.
82
83 OTOH, we should print the source line to the console when stepping
84 or other similar commands, iff the step was started by that console
85 (or in MI's case, by a console command), but not if it was started
86 with MI's -exec-step or similar. */
87
88int
89should_print_stop_to_console (struct interp *console_interp,
90 struct thread_info *tp)
91{
92 if ((bpstat_what (tp->control.stop_bpstat).main_action
93 == BPSTAT_WHAT_STOP_NOISY)
573269a8
LS
94 || tp->thread_fsm () == nullptr
95 || tp->thread_fsm ()->command_interp == console_interp
96 || !tp->thread_fsm ()->finished_p ())
26cde2cc
PA
97 return 1;
98 return 0;
99}
100
fd664c91
PA
101/* Observers for several run control events. If the interpreter is
102 quiet (i.e., another interpreter is being run with
5227abd2
PA
103 interpreter-exec), print nothing. These are named "cli_base" as
104 they print to both CLI interpreters and TUI interpreters. */
fd664c91 105
87829267
SM
106void
107cli_interp_base::on_normal_stop (struct bpstat *bs, int print_frame)
243a9253 108{
eaae60fd
PA
109 if (!print_frame)
110 return;
111
2b826f75
TBA
112 /* This event is suppressed. */
113 if (cli_suppress_notification.normal_stop)
114 return;
115
87829267
SM
116 thread_info *thread = inferior_thread ();
117 if (should_print_stop_to_console (this, thread))
118 print_stop_event (this->interp_ui_out ());
73ab01a0 119
243a9253
PA
120}
121
3f75a984
SM
122void
123cli_interp_base::on_signal_received (enum gdb_signal siggnal)
fd664c91 124{
3f75a984 125 print_signal_received_reason (this->interp_ui_out (), siggnal);
fd664c91
PA
126}
127
d6bd2ef5
SM
128void
129cli_interp_base::on_signal_exited (gdb_signal sig)
fd664c91 130{
d6bd2ef5 131 print_signal_exited_reason (this->interp_ui_out (), sig);
fd664c91
PA
132}
133
bf64d1d5
SM
134void
135cli_interp_base::on_exited (int status)
fd664c91 136{
bf64d1d5 137 print_exited_reason (this->interp_ui_out (), status);
fd664c91
PA
138}
139
2e5dbfab
SM
140void
141cli_interp_base::on_no_history ()
fd664c91 142{
2e5dbfab 143 print_no_history_reason (this->interp_ui_out ());
fd664c91
PA
144}
145
c3d321de
SM
146void
147cli_interp_base::on_sync_execution_done ()
92bcb5f9 148{
73ab01a0 149 display_gdb_prompt (NULL);
92bcb5f9
PA
150}
151
2736b771
SM
152void
153cli_interp_base::on_command_error ()
92bcb5f9 154{
73ab01a0 155 display_gdb_prompt (NULL);
92bcb5f9
PA
156}
157
77cd03e2
SM
158void
159cli_interp_base::on_user_selected_context_changed (user_selected_what selection)
4034d0ff 160{
4034d0ff
AT
161 /* This event is suppressed. */
162 if (cli_suppress_notification.user_selected_context)
163 return;
164
5227abd2 165 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
4034d0ff 166
77cd03e2
SM
167 if (selection & USER_SELECTED_INFERIOR)
168 print_selected_inferior (this->interp_ui_out ());
4034d0ff 169
77cd03e2
SM
170 if (tp != nullptr
171 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
172 print_selected_thread_frame (this->interp_ui_out (), selection);
4034d0ff
AT
173}
174
b2d86570
PA
175/* pre_command_loop implementation. */
176
177void
d6f9b0fb 178cli_interp_base::pre_command_loop ()
b2d86570
PA
179{
180 display_gdb_prompt (0);
181}
182
4a8f6654
AC
183/* These implement the cli out interpreter: */
184
d6f9b0fb
PA
185void
186cli_interp::init (bool top_level)
4a8f6654 187{
4a8f6654
AC
188}
189
d6f9b0fb
PA
190void
191cli_interp::resume ()
4a8f6654 192{
3c216924 193 struct ui *ui = current_ui;
38caaeec
DJ
194 struct ui_file *stream;
195
4a8f6654 196 /*sync_execution = 1; */
38caaeec 197
ebcd3b23
MS
198 /* gdb_setup_readline will change gdb_stdout. If the CLI was
199 previously writing to gdb_stdout, then set it to the new
200 gdb_stdout afterwards. */
38caaeec 201
083aca0c 202 stream = m_cli_uiout->set_stream (gdb_stdout);
38caaeec
DJ
203 if (stream != gdb_stdout)
204 {
083aca0c 205 m_cli_uiout->set_stream (stream);
38caaeec
DJ
206 stream = NULL;
207 }
208
3c216924
PA
209 gdb_setup_readline (1);
210
211 ui->input_handler = command_line_handler;
38caaeec
DJ
212
213 if (stream != NULL)
083aca0c 214 m_cli_uiout->set_stream (gdb_stdout);
4a8f6654
AC
215}
216
d6f9b0fb
PA
217void
218cli_interp::suspend ()
4a8f6654
AC
219{
220 gdb_disable_readline ();
4a8f6654
AC
221}
222
b885aea1 223void
d6f9b0fb 224cli_interp::exec (const char *command_str)
4a8f6654 225{
083aca0c 226 /* gdb_stdout could change between the time m_cli_uiout was
ebcd3b23
MS
227 initialized and now. Since we're probably using a different
228 interpreter which has a new ui_file for gdb_stdout, use that one
229 instead of the default.
4a8f6654 230
ebcd3b23
MS
231 It is important that it gets reset everytime, since the user
232 could set gdb to use a different interpreter. */
b885aea1
PA
233 ui_file *old_stream = m_cli_uiout->set_stream (gdb_stdout);
234 SCOPE_EXIT { m_cli_uiout->set_stream (old_stream); };
f9679975
PA
235
236 /* Save and override the global ``struct ui_out'' builder. */
753ff9bd 237 scoped_restore saved_uiout = make_scoped_restore (&current_uiout,
b885aea1 238 m_cli_uiout.get ());
cdb27c12 239
a70b8144 240 try
04bd08de 241 {
b885aea1 242 execute_command (command_str, 1);
04bd08de 243 }
b885aea1 244 catch (const gdb_exception_error &ex)
7556d4a4 245 {
b885aea1
PA
246 exception_print (gdb_stderr, ex);
247 throw;
7556d4a4 248 }
b885aea1 249}
f9679975 250
b885aea1
PA
251bool
252cli_interp_base::supports_command_editing ()
253{
254 return true;
4a8f6654
AC
255}
256
d6f9b0fb
PA
257ui_out *
258cli_interp::interp_ui_out ()
4801a9a3 259{
083aca0c 260 return m_cli_uiout.get ();
8322445e
PA
261}
262
616268b6
PA
263/* See cli-interp.h. */
264
265void
ca1285d1
AH
266cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect,
267 bool debug_redirect)
616268b6 268{
f3a09c80 269 if (logfile != nullptr)
616268b6 270 {
19622df1
TT
271 gdb_assert (m_saved_output == nullptr);
272 m_saved_output.reset (new saved_output_files);
273 m_saved_output->out = gdb_stdout;
274 m_saved_output->err = gdb_stderr;
275 m_saved_output->log = gdb_stdlog;
276 m_saved_output->targ = gdb_stdtarg;
277 m_saved_output->targerr = gdb_stdtargerr;
f3a09c80 278
2b141965 279 ui_file *logfile_p = logfile.get ();
35254615 280 m_saved_output->logfile_holder = std::move (logfile);
2b141965 281
1dd88936
TT
282 /* The new stdout and stderr only depend on whether logging
283 redirection is being done. */
284 ui_file *new_stdout = logfile_p;
285 ui_file *new_stderr = logfile_p;
286 if (!logging_redirect)
ca1285d1 287 {
35254615 288 m_saved_output->stdout_holder.reset
2b141965 289 (new tee_file (gdb_stdout, logfile_p));
35254615
TT
290 new_stdout = m_saved_output->stdout_holder.get ();
291 m_saved_output->stderr_holder.reset
1dd88936 292 (new tee_file (gdb_stderr, logfile_p));
35254615 293 new_stderr = m_saved_output->stderr_holder.get ();
ca1285d1 294 }
59b59f08 295
35254615 296 m_saved_output->stdlog_holder.reset
1dd88936 297 (new timestamped_file (debug_redirect ? logfile_p : new_stderr));
52a4a588 298
1dd88936 299 gdb_stdout = new_stdout;
35254615 300 gdb_stdlog = m_saved_output->stdlog_holder.get ();
1dd88936
TT
301 gdb_stderr = new_stderr;
302 gdb_stdtarg = new_stderr;
303 gdb_stdtargerr = new_stderr;
616268b6
PA
304 }
305 else
306 {
19622df1
TT
307 gdb_stdout = m_saved_output->out;
308 gdb_stderr = m_saved_output->err;
309 gdb_stdlog = m_saved_output->log;
310 gdb_stdtarg = m_saved_output->targ;
311 gdb_stdtargerr = m_saved_output->targerr;
8b1931b3 312
19622df1 313 m_saved_output.reset (nullptr);
616268b6
PA
314 }
315}
316
8322445e
PA
317/* Factory for CLI interpreters. */
318
319static struct interp *
320cli_interp_factory (const char *name)
321{
d6f9b0fb 322 return new cli_interp (name);
4801a9a3 323}
4a8f6654 324
4791eb66 325/* Standard gdb initialization hook. */
b9362cc7 326
6c265988 327void _initialize_cli_interp ();
4a8f6654 328void
6c265988 329_initialize_cli_interp ()
4a8f6654 330{
8322445e 331 interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
4a8f6654 332}