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