xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/cli/cli-interp.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
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 
33 cli_interp_base::cli_interp_base (const char *name)
34   : interp (name)
35 {}
36 
37 cli_interp_base::~cli_interp_base ()
38 {}
39 
40 /* The console interpreter.  */
41 
42 class 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 
58 cli_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 
65 cli_interp::~cli_interp ()
66 {
67   delete cli_uiout;
68 }
69 
70 /* Suppress notification struct.  */
71 struct 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 
79 static struct cli_interp *
80 as_cli_interp (struct interp *interp)
81 {
82   return dynamic_cast<cli_interp *> (interp);
83 }
84 
85 /* Longjmp-safe wrapper for "execute_command".  */
86 static 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 
108 int
109 should_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 
127 static void
128 cli_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 
150 static void
151 cli_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 
166 static void
167 cli_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 
182 static void
183 cli_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 
198 static void
199 cli_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 
214 static void
215 cli_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 
230 static void
231 cli_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 
243 static void
244 cli_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 
256 static void
257 cli_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 
283 void
284 cli_interp_base::pre_command_loop ()
285 {
286   display_gdb_prompt (0);
287 }
288 
289 /* These implement the cli out interpreter: */
290 
291 void
292 cli_interp::init (bool top_level)
293 {
294 }
295 
296 void
297 cli_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 
324 void
325 cli_interp::suspend ()
326 {
327   gdb_disable_readline ();
328 }
329 
330 gdb_exception
331 cli_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 
350 bool
351 cli_interp_base::supports_command_editing ()
352 {
353   return true;
354 }
355 
356 static struct gdb_exception
357 safe_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 
381 ui_out *
382 cli_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.  */
391 struct 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 };
400 static saved_output_files saved_output;
401 
402 /* See cli-interp.h.  */
403 
404 void
405 cli_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 
462 static struct interp *
463 cli_interp_factory (const char *name)
464 {
465   return new cli_interp (name);
466 }
467 
468 /* Standard gdb initialization hook.  */
469 
470 void _initialize_cli_interp ();
471 void
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