Fix regression from TUI disassembly style patch
[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
DE
59 s = find_pc_line_symtab (addr);
60 if (s != NULL)
61 tui_update_locator_fullname (symtab_to_fullname (s));
2e17b763 62 else
56d397a3 63 tui_update_locator_fullname ("??");
c906108c
SS
64 }
65 }
2e17b763 66}
c906108c 67
1df2f9ef 68/* See tui-winsource.h. */
c906108c 69
1df2f9ef
TT
70std::string
71tui_copy_source_line (const char **ptr, int line_no, int first_col,
72 int line_width)
73{
74 const char *lineptr = *ptr;
75
76 /* Init the line with the line number. */
77 std::string result;
78
79 if (line_no > 0)
80 {
81 result = string_printf ("%-6d", line_no);
82 int len = result.size ();
83 len = len - ((len / tui_tab_width) * tui_tab_width);
84 result.append (len, ' ');
85 }
86
87 int column = 0;
88 char c;
89 do
90 {
91 int skip_bytes;
92
93 c = *lineptr;
94 if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
95 {
96 /* We always have to preserve escapes. */
97 result.append (lineptr, lineptr + skip_bytes);
98 lineptr += skip_bytes;
99 continue;
100 }
101
102 ++lineptr;
103 ++column;
104
105 auto process_tab = [&] ()
106 {
107 int max_tab_len = tui_tab_width;
108
109 --column;
110 for (int j = column % max_tab_len;
111 j < max_tab_len && column < first_col + line_width;
112 column++, j++)
113 if (column >= first_col)
114 result.push_back (' ');
115 };
116
117 /* We have to process all the text in order to pick up all the
118 escapes. */
119 if (column <= first_col || column > first_col + line_width)
120 {
121 if (c == '\t')
122 process_tab ();
123 continue;
124 }
125
126 if (c == '\n' || c == '\r' || c == '\0')
127 {
128 /* Nothing. */
129 }
130 else if (c < 040 && c != '\t')
131 {
132 result.push_back ('^');
133 result.push_back (c + 0100);
134 }
135 else if (c == 0177)
136 {
137 result.push_back ('^');
138 result.push_back ('?');
139 }
140 else if (c == '\t')
141 process_tab ();
142 else
143 result.push_back (c);
144 }
145 while (c != '\0' && c != '\n' && c != '\r');
146
147 if (c == '\r' && *lineptr == '\n')
148 ++lineptr;
149 *ptr = lineptr;
150
151 return result;
152}
153
154void
155tui_source_window_base::style_changed ()
156{
157 if (tui_active && is_visible ())
158 refill ();
159}
c906108c 160
f80bda8e
AC
161/* Function to display source in the source window. This function
162 initializes the horizontal scroll to 0. */
c906108c 163void
017f9828
TT
164tui_source_window_base::update_source_window
165 (struct gdbarch *gdbarch,
166 struct symtab *s,
167 struct tui_line_or_address line_or_addr)
c906108c 168{
017f9828
TT
169 horizontal_offset = 0;
170 update_source_window_as_is (gdbarch, s, line_or_addr);
f80bda8e 171}
c906108c
SS
172
173
f80bda8e
AC
174/* Function to display source in the source/asm window. This function
175 shows the source as specified by the horizontal offset. */
c906108c 176void
ed8358e9
TT
177tui_source_window_base::update_source_window_as_is
178 (struct gdbarch *gdbarch,
179 struct symtab *s,
180 struct tui_line_or_address line_or_addr)
c906108c 181{
81c82c4b
TT
182 enum tui_status ret
183 = set_contents (gdbarch, s, line_or_addr);
c906108c
SS
184
185 if (ret == TUI_FAILURE)
ed8358e9 186 erase_source_content ();
c906108c
SS
187 else
188 {
2ddaf614 189 update_breakpoint_info (nullptr, false);
ed8358e9
TT
190 show_source_content ();
191 update_exec_info ();
192 if (type == SRC_WIN)
c906108c 193 {
51abb421
PA
194 symtab_and_line sal;
195
ed8358e9 196 sal.line = line_or_addr.u.line_no + (content.size () - 2);
52575520 197 sal.symtab = s;
eb822aa6 198 sal.pspace = SYMTAB_PSPACE (s);
51abb421 199 set_current_source_symtab_and_line (sal);
ef5eab5a
MS
200 /* If the focus was in the asm win, put it in the src win if
201 we don't have a split layout. */
e5908723
MS
202 if (tui_win_with_focus () == TUI_DISASM_WIN
203 && tui_current_layout () != SRC_DISASSEM_COMMAND)
ed8358e9 204 tui_set_win_focus_to (this);
c906108c
SS
205 }
206 }
f80bda8e 207}
c906108c
SS
208
209
f80bda8e
AC
210/* Function to ensure that the source and/or disassemly windows
211 reflect the input address. */
c906108c 212void
13274fc3 213tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 214{
c774cec6 215 if (addr != 0)
c906108c
SS
216 {
217 struct symtab_and_line sal;
362c05fe 218 struct tui_line_or_address l;
a4b99e53 219
dd1abb8c 220 switch (tui_current_layout ())
c906108c
SS
221 {
222 case DISASSEM_COMMAND:
223 case DISASSEM_DATA_COMMAND:
13274fc3 224 tui_show_disassem (gdbarch, addr);
c906108c
SS
225 break;
226 case SRC_DISASSEM_COMMAND:
13274fc3 227 tui_show_disassem_and_update_source (gdbarch, addr);
c906108c
SS
228 break;
229 default:
c774cec6 230 sal = find_pc_line (addr, 0);
362c05fe
AS
231 l.loa = LOA_LINE;
232 l.u.line_no = sal.line;
bb01dbfc 233 TUI_SRC_WIN->show_symtab_source (gdbarch, sal.symtab, l);
c906108c
SS
234 break;
235 }
236 }
237 else
238 {
ad54d15b 239 for (struct tui_source_window_base *win_info : tui_source_windows ())
c398c3d0 240 win_info->erase_source_content ();
c906108c 241 }
6ba8e26f 242}
c906108c 243
f80bda8e
AC
244/* Function to ensure that the source and/or disassemly windows
245 reflect the input address. */
c906108c 246void
f80bda8e 247tui_update_source_windows_with_line (struct symtab *s, int line)
c906108c 248{
13274fc3 249 struct gdbarch *gdbarch;
84b1e7c7 250 CORE_ADDR pc;
362c05fe 251 struct tui_line_or_address l;
13274fc3
UW
252
253 if (!s)
254 return;
255
eb822aa6 256 gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
13274fc3 257
dd1abb8c 258 switch (tui_current_layout ())
c906108c
SS
259 {
260 case DISASSEM_COMMAND:
261 case DISASSEM_DATA_COMMAND:
84b1e7c7 262 find_line_pc (s, line, &pc);
13274fc3 263 tui_update_source_windows_with_addr (gdbarch, pc);
c906108c
SS
264 break;
265 default:
362c05fe
AS
266 l.loa = LOA_LINE;
267 l.u.line_no = line;
bb01dbfc 268 TUI_SRC_WIN->show_symtab_source (gdbarch, s, l);
dd1abb8c 269 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
84b1e7c7
SC
270 {
271 find_line_pc (s, line, &pc);
13274fc3 272 tui_show_disassem (gdbarch, pc);
84b1e7c7 273 }
c906108c
SS
274 break;
275 }
f80bda8e 276}
c906108c 277
c906108c 278void
e25d2004 279tui_source_window_base::do_erase_source_content (const char *str)
c906108c 280{
6ba8e26f 281 int x_pos;
e25d2004 282 int half_width = (width - 2) / 2;
c906108c 283
c398c3d0 284 content.clear ();
e25d2004 285 if (handle != NULL)
c906108c 286 {
7523da63 287 werase (handle.get ());
e25d2004 288 check_and_display_highlight_if_needed ();
caf0bc4e 289
e25d2004 290 if (strlen (str) >= half_width)
caf0bc4e
TT
291 x_pos = 1;
292 else
e25d2004 293 x_pos = half_width - strlen (str);
7523da63 294 mvwaddstr (handle.get (),
e25d2004 295 (height / 2),
caf0bc4e 296 x_pos,
e25d2004 297 (char *) str);
93858ad3 298
e25d2004 299 refresh_window ();
c906108c 300 }
6ba8e26f 301}
c906108c
SS
302
303
bc712bbf
SC
304/* Redraw the complete line of a source or disassembly window. */
305static void
53e7cdba 306tui_show_source_line (struct tui_source_window_base *win_info, int lineno)
bc712bbf 307{
53e7cdba 308 struct tui_source_element *line;
798e1c30 309 int x;
bc712bbf 310
53e7cdba
TT
311 line = &win_info->content[lineno - 1];
312 if (line->is_exec_point)
7523da63 313 tui_set_reverse_mode (win_info->handle.get (), true);
bc712bbf 314
7523da63 315 wmove (win_info->handle.get (), lineno, TUI_EXECINFO_SIZE);
5d051055 316 tui_puts (line->line.c_str (), win_info->handle.get ());
53e7cdba 317 if (line->is_exec_point)
7523da63 318 tui_set_reverse_mode (win_info->handle.get (), false);
bc712bbf
SC
319
320 /* Clear to end of line but stop before the border. */
7523da63 321 x = getcurx (win_info->handle.get ());
cb2ce893 322 while (x + 1 < win_info->width)
798e1c30 323 {
7523da63
TT
324 waddch (win_info->handle.get (), ' ');
325 x = getcurx (win_info->handle.get ());
798e1c30 326 }
bc712bbf
SC
327}
328
c906108c 329void
0bd27e07 330tui_source_window_base::show_source_content ()
c906108c 331{
2ad52f6f 332 gdb_assert (!content.empty ());
bc712bbf 333
2ad52f6f
TT
334 for (int lineno = 1; lineno <= content.size (); lineno++)
335 tui_show_source_line (this, lineno);
bc712bbf 336
0bd27e07
TT
337 check_and_display_highlight_if_needed ();
338 refresh_window ();
bc712bbf 339}
c906108c 340
5104fe36 341tui_source_window_base::tui_source_window_base (enum tui_win_type type)
398fdd60 342 : tui_win_info (type)
5104fe36
TT
343{
344 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
345 start_line_or_addr.loa = LOA_ADDRESS;
346 start_line_or_addr.u.addr = 0;
1df2f9ef
TT
347
348 gdb::observers::source_styling_changed.attach
349 (std::bind (&tui_source_window::style_changed, this),
350 m_observable);
5104fe36
TT
351}
352
1df2f9ef
TT
353tui_source_window_base::~tui_source_window_base ()
354{
355 gdb::observers::source_styling_changed.detach (m_observable);
356}
5104fe36 357
5104fe36
TT
358/* See tui-data.h. */
359
5104fe36
TT
360void
361tui_source_window_base::update_tab_width ()
362{
7523da63 363 werase (handle.get ());
3df505f6 364 rerender ();
5104fe36
TT
365}
366
5104fe36 367void
3df505f6 368tui_source_window_base::rerender ()
5104fe36 369{
5104fe36
TT
370 if (!content.empty ())
371 {
372 struct tui_line_or_address line_or_addr;
373 struct symtab_and_line cursal
374 = get_current_source_symtab_and_line ();
375
376 line_or_addr = start_line_or_addr;
017f9828 377 update_source_window (gdbarch, cursal.symtab, line_or_addr);
5104fe36
TT
378 }
379 else if (deprecated_safe_get_selected_frame () != NULL)
380 {
381 struct tui_line_or_address line;
382 struct symtab_and_line cursal
383 = get_current_source_symtab_and_line ();
384 struct frame_info *frame = deprecated_safe_get_selected_frame ();
385 struct gdbarch *gdbarch = get_frame_arch (frame);
386
387 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
388 if (type == SRC_WIN)
389 {
390 line.loa = LOA_LINE;
391 line.u.line_no = cursal.line;
392 }
393 else
394 {
395 line.loa = LOA_ADDRESS;
396 find_line_pc (s, cursal.line, &line.u.addr);
397 }
017f9828 398 update_source_window (gdbarch, s, line);
5104fe36 399 }
3df505f6
TT
400 else
401 erase_source_content ();
5104fe36
TT
402}
403
404/* See tui-data.h. */
405
6f11e682 406void
ad54d15b 407tui_source_window_base::refill ()
6f11e682
TT
408{
409 symtab *s = nullptr;
410
cb2ce893 411 if (type == SRC_WIN)
6f11e682
TT
412 {
413 symtab_and_line cursal = get_current_source_symtab_and_line ();
414 s = (cursal.symtab == NULL
415 ? find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)))
416 : cursal.symtab);
417 }
418
ed8358e9 419 update_source_window_as_is (gdbarch, s, content[0].line_or_addr);
6f11e682 420}
c906108c 421
f80bda8e 422/* Scroll the source forward or backward horizontally. */
6f11e682 423
c906108c 424void
c3bd716f 425tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 426{
53e7cdba 427 if (!content.empty ())
c906108c 428 {
c3bd716f
TT
429 int offset = horizontal_offset + num_to_scroll;
430 if (offset < 0)
431 offset = 0;
e6e41501 432 horizontal_offset = offset;
ad54d15b 433 refill ();
c906108c 434 }
6ba8e26f 435}
c906108c
SS
436
437
0598af48 438/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
439 line_no. */
440
c906108c 441void
ad54d15b 442tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 443{
02c28df0 444 bool changed = false;
c906108c 445 int i;
c906108c
SS
446
447 i = 0;
53e7cdba 448 while (i < content.size ())
c906108c 449 {
02c28df0 450 bool new_state;
362c05fe 451 struct tui_line_or_address content_loa =
53e7cdba 452 content[i].line_or_addr;
362c05fe
AS
453
454 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
455 gdb_assert (content_loa.loa == LOA_LINE
456 || content_loa.loa == LOA_ADDRESS);
457 if (content_loa.loa == l.loa
458 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
f7952c57 459 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
02c28df0 460 new_state = true;
c906108c 461 else
02c28df0 462 new_state = false;
53e7cdba 463 if (new_state != content[i].is_exec_point)
00b90ae2 464 {
02c28df0 465 changed = true;
53e7cdba 466 content[i].is_exec_point = new_state;
ad54d15b 467 tui_show_source_line (this, i + 1);
00b90ae2 468 }
c906108c
SS
469 i++;
470 }
00b90ae2 471 if (changed)
ad54d15b 472 refill ();
00b90ae2 473}
c906108c 474
0807ab7b
TT
475/* See tui-winsource.h. */
476
c906108c 477void
0807ab7b 478tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 479{
ad54d15b 480 for (tui_source_window_base *win : tui_source_windows ())
c906108c 481 {
2ddaf614
TT
482 if (win->update_breakpoint_info (being_deleted, false))
483 win->update_exec_info ();
c906108c 484 }
00b2bad4 485}
c906108c
SS
486
487
0807ab7b 488/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
489 information for each line.
490
0807ab7b 491 Returns true if something changed and the execution window must be
1cc6d956
MS
492 refreshed. */
493
0807ab7b 494bool
2ddaf614
TT
495tui_source_window_base::update_breakpoint_info
496 (struct breakpoint *being_deleted, bool current_only)
c906108c
SS
497{
498 int i;
0807ab7b 499 bool need_refresh = false;
c906108c 500
2ddaf614 501 for (i = 0; i < content.size (); i++)
00b2bad4 502 {
5b6fe301 503 struct tui_source_element *line;
00b2bad4 504
2ddaf614 505 line = &content[i];
6d012f14 506 if (current_only && !line->is_exec_point)
00b2bad4
SC
507 continue;
508
509 /* Scan each breakpoint to see if the current line has something to
510 do with it. Identify enable/disabled breakpoints as well as
511 those that we already hit. */
0598af48 512 tui_bp_flags mode = 0;
81e6b8eb 513 iterate_over_breakpoints ([&] (breakpoint *bp) -> bool
00b2bad4 514 {
f8eba3c6
TT
515 struct bp_location *loc;
516
362c05fe
AS
517 gdb_assert (line->line_or_addr.loa == LOA_LINE
518 || line->line_or_addr.loa == LOA_ADDRESS);
f8eba3c6 519
0807ab7b 520 if (bp == being_deleted)
81e6b8eb 521 return false;
0807ab7b 522
f8eba3c6
TT
523 for (loc = bp->loc; loc != NULL; loc = loc->next)
524 {
2ddaf614 525 if (location_matches_p (loc, i))
f8eba3c6
TT
526 {
527 if (bp->enable_state == bp_disabled)
528 mode |= TUI_BP_DISABLED;
529 else
530 mode |= TUI_BP_ENABLED;
531 if (bp->hit_count)
532 mode |= TUI_BP_HIT;
533 if (bp->loc->cond)
534 mode |= TUI_BP_CONDITIONAL;
535 if (bp->type == bp_hardware_breakpoint)
536 mode |= TUI_BP_HARDWARE;
537 }
538 }
81e6b8eb
CB
539 return false;
540 });
0598af48 541 if (line->break_mode != mode)
00b2bad4 542 {
0598af48
TT
543 line->break_mode = mode;
544 need_refresh = true;
00b2bad4
SC
545 }
546 }
547 return need_refresh;
548}
c906108c 549
6ba8e26f
AC
550/* Function to initialize the content of the execution info window,
551 based upon the input window which is either the source or
552 disassembly window. */
73fbdc65 553void
5216580d 554tui_source_window_base::update_exec_info ()
c906108c 555{
2ddaf614 556 update_breakpoint_info (nullptr, true);
37a4a131 557 for (int i = 0; i < content.size (); i++)
098f9ed4 558 {
5216580d
TT
559 struct tui_source_element *src_element = &content[i];
560 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
561
562 /* Now update the exec info content based upon the state
563 of each line as indicated by the source content. */
5216580d 564 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
565 if (mode & TUI_BP_HIT)
566 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
567 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
568 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
569
570 if (mode & TUI_BP_ENABLED)
571 element[TUI_BP_BREAK_POS] = '+';
572 else if (mode & TUI_BP_DISABLED)
573 element[TUI_BP_BREAK_POS] = '-';
574
575 if (src_element->is_exec_point)
576 element[TUI_EXEC_POS] = '>';
c906108c 577
7523da63 578 mvwaddstr (handle.get (), i + 1, 1, element);
5216580d 579 }
398fdd60 580 refresh_window ();
f80bda8e 581}
This page took 2.109319 seconds and 4 git commands to generate.