]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tui/tui-stack.c
Move locator code to tui-stack.c
[thirdparty/binutils-gdb.git] / gdb / tui / tui-stack.c
CommitLineData
f377b406 1/* TUI display locator.
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 "symtab.h"
24#include "breakpoint.h"
25#include "frame.h"
75fd9bc1 26#include "command.h"
50265402
SC
27#include "inferior.h"
28#include "target.h"
7563e053 29#include "top.h"
50f182aa 30#include "gdb-demangle.h"
56d397a3 31#include "source.h"
d7b2e967
AC
32#include "tui/tui.h"
33#include "tui/tui-data.h"
34#include "tui/tui-stack.h"
35#include "tui/tui-wingeneral.h"
36#include "tui/tui-source.h"
37#include "tui/tui-winsource.h"
38#include "tui/tui-file.h"
c906108c 39
6a83354a 40#include "gdb_curses.h"
c906108c 41
f2dda477
TT
42static struct tui_locator_window _locator;
43
5564c769
SC
44/* Get a printable name for the function at the address.
45 The symbol name is demangled if demangling is turned on.
46 Returns a pointer to a static area holding the result. */
5b6fe301 47static char *tui_get_function_from_frame (struct frame_info *fi);
c906108c 48
56d397a3
JK
49/* Set the full_name portion of the locator. */
50static void tui_set_locator_fullname (const char *fullname);
2e17b763
SC
51
52/* Update the locator, with the provided arguments. */
b5fca6d7
PP
53static int tui_set_locator_info (struct gdbarch *gdbarch,
54 const char *fullname,
55 const char *procname,
56 int lineno, CORE_ADDR addr);
2e17b763 57
0b39b52e 58static void tui_update_command (const char *, int);
7d6dd1e9 59\f
c906108c 60
f2dda477
TT
61/* Accessor for the locator win info. Answers a pointer to the static
62 locator win info struct. */
63struct tui_locator_window *
64tui_locator_win_info_ptr (void)
65{
66 return &_locator;
67}
68
69void
70tui_initialize_static_data ()
71{
72 tui_gen_win_info *win = tui_locator_win_info_ptr ();
73 win->width =
74 win->height =
75 win->origin.x =
76 win->origin.y =
77 win->viewport_height = 0;
78 win->handle = NULL;
79 win->is_visible = false;
80 win->title = 0;
81}
82
83
1cc6d956
MS
84/* Create the status line to display as much information as we can on
85 this single line: target name, process number, current function,
86 current line, current PC, SingleKey mode. */
3add462f
TT
87static char *
88tui_make_status_line (struct tui_locator_window *loc)
50265402 89{
5b6fe301 90 char *string;
a42a37b7 91 char line_buf[50], *pname;
5b6fe301 92 char *buf;
a42a37b7 93 int status_size;
50265402 94 int i, proc_width;
5b6fe301 95 const char *pid_name;
50265402
SC
96 int target_width;
97 int pid_width;
98 int line_width;
50265402 99
a068643d 100 std::string pid_name_holder;
d7e15655 101 if (inferior_ptid == null_ptid)
50265402
SC
102 pid_name = "No process";
103 else
a068643d
TT
104 {
105 pid_name_holder = target_pid_to_str (inferior_ptid);
106 pid_name = pid_name_holder.c_str ();
107 }
50265402
SC
108
109 target_width = strlen (target_shortname);
110 if (target_width > MAX_TARGET_WIDTH)
111 target_width = MAX_TARGET_WIDTH;
112
113 pid_width = strlen (pid_name);
114 if (pid_width > MAX_PID_WIDTH)
115 pid_width = MAX_PID_WIDTH;
a42a37b7 116
dd1abb8c 117 status_size = tui_term_width ();
50265402 118 string = (char *) xmalloc (status_size + 1);
a42a37b7 119 buf = (char*) alloca (status_size + 1);
50265402
SC
120
121 /* Translate line number and obtain its size. */
6d012f14 122 if (loc->line_no > 0)
8c042590 123 xsnprintf (line_buf, sizeof (line_buf), "%d", loc->line_no);
50265402
SC
124 else
125 strcpy (line_buf, "??");
126 line_width = strlen (line_buf);
127 if (line_width < MIN_LINE_WIDTH)
128 line_width = MIN_LINE_WIDTH;
129
130 /* Translate PC address. */
d7e74731
PA
131 string_file pc_out;
132
2d5f09f0 133 fputs_filtered (loc->gdbarch? paddress (loc->gdbarch, loc->addr) : "??",
d7e74731
PA
134 &pc_out);
135
136 const char *pc_buf = pc_out.c_str ();
137 int pc_width = pc_out.size ();
138
50265402
SC
139 /* First determine the amount of proc name width we have available.
140 The +1 are for a space separator between fields.
141 The -1 are to take into account the \0 counted by sizeof. */
142 proc_width = (status_size
143 - (target_width + 1)
144 - (pid_width + 1)
145 - (sizeof (PROC_PREFIX) - 1 + 1)
146 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
147 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
6d012f14 148 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
50265402
SC
149 ? (sizeof (SINGLE_KEY) - 1 + 1)
150 : 0));
151
152 /* If there is no room to print the function name, try by removing
153 some fields. */
154 if (proc_width < MIN_PROC_WIDTH)
155 {
156 proc_width += target_width + 1;
157 target_width = 0;
158 if (proc_width < MIN_PROC_WIDTH)
159 {
160 proc_width += pid_width + 1;
161 pid_width = 0;
162 if (proc_width <= MIN_PROC_WIDTH)
163 {
164 proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
165 pc_width = 0;
166 if (proc_width < 0)
167 {
168 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
169 line_width = 0;
170 if (proc_width < 0)
171 proc_width = 0;
172 }
173 }
174 }
175 }
176
1cc6d956 177 /* Now convert elements to string form. */
6d012f14 178 pname = loc->proc_name;
50265402 179
1cc6d956
MS
180 /* Now create the locator line from the string version of the
181 elements. We could use sprintf() here but that wouldn't ensure
182 that we don't overrun the size of the allocated buffer.
183 strcat_to_buf() will. */
50265402
SC
184 *string = (char) 0;
185
186 if (target_width > 0)
187 {
188 sprintf (buf, "%*.*s ",
189 -target_width, target_width, target_shortname);
190 strcat_to_buf (string, status_size, buf);
191 }
192 if (pid_width > 0)
193 {
194 sprintf (buf, "%*.*s ",
195 -pid_width, pid_width, pid_name);
196 strcat_to_buf (string, status_size, buf);
197 }
198
199 /* Show whether we are in SingleKey mode. */
6d012f14 200 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
50265402
SC
201 {
202 strcat_to_buf (string, status_size, SINGLE_KEY);
203 strcat_to_buf (string, status_size, " ");
204 }
205
1cc6d956 206 /* Procedure/class name. */
50265402
SC
207 if (proc_width > 0)
208 {
209 if (strlen (pname) > proc_width)
210 sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
211 1 - proc_width, proc_width - 1, pname);
212 else
213 sprintf (buf, "%s%*.*s ", PROC_PREFIX,
214 -proc_width, proc_width, pname);
215 strcat_to_buf (string, status_size, buf);
216 }
217
218 if (line_width > 0)
219 {
220 sprintf (buf, "%s%*.*s ", LINE_PREFIX,
221 -line_width, line_width, line_buf);
222 strcat_to_buf (string, status_size, buf);
223 }
224 if (pc_width > 0)
225 {
226 strcat_to_buf (string, status_size, PC_PREFIX);
227 strcat_to_buf (string, status_size, pc_buf);
228 }
229
230
231 for (i = strlen (string); i < status_size; i++)
232 string[i] = ' ';
233 string[status_size] = (char) 0;
234
50265402
SC
235 return string;
236}
237
1cc6d956
MS
238/* Get a printable name for the function at the address. The symbol
239 name is demangled if demangling is turned on. Returns a pointer to
240 a static area holding the result. */
5564c769
SC
241static char*
242tui_get_function_from_frame (struct frame_info *fi)
243{
244 static char name[256];
d7e74731 245 string_file stream;
5564c769 246
22e722e1 247 print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
d7e74731 248 &stream, demangle, "");
5564c769 249
1cc6d956
MS
250 /* Use simple heuristics to isolate the function name. The symbol
251 can be demangled and we can have function parameters. Remove
252 them because the status line is too short to display them. */
d7e74731
PA
253 const char *d = stream.c_str ();
254 if (*d == '<')
255 d++;
256 strncpy (name, d, sizeof (name) - 1);
4e2af517 257 name[sizeof (name) - 1] = 0;
d7e74731
PA
258
259 char *p = strchr (name, '(');
5564c769
SC
260 if (!p)
261 p = strchr (name, '>');
262 if (p)
263 *p = 0;
264 p = strchr (name, '+');
265 if (p)
266 *p = 0;
5564c769
SC
267 return name;
268}
c906108c 269
c906108c 270void
47d3492a 271tui_show_locator_content (void)
c906108c
SS
272{
273 char *string;
3add462f 274 struct tui_locator_window *locator;
c906108c 275
dd1abb8c 276 locator = tui_locator_win_info_ptr ();
c906108c 277
cafb3438 278 if (locator != NULL && locator->handle != NULL)
c906108c 279 {
3add462f 280 string = tui_make_status_line (locator);
50265402 281 wmove (locator->handle, 0, 0);
cae3f17b
JB
282 /* We ignore the return value from wstandout and wstandend, casting
283 them to void in order to avoid a compiler warning. The warning
284 itself was introduced by a patch to ncurses 5.7 dated 2009-08-29,
285 changing these macro to expand to code that causes the compiler
286 to generate an unused-value warning. */
ae3bccd4 287 (void) wstandout (locator->handle);
50265402
SC
288 waddstr (locator->handle, string);
289 wclrtoeol (locator->handle);
ae3bccd4 290 (void) wstandend (locator->handle);
5b81daba 291 locator->refresh_window ();
50265402
SC
292 wmove (locator->handle, 0, 0);
293 xfree (string);
c906108c 294 }
50265402 295}
c906108c 296
c906108c 297
2e17b763
SC
298/* Set the filename portion of the locator. */
299static void
56d397a3 300tui_set_locator_fullname (const char *fullname)
2e17b763 301{
3add462f 302 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
2e17b763 303
3add462f
TT
304 locator->full_name[0] = 0;
305 strcat_to_buf (locator->full_name, MAX_LOCATOR_ELEMENT_LEN, fullname);
2e17b763 306}
c906108c 307
b5fca6d7
PP
308/* Update the locator, with the provided arguments.
309
310 Returns 1 if any of the locator's fields were actually changed,
311 and 0 otherwise. */
312
313static int
13274fc3 314tui_set_locator_info (struct gdbarch *gdbarch,
56d397a3 315 const char *fullname,
08ef48c5
MS
316 const char *procname,
317 int lineno,
7d6dd1e9 318 CORE_ADDR addr)
c906108c 319{
3add462f 320 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
b5fca6d7 321 int locator_changed_p = 0;
7d6dd1e9 322
b5fca6d7
PP
323 if (procname == NULL)
324 procname = "";
325
326 if (fullname == NULL)
327 fullname = "";
328
3add462f 329 locator_changed_p |= strncmp (locator->proc_name, procname,
b5fca6d7 330 MAX_LOCATOR_ELEMENT_LEN) != 0;
3add462f
TT
331 locator_changed_p |= lineno != locator->line_no;
332 locator_changed_p |= addr != locator->addr;
333 locator_changed_p |= gdbarch != locator->gdbarch;
334 locator_changed_p |= strncmp (locator->full_name, fullname,
b5fca6d7
PP
335 MAX_LOCATOR_ELEMENT_LEN) != 0;
336
3add462f
TT
337 locator->proc_name[0] = (char) 0;
338 strcat_to_buf (locator->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
339 locator->line_no = lineno;
340 locator->addr = addr;
341 locator->gdbarch = gdbarch;
56d397a3 342 tui_set_locator_fullname (fullname);
b5fca6d7
PP
343
344 return locator_changed_p;
c7c228ed 345}
c906108c 346
56d397a3 347/* Update only the full_name portion of the locator. */
c906108c 348void
56d397a3 349tui_update_locator_fullname (const char *fullname)
c906108c 350{
56d397a3 351 tui_set_locator_fullname (fullname);
47d3492a 352 tui_show_locator_content ();
2e17b763 353}
c906108c 354
b5fca6d7 355/* Function to print the frame information for the TUI. The windows are
bbcbf914 356 refreshed only if frame information has changed since the last refresh.
b5fca6d7 357
bbcbf914
PP
358 Return 1 if frame information has changed (and windows subsequently
359 refreshed), 0 otherwise. */
360
361int
47d3492a 362tui_show_frame_info (struct frame_info *fi)
c906108c 363{
b5fca6d7 364 int locator_changed_p;
c906108c
SS
365
366 if (fi)
367 {
3add462f 368 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
6ba8e26f 369 int source_already_displayed;
e3eebbd7 370 CORE_ADDR pc;
7d6dd1e9 371
51abb421 372 symtab_and_line sal = find_frame_sal (fi);
7d6dd1e9 373
a38da35d
TT
374 const char *fullname = nullptr;
375 if (sal.symtab != nullptr)
376 fullname = symtab_to_fullname (sal.symtab);
377
378 source_already_displayed = (sal.symtab != 0
379 && TUI_SRC_WIN != nullptr
380 && TUI_SRC_WIN->showing_source_p (fullname));
e3eebbd7
PA
381
382 if (get_frame_pc_if_available (fi, &pc))
b5fca6d7
PP
383 locator_changed_p
384 = tui_set_locator_info (get_frame_arch (fi),
385 (sal.symtab == 0
a38da35d 386 ? "??" : fullname),
b5fca6d7
PP
387 tui_get_function_from_frame (fi),
388 sal.line,
389 pc);
e3eebbd7 390 else
b5fca6d7
PP
391 locator_changed_p
392 = tui_set_locator_info (get_frame_arch (fi),
393 "??", _("<unavailable>"), sal.line, 0);
394
395 /* If the locator information has not changed, then frame information has
396 not changed. If frame information has not changed, then the windows'
397 contents will not change. So don't bother refreshing the windows. */
398 if (!locator_changed_p)
bbcbf914 399 return 0;
e3eebbd7 400
47d3492a 401 tui_show_locator_content ();
ad54d15b 402 for (struct tui_source_window_base *win_info : tui_source_windows ())
c906108c 403 {
6d012f14 404 if (win_info == TUI_SRC_WIN)
c906108c 405 {
9ad7fdef
TT
406 int start_line = (locator->line_no -
407 (win_info->viewport_height / 2)) + 1;
6d012f14
AC
408 if (start_line <= 0)
409 start_line = 1;
c906108c 410
362c05fe 411 struct tui_line_or_address l;
1c5313c5 412
362c05fe
AS
413 l.loa = LOA_LINE;
414 l.u.line_no = start_line;
6ba8e26f 415 if (!(source_already_displayed
3add462f 416 && tui_line_is_displayed (locator->line_no,
9a2b4c1b 417 win_info, TRUE)))
13274fc3
UW
418 tui_update_source_window (win_info, get_frame_arch (fi),
419 sal.symtab, l, TRUE);
c906108c 420 else
a4b99e53 421 {
3add462f 422 l.u.line_no = locator->line_no;
ad54d15b 423 win_info->set_is_exec_point_at (l);
a4b99e53 424 }
c906108c
SS
425 }
426 else
427 {
9ad7fdef
TT
428 CORE_ADDR low;
429
430 if (find_pc_partial_function (get_frame_pc (fi),
431 NULL, &low, NULL) == 0)
432 {
433 /* There is no symbol available for current PC. There is no
434 safe way how to "disassemble backwards". */
435 low = get_frame_pc (fi);
436 }
437 else
438 low = tui_get_low_disassembly_address (get_frame_arch (fi),
439 low, get_frame_pc (fi));
440
441 struct tui_line_or_address a;
442
443 a.loa = LOA_ADDRESS;
444 a.u.addr = low;
445 if (!tui_addr_is_displayed (locator->addr,
446 win_info, TRUE))
447 tui_update_source_window (win_info, get_frame_arch (fi),
448 sal.symtab, a, TRUE);
449 else
c906108c 450 {
9ad7fdef
TT
451 a.u.addr = locator->addr;
452 win_info->set_is_exec_point_at (a);
c906108c
SS
453 }
454 }
9ad7fdef 455
7ba913dc 456 win_info->update_exec_info ();
c906108c 457 }
bbcbf914
PP
458
459 return 1;
c906108c
SS
460 }
461 else
462 {
b5fca6d7
PP
463 locator_changed_p
464 = tui_set_locator_info (NULL, NULL, NULL, 0, (CORE_ADDR) 0);
465
466 if (!locator_changed_p)
bbcbf914 467 return 0;
b5fca6d7 468
47d3492a 469 tui_show_locator_content ();
ad54d15b 470 for (struct tui_source_window_base *win_info : tui_source_windows ())
c906108c 471 {
caf0bc4e 472 tui_clear_source_content (win_info);
7ba913dc 473 win_info->update_exec_info ();
c906108c 474 }
bbcbf914
PP
475
476 return 1;
c906108c 477 }
7d6dd1e9 478}
c906108c 479
6ba8e26f
AC
480/* Function to initialize gdb commands, for tui window stack
481 manipulation. */
2c0b251b 482
c906108c 483void
6ba8e26f 484_initialize_tui_stack (void)
c906108c 485{
9a2b4c1b
MS
486 add_com ("update", class_tui, tui_update_command,
487 _("Update the source window and locator to "
89549d7f 488 "display the current execution point."));
41783295 489}
c906108c 490
7563e053 491/* Command to update the display with the current execution point. */
c906108c 492static void
0b39b52e 493tui_update_command (const char *arg, int from_tty)
c906108c 494{
95a6b0a1 495 execute_command ("frame 0", from_tty);
7563e053 496}