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