1 /* TUI display source/assembly window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008,
4 2009 Free Software Foundation, Inc.
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
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.
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.
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/>. */
27 #include "breakpoint.h"
32 #include "tui/tui-data.h"
33 #include "tui/tui-stack.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-wingeneral.h"
36 #include "tui/tui-winsource.h"
37 #include "tui/tui-source.h"
38 #include "tui/tui-disasm.h"
40 #include "gdb_string.h"
41 #include "gdb_curses.h"
42 #include "gdb_assert.h"
44 /* Function to display the "main" routine. */
46 tui_display_main (void)
48 if ((tui_source_windows ())->count > 0)
52 addr = tui_get_begin_asm_address ();
53 if (addr != (CORE_ADDR) 0)
55 struct symtab_and_line sal;
57 tui_update_source_windows_with_addr (addr);
58 sal = find_pc_line (addr, 0);
60 tui_update_locator_filename (sal.symtab->filename);
62 tui_update_locator_filename ("??");
69 /* Function to display source in the source window. This function
70 initializes the horizontal scroll to 0. */
72 tui_update_source_window (struct tui_win_info *win_info,
74 struct tui_line_or_address line_or_addr,
77 win_info->detail.source_info.horizontal_offset = 0;
78 tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
84 /* Function to display source in the source/asm window. This function
85 shows the source as specified by the horizontal offset. */
87 tui_update_source_window_as_is (struct tui_win_info *win_info,
89 struct tui_line_or_address line_or_addr,
94 if (win_info->generic.type == SRC_WIN)
95 ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
97 ret = tui_set_disassem_content (line_or_addr.u.addr);
99 if (ret == TUI_FAILURE)
101 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
102 tui_clear_exec_info_content (win_info);
106 tui_update_breakpoint_info (win_info, 0);
107 tui_show_source_content (win_info);
108 tui_update_exec_info (win_info);
109 if (win_info->generic.type == SRC_WIN)
111 struct symtab_and_line sal;
113 sal.line = line_or_addr.u.line_no +
114 (win_info->generic.content_size - 2);
116 set_current_source_symtab_and_line (&sal);
117 /* If the focus was in the asm win, put it in the src win if
118 we don't have a split layout. */
119 if (tui_win_with_focus () == TUI_DISASM_WIN
120 && tui_current_layout () != SRC_DISASSEM_COMMAND)
121 tui_set_win_focus_to (TUI_SRC_WIN);
130 /* Function to ensure that the source and/or disassemly windows
131 reflect the input address. */
133 tui_update_source_windows_with_addr (CORE_ADDR addr)
137 struct symtab_and_line sal;
138 struct tui_line_or_address l;
140 switch (tui_current_layout ())
142 case DISASSEM_COMMAND:
143 case DISASSEM_DATA_COMMAND:
144 tui_show_disassem (addr);
146 case SRC_DISASSEM_COMMAND:
147 tui_show_disassem_and_update_source (addr);
150 sal = find_pc_line (addr, 0);
152 l.u.line_no = sal.line;
153 tui_show_symtab_source (sal.symtab, l, FALSE);
161 for (i = 0; i < (tui_source_windows ())->count; i++)
163 struct tui_win_info *win_info = (tui_source_windows ())->list[i];
165 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
166 tui_clear_exec_info_content (win_info);
171 /* Function to ensure that the source and/or disassemly windows
172 reflect the input address. */
174 tui_update_source_windows_with_line (struct symtab *s, int line)
177 struct tui_line_or_address l;
179 switch (tui_current_layout ())
181 case DISASSEM_COMMAND:
182 case DISASSEM_DATA_COMMAND:
183 find_line_pc (s, line, &pc);
184 tui_update_source_windows_with_addr (pc);
189 tui_show_symtab_source (s, l, FALSE);
190 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
192 find_line_pc (s, line, &pc);
193 tui_show_disassem (pc);
202 tui_clear_source_content (struct tui_win_info *win_info,
205 if (win_info != NULL)
209 win_info->generic.content_in_use = FALSE;
210 tui_erase_source_content (win_info, display_prompt);
211 for (i = 0; i < win_info->generic.content_size; i++)
213 struct tui_win_element *element =
214 (struct tui_win_element *) win_info->generic.content[i];
215 element->which_element.source.has_break = FALSE;
216 element->which_element.source.is_exec_point = FALSE;
223 tui_erase_source_content (struct tui_win_info *win_info,
227 int half_width = (win_info->generic.width - 2) / 2;
229 if (win_info->generic.handle != (WINDOW *) NULL)
231 werase (win_info->generic.handle);
232 tui_check_and_display_highlight_if_needed (win_info);
233 if (display_prompt == EMPTY_SOURCE_PROMPT)
237 if (win_info->generic.type == SRC_WIN)
238 no_src_str = NO_SRC_STRING;
240 no_src_str = NO_DISASSEM_STRING;
241 if (strlen (no_src_str) >= half_width)
244 x_pos = half_width - strlen (no_src_str);
245 mvwaddstr (win_info->generic.handle,
246 (win_info->generic.height / 2),
250 /* elz: Added this function call to set the real contents of
251 the window to what is on the screen, so that later calls
252 to refresh, do display the correct stuff, and not the old
255 tui_set_source_content_nil (win_info, no_src_str);
257 tui_refresh_win (&win_info->generic);
262 /* Redraw the complete line of a source or disassembly window. */
264 tui_show_source_line (struct tui_win_info *win_info, int lineno)
266 struct tui_win_element *line;
269 line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
270 if (line->which_element.source.is_exec_point)
271 wattron (win_info->generic.handle, A_STANDOUT);
273 mvwaddstr (win_info->generic.handle, lineno, 1,
274 line->which_element.source.line);
275 if (line->which_element.source.is_exec_point)
276 wattroff (win_info->generic.handle, A_STANDOUT);
278 /* Clear to end of line but stop before the border. */
279 getyx (win_info->generic.handle, y, x);
280 while (x + 1 < win_info->generic.width)
282 waddch (win_info->generic.handle, ' ');
283 getyx (win_info->generic.handle, y, x);
288 tui_show_source_content (struct tui_win_info *win_info)
290 if (win_info->generic.content_size > 0)
294 for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
295 tui_show_source_line (win_info, lineno);
298 tui_erase_source_content (win_info, TRUE);
300 tui_check_and_display_highlight_if_needed (win_info);
301 tui_refresh_win (&win_info->generic);
302 win_info->generic.content_in_use = TRUE;
306 /* Scroll the source forward or backward horizontally. */
308 tui_horizontal_source_scroll (struct tui_win_info *win_info,
309 enum tui_scroll_direction direction,
312 if (win_info->generic.content != NULL)
316 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
318 if (cursal.symtab == (struct symtab *) NULL)
319 s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
323 if (direction == LEFT_SCROLL)
324 offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
328 win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
331 win_info->detail.source_info.horizontal_offset = offset;
332 tui_update_source_window_as_is (win_info, s,
333 ((struct tui_win_element *)
334 win_info->generic.content[0])->which_element.source.line_or_addr,
342 /* Set or clear the has_break flag in the line whose line is
346 tui_set_is_exec_point_at (struct tui_line_or_address l,
347 struct tui_win_info *win_info)
351 tui_win_content content = (tui_win_content) win_info->generic.content;
354 while (i < win_info->generic.content_size)
357 struct tui_line_or_address content_loa =
358 content[i]->which_element.source.line_or_addr;
360 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
361 gdb_assert (content_loa.loa == LOA_LINE
362 || content_loa.loa == LOA_ADDRESS);
363 if (content_loa.loa == l.loa
364 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
365 || (content_loa.u.addr == l.u.addr)))
369 if (new_state != content[i]->which_element.source.is_exec_point)
372 content[i]->which_element.source.is_exec_point = new_state;
373 tui_show_source_line (win_info, i + 1);
378 tui_refresh_win (&win_info->generic);
381 /* Update the execution windows to show the active breakpoints.
382 This is called whenever a breakpoint is inserted, removed or
383 has its state changed. */
385 tui_update_all_breakpoint_info (void)
387 struct tui_list *list = tui_source_windows ();
390 for (i = 0; i < list->count; i++)
392 struct tui_win_info *win = list->list[i];
394 if (tui_update_breakpoint_info (win, FALSE))
396 tui_update_exec_info (win);
402 /* Scan the source window and the breakpoints to update the has_break
403 information for each line.
405 Returns 1 if something changed and the execution window must be
409 tui_update_breakpoint_info (struct tui_win_info *win,
413 int need_refresh = 0;
414 struct tui_source_info *src = &win->detail.source_info;
416 for (i = 0; i < win->generic.content_size; i++)
418 struct breakpoint *bp;
419 extern struct breakpoint *breakpoint_chain;
421 struct tui_source_element *line;
423 line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
424 if (current_only && !line->is_exec_point)
427 /* Scan each breakpoint to see if the current line has something to
428 do with it. Identify enable/disabled breakpoints as well as
429 those that we already hit. */
431 for (bp = breakpoint_chain;
432 bp != (struct breakpoint *) NULL;
435 gdb_assert (line->line_or_addr.loa == LOA_LINE
436 || line->line_or_addr.loa == LOA_ADDRESS);
437 if ((win == TUI_SRC_WIN
439 && (strcmp (src->filename, bp->source_file) == 0)
440 && line->line_or_addr.loa == LOA_LINE
441 && bp->line_number == line->line_or_addr.u.line_no)
442 || (win == TUI_DISASM_WIN
443 && line->line_or_addr.loa == LOA_ADDRESS
445 && bp->loc->address == line->line_or_addr.u.addr))
447 if (bp->enable_state == bp_disabled)
448 mode |= TUI_BP_DISABLED;
450 mode |= TUI_BP_ENABLED;
454 mode |= TUI_BP_CONDITIONAL;
455 if (bp->type == bp_hardware_breakpoint)
456 mode |= TUI_BP_HARDWARE;
459 if (line->has_break != mode)
461 line->has_break = mode;
469 /* Function to initialize the content of the execution info window,
470 based upon the input window which is either the source or
471 disassembly window. */
473 tui_set_exec_info_content (struct tui_win_info *win_info)
475 enum tui_status ret = TUI_SUCCESS;
477 if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
479 struct tui_gen_win_info *exec_info_ptr = win_info->detail.source_info.execution_info;
481 if (exec_info_ptr->content == NULL)
482 exec_info_ptr->content =
483 (void **) tui_alloc_content (win_info->generic.height,
484 exec_info_ptr->type);
485 if (exec_info_ptr->content != NULL)
489 tui_update_breakpoint_info (win_info, 1);
490 for (i = 0; i < win_info->generic.content_size; i++)
492 struct tui_win_element *element;
493 struct tui_win_element *src_element;
496 element = (struct tui_win_element *) exec_info_ptr->content[i];
497 src_element = (struct tui_win_element *) win_info->generic.content[i];
499 memset(element->which_element.simple_string, ' ',
500 sizeof(element->which_element.simple_string));
501 element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
503 /* Now update the exec info content based upon the state
504 of each line as indicated by the source content. */
505 mode = src_element->which_element.source.has_break;
506 if (mode & TUI_BP_HIT)
507 element->which_element.simple_string[TUI_BP_HIT_POS] =
508 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
509 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
510 element->which_element.simple_string[TUI_BP_HIT_POS] =
511 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
513 if (mode & TUI_BP_ENABLED)
514 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
515 else if (mode & TUI_BP_DISABLED)
516 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
518 if (src_element->which_element.source.is_exec_point)
519 element->which_element.simple_string[TUI_EXEC_POS] = '>';
521 exec_info_ptr->content_size = win_info->generic.content_size;
532 tui_show_exec_info_content (struct tui_win_info *win_info)
534 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
537 werase (exec_info->handle);
538 tui_refresh_win (exec_info);
539 for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
540 mvwaddstr (exec_info->handle,
543 ((struct tui_win_element *)
544 exec_info->content[cur_line - 1])->which_element.simple_string);
545 tui_refresh_win (exec_info);
546 exec_info->content_in_use = TRUE;
551 tui_erase_exec_info_content (struct tui_win_info *win_info)
553 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
555 werase (exec_info->handle);
556 tui_refresh_win (exec_info);
560 tui_clear_exec_info_content (struct tui_win_info *win_info)
562 win_info->detail.source_info.execution_info->content_in_use = FALSE;
563 tui_erase_exec_info_content (win_info);
568 /* Function to update the execution info window. */
570 tui_update_exec_info (struct tui_win_info *win_info)
572 tui_set_exec_info_content (win_info);
573 tui_show_exec_info_content (win_info);
577 tui_alloc_source_buffer (struct tui_win_info *win_info)
580 int i, line_width, max_lines;
582 max_lines = win_info->generic.height; /* Less the highlight box. */
583 line_width = win_info->generic.width - 1;
585 * Allocate the buffer for the source lines. Do this only once
586 * since they will be re-used for all source displays. The only
587 * other time this will be done is when a window's size changes.
589 if (win_info->generic.content == NULL)
591 src_line_buf = (char *)
592 xmalloc ((max_lines * line_width) * sizeof (char));
593 if (src_line_buf == (char *) NULL)
595 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
599 /* Allocate the content list. */
600 if ((win_info->generic.content =
601 (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
603 xfree (src_line_buf);
604 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
608 for (i = 0; i < max_lines; i++)
609 ((struct tui_win_element *)
610 win_info->generic.content[i])->which_element.source.line =
611 src_line_buf + (line_width * i);
618 /* Answer whether the a particular line number or address is displayed
619 in the current source window. */
621 tui_line_is_displayed (int line,
622 struct tui_win_info *win_info,
625 int is_displayed = FALSE;
629 threshold = SCROLL_THRESHOLD;
633 while (i < win_info->generic.content_size - threshold
636 is_displayed = (((struct tui_win_element *)
637 win_info->generic.content[i])->which_element.source.line_or_addr.loa
639 && (((struct tui_win_element *)
640 win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
649 /* Answer whether the a particular line number or address is displayed
650 in the current source window. */
652 tui_addr_is_displayed (CORE_ADDR addr,
653 struct tui_win_info *win_info,
656 int is_displayed = FALSE;
660 threshold = SCROLL_THRESHOLD;
664 while (i < win_info->generic.content_size - threshold
667 is_displayed = (((struct tui_win_element *)
668 win_info->generic.content[i])->which_element.source.line_or_addr.loa
670 && (((struct tui_win_element *)
671 win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
680 /*****************************************
681 ** STATIC LOCAL FUNCTIONS **
682 ******************************************/