Remove tui_alloc_source_buffer
[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{
b4eb2452 47 if (!tui_source_windows ().empty ())
c906108c 48 {
13274fc3 49 struct gdbarch *gdbarch;
c906108c
SS
50 CORE_ADDR addr;
51
13274fc3 52 tui_get_begin_asm_address (&gdbarch, &addr);
c774cec6 53 if (addr != (CORE_ADDR) 0)
c906108c 54 {
34248c3a 55 struct symtab *s;
c906108c 56
13274fc3 57 tui_update_source_windows_with_addr (gdbarch, addr);
34248c3a
DE
58 s = find_pc_line_symtab (addr);
59 if (s != NULL)
60 tui_update_locator_fullname (symtab_to_fullname (s));
2e17b763 61 else
56d397a3 62 tui_update_locator_fullname ("??");
c906108c
SS
63 }
64 }
2e17b763 65}
c906108c
SS
66
67
68
f80bda8e
AC
69/* Function to display source in the source window. This function
70 initializes the horizontal scroll to 0. */
c906108c 71void
be4da588 72tui_update_source_window (struct tui_source_window_base *win_info,
13274fc3 73 struct gdbarch *gdbarch,
08ef48c5
MS
74 struct symtab *s,
75 struct tui_line_or_address line_or_addr,
76 int noerror)
c906108c 77{
be4da588 78 win_info->horizontal_offset = 0;
13274fc3 79 tui_update_source_window_as_is (win_info, gdbarch, s, line_or_addr, noerror);
f80bda8e 80}
c906108c
SS
81
82
f80bda8e
AC
83/* Function to display source in the source/asm window. This function
84 shows the source as specified by the horizontal offset. */
c906108c 85void
be4da588 86tui_update_source_window_as_is (struct tui_source_window_base *win_info,
13274fc3 87 struct gdbarch *gdbarch,
08ef48c5
MS
88 struct symtab *s,
89 struct tui_line_or_address line_or_addr,
90 int noerror)
c906108c 91{
22940a24 92 enum tui_status ret;
c906108c 93
cb2ce893 94 if (win_info->type == SRC_WIN)
5813316f
TT
95 ret = tui_set_source_content (win_info, s, line_or_addr.u.line_no,
96 noerror);
c906108c 97 else
9d391078 98 ret = tui_set_disassem_content (win_info, gdbarch, line_or_addr.u.addr);
c906108c
SS
99
100 if (ret == TUI_FAILURE)
93858ad3 101 tui_clear_source_content (win_info);
c906108c
SS
102 else
103 {
0807ab7b 104 tui_update_breakpoint_info (win_info, nullptr, false);
0bd27e07 105 win_info->show_source_content ();
7ba913dc 106 win_info->update_exec_info ();
cb2ce893 107 if (win_info->type == SRC_WIN)
c906108c 108 {
51abb421
PA
109 symtab_and_line sal;
110
362c05fe 111 sal.line = line_or_addr.u.line_no +
53e7cdba 112 (win_info->content.size () - 2);
52575520 113 sal.symtab = s;
eb822aa6 114 sal.pspace = SYMTAB_PSPACE (s);
51abb421 115 set_current_source_symtab_and_line (sal);
ef5eab5a
MS
116 /* If the focus was in the asm win, put it in the src win if
117 we don't have a split layout. */
e5908723
MS
118 if (tui_win_with_focus () == TUI_DISASM_WIN
119 && tui_current_layout () != SRC_DISASSEM_COMMAND)
5813316f 120 tui_set_win_focus_to (win_info);
c906108c
SS
121 }
122 }
f80bda8e 123}
c906108c
SS
124
125
f80bda8e
AC
126/* Function to ensure that the source and/or disassemly windows
127 reflect the input address. */
c906108c 128void
13274fc3 129tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 130{
c774cec6 131 if (addr != 0)
c906108c
SS
132 {
133 struct symtab_and_line sal;
362c05fe 134 struct tui_line_or_address l;
a4b99e53 135
dd1abb8c 136 switch (tui_current_layout ())
c906108c
SS
137 {
138 case DISASSEM_COMMAND:
139 case DISASSEM_DATA_COMMAND:
13274fc3 140 tui_show_disassem (gdbarch, addr);
c906108c
SS
141 break;
142 case SRC_DISASSEM_COMMAND:
13274fc3 143 tui_show_disassem_and_update_source (gdbarch, addr);
c906108c
SS
144 break;
145 default:
c774cec6 146 sal = find_pc_line (addr, 0);
362c05fe
AS
147 l.loa = LOA_LINE;
148 l.u.line_no = sal.line;
5813316f 149 tui_show_symtab_source (TUI_SRC_WIN, gdbarch, sal.symtab, l, FALSE);
c906108c
SS
150 break;
151 }
152 }
153 else
154 {
ad54d15b 155 for (struct tui_source_window_base *win_info : tui_source_windows ())
93858ad3 156 tui_clear_source_content (win_info);
c906108c 157 }
6ba8e26f 158}
c906108c 159
f80bda8e
AC
160/* Function to ensure that the source and/or disassemly windows
161 reflect the input address. */
c906108c 162void
f80bda8e 163tui_update_source_windows_with_line (struct symtab *s, int line)
c906108c 164{
13274fc3 165 struct gdbarch *gdbarch;
84b1e7c7 166 CORE_ADDR pc;
362c05fe 167 struct tui_line_or_address l;
13274fc3
UW
168
169 if (!s)
170 return;
171
eb822aa6 172 gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
13274fc3 173
dd1abb8c 174 switch (tui_current_layout ())
c906108c
SS
175 {
176 case DISASSEM_COMMAND:
177 case DISASSEM_DATA_COMMAND:
84b1e7c7 178 find_line_pc (s, line, &pc);
13274fc3 179 tui_update_source_windows_with_addr (gdbarch, pc);
c906108c
SS
180 break;
181 default:
362c05fe
AS
182 l.loa = LOA_LINE;
183 l.u.line_no = line;
5813316f 184 tui_show_symtab_source (TUI_SRC_WIN, gdbarch, s, l, FALSE);
dd1abb8c 185 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
84b1e7c7
SC
186 {
187 find_line_pc (s, line, &pc);
13274fc3 188 tui_show_disassem (gdbarch, pc);
84b1e7c7 189 }
c906108c
SS
190 break;
191 }
f80bda8e 192}
c906108c 193
c906108c 194void
caf0bc4e 195tui_clear_source_content (struct tui_source_window_base *win_info)
c906108c 196{
6d012f14 197 if (win_info != NULL)
c906108c 198 {
d02c80cd 199 int i;
c906108c 200
caf0bc4e 201 tui_erase_source_content (win_info);
53e7cdba 202 for (i = 0; i < win_info->content.size (); i++)
c906108c 203 {
53e7cdba 204 struct tui_source_element *element = &win_info->content[i];
1c5313c5 205
0598af48 206 element->break_mode = 0;
53e7cdba 207 element->is_exec_point = false;
c906108c
SS
208 }
209 }
6ba8e26f 210}
c906108c
SS
211
212
c906108c 213void
caf0bc4e 214tui_erase_source_content (struct tui_source_window_base *win_info)
c906108c 215{
6ba8e26f 216 int x_pos;
cb2ce893 217 int half_width = (win_info->width - 2) / 2;
c906108c 218
cb2ce893 219 if (win_info->handle != NULL)
c906108c 220 {
cb2ce893 221 werase (win_info->handle);
b4ef5aeb 222 win_info->check_and_display_highlight_if_needed ();
caf0bc4e
TT
223
224 const char *no_src_str;
225
226 if (win_info->type == SRC_WIN)
227 no_src_str = NO_SRC_STRING;
228 else
229 no_src_str = NO_DISASSEM_STRING;
230 if (strlen (no_src_str) >= half_width)
231 x_pos = 1;
232 else
233 x_pos = half_width - strlen (no_src_str);
234 mvwaddstr (win_info->handle,
235 (win_info->height / 2),
236 x_pos,
237 (char *) no_src_str);
238
f31ec9af 239 win_info->content.clear ();
5b81daba 240 win_info->refresh_window ();
93858ad3
TT
241
242 struct tui_gen_win_info *exec_info = win_info->execution_info;
243
244 werase (exec_info->handle);
245 exec_info->refresh_window ();
c906108c 246 }
6ba8e26f 247}
c906108c
SS
248
249
bc712bbf
SC
250/* Redraw the complete line of a source or disassembly window. */
251static void
53e7cdba 252tui_show_source_line (struct tui_source_window_base *win_info, int lineno)
bc712bbf 253{
53e7cdba 254 struct tui_source_element *line;
798e1c30 255 int x;
bc712bbf 256
53e7cdba
TT
257 line = &win_info->content[lineno - 1];
258 if (line->is_exec_point)
cb2ce893 259 tui_set_reverse_mode (win_info->handle, true);
bc712bbf 260
cb2ce893 261 wmove (win_info->handle, lineno, 1);
53e7cdba 262 tui_puts (line->line,
cb2ce893 263 win_info->handle);
53e7cdba 264 if (line->is_exec_point)
cb2ce893 265 tui_set_reverse_mode (win_info->handle, false);
bc712bbf
SC
266
267 /* Clear to end of line but stop before the border. */
cb2ce893
TT
268 x = getcurx (win_info->handle);
269 while (x + 1 < win_info->width)
798e1c30 270 {
cb2ce893
TT
271 waddch (win_info->handle, ' ');
272 x = getcurx (win_info->handle);
798e1c30 273 }
bc712bbf
SC
274}
275
c906108c 276void
0bd27e07 277tui_source_window_base::show_source_content ()
c906108c 278{
0bd27e07 279 if (!content.empty ())
c906108c 280 {
bc712bbf
SC
281 int lineno;
282
0bd27e07
TT
283 for (lineno = 1; lineno <= content.size (); lineno++)
284 tui_show_source_line (this, lineno);
c906108c 285 }
bc712bbf 286 else
0bd27e07 287 tui_erase_source_content (this);
bc712bbf 288
0bd27e07
TT
289 check_and_display_highlight_if_needed ();
290 refresh_window ();
bc712bbf 291}
c906108c 292
ad54d15b 293/* See tui-data.h. */
6f11e682 294
5104fe36
TT
295void
296tui_source_window_base::clear_detail ()
297{
298 gdbarch = NULL;
299 start_line_or_addr.loa = LOA_ADDRESS;
300 start_line_or_addr.u.addr = 0;
301 horizontal_offset = 0;
302}
303
304tui_source_window_base::tui_source_window_base (enum tui_win_type type)
305 : tui_win_info (type),
306 execution_info (new tui_exec_info_window ())
307{
308 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
309 start_line_or_addr.loa = LOA_ADDRESS;
310 start_line_or_addr.u.addr = 0;
311}
312
313
314tui_source_window_base::~tui_source_window_base ()
315{
316 xfree (fullname);
317 delete execution_info;
318}
319
320void
321tui_source_window_base::reset (int height, int width,
322 int origin_x, int origin_y)
323{
324 tui_gen_win_info::reset (height, width - 3,
325 origin_x + 3, origin_y);
326 execution_info->reset (height, 3, origin_x, origin_y);
327}
328
329/* See tui-data.h. */
330
331void
332tui_source_window_base::refresh_all ()
333{
0bd27e07 334 show_source_content ();
b4ef5aeb 335 check_and_display_highlight_if_needed ();
7ba913dc 336 update_exec_info ();
5104fe36
TT
337}
338
339/* See tui-data.h. */
340
341void
342tui_source_window_base::update_tab_width ()
343{
344 /* We don't really change the height of any windows, but
345 calling these 2 functions causes a complete regeneration
346 and redisplay of the window's contents, which will take
347 the new tab width into account. */
348 make_invisible_and_set_new_height (height);
349 make_visible_with_new_height ();
350}
351
352/* See tui-data.h. */
353
354void
355tui_source_window_base::set_new_height (int height)
356{
357 execution_info->make_visible (false);
358 execution_info->height = height;
359 execution_info->origin.y = origin.y;
360 if (height > 1)
361 execution_info->viewport_height = height - 1;
362 else
363 execution_info->viewport_height = height;
364 execution_info->viewport_height--;
365
366 if (m_has_locator)
367 {
368 tui_locator_window *gen_win_info = tui_locator_win_info_ptr ();
369 gen_win_info->make_visible (false);
370 gen_win_info->origin.y = origin.y + height;
371 }
372}
373
374/* See tui-data.h. */
375
376void
377tui_source_window_base::do_make_visible_with_new_height ()
378{
379 execution_info->make_visible (true);
380 if (!content.empty ())
381 {
382 struct tui_line_or_address line_or_addr;
383 struct symtab_and_line cursal
384 = get_current_source_symtab_and_line ();
385
386 line_or_addr = start_line_or_addr;
387 tui_update_source_window (this, gdbarch,
388 cursal.symtab, line_or_addr, TRUE);
389 }
390 else if (deprecated_safe_get_selected_frame () != NULL)
391 {
392 struct tui_line_or_address line;
393 struct symtab_and_line cursal
394 = get_current_source_symtab_and_line ();
395 struct frame_info *frame = deprecated_safe_get_selected_frame ();
396 struct gdbarch *gdbarch = get_frame_arch (frame);
397
398 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
399 if (type == SRC_WIN)
400 {
401 line.loa = LOA_LINE;
402 line.u.line_no = cursal.line;
403 }
404 else
405 {
406 line.loa = LOA_ADDRESS;
407 find_line_pc (s, cursal.line, &line.u.addr);
408 }
409 tui_update_source_window (this, gdbarch, s, line, TRUE);
410 }
411 if (m_has_locator)
412 {
413 tui_locator_win_info_ptr ()->make_visible (true);
414 tui_show_locator_content ();
415 }
416}
417
418/* See tui-data.h. */
419
420void
421tui_source_window_base::make_visible (bool visible)
422{
423 execution_info->make_visible (visible);
424 tui_win_info::make_visible (visible);
425}
426
427/* See tui-data.h. */
428
429void
430tui_source_window_base::refresh_window ()
431{
432 execution_info->refresh_window ();
433 tui_win_info::refresh_window ();
434}
435
436/* See tui-data.h. */
437
6f11e682 438void
ad54d15b 439tui_source_window_base::refill ()
6f11e682
TT
440{
441 symtab *s = nullptr;
442
cb2ce893 443 if (type == SRC_WIN)
6f11e682
TT
444 {
445 symtab_and_line cursal = get_current_source_symtab_and_line ();
446 s = (cursal.symtab == NULL
447 ? find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)))
448 : cursal.symtab);
449 }
450
ad54d15b 451 tui_update_source_window_as_is (this, gdbarch, s,
53e7cdba 452 content[0].line_or_addr,
6f11e682
TT
453 FALSE);
454}
c906108c 455
f80bda8e 456/* Scroll the source forward or backward horizontally. */
6f11e682 457
c906108c 458void
c3bd716f 459tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 460{
53e7cdba 461 if (!content.empty ())
c906108c 462 {
c3bd716f
TT
463 int offset = horizontal_offset + num_to_scroll;
464 if (offset < 0)
465 offset = 0;
e6e41501 466 horizontal_offset = offset;
ad54d15b 467 refill ();
c906108c 468 }
6ba8e26f 469}
c906108c
SS
470
471
0598af48 472/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
473 line_no. */
474
c906108c 475void
ad54d15b 476tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 477{
02c28df0 478 bool changed = false;
c906108c 479 int i;
c906108c
SS
480
481 i = 0;
53e7cdba 482 while (i < content.size ())
c906108c 483 {
02c28df0 484 bool new_state;
362c05fe 485 struct tui_line_or_address content_loa =
53e7cdba 486 content[i].line_or_addr;
362c05fe
AS
487
488 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
489 gdb_assert (content_loa.loa == LOA_LINE
490 || content_loa.loa == LOA_ADDRESS);
491 if (content_loa.loa == l.loa
492 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
f7952c57 493 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
02c28df0 494 new_state = true;
c906108c 495 else
02c28df0 496 new_state = false;
53e7cdba 497 if (new_state != content[i].is_exec_point)
00b90ae2 498 {
02c28df0 499 changed = true;
53e7cdba 500 content[i].is_exec_point = new_state;
ad54d15b 501 tui_show_source_line (this, i + 1);
00b90ae2 502 }
c906108c
SS
503 i++;
504 }
00b90ae2 505 if (changed)
ad54d15b 506 refill ();
00b90ae2 507}
c906108c 508
0807ab7b
TT
509/* See tui-winsource.h. */
510
c906108c 511void
0807ab7b 512tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 513{
ad54d15b 514 for (tui_source_window_base *win : tui_source_windows ())
c906108c 515 {
0807ab7b 516 if (tui_update_breakpoint_info (win, being_deleted, false))
00b2bad4 517 {
7ba913dc 518 win->update_exec_info ();
00b2bad4 519 }
c906108c 520 }
00b2bad4 521}
c906108c
SS
522
523
0807ab7b 524/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
525 information for each line.
526
0807ab7b 527 Returns true if something changed and the execution window must be
1cc6d956
MS
528 refreshed. */
529
0807ab7b
TT
530bool
531tui_update_breakpoint_info (struct tui_source_window_base *win,
532 struct breakpoint *being_deleted,
533 bool current_only)
c906108c
SS
534{
535 int i;
0807ab7b 536 bool need_refresh = false;
c906108c 537
53e7cdba 538 for (i = 0; i < win->content.size (); i++)
00b2bad4
SC
539 {
540 struct breakpoint *bp;
541 extern struct breakpoint *breakpoint_chain;
5b6fe301 542 struct tui_source_element *line;
00b2bad4 543
53e7cdba 544 line = &win->content[i];
6d012f14 545 if (current_only && !line->is_exec_point)
00b2bad4
SC
546 continue;
547
548 /* Scan each breakpoint to see if the current line has something to
549 do with it. Identify enable/disabled breakpoints as well as
550 those that we already hit. */
0598af48 551 tui_bp_flags mode = 0;
00b2bad4 552 for (bp = breakpoint_chain;
cafb3438 553 bp != NULL;
00b2bad4
SC
554 bp = bp->next)
555 {
f8eba3c6
TT
556 struct bp_location *loc;
557
362c05fe
AS
558 gdb_assert (line->line_or_addr.loa == LOA_LINE
559 || line->line_or_addr.loa == LOA_ADDRESS);
f8eba3c6 560
0807ab7b
TT
561 if (bp == being_deleted)
562 continue;
563
f8eba3c6
TT
564 for (loc = bp->loc; loc != NULL; loc = loc->next)
565 {
c2cd8994 566 if (win->location_matches_p (loc, i))
f8eba3c6
TT
567 {
568 if (bp->enable_state == bp_disabled)
569 mode |= TUI_BP_DISABLED;
570 else
571 mode |= TUI_BP_ENABLED;
572 if (bp->hit_count)
573 mode |= TUI_BP_HIT;
574 if (bp->loc->cond)
575 mode |= TUI_BP_CONDITIONAL;
576 if (bp->type == bp_hardware_breakpoint)
577 mode |= TUI_BP_HARDWARE;
578 }
579 }
00b2bad4 580 }
0598af48 581 if (line->break_mode != mode)
00b2bad4 582 {
0598af48
TT
583 line->break_mode = mode;
584 need_refresh = true;
00b2bad4
SC
585 }
586 }
587 return need_refresh;
588}
c906108c 589
6ba8e26f
AC
590/* Function to initialize the content of the execution info window,
591 based upon the input window which is either the source or
592 disassembly window. */
73fbdc65 593void
5216580d 594tui_source_window_base::update_exec_info ()
c906108c 595{
5216580d 596 werase (execution_info->handle);
37a4a131
TT
597 tui_update_breakpoint_info (this, nullptr, true);
598 for (int i = 0; i < content.size (); i++)
098f9ed4 599 {
5216580d
TT
600 struct tui_source_element *src_element = &content[i];
601 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
602
603 /* Now update the exec info content based upon the state
604 of each line as indicated by the source content. */
5216580d 605 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
606 if (mode & TUI_BP_HIT)
607 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
608 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
609 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
610
611 if (mode & TUI_BP_ENABLED)
612 element[TUI_BP_BREAK_POS] = '+';
613 else if (mode & TUI_BP_DISABLED)
614 element[TUI_BP_BREAK_POS] = '-';
615
616 if (src_element->is_exec_point)
617 element[TUI_EXEC_POS] = '>';
c906108c 618
5216580d
TT
619 mvwaddstr (execution_info->handle, i + 1, 0, element);
620 }
621 execution_info->refresh_window ();
f80bda8e 622}
This page took 2.113045 seconds and 4 git commands to generate.