mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 19:50:13 +08:00
[gdb/cli] Add a progress meter
Add a progress meter. It's not used anywhere yet. gdb/ChangeLog: 2020-12-16 Tom Tromey <tom@tromey.com> Tom Tromey <tromey@redhat.com> Tom de Vries <tdevries@suse.de> * utils.h (get_chars_per_line): Declare. * utils.c (get_chars_per_line): New function. (fputs_maybe_filtered): Handle '\r'. * ui-out.h (ui_out::progress_meter): New class. (ui_out::progress, ui_out::do_progress_start) (ui_out::do_progress_notify, ui_out::do_progress_end): New methods. * ui-out.c (do_progress_end) (make_cleanup_ui_out_progress_begin_end, ui_out_progress): New functions. * mi/mi-out.h (mi_ui_out::do_progress_start) (mi_ui_out::do_progress_notify, mi_ui_out::do_progress_end): New methods. * cli-out.h (struct cli_ui_out) <do_progress_start, do_progress_notify, do_progress_end>: New methods. <enum meter_stat, struct cli_progress_info>: New. <m_meters>: New member. * cli-out.c (cli_ui_out::do_progress_start) (cli_ui_out::do_progress_notify, cli_ui_out::do_progress_end): New methods.
This commit is contained in:
@ -1,3 +1,28 @@
|
|||||||
|
2020-12-16 Tom Tromey <tom@tromey.com>
|
||||||
|
Tom Tromey <tromey@redhat.com>
|
||||||
|
Tom de Vries <tdevries@suse.de>
|
||||||
|
|
||||||
|
* utils.h (get_chars_per_line): Declare.
|
||||||
|
* utils.c (get_chars_per_line): New function.
|
||||||
|
(fputs_maybe_filtered): Handle '\r'.
|
||||||
|
* ui-out.h (ui_out::progress_meter): New class.
|
||||||
|
(ui_out::progress, ui_out::do_progress_start)
|
||||||
|
(ui_out::do_progress_notify, ui_out::do_progress_end): New
|
||||||
|
methods.
|
||||||
|
* ui-out.c (do_progress_end)
|
||||||
|
(make_cleanup_ui_out_progress_begin_end, ui_out_progress): New
|
||||||
|
functions.
|
||||||
|
* mi/mi-out.h (mi_ui_out::do_progress_start)
|
||||||
|
(mi_ui_out::do_progress_notify, mi_ui_out::do_progress_end): New
|
||||||
|
methods.
|
||||||
|
* cli-out.h (struct cli_ui_out) <do_progress_start,
|
||||||
|
do_progress_notify, do_progress_end>: New methods.
|
||||||
|
<enum meter_stat, struct cli_progress_info>: New.
|
||||||
|
<m_meters>: New member.
|
||||||
|
* cli-out.c (cli_ui_out::do_progress_start)
|
||||||
|
(cli_ui_out::do_progress_notify, cli_ui_out::do_progress_end): New
|
||||||
|
methods.
|
||||||
|
|
||||||
2020-12-16 Luis Machado <luis.machado@linaro.org>
|
2020-12-16 Luis Machado <luis.machado@linaro.org>
|
||||||
|
|
||||||
* aarch64-tdep.c (aarch64_record_data_proc_simd_fp): Record FPSR.
|
* aarch64-tdep.c (aarch64_record_data_proc_simd_fp): Record FPSR.
|
||||||
|
101
gdb/cli-out.c
101
gdb/cli-out.c
@ -265,6 +265,107 @@ cli_ui_out::do_redirect (ui_file *outstream)
|
|||||||
m_streams.pop_back ();
|
m_streams.pop_back ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The cli_ui_out::do_progress_* functions result in the following:
|
||||||
|
- printed for tty, SHOULD_PRINT == true:
|
||||||
|
<NAME
|
||||||
|
[##### ]\r>
|
||||||
|
- printed for tty, SHOULD_PRINT == false:
|
||||||
|
<>
|
||||||
|
- printed for not-a-tty:
|
||||||
|
<NAME...done.
|
||||||
|
>
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_ui_out::do_progress_start (const std::string &name, bool should_print)
|
||||||
|
{
|
||||||
|
struct ui_file *stream = m_streams.back ();
|
||||||
|
cli_progress_info meter;
|
||||||
|
|
||||||
|
meter.last_value = 0;
|
||||||
|
meter.name = name;
|
||||||
|
if (!stream->isatty ())
|
||||||
|
{
|
||||||
|
fprintf_unfiltered (stream, "%s...", meter.name.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meters.push_back (std::move (meter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_ui_out::do_progress_notify (double howmuch)
|
||||||
|
{
|
||||||
|
struct ui_file *stream = m_streams.back ();
|
||||||
|
cli_progress_info &meter (m_meters.back ());
|
||||||
|
|
||||||
|
if (meter.printing == NO_PRINT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (meter.printing == START)
|
||||||
|
{
|
||||||
|
fprintf_unfiltered (stream, "%s\n", meter.name.c_str ());
|
||||||
|
gdb_flush (stream);
|
||||||
|
meter.printing = WORKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meter.printing == WORKING && howmuch >= 1.0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!stream->isatty ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
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;
|
||||||
|
fprintf_unfiltered (stream, "\r[");
|
||||||
|
for (i = 0; i < width; ++i)
|
||||||
|
fprintf_unfiltered (stream, i < max ? "#" : " ");
|
||||||
|
fprintf_unfiltered (stream, "]");
|
||||||
|
gdb_flush (stream);
|
||||||
|
meter.printing = PROGRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_ui_out::do_progress_end ()
|
||||||
|
{
|
||||||
|
struct ui_file *stream = m_streams.back ();
|
||||||
|
cli_progress_info &meter = m_meters.back ();
|
||||||
|
|
||||||
|
if (!stream->isatty ())
|
||||||
|
{
|
||||||
|
fprintf_unfiltered (stream, "done.\n");
|
||||||
|
gdb_flush (stream);
|
||||||
|
}
|
||||||
|
else if (meter.printing == PROGRESS)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int width = get_chars_per_line () - 3;
|
||||||
|
|
||||||
|
fprintf_unfiltered (stream, "\r");
|
||||||
|
for (i = 0; i < width + 2; ++i)
|
||||||
|
fprintf_unfiltered (stream, " ");
|
||||||
|
fprintf_unfiltered (stream, "\r");
|
||||||
|
gdb_flush (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meters.pop_back ();
|
||||||
|
}
|
||||||
|
|
||||||
/* local functions */
|
/* local functions */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,6 +71,10 @@ protected:
|
|||||||
virtual void do_flush () override;
|
virtual void do_flush () override;
|
||||||
virtual void do_redirect (struct ui_file *outstream) 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_end () override;
|
||||||
|
|
||||||
bool suppress_output ()
|
bool suppress_output ()
|
||||||
{ return m_suppress_output; }
|
{ return m_suppress_output; }
|
||||||
|
|
||||||
@ -80,6 +84,33 @@ private:
|
|||||||
|
|
||||||
std::vector<ui_file *> m_streams;
|
std::vector<ui_file *> m_streams;
|
||||||
bool m_suppress_output;
|
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. */
|
||||||
|
struct cli_progress_info
|
||||||
|
{
|
||||||
|
/* The current state. */
|
||||||
|
enum meter_state printing;
|
||||||
|
/* The name to print. */
|
||||||
|
std::string name;
|
||||||
|
/* The last notification value. */
|
||||||
|
double last_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Stack of progress meters. */
|
||||||
|
std::vector<cli_progress_info> m_meters;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cli_ui_out *cli_out_new (struct ui_file *stream);
|
extern cli_ui_out *cli_out_new (struct ui_file *stream);
|
||||||
|
@ -83,6 +83,18 @@ protected:
|
|||||||
virtual bool do_is_mi_like_p () const override
|
virtual bool do_is_mi_like_p () const override
|
||||||
{ return true; }
|
{ return true; }
|
||||||
|
|
||||||
|
virtual void do_progress_start (const std::string &, bool) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void do_progress_notify (double) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void do_progress_end () override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void field_separator ();
|
void field_separator ();
|
||||||
|
37
gdb/ui-out.h
37
gdb/ui-out.h
@ -275,6 +275,39 @@ class ui_out
|
|||||||
escapes. */
|
escapes. */
|
||||||
virtual bool can_emit_style_escape () const = 0;
|
virtual bool can_emit_style_escape () const = 0;
|
||||||
|
|
||||||
|
/* An object that starts and finishes a progress meter. */
|
||||||
|
class progress_meter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
m_uiout->do_progress_start (name, should_print);
|
||||||
|
}
|
||||||
|
|
||||||
|
~progress_meter ()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct ui_out *m_uiout;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Emit some progress corresponding to the most recently created
|
||||||
|
progress meter. HOWMUCH may range from 0.0 to 1.0. */
|
||||||
|
void progress (double howmuch)
|
||||||
|
{
|
||||||
|
do_progress_notify (howmuch);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid)
|
virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid)
|
||||||
@ -309,6 +342,10 @@ class ui_out
|
|||||||
virtual void do_flush () = 0;
|
virtual void do_flush () = 0;
|
||||||
virtual void do_redirect (struct ui_file *outstream) = 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;
|
||||||
|
|
||||||
/* Set as not MI-like by default. It is overridden in subclasses if
|
/* Set as not MI-like by default. It is overridden in subclasses if
|
||||||
necessary. */
|
necessary. */
|
||||||
|
|
||||||
|
14
gdb/utils.c
14
gdb/utils.c
@ -1579,6 +1579,14 @@ gdb_flush (struct ui_file *stream)
|
|||||||
stream->flush ();
|
stream->flush ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See utils.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
get_chars_per_line ()
|
||||||
|
{
|
||||||
|
return chars_per_line;
|
||||||
|
}
|
||||||
|
|
||||||
/* Indicate that if the next sequence of characters overflows the line,
|
/* Indicate that if the next sequence of characters overflows the line,
|
||||||
a newline should be inserted here rather than when it hits the end.
|
a newline should be inserted here rather than when it hits the end.
|
||||||
If INDENT is non-null, it is a string to be printed to indent the
|
If INDENT is non-null, it is a string to be printed to indent the
|
||||||
@ -1769,6 +1777,12 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
|
|||||||
don't increment chars_printed here. */
|
don't increment chars_printed here. */
|
||||||
lineptr += skip_bytes;
|
lineptr += skip_bytes;
|
||||||
}
|
}
|
||||||
|
else if (*lineptr == '\r')
|
||||||
|
{
|
||||||
|
wrap_buffer.push_back (*lineptr);
|
||||||
|
chars_printed = 0;
|
||||||
|
lineptr++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wrap_buffer.push_back (*lineptr);
|
wrap_buffer.push_back (*lineptr);
|
||||||
|
@ -364,6 +364,10 @@ extern void wrap_here (const char *);
|
|||||||
|
|
||||||
extern void reinitialize_more_filter (void);
|
extern void reinitialize_more_filter (void);
|
||||||
|
|
||||||
|
/* Return the number of characters in a line. */
|
||||||
|
|
||||||
|
extern int get_chars_per_line ();
|
||||||
|
|
||||||
extern bool pagination_enabled;
|
extern bool pagination_enabled;
|
||||||
|
|
||||||
extern struct ui_file **current_ui_gdb_stdout_ptr (void);
|
extern struct ui_file **current_ui_gdb_stdout_ptr (void);
|
||||||
|
Reference in New Issue
Block a user