xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/cli/cli-interp.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /* CLI Definitions for GDB, the GNU debugger.
2 
3    Copyright (C) 2002-2017 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 "event-top.h"
28 #include "infrun.h"
29 #include "observer.h"
30 #include "gdbthread.h"
31 #include "thread-fsm.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 
47   void init (bool top_level) override;
48   void resume () override;
49   void suspend () override;
50   gdb_exception exec (const char *command_str) override;
51   ui_out *interp_ui_out () override;
52 
53   /* The ui_out for the console interpreter.  */
54   cli_ui_out *cli_uiout;
55 };
56 
57 cli_interp::cli_interp (const char *name)
58   : cli_interp_base (name)
59 {
60   /* Create a default uiout builder for the CLI.  */
61   this->cli_uiout = cli_out_new (gdb_stdout);
62 }
63 
64 /* Suppress notification struct.  */
65 struct cli_suppress_notification cli_suppress_notification =
66   {
67     0   /* user_selected_context_changed */
68   };
69 
70 /* Returns the INTERP's data cast as cli_interp if INTERP is a CLI,
71    and returns NULL otherwise.  */
72 
73 static struct cli_interp *
74 as_cli_interp (struct interp *interp)
75 {
76   if (strcmp (interp_name (interp), INTERP_CONSOLE) == 0)
77     return (struct cli_interp *) interp;
78   return NULL;
79 }
80 
81 /* Longjmp-safe wrapper for "execute_command".  */
82 static struct gdb_exception safe_execute_command (struct ui_out *uiout,
83 						  char *command,
84 						  int from_tty);
85 
86 /* See cli-interp.h.
87 
88    Breakpoint hits should always be mirrored to a console.  Deciding
89    what to mirror to a console wrt to breakpoints and random stops
90    gets messy real fast.  E.g., say "s" trips on a breakpoint.  We'd
91    clearly want to mirror the event to the console in this case.  But
92    what about more complicated cases like "s&; thread n; s&", and one
93    of those steps spawning a new thread, and that thread hitting a
94    breakpoint?  It's impossible in general to track whether the thread
95    had any relation to the commands that had been executed.  So we
96    just simplify and always mirror breakpoints and random events to
97    all consoles.
98 
99    OTOH, we should print the source line to the console when stepping
100    or other similar commands, iff the step was started by that console
101    (or in MI's case, by a console command), but not if it was started
102    with MI's -exec-step or similar.  */
103 
104 int
105 should_print_stop_to_console (struct interp *console_interp,
106 			      struct thread_info *tp)
107 {
108   if ((bpstat_what (tp->control.stop_bpstat).main_action
109        == BPSTAT_WHAT_STOP_NOISY)
110       || tp->thread_fsm == NULL
111       || tp->thread_fsm->command_interp == console_interp
112       || !thread_fsm_finished_p (tp->thread_fsm))
113     return 1;
114   return 0;
115 }
116 
117 /* Observers for several run control events.  If the interpreter is
118    quiet (i.e., another interpreter is being run with
119    interpreter-exec), print nothing.  */
120 
121 /* Observer for the normal_stop notification.  */
122 
123 static void
124 cli_on_normal_stop (struct bpstats *bs, int print_frame)
125 {
126   if (!print_frame)
127     return;
128 
129   SWITCH_THRU_ALL_UIS ()
130     {
131       struct interp *interp = top_level_interpreter ();
132       struct cli_interp *cli = as_cli_interp (interp);
133       struct thread_info *thread;
134 
135       if (cli == NULL)
136 	continue;
137 
138       thread = inferior_thread ();
139       if (should_print_stop_to_console (interp, thread))
140 	print_stop_event (cli->cli_uiout);
141     }
142 }
143 
144 /* Observer for the signal_received notification.  */
145 
146 static void
147 cli_on_signal_received (enum gdb_signal siggnal)
148 {
149   SWITCH_THRU_ALL_UIS ()
150     {
151       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
152 
153       if (cli == NULL)
154 	continue;
155 
156       print_signal_received_reason (cli->cli_uiout, siggnal);
157     }
158 }
159 
160 /* Observer for the end_stepping_range notification.  */
161 
162 static void
163 cli_on_end_stepping_range (void)
164 {
165   SWITCH_THRU_ALL_UIS ()
166     {
167       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
168 
169       if (cli == NULL)
170 	continue;
171 
172       print_end_stepping_range_reason (cli->cli_uiout);
173     }
174 }
175 
176 /* Observer for the signalled notification.  */
177 
178 static void
179 cli_on_signal_exited (enum gdb_signal siggnal)
180 {
181   SWITCH_THRU_ALL_UIS ()
182     {
183       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
184 
185       if (cli == NULL)
186 	continue;
187 
188       print_signal_exited_reason (cli->cli_uiout, siggnal);
189     }
190 }
191 
192 /* Observer for the exited notification.  */
193 
194 static void
195 cli_on_exited (int exitstatus)
196 {
197   SWITCH_THRU_ALL_UIS ()
198     {
199       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
200 
201       if (cli == NULL)
202 	continue;
203 
204       print_exited_reason (cli->cli_uiout, exitstatus);
205     }
206 }
207 
208 /* Observer for the no_history notification.  */
209 
210 static void
211 cli_on_no_history (void)
212 {
213   SWITCH_THRU_ALL_UIS ()
214     {
215       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
216 
217       if (cli == NULL)
218 	continue;
219 
220       print_no_history_reason (cli->cli_uiout);
221     }
222 }
223 
224 /* Observer for the sync_execution_done notification.  */
225 
226 static void
227 cli_on_sync_execution_done (void)
228 {
229   struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
230 
231   if (cli == NULL)
232     return;
233 
234   display_gdb_prompt (NULL);
235 }
236 
237 /* Observer for the command_error notification.  */
238 
239 static void
240 cli_on_command_error (void)
241 {
242   struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
243 
244   if (cli == NULL)
245     return;
246 
247   display_gdb_prompt (NULL);
248 }
249 
250 /* Observer for the user_selected_context_changed notification.  */
251 
252 static void
253 cli_on_user_selected_context_changed (user_selected_what selection)
254 {
255   struct thread_info *tp;
256 
257   /* This event is suppressed.  */
258   if (cli_suppress_notification.user_selected_context)
259     return;
260 
261   tp = find_thread_ptid (inferior_ptid);
262 
263   SWITCH_THRU_ALL_UIS ()
264     {
265       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
266 
267       if (cli == NULL)
268 	continue;
269 
270       if (selection & USER_SELECTED_INFERIOR)
271 	print_selected_inferior (cli->cli_uiout);
272 
273       if (tp != NULL
274 	  && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
275 	print_selected_thread_frame (cli->cli_uiout, selection);
276     }
277 }
278 
279 /* pre_command_loop implementation.  */
280 
281 void
282 cli_interp_base::pre_command_loop ()
283 {
284   display_gdb_prompt (0);
285 }
286 
287 /* These implement the cli out interpreter: */
288 
289 void
290 cli_interp::init (bool top_level)
291 {
292 }
293 
294 void
295 cli_interp::resume ()
296 {
297   struct ui *ui = current_ui;
298   struct cli_interp *cli = this;
299   struct ui_file *stream;
300 
301   /*sync_execution = 1; */
302 
303   /* gdb_setup_readline will change gdb_stdout.  If the CLI was
304      previously writing to gdb_stdout, then set it to the new
305      gdb_stdout afterwards.  */
306 
307   stream = cli->cli_uiout->set_stream (gdb_stdout);
308   if (stream != gdb_stdout)
309     {
310       cli->cli_uiout->set_stream (stream);
311       stream = NULL;
312     }
313 
314   gdb_setup_readline (1);
315 
316   ui->input_handler = command_line_handler;
317 
318   if (stream != NULL)
319     cli->cli_uiout->set_stream (gdb_stdout);
320 }
321 
322 void
323 cli_interp::suspend ()
324 {
325   gdb_disable_readline ();
326 }
327 
328 gdb_exception
329 cli_interp::exec (const char *command_str)
330 {
331   struct cli_interp *cli = this;
332   struct ui_file *old_stream;
333   struct gdb_exception result;
334 
335   /* FIXME: cagney/2003-02-01: Need to const char *propogate
336      safe_execute_command.  */
337   char *str = (char *) alloca (strlen (command_str) + 1);
338   strcpy (str, command_str);
339 
340   /* gdb_stdout could change between the time cli_uiout was
341      initialized and now.  Since we're probably using a different
342      interpreter which has a new ui_file for gdb_stdout, use that one
343      instead of the default.
344 
345      It is important that it gets reset everytime, since the user
346      could set gdb to use a different interpreter.  */
347   old_stream = cli->cli_uiout->set_stream (gdb_stdout);
348   result = safe_execute_command (cli->cli_uiout, str, 1);
349   cli->cli_uiout->set_stream (old_stream);
350   return result;
351 }
352 
353 bool
354 cli_interp_base::supports_command_editing ()
355 {
356   return true;
357 }
358 
359 static struct gdb_exception
360 safe_execute_command (struct ui_out *command_uiout, char *command, int from_tty)
361 {
362   struct gdb_exception e = exception_none;
363   struct ui_out *saved_uiout;
364 
365   /* Save and override the global ``struct ui_out'' builder.  */
366   saved_uiout = current_uiout;
367   current_uiout = command_uiout;
368 
369   TRY
370     {
371       execute_command (command, from_tty);
372     }
373   CATCH (exception, RETURN_MASK_ALL)
374     {
375       e = exception;
376     }
377   END_CATCH
378 
379   /* Restore the global builder.  */
380   current_uiout = saved_uiout;
381 
382   /* FIXME: cagney/2005-01-13: This shouldn't be needed.  Instead the
383      caller should print the exception.  */
384   exception_print (gdb_stderr, e);
385   return e;
386 }
387 
388 ui_out *
389 cli_interp::interp_ui_out ()
390 {
391   struct cli_interp *cli = (struct cli_interp *) this;
392 
393   return cli->cli_uiout;
394 }
395 
396 /* These hold the pushed copies of the gdb output files.
397    If NULL then nothing has yet been pushed.  */
398 struct saved_output_files
399 {
400   ui_file *out;
401   ui_file *err;
402   ui_file *log;
403   ui_file *targ;
404   ui_file *targerr;
405 };
406 static saved_output_files saved_output;
407 
408 /* See cli-interp.h.  */
409 
410 void
411 cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect)
412 {
413   if (logfile != NULL)
414     {
415       saved_output.out = gdb_stdout;
416       saved_output.err = gdb_stderr;
417       saved_output.log = gdb_stdlog;
418       saved_output.targ = gdb_stdtarg;
419       saved_output.targerr = gdb_stdtargerr;
420 
421       /* A raw pointer since ownership is transferred to
422 	 gdb_stdout.  */
423       ui_file *output = make_logging_output (gdb_stdout,
424 					     std::move (logfile),
425 					     logging_redirect);
426       gdb_stdout = output;
427       gdb_stdlog = output;
428       gdb_stderr = output;
429       gdb_stdtarg = output;
430       gdb_stdtargerr = output;
431     }
432   else
433     {
434       /* Only delete one of the files -- they are all set to the same
435 	 value.  */
436       delete gdb_stdout;
437 
438       gdb_stdout = saved_output.out;
439       gdb_stderr = saved_output.err;
440       gdb_stdlog = saved_output.log;
441       gdb_stdtarg = saved_output.targ;
442       gdb_stdtargerr = saved_output.targerr;
443 
444       saved_output.out = NULL;
445       saved_output.err = NULL;
446       saved_output.log = NULL;
447       saved_output.targ = NULL;
448       saved_output.targerr = NULL;
449     }
450 }
451 
452 /* Factory for CLI interpreters.  */
453 
454 static struct interp *
455 cli_interp_factory (const char *name)
456 {
457   return new cli_interp (name);
458 }
459 
460 /* Standard gdb initialization hook.  */
461 extern initialize_file_ftype _initialize_cli_interp; /* -Wmissing-prototypes */
462 
463 void
464 _initialize_cli_interp (void)
465 {
466   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
467 
468   /* If changing this, remember to update tui-interp.c as well.  */
469   observer_attach_normal_stop (cli_on_normal_stop);
470   observer_attach_end_stepping_range (cli_on_end_stepping_range);
471   observer_attach_signal_received (cli_on_signal_received);
472   observer_attach_signal_exited (cli_on_signal_exited);
473   observer_attach_exited (cli_on_exited);
474   observer_attach_no_history (cli_on_no_history);
475   observer_attach_sync_execution_done (cli_on_sync_execution_done);
476   observer_attach_command_error (cli_on_command_error);
477   observer_attach_user_selected_context_changed
478     (cli_on_user_selected_context_changed);
479 }
480