From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 8FA06384D15B for ; Fri, 26 Aug 2022 21:25:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8FA06384D15B Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-512-gURdOYu9NKWbiasizEbRag-1; Fri, 26 Aug 2022 17:25:21 -0400 X-MC-Unique: gURdOYu9NKWbiasizEbRag-1 Received: by mail-qt1-f198.google.com with SMTP id b10-20020a05622a020a00b003437e336ca7so2135931qtx.16 for ; Fri, 26 Aug 2022 14:25:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc; bh=TFtfBWybh33gIhzWjOAnYLlfD5nnqu/B6ZOzxUT/2YI=; b=T3M3XMxH1MFY7pr64Z+qgdeBkiJJJ72/JeDJlDiu3gKEDOL9peGqERxeIYaNcdivc2 etOaE8Z6SVt4CgpWvUdK8PJsHdXW4e/7IXjzfDcfy/I4e6RfpIBIEuFwI+k7W1fldIzO msoclZ8Eb1cvEzUYBBqO//1fYoXb5UtJQtrDX7/OpjSSM7dEhEZWDS6HJQyQ+uHBmIi+ rbcdDq4yEo+TMZdiQG1loMCNaykgam8g3TsjLWdgM/GCRTi1cCRx3uL+0m7YZTqKXpZi IfPVGuiYvtDiHB/MVlkVAkqBjfd//MlpS2IThPIH2YRZCx6vMSDjh7OI6wWHBOjy/vp9 q9+Q== X-Gm-Message-State: ACgBeo2+Gq4YAKdFiLcRkE/azZ7trgUwpqTsZZ7mUz5S+tTdTl9XkPDA LkwjO6+hwG5Wq41PcOTKk+vTmcZ5M62IkazO+jsu4owR4sXnmGjvLPosE6MzGThPOhtNZ4YUP5N nCkV+cJCFhOQUIc9V1upWwHUK7L0b8joUMyVM X-Received: by 2002:a0c:a99d:0:b0:474:7389:858b with SMTP id a29-20020a0ca99d000000b004747389858bmr1287635qvb.100.1661549120140; Fri, 26 Aug 2022 14:25:20 -0700 (PDT) X-Google-Smtp-Source: AA6agR5w9dHwjbBQGbysZrmE7qOGERVCVyy7pIkWnxEwCa+70HQYDm+okap6bqzwC5Vfjr6cPV+VlI5bKm0jsQSYxps= X-Received: by 2002:a0c:a99d:0:b0:474:7389:858b with SMTP id a29-20020a0ca99d000000b004747389858bmr1287602qvb.100.1661549119603; Fri, 26 Aug 2022 14:25:19 -0700 (PDT) MIME-Version: 1.0 References: <20220708213306.421974-1-amerey@redhat.com> In-Reply-To: <20220708213306.421974-1-amerey@redhat.com> From: Aaron Merey Date: Fri, 26 Aug 2022 17:25:08 -0400 Message-ID: Subject: [PING][PATCH v4] gdb: Improve debuginfod progress updates To: gdb-patches@sourceware.org X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Aug 2022 21:25:25 -0000 Ping Thanks, Aaron On Fri, Jul 8, 2022 at 5:33 PM Aaron Merey wrote: > > v3 can be found here: > https://sourceware.org/pipermail/gdb-patches/2022-February/185798.html > > Changes from v3 include a simplified progress update API and display. > Truncation of the progress update message has been removed as well. > > The progress update display for debuginfod downloading implemented in > this patch is as follows. > > If the download size is known, a progress bar is displayed along with > the percentage of completion and the total download size. > > Downloading separate debug info for /lib/libxyz.so > [############ ] 25% (10.01 MB) > > If the download size is not known, a progress indicator is displayed > with a ticker ("###") that moves across the screen at a rate of 1 tick > every 0.5 seconds. > > Downloading separate debug info for /lib/libxyz.so > [ ### ] > > If the output stream is not a tty, batch mode is enabled or the screen > is too narrow then only a static description of the download is printed. > No bar or ticker is displayed. > > Downloading separate debug info for /lib/libxyz.so... > > In any case, if the size of the download is known at the time the > description is printed then it will be included in the description. > > Downloading 10.01 MB separate debug info for /lib/libxyz.so... > --- > gdb/cli-out.c | 194 +++++++++++++++++++++++++-------------- > gdb/cli-out.h | 36 +++----- > gdb/debuginfod-support.c | 130 +++++++++++++++++--------- > gdb/mi/mi-out.c | 28 ++++++ > gdb/mi/mi-out.h | 21 +++-- > gdb/ui-out.h | 53 +++++++---- > 6 files changed, 303 insertions(+), 159 deletions(-) > > diff --git a/gdb/cli-out.c b/gdb/cli-out.c > index e0802df352b..555154406cf 100644 > --- a/gdb/cli-out.c > +++ b/gdb/cli-out.c > @@ -26,6 +26,7 @@ > #include "completer.h" > #include "readline/readline.h" > #include "cli/cli-style.h" > +#include "top.h" > > /* These are the CLI output functions */ > > @@ -262,105 +263,164 @@ cli_ui_out::do_redirect (ui_file *outstream) > m_streams.pop_back (); > } > > -/* The cli_ui_out::do_progress_* functions result in the following: > - - printed for tty, SHOULD_PRINT == true: > - - [##### ]\r> > - - printed for tty, SHOULD_PRINT == false: > - <> > +/* Initialize a progress update to be displayed with > + cli_ui_out::do_progress_notify. */ > + > +void > +cli_ui_out::do_progress_start () > +{ > + cli_progress_info info; > + > + info.pos = 0; > + info.state = progress_update::START; > + m_progress_info.push_back (std::move (info)); > +} > + > +/* Print a progress update. MSG is a string to be printed on the line above > + the progress bar. TOTAL is the size of the download whose progress is > + being displayed. UNIT should be the unit of TOTAL (ex. "KB"). If HOWMUCH > + is between 0.0 and 1.0, a progress bar is displayed indicating the percentage > + of completion and the download size. If HOWMUCH is negative, a progress > + indicator will tick across the screen. If the output stream is not a tty > + then only MSG is printed. > + > + - printed for tty, HOWMUCH between 0.0 and 1.0: > + + [######### ] HOWMUCH*100% (TOTAL UNIT)\r> > + - printed for tty, HOWMUCH < 0.0: > + + [ ### ]\r> > - printed for not-a-tty: > - - > > + > */ > > void > -cli_ui_out::do_progress_start (const std::string &name, bool should_print) > +cli_ui_out::do_progress_notify (const std::string &msg, > + const std::string &unit, > + double howmuch, double total) > { > + int chars_per_line = get_chars_per_line (); > struct ui_file *stream = m_streams.back (); > - cli_progress_info meter; > + cli_progress_info &info (m_progress_info.back ()); > + > +#define MIN_CHARS_PER_LINE 50 > +#define MAX_CHARS_PER_LINE 4096 > + > + if (chars_per_line > MAX_CHARS_PER_LINE > + || chars_per_line == -1) > + chars_per_line = MAX_CHARS_PER_LINE; > + > + if (info.state == progress_update::START) > + { > + if (stream->isatty () > + && input_interactive_p (current_ui) > + && chars_per_line >= MIN_CHARS_PER_LINE) > + { > + gdb_printf (stream, "%s\n", msg.c_str ()); > + info.state = progress_update::BAR; > + } > + else > + { > + gdb_printf (stream, "%s...\n", msg.c_str ()); > + info.state = progress_update::WORKING; > + } > + } > > - meter.last_value = 0; > - meter.name = name; > - if (!stream->isatty ()) > + if (info.state != progress_update::BAR > + || chars_per_line < MIN_CHARS_PER_LINE) > + return; > + > + if (total > 0 && howmuch >= 0 && howmuch <= 1.0) > { > - gdb_printf (stream, "%s...", meter.name.c_str ()); > + std::string progress = string_printf (" %3.f%% (%.2f %s)", > + howmuch * 100, total, > + unit.c_str ()); > + int width = chars_per_line - progress.size () - 3; > + int max = width * howmuch; > + > + std::string display = "\r["; > + > + for (int i = 0; i < width; ++i) > + if (i < max) > + display += "#"; > + else > + display += " "; > + > + display += "]" + progress; > + gdb_printf (stream, "%s", display.c_str ()); > gdb_flush (stream); > - meter.printing = 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. */ > - meter.printing = should_print ? START : NO_PRINT; > + using namespace std::chrono; > + milliseconds diff = duration_cast > + (steady_clock::now () - info.last_update); > + > + /* Advance the progress indicator at a rate of 1 tick every > + every 0.5 seconds. */ > + if (diff.count () >= 500) > + { > + int width = chars_per_line - 3; > + > + gdb_printf (stream, "\r["); > + for (int i = 0; i < width; ++i) > + { > + if (i == info.pos % width > + || i == (info.pos + 1) % width > + || i == (info.pos + 2) % width) > + gdb_printf (stream, "#"); > + else > + gdb_printf (stream, " "); > + } > + > + gdb_printf (stream, "]"); > + gdb_flush (stream); > + info.last_update = steady_clock::now (); > + info.pos++; > + } > } > > - m_meters.push_back (std::move (meter)); > + return; > } > > +/* Clear the current line of the most recent progress update. Overwrites > + the current line with whitespace. */ > + > void > -cli_ui_out::do_progress_notify (double howmuch) > +cli_ui_out::clear_current_line () > { > struct ui_file *stream = m_streams.back (); > - cli_progress_info &meter (m_meters.back ()); > + int chars_per_line = get_chars_per_line (); > > - if (meter.printing == NO_PRINT) > + if (!stream->isatty () > + || !input_interactive_p (current_ui)) > return; > > - if (meter.printing == START) > - { > - gdb_printf (stream, "%s\n", meter.name.c_str ()); > - gdb_flush (stream); > - meter.printing = WORKING; > - } > + if (chars_per_line > MAX_CHARS_PER_LINE > + || chars_per_line == -1) > + chars_per_line = MAX_CHARS_PER_LINE; > > - if (meter.printing == WORKING && howmuch >= 1.0) > - return; > + int width = chars_per_line; > > - if (!stream->isatty ()) > - return; > + gdb_printf (stream, "\r"); > + for (int i = 0; i < width; ++i) > + gdb_printf (stream, " "); > + gdb_printf (stream, "\r"); > > - int chars_per_line = get_chars_per_line (); > - if (chars_per_line > 0) > - { > - int i, max; > - int width = chars_per_line - 3; > - > - max = width * howmuch; > - gdb_printf (stream, "\r["); > - for (i = 0; i < width; ++i) > - gdb_printf (stream, i < max ? "#" : " "); > - gdb_printf (stream, "]"); > - gdb_flush (stream); > - meter.printing = PROGRESS; > - } > + gdb_flush (stream); > } > > +/* Remove the most recent progress update from the progress_info stack > + and overwrite the current line with whitespace. */ > + > void > cli_ui_out::do_progress_end () > { > struct ui_file *stream = m_streams.back (); > - cli_progress_info &meter = m_meters.back (); > - > - if (!stream->isatty ()) > - { > - gdb_printf (stream, "\n"); > - gdb_flush (stream); > - } > - else if (meter.printing == PROGRESS) > - { > - int i; > - int width = get_chars_per_line () - 3; > - > - gdb_printf (stream, "\r"); > - for (i = 0; i < width + 2; ++i) > - gdb_printf (stream, " "); > - gdb_printf (stream, "\r"); > - gdb_flush (stream); > - } > + m_progress_info.pop_back (); > > - m_meters.pop_back (); > + if (stream->isatty ()) > + clear_current_line (); > } > > /* local functions */ > diff --git a/gdb/cli-out.h b/gdb/cli-out.h > index 3fc794b61a4..c3114878986 100644 > --- a/gdb/cli-out.h > +++ b/gdb/cli-out.h > @@ -21,6 +21,7 @@ > #define CLI_OUT_H > > #include "ui-out.h" > +#include > #include > > class cli_ui_out : public ui_out > @@ -71,8 +72,9 @@ class cli_ui_out : public ui_out > 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) override; > + virtual void do_progress_start () override; > + virtual void do_progress_notify (const std::string &, const std::string &, > + double, double) override; > virtual void do_progress_end () override; > > bool suppress_output () > @@ -85,32 +87,20 @@ class cli_ui_out : public ui_out > std::vector m_streams; > bool m_suppress_output; > > - /* Represents the printing state of a progress meter. */ > - enum meter_state > - { > - /* Printing will start with the next output. */ > - START, > - /* Printing has already started. */ > - WORKING, > - /* Progress printing has already started. */ > - PROGRESS, > - /* Printing should not be done. */ > - NO_PRINT > - }; > - > - /* The state of a recent progress meter. */ > + /* The state of a recent progress update. */ > struct cli_progress_info > { > + /* Position of the progress indicator. */ > + int pos; > /* The current state. */ > - enum meter_state printing; > - /* The name to print. */ > - std::string name; > - /* The last notification value. */ > - double last_value; > + progress_update::state state; > + /* Progress indicator's time of last update. */ > + std::chrono::steady_clock::time_point last_update; > }; > > - /* Stack of progress meters. */ > - std::vector m_meters; > + /* Stack of progress info. */ > + std::vector m_progress_info; > + void clear_current_line (); > }; > > extern cli_ui_out *cli_out_new (struct ui_file *stream); > diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c > index 9dbe6b5d8b2..93b9250d6fe 100644 > --- a/gdb/debuginfod-support.c > +++ b/gdb/debuginfod-support.c > @@ -24,7 +24,9 @@ > #include "gdbsupport/gdb_optional.h" > #include "cli/cli-cmds.h" > #include "cli/cli-style.h" > +#include "cli-out.h" > #include "target.h" > +#include > > /* Set/show debuginfod commands. */ > static cmd_list_element *set_debuginfod_prefix_list; > @@ -87,12 +89,12 @@ debuginfod_exec_query (const unsigned char *build_id, > struct user_data > { > user_data (const char *desc, const char *fname) > - : desc (desc), fname (fname), has_printed (false) > + : desc (desc), fname (fname) > { } > > const char * const desc; > const char * const fname; > - bool has_printed; > + ui_out::progress_update progress; > }; > > /* Deleter for a debuginfod_client. */ > @@ -108,47 +110,85 @@ struct debuginfod_client_deleter > using debuginfod_client_up > = std::unique_ptr; > > + > +/* Convert SIZE into a unit suitable for use with progress updates. > + SIZE should in given in bytes and will be converted into KB, MB, GB > + or remain unchanged. UNIT will be set to "B", "KB", "MB" or "GB" > + accordingly. */ > + > +static void > +get_size_and_unit (double &size, std::string &unit) > +{ > + if (size < 1024) > + { > + /* If size is less than 1 KB then set unit to B. */ > + unit = "B"; > + return; > + } > + > + size /= 1024; > + if (size < 1024) > + { > + /* If size is less than 1 MB then set unit to KB. */ > + unit = "KB"; > + return; > + } > + > + size /= 1024; > + if (size < 1024) > + { > + /* If size is less than 1 GB then set unit to MB. */ > + unit = "MB"; > + return; > + } > + > + size /= 1024; > + unit = "GB"; > +} > + > static int > progressfn (debuginfod_client *c, long cur, long total) > { > user_data *data = static_cast (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); > + > if (check_quit_flag ()) > { > - gdb_printf ("Cancelling download of %s %ps...\n", > - data->desc, > - styled_string (file_name_style.style (), data->fname)); > + gdb_printf ("Cancelling download of %s %s...\n", > + data->desc, styled_fname.c_str ()); > return 1; > } > > - if (!data->has_printed) > + if (debuginfod_verbose == 0) > + return 0; > + > + /* Print progress update. Include the transfer size if available. */ > + if (total > 0) > { > - /* Include the transfer size, if available. */ > - if (total > 0) > + /* Transfer size is known. */ > + double howmuch = (double) cur / (double) total; > + > + if (howmuch >= 0.0 && howmuch <= 1.0) > { > - float size = 1.0f * total / 1024; > - const char *unit = "KB"; > - > - /* If size is greater than 0.01 MB, set unit to MB. */ > - if (size > 10.24) > - { > - size /= 1024; > - unit = "MB"; > - } > - > - gdb_printf ("Downloading %.2f %s %s %ps...\n", > - size, unit, data->desc, > - styled_string (file_name_style.style (), > - data->fname)); > + double d_total = (double) total; > + std::string unit = ""; > + > + get_size_and_unit (d_total, unit); > + std::string msg = string_printf ("Downloading %0.2f %s %s %s", > + d_total, unit.c_str (), data->desc, > + styled_fname.c_str ()); > + data->progress.update_progress (msg, unit, howmuch, d_total); > + return 0; > } > - else > - gdb_printf ("Downloading %s %ps...\n", data->desc, > - styled_string (file_name_style.style (), data->fname)); > - > - data->has_printed = true; > } > > + std::string msg = string_printf ("Downloading %s %s", > + data->desc, styled_fname.c_str ()); > + data->progress.update_progress (msg); > return 0; > } > > @@ -230,6 +270,23 @@ debuginfod_is_enabled () > return true; > } > > +/* Print the result of the most recent attempted download. */ > + > +static void > +print_outcome (user_data &data, int fd) > +{ > + /* Clears the current line of progress output. */ > + current_uiout->do_progress_end (); > + > + string_file styled_fname (current_uiout->can_emit_style_escape ()); > + fprintf_styled (&styled_fname, file_name_style.style (), "%s", > + data.fname); > + > + if (fd < 0 && fd != -ENOENT) > + gdb_printf (_("Download failed: %s. Continuing without %s %s.\n"), > + safe_strerror (-fd), data.desc, styled_fname.c_str ()); > +} > + > /* See debuginfod-support.h */ > > scoped_fd > @@ -263,11 +320,7 @@ debuginfod_source_query (const unsigned char *build_id, > srcpath, > &dname)); > debuginfod_set_user_data (c, nullptr); > - > - if (fd.get () < 0 && fd.get () != -ENOENT) > - gdb_printf (_("Download failed: %s. Continuing without source file %ps.\n"), > - safe_strerror (-fd.get ()), > - styled_string (file_name_style.style (), srcpath)); > + print_outcome (data, fd.get ()); > > if (fd.get () >= 0) > destname->reset (dname); > @@ -305,11 +358,7 @@ debuginfod_debuginfo_query (const unsigned char *build_id, > scoped_fd fd (debuginfod_find_debuginfo (c, build_id, build_id_len, > &dname)); > debuginfod_set_user_data (c, nullptr); > - > - if (fd.get () < 0 && fd.get () != -ENOENT) > - gdb_printf (_("Download failed: %s. Continuing without debug info for %ps.\n"), > - safe_strerror (-fd.get ()), > - styled_string (file_name_style.style (), filename)); > + print_outcome (data, fd.get ()); > > if (fd.get () >= 0) > destname->reset (dname); > @@ -346,12 +395,7 @@ debuginfod_exec_query (const unsigned char *build_id, > > scoped_fd fd (debuginfod_find_executable (c, build_id, build_id_len, &dname)); > debuginfod_set_user_data (c, nullptr); > - > - if (fd.get () < 0 && fd.get () != -ENOENT) > - gdb_printf (_("Download failed: %s. " \ > - "Continuing without executable for %ps.\n"), > - safe_strerror (-fd.get ()), > - styled_string (file_name_style.style (), filename)); > + print_outcome (data, fd.get ()); > > if (fd.get () >= 0) > destname->reset (dname); > diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c > index 567ef83de9b..98a552820ea 100644 > --- a/gdb/mi/mi-out.c > +++ b/gdb/mi/mi-out.c > @@ -258,6 +258,34 @@ mi_ui_out::main_stream () > return (string_file *) m_streams.back (); > } > > +/* Initialize a progress update to be displayed with > + mi_ui_out::do_progress_notify. */ > + > +void > +mi_ui_out::do_progress_start () > +{ > + mi_progress_info info; > + > + info.state = progress_update::START; > + m_progress_info.push_back (std::move (info)); > +} > + > +/* Indicate that a task described by MSG is in progress. */ > + > +void > +mi_ui_out::do_progress_notify (const std::string &msg, const std::string &unit, > + double cur, double total) > +{ > + mi_progress_info &info (m_progress_info.back ()); > + > + if (info.state == progress_update::START) > + { > + struct ui_file *stream = gdb_stdout; > + gdb_printf (stream, "%s...\n", msg.c_str ()); > + info.state = progress_update::WORKING; > + } > +} > + > /* Clear the buffer. */ > > void > diff --git a/gdb/mi/mi-out.h b/gdb/mi/mi-out.h > index 8f2f2d82ec0..8298e06ad46 100644 > --- a/gdb/mi/mi-out.h > +++ b/gdb/mi/mi-out.h > @@ -25,7 +25,6 @@ > struct ui_out; > struct ui_file; > > - > class mi_ui_out : public ui_out > { > public: > @@ -83,13 +82,9 @@ class mi_ui_out : public ui_out > virtual bool do_is_mi_like_p () const override > { return true; } > > - virtual void do_progress_start (const std::string &, bool) override > - { > - } > - > - virtual void do_progress_notify (double) override > - { > - } > + virtual void do_progress_start () override; > + virtual void do_progress_notify (const std::string &, const std::string &, > + double, double) override; > > virtual void do_progress_end () override > { > @@ -101,6 +96,16 @@ class mi_ui_out : public ui_out > void open (const char *name, ui_out_type type); > void close (ui_out_type type); > > + /* The state of a recent progress_update. */ > + struct mi_progress_info > + { > + /* The current state. */ > + progress_update::state state; > + }; > + > + /* Stack of progress info. */ > + std::vector m_progress_info; > + > /* Convenience method that returns the MI out's string stream cast > to its appropriate type. Assumes/asserts that output was not > redirected. */ > diff --git a/gdb/ui-out.h b/gdb/ui-out.h > index 9e6ff9a29bf..6b86c5f0870 100644 > --- a/gdb/ui-out.h > +++ b/gdb/ui-out.h > @@ -277,39 +277,56 @@ class ui_out > escapes. */ > virtual bool can_emit_style_escape () const = 0; > > - /* An object that starts and finishes a progress meter. */ > - class progress_meter > + /* An object that starts and finishes displaying progress updates. */ > + class progress_update > { > public: > + /* Represents the printing state of a progress update. */ > + enum state > + { > + /* Printing will start with the next update. */ > + START, > + /* Printing has already started. */ > + WORKING, > + /* Progress bar printing has already started. */ > + BAR > + }; > + > /* SHOULD_PRINT indicates whether something should be printed for a tty. */ > - progress_meter (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_meter () > + ~progress_update () > { > - m_uiout->do_progress_notify (1.0); > - m_uiout->do_progress_end (); > + > } > > - progress_meter (const progress_meter &) = delete; > - progress_meter &operator= (const progress_meter &) = delete; > + progress_update (const progress_update &) = delete; > + progress_update &operator= (const progress_update &) = delete; > > - /* Emit some progress for this progress meter. HOWMUCH may range > - from 0.0 to 1.0. */ > - void progress (double howmuch) > + /* Emit some progress for this progress meter. Includes current > + amount of progress made and total amount in the display. */ > + void update_progress (const std::string& msg, std::string& unit, > + double cur, double total) > { > - m_uiout->do_progress_notify (howmuch); > + m_uiout->do_progress_notify (msg, unit, cur, total); > } > > + /* Emit some progress for this progress meter. */ > + void update_progress (const std::string& msg) > + { > + m_uiout->do_progress_notify (msg, "", -1, -1); > + } > private: > > struct ui_out *m_uiout; > }; > > + virtual void do_progress_end () = 0; > + > protected: > > virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid) > @@ -344,9 +361,9 @@ 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) = 0; > - virtual void do_progress_end () = 0; > + virtual void do_progress_start () = 0; > + virtual void do_progress_notify (const std::string &, const std::string &, > + double, double) = 0; > > /* Set as not MI-like by default. It is overridden in subclasses if > necessary. */ > -- > 2.35.3 >