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