1 /* TUI display locator.
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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.
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.
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/>. */
24 #include "breakpoint.h"
30 #include "gdb-demangle.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"
40 #include "gdb_curses.h"
42 #define PROC_PREFIX "In: "
43 #define LINE_PREFIX "L"
44 #define PC_PREFIX "PC: "
46 /* Minimum/Maximum length of some fields displayed in the TUI status
48 #define MIN_LINE_WIDTH 4 /* Use at least 4 digits for line
50 #define MIN_PROC_WIDTH 12
51 #define MAX_TARGET_WIDTH 10
52 #define MAX_PID_WIDTH 19
54 static struct tui_locator_window _locator
;
56 /* Get a printable name for the function at the address.
57 The symbol name is demangled if demangling is turned on.
58 Returns a pointer to a static area holding the result. */
59 static char *tui_get_function_from_frame (struct frame_info
*fi
);
61 /* Set the full_name portion of the locator. */
62 static void tui_set_locator_fullname (const char *fullname
);
64 /* Update the locator, with the provided arguments. */
65 static int tui_set_locator_info (struct gdbarch
*gdbarch
,
68 int lineno
, CORE_ADDR addr
);
70 static void tui_update_command (const char *, int);
73 /* Accessor for the locator win info. Answers a pointer to the static
74 locator win info struct. */
75 struct tui_locator_window
*
76 tui_locator_win_info_ptr (void)
81 /* Create the status line to display as much information as we can on
82 this single line: target name, process number, current function,
83 current line, current PC, SingleKey mode. */
85 tui_make_status_line (struct tui_locator_window
*loc
)
88 char line_buf
[50], *pname
;
97 std::string pid_name_holder
;
98 if (inferior_ptid
== null_ptid
)
99 pid_name
= "No process";
102 pid_name_holder
= target_pid_to_str (inferior_ptid
);
103 pid_name
= pid_name_holder
.c_str ();
106 target_width
= strlen (target_shortname
);
107 if (target_width
> MAX_TARGET_WIDTH
)
108 target_width
= MAX_TARGET_WIDTH
;
110 pid_width
= strlen (pid_name
);
111 if (pid_width
> MAX_PID_WIDTH
)
112 pid_width
= MAX_PID_WIDTH
;
114 status_size
= tui_term_width ();
115 string
= (char *) xmalloc (status_size
+ 1);
116 buf
= (char*) alloca (status_size
+ 1);
118 /* Translate line number and obtain its size. */
119 if (loc
->line_no
> 0)
120 xsnprintf (line_buf
, sizeof (line_buf
), "%d", loc
->line_no
);
122 strcpy (line_buf
, "??");
123 line_width
= strlen (line_buf
);
124 if (line_width
< MIN_LINE_WIDTH
)
125 line_width
= MIN_LINE_WIDTH
;
127 /* Translate PC address. */
128 std::string
pc_out (loc
->gdbarch
129 ? paddress (loc
->gdbarch
, loc
->addr
)
131 const char *pc_buf
= pc_out
.c_str ();
132 int pc_width
= pc_out
.size ();
134 /* First determine the amount of proc name width we have available.
135 The +1 are for a space separator between fields.
136 The -1 are to take into account the \0 counted by sizeof. */
137 proc_width
= (status_size
140 - (sizeof (PROC_PREFIX
) - 1 + 1)
141 - (sizeof (LINE_PREFIX
) - 1 + line_width
+ 1)
142 - (sizeof (PC_PREFIX
) - 1 + pc_width
+ 1)
143 - (tui_current_key_mode
== TUI_SINGLE_KEY_MODE
144 ? (sizeof (SINGLE_KEY
) - 1 + 1)
147 /* If there is no room to print the function name, try by removing
149 if (proc_width
< MIN_PROC_WIDTH
)
151 proc_width
+= target_width
+ 1;
153 if (proc_width
< MIN_PROC_WIDTH
)
155 proc_width
+= pid_width
+ 1;
157 if (proc_width
<= MIN_PROC_WIDTH
)
159 proc_width
+= pc_width
+ sizeof (PC_PREFIX
) - 1 + 1;
163 proc_width
+= line_width
+ sizeof (LINE_PREFIX
) - 1 + 1;
172 /* Now convert elements to string form. */
173 pname
= loc
->proc_name
;
175 /* Now create the locator line from the string version of the
176 elements. We could use sprintf() here but that wouldn't ensure
177 that we don't overrun the size of the allocated buffer.
178 strcat_to_buf() will. */
181 if (target_width
> 0)
183 sprintf (buf
, "%*.*s ",
184 -target_width
, target_width
, target_shortname
);
185 strcat_to_buf (string
, status_size
, buf
);
189 sprintf (buf
, "%*.*s ",
190 -pid_width
, pid_width
, pid_name
);
191 strcat_to_buf (string
, status_size
, buf
);
194 /* Show whether we are in SingleKey mode. */
195 if (tui_current_key_mode
== TUI_SINGLE_KEY_MODE
)
197 strcat_to_buf (string
, status_size
, SINGLE_KEY
);
198 strcat_to_buf (string
, status_size
, " ");
201 /* Procedure/class name. */
204 if (strlen (pname
) > proc_width
)
205 sprintf (buf
, "%s%*.*s* ", PROC_PREFIX
,
206 1 - proc_width
, proc_width
- 1, pname
);
208 sprintf (buf
, "%s%*.*s ", PROC_PREFIX
,
209 -proc_width
, proc_width
, pname
);
210 strcat_to_buf (string
, status_size
, buf
);
215 sprintf (buf
, "%s%*.*s ", LINE_PREFIX
,
216 -line_width
, line_width
, line_buf
);
217 strcat_to_buf (string
, status_size
, buf
);
221 strcat_to_buf (string
, status_size
, PC_PREFIX
);
222 strcat_to_buf (string
, status_size
, pc_buf
);
226 for (i
= strlen (string
); i
< status_size
; i
++)
228 string
[status_size
] = (char) 0;
233 /* Get a printable name for the function at the address. The symbol
234 name is demangled if demangling is turned on. Returns a pointer to
235 a static area holding the result. */
237 tui_get_function_from_frame (struct frame_info
*fi
)
239 static char name
[256];
242 print_address_symbolic (get_frame_arch (fi
), get_frame_pc (fi
),
243 &stream
, demangle
, "");
245 /* Use simple heuristics to isolate the function name. The symbol
246 can be demangled and we can have function parameters. Remove
247 them because the status line is too short to display them. */
248 const char *d
= stream
.c_str ();
251 strncpy (name
, d
, sizeof (name
) - 1);
252 name
[sizeof (name
) - 1] = 0;
254 char *p
= strchr (name
, '(');
256 p
= strchr (name
, '>');
259 p
= strchr (name
, '+');
266 tui_show_locator_content (void)
269 struct tui_locator_window
*locator
;
271 locator
= tui_locator_win_info_ptr ();
273 if (locator
!= NULL
&& locator
->handle
!= NULL
)
275 string
= tui_make_status_line (locator
);
276 wmove (locator
->handle
, 0, 0);
277 /* We ignore the return value from wstandout and wstandend, casting
278 them to void in order to avoid a compiler warning. The warning
279 itself was introduced by a patch to ncurses 5.7 dated 2009-08-29,
280 changing these macro to expand to code that causes the compiler
281 to generate an unused-value warning. */
282 (void) wstandout (locator
->handle
);
283 waddstr (locator
->handle
, string
);
284 wclrtoeol (locator
->handle
);
285 (void) wstandend (locator
->handle
);
286 locator
->refresh_window ();
287 wmove (locator
->handle
, 0, 0);
293 tui_locator_window::rerender ()
295 tui_show_locator_content ();
298 /* Set the filename portion of the locator. */
300 tui_set_locator_fullname (const char *fullname
)
302 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
304 locator
->full_name
[0] = 0;
305 strcat_to_buf (locator
->full_name
, MAX_LOCATOR_ELEMENT_LEN
, fullname
);
308 /* Update the locator, with the provided arguments.
310 Returns 1 if any of the locator's fields were actually changed,
314 tui_set_locator_info (struct gdbarch
*gdbarch
,
315 const char *fullname
,
316 const char *procname
,
320 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
321 int locator_changed_p
= 0;
323 if (procname
== NULL
)
326 if (fullname
== NULL
)
329 locator_changed_p
|= strncmp (locator
->proc_name
, procname
,
330 MAX_LOCATOR_ELEMENT_LEN
) != 0;
331 locator_changed_p
|= lineno
!= locator
->line_no
;
332 locator_changed_p
|= addr
!= locator
->addr
;
333 locator_changed_p
|= gdbarch
!= locator
->gdbarch
;
334 locator_changed_p
|= strncmp (locator
->full_name
, fullname
,
335 MAX_LOCATOR_ELEMENT_LEN
) != 0;
337 locator
->proc_name
[0] = (char) 0;
338 strcat_to_buf (locator
->proc_name
, MAX_LOCATOR_ELEMENT_LEN
, procname
);
339 locator
->line_no
= lineno
;
340 locator
->addr
= addr
;
341 locator
->gdbarch
= gdbarch
;
342 tui_set_locator_fullname (fullname
);
344 return locator_changed_p
;
347 /* Update only the full_name portion of the locator. */
349 tui_update_locator_fullname (const char *fullname
)
351 tui_set_locator_fullname (fullname
);
352 tui_show_locator_content ();
355 /* Function to print the frame information for the TUI. The windows are
356 refreshed only if frame information has changed since the last refresh.
358 Return 1 if frame information has changed (and windows subsequently
359 refreshed), 0 otherwise. */
362 tui_show_frame_info (struct frame_info
*fi
)
364 int locator_changed_p
;
368 struct tui_locator_window
*locator
= tui_locator_win_info_ptr ();
371 symtab_and_line sal
= find_frame_sal (fi
);
373 const char *fullname
= nullptr;
374 if (sal
.symtab
!= nullptr)
375 fullname
= symtab_to_fullname (sal
.symtab
);
377 if (get_frame_pc_if_available (fi
, &pc
))
379 = tui_set_locator_info (get_frame_arch (fi
),
382 tui_get_function_from_frame (fi
),
387 = tui_set_locator_info (get_frame_arch (fi
),
388 "??", _("<unavailable>"), sal
.line
, 0);
390 /* If the locator information has not changed, then frame information has
391 not changed. If frame information has not changed, then the windows'
392 contents will not change. So don't bother refreshing the windows. */
393 if (!locator_changed_p
)
396 tui_show_locator_content ();
397 for (struct tui_source_window_base
*win_info
: tui_source_windows ())
399 win_info
->maybe_update (fi
, sal
, locator
->line_no
, locator
->addr
);
400 win_info
->update_exec_info ();
408 = tui_set_locator_info (NULL
, NULL
, NULL
, 0, (CORE_ADDR
) 0);
410 if (!locator_changed_p
)
413 tui_show_locator_content ();
414 for (struct tui_source_window_base
*win_info
: tui_source_windows ())
416 win_info
->erase_source_content ();
417 win_info
->update_exec_info ();
424 /* Function to initialize gdb commands, for tui window stack
428 _initialize_tui_stack (void)
430 add_com ("update", class_tui
, tui_update_command
,
431 _("Update the source window and locator to "
432 "display the current execution point."));
435 /* Command to update the display with the current execution point. */
437 tui_update_command (const char *arg
, int from_tty
)
439 execute_command ("frame 0", from_tty
);