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