]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tui/tui-winsource.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / tui / tui-winsource.c
CommitLineData
f377b406 1/* TUI display source/assembly window.
f33c6cbf 2
3666a048 3 Copyright (C) 1998-2021 Free Software Foundation, Inc.
f33c6cbf 4
f377b406
SC
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "defs.h"
23#include <ctype.h>
24#include "symtab.h"
25#include "frame.h"
26#include "breakpoint.h"
fd0407d6 27#include "value.h"
52575520 28#include "source.h"
13274fc3 29#include "objfiles.h"
a7417d46 30#include "filenames.h"
35a98237 31#include "safe-ctype.h"
c906108c 32
d7b2e967
AC
33#include "tui/tui.h"
34#include "tui/tui-data.h"
62f29fda 35#include "tui/tui-io.h"
d7b2e967
AC
36#include "tui/tui-stack.h"
37#include "tui/tui-win.h"
38#include "tui/tui-wingeneral.h"
39#include "tui/tui-winsource.h"
40#include "tui/tui-source.h"
41#include "tui/tui-disasm.h"
6a83354a 42#include "gdb_curses.h"
c906108c 43
1f393769 44/* Function to display the "main" routine. */
c906108c 45void
b4eb2452 46tui_display_main ()
c906108c 47{
3891b65e
TT
48 auto adapter = tui_source_windows ();
49 if (adapter.begin () != adapter.end ())
c906108c 50 {
13274fc3 51 struct gdbarch *gdbarch;
c906108c
SS
52 CORE_ADDR addr;
53
13274fc3 54 tui_get_begin_asm_address (&gdbarch, &addr);
c774cec6 55 if (addr != (CORE_ADDR) 0)
c906108c 56 {
34248c3a 57 struct symtab *s;
c906108c 58
13274fc3 59 tui_update_source_windows_with_addr (gdbarch, addr);
34248c3a 60 s = find_pc_line_symtab (addr);
c1b167d7 61 tui_update_locator_fullname (s);
c906108c
SS
62 }
63 }
2e17b763 64}
c906108c 65
1df2f9ef 66/* See tui-winsource.h. */
c906108c 67
1df2f9ef 68std::string
9e820dec 69tui_copy_source_line (const char **ptr, int *length)
1df2f9ef
TT
70{
71 const char *lineptr = *ptr;
72
73 /* Init the line with the line number. */
74 std::string result;
75
1df2f9ef
TT
76 int column = 0;
77 char c;
78 do
79 {
80 int skip_bytes;
81
82 c = *lineptr;
83 if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
84 {
85 /* We always have to preserve escapes. */
86 result.append (lineptr, lineptr + skip_bytes);
87 lineptr += skip_bytes;
88 continue;
89 }
517d261d
TT
90 if (c == '\0')
91 break;
1df2f9ef
TT
92
93 ++lineptr;
94 ++column;
95
96 auto process_tab = [&] ()
97 {
98 int max_tab_len = tui_tab_width;
99
100 --column;
101 for (int j = column % max_tab_len;
9e820dec 102 j < max_tab_len;
1df2f9ef 103 column++, j++)
9e820dec 104 result.push_back (' ');
1df2f9ef
TT
105 };
106
1df2f9ef
TT
107 if (c == '\n' || c == '\r' || c == '\0')
108 {
109 /* Nothing. */
110 }
35a98237
TT
111 else if (c == '\t')
112 process_tab ();
113 else if (ISCNTRL (c))
1df2f9ef
TT
114 {
115 result.push_back ('^');
116 result.push_back (c + 0100);
9e820dec 117 ++column;
1df2f9ef
TT
118 }
119 else if (c == 0177)
120 {
121 result.push_back ('^');
122 result.push_back ('?');
9e820dec 123 ++column;
1df2f9ef 124 }
1df2f9ef
TT
125 else
126 result.push_back (c);
127 }
128 while (c != '\0' && c != '\n' && c != '\r');
129
130 if (c == '\r' && *lineptr == '\n')
131 ++lineptr;
132 *ptr = lineptr;
133
9e820dec
TT
134 if (length != nullptr)
135 *length = column;
136
1df2f9ef
TT
137 return result;
138}
139
140void
141tui_source_window_base::style_changed ()
142{
143 if (tui_active && is_visible ())
144 refill ();
145}
c906108c 146
f80bda8e
AC
147/* Function to display source in the source window. This function
148 initializes the horizontal scroll to 0. */
c906108c 149void
017f9828
TT
150tui_source_window_base::update_source_window
151 (struct gdbarch *gdbarch,
9f7540a5 152 const struct symtab_and_line &sal)
c906108c 153{
432b5c40 154 m_horizontal_offset = 0;
9f7540a5 155 update_source_window_as_is (gdbarch, sal);
f80bda8e 156}
c906108c
SS
157
158
f80bda8e
AC
159/* Function to display source in the source/asm window. This function
160 shows the source as specified by the horizontal offset. */
c906108c 161void
ed8358e9
TT
162tui_source_window_base::update_source_window_as_is
163 (struct gdbarch *gdbarch,
9f7540a5 164 const struct symtab_and_line &sal)
c906108c 165{
9f7540a5 166 bool ret = set_contents (gdbarch, sal);
c906108c 167
61c33f10 168 if (!ret)
ed8358e9 169 erase_source_content ();
c906108c
SS
170 else
171 {
2ddaf614 172 update_breakpoint_info (nullptr, false);
ed8358e9
TT
173 show_source_content ();
174 update_exec_info ();
c906108c 175 }
f80bda8e 176}
c906108c
SS
177
178
f80bda8e
AC
179/* Function to ensure that the source and/or disassemly windows
180 reflect the input address. */
c906108c 181void
13274fc3 182tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 183{
88180c08 184 struct symtab_and_line sal {};
c774cec6 185 if (addr != 0)
88180c08 186 sal = find_pc_line (addr, 0);
8acfefcc 187
88180c08
TT
188 for (struct tui_source_window_base *win_info : tui_source_windows ())
189 win_info->update_source_window (gdbarch, sal);
6ba8e26f 190}
c906108c 191
5d49bf1b
TT
192/* Function to ensure that the source and/or disassembly windows
193 reflect the symtab and line. */
c906108c 194void
5d49bf1b 195tui_update_source_windows_with_line (struct symtab_and_line sal)
c906108c 196{
4f13c1c0
TT
197 struct gdbarch *gdbarch = nullptr;
198 if (sal.symtab != nullptr)
199 {
200 find_line_pc (sal.symtab, sal.line, &sal.pc);
08feed99 201 gdbarch = SYMTAB_OBJFILE (sal.symtab)->arch ();
4f13c1c0 202 }
13274fc3 203
5d49bf1b
TT
204 for (struct tui_source_window_base *win_info : tui_source_windows ())
205 win_info->update_source_window (gdbarch, sal);
f80bda8e 206}
c906108c 207
c906108c 208void
e25d2004 209tui_source_window_base::do_erase_source_content (const char *str)
c906108c 210{
6ba8e26f 211 int x_pos;
e25d2004 212 int half_width = (width - 2) / 2;
c906108c 213
432b5c40 214 m_content.clear ();
e25d2004 215 if (handle != NULL)
c906108c 216 {
7523da63 217 werase (handle.get ());
e25d2004 218 check_and_display_highlight_if_needed ();
caf0bc4e 219
e25d2004 220 if (strlen (str) >= half_width)
caf0bc4e
TT
221 x_pos = 1;
222 else
e25d2004 223 x_pos = half_width - strlen (str);
7523da63 224 mvwaddstr (handle.get (),
e25d2004 225 (height / 2),
caf0bc4e 226 x_pos,
e25d2004 227 (char *) str);
93858ad3 228
e25d2004 229 refresh_window ();
c906108c 230 }
6ba8e26f 231}
c906108c
SS
232
233
bc712bbf 234/* Redraw the complete line of a source or disassembly window. */
432b5c40
TT
235void
236tui_source_window_base::show_source_line (int lineno)
bc712bbf 237{
53e7cdba 238 struct tui_source_element *line;
bc712bbf 239
9e820dec 240 line = &m_content[lineno];
53e7cdba 241 if (line->is_exec_point)
9e820dec 242 tui_set_reverse_mode (m_pad.get (), true);
bc712bbf 243
9e820dec
TT
244 wmove (m_pad.get (), lineno, 0);
245 tui_puts (line->line.c_str (), m_pad.get ());
53e7cdba 246 if (line->is_exec_point)
9e820dec
TT
247 tui_set_reverse_mode (m_pad.get (), false);
248}
bc712bbf 249
9e820dec
TT
250/* See tui-winsource.h. */
251
252void
22cc388e 253tui_source_window_base::refresh_window ()
9e820dec 254{
22cc388e
TT
255 tui_win_info::refresh_window ();
256
9e820dec
TT
257 int pad_width = std::max (m_max_length, width);
258 int left_margin = 1 + TUI_EXECINFO_SIZE + extra_margin ();
259 int view_width = width - left_margin - 1;
260 int pad_x = std::min (pad_width - view_width, m_horizontal_offset);
261 /* Ensure that an equal number of scrolls will work if the user
262 scrolled beyond where we clip. */
263 m_horizontal_offset = pad_x;
264 prefresh (m_pad.get (), 0, pad_x, y + 1, x + left_margin,
265 y + 1 + m_content.size (), x + left_margin + view_width - 1);
bc712bbf
SC
266}
267
c906108c 268void
0bd27e07 269tui_source_window_base::show_source_content ()
c906108c 270{
432b5c40 271 gdb_assert (!m_content.empty ());
bc712bbf 272
9e820dec
TT
273 check_and_display_highlight_if_needed ();
274
275 int pad_width = std::max (m_max_length, width);
276 if (m_pad == nullptr || pad_width > getmaxx (m_pad.get ()))
277 m_pad.reset (newpad (m_content.size (), pad_width));
278
279 werase (m_pad.get ());
280 for (int lineno = 0; lineno < m_content.size (); lineno++)
432b5c40 281 show_source_line (lineno);
bc712bbf 282
0bd27e07 283 refresh_window ();
bc712bbf 284}
c906108c 285
fdb01f0c 286tui_source_window_base::tui_source_window_base ()
5104fe36 287{
432b5c40
TT
288 m_start_line_or_addr.loa = LOA_ADDRESS;
289 m_start_line_or_addr.u.addr = 0;
1df2f9ef
TT
290
291 gdb::observers::source_styling_changed.attach
292 (std::bind (&tui_source_window::style_changed, this),
293 m_observable);
5104fe36
TT
294}
295
1df2f9ef
TT
296tui_source_window_base::~tui_source_window_base ()
297{
298 gdb::observers::source_styling_changed.detach (m_observable);
299}
5104fe36 300
5104fe36
TT
301/* See tui-data.h. */
302
5104fe36
TT
303void
304tui_source_window_base::update_tab_width ()
305{
7523da63 306 werase (handle.get ());
3df505f6 307 rerender ();
5104fe36
TT
308}
309
5104fe36 310void
3df505f6 311tui_source_window_base::rerender ()
5104fe36 312{
432b5c40 313 if (!m_content.empty ())
5104fe36 314 {
5104fe36
TT
315 struct symtab_and_line cursal
316 = get_current_source_symtab_and_line ();
317
432b5c40
TT
318 if (m_start_line_or_addr.loa == LOA_LINE)
319 cursal.line = m_start_line_or_addr.u.line_no;
9f7540a5 320 else
432b5c40
TT
321 cursal.pc = m_start_line_or_addr.u.addr;
322 update_source_window (m_gdbarch, cursal);
5104fe36
TT
323 }
324 else if (deprecated_safe_get_selected_frame () != NULL)
325 {
5104fe36
TT
326 struct symtab_and_line cursal
327 = get_current_source_symtab_and_line ();
328 struct frame_info *frame = deprecated_safe_get_selected_frame ();
329 struct gdbarch *gdbarch = get_frame_arch (frame);
330
331 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
fdb01f0c 332 if (this != TUI_SRC_WIN)
9f7540a5
TT
333 find_line_pc (s, cursal.line, &cursal.pc);
334 update_source_window (gdbarch, cursal);
5104fe36 335 }
3df505f6
TT
336 else
337 erase_source_content ();
5104fe36
TT
338}
339
340/* See tui-data.h. */
341
6f11e682 342void
ad54d15b 343tui_source_window_base::refill ()
6f11e682 344{
9f7540a5 345 symtab_and_line sal {};
6f11e682 346
fdb01f0c 347 if (this == TUI_SRC_WIN)
6f11e682 348 {
9f7540a5
TT
349 sal = get_current_source_symtab_and_line ();
350 if (sal.symtab == NULL)
7c392d1d
TT
351 {
352 struct frame_info *fi = deprecated_safe_get_selected_frame ();
353 if (fi != nullptr)
354 sal = find_pc_line (get_frame_pc (fi), 0);
355 }
6f11e682
TT
356 }
357
9f7540a5
TT
358 if (sal.pspace == nullptr)
359 sal.pspace = current_program_space;
360
432b5c40
TT
361 if (m_start_line_or_addr.loa == LOA_LINE)
362 sal.line = m_start_line_or_addr.u.line_no;
9f7540a5 363 else
432b5c40 364 sal.pc = m_start_line_or_addr.u.addr;
9f7540a5 365
432b5c40 366 update_source_window_as_is (m_gdbarch, sal);
6f11e682 367}
c906108c 368
f80bda8e 369/* Scroll the source forward or backward horizontally. */
6f11e682 370
c906108c 371void
c3bd716f 372tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 373{
432b5c40 374 if (!m_content.empty ())
c906108c 375 {
432b5c40 376 int offset = m_horizontal_offset + num_to_scroll;
c3bd716f
TT
377 if (offset < 0)
378 offset = 0;
432b5c40 379 m_horizontal_offset = offset;
22cc388e 380 refresh_window ();
c906108c 381 }
6ba8e26f 382}
c906108c
SS
383
384
0598af48 385/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
386 line_no. */
387
c906108c 388void
ad54d15b 389tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 390{
02c28df0 391 bool changed = false;
c906108c 392 int i;
c906108c
SS
393
394 i = 0;
432b5c40 395 while (i < m_content.size ())
c906108c 396 {
02c28df0 397 bool new_state;
362c05fe 398 struct tui_line_or_address content_loa =
432b5c40 399 m_content[i].line_or_addr;
362c05fe 400
362c05fe
AS
401 if (content_loa.loa == l.loa
402 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
dda83cd7
SM
403 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
404 new_state = true;
c906108c 405 else
02c28df0 406 new_state = false;
432b5c40 407 if (new_state != m_content[i].is_exec_point)
dda83cd7
SM
408 {
409 changed = true;
410 m_content[i].is_exec_point = new_state;
411 }
c906108c
SS
412 i++;
413 }
00b90ae2 414 if (changed)
ad54d15b 415 refill ();
00b90ae2 416}
c906108c 417
0807ab7b
TT
418/* See tui-winsource.h. */
419
c906108c 420void
0807ab7b 421tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 422{
ad54d15b 423 for (tui_source_window_base *win : tui_source_windows ())
c906108c 424 {
2ddaf614
TT
425 if (win->update_breakpoint_info (being_deleted, false))
426 win->update_exec_info ();
c906108c 427 }
00b2bad4 428}
c906108c
SS
429
430
0807ab7b 431/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
432 information for each line.
433
0807ab7b 434 Returns true if something changed and the execution window must be
1cc6d956
MS
435 refreshed. */
436
0807ab7b 437bool
2ddaf614
TT
438tui_source_window_base::update_breakpoint_info
439 (struct breakpoint *being_deleted, bool current_only)
c906108c
SS
440{
441 int i;
0807ab7b 442 bool need_refresh = false;
c906108c 443
432b5c40 444 for (i = 0; i < m_content.size (); i++)
00b2bad4 445 {
5b6fe301 446 struct tui_source_element *line;
00b2bad4 447
432b5c40 448 line = &m_content[i];
6d012f14 449 if (current_only && !line->is_exec_point)
dda83cd7 450 continue;
00b2bad4
SC
451
452 /* Scan each breakpoint to see if the current line has something to
dda83cd7
SM
453 do with it. Identify enable/disabled breakpoints as well as
454 those that we already hit. */
0598af48 455 tui_bp_flags mode = 0;
81e6b8eb 456 iterate_over_breakpoints ([&] (breakpoint *bp) -> bool
dda83cd7 457 {
f8eba3c6
TT
458 struct bp_location *loc;
459
0807ab7b 460 if (bp == being_deleted)
81e6b8eb 461 return false;
0807ab7b 462
f8eba3c6
TT
463 for (loc = bp->loc; loc != NULL; loc = loc->next)
464 {
2ddaf614 465 if (location_matches_p (loc, i))
f8eba3c6
TT
466 {
467 if (bp->enable_state == bp_disabled)
468 mode |= TUI_BP_DISABLED;
469 else
470 mode |= TUI_BP_ENABLED;
471 if (bp->hit_count)
472 mode |= TUI_BP_HIT;
473 if (bp->loc->cond)
474 mode |= TUI_BP_CONDITIONAL;
475 if (bp->type == bp_hardware_breakpoint)
476 mode |= TUI_BP_HARDWARE;
477 }
478 }
81e6b8eb 479 return false;
dda83cd7 480 });
0598af48 481 if (line->break_mode != mode)
dda83cd7
SM
482 {
483 line->break_mode = mode;
484 need_refresh = true;
485 }
00b2bad4
SC
486 }
487 return need_refresh;
488}
c906108c 489
6ba8e26f
AC
490/* Function to initialize the content of the execution info window,
491 based upon the input window which is either the source or
492 disassembly window. */
73fbdc65 493void
5216580d 494tui_source_window_base::update_exec_info ()
c906108c 495{
2ddaf614 496 update_breakpoint_info (nullptr, true);
432b5c40 497 for (int i = 0; i < m_content.size (); i++)
098f9ed4 498 {
432b5c40 499 struct tui_source_element *src_element = &m_content[i];
5216580d 500 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
501
502 /* Now update the exec info content based upon the state
503 of each line as indicated by the source content. */
5216580d 504 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
505 if (mode & TUI_BP_HIT)
506 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
507 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
508 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
509
510 if (mode & TUI_BP_ENABLED)
511 element[TUI_BP_BREAK_POS] = '+';
512 else if (mode & TUI_BP_DISABLED)
513 element[TUI_BP_BREAK_POS] = '-';
514
515 if (src_element->is_exec_point)
516 element[TUI_EXEC_POS] = '>';
c906108c 517
7523da63 518 mvwaddstr (handle.get (), i + 1, 1, element);
9e820dec
TT
519
520 show_line_number (i);
5216580d 521 }
398fdd60 522 refresh_window ();
f80bda8e 523}