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