2002-02-08 Daniel Jacobowitz <drow@mvista.com>
[platform/upstream/binutils.git] / gdb / tui / tui-hooks.c
1 /* GDB hooks for TUI.
2    Copyright 2001 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 /* If we need <curses.h>, we must include it before we get "bfd.h".  */
22 #include "config.h"
23 #ifdef HAVE_NCURSES_H
24 #include <ncurses.h>
25 #else
26 #ifdef HAVE_CURSES_H
27 #include <curses.h>
28 #endif
29 #endif
30
31 #include "defs.h"
32 #include "symtab.h"
33 #include "inferior.h"
34 #include "command.h"
35 #include "bfd.h"
36 #include "symfile.h"
37 #include "objfiles.h"
38 #include "target.h"
39 #include "gdbcore.h"
40 #include "event-loop.h"
41 #include "frame.h"
42 #include "breakpoint.h"
43 #include "gdb-events.h"
44 #include <unistd.h>
45 #include <fcntl.h>
46
47 #include "tui.h"
48 #include "tuiData.h"
49 #include "tuiLayout.h"
50 #include "tuiIO.h"
51 #include "tuiRegs.h"
52 #include "tuiWin.h"
53 #include "tuiStack.h"
54 #include "tuiDataWin.h"
55 #include "tuiSourceWin.h"
56
57 int tui_target_has_run = 0;
58
59 static void (* tui_target_new_objfile_chain) (struct objfile*);
60 extern void (*selected_frame_level_changed_hook) (int);
61
62 static void
63 tui_new_objfile_hook (struct objfile* objfile)
64 {
65   if (tui_active)
66     {
67       tuiDisplayMainFunction ();
68     }
69   
70   if (tui_target_new_objfile_chain)
71     tui_target_new_objfile_chain (objfile);
72 }
73
74 static int
75 tui_query_hook (const char * msg, va_list argp)
76 {
77   int retval;
78   int ans2;
79   int answer;
80
81   /* Automatically answer "yes" if input is not from a terminal.  */
82   if (!input_from_terminal_p ())
83     return 1;
84
85   echo ();
86   while (1)
87     {
88       wrap_here ("");           /* Flush any buffered output */
89       gdb_flush (gdb_stdout);
90
91       vfprintf_filtered (gdb_stdout, msg, argp);
92       printf_filtered ("(y or n) ");
93
94       wrap_here ("");
95       gdb_flush (gdb_stdout);
96
97       answer = tui_getc (stdin);
98       clearerr (stdin);         /* in case of C-d */
99       if (answer == EOF)        /* C-d */
100         {
101           retval = 1;
102           break;
103         }
104       /* Eat rest of input line, to EOF or newline */
105       if (answer != '\n')
106         do
107           {
108             ans2 = tui_getc (stdin);
109             clearerr (stdin);
110           }
111         while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
112
113       if (answer >= 'a')
114         answer -= 040;
115       if (answer == 'Y')
116         {
117           retval = 1;
118           break;
119         }
120       if (answer == 'N')
121         {
122           retval = 0;
123           break;
124         }
125       printf_filtered ("Please answer y or n.\n");
126     }
127   noecho ();
128   return retval;
129 }
130
131 /* Prevent recursion of registers_changed_hook().  */
132 static int tui_refreshing_registers = 0;
133
134 static void
135 tui_registers_changed_hook (void)
136 {
137   struct frame_info *fi;
138
139   fi = selected_frame;
140   if (fi && tui_refreshing_registers == 0)
141     {
142       tui_refreshing_registers = 1;
143 #if 0
144       tuiCheckDataValues (fi);
145 #endif
146       tui_refreshing_registers = 0;
147     }
148 }
149
150 static void
151 tui_register_changed_hook (int regno)
152 {
153   struct frame_info *fi;
154
155   fi = selected_frame;
156   if (fi && tui_refreshing_registers == 0)
157     {
158       tui_refreshing_registers = 1;
159       tuiCheckDataValues (fi);
160       tui_refreshing_registers = 0;
161     }
162 }
163
164 extern struct breakpoint *breakpoint_chain;
165
166 /* Find a breakpoint given its number.  Returns null if not found.  */
167 static struct breakpoint *
168 get_breakpoint (int number)
169 {
170   struct breakpoint *bp;
171
172   for (bp = breakpoint_chain; bp; bp = bp->next)
173     {
174       if (bp->number == number)
175         return bp;
176     }
177   return 0;
178 }
179
180 /* Breakpoint creation hook.
181    Update the screen to show the new breakpoint.  */
182 static void
183 tui_event_create_breakpoint (int number)
184 {
185   struct breakpoint *bp;
186
187   bp = get_breakpoint (number);
188   if (bp)
189     {
190       switch (bp->type)
191         {
192         case bp_breakpoint:
193         case bp_hardware_breakpoint:
194           tuiAllSetHasBreakAt (bp, 1);
195           tuiUpdateAllExecInfos ();
196           break;
197
198         default:
199           break;
200         }
201     }
202 }
203
204 /* Breakpoint deletion hook.
205    Refresh the screen to update the breakpoint marks.  */
206 static void
207 tui_event_delete_breakpoint (int number)
208 {
209   struct breakpoint *bp;
210   struct breakpoint *b;
211   int clearIt;
212
213   bp = get_breakpoint (number);
214   if (bp == 0)
215     return;
216
217   /* Before turning off the visuals for the bp, check to see that
218      there are no other bps at the same address. */
219   clearIt = 0;
220   for (b = breakpoint_chain; b; b = b->next)
221     {
222       clearIt = (b == bp || b->address != bp->address);
223       if (!clearIt)
224         break;
225     }
226
227   if (clearIt)
228     {
229       tuiAllSetHasBreakAt (bp, 0);
230       tuiUpdateAllExecInfos ();
231     }
232 }
233
234 static void
235 tui_event_modify_breakpoint (int number)
236 {
237   ;
238 }
239
240 static void
241 tui_event_default (int number)
242 {
243   ;
244 }
245
246 static struct gdb_events *tui_old_event_hooks;
247
248 static struct gdb_events tui_event_hooks =
249 {
250   tui_event_create_breakpoint,
251   tui_event_delete_breakpoint,
252   tui_event_modify_breakpoint,
253   tui_event_default,
254   tui_event_default,
255   tui_event_default
256 };
257
258 /* Called when going to wait for the target.
259    Leave curses mode and setup program mode.  */
260 static ptid_t
261 tui_target_wait_hook (ptid_t pid, struct target_waitstatus *status)
262 {
263   ptid_t res;
264
265   /* Leave tui mode (optional).  */
266 #if 0
267   if (tui_active)
268     {
269       target_terminal_ours ();
270       endwin ();
271       target_terminal_inferior ();
272     }
273 #endif
274   tui_target_has_run = 1;
275   res = target_wait (pid, status);
276
277   if (tui_active)
278     {
279       /* TODO: need to refresh (optional).  */
280     }
281   return res;
282 }
283
284 /* The selected frame has changed.  This is happens after a target
285    stop or when the user explicitly changes the frame (up/down/thread/...).  */
286 static void
287 tui_selected_frame_level_changed_hook (int level)
288 {
289   struct frame_info *fi;
290
291   fi = selected_frame;
292   /* Ensure that symbols for this frame are read in.  Also, determine the
293      source language of this frame, and switch to it if desired.  */
294   if (fi)
295     {
296       struct symtab *s;
297       
298       s = find_pc_symtab (fi->pc);
299       /* elz: this if here fixes the problem with the pc not being displayed
300          in the tui asm layout, with no debug symbols. The value of s 
301          would be 0 here, and select_source_symtab would abort the
302          command by calling the 'error' function */
303       if (s)
304         {
305           select_source_symtab (s);
306           tuiShowFrameInfo (fi);
307         }
308
309       /* Refresh the register window if it's visible.  */
310       if (tui_is_window_visible (DATA_WIN))
311         {
312           tui_refreshing_registers = 1;
313           tuiCheckDataValues (fi);
314           tui_refreshing_registers = 0;
315         }
316     }
317 }
318
319 /* Called from print_frame_info to list the line we stopped in.  */
320 static void
321 tui_print_frame_info_listing_hook (struct symtab *s, int line,
322                                    int stopline, int noerror)
323 {
324   select_source_symtab (s);
325   tuiShowFrameInfo (selected_frame);
326 }
327
328 /* Install the TUI specific hooks.  */
329 void
330 tui_install_hooks (void)
331 {
332   target_wait_hook = tui_target_wait_hook;
333   selected_frame_level_changed_hook = tui_selected_frame_level_changed_hook;
334   print_frame_info_listing_hook = tui_print_frame_info_listing_hook;
335
336   query_hook = tui_query_hook;
337
338   /* Install the event hooks.  */
339   tui_old_event_hooks = set_gdb_event_hooks (&tui_event_hooks);
340
341   registers_changed_hook = tui_registers_changed_hook;
342   register_changed_hook = tui_register_changed_hook;
343 }
344
345 /* Remove the TUI specific hooks.  */
346 void
347 tui_remove_hooks (void)
348 {
349   target_wait_hook = 0;
350   selected_frame_level_changed_hook = 0;
351   print_frame_info_listing_hook = 0;
352   query_hook = 0;
353   registers_changed_hook = 0;
354   register_changed_hook = 0;
355
356   /* Restore the previous event hooks.  */
357   set_gdb_event_hooks (tui_old_event_hooks);
358 }
359
360 /* Cleanup the tui before exiting.  */
361 static void
362 tui_exit (void)
363 {
364   /* Disable the tui.  Curses mode is left leaving the screen
365      in a clean state (see endwin()).  */
366   tui_disable ();
367 }
368
369 /* Initialize the tui by installing several gdb hooks, initializing
370    the tui IO and preparing the readline with the kind binding.  */
371 static void
372 tui_init_hook (char *argv0)
373 {
374   /* Install exit handler to leave the screen in a good shape.  */
375   atexit (tui_exit);
376
377   initializeStaticData ();
378
379   /* Install the permanent hooks.  */
380   tui_target_new_objfile_chain = target_new_objfile_hook;
381   target_new_objfile_hook = tui_new_objfile_hook;
382
383   tui_initialize_io ();
384   tui_initialize_readline ();
385
386   /* Decide in which mode to start using GDB (based on -tui).  */
387   if (tui_version)
388     {
389       tui_enable ();
390     }
391 }
392
393 /* Initialize the tui.  */
394 void
395 _initialize_tui (void)
396 {
397   /* Setup initialization hook.  */
398   init_ui_hook = tui_init_hook;
399 }
400