Fix GDB busy loop when interrupting non-stop program (PR 26199)
[deliverable/binutils-gdb.git] / gdb / tui / tui-stack.c
1 /* TUI display locator.
2
3 Copyright (C) 1998-2020 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
40 #include "gdb_curses.h"
41
42 #define PROC_PREFIX "In: "
43 #define LINE_PREFIX "L"
44 #define PC_PREFIX "PC: "
45
46 /* Strings to display in the TUI status line. */
47 #define SINGLE_KEY "(SingleKey)"
48
49 /* Minimum/Maximum length of some fields displayed in the TUI status
50 line. */
51 #define MIN_LINE_WIDTH 4 /* Use at least 4 digits for line
52 numbers. */
53 #define MIN_PROC_WIDTH 12
54 #define MAX_TARGET_WIDTH 10
55 #define MAX_PID_WIDTH 19
56
57 static struct tui_locator_window _locator;
58
59 \f
60
61 /* Accessor for the locator win info. Answers a pointer to the static
62 locator win info struct. */
63 struct tui_locator_window *
64 tui_locator_win_info_ptr (void)
65 {
66 return &_locator;
67 }
68
69 std::string
70 tui_locator_window::make_status_line () const
71 {
72 char line_buf[50];
73 int status_size;
74 int proc_width;
75 const char *pid_name;
76 int target_width;
77 int pid_width;
78 int line_width;
79
80 std::string pid_name_holder;
81 if (inferior_ptid == null_ptid)
82 pid_name = "No process";
83 else
84 {
85 pid_name_holder = target_pid_to_str (inferior_ptid);
86 pid_name = pid_name_holder.c_str ();
87 }
88
89 target_width = strlen (target_shortname);
90 if (target_width > MAX_TARGET_WIDTH)
91 target_width = MAX_TARGET_WIDTH;
92
93 pid_width = strlen (pid_name);
94 if (pid_width > MAX_PID_WIDTH)
95 pid_width = MAX_PID_WIDTH;
96
97 status_size = width;
98
99 /* Translate line number and obtain its size. */
100 if (line_no > 0)
101 xsnprintf (line_buf, sizeof (line_buf), "%d", line_no);
102 else
103 strcpy (line_buf, "??");
104 line_width = strlen (line_buf);
105 if (line_width < MIN_LINE_WIDTH)
106 line_width = MIN_LINE_WIDTH;
107
108 /* Translate PC address. */
109 std::string pc_out (gdbarch
110 ? paddress (gdbarch, addr)
111 : "??");
112 const char *pc_buf = pc_out.c_str ();
113 int pc_width = pc_out.size ();
114
115 /* First determine the amount of proc name width we have available.
116 The +1 are for a space separator between fields.
117 The -1 are to take into account the \0 counted by sizeof. */
118 proc_width = (status_size
119 - (target_width + 1)
120 - (pid_width + 1)
121 - (sizeof (PROC_PREFIX) - 1 + 1)
122 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
123 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
124 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
125 ? (sizeof (SINGLE_KEY) - 1 + 1)
126 : 0));
127
128 /* If there is no room to print the function name, try by removing
129 some fields. */
130 if (proc_width < MIN_PROC_WIDTH)
131 {
132 proc_width += target_width + 1;
133 target_width = 0;
134 if (proc_width < MIN_PROC_WIDTH)
135 {
136 proc_width += pid_width + 1;
137 pid_width = 0;
138 if (proc_width <= MIN_PROC_WIDTH)
139 {
140 proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
141 pc_width = 0;
142 if (proc_width < 0)
143 {
144 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
145 line_width = 0;
146 if (proc_width < 0)
147 proc_width = 0;
148 }
149 }
150 }
151 }
152
153 /* Now create the locator line from the string version of the
154 elements. */
155 string_file string;
156
157 if (target_width > 0)
158 string.printf ("%*.*s ", -target_width, target_width, target_shortname);
159 if (pid_width > 0)
160 string.printf ("%*.*s ", -pid_width, pid_width, pid_name);
161
162 /* Show whether we are in SingleKey mode. */
163 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
164 {
165 string.puts (SINGLE_KEY);
166 string.puts (" ");
167 }
168
169 /* Procedure/class name. */
170 if (proc_width > 0)
171 {
172 if (proc_name.size () > proc_width)
173 string.printf ("%s%*.*s* ", PROC_PREFIX,
174 1 - proc_width, proc_width - 1, proc_name.c_str ());
175 else
176 string.printf ("%s%*.*s ", PROC_PREFIX,
177 -proc_width, proc_width, proc_name.c_str ());
178 }
179
180 if (line_width > 0)
181 string.printf ("%s%*.*s ", LINE_PREFIX,
182 -line_width, line_width, line_buf);
183 if (pc_width > 0)
184 {
185 string.puts (PC_PREFIX);
186 string.puts (pc_buf);
187 }
188
189 if (string.size () < status_size)
190 string.puts (n_spaces (status_size - string.size ()));
191 else if (string.size () > status_size)
192 string.string ().erase (status_size, string.size ());
193
194 return std::move (string.string ());
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. */
200 static char*
201 tui_get_function_from_frame (struct frame_info *fi)
202 {
203 static char name[256];
204 string_file stream;
205
206 print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
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
229 void
230 tui_locator_window::rerender ()
231 {
232 if (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
238 them to void in order to avoid a compiler warning. The warning
239 itself was introduced by a patch to ncurses 5.7 dated 2009-08-29,
240 changing these macro to expand to code that causes the compiler
241 to generate an unused-value warning. */
242 (void) wstandout (handle.get ());
243 waddstr (handle.get (), string.c_str ());
244 wclrtoeol (handle.get ());
245 (void) wstandend (handle.get ());
246 refresh_window ();
247 wmove (handle.get (), 0, 0);
248 }
249 }
250
251 /* See tui-stack.h. */
252
253 void
254 tui_locator_window::set_locator_fullname (const char *fullname)
255 {
256 full_name = fullname;
257 rerender ();
258 }
259
260 /* See tui-stack.h. */
261
262 bool
263 tui_locator_window::set_locator_info (struct gdbarch *gdbarch_in,
264 const struct symtab_and_line &sal,
265 const char *procname)
266 {
267 bool locator_changed_p = false;
268
269 gdb_assert (procname != NULL);
270
271 const char *fullname = (sal.symtab == nullptr
272 ? "??"
273 : symtab_to_fullname (sal.symtab));
274
275 locator_changed_p |= proc_name != procname;
276 locator_changed_p |= sal.line != line_no;
277 locator_changed_p |= sal.pc != addr;
278 locator_changed_p |= gdbarch_in != gdbarch;
279 locator_changed_p |= full_name != fullname;
280
281 proc_name = procname;
282 line_no = sal.line;
283 addr = sal.pc;
284 gdbarch = gdbarch_in;
285 set_locator_fullname (fullname);
286
287 return locator_changed_p;
288 }
289
290 /* Update only the full_name portion of the locator. */
291 void
292 tui_update_locator_fullname (struct symtab *symtab)
293 {
294 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
295
296 const char *fullname;
297 if (symtab != nullptr)
298 fullname = symtab_to_fullname (symtab);
299 else
300 fullname = "??";
301 locator->set_locator_fullname (fullname);
302 }
303
304 /* Function to print the frame information for the TUI. The windows are
305 refreshed only if frame information has changed since the last refresh.
306
307 Return true if frame information has changed (and windows
308 subsequently refreshed), false otherwise. */
309
310 bool
311 tui_show_frame_info (struct frame_info *fi)
312 {
313 bool locator_changed_p;
314 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
315
316 if (fi)
317 {
318 symtab_and_line sal = find_frame_sal (fi);
319
320 const char *func_name;
321 /* find_frame_sal does not always set PC, but we want to ensure
322 that it is available in the SAL. */
323 if (get_frame_pc_if_available (fi, &sal.pc))
324 func_name = tui_get_function_from_frame (fi);
325 else
326 func_name = _("<unavailable>");
327
328 locator_changed_p = locator->set_locator_info (get_frame_arch (fi),
329 sal, func_name);
330
331 /* If the locator information has not changed, then frame information has
332 not changed. If frame information has not changed, then the windows'
333 contents will not change. So don't bother refreshing the windows. */
334 if (!locator_changed_p)
335 return false;
336
337 for (struct tui_source_window_base *win_info : tui_source_windows ())
338 {
339 win_info->maybe_update (fi, sal);
340 win_info->update_exec_info ();
341 }
342 }
343 else
344 {
345 symtab_and_line sal {};
346
347 locator_changed_p = locator->set_locator_info (NULL, sal, "");
348
349 if (!locator_changed_p)
350 return false;
351
352 for (struct tui_source_window_base *win_info : tui_source_windows ())
353 win_info->erase_source_content ();
354 }
355
356 return true;
357 }
358
359 void
360 tui_show_locator_content ()
361 {
362 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
363 locator->rerender ();
364 }
365
366 /* Command to update the display with the current execution point. */
367 static void
368 tui_update_command (const char *arg, int from_tty)
369 {
370 execute_command ("frame 0", from_tty);
371 }
372
373 /* Function to initialize gdb commands, for tui window stack
374 manipulation. */
375
376 void _initialize_tui_stack ();
377 void
378 _initialize_tui_stack ()
379 {
380 add_com ("update", class_tui, tui_update_command,
381 _("Update the source window and locator to "
382 "display the current execution point.\n\
383 Usage: update"));
384 }
This page took 0.042 seconds and 4 git commands to generate.