Revert "do_target_wait_1: Clear TARGET_WNOHANG if the target isn't async."
[binutils-gdb.git] / gdb / tui / tui-stack.c
index 6bd3b58188030c17b5b1e0a9c0d39c7c892f1578..be8ffbd0c124010053a320f98ace0263476ff488 100644 (file)
@@ -1,7 +1,6 @@
 /* TUI display locator.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1998-2022 Free Software Foundation, Inc.
 
    Contributed by Hewlett-Packard Company.
 
@@ -9,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -30,7 +27,8 @@
 #include "inferior.h"
 #include "target.h"
 #include "top.h"
-#include "gdb_string.h"
+#include "gdb-demangle.h"
+#include "source.h"
 #include "tui/tui.h"
 #include "tui/tui-data.h"
 #include "tui/tui-stack.h"
 #include "tui/tui-source.h"
 #include "tui/tui-winsource.h"
 #include "tui/tui-file.h"
+#include "tui/tui-location.h"
 
 #include "gdb_curses.h"
 
-/* Get a printable name for the function at the address.
-   The symbol name is demangled if demangling is turned on.
-   Returns a pointer to a static area holding the result.  */
-static char* tui_get_function_from_frame (struct frame_info *fi);
+#define PROC_PREFIX             "In: "
+#define LINE_PREFIX             "L"
+#define PC_PREFIX               "PC: "
 
-/* Set the filename portion of the locator.  */
-static void tui_set_locator_filename (const char *filename);
+/* Strings to display in the TUI status line.  */
+#define SINGLE_KEY              "(SingleKey)"
 
-/* Update the locator, with the provided arguments.  */
-static void tui_set_locator_info (const char *filename, const char *procname,
-                                  int lineno, CORE_ADDR addr);
+/* Minimum/Maximum length of some fields displayed in the TUI status
+   line.  */
+#define MIN_LINE_WIDTH     4   /* Use at least 4 digits for line
+                                  numbers.  */
+#define MIN_PROC_WIDTH    12
+#define MAX_TARGET_WIDTH  10
+#define MAX_PID_WIDTH     19
 
-static void tui_update_command (char *, int);
 \f
 
-/* Create the status line to display as much information as we
-   can on this single line: target name, process number, current
-   function, current line, current PC, SingleKey mode.  */
-static char*
-tui_make_status_line (struct tui_locator_element* loc)
+std::string
+tui_locator_window::make_status_line () const
 {
-  char* string;
-  char line_buf[50], *pname;
-  char* buf;
+  char line_buf[50];
   int status_size;
-  int i, proc_width;
-  const char* pid_name;
-  const char* pc_buf;
+  int proc_width;
+  const char *pid_name;
   int target_width;
   int pid_width;
   int line_width;
-  int pc_width;
-  struct ui_file *pc_out;
 
-  if (ptid_equal (inferior_ptid, null_ptid))
+  std::string pid_name_holder;
+  if (inferior_ptid == null_ptid)
     pid_name = "No process";
   else
-    pid_name = target_pid_to_str (inferior_ptid);
+    {
+      pid_name_holder = target_pid_to_str (inferior_ptid);
+      pid_name = pid_name_holder.c_str ();
+    }
 
-  target_width = strlen (target_shortname);
+  target_width = strlen (target_shortname ());
   if (target_width > MAX_TARGET_WIDTH)
     target_width = MAX_TARGET_WIDTH;
 
@@ -88,13 +85,12 @@ tui_make_status_line (struct tui_locator_element* loc)
   if (pid_width > MAX_PID_WIDTH)
     pid_width = MAX_PID_WIDTH;
 
-  status_size = tui_term_width ();
-  string = (char *) xmalloc (status_size + 1);
-  buf = (char*) alloca (status_size + 1);
+  status_size = width;
 
   /* Translate line number and obtain its size.  */
-  if (loc->line_no > 0)
-    sprintf (line_buf, "%d", loc->line_no);
+  int line_no = tui_location.line_no ();
+  if (line_no > 0)
+    xsnprintf (line_buf, sizeof (line_buf), "%d", line_no);
   else
     strcpy (line_buf, "??");
   line_width = strlen (line_buf);
@@ -102,23 +98,26 @@ tui_make_status_line (struct tui_locator_element* loc)
     line_width = MIN_LINE_WIDTH;
 
   /* Translate PC address.  */
-  pc_out = tui_sfileopen (128);
-  deprecated_print_address_numeric (loc->addr, 1, pc_out);
-  pc_buf = tui_file_get_strbuf (pc_out);
-  pc_width = strlen (pc_buf);
-  
+  struct gdbarch *gdbarch = tui_location.gdbarch ();
+  CORE_ADDR addr = tui_location.addr ();
+  std::string pc_out (gdbarch
+                     ? paddress (gdbarch, addr)
+                     : "??");
+  const char *pc_buf = pc_out.c_str ();
+  int pc_width = pc_out.size ();
+
   /* First determine the amount of proc name width we have available.
      The +1 are for a space separator between fields.
      The -1 are to take into account the \0 counted by sizeof.  */
   proc_width = (status_size
-                - (target_width + 1)
-                - (pid_width + 1)
-                - (sizeof (PROC_PREFIX) - 1 + 1)
-                - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
-                - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
-                - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
-                   ? (sizeof (SINGLE_KEY) - 1 + 1)
-                   : 0));
+               - (target_width + 1)
+               - (pid_width + 1)
+               - (sizeof (PROC_PREFIX) - 1 + 1)
+               - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
+               - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
+               - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
+                  ? (sizeof (SINGLE_KEY) - 1 + 1)
+                  : 0));
 
   /* If there is no room to print the function name, try by removing
      some fields.  */
@@ -127,106 +126,93 @@ tui_make_status_line (struct tui_locator_element* loc)
       proc_width += target_width + 1;
       target_width = 0;
       if (proc_width < MIN_PROC_WIDTH)
-        {
-          proc_width += pid_width + 1;
-          pid_width = 0;
-          if (proc_width <= MIN_PROC_WIDTH)
-            {
-              proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
-              pc_width = 0;
-              if (proc_width < 0)
-                {
-                  proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
-                  line_width = 0;
-                  if (proc_width < 0)
-                    proc_width = 0;
-                }
-            }
-        }
+       {
+         proc_width += pid_width + 1;
+         pid_width = 0;
+         if (proc_width <= MIN_PROC_WIDTH)
+           {
+             proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
+             pc_width = 0;
+             if (proc_width < 0)
+               {
+                 proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
+                 line_width = 0;
+                 if (proc_width < 0)
+                   proc_width = 0;
+               }
+           }
+       }
     }
 
-  /* Now convert elements to string form */
-  pname = loc->proc_name;
-
-  /* Now create the locator line from the string version
-     of the elements.  We could use sprintf() here but
-     that wouldn't ensure that we don't overrun the size
-     of the allocated buffer.  strcat_to_buf() will.  */
-  *string = (char) 0;
+  /* Now create the locator line from the string version of the
+     elements.  */
+  string_file string;
 
   if (target_width > 0)
-    {
-      sprintf (buf, "%*.*s ",
-               -target_width, target_width, target_shortname);
-      strcat_to_buf (string, status_size, buf);
-    }
+    string.printf ("%*.*s ", -target_width, target_width, target_shortname ());
   if (pid_width > 0)
-    {
-      sprintf (buf, "%*.*s ",
-               -pid_width, pid_width, pid_name);
-      strcat_to_buf (string, status_size, buf);
-    }
-  
+    string.printf ("%*.*s ", -pid_width, pid_width, pid_name);
+
   /* Show whether we are in SingleKey mode.  */
   if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
     {
-      strcat_to_buf (string, status_size, SINGLE_KEY);
-      strcat_to_buf (string, status_size, " ");
+      string.puts (SINGLE_KEY);
+      string.puts (" ");
     }
 
-  /* procedure/class name */
+  /* Procedure/class name.  */
   if (proc_width > 0)
     {
-      if (strlen (pname) > proc_width)
-        sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
-                 1 - proc_width, proc_width - 1, pname);
+      const std::string &proc_name = tui_location.proc_name ();
+      if (proc_name.size () > proc_width)
+       string.printf ("%s%*.*s* ", PROC_PREFIX,
+                      1 - proc_width, proc_width - 1, proc_name.c_str ());
       else
-        sprintf (buf, "%s%*.*s ", PROC_PREFIX,
-                 -proc_width, proc_width, pname);
-      strcat_to_buf (string, status_size, buf);
+       string.printf ("%s%*.*s ", PROC_PREFIX,
+                      -proc_width, proc_width, proc_name.c_str ());
     }
 
   if (line_width > 0)
-    {
-      sprintf (buf, "%s%*.*s ", LINE_PREFIX,
-               -line_width, line_width, line_buf);
-      strcat_to_buf (string, status_size, buf);
-    }
+    string.printf ("%s%*.*s ", LINE_PREFIX,
+                  -line_width, line_width, line_buf);
   if (pc_width > 0)
     {
-      strcat_to_buf (string, status_size, PC_PREFIX);
-      strcat_to_buf (string, status_size, pc_buf);
+      string.puts (PC_PREFIX);
+      string.puts (pc_buf);
     }
-  
-  
-  for (i = strlen (string); i < status_size; i++)
-    string[i] = ' ';
-  string[status_size] = (char) 0;
-
-  ui_file_delete (pc_out);
-  return string;
+
+  std::string string_val = string.release ();
+
+  if (string.size () < status_size)
+    string_val.append (status_size - string.size (), ' ');
+  else if (string.size () > status_size)
+    string_val.erase (status_size, string.size ());
+
+  return string_val;
 }
 
-/* Get a printable name for the function at the address.
-   The symbol name is demangled if demangling is turned on.
-   Returns a pointer to a static area holding the result.  */
+/* Get a printable name for the function at the address.  The symbol
+   name is demangled if demangling is turned on.  Returns a pointer to
+   a static area holding the result.  */
 static char*
 tui_get_function_from_frame (struct frame_info *fi)
 {
   static char name[256];
-  struct ui_file *stream = tui_sfileopen (256);
-  char *p;
-
-  print_address_symbolic (get_frame_pc (fi), stream, demangle, "");
-  p = tui_file_get_strbuf (stream);
-
-  /* Use simple heuristics to isolate the function name.  The symbol can
-     be demangled and we can have function parameters.  Remove them because
-     the status line is too short to display them.  */
-  if (*p == '<')
-    p++;
-  strncpy (name, p, sizeof (name));
-  p = strchr (name, '(');
+  string_file stream;
+
+  print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
+                         &stream, demangle, "");
+
+  /* Use simple heuristics to isolate the function name.  The symbol
+     can be demangled and we can have function parameters.  Remove
+     them because the status line is too short to display them.  */
+  const char *d = stream.c_str ();
+  if (*d == '<')
+    d++;
+  strncpy (name, d, sizeof (name) - 1);
+  name[sizeof (name) - 1] = 0;
+
+  char *p = strchr (name, '(');
   if (!p)
     p = strchr (name, '>');
   if (p)
@@ -234,195 +220,107 @@ tui_get_function_from_frame (struct frame_info *fi)
   p = strchr (name, '+');
   if (p)
     *p = 0;
-  ui_file_delete (stream);
   return name;
 }
 
 void
-tui_show_locator_content (void)
+tui_locator_window::rerender ()
 {
-  char *string;
-  struct tui_gen_win_info * locator;
-
-  locator = tui_locator_win_info_ptr ();
-
-  if (locator != NULL && locator->handle != (WINDOW *) NULL)
-    {
-      struct tui_win_element * element;
-
-      element = (struct tui_win_element *) locator->content[0];
-
-      string = tui_make_status_line (&element->which_element.locator);
-      wmove (locator->handle, 0, 0);
-      wstandout (locator->handle);
-      waddstr (locator->handle, string);
-      wclrtoeol (locator->handle);
-      wstandend (locator->handle);
-      tui_refresh_win (locator);
-      wmove (locator->handle, 0, 0);
-      xfree (string);
-      locator->content_in_use = TRUE;
-    }
+  gdb_assert (handle != NULL);
+
+  std::string string = make_status_line ();
+  scrollok (handle.get (), FALSE);
+  wmove (handle.get (), 0, 0);
+  /* We ignore the return value from wstandout and wstandend, casting them
+     to void in order to avoid a compiler warning.  The warning itself was
+     introduced by a patch to ncurses 5.7 dated 2009-08-29, changing these
+     macro to expand to code that causes the compiler to generate an
+     unused-value warning.  */
+  (void) wstandout (handle.get ());
+  waddstr (handle.get (), string.c_str ());
+  wclrtoeol (handle.get ());
+  (void) wstandend (handle.get ());
+  refresh_window ();
+  wmove (handle.get (), 0, 0);
 }
 
+/* Function to print the frame information for the TUI.  The windows are
+   refreshed only if frame information has changed since the last refresh.
 
-/* Set the filename portion of the locator.  */
-static void
-tui_set_locator_filename (const char *filename)
-{
-  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
-  struct tui_locator_element * element;
+   Return true if frame information has changed (and windows
+   subsequently refreshed), false otherwise.  */
 
-  if (locator->content[0] == NULL)
-    {
-      tui_set_locator_info (filename, NULL, 0, 0);
-      return;
-    }
-
-  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
-  element->file_name[0] = 0;
-  strcat_to_buf (element->file_name, MAX_LOCATOR_ELEMENT_LEN, filename);
-}
-
-/* Update the locator, with the provided arguments.  */
-static void
-tui_set_locator_info (const char *filename, const char *procname, int lineno,
-                      CORE_ADDR addr)
+bool
+tui_show_frame_info (struct frame_info *fi)
 {
-  struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
-  struct tui_locator_element * element;
+  bool locator_changed_p;
 
-  /* Allocate the locator content if necessary.  */
-  if (locator->content_size <= 0)
+  if (fi != nullptr)
     {
-      locator->content = (void **) tui_alloc_content (1, locator->type);
-      locator->content_size = 1;
-    }
+      symtab_and_line sal = find_frame_sal (fi);
 
-  element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
-  element->proc_name[0] = (char) 0;
-  strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
-  element->line_no = lineno;
-  element->addr = addr;
-  tui_set_locator_filename (filename);
-}
+      const char *func_name;
+      /* find_frame_sal does not always set PC, but we want to ensure
+        that it is available in the SAL.  */
+      if (get_frame_pc_if_available (fi, &sal.pc))
+       func_name = tui_get_function_from_frame (fi);
+      else
+       func_name = _("<unavailable>");
 
-/* Update only the filename portion of the locator.  */
-void
-tui_update_locator_filename (const char *filename)
-{
-  tui_set_locator_filename (filename);
-  tui_show_locator_content ();
-}
+      locator_changed_p
+       = tui_location.set_location (get_frame_arch (fi), sal, func_name);
 
-/* Function to print the frame information for the TUI.  */
-void
-tui_show_frame_info (struct frame_info *fi)
-{
-  struct tui_win_info * win_info;
-  int i;
+      /* If the locator information has not changed, then frame information has
+        not changed.  If frame information has not changed, then the windows'
+        contents will not change.  So don't bother refreshing the windows.  */
+      if (!locator_changed_p)
+       return false;
 
-  if (fi)
-    {
-      int start_line, i;
-      CORE_ADDR low;
-      struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
-      int source_already_displayed;
-      struct symtab_and_line sal;
-
-      find_frame_sal (fi, &sal);
-
-      source_already_displayed = sal.symtab != 0
-        && tui_source_is_displayed (sal.symtab->filename);
-      tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename,
-                            tui_get_function_from_frame (fi),
-                            sal.line,
-                            get_frame_pc (fi));
-      tui_show_locator_content ();
-      start_line = 0;
-      for (i = 0; i < (tui_source_windows ())->count; i++)
+      for (struct tui_source_window_base *win_info : tui_source_windows ())
        {
-         union tui_which_element *item;
-         win_info = (tui_source_windows ())->list[i];
-
-         item = &((struct tui_win_element *) locator->content[0])->which_element;
-         if (win_info == TUI_SRC_WIN)
-           {
-             start_line = (item->locator.line_no -
-                          (win_info->generic.viewport_height / 2)) + 1;
-             if (start_line <= 0)
-               start_line = 1;
-           }
-         else
-           {
-             if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL,
-                                           &low, (CORE_ADDR) 0) == 0)
-               error (_("No function contains program counter for selected frame."));
-             else
-               low = tui_get_low_disassembly_address (low, get_frame_pc (fi));
-           }
-
-         if (win_info == TUI_SRC_WIN)
-           {
-             struct tui_line_or_address l;
-             l.loa = LOA_LINE;
-             l.u.line_no = start_line;
-             if (!(source_already_displayed
-                   && tui_line_is_displayed (item->locator.line_no, win_info, TRUE)))
-               tui_update_source_window (win_info, sal.symtab, l, TRUE);
-             else
-               {
-                 l.u.line_no = item->locator.line_no;
-                 tui_set_is_exec_point_at (l, win_info);
-               }
-           }
-         else
-           {
-             if (win_info == TUI_DISASM_WIN)
-               {
-                 struct tui_line_or_address a;
-                 a.loa = LOA_ADDRESS;
-                 a.u.addr = low;
-                 if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE))
-                   tui_update_source_window (win_info, sal.symtab, a, TRUE);
-                 else
-                   {
-                     a.u.addr = item->locator.addr;
-                     tui_set_is_exec_point_at (a, win_info);
-                   }
-               }
-           }
-         tui_update_exec_info (win_info);
+         win_info->maybe_update (fi, sal);
+         win_info->update_exec_info ();
        }
     }
   else
     {
-      tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0);
-      tui_show_locator_content ();
-      for (i = 0; i < (tui_source_windows ())->count; i++)
-       {
-         win_info = (tui_source_windows ())->list[i];
-         tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
-         tui_update_exec_info (win_info);
-       }
+      symtab_and_line sal {};
+
+      locator_changed_p = tui_location.set_location (NULL, sal, "");
+
+      if (!locator_changed_p)
+       return false;
+
+      for (struct tui_source_window_base *win_info : tui_source_windows ())
+       win_info->erase_source_content ();
     }
+
+  return true;
 }
 
-/* Function to initialize gdb commands, for tui window stack
-   manipulation.  */
 void
-_initialize_tui_stack (void)
+tui_show_locator_content ()
 {
-  add_com ("update", class_tui, tui_update_command, _("\
-Update the source window and locator to display the current execution point.\n"));
+  if (tui_is_window_visible (STATUS_WIN))
+    TUI_STATUS_WIN->rerender ();
 }
 
 /* Command to update the display with the current execution point.  */
 static void
-tui_update_command (char *arg, int from_tty)
+tui_update_command (const char *arg, int from_tty)
 {
-  char cmd[sizeof("frame 0")];
+  execute_command ("frame 0", from_tty);
+}
 
-  strcpy (cmd, "frame 0");
-  execute_command (cmd, from_tty);
+/* Function to initialize gdb commands, for tui window stack
+   manipulation.  */
+
+void _initialize_tui_stack ();
+void
+_initialize_tui_stack ()
+{
+  add_com ("update", class_tui, tui_update_command,
+          _("Update the source window and locator to "
+            "display the current execution point.\n\
+Usage: update"));
 }