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