]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/tui/tui-stack.c
Remove tui_clear_source_content
[thirdparty/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 static struct tui_locator_window _locator;
43
44 /* Get a printable name for the function at the address.
45 The symbol name is demangled if demangling is turned on.
46 Returns a pointer to a static area holding the result. */
47 static char *tui_get_function_from_frame (struct frame_info *fi);
48
49 /* Set the full_name portion of the locator. */
50 static void tui_set_locator_fullname (const char *fullname);
51
52 /* Update the locator, with the provided arguments. */
53 static int tui_set_locator_info (struct gdbarch *gdbarch,
54 const char *fullname,
55 const char *procname,
56 int lineno, CORE_ADDR addr);
57
58 static void tui_update_command (const char *, int);
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 void
70 tui_initialize_static_data ()
71 {
72 tui_gen_win_info *win = tui_locator_win_info_ptr ();
73 win->width =
74 win->height =
75 win->origin.x =
76 win->origin.y =
77 win->viewport_height = 0;
78 win->handle = NULL;
79 win->is_visible = false;
80 win->title = 0;
81 }
82
83
84 /* Create the status line to display as much information as we can on
85 this single line: target name, process number, current function,
86 current line, current PC, SingleKey mode. */
87 static char *
88 tui_make_status_line (struct tui_locator_window *loc)
89 {
90 char *string;
91 char line_buf[50], *pname;
92 char *buf;
93 int status_size;
94 int i, proc_width;
95 const char *pid_name;
96 int target_width;
97 int pid_width;
98 int line_width;
99
100 std::string pid_name_holder;
101 if (inferior_ptid == null_ptid)
102 pid_name = "No process";
103 else
104 {
105 pid_name_holder = target_pid_to_str (inferior_ptid);
106 pid_name = pid_name_holder.c_str ();
107 }
108
109 target_width = strlen (target_shortname);
110 if (target_width > MAX_TARGET_WIDTH)
111 target_width = MAX_TARGET_WIDTH;
112
113 pid_width = strlen (pid_name);
114 if (pid_width > MAX_PID_WIDTH)
115 pid_width = MAX_PID_WIDTH;
116
117 status_size = tui_term_width ();
118 string = (char *) xmalloc (status_size + 1);
119 buf = (char*) alloca (status_size + 1);
120
121 /* Translate line number and obtain its size. */
122 if (loc->line_no > 0)
123 xsnprintf (line_buf, sizeof (line_buf), "%d", loc->line_no);
124 else
125 strcpy (line_buf, "??");
126 line_width = strlen (line_buf);
127 if (line_width < MIN_LINE_WIDTH)
128 line_width = MIN_LINE_WIDTH;
129
130 /* Translate PC address. */
131 std::string pc_out (loc->gdbarch
132 ? paddress (loc->gdbarch, loc->addr)
133 : "??");
134 const char *pc_buf = pc_out.c_str ();
135 int pc_width = pc_out.size ();
136
137 /* First determine the amount of proc name width we have available.
138 The +1 are for a space separator between fields.
139 The -1 are to take into account the \0 counted by sizeof. */
140 proc_width = (status_size
141 - (target_width + 1)
142 - (pid_width + 1)
143 - (sizeof (PROC_PREFIX) - 1 + 1)
144 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
145 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
146 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
147 ? (sizeof (SINGLE_KEY) - 1 + 1)
148 : 0));
149
150 /* If there is no room to print the function name, try by removing
151 some fields. */
152 if (proc_width < MIN_PROC_WIDTH)
153 {
154 proc_width += target_width + 1;
155 target_width = 0;
156 if (proc_width < MIN_PROC_WIDTH)
157 {
158 proc_width += pid_width + 1;
159 pid_width = 0;
160 if (proc_width <= MIN_PROC_WIDTH)
161 {
162 proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
163 pc_width = 0;
164 if (proc_width < 0)
165 {
166 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
167 line_width = 0;
168 if (proc_width < 0)
169 proc_width = 0;
170 }
171 }
172 }
173 }
174
175 /* Now convert elements to string form. */
176 pname = loc->proc_name;
177
178 /* Now create the locator line from the string version of the
179 elements. We could use sprintf() here but that wouldn't ensure
180 that we don't overrun the size of the allocated buffer.
181 strcat_to_buf() will. */
182 *string = (char) 0;
183
184 if (target_width > 0)
185 {
186 sprintf (buf, "%*.*s ",
187 -target_width, target_width, target_shortname);
188 strcat_to_buf (string, status_size, buf);
189 }
190 if (pid_width > 0)
191 {
192 sprintf (buf, "%*.*s ",
193 -pid_width, pid_width, pid_name);
194 strcat_to_buf (string, status_size, buf);
195 }
196
197 /* Show whether we are in SingleKey mode. */
198 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
199 {
200 strcat_to_buf (string, status_size, SINGLE_KEY);
201 strcat_to_buf (string, status_size, " ");
202 }
203
204 /* Procedure/class name. */
205 if (proc_width > 0)
206 {
207 if (strlen (pname) > proc_width)
208 sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
209 1 - proc_width, proc_width - 1, pname);
210 else
211 sprintf (buf, "%s%*.*s ", PROC_PREFIX,
212 -proc_width, proc_width, pname);
213 strcat_to_buf (string, status_size, buf);
214 }
215
216 if (line_width > 0)
217 {
218 sprintf (buf, "%s%*.*s ", LINE_PREFIX,
219 -line_width, line_width, line_buf);
220 strcat_to_buf (string, status_size, buf);
221 }
222 if (pc_width > 0)
223 {
224 strcat_to_buf (string, status_size, PC_PREFIX);
225 strcat_to_buf (string, status_size, pc_buf);
226 }
227
228
229 for (i = strlen (string); i < status_size; i++)
230 string[i] = ' ';
231 string[status_size] = (char) 0;
232
233 return string;
234 }
235
236 /* Get a printable name for the function at the address. The symbol
237 name is demangled if demangling is turned on. Returns a pointer to
238 a static area holding the result. */
239 static char*
240 tui_get_function_from_frame (struct frame_info *fi)
241 {
242 static char name[256];
243 string_file stream;
244
245 print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
246 &stream, demangle, "");
247
248 /* Use simple heuristics to isolate the function name. The symbol
249 can be demangled and we can have function parameters. Remove
250 them because the status line is too short to display them. */
251 const char *d = stream.c_str ();
252 if (*d == '<')
253 d++;
254 strncpy (name, d, sizeof (name) - 1);
255 name[sizeof (name) - 1] = 0;
256
257 char *p = strchr (name, '(');
258 if (!p)
259 p = strchr (name, '>');
260 if (p)
261 *p = 0;
262 p = strchr (name, '+');
263 if (p)
264 *p = 0;
265 return name;
266 }
267
268 void
269 tui_show_locator_content (void)
270 {
271 char *string;
272 struct tui_locator_window *locator;
273
274 locator = tui_locator_win_info_ptr ();
275
276 if (locator != NULL && locator->handle != NULL)
277 {
278 string = tui_make_status_line (locator);
279 wmove (locator->handle, 0, 0);
280 /* We ignore the return value from wstandout and wstandend, casting
281 them to void in order to avoid a compiler warning. The warning
282 itself was introduced by a patch to ncurses 5.7 dated 2009-08-29,
283 changing these macro to expand to code that causes the compiler
284 to generate an unused-value warning. */
285 (void) wstandout (locator->handle);
286 waddstr (locator->handle, string);
287 wclrtoeol (locator->handle);
288 (void) wstandend (locator->handle);
289 locator->refresh_window ();
290 wmove (locator->handle, 0, 0);
291 xfree (string);
292 }
293 }
294
295
296 /* Set the filename portion of the locator. */
297 static void
298 tui_set_locator_fullname (const char *fullname)
299 {
300 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
301
302 locator->full_name[0] = 0;
303 strcat_to_buf (locator->full_name, MAX_LOCATOR_ELEMENT_LEN, fullname);
304 }
305
306 /* Update the locator, with the provided arguments.
307
308 Returns 1 if any of the locator's fields were actually changed,
309 and 0 otherwise. */
310
311 static int
312 tui_set_locator_info (struct gdbarch *gdbarch,
313 const char *fullname,
314 const char *procname,
315 int lineno,
316 CORE_ADDR addr)
317 {
318 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
319 int locator_changed_p = 0;
320
321 if (procname == NULL)
322 procname = "";
323
324 if (fullname == NULL)
325 fullname = "";
326
327 locator_changed_p |= strncmp (locator->proc_name, procname,
328 MAX_LOCATOR_ELEMENT_LEN) != 0;
329 locator_changed_p |= lineno != locator->line_no;
330 locator_changed_p |= addr != locator->addr;
331 locator_changed_p |= gdbarch != locator->gdbarch;
332 locator_changed_p |= strncmp (locator->full_name, fullname,
333 MAX_LOCATOR_ELEMENT_LEN) != 0;
334
335 locator->proc_name[0] = (char) 0;
336 strcat_to_buf (locator->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
337 locator->line_no = lineno;
338 locator->addr = addr;
339 locator->gdbarch = gdbarch;
340 tui_set_locator_fullname (fullname);
341
342 return locator_changed_p;
343 }
344
345 /* Update only the full_name portion of the locator. */
346 void
347 tui_update_locator_fullname (const char *fullname)
348 {
349 tui_set_locator_fullname (fullname);
350 tui_show_locator_content ();
351 }
352
353 /* Function to print the frame information for the TUI. The windows are
354 refreshed only if frame information has changed since the last refresh.
355
356 Return 1 if frame information has changed (and windows subsequently
357 refreshed), 0 otherwise. */
358
359 int
360 tui_show_frame_info (struct frame_info *fi)
361 {
362 int locator_changed_p;
363
364 if (fi)
365 {
366 struct tui_locator_window *locator = tui_locator_win_info_ptr ();
367 CORE_ADDR pc;
368
369 symtab_and_line sal = find_frame_sal (fi);
370
371 const char *fullname = nullptr;
372 if (sal.symtab != nullptr)
373 fullname = symtab_to_fullname (sal.symtab);
374
375 if (get_frame_pc_if_available (fi, &pc))
376 locator_changed_p
377 = tui_set_locator_info (get_frame_arch (fi),
378 (sal.symtab == 0
379 ? "??" : fullname),
380 tui_get_function_from_frame (fi),
381 sal.line,
382 pc);
383 else
384 locator_changed_p
385 = tui_set_locator_info (get_frame_arch (fi),
386 "??", _("<unavailable>"), sal.line, 0);
387
388 /* If the locator information has not changed, then frame information has
389 not changed. If frame information has not changed, then the windows'
390 contents will not change. So don't bother refreshing the windows. */
391 if (!locator_changed_p)
392 return 0;
393
394 tui_show_locator_content ();
395 for (struct tui_source_window_base *win_info : tui_source_windows ())
396 {
397 win_info->maybe_update (fi, sal, locator->line_no, locator->addr);
398 win_info->update_exec_info ();
399 }
400
401 return 1;
402 }
403 else
404 {
405 locator_changed_p
406 = tui_set_locator_info (NULL, NULL, NULL, 0, (CORE_ADDR) 0);
407
408 if (!locator_changed_p)
409 return 0;
410
411 tui_show_locator_content ();
412 for (struct tui_source_window_base *win_info : tui_source_windows ())
413 {
414 win_info->erase_source_content ();
415 win_info->update_exec_info ();
416 }
417
418 return 1;
419 }
420 }
421
422 /* Function to initialize gdb commands, for tui window stack
423 manipulation. */
424
425 void
426 _initialize_tui_stack (void)
427 {
428 add_com ("update", class_tui, tui_update_command,
429 _("Update the source window and locator to "
430 "display the current execution point."));
431 }
432
433 /* Command to update the display with the current execution point. */
434 static void
435 tui_update_command (const char *arg, int from_tty)
436 {
437 execute_command ("frame 0", from_tty);
438 }