Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / tui / tui-stack.c
1 /* TUI display locator.
2
3 Copyright (C) 1998-2022 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 \f
59
60 std::string
61 tui_locator_window::make_status_line () const
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)
118 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
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. */
157 if (tui_current_key_mode == TUI_SINGLE_KEY_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 if (string.size () < status_size)
185 string.puts (n_spaces (status_size - string.size ()));
186 else if (string.size () > status_size)
187 string.string ().erase (status_size, string.size ());
188
189 return std::move (string.string ());
190 }
191
192 /* Get a printable name for the function at the address. The symbol
193 name is demangled if demangling is turned on. Returns a pointer to
194 a static area holding the result. */
195 static char*
196 tui_get_function_from_frame (struct frame_info *fi)
197 {
198 static char name[256];
199 string_file stream;
200
201 print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
202 &stream, demangle, "");
203
204 /* Use simple heuristics to isolate the function name. The symbol
205 can be demangled and we can have function parameters. Remove
206 them because the status line is too short to display them. */
207 const char *d = stream.c_str ();
208 if (*d == '<')
209 d++;
210 strncpy (name, d, sizeof (name) - 1);
211 name[sizeof (name) - 1] = 0;
212
213 char *p = strchr (name, '(');
214 if (!p)
215 p = strchr (name, '>');
216 if (p)
217 *p = 0;
218 p = strchr (name, '+');
219 if (p)
220 *p = 0;
221 return name;
222 }
223
224 void
225 tui_locator_window::rerender ()
226 {
227 gdb_assert (handle != NULL);
228
229 std::string string = make_status_line ();
230 scrollok (handle.get (), FALSE);
231 wmove (handle.get (), 0, 0);
232 /* We ignore the return value from wstandout and wstandend, casting them
233 to void in order to avoid a compiler warning. The warning itself was
234 introduced by a patch to ncurses 5.7 dated 2009-08-29, changing these
235 macro to expand to code that causes the compiler to generate an
236 unused-value warning. */
237 (void) wstandout (handle.get ());
238 waddstr (handle.get (), string.c_str ());
239 wclrtoeol (handle.get ());
240 (void) wstandend (handle.get ());
241 refresh_window ();
242 wmove (handle.get (), 0, 0);
243 }
244
245 /* Function to print the frame information for the TUI. The windows are
246 refreshed only if frame information has changed since the last refresh.
247
248 Return true if frame information has changed (and windows
249 subsequently refreshed), false otherwise. */
250
251 bool
252 tui_show_frame_info (struct frame_info *fi)
253 {
254 bool locator_changed_p;
255
256 if (fi != nullptr)
257 {
258 symtab_and_line sal = find_frame_sal (fi);
259
260 const char *func_name;
261 /* find_frame_sal does not always set PC, but we want to ensure
262 that it is available in the SAL. */
263 if (get_frame_pc_if_available (fi, &sal.pc))
264 func_name = tui_get_function_from_frame (fi);
265 else
266 func_name = _("<unavailable>");
267
268 locator_changed_p
269 = tui_location.set_location (get_frame_arch (fi), sal, func_name);
270
271 /* If the locator information has not changed, then frame information has
272 not changed. If frame information has not changed, then the windows'
273 contents will not change. So don't bother refreshing the windows. */
274 if (!locator_changed_p)
275 return false;
276
277 for (struct tui_source_window_base *win_info : tui_source_windows ())
278 {
279 win_info->maybe_update (fi, sal);
280 win_info->update_exec_info ();
281 }
282 }
283 else
284 {
285 symtab_and_line sal {};
286
287 locator_changed_p = tui_location.set_location (NULL, sal, "");
288
289 if (!locator_changed_p)
290 return false;
291
292 for (struct tui_source_window_base *win_info : tui_source_windows ())
293 win_info->erase_source_content ();
294 }
295
296 return true;
297 }
298
299 void
300 tui_show_locator_content ()
301 {
302 if (tui_is_window_visible (STATUS_WIN))
303 TUI_STATUS_WIN->rerender ();
304 }
305
306 /* Command to update the display with the current execution point. */
307 static void
308 tui_update_command (const char *arg, int from_tty)
309 {
310 execute_command ("frame 0", from_tty);
311 }
312
313 /* Function to initialize gdb commands, for tui window stack
314 manipulation. */
315
316 void _initialize_tui_stack ();
317 void
318 _initialize_tui_stack ()
319 {
320 add_com ("update", class_tui, tui_update_command,
321 _("Update the source window and locator to "
322 "display the current execution point.\n\
323 Usage: update"));
324 }
This page took 0.035038 seconds and 4 git commands to generate.