1/* CLI Definitions for GDB, the GNU debugger.
2
3   Copyright (C) 2002-2020 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 "infrun.h"
28#include "observable.h"
29#include "gdbthread.h"
30#include "thread-fsm.h"
31#include "inferior.h"
32
33cli_interp_base::cli_interp_base (const char *name)
34  : interp (name)
35{}
36
37cli_interp_base::~cli_interp_base ()
38{}
39
40/* The console interpreter.  */
41
42class cli_interp final : public cli_interp_base
43{
44 public:
45  explicit cli_interp (const char *name);
46  ~cli_interp ();
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
54  /* The ui_out for the console interpreter.  */
55  cli_ui_out *cli_uiout;
56};
57
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
65cli_interp::~cli_interp ()
66{
67  delete cli_uiout;
68}
69
70/* Suppress notification struct.  */
71struct cli_suppress_notification cli_suppress_notification =
72  {
73    0   /* user_selected_context_changed */
74  };
75
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{
82  return dynamic_cast<cli_interp *> (interp);
83}
84
85/* Longjmp-safe wrapper for "execute_command".  */
86static struct gdb_exception safe_execute_command (struct ui_out *uiout,
87						  const char *command,
88						  int from_tty);
89
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)
114      || tp->thread_fsm == NULL
115      || tp->thread_fsm->command_interp == console_interp
116      || !tp->thread_fsm->finished_p ())
117    return 1;
118  return 0;
119}
120
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
125/* Observer for the normal_stop notification.  */
126
127static void
128cli_on_normal_stop (struct bpstats *bs, int print_frame)
129{
130  if (!print_frame)
131    return;
132
133  SWITCH_THRU_ALL_UIS ()
134    {
135      struct interp *interp = top_level_interpreter ();
136      struct cli_interp *cli = as_cli_interp (interp);
137      struct thread_info *thread;
138
139      if (cli == NULL)
140	continue;
141
142      thread = inferior_thread ();
143      if (should_print_stop_to_console (interp, thread))
144	print_stop_event (cli->cli_uiout);
145    }
146}
147
148/* Observer for the signal_received notification.  */
149
150static void
151cli_on_signal_received (enum gdb_signal siggnal)
152{
153  SWITCH_THRU_ALL_UIS ()
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    }
162}
163
164/* Observer for the end_stepping_range notification.  */
165
166static void
167cli_on_end_stepping_range (void)
168{
169  SWITCH_THRU_ALL_UIS ()
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    }
178}
179
180/* Observer for the signalled notification.  */
181
182static void
183cli_on_signal_exited (enum gdb_signal siggnal)
184{
185  SWITCH_THRU_ALL_UIS ()
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    }
194}
195
196/* Observer for the exited notification.  */
197
198static void
199cli_on_exited (int exitstatus)
200{
201  SWITCH_THRU_ALL_UIS ()
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    }
210}
211
212/* Observer for the no_history notification.  */
213
214static void
215cli_on_no_history (void)
216{
217  SWITCH_THRU_ALL_UIS ()
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    }
226}
227
228/* Observer for the sync_execution_done notification.  */
229
230static void
231cli_on_sync_execution_done (void)
232{
233  struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
234
235  if (cli == NULL)
236    return;
237
238  display_gdb_prompt (NULL);
239}
240
241/* Observer for the command_error notification.  */
242
243static void
244cli_on_command_error (void)
245{
246  struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
247
248  if (cli == NULL)
249    return;
250
251  display_gdb_prompt (NULL);
252}
253
254/* Observer for the user_selected_context_changed notification.  */
255
256static void
257cli_on_user_selected_context_changed (user_selected_what selection)
258{
259  /* This event is suppressed.  */
260  if (cli_suppress_notification.user_selected_context)
261    return;
262
263  thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : NULL;
264
265  SWITCH_THRU_ALL_UIS ()
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
281/* pre_command_loop implementation.  */
282
283void
284cli_interp_base::pre_command_loop ()
285{
286  display_gdb_prompt (0);
287}
288
289/* These implement the cli out interpreter: */
290
291void
292cli_interp::init (bool top_level)
293{
294}
295
296void
297cli_interp::resume ()
298{
299  struct ui *ui = current_ui;
300  struct cli_interp *cli = this;
301  struct ui_file *stream;
302
303  /*sync_execution = 1; */
304
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.  */
308
309  stream = cli->cli_uiout->set_stream (gdb_stdout);
310  if (stream != gdb_stdout)
311    {
312      cli->cli_uiout->set_stream (stream);
313      stream = NULL;
314    }
315
316  gdb_setup_readline (1);
317
318  ui->input_handler = command_line_handler;
319
320  if (stream != NULL)
321    cli->cli_uiout->set_stream (gdb_stdout);
322}
323
324void
325cli_interp::suspend ()
326{
327  gdb_disable_readline ();
328}
329
330gdb_exception
331cli_interp::exec (const char *command_str)
332{
333  struct cli_interp *cli = this;
334  struct ui_file *old_stream;
335  struct gdb_exception result;
336
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.
341
342     It is important that it gets reset everytime, since the user
343     could set gdb to use a different interpreter.  */
344  old_stream = cli->cli_uiout->set_stream (gdb_stdout);
345  result = safe_execute_command (cli->cli_uiout, command_str, 1);
346  cli->cli_uiout->set_stream (old_stream);
347  return result;
348}
349
350bool
351cli_interp_base::supports_command_editing ()
352{
353  return true;
354}
355
356static struct gdb_exception
357safe_execute_command (struct ui_out *command_uiout, const char *command,
358		      int from_tty)
359{
360  struct gdb_exception e;
361
362  /* Save and override the global ``struct ui_out'' builder.  */
363  scoped_restore saved_uiout = make_scoped_restore (&current_uiout,
364						    command_uiout);
365
366  try
367    {
368      execute_command (command, from_tty);
369    }
370  catch (gdb_exception &exception)
371    {
372      e = std::move (exception);
373    }
374
375  /* FIXME: cagney/2005-01-13: This shouldn't be needed.  Instead the
376     caller should print the exception.  */
377  exception_print (gdb_stderr, e);
378  return e;
379}
380
381ui_out *
382cli_interp::interp_ui_out ()
383{
384  struct cli_interp *cli = (struct cli_interp *) this;
385
386  return cli->cli_uiout;
387}
388
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;
398  ui_file *file_to_delete;
399};
400static saved_output_files saved_output;
401
402/* See cli-interp.h.  */
403
404void
405cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect,
406			      bool debug_redirect)
407{
408  if (logfile != nullptr)
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
416      /* If something is being redirected, then grab logfile.  */
417      ui_file *logfile_p = nullptr;
418      if (logging_redirect || debug_redirect)
419	{
420	  logfile_p = logfile.get ();
421	  saved_output.file_to_delete = logfile_p;
422	}
423
424      /* If something is not being redirected, then a tee containing both the
425	 logfile and stdout.  */
426      ui_file *tee = nullptr;
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	}
432
433      gdb_stdout = logging_redirect ? logfile_p : tee;
434      gdb_stdlog = debug_redirect ? logfile_p : tee;
435      gdb_stderr = logging_redirect ? logfile_p : tee;
436      gdb_stdtarg = logging_redirect ? logfile_p : tee;
437      gdb_stdtargerr = logging_redirect ? logfile_p : tee;
438    }
439  else
440    {
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;
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
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;
456      saved_output.file_to_delete = nullptr;
457    }
458}
459
460/* Factory for CLI interpreters.  */
461
462static struct interp *
463cli_interp_factory (const char *name)
464{
465  return new cli_interp (name);
466}
467
468/* Standard gdb initialization hook.  */
469
470void _initialize_cli_interp ();
471void
472_initialize_cli_interp ()
473{
474  interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
475
476  /* If changing this, remember to update tui-interp.c as well.  */
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
486    (cli_on_user_selected_context_changed);
487}
488