Use symtab_and_line when updating TUI windows
[deliverable/binutils-gdb.git] / gdb / tui / tui-winsource.c
CommitLineData
f377b406 1/* TUI display source/assembly window.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 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{
017f9828 172 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 ();
193 if (type == SRC_WIN)
c906108c 194 {
9f7540a5 195 symtab_and_line new_sal = sal;
51abb421 196
9f7540a5
TT
197 new_sal.line = sal.line + (content.size () - 2);
198 set_current_source_symtab_and_line (new_sal);
c906108c
SS
199 }
200 }
f80bda8e 201}
c906108c
SS
202
203
f80bda8e
AC
204/* Function to ensure that the source and/or disassemly windows
205 reflect the input address. */
c906108c 206void
13274fc3 207tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 208{
c774cec6 209 if (addr != 0)
c906108c 210 {
855f89b3 211 struct symtab_and_line sal = find_pc_line (addr, 0);
a4b99e53 212
8acfefcc 213 if (TUI_DISASM_WIN != nullptr)
9f7540a5 214 TUI_DISASM_WIN->update_source_window (gdbarch, sal);
8acfefcc
TT
215
216 if (TUI_SRC_WIN != nullptr)
9f7540a5 217 TUI_SRC_WIN->update_source_window (gdbarch, sal);
c906108c
SS
218 }
219 else
220 {
ad54d15b 221 for (struct tui_source_window_base *win_info : tui_source_windows ())
c398c3d0 222 win_info->erase_source_content ();
c906108c 223 }
6ba8e26f 224}
c906108c 225
f80bda8e
AC
226/* Function to ensure that the source and/or disassemly windows
227 reflect the input address. */
c906108c 228void
f80bda8e 229tui_update_source_windows_with_line (struct symtab *s, int line)
c906108c 230{
13274fc3 231 struct gdbarch *gdbarch;
84b1e7c7 232 CORE_ADDR pc;
9f7540a5 233 struct symtab_and_line sal;
13274fc3
UW
234
235 if (!s)
236 return;
237
9f7540a5
TT
238 sal.pspace = current_program_space;
239 sal.symtab = s;
240 sal.line = line;
241
eb822aa6 242 gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
13274fc3 243
dd1abb8c 244 switch (tui_current_layout ())
c906108c
SS
245 {
246 case DISASSEM_COMMAND:
247 case DISASSEM_DATA_COMMAND:
84b1e7c7 248 find_line_pc (s, line, &pc);
13274fc3 249 tui_update_source_windows_with_addr (gdbarch, pc);
c906108c
SS
250 break;
251 default:
9f7540a5
TT
252 find_line_pc (s, line, &pc);
253 sal.pc = pc;
254 TUI_SRC_WIN->update_source_window (gdbarch, sal);
dd1abb8c 255 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
9f7540a5 256 TUI_DISASM_WIN->update_source_window (gdbarch, sal);
c906108c
SS
257 break;
258 }
f80bda8e 259}
c906108c 260
c906108c 261void
e25d2004 262tui_source_window_base::do_erase_source_content (const char *str)
c906108c 263{
6ba8e26f 264 int x_pos;
e25d2004 265 int half_width = (width - 2) / 2;
c906108c 266
c398c3d0 267 content.clear ();
e25d2004 268 if (handle != NULL)
c906108c 269 {
7523da63 270 werase (handle.get ());
e25d2004 271 check_and_display_highlight_if_needed ();
caf0bc4e 272
e25d2004 273 if (strlen (str) >= half_width)
caf0bc4e
TT
274 x_pos = 1;
275 else
e25d2004 276 x_pos = half_width - strlen (str);
7523da63 277 mvwaddstr (handle.get (),
e25d2004 278 (height / 2),
caf0bc4e 279 x_pos,
e25d2004 280 (char *) str);
93858ad3 281
e25d2004 282 refresh_window ();
c906108c 283 }
6ba8e26f 284}
c906108c
SS
285
286
bc712bbf
SC
287/* Redraw the complete line of a source or disassembly window. */
288static void
53e7cdba 289tui_show_source_line (struct tui_source_window_base *win_info, int lineno)
bc712bbf 290{
53e7cdba 291 struct tui_source_element *line;
798e1c30 292 int x;
bc712bbf 293
53e7cdba
TT
294 line = &win_info->content[lineno - 1];
295 if (line->is_exec_point)
7523da63 296 tui_set_reverse_mode (win_info->handle.get (), true);
bc712bbf 297
7523da63 298 wmove (win_info->handle.get (), lineno, TUI_EXECINFO_SIZE);
5d051055 299 tui_puts (line->line.c_str (), win_info->handle.get ());
53e7cdba 300 if (line->is_exec_point)
7523da63 301 tui_set_reverse_mode (win_info->handle.get (), false);
bc712bbf
SC
302
303 /* Clear to end of line but stop before the border. */
7523da63 304 x = getcurx (win_info->handle.get ());
cb2ce893 305 while (x + 1 < win_info->width)
798e1c30 306 {
7523da63
TT
307 waddch (win_info->handle.get (), ' ');
308 x = getcurx (win_info->handle.get ());
798e1c30 309 }
bc712bbf
SC
310}
311
c906108c 312void
0bd27e07 313tui_source_window_base::show_source_content ()
c906108c 314{
2ad52f6f 315 gdb_assert (!content.empty ());
bc712bbf 316
2ad52f6f
TT
317 for (int lineno = 1; lineno <= content.size (); lineno++)
318 tui_show_source_line (this, lineno);
bc712bbf 319
0bd27e07
TT
320 check_and_display_highlight_if_needed ();
321 refresh_window ();
bc712bbf 322}
c906108c 323
5104fe36 324tui_source_window_base::tui_source_window_base (enum tui_win_type type)
398fdd60 325 : tui_win_info (type)
5104fe36
TT
326{
327 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
328 start_line_or_addr.loa = LOA_ADDRESS;
329 start_line_or_addr.u.addr = 0;
1df2f9ef
TT
330
331 gdb::observers::source_styling_changed.attach
332 (std::bind (&tui_source_window::style_changed, this),
333 m_observable);
5104fe36
TT
334}
335
1df2f9ef
TT
336tui_source_window_base::~tui_source_window_base ()
337{
338 gdb::observers::source_styling_changed.detach (m_observable);
339}
5104fe36 340
5104fe36
TT
341/* See tui-data.h. */
342
5104fe36
TT
343void
344tui_source_window_base::update_tab_width ()
345{
7523da63 346 werase (handle.get ());
3df505f6 347 rerender ();
5104fe36
TT
348}
349
5104fe36 350void
3df505f6 351tui_source_window_base::rerender ()
5104fe36 352{
5104fe36
TT
353 if (!content.empty ())
354 {
5104fe36
TT
355 struct symtab_and_line cursal
356 = get_current_source_symtab_and_line ();
357
9f7540a5
TT
358 if (start_line_or_addr.loa == LOA_LINE)
359 cursal.line = start_line_or_addr.u.line_no;
360 else
361 cursal.pc = start_line_or_addr.u.addr;
362 update_source_window (gdbarch, cursal);
5104fe36
TT
363 }
364 else if (deprecated_safe_get_selected_frame () != NULL)
365 {
5104fe36
TT
366 struct symtab_and_line cursal
367 = get_current_source_symtab_and_line ();
368 struct frame_info *frame = deprecated_safe_get_selected_frame ();
369 struct gdbarch *gdbarch = get_frame_arch (frame);
370
371 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
9f7540a5
TT
372 if (type != SRC_WIN)
373 find_line_pc (s, cursal.line, &cursal.pc);
374 update_source_window (gdbarch, cursal);
5104fe36 375 }
3df505f6
TT
376 else
377 erase_source_content ();
5104fe36
TT
378}
379
380/* See tui-data.h. */
381
6f11e682 382void
ad54d15b 383tui_source_window_base::refill ()
6f11e682 384{
9f7540a5 385 symtab_and_line sal {};
6f11e682 386
cb2ce893 387 if (type == SRC_WIN)
6f11e682 388 {
9f7540a5
TT
389 sal = get_current_source_symtab_and_line ();
390 if (sal.symtab == NULL)
391 sal = find_pc_line (get_frame_pc (get_selected_frame (NULL)), 0);
6f11e682
TT
392 }
393
9f7540a5
TT
394 if (sal.pspace == nullptr)
395 sal.pspace = current_program_space;
396
397 if (start_line_or_addr.loa == LOA_LINE)
398 sal.line = start_line_or_addr.u.line_no;
399 else
400 sal.pc = start_line_or_addr.u.addr;
401
402 update_source_window_as_is (gdbarch, sal);
6f11e682 403}
c906108c 404
f80bda8e 405/* Scroll the source forward or backward horizontally. */
6f11e682 406
c906108c 407void
c3bd716f 408tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 409{
53e7cdba 410 if (!content.empty ())
c906108c 411 {
c3bd716f
TT
412 int offset = horizontal_offset + num_to_scroll;
413 if (offset < 0)
414 offset = 0;
e6e41501 415 horizontal_offset = offset;
ad54d15b 416 refill ();
c906108c 417 }
6ba8e26f 418}
c906108c
SS
419
420
0598af48 421/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
422 line_no. */
423
c906108c 424void
ad54d15b 425tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 426{
02c28df0 427 bool changed = false;
c906108c 428 int i;
c906108c
SS
429
430 i = 0;
53e7cdba 431 while (i < content.size ())
c906108c 432 {
02c28df0 433 bool new_state;
362c05fe 434 struct tui_line_or_address content_loa =
53e7cdba 435 content[i].line_or_addr;
362c05fe 436
362c05fe
AS
437 if (content_loa.loa == l.loa
438 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
f7952c57 439 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
02c28df0 440 new_state = true;
c906108c 441 else
02c28df0 442 new_state = false;
53e7cdba 443 if (new_state != content[i].is_exec_point)
00b90ae2 444 {
02c28df0 445 changed = true;
53e7cdba 446 content[i].is_exec_point = new_state;
ad54d15b 447 tui_show_source_line (this, i + 1);
00b90ae2 448 }
c906108c
SS
449 i++;
450 }
00b90ae2 451 if (changed)
ad54d15b 452 refill ();
00b90ae2 453}
c906108c 454
0807ab7b
TT
455/* See tui-winsource.h. */
456
c906108c 457void
0807ab7b 458tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 459{
ad54d15b 460 for (tui_source_window_base *win : tui_source_windows ())
c906108c 461 {
2ddaf614
TT
462 if (win->update_breakpoint_info (being_deleted, false))
463 win->update_exec_info ();
c906108c 464 }
00b2bad4 465}
c906108c
SS
466
467
0807ab7b 468/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
469 information for each line.
470
0807ab7b 471 Returns true if something changed and the execution window must be
1cc6d956
MS
472 refreshed. */
473
0807ab7b 474bool
2ddaf614
TT
475tui_source_window_base::update_breakpoint_info
476 (struct breakpoint *being_deleted, bool current_only)
c906108c
SS
477{
478 int i;
0807ab7b 479 bool need_refresh = false;
c906108c 480
2ddaf614 481 for (i = 0; i < content.size (); i++)
00b2bad4 482 {
5b6fe301 483 struct tui_source_element *line;
00b2bad4 484
2ddaf614 485 line = &content[i];
6d012f14 486 if (current_only && !line->is_exec_point)
00b2bad4
SC
487 continue;
488
489 /* Scan each breakpoint to see if the current line has something to
490 do with it. Identify enable/disabled breakpoints as well as
491 those that we already hit. */
0598af48 492 tui_bp_flags mode = 0;
81e6b8eb 493 iterate_over_breakpoints ([&] (breakpoint *bp) -> bool
00b2bad4 494 {
f8eba3c6
TT
495 struct bp_location *loc;
496
0807ab7b 497 if (bp == being_deleted)
81e6b8eb 498 return false;
0807ab7b 499
f8eba3c6
TT
500 for (loc = bp->loc; loc != NULL; loc = loc->next)
501 {
2ddaf614 502 if (location_matches_p (loc, i))
f8eba3c6
TT
503 {
504 if (bp->enable_state == bp_disabled)
505 mode |= TUI_BP_DISABLED;
506 else
507 mode |= TUI_BP_ENABLED;
508 if (bp->hit_count)
509 mode |= TUI_BP_HIT;
510 if (bp->loc->cond)
511 mode |= TUI_BP_CONDITIONAL;
512 if (bp->type == bp_hardware_breakpoint)
513 mode |= TUI_BP_HARDWARE;
514 }
515 }
81e6b8eb
CB
516 return false;
517 });
0598af48 518 if (line->break_mode != mode)
00b2bad4 519 {
0598af48
TT
520 line->break_mode = mode;
521 need_refresh = true;
00b2bad4
SC
522 }
523 }
524 return need_refresh;
525}
c906108c 526
6ba8e26f
AC
527/* Function to initialize the content of the execution info window,
528 based upon the input window which is either the source or
529 disassembly window. */
73fbdc65 530void
5216580d 531tui_source_window_base::update_exec_info ()
c906108c 532{
2ddaf614 533 update_breakpoint_info (nullptr, true);
37a4a131 534 for (int i = 0; i < content.size (); i++)
098f9ed4 535 {
5216580d
TT
536 struct tui_source_element *src_element = &content[i];
537 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
538
539 /* Now update the exec info content based upon the state
540 of each line as indicated by the source content. */
5216580d 541 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
542 if (mode & TUI_BP_HIT)
543 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
544 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
545 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
546
547 if (mode & TUI_BP_ENABLED)
548 element[TUI_BP_BREAK_POS] = '+';
549 else if (mode & TUI_BP_DISABLED)
550 element[TUI_BP_BREAK_POS] = '-';
551
552 if (src_element->is_exec_point)
553 element[TUI_EXEC_POS] = '>';
c906108c 554
7523da63 555 mvwaddstr (handle.get (), i + 1, 1, element);
5216580d 556 }
398fdd60 557 refresh_window ();
f80bda8e 558}
This page took 2.136044 seconds and 4 git commands to generate.