xref: /NextBSD/contrib/gdb/gdb/tui/tui-hooks.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /* GDB hooks for TUI.
2 
3    Copyright 2001, 2002, 2003, 2004 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 2 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, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21 
22 #include "defs.h"
23 #include "symtab.h"
24 #include "inferior.h"
25 #include "command.h"
26 #include "bfd.h"
27 #include "symfile.h"
28 #include "objfiles.h"
29 #include "target.h"
30 #include "gdbcore.h"
31 #include "event-loop.h"
32 #include "event-top.h"
33 #include "frame.h"
34 #include "breakpoint.h"
35 #include "gdb-events.h"
36 #include "ui-out.h"
37 #include "top.h"
38 #include "readline/readline.h"
39 #include <unistd.h>
40 #include <fcntl.h>
41 
42 #include "tui/tui.h"
43 #include "tui/tui-hooks.h"
44 #include "tui/tui-data.h"
45 #include "tui/tui-layout.h"
46 #include "tui/tui-io.h"
47 #include "tui/tui-regs.h"
48 #include "tui/tui-win.h"
49 #include "tui/tui-stack.h"
50 #include "tui/tui-windata.h"
51 #include "tui/tui-winsource.h"
52 
53 #include "gdb_curses.h"
54 
55 int tui_target_has_run = 0;
56 
57 static void (* tui_target_new_objfile_chain) (struct objfile*);
58 
59 static void
tui_new_objfile_hook(struct objfile * objfile)60 tui_new_objfile_hook (struct objfile* objfile)
61 {
62   if (tui_active)
63     tui_display_main ();
64 
65   if (tui_target_new_objfile_chain)
66     tui_target_new_objfile_chain (objfile);
67 }
68 
69 static int
tui_query_hook(const char * msg,va_list argp)70 tui_query_hook (const char * msg, va_list argp)
71 {
72   int retval;
73   int ans2;
74   int answer;
75 
76   /* Automatically answer "yes" if input is not from a terminal.  */
77   if (!input_from_terminal_p ())
78     return 1;
79 
80   echo ();
81   while (1)
82     {
83       wrap_here ("");		/* Flush any buffered output */
84       gdb_flush (gdb_stdout);
85 
86       vfprintf_filtered (gdb_stdout, msg, argp);
87       printf_filtered ("(y or n) ");
88 
89       wrap_here ("");
90       gdb_flush (gdb_stdout);
91 
92       answer = tui_getc (stdin);
93       clearerr (stdin);		/* in case of C-d */
94       if (answer == EOF)	/* C-d */
95 	{
96 	  retval = 1;
97 	  break;
98 	}
99       /* Eat rest of input line, to EOF or newline */
100       if (answer != '\n')
101 	do
102 	  {
103             ans2 = tui_getc (stdin);
104 	    clearerr (stdin);
105 	  }
106 	while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
107 
108       if (answer >= 'a')
109 	answer -= 040;
110       if (answer == 'Y')
111 	{
112 	  retval = 1;
113 	  break;
114 	}
115       if (answer == 'N')
116 	{
117 	  retval = 0;
118 	  break;
119 	}
120       printf_filtered ("Please answer y or n.\n");
121     }
122   noecho ();
123   return retval;
124 }
125 
126 /* Prevent recursion of registers_changed_hook().  */
127 static int tui_refreshing_registers = 0;
128 
129 static void
tui_registers_changed_hook(void)130 tui_registers_changed_hook (void)
131 {
132   struct frame_info *fi;
133 
134   fi = deprecated_selected_frame;
135   if (fi && tui_refreshing_registers == 0)
136     {
137       tui_refreshing_registers = 1;
138 #if 0
139       tui_check_data_values (fi);
140 #endif
141       tui_refreshing_registers = 0;
142     }
143 }
144 
145 static void
tui_register_changed_hook(int regno)146 tui_register_changed_hook (int regno)
147 {
148   struct frame_info *fi;
149 
150   fi = deprecated_selected_frame;
151   if (fi && tui_refreshing_registers == 0)
152     {
153       tui_refreshing_registers = 1;
154       tui_check_data_values (fi);
155       tui_refreshing_registers = 0;
156     }
157 }
158 
159 /* Breakpoint creation hook.
160    Update the screen to show the new breakpoint.  */
161 static void
tui_event_create_breakpoint(int number)162 tui_event_create_breakpoint (int number)
163 {
164   tui_update_all_breakpoint_info ();
165 }
166 
167 /* Breakpoint deletion hook.
168    Refresh the screen to update the breakpoint marks.  */
169 static void
tui_event_delete_breakpoint(int number)170 tui_event_delete_breakpoint (int number)
171 {
172   tui_update_all_breakpoint_info ();
173 }
174 
175 static void
tui_event_modify_breakpoint(int number)176 tui_event_modify_breakpoint (int number)
177 {
178   tui_update_all_breakpoint_info ();
179 }
180 
181 static void
tui_event_default(int number)182 tui_event_default (int number)
183 {
184   ;
185 }
186 
187 static struct gdb_events *tui_old_event_hooks;
188 
189 static struct gdb_events tui_event_hooks =
190 {
191   tui_event_create_breakpoint,
192   tui_event_delete_breakpoint,
193   tui_event_modify_breakpoint,
194   tui_event_default,
195   tui_event_default,
196   tui_event_default
197 };
198 
199 /* Called when going to wait for the target.
200    Leave curses mode and setup program mode.  */
201 static ptid_t
tui_target_wait_hook(ptid_t pid,struct target_waitstatus * status)202 tui_target_wait_hook (ptid_t pid, struct target_waitstatus *status)
203 {
204   ptid_t res;
205 
206   /* Leave tui mode (optional).  */
207 #if 0
208   if (tui_active)
209     {
210       target_terminal_ours ();
211       endwin ();
212       target_terminal_inferior ();
213     }
214 #endif
215   tui_target_has_run = 1;
216   res = target_wait (pid, status);
217 
218   if (tui_active)
219     {
220       /* TODO: need to refresh (optional).  */
221     }
222   return res;
223 }
224 
225 /* The selected frame has changed.  This is happens after a target
226    stop or when the user explicitly changes the frame (up/down/thread/...).  */
227 static void
tui_selected_frame_level_changed_hook(int level)228 tui_selected_frame_level_changed_hook (int level)
229 {
230   struct frame_info *fi;
231 
232   fi = deprecated_selected_frame;
233   /* Ensure that symbols for this frame are read in.  Also, determine the
234      source language of this frame, and switch to it if desired.  */
235   if (fi)
236     {
237       struct symtab *s;
238 
239       s = find_pc_symtab (get_frame_pc (fi));
240       /* elz: this if here fixes the problem with the pc not being displayed
241          in the tui asm layout, with no debug symbols. The value of s
242          would be 0 here, and select_source_symtab would abort the
243          command by calling the 'error' function */
244       if (s)
245         select_source_symtab (s);
246 
247       /* Display the frame position (even if there is no symbols).  */
248       tui_show_frame_info (fi);
249 
250       /* Refresh the register window if it's visible.  */
251       if (tui_is_window_visible (DATA_WIN))
252         {
253           tui_refreshing_registers = 1;
254           tui_check_data_values (fi);
255           tui_refreshing_registers = 0;
256         }
257     }
258 }
259 
260 /* Called from print_frame_info to list the line we stopped in.  */
261 static void
tui_print_frame_info_listing_hook(struct symtab * s,int line,int stopline,int noerror)262 tui_print_frame_info_listing_hook (struct symtab *s, int line,
263                                    int stopline, int noerror)
264 {
265   select_source_symtab (s);
266   tui_show_frame_info (deprecated_selected_frame);
267 }
268 
269 /* Called when the target process died or is detached.
270    Update the status line.  */
271 static void
tui_detach_hook(void)272 tui_detach_hook (void)
273 {
274   tui_show_frame_info (0);
275   tui_display_main ();
276 }
277 
278 /* Install the TUI specific hooks.  */
279 void
tui_install_hooks(void)280 tui_install_hooks (void)
281 {
282   target_wait_hook = tui_target_wait_hook;
283   selected_frame_level_changed_hook = tui_selected_frame_level_changed_hook;
284   print_frame_info_listing_hook = tui_print_frame_info_listing_hook;
285 
286   query_hook = tui_query_hook;
287 
288   /* Install the event hooks.  */
289   tui_old_event_hooks = set_gdb_event_hooks (&tui_event_hooks);
290 
291   registers_changed_hook = tui_registers_changed_hook;
292   register_changed_hook = tui_register_changed_hook;
293   detach_hook = tui_detach_hook;
294 }
295 
296 /* Remove the TUI specific hooks.  */
297 void
tui_remove_hooks(void)298 tui_remove_hooks (void)
299 {
300   target_wait_hook = 0;
301   selected_frame_level_changed_hook = 0;
302   print_frame_info_listing_hook = 0;
303   query_hook = 0;
304   registers_changed_hook = 0;
305   register_changed_hook = 0;
306   detach_hook = 0;
307 
308   /* Restore the previous event hooks.  */
309   set_gdb_event_hooks (tui_old_event_hooks);
310 }
311 
312 void _initialize_tui_hooks (void);
313 
314 void
_initialize_tui_hooks(void)315 _initialize_tui_hooks (void)
316 {
317   /* Install the permanent hooks.  */
318   tui_target_new_objfile_chain = target_new_objfile_hook;
319   target_new_objfile_hook = tui_new_objfile_hook;
320 }
321