the "ambiguous linespec" series
[deliverable/binutils-gdb.git] / gdb / tui / tui-winsource.c
... / ...
CommitLineData
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. */
47void
48tui_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. */
74void
75tui_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. */
90void
91tui_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. */
139void
140tui_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. */
180void
181tui_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
214void
215tui_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
236void
237tui_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. */
277static void
278tui_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
301void
302tui_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. */
321void
322tui_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
367void
368tui_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. */
406void
407tui_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
430int
431tui_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. */
500enum tui_status
501tui_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
562void
563tui_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
582void
583tui_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
592void
593tui_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. */
602void
603tui_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
609enum tui_status
610tui_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. */
655int
656tui_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. */
686int
687tui_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******************************************/
This page took 0.027244 seconds and 4 git commands to generate.