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