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