]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
change api, progress bar
authorAaron Merey <amerey@redhat.com>
Thu, 5 May 2022 17:16:59 +0000 (13:16 -0400)
committerAaron Merey <amerey@redhat.com>
Thu, 5 May 2022 17:16:59 +0000 (13:16 -0400)
gdb/cli-out.c
gdb/cli-out.h
gdb/debuginfod-support.c
gdb/mi/mi-out.c
gdb/mi/mi-out.h
gdb/ui-out.h

index 3523b074e75ae4c22e5b9c92d11b65aa6944e211..ca1071ac31a4d88bebb5b8ff5225ef0ee7c0176a 100644 (file)
@@ -265,134 +265,106 @@ cli_ui_out::do_redirect (ui_file *outstream)
     m_streams.pop_back ();
 }
 
-/* The cli_ui_out::do_progress_{start, notify} functions result in
-   the following:
-
-   - printed for tty, SHOULD_PRINT == true
-      - next state == PERCENT:
-       <(XX%) NAME\r>
-      - next state == SPIN:
-       <-\|/ NAME\r>
-      - next state == BAR:
-       <NAME
-       [#####                      ]\r>
-   - printed for tty, SHOULD_PRINT == false:
-     <>
-   - printed for not-a-tty:
-     <NAME...
-     >
-*/
-
 void
-cli_ui_out::do_progress_start (const std::string &name, bool should_print)
+cli_ui_out::do_progress_start ()
 {
-  struct ui_file *stream = m_streams.back ();
   cli_progress_info info;
 
-  info.name = name;
-  if (!stream->isatty ())
-    {
-      fprintf_unfiltered (stream, "%s\n", info.name.c_str ());
-      gdb_flush (stream);
-      info.state = progress_update::WORKING;
-    }
-  else
-    {
-      /* Don't actually emit anything until the first call notifies us
-        of progress.  This makes it so a second progress message can
-        be started before the first one has been notified, without
-        messy output.  */
-      info.state = should_print ? progress_update::START
-                               : progress_update::NO_PRINT;
-    }
-
+  info.pos = 0;
+  info.state = progress_update::START;
   m_progress_info.push_back (std::move (info));
 }
 
 /* Pick a reasonable limit for the progress update length.  */
 #define MAX_CHARS_PER_LINE 4096
 
+/* Print a progress update.  MSG is a string to be printed before
+   If HOWMUCH is between 0.0 and 1.0, a progress bar is displayed
+   indicating the percentage of completion.  If HOWMUCH is negative, 
+   a progress indicator ticks across the screen.  Multiple calls
+   to this function progressively update the display.
+   
+   - printed for tty, HOWMUCH between 0.0 and 1.0:
+       <NAME
+       [########                   ]\r>
+   - printed for tty, HOWMUCH < 0.0:
+       <NAME
+       [    ###                    ]\r>
+   - printed for not-a-tty:
+     <NAME...
+     >
+*/
+
 void
-cli_ui_out::do_progress_notify (double howmuch,
-                               progress_update::state next_state)
+cli_ui_out::do_progress_notify (const std::string &msg, double howmuch)
 {
   struct ui_file *stream = m_streams.back ();
   cli_progress_info &info (m_progress_info.back ());
 
-  if (info.state == progress_update::NO_PRINT)
-    return;
-
-  int chars_per_line = get_chars_per_line ();
-  if (chars_per_line > MAX_CHARS_PER_LINE)
-    chars_per_line = MAX_CHARS_PER_LINE;
-
   if (info.state == progress_update::START)
     {
-      fprintf_unfiltered (stream, "%s", info.name.c_str ());
-      if (chars_per_line <= 0)
-       fprintf_unfiltered (stream, "\n");
-      gdb_flush (stream);
-      info.state = progress_update::WORKING;
+      if (!stream->isatty ())
+       {
+         fprintf_unfiltered (stream, "%s...\n", msg.c_str ());
+         info.state = progress_update::WORKING;
+       }
+      else
+       {
+         fprintf_unfiltered (stream, "%s\n", msg.c_str ());
+         info.state = progress_update::BAR;
+       }
     }
 
-  if (chars_per_line <= 0)
-    return;
-
-  if (info.state == progress_update::WORKING && howmuch >= 1.0)
-    return;
+  int chars_per_line = get_chars_per_line ();
+  if (chars_per_line > MAX_CHARS_PER_LINE)
+    chars_per_line = MAX_CHARS_PER_LINE;
 
-  if (!stream->isatty ())
+  if (chars_per_line <= 0
+      || info.state == progress_update::WORKING
+      || !stream->isatty ())
     return;
-
-  if (next_state == progress_update::PERCENT)
+/*
+  if (howmuch >= 0)
     {
-      fprintf_unfiltered (stream, "\r(%2.0f%%) %s",
-                         howmuch * 100, info.name.c_str ());
+      int width = chars_per_line - 3;
+      int max = width * howmuch;
+
+      fprintf_unfiltered (stream, "\r[");
+      for (int i = 0; i < width; ++i)
+       fprintf_unfiltered (stream, i < max ? "#" : " ");
+      fprintf_unfiltered (stream, "]");
       gdb_flush (stream);
-      info.state = progress_update::PERCENT;
     }
-  else if (next_state == progress_update::SPIN)
+  else
     {
       using namespace std::chrono;
-      seconds diff = duration_cast<seconds>
+      milliseconds diff = duration_cast<milliseconds>
        (steady_clock::now () - info.last_update);
 
-      /* Advance the spinner no faster than 1 tick per second.  */
-      if (diff.count () >= 1.0)
+      * Advance the progress indicator at a rate of 1 tick every
+        every 0.5 seconds.  *
+      if (diff.count () >= 500)
        {
-         static int spin = 0;
+         int width = chars_per_line - 3;
 
-         fprintf_unfiltered (stream, "\r%c %s", "-\\|/"[spin++ % 4],
-                             info.name.c_str ());
+         fprintf_unfiltered (stream, "\r[");
+          
+         for (int i = 0; i < width; ++i)
+           {
+             if (i >= info.pos % width
+                 && i < (info.pos + 3) % width)
+               fprintf_unfiltered (stream, "#");
+             else
+               fprintf_unfiltered (stream, " ");
+           }   
+
+         fprintf_unfiltered (stream, "]");
          gdb_flush (stream);
          info.last_update = steady_clock::now ();
+         info.pos++;
        }
-      info.state = progress_update::SPIN;
-    }
-  else if (next_state == progress_update::BAR)
-    {
-      int i, max;
-      int width = chars_per_line - 3;
-      max = width * howmuch;
-
-      if (info.state == progress_update::SPIN
-         || info.state == progress_update::PERCENT)
-       {
-         /* Ensure the progress bar prints on its own line so that
-            progress updates don't overwrite NAME.  */
-         fprintf_unfiltered (stream, "\r%s\n", info.name.c_str ());
-         gdb_flush (stream);
-       }
-
-      fprintf_unfiltered (stream, "\r[");
-
-      for (i = 0; i < width; ++i)
-       fprintf_unfiltered (stream, i < max ? "#" : " ");
-      fprintf_unfiltered (stream, "]");
-      gdb_flush (stream);
-      info.state = progress_update::BAR;
     }
-
+*/
   return;
 }
 
@@ -409,40 +381,16 @@ cli_ui_out::clear_current_line ()
       || chars_per_line > MAX_CHARS_PER_LINE)
     chars_per_line = MAX_CHARS_PER_LINE;
 
-  int i;
   int width = chars_per_line;
 
   fprintf_unfiltered (stream, "\r");
-  for (i = 0; i < width; ++i)
+  for (int i = 0; i < width; ++i)
     fprintf_unfiltered (stream, " ");
   fprintf_unfiltered (stream, "\r");
 
   gdb_flush (stream);
 }
 
-/* Set NAME as the new description of the most recent progress update.  */
-
-void
-cli_ui_out::update_progress_name (const std::string &name)
-{
-  struct ui_file *stream = m_streams.back ();
-  cli_progress_info &info = m_progress_info.back ();
-  info.name = name;
-
-  if (stream->isatty ())
-    clear_current_line ();
-}
-
-/* Get the current state of the most recent progress update.  */
-
-cli_ui_out::progress_update::state
-cli_ui_out::get_progress_state ()
-{
-  cli_progress_info &info = m_progress_info.back ();
-  return info.state;
-}
-
-
 /* Remove the most recent progress update from the stack and
    overwrite the current line with whitespace.  */
 
index 2afd5b32706bd58271166428c6d710e114e95e5f..ae42ff03cf0bd6b1576e9a76d59a8b906b6bf3ca 100644 (file)
@@ -72,11 +72,9 @@ protected:
   virtual void do_flush () override;
   virtual void do_redirect (struct ui_file *outstream) override;
 
-  virtual void do_progress_start (const std::string &, bool) override;
-  virtual void do_progress_notify (double, progress_update::state) override;
+  virtual void do_progress_start () override;
+  virtual void do_progress_notify (const std::string &, double) override;
   virtual void do_progress_end () override;
-  virtual void update_progress_name (const std::string &) override;
-  virtual progress_update::state get_progress_state () override;
 
   bool suppress_output ()
   { return m_suppress_output; }
@@ -91,10 +89,10 @@ private:
   /* The state of a recent progress update.  */
   struct cli_progress_info
   {
+    /* Position of indicator.  */
+    int pos;
     /* The current state.  */
     progress_update::state state;
-    /* The name to print.  */
-    std::string name;
     /* Time of last spinner update.  */
     std::chrono::steady_clock::time_point last_update;
   };
index 5a5420c8c039b4076c1af1eb09b1dc765bbbc40e..2d227ba43503ce4b2c828f7b7cfe18687fc8ff50 100644 (file)
@@ -84,7 +84,7 @@ struct user_data
 
   const char * const desc;
   std::string & fname;
-  gdb::optional<ui_out::progress_update> progress;
+  ui_out::progress_update progress;
 };
 
 /* Deleter for a debuginfod_client.  */
@@ -119,200 +119,51 @@ get_size_and_unit (double *size, const char **unit)
     *unit = "KB";
 }
 
-/* Ensure the progress message can fit on a single line. Otherwise
-   garbled output is possible with \r.
-
-   An example of possible truncations, starting with the original message:
-   "Downloading XX MB separate debug info for /aa/bb/cc/dd/ee"
-   "Downloading XX MB separate debug info for /aa/bb/.../ee"
-   "Downloading XX MB separate debug info for ee"
-   "Downloading XX MB separate debug info"
-   "Downloading XX MB"
-   "Downloading"
-  */
-
-static std::string
-build_message (std::string size, std::string unit, std::string desc, std::string fname)
-{
-  int width = get_chars_per_line ();
-  std::stringstream message;
-
-  message << "Downloading";
-  /* Leave room for spinner and percent indicator.  */
-  int message_size = message.str ().length () + 6;
-
-  if (!size.empty () && !unit.empty ())
-    {
-      message_size += size.size () + unit.size () + 2;
-      if (message_size > width)
-       return message.str ();
-
-      /* "Downloading XX MB" */
-      message << " " << size << " " << unit;
-    }
-
-  /* If FNAME does not fit then message will end with DESC_END.
-     In case DESC_END is "separate debug info for", remove " for".  */
-  std::string desc_end = desc;
-  if (desc.substr (desc.size () - 4) == " for")
-    desc_end = desc.substr (0, desc.size () - 4);
-
-  if (message_size + desc_end.size () + 1 > width)
-    return message.str ();
-
-  string_file styled_fname (current_uiout->can_emit_style_escape ());
-  if (message_size + desc.size () + fname.size () + 2 <= width)
-    {
-      /* Truncation is not necessary. Return untruncated message.
-        "Downloading XX MB separate debug info for /usr/libxyz.so" */
-      fprintf_styled (&styled_fname, file_name_style.style (), "%s",
-                     fname.c_str ());
-
-      message << " " << desc << " " << styled_fname.c_str ();
-      return message.str ();
-    }
-
-   while (fname.back () == '/')
-    fname.pop_back ();
-
-  /* Find path separators for the first, second and final components.
-     If FNAME does not have path separators and it does not fit in the
-     available space, do not include it in message.  */
-  size_t sep1 = fname.find ('/');
-  if (sep1 == std::string::npos)
-    {
-      message << " " << desc_end;
-      return message.str ();
-    }
-
-  size_t sep2 = fname.find ('/', sep1 + 1);
-  size_t sep3;
-  if (sep2 == std::string::npos)
-    sep3 = std::string::npos;
-  else
-    sep3 = fname.find ('/', sep2 + 1);
-  size_t seplast = fname.find_last_of ('/');
-
-  /* If the first, second, and final path components are distinct, try to
-     truncate FNAME so that it fits in the available space.  Preserve the
-     first, second and final path components.  For example,
-     "/aa/bb/cc/dd/ee" becomes "/aa/bb/.../ee" and
-     "../aa/bb/cc/dd/" becomes "../aa/.../ee"  */
-  std::stringstream trunc;
-  if (sep2 != sep3 && sep2 != seplast && sep2 != std::string::npos)
-    {
-      std::stringstream fnametmp;
-
-      if (sep1 == 0 && sep3 != seplast && sep3 != std::string::npos)
-       fnametmp << fname.substr (0, sep3 + 1)
-                << "..." << fname.substr (seplast);
-      else if (sep1 != 0)
-       fnametmp << fname.substr (0, sep2 + 1)
-                << "..." << fname.substr (seplast);
-
-      if (!fnametmp.str ().empty ())
-       {
-         trunc << " " << desc << " ";
-         if (message_size + trunc.str ().size () + fnametmp.str ().size () <= width)
-           {
-             fprintf_styled (&styled_fname, file_name_style.style (), "%s",
-                             fnametmp.str ().c_str ());
-             message << trunc.str () << styled_fname.c_str ();
-             return message.str ();
-           }
-       }
-    }
-
-  /* The first, second and final components are not distinct or
-     "/aa/bb/.../ee" does not fit. Try "ee" instead.  */
-  trunc.str ("");
-  trunc << " " << desc << " ";
-  fname = fname.substr (seplast + 1);
-  if (message_size + trunc.str ().size () + fname.size () <= width)
-    {
-      fprintf_styled (&styled_fname, file_name_style.style (), "%s",
-                     fname.c_str ());
-      message << trunc.str () << styled_fname.c_str ();
-      return message.str ();
-    }
-
-  /* We aren't able to fit anything from FNAME. End message with DESC_END
-     since we already confirmed it will fit.  */
-  message << " " << desc_end;
-  return message.str ();
-}
-
-
 static int
 progressfn (debuginfod_client *c, long cur, long total)
 {
   user_data *data = static_cast<user_data *> (debuginfod_get_user_data (c));
   gdb_assert (data != nullptr);
 
+  string_file styled_fname (current_uiout->can_emit_style_escape ());
+  fprintf_styled (&styled_fname, file_name_style.style (), "%s",
+                 data->fname.c_str ());
+
   if (check_quit_flag ())
     {
-      if (data->progress.has_value ())
-       data->progress.reset ();
-
-      string_file styled_fname (current_uiout->can_emit_style_escape ());
-      fprintf_styled (&styled_fname, file_name_style.style (), "%s",
-                     data->fname.c_str ());
+      current_uiout->do_progress_end (); ///?
 
       printf_filtered ("Cancelled download of %s %s\n",
                       data->desc, styled_fname.c_str ());
       return 1;
     }
 
-  if (debuginfod_verbose == 0
-      || (data->progress.has_value ()
-         && data->progress->get_state () == ui_out::progress_update::WORKING))
+  if (debuginfod_verbose == 0)
     return 0;
 
   /* Print progress update.  Include the transfer size if available.  */
   if (total > 0)
     {
       /* Transfer size is known.  */
-      double percent = (double)cur / (double)total;
+      double howmuch = (double) cur / (double) total;
 
-      if (percent >= 0.0 && percent <= 1.0)
+      if (howmuch >= 0.0 && howmuch <= 1.0)
        {
-         if (!data->progress.has_value ()
-             || data->progress->get_state ()
-                != ui_out::progress_update::PERCENT)
-           {
-             double size = (double)total;
-             const char *unit = "";
-
-             get_size_and_unit (&size, &unit);
-             std::string fsize = string_printf ("%.2f", size);
-             std::string message = build_message (fsize, unit, data->desc,
-                                                  data->fname);
-             if (!data->progress.has_value ())
-               data->progress.emplace (current_uiout, message, 1);
-             else
-               data->progress->update_name (message);
-           }
-
-           /* Ensure PERCENT doesn't require three digits to display.  */
-           if (percent > 0.99 && percent <= 1.0)
-             percent = .99;
-           current_uiout->update_progress_percent (percent);
-           return 0;
-       }
-    }
-
-  if (!data->progress.has_value ()
-      || data->progress->get_state () != ui_out::progress_update::SPIN)
-    {
-      std::string message = build_message ("", "", data->desc, data->fname);
+         double size = (double) total;
+         const char *unit = "";
 
-      if (!data->progress.has_value ())
-       data->progress.emplace (current_uiout, message, 1);
-      else
-       data->progress->update_name (message);
+         get_size_and_unit (&size, &unit);
+         std::string msg = string_printf ("Downloading %0.2f %s %s %s\n",
+                                          size, unit, data->desc,
+                                          styled_fname.c_str ());
+         current_uiout->update_progress (msg, howmuch);
+         return 0;
+       }
     }
 
-  current_uiout->update_progress_spin ();
+  std::string msg = string_printf ("Downloading %s %s\n",
+                                  data->desc, styled_fname.c_str ());
+  current_uiout->update_progress (msg, -1);
   return 0;
 }
 
@@ -374,8 +225,7 @@ static void
 print_outcome (user_data &data, int fd)
 {
   /* Clears the current line of progress output.  */
-  if (data.progress.has_value ())
-    data.progress.reset ();
+  current_uiout->do_progress_end ();
 
   string_file styled_fname (current_uiout->can_emit_style_escape ());
   fprintf_styled (&styled_fname, file_name_style.style (), "%s",
index a7f697b4f2887785778b0e787e54dad53c562ed4..e5c4e3b8534abee63e7274c879ac06aa79dd040a 100644 (file)
@@ -258,38 +258,28 @@ mi_ui_out::main_stream ()
   return (string_file *) m_streams.back ();
 }
 
-/* Indicate that a task described by NAME is in progress:
-
-   - SHOULD_PRINT == true:
-     <NAME
-     >
-   - SHOULD_PRINT == false:
-     <>
-*/
-
 void
-mi_ui_out::do_progress_start (const std::string &name, bool should_print)
+mi_ui_out::do_progress_start ()
 {
-  struct ui_file *stream = gdb_stdout;
   mi_progress_info info;
 
-  if (should_print)
-    {
-      fprintf_unfiltered (stream, "%s\n", name.c_str ());
-      gdb_flush (stream);
-    }
-
-  info.state = progress_update::WORKING;
+  info.state = progress_update::START;
   m_progress_info.push_back (std::move (info));
 }
 
-/* Get the state of the most recent progress update.  */
+/* Indicate that a task described by NAME is in progress.  */
 
-mi_ui_out::progress_update::state
-mi_ui_out::get_progress_state ()
+void
+mi_ui_out::do_progress_notify (const std::string &msg, double howmuch)
 {
-  mi_progress_info &info = m_progress_info.back ();
-  return info.state;
+  mi_progress_info &info (m_progress_info.back ());
+
+  if (info.state == progress_update::START)
+    {
+      struct ui_file *stream = gdb_stdout;
+      fprintf_unfiltered (stream, "%s\n", msg.c_str ());
+      info.state = progress_update::WORKING;
+    }
 }
 
 /* Clear the buffer.  */
index d915b35f6333d79ceb64577ec53f11b22f100cb5..5ce81c9447383af633d1f2376ffb7e9ff74ed58c 100644 (file)
@@ -82,21 +82,13 @@ protected:
   virtual bool do_is_mi_like_p () const override
   { return true; }
 
-  virtual void do_progress_start (const std::string &, bool) override;
-  virtual progress_update::state get_progress_state () override;
-
-  virtual void do_progress_notify (double, progress_update::state) override
-  {
-  }
+  virtual void do_progress_start () override;
+  virtual void do_progress_notify (const std::string &, double) override;
 
   virtual void do_progress_end () override
   {
   }
 
-  virtual void update_progress_name (const std::string &) override
-  {
-  }
-
 private:
 
   void field_separator ();
index 4c490c11b8215b75cdfc7868216f2558b4900082..175ff5fb156d50e94b198b06ef50f498bcca51af 100644 (file)
@@ -293,35 +293,20 @@ class ui_out
       WORKING,
       /* Progress bar printing has already started.  */
       BAR,
-      /* Spinner printing has already started.  */
-      SPIN,
-      /* Percent printing has already started.  */
-      PERCENT,
       /* Printing should not be done.  */
       NO_PRINT
     };
 
     /* SHOULD_PRINT indicates whether something should be printed for a tty.  */
-    progress_update (struct ui_out *uiout, const std::string &name,
-                    bool should_print)
-      : m_uiout (uiout)
+    progress_update ()
     {
-      m_uiout->do_progress_start (name, should_print);
+      m_uiout = current_uiout;
+      m_uiout->do_progress_start ();
     }
 
     ~progress_update ()
     {
-      m_uiout->do_progress_end ();
-    }
-
-    void update_name (std::string &name)
-    {
-      m_uiout->update_progress_name (name);
-    }
 
-    state get_state ()
-    {
-      return m_uiout->get_progress_state ();
     }
 
     progress_update (const progress_update &) = delete;
@@ -334,20 +319,12 @@ class ui_out
 
   /* Emit some progress corresponding to the most recently created
      progress_update object.  */
-  void update_progress_bar (double howmuch)
-  {
-    do_progress_notify (howmuch, progress_update::BAR);
-  }
-
-  void update_progress_percent (double howmuch)
+  void update_progress (std::string &msg, double howmuch)
   {
-    do_progress_notify (howmuch, progress_update::PERCENT);
+    do_progress_notify (msg, howmuch);
   }
 
-  void update_progress_spin ()
-  {
-    do_progress_notify (0, progress_update::SPIN);
-  }
+  virtual void do_progress_end () = 0;
 
  protected:
 
@@ -383,11 +360,8 @@ class ui_out
   virtual void do_flush () = 0;
   virtual void do_redirect (struct ui_file *outstream) = 0;
 
-  virtual void do_progress_start (const std::string &, bool) = 0;
-  virtual void do_progress_notify (double, progress_update::state) = 0;
-  virtual void do_progress_end () = 0;
-  virtual void update_progress_name (const std::string &) = 0;
-  virtual progress_update::state get_progress_state () = 0;
+  virtual void do_progress_start () = 0;
+  virtual void do_progress_notify (const std::string &, double) = 0;
 
   /* Set as not MI-like by default.  It is overridden in subclasses if
      necessary.  */