OSDN Git Service

* gdb.texinfo (Target Description Format): Add version attribute
[pf3gnuchains/pf3gnuchains4x.git] / gdb / tui / tui-winsource.c
1 /* TUI display source/assembly window.
2
3    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
4    Free Software Foundation, Inc.
5
6    Contributed by Hewlett-Packard Company.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110-1301, USA.  */
24
25 #include "defs.h"
26 #include <ctype.h>
27 #include "symtab.h"
28 #include "frame.h"
29 #include "breakpoint.h"
30 #include "value.h"
31 #include "source.h"
32
33 #include "tui/tui.h"
34 #include "tui/tui-data.h"
35 #include "tui/tui-stack.h"
36 #include "tui/tui-win.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-winsource.h"
39 #include "tui/tui-source.h"
40 #include "tui/tui-disasm.h"
41
42 #include "gdb_string.h"
43 #include "gdb_curses.h"
44 #include "gdb_assert.h"
45
46 /* Function to display the "main" routine.  */
47 void
48 tui_display_main (void)
49 {
50   if ((tui_source_windows ())->count > 0)
51     {
52       CORE_ADDR addr;
53
54       addr = tui_get_begin_asm_address ();
55       if (addr != (CORE_ADDR) 0)
56         {
57           struct symtab_and_line sal;
58
59           tui_update_source_windows_with_addr (addr);
60           sal = find_pc_line (addr, 0);
61           if (sal.symtab)
62              tui_update_locator_filename (sal.symtab->filename);
63           else
64              tui_update_locator_filename ("??");
65         }
66     }
67 }
68
69
70
71 /* Function to display source in the source window.  This function
72    initializes the horizontal scroll to 0.  */
73 void
74 tui_update_source_window (struct tui_win_info * win_info, struct symtab *s,
75                           struct tui_line_or_address line_or_addr, int noerror)
76 {
77   win_info->detail.source_info.horizontal_offset = 0;
78   tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
79
80   return;
81 }
82
83
84 /* Function to display source in the source/asm window.  This function
85    shows the source as specified by the horizontal offset.  */
86 void
87 tui_update_source_window_as_is (struct tui_win_info * win_info, struct symtab *s,
88                                 struct tui_line_or_address line_or_addr, int noerror)
89 {
90   enum tui_status ret;
91
92   if (win_info->generic.type == SRC_WIN)
93     ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
94   else
95     ret = tui_set_disassem_content (line_or_addr.u.addr);
96
97   if (ret == TUI_FAILURE)
98     {
99       tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
100       tui_clear_exec_info_content (win_info);
101     }
102   else
103     {
104       tui_update_breakpoint_info (win_info, 0);
105       tui_show_source_content (win_info);
106       tui_update_exec_info (win_info);
107       if (win_info->generic.type == SRC_WIN)
108         {
109           struct symtab_and_line sal;
110           
111           sal.line = line_or_addr.u.line_no +
112             (win_info->generic.content_size - 2);
113           sal.symtab = s;
114           set_current_source_symtab_and_line (&sal);
115           /*
116              ** If the focus was in the asm win, put it in the src
117              ** win if we don't have a split layout
118            */
119           if (tui_win_with_focus () == TUI_DISASM_WIN &&
120               tui_current_layout () != SRC_DISASSEM_COMMAND)
121             tui_set_win_focus_to (TUI_SRC_WIN);
122         }
123     }
124
125
126   return;
127 }
128
129
130 /* Function to ensure that the source and/or disassemly windows
131    reflect the input address.  */
132 void
133 tui_update_source_windows_with_addr (CORE_ADDR addr)
134 {
135   if (addr != 0)
136     {
137       struct symtab_and_line sal;
138       struct tui_line_or_address l;
139       
140       switch (tui_current_layout ())
141         {
142         case DISASSEM_COMMAND:
143         case DISASSEM_DATA_COMMAND:
144           tui_show_disassem (addr);
145           break;
146         case SRC_DISASSEM_COMMAND:
147           tui_show_disassem_and_update_source (addr);
148           break;
149         default:
150           sal = find_pc_line (addr, 0);
151           l.loa = LOA_LINE;
152           l.u.line_no = sal.line;
153           tui_show_symtab_source (sal.symtab, l, FALSE);
154           break;
155         }
156     }
157   else
158     {
159       int i;
160
161       for (i = 0; i < (tui_source_windows ())->count; i++)
162         {
163           struct tui_win_info * win_info = (tui_source_windows ())->list[i];
164
165           tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
166           tui_clear_exec_info_content (win_info);
167         }
168     }
169 }
170
171 /* Function to ensure that the source and/or disassemly windows
172    reflect the input address.  */
173 void
174 tui_update_source_windows_with_line (struct symtab *s, int line)
175 {
176   CORE_ADDR pc;
177   struct tui_line_or_address l;
178   
179   switch (tui_current_layout ())
180     {
181     case DISASSEM_COMMAND:
182     case DISASSEM_DATA_COMMAND:
183       find_line_pc (s, line, &pc);
184       tui_update_source_windows_with_addr (pc);
185       break;
186     default:
187       l.loa = LOA_LINE;
188       l.u.line_no = line;
189       tui_show_symtab_source (s, l, FALSE);
190       if (tui_current_layout () == SRC_DISASSEM_COMMAND)
191         {
192           find_line_pc (s, line, &pc);
193           tui_show_disassem (pc);
194         }
195       break;
196     }
197
198   return;
199 }
200
201 void
202 tui_clear_source_content (struct tui_win_info * win_info, int display_prompt)
203 {
204   if (win_info != NULL)
205     {
206       int i;
207
208       win_info->generic.content_in_use = FALSE;
209       tui_erase_source_content (win_info, display_prompt);
210       for (i = 0; i < win_info->generic.content_size; i++)
211         {
212           struct tui_win_element * element =
213           (struct tui_win_element *) win_info->generic.content[i];
214           element->which_element.source.has_break = FALSE;
215           element->which_element.source.is_exec_point = FALSE;
216         }
217     }
218 }
219
220
221 void
222 tui_erase_source_content (struct tui_win_info * win_info, int display_prompt)
223 {
224   int x_pos;
225   int half_width = (win_info->generic.width - 2) / 2;
226
227   if (win_info->generic.handle != (WINDOW *) NULL)
228     {
229       werase (win_info->generic.handle);
230       tui_check_and_display_highlight_if_needed (win_info);
231       if (display_prompt == EMPTY_SOURCE_PROMPT)
232         {
233           char *no_src_str;
234
235           if (win_info->generic.type == SRC_WIN)
236             no_src_str = NO_SRC_STRING;
237           else
238             no_src_str = NO_DISASSEM_STRING;
239           if (strlen (no_src_str) >= half_width)
240             x_pos = 1;
241           else
242             x_pos = half_width - strlen (no_src_str);
243           mvwaddstr (win_info->generic.handle,
244                      (win_info->generic.height / 2),
245                      x_pos,
246                      no_src_str);
247
248           /* elz: added this function call to set the real contents of
249              the window to what is on the  screen, so that later calls
250              to refresh, do display
251              the correct stuff, and not the old image */
252
253           tui_set_source_content_nil (win_info, no_src_str);
254         }
255       tui_refresh_win (&win_info->generic);
256     }
257 }
258
259
260 /* Redraw the complete line of a source or disassembly window.  */
261 static void
262 tui_show_source_line (struct tui_win_info * win_info, int lineno)
263 {
264   struct tui_win_element * line;
265   int x, y;
266
267   line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
268   if (line->which_element.source.is_exec_point)
269     wattron (win_info->generic.handle, A_STANDOUT);
270
271   mvwaddstr (win_info->generic.handle, lineno, 1,
272              line->which_element.source.line);
273   if (line->which_element.source.is_exec_point)
274     wattroff (win_info->generic.handle, A_STANDOUT);
275
276   /* Clear to end of line but stop before the border.  */
277   getyx (win_info->generic.handle, y, x);
278   while (x + 1 < win_info->generic.width)
279     {
280       waddch (win_info->generic.handle, ' ');
281       getyx (win_info->generic.handle, y, x);
282     }
283 }
284
285 void
286 tui_show_source_content (struct tui_win_info * win_info)
287 {
288   if (win_info->generic.content_size > 0)
289     {
290       int lineno;
291
292       for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
293         tui_show_source_line (win_info, lineno);
294     }
295   else
296     tui_erase_source_content (win_info, TRUE);
297
298   tui_check_and_display_highlight_if_needed (win_info);
299   tui_refresh_win (&win_info->generic);
300   win_info->generic.content_in_use = TRUE;
301 }
302
303
304 /* Scroll the source forward or backward horizontally.  */
305 void
306 tui_horizontal_source_scroll (struct tui_win_info * win_info,
307                               enum tui_scroll_direction direction,
308                               int num_to_scroll)
309 {
310   if (win_info->generic.content != NULL)
311     {
312       int offset;
313       struct symtab *s;
314       struct symtab_and_line cursal = get_current_source_symtab_and_line ();
315
316       if (cursal.symtab == (struct symtab *) NULL)
317         s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
318       else
319         s = cursal.symtab;
320
321       if (direction == LEFT_SCROLL)
322         offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
323       else
324         {
325           if ((offset =
326              win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
327             offset = 0;
328         }
329       win_info->detail.source_info.horizontal_offset = offset;
330       tui_update_source_window_as_is (win_info, s,
331                                       ((struct tui_win_element *)
332                                        win_info->generic.content[0])->which_element.source.line_or_addr,
333                                       FALSE);
334     }
335
336   return;
337 }
338
339
340 /* Set or clear the has_break flag in the line whose line is line_no.  */
341 void
342 tui_set_is_exec_point_at (struct tui_line_or_address l, struct tui_win_info * win_info)
343 {
344   int changed = 0;
345   int i;
346   tui_win_content content = (tui_win_content) win_info->generic.content;
347
348   i = 0;
349   while (i < win_info->generic.content_size)
350     {
351       int new_state;
352       struct tui_line_or_address content_loa =
353         content[i]->which_element.source.line_or_addr;
354
355       gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
356       gdb_assert (content_loa.loa == LOA_LINE
357                   || content_loa.loa == LOA_ADDRESS);
358       if (content_loa.loa == l.loa
359           && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
360               || (content_loa.u.addr == l.u.addr)))
361         new_state = TRUE;
362       else
363         new_state = FALSE;
364       if (new_state != content[i]->which_element.source.is_exec_point)
365         {
366           changed++;
367           content[i]->which_element.source.is_exec_point = new_state;
368           tui_show_source_line (win_info, i + 1);
369         }
370       i++;
371     }
372   if (changed)
373     tui_refresh_win (&win_info->generic);
374 }
375
376 /* Update the execution windows to show the active breakpoints.
377    This is called whenever a breakpoint is inserted, removed or
378    has its state changed.  */
379 void
380 tui_update_all_breakpoint_info (void)
381 {
382   struct tui_list *list = tui_source_windows ();
383   int i;
384
385   for (i = 0; i < list->count; i++)
386     {
387       struct tui_win_info * win = list->list[i];
388
389       if (tui_update_breakpoint_info (win, FALSE))
390         {
391           tui_update_exec_info (win);
392         }
393     }
394 }
395
396
397 /* Scan the source window and the breakpoints to update the
398    has_break information for each line.
399    Returns 1 if something changed and the execution window
400    must be refreshed.  */
401 int
402 tui_update_breakpoint_info (struct tui_win_info * win, int current_only)
403 {
404   int i;
405   int need_refresh = 0;
406   struct tui_source_info * src = &win->detail.source_info;
407
408   for (i = 0; i < win->generic.content_size; i++)
409     {
410       struct breakpoint *bp;
411       extern struct breakpoint *breakpoint_chain;
412       int mode;
413       struct tui_source_element* line;
414
415       line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
416       if (current_only && !line->is_exec_point)
417          continue;
418
419       /* Scan each breakpoint to see if the current line has something to
420          do with it.  Identify enable/disabled breakpoints as well as
421          those that we already hit.  */
422       mode = 0;
423       for (bp = breakpoint_chain;
424            bp != (struct breakpoint *) NULL;
425            bp = bp->next)
426         {
427           gdb_assert (line->line_or_addr.loa == LOA_LINE
428                       || line->line_or_addr.loa == LOA_ADDRESS);
429           if ((win == TUI_SRC_WIN
430                && bp->source_file
431                && (strcmp (src->filename, bp->source_file) == 0)
432                && line->line_or_addr.loa == LOA_LINE
433                && bp->line_number == line->line_or_addr.u.line_no)
434               || (win == TUI_DISASM_WIN
435                   && line->line_or_addr.loa == LOA_ADDRESS
436                   && bp->loc->address == line->line_or_addr.u.addr))
437             {
438               if (bp->enable_state == bp_disabled)
439                 mode |= TUI_BP_DISABLED;
440               else
441                 mode |= TUI_BP_ENABLED;
442               if (bp->hit_count)
443                 mode |= TUI_BP_HIT;
444               if (bp->cond)
445                 mode |= TUI_BP_CONDITIONAL;
446               if (bp->type == bp_hardware_breakpoint)
447                 mode |= TUI_BP_HARDWARE;
448             }
449         }
450       if (line->has_break != mode)
451         {
452           line->has_break = mode;
453           need_refresh = 1;
454         }
455     }
456   return need_refresh;
457 }
458
459
460 /* Function to initialize the content of the execution info window,
461    based upon the input window which is either the source or
462    disassembly window.  */
463 enum tui_status
464 tui_set_exec_info_content (struct tui_win_info * win_info)
465 {
466   enum tui_status ret = TUI_SUCCESS;
467
468   if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
469     {
470       struct tui_gen_win_info * exec_info_ptr = win_info->detail.source_info.execution_info;
471
472       if (exec_info_ptr->content == NULL)
473         exec_info_ptr->content =
474           (void **) tui_alloc_content (win_info->generic.height,
475                                          exec_info_ptr->type);
476       if (exec_info_ptr->content != NULL)
477         {
478           int i;
479
480           tui_update_breakpoint_info (win_info, 1);
481           for (i = 0; i < win_info->generic.content_size; i++)
482             {
483               struct tui_win_element * element;
484               struct tui_win_element * src_element;
485               int mode;
486
487               element = (struct tui_win_element *) exec_info_ptr->content[i];
488               src_element = (struct tui_win_element *) win_info->generic.content[i];
489
490               memset(element->which_element.simple_string, ' ',
491                      sizeof(element->which_element.simple_string));
492               element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
493
494               /* Now update the exec info content based upon the state
495                  of each line as indicated by the source content.  */
496               mode = src_element->which_element.source.has_break;
497               if (mode & TUI_BP_HIT)
498                 element->which_element.simple_string[TUI_BP_HIT_POS] =
499                   (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
500               else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
501                 element->which_element.simple_string[TUI_BP_HIT_POS] =
502                   (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
503
504               if (mode & TUI_BP_ENABLED)
505                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
506               else if (mode & TUI_BP_DISABLED)
507                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
508
509               if (src_element->which_element.source.is_exec_point)
510                 element->which_element.simple_string[TUI_EXEC_POS] = '>';
511             }
512           exec_info_ptr->content_size = win_info->generic.content_size;
513         }
514       else
515         ret = TUI_FAILURE;
516     }
517
518   return ret;
519 }
520
521
522 void
523 tui_show_exec_info_content (struct tui_win_info * win_info)
524 {
525   struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
526   int cur_line;
527
528   werase (exec_info->handle);
529   tui_refresh_win (exec_info);
530   for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
531     mvwaddstr (exec_info->handle,
532                cur_line,
533                0,
534                ((struct tui_win_element *)
535                 exec_info->content[cur_line - 1])->which_element.simple_string);
536   tui_refresh_win (exec_info);
537   exec_info->content_in_use = TRUE;
538 }
539
540
541 void
542 tui_erase_exec_info_content (struct tui_win_info * win_info)
543 {
544   struct tui_gen_win_info * exec_info = win_info->detail.source_info.execution_info;
545
546   werase (exec_info->handle);
547   tui_refresh_win (exec_info);
548 }
549
550 void
551 tui_clear_exec_info_content (struct tui_win_info * win_info)
552 {
553   win_info->detail.source_info.execution_info->content_in_use = FALSE;
554   tui_erase_exec_info_content (win_info);
555
556   return;
557 }
558
559 /* Function to update the execution info window.  */
560 void
561 tui_update_exec_info (struct tui_win_info * win_info)
562 {
563   tui_set_exec_info_content (win_info);
564   tui_show_exec_info_content (win_info);
565 }
566
567 enum tui_status
568 tui_alloc_source_buffer (struct tui_win_info *win_info)
569 {
570   char *src_line_buf;
571   int i, line_width, max_lines;
572   enum tui_status ret = TUI_FAILURE;
573
574   max_lines = win_info->generic.height; /* less the highlight box */
575   line_width = win_info->generic.width - 1;
576   /*
577      ** Allocate the buffer for the source lines.  Do this only once since they
578      ** will be re-used for all source displays.  The only other time this will
579      ** be done is when a window's size changes.
580    */
581   if (win_info->generic.content == NULL)
582     {
583       src_line_buf = (char *) xmalloc ((max_lines * line_width) * sizeof (char));
584       if (src_line_buf == (char *) NULL)
585         fputs_unfiltered (
586            "Unable to Allocate Memory for Source or Disassembly Display.\n",
587                            gdb_stderr);
588       else
589         {
590           /* allocate the content list */
591           if ((win_info->generic.content =
592           (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
593             {
594               xfree (src_line_buf);
595               src_line_buf = (char *) NULL;
596               fputs_unfiltered (
597                                  "Unable to Allocate Memory for Source or Disassembly Display.\n",
598                                  gdb_stderr);
599             }
600         }
601       for (i = 0; i < max_lines; i++)
602         ((struct tui_win_element *)
603          win_info->generic.content[i])->which_element.source.line =
604           src_line_buf + (line_width * i);
605       ret = TUI_SUCCESS;
606     }
607   else
608     ret = TUI_SUCCESS;
609
610   return ret;
611 }
612
613
614 /* Answer whether the a particular line number or address is displayed
615    in the current source window.  */
616 int
617 tui_line_is_displayed (int line, struct tui_win_info * win_info,
618                        int check_threshold)
619 {
620   int is_displayed = FALSE;
621   int i, threshold;
622
623   if (check_threshold)
624     threshold = SCROLL_THRESHOLD;
625   else
626     threshold = 0;
627   i = 0;
628   while (i < win_info->generic.content_size - threshold && !is_displayed)
629     {
630       is_displayed = (((struct tui_win_element *)
631                       win_info->generic.content[i])->which_element.source.line_or_addr.loa
632                       == LOA_LINE)
633                      && (((struct tui_win_element *)
634                       win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
635                       == (int) line);
636       i++;
637     }
638
639   return is_displayed;
640 }
641
642
643 /* Answer whether the a particular line number or address is displayed
644    in the current source window.  */
645 int
646 tui_addr_is_displayed (CORE_ADDR addr, struct tui_win_info * win_info,
647                     int check_threshold)
648 {
649   int is_displayed = FALSE;
650   int i, threshold;
651
652   if (check_threshold)
653     threshold = SCROLL_THRESHOLD;
654   else
655     threshold = 0;
656   i = 0;
657   while (i < win_info->generic.content_size - threshold && !is_displayed)
658     {
659       is_displayed = (((struct tui_win_element *)
660                       win_info->generic.content[i])->which_element.source.line_or_addr.loa
661                       == LOA_ADDRESS)
662                      && (((struct tui_win_element *)
663                       win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
664                       == addr);
665       i++;
666     }
667
668   return is_displayed;
669 }
670
671
672 /*****************************************
673 ** STATIC LOCAL FUNCTIONS               **
674 ******************************************/