GDB (xrefs)
Loading...
Searching...
No Matches
tui-stack.c
Go to the documentation of this file.
1/* TUI display locator.
2
3 Copyright (C) 1998-2023 Free Software Foundation, Inc.
4
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
11 the Free Software Foundation; either version 3 of the License, or
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22#include "defs.h"
23#include "symtab.h"
24#include "breakpoint.h"
25#include "frame.h"
26#include "command.h"
27#include "inferior.h"
28#include "target.h"
29#include "top.h"
30#include "gdb-demangle.h"
31#include "source.h"
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"
39#include "tui/tui-location.h"
40
41#include "gdb_curses.h"
42
43#define PROC_PREFIX "In: "
44#define LINE_PREFIX "L"
45#define PC_PREFIX "PC: "
46
47/* Strings to display in the TUI status line. */
48#define SINGLE_KEY "(SingleKey)"
49
50/* Minimum/Maximum length of some fields displayed in the TUI status
51 line. */
52#define MIN_LINE_WIDTH 4 /* Use at least 4 digits for line
53 numbers. */
54#define MIN_PROC_WIDTH 12
55#define MAX_TARGET_WIDTH 10
56#define MAX_PID_WIDTH 19
57
58
59
60std::string
62{
63 char line_buf[50];
64 int status_size;
65 int proc_width;
66 const char *pid_name;
67 int target_width;
68 int pid_width;
69 int line_width;
70
71 std::string pid_name_holder;
72 if (inferior_ptid == null_ptid)
73 pid_name = "No process";
74 else
75 {
76 pid_name_holder = target_pid_to_str (inferior_ptid);
77 pid_name = pid_name_holder.c_str ();
78 }
79
80 target_width = strlen (target_shortname ());
81 if (target_width > MAX_TARGET_WIDTH)
82 target_width = MAX_TARGET_WIDTH;
83
84 pid_width = strlen (pid_name);
85 if (pid_width > MAX_PID_WIDTH)
86 pid_width = MAX_PID_WIDTH;
87
88 status_size = width;
89
90 /* Translate line number and obtain its size. */
91 int line_no = tui_location.line_no ();
92 if (line_no > 0)
93 xsnprintf (line_buf, sizeof (line_buf), "%d", line_no);
94 else
95 strcpy (line_buf, "??");
96 line_width = strlen (line_buf);
97 if (line_width < MIN_LINE_WIDTH)
98 line_width = MIN_LINE_WIDTH;
99
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)
105 : "??");
106 const char *pc_buf = pc_out.c_str ();
107 int pc_width = pc_out.size ();
108
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
113 - (target_width + 1)
114 - (pid_width + 1)
115 - (sizeof (PROC_PREFIX) - 1 + 1)
116 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
117 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
119 ? (sizeof (SINGLE_KEY) - 1 + 1)
120 : 0));
121
122 /* If there is no room to print the function name, try by removing
123 some fields. */
124 if (proc_width < MIN_PROC_WIDTH)
125 {
126 proc_width += target_width + 1;
127 target_width = 0;
128 if (proc_width < MIN_PROC_WIDTH)
129 {
130 proc_width += pid_width + 1;
131 pid_width = 0;
132 if (proc_width <= MIN_PROC_WIDTH)
133 {
134 proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
135 pc_width = 0;
136 if (proc_width < 0)
137 {
138 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
139 line_width = 0;
140 if (proc_width < 0)
141 proc_width = 0;
142 }
143 }
144 }
145 }
146
147 /* Now create the locator line from the string version of the
148 elements. */
149 string_file string;
150
151 if (target_width > 0)
152 string.printf ("%*.*s ", -target_width, target_width, target_shortname ());
153 if (pid_width > 0)
154 string.printf ("%*.*s ", -pid_width, pid_width, pid_name);
155
156 /* Show whether we are in SingleKey mode. */
158 {
159 string.puts (SINGLE_KEY);
160 string.puts (" ");
161 }
162
163 /* Procedure/class name. */
164 if (proc_width > 0)
165 {
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 ());
170 else
171 string.printf ("%s%*.*s ", PROC_PREFIX,
172 -proc_width, proc_width, proc_name.c_str ());
173 }
174
175 if (line_width > 0)
176 string.printf ("%s%*.*s ", LINE_PREFIX,
177 -line_width, line_width, line_buf);
178 if (pc_width > 0)
179 {
180 string.puts (PC_PREFIX);
181 string.puts (pc_buf);
182 }
183
184 std::string string_val = string.release ();
185
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);
191
192 gdb_assert (string_val.size () == status_size);
193
194 return string_val;
195}
196
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. */
200static char*
202{
203 static char name[256];
204 string_file stream;
205
207 &stream, demangle, "");
208
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 ();
213 if (*d == '<')
214 d++;
215 strncpy (name, d, sizeof (name) - 1);
216 name[sizeof (name) - 1] = 0;
217
218 char *p = strchr (name, '(');
219 if (!p)
220 p = strchr (name, '>');
221 if (p)
222 *p = 0;
223 p = strchr (name, '+');
224 if (p)
225 *p = 0;
226 return name;
227}
228
229void
231{
232 gdb_assert (handle != NULL);
233
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);
248}
249
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.
252
253 Return true if frame information has changed (and windows
254 subsequently refreshed), false otherwise. */
255
256bool
258{
259 bool locator_changed_p;
260
261 if (fi != nullptr)
262 {
264
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);
270 else
271 func_name = _("<unavailable>");
272
273 locator_changed_p
274 = tui_location.set_location (get_frame_arch (fi), sal, func_name);
275
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)
280 return false;
281
282 for (struct tui_source_window_base *win_info : tui_source_windows ())
283 {
284 win_info->maybe_update (fi, sal);
285 win_info->update_exec_info ();
286 }
287 }
288 else
289 {
290 symtab_and_line sal {};
291
292 locator_changed_p = tui_location.set_location (NULL, sal, "");
293
294 if (!locator_changed_p)
295 return false;
296
297 for (struct tui_source_window_base *win_info : tui_source_windows ())
298 win_info->erase_source_content ();
299 }
300
301 return true;
302}
303
304void
306{
308 TUI_STATUS_WIN->rerender ();
309}
310
311/* Command to update the display with the current execution point. */
312static void
313tui_update_command (const char *arg, int from_tty)
314{
315 execute_command ("frame 0", from_tty);
316}
317
318/* Function to initialize gdb commands, for tui window stack
319 manipulation. */
320
322void
324{
326 _("Update the source window and locator to "
327 "display the current execution point.\n\
328Usage: update"));
329}
const char *const name
const char * c_str() const
Definition ui-file.h:222
void printf(const char *,...) ATTRIBUTE_PRINTF(2
Definition ui-file.c:40
struct cmd_list_element * add_com(const char *name, enum command_class theclass, cmd_simple_func_ftype *fun, const char *doc)
@ class_tui
Definition command.h:66
int print_address_symbolic(struct gdbarch *, CORE_ADDR, struct ui_file *, int, const char *)
Definition printcmd.c:554
CORE_ADDR get_frame_pc(frame_info_ptr frame)
Definition frame.c:2712
struct gdbarch * get_frame_arch(frame_info_ptr this_frame)
Definition frame.c:3027
bool get_frame_pc_if_available(frame_info_ptr frame, CORE_ADDR *pc)
Definition frame.c:2719
symtab_and_line find_frame_sal(frame_info_ptr frame)
Definition frame.c:2821
bool demangle
void execute_command(const char *, int)
Definition top.c:459
ptid_t inferior_ptid
Definition infcmd.c:74
CORE_ADDR pc
Definition symtab.h:2337
struct gdbarch * gdbarch() const
const std::string & proc_name() const
CORE_ADDR addr() const
bool set_location(struct gdbarch *gdbarch, const struct symtab_and_line &sal, const char *procname)
void rerender() override
Definition tui-stack.c:229
std::string make_status_line() const
Definition tui-stack.c:60
std::unique_ptr< WINDOW, curses_deleter > handle
Definition tui-data.h:158
virtual void refresh_window()
std::string target_pid_to_str(ptid_t ptid)
Definition target.c:2623
const char * target_shortname()
Definition target.c:216
#define TUI_STATUS_WIN
Definition tui-data.h:199
tui_location_tracker tui_location
#define MAX_TARGET_WIDTH
Definition tui-stack.c:54
#define MIN_LINE_WIDTH
Definition tui-stack.c:52
bool tui_show_frame_info(frame_info_ptr fi)
Definition tui-stack.c:256
static char * tui_get_function_from_frame(frame_info_ptr fi)
Definition tui-stack.c:200
void _initialize_tui_stack()
Definition tui-stack.c:322
#define PROC_PREFIX
Definition tui-stack.c:43
#define LINE_PREFIX
Definition tui-stack.c:44
void tui_show_locator_content()
Definition tui-stack.c:304
#define PC_PREFIX
Definition tui-stack.c:45
#define MIN_PROC_WIDTH
Definition tui-stack.c:53
#define SINGLE_KEY
Definition tui-stack.c:48
static void tui_update_command(const char *arg, int from_tty)
Definition tui-stack.c:312
#define MAX_PID_WIDTH
Definition tui-stack.c:55
enum tui_key_mode tui_current_key_mode
Definition tui.c:76
bool tui_is_window_visible(enum tui_win_type type)
Definition tui.c:581
@ STATUS_WIN
Definition tui.h:58
@ TUI_SINGLE_KEY_MODE
Definition tui.h:86
const char * paddress(struct gdbarch *gdbarch, CORE_ADDR addr)
Definition utils.c:3166