1 /* CLI Definitions for GDB, the GNU debugger.
3 Copyright (C) 2002-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "cli-interp.h"
21 #include "exceptions.h"
23 #include "event-top.h"
29 #include "observable.h"
30 #include "gdbthread.h"
31 #include "thread-fsm.h"
34 cli_interp_base::cli_interp_base (const char *name
)
38 cli_interp_base::~cli_interp_base ()
41 /* The console interpreter. */
43 class cli_interp final
: public cli_interp_base
46 explicit cli_interp (const char *name
);
47 ~cli_interp () = default;
49 void init (bool top_level
) override
;
50 void resume () override
;
51 void suspend () override
;
52 void exec (const char *command_str
) override
;
53 ui_out
*interp_ui_out () override
;
57 /* The ui_out for the console interpreter. */
58 std::unique_ptr
<cli_ui_out
> m_cli_uiout
;
61 cli_interp::cli_interp (const char *name
)
62 : cli_interp_base (name
),
63 m_cli_uiout (new cli_ui_out (gdb_stdout
))
67 /* Suppress notification struct. */
68 struct cli_suppress_notification cli_suppress_notification
;
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
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. */
89 should_print_stop_to_console (struct interp
*console_interp
,
90 struct thread_info
*tp
)
92 if ((bpstat_what (tp
->control
.stop_bpstat
).main_action
93 == BPSTAT_WHAT_STOP_NOISY
)
94 || tp
->thread_fsm () == nullptr
95 || tp
->thread_fsm ()->command_interp
== console_interp
96 || !tp
->thread_fsm ()->finished_p ())
101 /* Observers for several run control events. If the interpreter is
102 quiet (i.e., another interpreter is being run with
103 interpreter-exec), print nothing. These are named "cli_base" as
104 they print to both CLI interpreters and TUI interpreters. */
107 cli_interp_base::on_normal_stop (struct bpstat
*bs
, int print_frame
)
112 /* This event is suppressed. */
113 if (cli_suppress_notification
.normal_stop
)
116 thread_info
*thread
= inferior_thread ();
117 if (should_print_stop_to_console (this, thread
))
118 print_stop_event (this->interp_ui_out ());
123 cli_interp_base::on_signal_received (enum gdb_signal siggnal
)
125 print_signal_received_reason (this->interp_ui_out (), siggnal
);
129 cli_interp_base::on_signal_exited (gdb_signal sig
)
131 print_signal_exited_reason (this->interp_ui_out (), sig
);
135 cli_interp_base::on_exited (int status
)
137 print_exited_reason (this->interp_ui_out (), status
);
141 cli_interp_base::on_no_history ()
143 print_no_history_reason (this->interp_ui_out ());
147 cli_interp_base::on_sync_execution_done ()
149 display_gdb_prompt (NULL
);
153 cli_interp_base::on_command_error ()
155 display_gdb_prompt (NULL
);
159 cli_interp_base::on_user_selected_context_changed (user_selected_what selection
)
161 /* This event is suppressed. */
162 if (cli_suppress_notification
.user_selected_context
)
165 thread_info
*tp
= inferior_ptid
!= null_ptid
? inferior_thread () : nullptr;
167 if (selection
& USER_SELECTED_INFERIOR
)
168 print_selected_inferior (this->interp_ui_out ());
171 && ((selection
& (USER_SELECTED_THREAD
| USER_SELECTED_FRAME
))))
172 print_selected_thread_frame (this->interp_ui_out (), selection
);
175 /* pre_command_loop implementation. */
178 cli_interp_base::pre_command_loop ()
180 display_gdb_prompt (0);
183 /* These implement the cli out interpreter: */
186 cli_interp::init (bool top_level
)
191 cli_interp::resume ()
193 struct ui
*ui
= current_ui
;
194 struct ui_file
*stream
;
196 /*sync_execution = 1; */
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. */
202 stream
= m_cli_uiout
->set_stream (gdb_stdout
);
203 if (stream
!= gdb_stdout
)
205 m_cli_uiout
->set_stream (stream
);
209 gdb_setup_readline (1);
211 ui
->input_handler
= command_line_handler
;
214 m_cli_uiout
->set_stream (gdb_stdout
);
218 cli_interp::suspend ()
220 gdb_disable_readline ();
224 cli_interp::exec (const char *command_str
)
226 /* gdb_stdout could change between the time m_cli_uiout was
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.
231 It is important that it gets reset every time, since the user
232 could set gdb to use a different interpreter. */
233 ui_file
*old_stream
= m_cli_uiout
->set_stream (gdb_stdout
);
234 SCOPE_EXIT
{ m_cli_uiout
->set_stream (old_stream
); };
236 /* Save and override the global ``struct ui_out'' builder. */
237 scoped_restore saved_uiout
= make_scoped_restore (¤t_uiout
,
242 execute_command (command_str
, 1);
244 catch (const gdb_exception_error
&ex
)
246 exception_print (gdb_stderr
, ex
);
252 cli_interp_base::supports_command_editing ()
258 cli_interp::interp_ui_out ()
260 return m_cli_uiout
.get ();
263 /* See cli-interp.h. */
266 cli_interp_base::set_logging (ui_file_up logfile
, bool logging_redirect
,
269 if (logfile
!= nullptr)
271 gdb_assert (m_saved_output
== nullptr);
272 m_saved_output
= std::make_unique
<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
;
278 ui_file
*logfile_p
= logfile
.get ();
279 m_saved_output
->logfile_holder
= std::move (logfile
);
281 /* The new stdout and stderr only depend on whether logging
282 redirection is being done. */
283 ui_file
*new_stdout
= logfile_p
;
284 ui_file
*new_stderr
= logfile_p
;
285 if (!logging_redirect
)
287 m_saved_output
->stdout_holder
.reset
288 (new tee_file (gdb_stdout
, logfile_p
));
289 new_stdout
= m_saved_output
->stdout_holder
.get ();
290 m_saved_output
->stderr_holder
.reset
291 (new tee_file (gdb_stderr
, logfile_p
));
292 new_stderr
= m_saved_output
->stderr_holder
.get ();
295 m_saved_output
->stdlog_holder
.reset
296 (new timestamped_file (debug_redirect
? logfile_p
: new_stderr
));
298 gdb_stdout
= new_stdout
;
299 gdb_stdlog
= m_saved_output
->stdlog_holder
.get ();
300 gdb_stderr
= new_stderr
;
301 gdb_stdtarg
= new_stderr
;
305 gdb_stdout
= m_saved_output
->out
;
306 gdb_stderr
= m_saved_output
->err
;
307 gdb_stdlog
= m_saved_output
->log
;
308 gdb_stdtarg
= m_saved_output
->targ
;
310 m_saved_output
.reset (nullptr);
314 /* Factory for CLI interpreters. */
316 static struct interp
*
317 cli_interp_factory (const char *name
)
319 return new cli_interp (name
);
322 /* Standard gdb initialization hook. */
324 void _initialize_cli_interp ();
326 _initialize_cli_interp ()
328 interp_factory_register (INTERP_CONSOLE
, cli_interp_factory
);