Update copyright year range in all GDB files
[external/binutils.git] / gdb / tui / tui-winsource.c
1 /* TUI display source/assembly window.
2
3    Copyright (C) 1998-2018 Free Software Foundation, Inc.
4
5    Contributed by Hewlett-Packard Company.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "defs.h"
23 #include <ctype.h>
24 #include "symtab.h"
25 #include "frame.h"
26 #include "breakpoint.h"
27 #include "value.h"
28 #include "source.h"
29 #include "objfiles.h"
30 #include "filenames.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 #include "gdb_curses.h"
41
42 /* Function to display the "main" routine.  */
43 void
44 tui_display_main (void)
45 {
46   if ((tui_source_windows ())->count > 0)
47     {
48       struct gdbarch *gdbarch;
49       CORE_ADDR addr;
50
51       tui_get_begin_asm_address (&gdbarch, &addr);
52       if (addr != (CORE_ADDR) 0)
53         {
54           struct symtab *s;
55
56           tui_update_source_windows_with_addr (gdbarch, addr);
57           s = find_pc_line_symtab (addr);
58           if (s != NULL)
59              tui_update_locator_fullname (symtab_to_fullname (s));
60           else
61              tui_update_locator_fullname ("??");
62         }
63     }
64 }
65
66
67
68 /* Function to display source in the source window.  This function
69    initializes the horizontal scroll to 0.  */
70 void
71 tui_update_source_window (struct tui_win_info *win_info,
72                           struct gdbarch *gdbarch,
73                           struct symtab *s,
74                           struct tui_line_or_address line_or_addr,
75                           int noerror)
76 {
77   win_info->detail.source_info.horizontal_offset = 0;
78   tui_update_source_window_as_is (win_info, gdbarch, 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, 
88                                 struct gdbarch *gdbarch,
89                                 struct symtab *s,
90                                 struct tui_line_or_address line_or_addr, 
91                                 int noerror)
92 {
93   enum tui_status ret;
94
95   if (win_info->generic.type == SRC_WIN)
96     ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
97   else
98     ret = tui_set_disassem_content (gdbarch, line_or_addr.u.addr);
99
100   if (ret == TUI_FAILURE)
101     {
102       tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
103       tui_clear_exec_info_content (win_info);
104     }
105   else
106     {
107       tui_update_breakpoint_info (win_info, 0);
108       tui_show_source_content (win_info);
109       tui_update_exec_info (win_info);
110       if (win_info->generic.type == SRC_WIN)
111         {
112           symtab_and_line sal;
113
114           sal.line = line_or_addr.u.line_no +
115             (win_info->generic.content_size - 2);
116           sal.symtab = s;
117           sal.pspace = SYMTAB_PSPACE (s);
118           set_current_source_symtab_and_line (sal);
119           /* If the focus was in the asm win, put it in the src win if
120              we don't have a split layout.  */
121           if (tui_win_with_focus () == TUI_DISASM_WIN
122               && tui_current_layout () != SRC_DISASSEM_COMMAND)
123             tui_set_win_focus_to (TUI_SRC_WIN);
124         }
125     }
126
127
128   return;
129 }
130
131
132 /* Function to ensure that the source and/or disassemly windows
133    reflect the input address.  */
134 void
135 tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
136 {
137   if (addr != 0)
138     {
139       struct symtab_and_line sal;
140       struct tui_line_or_address l;
141       
142       switch (tui_current_layout ())
143         {
144         case DISASSEM_COMMAND:
145         case DISASSEM_DATA_COMMAND:
146           tui_show_disassem (gdbarch, addr);
147           break;
148         case SRC_DISASSEM_COMMAND:
149           tui_show_disassem_and_update_source (gdbarch, addr);
150           break;
151         default:
152           sal = find_pc_line (addr, 0);
153           l.loa = LOA_LINE;
154           l.u.line_no = sal.line;
155           tui_show_symtab_source (gdbarch, sal.symtab, l, FALSE);
156           break;
157         }
158     }
159   else
160     {
161       int i;
162
163       for (i = 0; i < (tui_source_windows ())->count; i++)
164         {
165           struct tui_win_info *win_info = (tui_source_windows ())->list[i];
166
167           tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
168           tui_clear_exec_info_content (win_info);
169         }
170     }
171 }
172
173 /* Function to ensure that the source and/or disassemly windows
174    reflect the input address.  */
175 void
176 tui_update_source_windows_with_line (struct symtab *s, int line)
177 {
178   struct gdbarch *gdbarch;
179   CORE_ADDR pc;
180   struct tui_line_or_address l;
181
182   if (!s)
183     return;
184
185   gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
186
187   switch (tui_current_layout ())
188     {
189     case DISASSEM_COMMAND:
190     case DISASSEM_DATA_COMMAND:
191       find_line_pc (s, line, &pc);
192       tui_update_source_windows_with_addr (gdbarch, pc);
193       break;
194     default:
195       l.loa = LOA_LINE;
196       l.u.line_no = line;
197       tui_show_symtab_source (gdbarch, s, l, FALSE);
198       if (tui_current_layout () == SRC_DISASSEM_COMMAND)
199         {
200           find_line_pc (s, line, &pc);
201           tui_show_disassem (gdbarch, pc);
202         }
203       break;
204     }
205
206   return;
207 }
208
209 void
210 tui_clear_source_content (struct tui_win_info *win_info, 
211                           int display_prompt)
212 {
213   if (win_info != NULL)
214     {
215       int i;
216
217       win_info->generic.content_in_use = FALSE;
218       tui_erase_source_content (win_info, display_prompt);
219       for (i = 0; i < win_info->generic.content_size; i++)
220         {
221           struct tui_win_element *element = win_info->generic.content[i];
222
223           element->which_element.source.has_break = FALSE;
224           element->which_element.source.is_exec_point = FALSE;
225         }
226     }
227 }
228
229
230 void
231 tui_erase_source_content (struct tui_win_info *win_info, 
232                           int display_prompt)
233 {
234   int x_pos;
235   int half_width = (win_info->generic.width - 2) / 2;
236
237   if (win_info->generic.handle != (WINDOW *) NULL)
238     {
239       werase (win_info->generic.handle);
240       tui_check_and_display_highlight_if_needed (win_info);
241       if (display_prompt == EMPTY_SOURCE_PROMPT)
242         {
243           const char *no_src_str;
244
245           if (win_info->generic.type == SRC_WIN)
246             no_src_str = NO_SRC_STRING;
247           else
248             no_src_str = NO_DISASSEM_STRING;
249           if (strlen (no_src_str) >= half_width)
250             x_pos = 1;
251           else
252             x_pos = half_width - strlen (no_src_str);
253           mvwaddstr (win_info->generic.handle,
254                      (win_info->generic.height / 2),
255                      x_pos,
256                      (char *) no_src_str);
257
258           /* elz: Added this function call to set the real contents of
259              the window to what is on the screen, so that later calls
260              to refresh, do display the correct stuff, and not the old
261              image.  */
262
263           tui_set_source_content_nil (win_info, no_src_str);
264         }
265       tui_refresh_win (&win_info->generic);
266     }
267 }
268
269
270 /* Redraw the complete line of a source or disassembly window.  */
271 static void
272 tui_show_source_line (struct tui_win_info *win_info, int lineno)
273 {
274   struct tui_win_element *line;
275   int x;
276
277   line = win_info->generic.content[lineno - 1];
278   if (line->which_element.source.is_exec_point)
279     wattron (win_info->generic.handle, A_STANDOUT);
280
281   mvwaddstr (win_info->generic.handle, lineno, 1,
282              (char *) line->which_element.source.line);
283   if (line->which_element.source.is_exec_point)
284     wattroff (win_info->generic.handle, A_STANDOUT);
285
286   /* Clear to end of line but stop before the border.  */
287   x = getcurx (win_info->generic.handle);
288   while (x + 1 < win_info->generic.width)
289     {
290       waddch (win_info->generic.handle, ' ');
291       x = getcurx (win_info->generic.handle);
292     }
293 }
294
295 void
296 tui_show_source_content (struct tui_win_info *win_info)
297 {
298   if (win_info->generic.content_size > 0)
299     {
300       int lineno;
301
302       for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
303         tui_show_source_line (win_info, lineno);
304     }
305   else
306     tui_erase_source_content (win_info, TRUE);
307
308   tui_check_and_display_highlight_if_needed (win_info);
309   tui_refresh_win (&win_info->generic);
310   win_info->generic.content_in_use = TRUE;
311 }
312
313
314 /* Scroll the source forward or backward horizontally.  */
315 void
316 tui_horizontal_source_scroll (struct tui_win_info *win_info,
317                               enum tui_scroll_direction direction,
318                               int num_to_scroll)
319 {
320   if (win_info->generic.content != NULL)
321     {
322       struct gdbarch *gdbarch = win_info->detail.source_info.gdbarch;
323       int offset;
324       struct symtab *s = NULL;
325
326       if (win_info->generic.type == SRC_WIN)
327         {
328           struct symtab_and_line cursal
329             = get_current_source_symtab_and_line ();
330
331           if (cursal.symtab == NULL)
332             s = find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)));
333           else
334             s = cursal.symtab;
335         }
336
337       if (direction == LEFT_SCROLL)
338         offset = win_info->detail.source_info.horizontal_offset
339           + num_to_scroll;
340       else
341         {
342           offset = win_info->detail.source_info.horizontal_offset
343             - num_to_scroll;
344           if (offset < 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                                       win_info->generic.content[0]
350                                         ->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 = &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           struct bp_location *loc;
452
453           gdb_assert (line->line_or_addr.loa == LOA_LINE
454                       || line->line_or_addr.loa == LOA_ADDRESS);
455
456           for (loc = bp->loc; loc != NULL; loc = loc->next)
457             {
458               if ((win == TUI_SRC_WIN
459                    && loc->symtab != NULL
460                    && filename_cmp (src->fullname,
461                                     symtab_to_fullname (loc->symtab)) == 0
462                    && line->line_or_addr.loa == LOA_LINE
463                    && loc->line_number == line->line_or_addr.u.line_no)
464                   || (win == TUI_DISASM_WIN
465                       && line->line_or_addr.loa == LOA_ADDRESS
466                       && loc->address == line->line_or_addr.u.addr))
467                 {
468                   if (bp->enable_state == bp_disabled)
469                     mode |= TUI_BP_DISABLED;
470                   else
471                     mode |= TUI_BP_ENABLED;
472                   if (bp->hit_count)
473                     mode |= TUI_BP_HIT;
474                   if (bp->loc->cond)
475                     mode |= TUI_BP_CONDITIONAL;
476                   if (bp->type == bp_hardware_breakpoint)
477                     mode |= TUI_BP_HARDWARE;
478                 }
479             }
480         }
481       if (line->has_break != mode)
482         {
483           line->has_break = mode;
484           need_refresh = 1;
485         }
486     }
487   return need_refresh;
488 }
489
490
491 /* Function to initialize the content of the execution info window,
492    based upon the input window which is either the source or
493    disassembly window.  */
494 enum tui_status
495 tui_set_exec_info_content (struct tui_win_info *win_info)
496 {
497   enum tui_status ret = TUI_SUCCESS;
498
499   if (win_info->detail.source_info.execution_info
500       != (struct tui_gen_win_info *) NULL)
501     {
502       struct tui_gen_win_info *exec_info_ptr
503         = win_info->detail.source_info.execution_info;
504
505       if (exec_info_ptr->content == NULL)
506         exec_info_ptr->content =
507           tui_alloc_content (win_info->generic.height, exec_info_ptr->type);
508       if (exec_info_ptr->content != NULL)
509         {
510           int i;
511
512           tui_update_breakpoint_info (win_info, 1);
513           for (i = 0; i < win_info->generic.content_size; i++)
514             {
515               struct tui_win_element *element;
516               struct tui_win_element *src_element;
517               int mode;
518
519               element = exec_info_ptr->content[i];
520               src_element = win_info->generic.content[i];
521
522               memset(element->which_element.simple_string, ' ',
523                      sizeof(element->which_element.simple_string));
524               element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
525
526               /* Now update the exec info content based upon the state
527                  of each line as indicated by the source content.  */
528               mode = src_element->which_element.source.has_break;
529               if (mode & TUI_BP_HIT)
530                 element->which_element.simple_string[TUI_BP_HIT_POS] =
531                   (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
532               else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
533                 element->which_element.simple_string[TUI_BP_HIT_POS] =
534                   (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
535
536               if (mode & TUI_BP_ENABLED)
537                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
538               else if (mode & TUI_BP_DISABLED)
539                 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
540
541               if (src_element->which_element.source.is_exec_point)
542                 element->which_element.simple_string[TUI_EXEC_POS] = '>';
543             }
544           exec_info_ptr->content_size = win_info->generic.content_size;
545         }
546       else
547         ret = TUI_FAILURE;
548     }
549
550   return ret;
551 }
552
553
554 void
555 tui_show_exec_info_content (struct tui_win_info *win_info)
556 {
557   struct tui_gen_win_info *exec_info
558     = win_info->detail.source_info.execution_info;
559   int cur_line;
560
561   werase (exec_info->handle);
562   tui_refresh_win (exec_info);
563   for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
564     mvwaddstr (exec_info->handle,
565                cur_line,
566                0,
567                (char *) exec_info->content[cur_line - 1]
568                           ->which_element.simple_string);
569   tui_refresh_win (exec_info);
570   exec_info->content_in_use = TRUE;
571 }
572
573
574 void
575 tui_erase_exec_info_content (struct tui_win_info *win_info)
576 {
577   struct tui_gen_win_info *exec_info
578     = win_info->detail.source_info.execution_info;
579
580   werase (exec_info->handle);
581   tui_refresh_win (exec_info);
582 }
583
584 void
585 tui_clear_exec_info_content (struct tui_win_info *win_info)
586 {
587   win_info->detail.source_info.execution_info->content_in_use = FALSE;
588   tui_erase_exec_info_content (win_info);
589
590   return;
591 }
592
593 /* Function to update the execution info window.  */
594 void
595 tui_update_exec_info (struct tui_win_info *win_info)
596 {
597   tui_set_exec_info_content (win_info);
598   tui_show_exec_info_content (win_info);
599 }
600
601 enum tui_status
602 tui_alloc_source_buffer (struct tui_win_info *win_info)
603 {
604   char *src_line_buf;
605   int i, line_width, max_lines;
606
607   /* The window width/height includes the highlight box.  Determine actual
608      content dimensions, including string null-terminators.  */
609   max_lines = win_info->generic.height - 2;
610   line_width = win_info->generic.width - 2 + 1;
611
612   /*
613    * Allocate the buffer for the source lines.  Do this only once
614    * since they will be re-used for all source displays.  The only
615    * other time this will be done is when a window's size changes.
616    */
617   if (win_info->generic.content == NULL)
618     {
619       src_line_buf = (char *) 
620         xmalloc ((max_lines * line_width) * sizeof (char));
621       /* Allocate the content list.  */
622       win_info->generic.content = tui_alloc_content (max_lines, SRC_WIN);
623       for (i = 0; i < max_lines; i++)
624         win_info->generic.content[i]->which_element.source.line
625           = src_line_buf + (line_width * i);
626     }
627
628   return TUI_SUCCESS;
629 }
630
631
632 /* Answer whether a particular line number or address is displayed
633    in the current source window.  */
634 int
635 tui_line_is_displayed (int line, 
636                        struct tui_win_info *win_info,
637                        int check_threshold)
638 {
639   int is_displayed = FALSE;
640   int i, threshold;
641
642   if (check_threshold)
643     threshold = SCROLL_THRESHOLD;
644   else
645     threshold = 0;
646   i = 0;
647   while (i < win_info->generic.content_size - threshold
648          && !is_displayed)
649     {
650       is_displayed
651         = win_info->generic.content[i]
652             ->which_element.source.line_or_addr.loa == LOA_LINE
653           && win_info->generic.content[i]
654                ->which_element.source.line_or_addr.u.line_no == (int) line;
655       i++;
656     }
657
658   return is_displayed;
659 }
660
661
662 /* Answer whether a particular line number or address is displayed
663    in the current source window.  */
664 int
665 tui_addr_is_displayed (CORE_ADDR addr, 
666                        struct tui_win_info *win_info,
667                        int check_threshold)
668 {
669   int is_displayed = FALSE;
670   int i, threshold;
671
672   if (check_threshold)
673     threshold = SCROLL_THRESHOLD;
674   else
675     threshold = 0;
676   i = 0;
677   while (i < win_info->generic.content_size - threshold
678          && !is_displayed)
679     {
680       is_displayed
681         = win_info->generic.content[i]
682             ->which_element.source.line_or_addr.loa == LOA_ADDRESS
683           && win_info->generic.content[i]
684                ->which_element.source.line_or_addr.u.addr == addr;
685       i++;
686     }
687
688   return is_displayed;
689 }
690
691
692 /*****************************************
693 ** STATIC LOCAL FUNCTIONS               **
694 ******************************************/