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