1 /* TUI display source/assembly window.
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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.
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.
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/>. */
26 #include "breakpoint.h"
30 #include "filenames.h"
33 #include "tui/tui-data.h"
34 #include "tui/tui-io.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 #include "gdb_curses.h"
43 /* Function to display the "main" routine. */
47 if (!tui_source_windows ().empty ())
49 struct gdbarch
*gdbarch
;
52 tui_get_begin_asm_address (&gdbarch
, &addr
);
53 if (addr
!= (CORE_ADDR
) 0)
57 tui_update_source_windows_with_addr (gdbarch
, addr
);
58 s
= find_pc_line_symtab (addr
);
60 tui_update_locator_fullname (symtab_to_fullname (s
));
62 tui_update_locator_fullname ("??");
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_source_window_base
*win_info
,
73 struct gdbarch
*gdbarch
,
75 struct tui_line_or_address line_or_addr
,
78 win_info
->horizontal_offset
= 0;
79 tui_update_source_window_as_is (win_info
, gdbarch
, s
, line_or_addr
, noerror
);
85 /* Function to display source in the source/asm window. This function
86 shows the source as specified by the horizontal offset. */
88 tui_update_source_window_as_is (struct tui_source_window_base
*win_info
,
89 struct gdbarch
*gdbarch
,
91 struct tui_line_or_address line_or_addr
,
96 if (win_info
->type
== SRC_WIN
)
97 ret
= tui_set_source_content (win_info
, s
, line_or_addr
.u
.line_no
,
100 ret
= tui_set_disassem_content (win_info
, gdbarch
, line_or_addr
.u
.addr
);
102 if (ret
== TUI_FAILURE
)
104 tui_clear_source_content (win_info
);
105 tui_clear_exec_info_content (win_info
);
109 tui_update_breakpoint_info (win_info
, nullptr, false);
110 tui_show_source_content (win_info
);
111 tui_update_exec_info (win_info
);
112 if (win_info
->type
== SRC_WIN
)
116 sal
.line
= line_or_addr
.u
.line_no
+
117 (win_info
->content
.size () - 2);
119 sal
.pspace
= SYMTAB_PSPACE (s
);
120 set_current_source_symtab_and_line (sal
);
121 /* If the focus was in the asm win, put it in the src win if
122 we don't have a split layout. */
123 if (tui_win_with_focus () == TUI_DISASM_WIN
124 && tui_current_layout () != SRC_DISASSEM_COMMAND
)
125 tui_set_win_focus_to (win_info
);
134 /* Function to ensure that the source and/or disassemly windows
135 reflect the input address. */
137 tui_update_source_windows_with_addr (struct gdbarch
*gdbarch
, CORE_ADDR addr
)
141 struct symtab_and_line sal
;
142 struct tui_line_or_address l
;
144 switch (tui_current_layout ())
146 case DISASSEM_COMMAND
:
147 case DISASSEM_DATA_COMMAND
:
148 tui_show_disassem (gdbarch
, addr
);
150 case SRC_DISASSEM_COMMAND
:
151 tui_show_disassem_and_update_source (gdbarch
, addr
);
154 sal
= find_pc_line (addr
, 0);
156 l
.u
.line_no
= sal
.line
;
157 tui_show_symtab_source (TUI_SRC_WIN
, gdbarch
, sal
.symtab
, l
, FALSE
);
163 for (struct tui_source_window_base
*win_info
: tui_source_windows ())
165 tui_clear_source_content (win_info
);
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
)
176 struct gdbarch
*gdbarch
;
178 struct tui_line_or_address l
;
183 gdbarch
= get_objfile_arch (SYMTAB_OBJFILE (s
));
185 switch (tui_current_layout ())
187 case DISASSEM_COMMAND
:
188 case DISASSEM_DATA_COMMAND
:
189 find_line_pc (s
, line
, &pc
);
190 tui_update_source_windows_with_addr (gdbarch
, pc
);
195 tui_show_symtab_source (TUI_SRC_WIN
, gdbarch
, s
, l
, FALSE
);
196 if (tui_current_layout () == SRC_DISASSEM_COMMAND
)
198 find_line_pc (s
, line
, &pc
);
199 tui_show_disassem (gdbarch
, pc
);
208 tui_clear_source_content (struct tui_source_window_base
*win_info
)
210 if (win_info
!= NULL
)
214 win_info
->content_in_use
= false;
215 tui_erase_source_content (win_info
);
216 for (i
= 0; i
< win_info
->content
.size (); i
++)
218 struct tui_source_element
*element
= &win_info
->content
[i
];
220 element
->break_mode
= 0;
221 element
->is_exec_point
= false;
228 tui_erase_source_content (struct tui_source_window_base
*win_info
)
231 int half_width
= (win_info
->width
- 2) / 2;
233 if (win_info
->handle
!= NULL
)
235 werase (win_info
->handle
);
236 tui_check_and_display_highlight_if_needed (win_info
);
238 const char *no_src_str
;
240 if (win_info
->type
== SRC_WIN
)
241 no_src_str
= NO_SRC_STRING
;
243 no_src_str
= NO_DISASSEM_STRING
;
244 if (strlen (no_src_str
) >= half_width
)
247 x_pos
= half_width
- strlen (no_src_str
);
248 mvwaddstr (win_info
->handle
,
249 (win_info
->height
/ 2),
251 (char *) no_src_str
);
253 /* elz: Added this function call to set the real contents of
254 the window to what is on the screen, so that later calls
255 to refresh, do display the correct stuff, and not the old
258 tui_set_source_content_nil (win_info
, no_src_str
);
260 win_info
->refresh_window ();
265 /* Redraw the complete line of a source or disassembly window. */
267 tui_show_source_line (struct tui_source_window_base
*win_info
, int lineno
)
269 struct tui_source_element
*line
;
272 line
= &win_info
->content
[lineno
- 1];
273 if (line
->is_exec_point
)
274 tui_set_reverse_mode (win_info
->handle
, true);
276 wmove (win_info
->handle
, lineno
, 1);
277 tui_puts (line
->line
,
279 if (line
->is_exec_point
)
280 tui_set_reverse_mode (win_info
->handle
, false);
282 /* Clear to end of line but stop before the border. */
283 x
= getcurx (win_info
->handle
);
284 while (x
+ 1 < win_info
->width
)
286 waddch (win_info
->handle
, ' ');
287 x
= getcurx (win_info
->handle
);
292 tui_show_source_content (struct tui_source_window_base
*win_info
)
294 if (!win_info
->content
.empty ())
298 for (lineno
= 1; lineno
<= win_info
->content
.size (); lineno
++)
299 tui_show_source_line (win_info
, lineno
);
302 tui_erase_source_content (win_info
);
304 tui_check_and_display_highlight_if_needed (win_info
);
305 win_info
->refresh_window ();
306 win_info
->content_in_use
= true;
309 /* See tui-data.h. */
312 tui_source_window_base::refill ()
318 symtab_and_line cursal
= get_current_source_symtab_and_line ();
319 s
= (cursal
.symtab
== NULL
320 ? find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL
)))
324 tui_update_source_window_as_is (this, gdbarch
, s
,
325 content
[0].line_or_addr
,
329 /* Scroll the source forward or backward horizontally. */
332 tui_source_window_base::do_scroll_horizontal (int num_to_scroll
)
334 if (!content
.empty ())
336 int offset
= horizontal_offset
+ num_to_scroll
;
339 horizontal_offset
= offset
;
345 /* Set or clear the is_exec_point flag in the line whose line is
349 tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l
)
351 bool changed
= false;
355 while (i
< content
.size ())
358 struct tui_line_or_address content_loa
=
359 content
[i
].line_or_addr
;
361 gdb_assert (l
.loa
== LOA_ADDRESS
|| l
.loa
== LOA_LINE
);
362 gdb_assert (content_loa
.loa
== LOA_LINE
363 || content_loa
.loa
== LOA_ADDRESS
);
364 if (content_loa
.loa
== l
.loa
365 && ((l
.loa
== LOA_LINE
&& content_loa
.u
.line_no
== l
.u
.line_no
)
366 || (l
.loa
== LOA_ADDRESS
&& content_loa
.u
.addr
== l
.u
.addr
)))
370 if (new_state
!= content
[i
].is_exec_point
)
373 content
[i
].is_exec_point
= new_state
;
374 tui_show_source_line (this, i
+ 1);
382 /* See tui-winsource.h. */
385 tui_update_all_breakpoint_info (struct breakpoint
*being_deleted
)
387 for (tui_source_window_base
*win
: tui_source_windows ())
389 if (tui_update_breakpoint_info (win
, being_deleted
, false))
391 tui_update_exec_info (win
);
397 /* Scan the source window and the breakpoints to update the break_mode
398 information for each line.
400 Returns true if something changed and the execution window must be
404 tui_update_breakpoint_info (struct tui_source_window_base
*win
,
405 struct breakpoint
*being_deleted
,
409 bool need_refresh
= false;
411 for (i
= 0; i
< win
->content
.size (); i
++)
413 struct breakpoint
*bp
;
414 extern struct breakpoint
*breakpoint_chain
;
415 struct tui_source_element
*line
;
417 line
= &win
->content
[i
];
418 if (current_only
&& !line
->is_exec_point
)
421 /* Scan each breakpoint to see if the current line has something to
422 do with it. Identify enable/disabled breakpoints as well as
423 those that we already hit. */
424 tui_bp_flags mode
= 0;
425 for (bp
= breakpoint_chain
;
429 struct bp_location
*loc
;
431 gdb_assert (line
->line_or_addr
.loa
== LOA_LINE
432 || line
->line_or_addr
.loa
== LOA_ADDRESS
);
434 if (bp
== being_deleted
)
437 for (loc
= bp
->loc
; loc
!= NULL
; loc
= loc
->next
)
439 if (win
->location_matches_p (loc
, i
))
441 if (bp
->enable_state
== bp_disabled
)
442 mode
|= TUI_BP_DISABLED
;
444 mode
|= TUI_BP_ENABLED
;
448 mode
|= TUI_BP_CONDITIONAL
;
449 if (bp
->type
== bp_hardware_breakpoint
)
450 mode
|= TUI_BP_HARDWARE
;
454 if (line
->break_mode
!= mode
)
456 line
->break_mode
= mode
;
463 /* See tui-data.h. */
465 tui_exec_info_content
*
466 tui_exec_info_window::maybe_allocate_content (int n_elements
)
468 if (m_content
== nullptr)
469 m_content
= XNEWVEC (tui_exec_info_content
, n_elements
);
474 /* Function to initialize the content of the execution info window,
475 based upon the input window which is either the source or
476 disassembly window. */
478 tui_set_exec_info_content (struct tui_source_window_base
*win_info
)
480 if (win_info
->execution_info
!= NULL
)
482 tui_exec_info_content
*content
483 = win_info
->execution_info
->maybe_allocate_content (win_info
->height
);
485 tui_update_breakpoint_info (win_info
, nullptr, true);
486 for (int i
= 0; i
< win_info
->content
.size (); i
++)
488 tui_exec_info_content
&element
= content
[i
];
489 struct tui_source_element
*src_element
;
492 src_element
= &win_info
->content
[i
];
494 memset (element
, ' ', sizeof (tui_exec_info_content
));
495 element
[TUI_EXECINFO_SIZE
- 1] = 0;
497 /* Now update the exec info content based upon the state
498 of each line as indicated by the source content. */
499 mode
= src_element
->break_mode
;
500 if (mode
& TUI_BP_HIT
)
501 element
[TUI_BP_HIT_POS
] = (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
502 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
503 element
[TUI_BP_HIT_POS
] = (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
505 if (mode
& TUI_BP_ENABLED
)
506 element
[TUI_BP_BREAK_POS
] = '+';
507 else if (mode
& TUI_BP_DISABLED
)
508 element
[TUI_BP_BREAK_POS
] = '-';
510 if (src_element
->is_exec_point
)
511 element
[TUI_EXEC_POS
] = '>';
518 tui_show_exec_info_content (struct tui_source_window_base
*win_info
)
520 struct tui_exec_info_window
*exec_info
= win_info
->execution_info
;
521 const tui_exec_info_content
*content
= exec_info
->get_content ();
523 werase (exec_info
->handle
);
524 exec_info
->refresh_window ();
525 for (int cur_line
= 1; cur_line
<= win_info
->content
.size (); cur_line
++)
526 mvwaddstr (exec_info
->handle
,
529 content
[cur_line
- 1]);
530 exec_info
->refresh_window ();
535 tui_erase_exec_info_content (struct tui_source_window_base
*win_info
)
537 struct tui_gen_win_info
*exec_info
= win_info
->execution_info
;
539 werase (exec_info
->handle
);
540 exec_info
->refresh_window ();
544 tui_clear_exec_info_content (struct tui_source_window_base
*win_info
)
546 tui_erase_exec_info_content (win_info
);
549 /* Function to update the execution info window. */
551 tui_update_exec_info (struct tui_source_window_base
*win_info
)
553 tui_set_exec_info_content (win_info
);
554 tui_show_exec_info_content (win_info
);
558 tui_alloc_source_buffer (struct tui_source_window_base
*win_info
)
560 int i
, line_width
, max_lines
;
562 /* The window width/height includes the highlight box. Determine actual
563 content dimensions, including string null-terminators. */
564 max_lines
= win_info
->height
- 2;
565 line_width
= win_info
->width
- 2 + 1;
567 /* Allocate the buffer for the source lines. */
568 win_info
->content
.resize (max_lines
);
569 for (i
= 0; i
< max_lines
; i
++)
571 if (win_info
->content
[i
].line
== nullptr)
572 win_info
->content
[i
].line
= (char *) xmalloc (line_width
);
577 /* Answer whether a particular line number or address is displayed
578 in the current source window. */
580 tui_line_is_displayed (int line
,
581 struct tui_source_window_base
*win_info
,
584 int is_displayed
= FALSE
;
588 threshold
= SCROLL_THRESHOLD
;
592 while (i
< win_info
->content
.size () - threshold
596 = win_info
->content
[i
].line_or_addr
.loa
== LOA_LINE
597 && win_info
->content
[i
].line_or_addr
.u
.line_no
== line
;
605 /* Answer whether a particular line number or address is displayed
606 in the current source window. */
608 tui_addr_is_displayed (CORE_ADDR addr
,
609 struct tui_source_window_base
*win_info
,
612 int is_displayed
= FALSE
;
616 threshold
= SCROLL_THRESHOLD
;
620 while (i
< win_info
->content
.size () - threshold
624 = win_info
->content
[i
].line_or_addr
.loa
== LOA_ADDRESS
625 && win_info
->content
[i
].line_or_addr
.u
.addr
== addr
;
633 /*****************************************
634 ** STATIC LOCAL FUNCTIONS **
635 ******************************************/