1 /* TUI display locator.
3 Copyright (C) 1998-2023 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "breakpoint.h"
30 #include "gdb-demangle.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"
39 #include "tui/tui-location.h"
41 #include "gdb_curses.h"
43 #define PROC_PREFIX "In: "
44 #define LINE_PREFIX "L"
45 #define PC_PREFIX "PC: "
47 /* Strings to display in the TUI status line. */
48 #define SINGLE_KEY "(SingleKey)"
50 /* Minimum/Maximum length of some fields displayed in the TUI status
52 #define MIN_LINE_WIDTH 4 /* Use at least 4 digits for line
54 #define MIN_PROC_WIDTH 12
55 #define MAX_TARGET_WIDTH 10
56 #define MAX_PID_WIDTH 19
61 tui_locator_window::make_status_line () const
71 std::string pid_name_holder
;
72 if (inferior_ptid
== null_ptid
)
73 pid_name
= "No process";
76 pid_name_holder
= target_pid_to_str (inferior_ptid
);
77 pid_name
= pid_name_holder
.c_str ();
80 target_width
= strlen (target_shortname ());
81 if (target_width
> MAX_TARGET_WIDTH
)
82 target_width
= MAX_TARGET_WIDTH
;
84 pid_width
= strlen (pid_name
);
85 if (pid_width
> MAX_PID_WIDTH
)
86 pid_width
= MAX_PID_WIDTH
;
90 /* Translate line number and obtain its size. */
91 int line_no
= tui_location
.line_no ();
93 xsnprintf (line_buf
, sizeof (line_buf
), "%d", line_no
);
95 strcpy (line_buf
, "??");
96 line_width
= strlen (line_buf
);
97 if (line_width
< MIN_LINE_WIDTH
)
98 line_width
= MIN_LINE_WIDTH
;
100 /* Translate PC address. */
101 struct gdbarch
*gdbarch
= tui_location
.gdbarch ();
102 CORE_ADDR addr
= tui_location
.addr ();
103 std::string
pc_out (gdbarch
104 ? paddress (gdbarch
, addr
)
106 const char *pc_buf
= pc_out
.c_str ();
107 int pc_width
= pc_out
.size ();
109 /* First determine the amount of proc name width we have available.
110 The +1 are for a space separator between fields.
111 The -1 are to take into account the \0 counted by sizeof. */
112 proc_width
= (status_size
115 - (sizeof (PROC_PREFIX
) - 1 + 1)
116 - (sizeof (LINE_PREFIX
) - 1 + line_width
+ 1)
117 - (sizeof (PC_PREFIX
) - 1 + pc_width
+ 1)
118 - (tui_current_key_mode
== TUI_SINGLE_KEY_MODE
119 ? (sizeof (SINGLE_KEY
) - 1 + 1)
122 /* If there is no room to print the function name, try by removing
124 if (proc_width
< MIN_PROC_WIDTH
)
126 proc_width
+= target_width
+ 1;
128 if (proc_width
< MIN_PROC_WIDTH
)
130 proc_width
+= pid_width
+ 1;
132 if (proc_width
<= MIN_PROC_WIDTH
)
134 proc_width
+= pc_width
+ sizeof (PC_PREFIX
) - 1 + 1;
138 proc_width
+= line_width
+ sizeof (LINE_PREFIX
) - 1 + 1;
147 /* Now create the locator line from the string version of the
151 if (target_width
> 0)
152 string
.printf ("%*.*s ", -target_width
, target_width
, target_shortname ());
154 string
.printf ("%*.*s ", -pid_width
, pid_width
, pid_name
);
156 /* Show whether we are in SingleKey mode. */
157 if (tui_current_key_mode
== TUI_SINGLE_KEY_MODE
)
159 string
.puts (SINGLE_KEY
);
163 /* Procedure/class name. */
166 const std::string
&proc_name
= tui_location
.proc_name ();
167 if (proc_name
.size () > proc_width
)
168 string
.printf ("%s%*.*s* ", PROC_PREFIX
,
169 1 - proc_width
, proc_width
- 1, proc_name
.c_str ());
171 string
.printf ("%s%*.*s ", PROC_PREFIX
,
172 -proc_width
, proc_width
, proc_name
.c_str ());
176 string
.printf ("%s%*.*s ", LINE_PREFIX
,
177 -line_width
, line_width
, line_buf
);
180 string
.puts (PC_PREFIX
);
181 string
.puts (pc_buf
);
184 std::string string_val
= string
.release ();
186 size_t len
= string_val
.size ();
187 if (len
< status_size
)
188 string_val
.append (status_size
- len
, ' ');
189 else if (len
> status_size
)
190 string_val
.erase (status_size
, len
);
192 gdb_assert (string_val
.size () == status_size
);
197 /* Get a printable name for the function at the address. The symbol
198 name is demangled if demangling is turned on. Returns a pointer to
199 a static area holding the result. */
201 tui_get_function_from_frame (frame_info_ptr fi
)
203 static char name
[256];
206 print_address_symbolic (get_frame_arch (fi
), get_frame_pc (fi
),
207 &stream
, demangle
, "");
209 /* Use simple heuristics to isolate the function name. The symbol
210 can be demangled and we can have function parameters. Remove
211 them because the status line is too short to display them. */
212 const char *d
= stream
.c_str ();
215 strncpy (name
, d
, sizeof (name
) - 1);
216 name
[sizeof (name
) - 1] = 0;
218 char *p
= strchr (name
, '(');
220 p
= strchr (name
, '>');
223 p
= strchr (name
, '+');
230 tui_locator_window::rerender ()
232 gdb_assert (handle
!= NULL
);
234 std::string string
= make_status_line ();
235 scrollok (handle
.get (), FALSE
);
236 wmove (handle
.get (), 0, 0);
237 /* We ignore the return value from wstandout and wstandend, casting them
238 to void in order to avoid a compiler warning. The warning itself was
239 introduced by a patch to ncurses 5.7 dated 2009-08-29, changing these
240 macro to expand to code that causes the compiler to generate an
241 unused-value warning. */
242 (void) wstandout (handle
.get ());
243 waddstr (handle
.get (), string
.c_str ());
244 wclrtoeol (handle
.get ());
245 (void) wstandend (handle
.get ());
247 wmove (handle
.get (), 0, 0);
250 /* Function to print the frame information for the TUI. The windows are
251 refreshed only if frame information has changed since the last refresh.
253 Return true if frame information has changed (and windows
254 subsequently refreshed), false otherwise. */
257 tui_show_frame_info (frame_info_ptr fi
)
259 bool locator_changed_p
;
263 symtab_and_line sal
= find_frame_sal (fi
);
265 const char *func_name
;
266 /* find_frame_sal does not always set PC, but we want to ensure
267 that it is available in the SAL. */
268 if (get_frame_pc_if_available (fi
, &sal
.pc
))
269 func_name
= tui_get_function_from_frame (fi
);
271 func_name
= _("<unavailable>");
274 = tui_location
.set_location (get_frame_arch (fi
), sal
, func_name
);
276 /* If the locator information has not changed, then frame information has
277 not changed. If frame information has not changed, then the windows'
278 contents will not change. So don't bother refreshing the windows. */
279 if (!locator_changed_p
)
282 for (struct tui_source_window_base
*win_info
: tui_source_windows ())
284 win_info
->maybe_update (fi
, sal
);
285 win_info
->update_exec_info ();
290 symtab_and_line sal
{};
292 locator_changed_p
= tui_location
.set_location (NULL
, sal
, "");
294 if (!locator_changed_p
)
297 for (struct tui_source_window_base
*win_info
: tui_source_windows ())
298 win_info
->erase_source_content ();
305 tui_show_locator_content ()
307 if (tui_is_window_visible (STATUS_WIN
))
308 TUI_STATUS_WIN
->rerender ();
311 /* Command to update the display with the current execution point. */
313 tui_update_command (const char *arg
, int from_tty
)
315 execute_command ("frame 0", from_tty
);
318 /* Function to initialize gdb commands, for tui window stack
321 void _initialize_tui_stack ();
323 _initialize_tui_stack ()
325 add_com ("update", class_tui
, tui_update_command
,
326 _("Update the source window and locator to "
327 "display the current execution point.\n\