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