[PATCH 19/22] Class-ify ui_out_impl

simon.marchi
2016-11-26T15:20:10Z

From: Simon Marchi <simon.marchi@polymtl.ca>

This patch makes the ui_out_impl implementations an actual class
hierarchy, instead of an array of function pointers.

gdb/ChangeLog:

* ui-out.h (class ui_out_impl_base): New class, based on now removed
struct ui_out_impl.
(table_begin_ftype): Remove, replace with pure virtual method in
class ui_out_impl_base.
(table_body_ftype): Likewise.
(table_end_ftype): Likewise.
(table_header_ftype): Likewise.
(ui_out_begin_ftype): Likewise.
(ui_out_end_ftype): Likewise.
(field_int_ftype): Likewise.
(field_skip_ftype): Likewise.
(field_string_ftype): Likewise.
(field_fmt_ftype): Likewise.
(spaces_ftype): Likewise.
(text_ftype): Likewise.
(message_ftype): Likewise.
(wrap_hint_ftype): Likewise.
(flush_ftype): Likewise.
(redirect_ftype): Likewise.
(data_destroy_ftype): Likewise.
(struct ui_out_impl): Remove.
(ui_out_data): Remove.
(ui_out_new): Change type of parameter impl, remove parameter
data, add default value to parameter flags.
(ui_out_impl): New function.
(uo_field_string): Move declaration to ui-out.c.
* ui-out.c (struct ui_out) <impl>: Change type to unique_ptr to
ui_out_impl_base.
: Remove.
(uo_field_string): Move declaration from ui-out.h.
(ui_out_is_mi_like_p): Update to call virtual method.
(uo_table_begin): Remove null check, update call to virtual
method.
(uo_table_body): Likewise.
(uo_table_end): Likewise.
(uo_table_header): Likewise.
(uo_begin): Likewise.
(uo_end): Likewise.
(uo_field_int): Likewise.
(uo_field_skip): Likewise.
(uo_field_string): Likewise.
(uo_field_fmt): Likewise.
(uo_spaces): Likewise.
(uo_text): Likewise.
(uo_message): Likewise.
(uo_wrap_hint): Likewise.
(uo_flush): Likewise.
(uo_redirect): Likewise.
(ui_out_data): Remove.
(ui_out_new): Change type of parameter impl, remove parameter
data, add default value to parameter flags. Update assignment
to unique_ptr
(ui_out_impl): New function.
* cli-out.h (cli_ui_out_data): Remove, replace with class
cli_ui_out_impl.
(class cli_ui_out_impl): New class.
(cli_ui_out_impl): Remove global variable.
(cli_out_data_ctor): Remove.
* cli-out.c (cli_out_data): Remove.
(cli_uiout_dtor): Remove.
(cli_table_begin): Replace with ...
(cli_ui_out_impl::table_begin): ... this new method.
(cli_table_body): Replace with ...
(cli_ui_out_impl::table_body): ... this new method.
(cli_table_end): Replace with ...
(cli_ui_out_impl::table_end): ... this new method.
(cli_table_header): Replace with ...
(cli_ui_out_impl::table_header): ... this new method.
(cli_begin): Replace with ...
(cli_ui_out_impl::begin): ... this new method.
(cli_end): Replace with ...
(cli_ui_out_impl::table_end): ... this new method.
(cli_field_int): Replace with ...
(cli_ui_out_impl::field_int): ... this new method.
(cli_field_skip): Replace with ...
(cli_ui_out_impl::field_skip): ... this new method.
(cli_field_string): Replace with ...
(cli_ui_out_impl::field_string): ... this new method.
(cli_field_fmt): Replace with ...
(cli_ui_out_impl::field_fmt): ... this new method.
(cli_spaces): Replace with ...
(cli_ui_out_impl::spaces): ... this new method.
(cli_text): Replace with ...
(cli_ui_out_impl::text): ... this new method.
(cli_message): Replace with ...
(cli_ui_out_impl::message): ... this new method.
(cli_wrap_hint): Replace with ...
(cli_ui_out_impl::wrap_hint): ... this new method.
(cli_flush): Replace with ...
(cli_ui_out_impl::flush): ... this new method.
(cli_redirect): Replace with ...
(cli_ui_out_impl::redirect): ... this new method.
(out_field_fmt): Replace with ...
(cli_ui_out_impl::out_field_fmt): ... this new method.
(field_separator): Replace with ...
(cli_ui_out_impl::field_separator): ... this new method.
(cli_ui_out_impl): Remove.
(cli_out_data_ctor): Remove.
(cli_ui_out_impl::cli_ui_out_impl): New constructor.
(cli_ui_out_impl::~cli_ui_out_impl): New destructor.
(cli_out_new): Instantiate
(cli_field_string): Likewise.
(cli_redirect): Likewise.
(cli_out_data_ctor): Likewise.
* mi/mi-out.c (UNKNOWN): Likewise.
(mi_field_skip): Likewise.
(mi_field_string): Likewise.
(mi_field_fmt): Likewise.
(mi_out_put): Likewise.
(mi_out_data_dtor): Likewise.
(mi_ui_out_impl_from): New function.
* mi/mi-out.h (UNKNOWN): Likewise.
* tui/tui-out.c (UNKNOWN): Likewise.
---
gdb/cli-out.c | 306 +++++++++++++++++--------------------------------
gdb/cli-out.h | 58 ++++++++--
gdb/mi/mi-out.c | 333 +++++++++++++++++++++---------------------------------
gdb/mi/mi-out.h | 69 ++++++++++-
gdb/tui/tui-out.c | 158 +++++++++++---------------
gdb/ui-out.c | 95 +++++-----------
gdb/ui-out.h | 125 +++++++-------------
7 files changed, 479 insertions(+), 665 deletions(-)

diff --git a/gdb/cli-out.c b/gdb/cli-out.c
index e042926..93ca5ed 100644
--- a/gdb/cli-out.c
+++ b/gdb/cli-out.c
@@ -27,163 +27,107 @@
#include "vec.h"
#include "readline/readline.h"

-typedef struct cli_ui_out_data cli_out_data;
-
-/* Prototypes for local functions */
-
-static void cli_text (struct ui_out *uiout, const char *string);
-
-static void field_separator (void);
-
-static void out_field_fmt (struct ui_out *uiout, int fldno,
- const char *fldname,
- const char *format,...) ATTRIBUTE_PRINTF (4, 5);
-
-/* The destructor. */
-
-static void
-cli_uiout_dtor (struct ui_out *ui_out)
-{
- cli_out_data *data = (cli_out_data *) ui_out_data (ui_out);
-
- delete data;
-}
-
/* These are the CLI output functions */

/* Mark beginning of a table */

-static void
-cli_table_begin (struct ui_out *uiout, int nbrofcols,
- int nr_rows,
- const char *tblid)
+void
+cli_ui_out_impl::table_begin (int nbrofcols, int nr_rows, const char *tblid)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
if (nr_rows == 0)
- data->suppress_output = 1;
+ m_suppress_output = 1;
else
/* Only the table suppresses the output and, fortunately, a table
is not a recursive data structure. */
- gdb_assert (data->suppress_output == 0);
+ gdb_assert (m_suppress_output == 0);
}

/* Mark beginning of a table body */

-static void
-cli_table_body (struct ui_out *uiout)
+void
+cli_ui_out_impl::table_body ()
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;
+
/* first, close the table header line */
- cli_text (uiout, "\n");
+ text ("\n");
}

/* Mark end of a table */

-static void
-cli_table_end (struct ui_out *uiout)
+void
+cli_ui_out_impl::table_end ()
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- data->suppress_output = 0;
+ m_suppress_output = 0;
}

/* Specify table header */

-static void
-cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
- const std::string &col_name, const std::string &col_hdr)
+void
+cli_ui_out_impl::table_header (int width, ui_align alignment,
+ const std::string &col_name,
+ const std::string &col_hdr)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- /* Always go through the function pointer (virtual function call).
- We may have been extended. */
- uo_field_string (uiout, 0, width, alignment, 0, col_hdr.c_str ());
+ field_string (0, width, alignment, 0, col_hdr.c_str ());
}

/* Mark beginning of a list */

-static void
-cli_begin (struct ui_out *uiout,
- enum ui_out_type type,
- const char *id)
+void
+cli_ui_out_impl::begin (ui_out_type type, const char *id)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
- return;
}

/* Mark end of a list */

-static void
-cli_end (struct ui_out *uiout,
- enum ui_out_type type)
+void
+cli_ui_out_impl::end (ui_out_type type)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
- return;
}

/* output an int field */

-static void
-cli_field_int (struct ui_out *uiout, int fldno, int width,
- enum ui_align alignment,
- const char *fldname, int value)
+void
+cli_ui_out_impl::field_int (int fldno, int width, ui_align alignment,
+ const char *fldname, int value)
{
char buffer[20]; /* FIXME: how many chars long a %d can become? */
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);

- if (data->suppress_output)
+ if (m_suppress_output)
return;
+
xsnprintf (buffer, sizeof (buffer), "%d", value);

- /* Always go through the function pointer (virtual function call).
- We may have been extended. */
- uo_field_string (uiout, fldno, width, alignment, fldname, buffer);
+ field_string (fldno, width, alignment, fldname, buffer);
}

-/* used to ommit a field */
+/* used to omit a field */

-static void
-cli_field_skip (struct ui_out *uiout, int fldno, int width,
- enum ui_align alignment,
- const char *fldname)
+void
+cli_ui_out_impl::field_skip (int fldno, int width, ui_align alignment,
+ const char *fldname)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- /* Always go through the function pointer (virtual function call).
- We may have been extended. */
- uo_field_string (uiout, fldno, width, alignment, fldname, "");
+ field_string (fldno, width, alignment, fldname, "");
}

/* other specific cli_field_* end up here so alignment and field
separators are both handled by cli_field_string */

-static void
-cli_field_string (struct ui_out *uiout,
- int fldno,
- int width,
- enum ui_align align,
- const char *fldname,
- const char *string)
+void
+cli_ui_out_impl::field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string)
{
int before = 0;
int after = 0;
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);

- if (data->suppress_output)
+ if (m_suppress_output)
return;

if ((align != ui_noalign) && string)
@@ -210,11 +154,13 @@ cli_field_string (struct ui_out *uiout,
}

if (before)
- ui_out_spaces (uiout, before);
+ spaces (before);
+
if (string)
- out_field_fmt (uiout, fldno, fldname, "%s", string);
+ out_field_fmt (fldno, fldname, "%s", string);
+
if (after)
- ui_out_spaces (uiout, after);
+ spaces (after);

if (align != ui_noalign)
field_separator ();
@@ -222,96 +168,73 @@ cli_field_string (struct ui_out *uiout,

/* This is the only field function that does not align. */

-static void ATTRIBUTE_PRINTF (6, 0)
-cli_field_fmt (struct ui_out *uiout, int fldno,
- int width, enum ui_align align,
- const char *fldname,
- const char *format,
- va_list args)
+void
+cli_ui_out_impl::field_fmt (int fldno, int width, ui_align align,
+ const char *fldname, const char *format,
+ va_list args)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *stream;
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- stream = data->streams.back ();
- vfprintf_filtered (stream, format, args);
+ vfprintf_filtered (m_streams.back (), format, args);

if (align != ui_noalign)
field_separator ();
}

-static void
-cli_spaces (struct ui_out *uiout, int numspaces)
+void
+cli_ui_out_impl::spaces (int numspaces)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *stream;
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- stream = data->streams.back ();
- print_spaces_filtered (numspaces, stream);
+ print_spaces_filtered (numspaces, m_streams.back ());
}

-static void
-cli_text (struct ui_out *uiout, const char *string)
+void
+cli_ui_out_impl::text (const char *string)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *stream;
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- stream = data->streams.back ();
- fputs_filtered (string, stream);
+ fputs_filtered (string, m_streams.back ());
}

-static void ATTRIBUTE_PRINTF (2, 0)
-cli_message (struct ui_out *uiout, const char *format, va_list args)
+void
+cli_ui_out_impl::message (const char *format, va_list args)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- struct ui_file *stream = data->streams.back ();
- vfprintf_unfiltered (stream, format, args);
+ vfprintf_unfiltered (m_streams.back (), format, args);
}

-static void
-cli_wrap_hint (struct ui_out *uiout, const char *identstring)
+void
+cli_ui_out_impl::wrap_hint (const char *identstring)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;
+
wrap_here (identstring);
}

-static void
-cli_flush (struct ui_out *uiout)
+void
+cli_ui_out_impl::flush ()
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *stream = data->streams.back ();
-
- gdb_flush (stream);
+ gdb_flush (m_streams.back ());
}

/* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams
and make it therefore active. OUTSTREAM as NULL will pop the last pushed
output stream; it is an internal error if it does not exist. */

-static int
-cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
+int
+cli_ui_out_impl::redirect (ui_file *outstream)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
-
if (outstream != NULL)
- data->streams.push_back (outstream);
+ m_streams.push_back (outstream);
else
- data->streams.pop_back ();
+ m_streams.pop_back ();

return 0;
}
@@ -322,66 +245,38 @@ cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
and makes a va_list and does not insert a separator. */

/* VARARGS */
-static void
-out_field_fmt (struct ui_out *uiout, int fldno,
- const char *fldname,
- const char *format,...)
+void
+cli_ui_out_impl::out_field_fmt (int fldno, const char *fldname,
+ const char *format, ...)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *stream = data->streams.back ();
va_list args;

va_start (args, format);
- vfprintf_filtered (stream, format, args);
+ vfprintf_filtered (m_streams.back (), format, args);

va_end (args);
}

/* Access to ui_out format private members. */

-static void
-field_separator (void)
+void
+cli_ui_out_impl::field_separator (void)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (current_uiout);
- struct ui_file *stream = data->streams.back ();
-
- fputc_filtered (' ', stream);
+ fputc_filtered (' ', m_streams.back ());
}

-/* This is the CLI ui-out implementation functions vector */
+/* Constructor for cli_ui_out_impl. */

-const struct ui_out_impl cli_ui_out_impl =
-{
- cli_table_begin,
- cli_table_body,
- cli_table_end,
- cli_table_header,
- cli_begin,
- cli_end,
- cli_field_int,
- cli_field_skip,
- cli_field_string,
- cli_field_fmt,
- cli_spaces,
- cli_text,
- cli_message,
- cli_wrap_hint,
- cli_flush,
- cli_redirect,
- cli_uiout_dtor,
- 0, /* Does not need MI hacks (i.e. needs CLI hacks). */
-};
-
-/* Constructor for a `cli_out_data' object. */
-
-void
-cli_out_data_ctor (cli_out_data *self, struct ui_file *stream)
+cli_ui_out_impl::cli_ui_out_impl (ui_file *stream)
+: m_suppress_output (0)
{
gdb_assert (stream != NULL);

- self->streams.push_back (stream);
+ m_streams.push_back (stream);
+}

- self->suppress_output = 0;
+cli_ui_out_impl::~cli_ui_out_impl ()
+{
}

/* Initialize private members at startup. */
@@ -389,26 +284,33 @@ cli_out_data_ctor (cli_out_data *self, struct ui_file *stream)
struct ui_out *
cli_out_new (struct ui_file *stream)
{
- int flags = ui_source_list;
- cli_out_data *data = new cli_out_data ();
+ cli_ui_out_impl *impl = new cli_ui_out_impl (stream);

- cli_out_data_ctor (data, stream);
- return ui_out_new (&cli_ui_out_impl, data, flags);
+ return ui_out_new (impl, ui_source_list);
}

-struct ui_file *
-cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
+ui_file *
+cli_ui_out_impl::set_stream (struct ui_file *stream)
{
- cli_out_data *data = (cli_out_data *) ui_out_data (uiout);
- struct ui_file *old;
+ ui_file *old;

- old = data->streams.back ();
- data->streams.pop_back ();
- data->streams.push_back (stream);
+ old = m_streams.back ();
+ m_streams.pop_back ();
+ m_streams.push_back (stream);

return old;
}

+ui_file *
+cli_out_set_stream (struct ui_out *uiout, ui_file *stream)
+{
+ cli_ui_out_impl *impl = dynamic_cast<cli_ui_out_impl *> (ui_out_impl (uiout));
+
+ gdb_assert (impl != NULL);
+
+ return impl->set_stream (stream);
+}
+
/* CLI interface to display tab-completion matches. */

/* CLI version of displayer.crlf. */
diff --git a/gdb/cli-out.h b/gdb/cli-out.h
index 296b8c0..aacb8c5 100644
--- a/gdb/cli-out.h
+++ b/gdb/cli-out.h
@@ -23,22 +23,58 @@
#include "ui-out.h"
#include <vector>

-/* These are exported so that they can be extended by other `ui_out'
- implementations, like TUI's. */
+class cli_ui_out_impl : public ui_out_impl_base
+{
+public:

-struct cli_ui_out_data
- {
- std::vector<ui_file *> streams;
- int suppress_output;
- };
+ cli_ui_out_impl (ui_file *stream);
+ virtual ~cli_ui_out_impl ();

-extern const struct ui_out_impl cli_ui_out_impl;
+ virtual void table_begin (int nbrofcols, int nr_rows,
+ const char *tblid) override;
+ virtual void table_body () override;
+ virtual void table_end () override;
+ virtual void table_header (int width, ui_align align,
+ const std::string &col_name,
+ const std::string &col_hdr) override;
+ /* Note: level 0 is the top-level so LEVEL is always greater than
+ zero. */
+ virtual void begin (ui_out_type type, const char *id) override;
+ virtual void end (ui_out_type type) override;
+ virtual void field_int (int fldno, int width, ui_align align,
+ const char *fldname, int value) override;
+ virtual void field_skip (int fldno, int width, ui_align align,
+ const char *fldname) override;
+ virtual void field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string) override;
+ virtual void ATTRIBUTE_PRINTF(6,0) field_fmt (int fldno, int width,
+ ui_align align,
+ const char *fldname,
+ const char *format,
+ va_list args) override;
+ virtual void spaces (int numspaces) override;
+ virtual void text (const char *string) override;
+ virtual void ATTRIBUTE_PRINTF(2,0)
+ message (const char *format, va_list args) override;
+ virtual void wrap_hint (const char *identstring) override;
+ virtual void flush () override;
+ virtual int redirect (struct ui_file * outstream) override;

+ ui_file *set_stream (ui_file *stream);

-extern struct ui_out *cli_out_new (struct ui_file *stream);
+protected:
+
+ std::vector<ui_file *> m_streams;
+ int m_suppress_output;
+
+private:
+ void field_separator (void);

-extern void cli_out_data_ctor (struct cli_ui_out_data *data,
- struct ui_file *stream);
+ void ATTRIBUTE_PRINTF(4, 5)
+ out_field_fmt (int fldno, const char *fldname, const char *format, ...);
+};
+
+extern struct ui_out *cli_out_new (struct ui_file *stream);

extern struct ui_file *cli_out_set_stream (struct ui_out *uiout,
struct ui_file *stream);
diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c
index b7cd433..744b113 100644
--- a/gdb/mi/mi-out.c
+++ b/gdb/mi/mi-out.c
@@ -25,185 +25,100 @@
#include "vec.h"
#include <vector>

-struct mi_ui_out_data
- {
- int suppress_field_separator;
- int suppress_output;
- int mi_version;
- std::vector<ui_file *> streams;
- };
-typedef struct mi_ui_out_data mi_out_data;
-
-/* These are the MI output functions */
-
-static void mi_out_data_dtor (struct ui_out *ui_out);
-static void mi_table_begin (struct ui_out *uiout, int nbrofcols,
- int nr_rows, const char *tblid);
-static void mi_table_body (struct ui_out *uiout);
-static void mi_table_end (struct ui_out *uiout);
-static void mi_table_header (struct ui_out *uiout, int width,
- enum ui_align alignment,
- const std::string &col_name,
- const std::string &col_hdr);
-static void mi_begin (struct ui_out *uiout, enum ui_out_type type,
- const char *id);
-static void mi_end (struct ui_out *uiout, enum ui_out_type type);
-static void mi_field_int (struct ui_out *uiout, int fldno, int width,
- enum ui_align alig, const char *fldname, int value);
-static void mi_field_skip (struct ui_out *uiout, int fldno, int width,
- enum ui_align alig, const char *fldname);
-static void mi_field_string (struct ui_out *uiout, int fldno, int width,
- enum ui_align alig, const char *fldname,
- const char *string);
-static void mi_field_fmt (struct ui_out *uiout, int fldno,
- int width, enum ui_align align,
- const char *fldname, const char *format,
- va_list args) ATTRIBUTE_PRINTF (6, 0);
-static void mi_spaces (struct ui_out *uiout, int numspaces);
-static void mi_text (struct ui_out *uiout, const char *string);
-static void mi_message (struct ui_out *uiout, const char *format, va_list args)
- ATTRIBUTE_PRINTF (2, 0);
-static void mi_wrap_hint (struct ui_out *uiout, const char *identstring);
-static void mi_flush (struct ui_out *uiout);
-static int mi_redirect (struct ui_out *uiout, struct ui_file *outstream);
-
-/* This is the MI ui-out implementation functions vector */
-
-static const struct ui_out_impl mi_ui_out_impl =
-{
- mi_table_begin,
- mi_table_body,
- mi_table_end,
- mi_table_header,
- mi_begin,
- mi_end,
- mi_field_int,
- mi_field_skip,
- mi_field_string,
- mi_field_fmt,
- mi_spaces,
- mi_text,
- mi_message,
- mi_wrap_hint,
- mi_flush,
- mi_redirect,
- mi_out_data_dtor,
- 1, /* Needs MI hacks. */
-};
-
-/* Prototypes for local functions */
-
-static void field_separator (struct ui_out *uiout);
-static void mi_open (struct ui_out *uiout, const char *name,
- enum ui_out_type type);
-static void mi_close (struct ui_out *uiout, enum ui_out_type type);
-
/* Mark beginning of a table. */

void
-mi_table_begin (struct ui_out *uiout,
- int nr_cols,
- int nr_rows,
- const char *tblid)
+mi_ui_out_impl::table_begin (int nr_cols, int nr_rows,
+ const char *tblid)
{
- mi_open (uiout, tblid, ui_out_type_tuple);
- mi_field_int (uiout, -1, -1, ui_left, "nr_rows", nr_rows);
- mi_field_int (uiout, -1, -1, ui_left, "nr_cols", nr_cols);
- mi_open (uiout, "hdr", ui_out_type_list);
+ open (tblid, ui_out_type_tuple);
+ field_int (-1, -1, ui_left, "nr_rows", nr_rows);
+ field_int (-1, -1, ui_left, "nr_cols", nr_cols);
+ open ("hdr", ui_out_type_list);
}

/* Mark beginning of a table body. */

void
-mi_table_body (struct ui_out *uiout)
+mi_ui_out_impl::table_body ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;
/* close the table header line if there were any headers */
- mi_close (uiout, ui_out_type_list);
- mi_open (uiout, "body", ui_out_type_list);
+ close (ui_out_type_list);
+ open ("body", ui_out_type_list);
}

/* Mark end of a table. */

void
-mi_table_end (struct ui_out *uiout)
+mi_ui_out_impl::table_end ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- data->suppress_output = 0;
- mi_close (uiout, ui_out_type_list); /* body */
- mi_close (uiout, ui_out_type_tuple);
+ m_suppress_output = 0;
+ close (ui_out_type_list); /* body */
+ close (ui_out_type_tuple);
}

/* Specify table header. */

void
-mi_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
- const std::string &col_name, const std::string &col_hdr)
+mi_ui_out_impl::table_header (int width, ui_align alignment,
+ const std::string &col_name,
+ const std::string &col_hdr)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- mi_open (uiout, NULL, ui_out_type_tuple);
- mi_field_int (uiout, 0, 0, ui_center, "width", width);
- mi_field_int (uiout, 0, 0, ui_center, "alignment", alignment);
- mi_field_string (uiout, 0, 0, ui_center, "col_name", col_name.c_str ());
- mi_field_string (uiout, 0, width, alignment, "colhdr", col_hdr.c_str ());
- mi_close (uiout, ui_out_type_tuple);
+ open (NULL, ui_out_type_tuple);
+ field_int (0, 0, ui_center, "width", width);
+ field_int (0, 0, ui_center, "alignment", alignment);
+ field_string (0, 0, ui_center, "col_name", col_name.c_str ());
+ field_string (0, width, alignment, "colhdr", col_hdr.c_str ());
+ close (ui_out_type_tuple);
}

/* Mark beginning of a list. */

void
-mi_begin (struct ui_out *uiout, enum ui_out_type type, const char *id)
+mi_ui_out_impl::begin (ui_out_type type, const char *id)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- mi_open (uiout, id, type);
+ open (id, type);
}

/* Mark end of a list. */

void
-mi_end (struct ui_out *uiout, enum ui_out_type type)
+mi_ui_out_impl::end (ui_out_type type)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- mi_close (uiout, type);
+ close (type);
}

/* Output an int field. */

-static void
-mi_field_int (struct ui_out *uiout, int fldno, int width,
- enum ui_align alignment, const char *fldname, int value)
+void
+mi_ui_out_impl::field_int (int fldno, int width, ui_align alignment,
+ const char *fldname, int value)
{
char buffer[20]; /* FIXME: how many chars long a %d can become? */
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);

- if (data->suppress_output)
+ if (m_suppress_output)
return;

xsnprintf (buffer, sizeof (buffer), "%d", value);
- mi_field_string (uiout, fldno, width, alignment, fldname, buffer);
+ field_string (fldno, width, alignment, fldname, buffer);
}

/* Used to omit a field. */

void
-mi_field_skip (struct ui_out *uiout, int fldno, int width,
- enum ui_align alignment, const char *fldname)
+mi_ui_out_impl::field_skip (int fldno, int width, ui_align alignment,
+ const char *fldname)
{
}

@@ -211,17 +126,15 @@ mi_field_skip (struct ui_out *uiout, int fldno, int width,
separators are both handled by mi_field_string. */

void
-mi_field_string (struct ui_out *uiout, int fldno, int width,
- enum ui_align align, const char *fldname, const char *string)
+mi_ui_out_impl::field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- struct ui_file *stream;
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- stream = data->streams.back ();
- field_separator (uiout);
+ ui_file *stream = m_streams.back ();
+ field_separator ();
+
if (fldname)
fprintf_unfiltered (stream, "%s=", fldname);
fprintf_unfiltered (stream, "\"");
@@ -233,18 +146,16 @@ mi_field_string (struct ui_out *uiout, int fldno, int width,
/* This is the only field function that does not align. */

void
-mi_field_fmt (struct ui_out *uiout, int fldno, int width,
- enum ui_align align, const char *fldname,
- const char *format, va_list args)
+mi_ui_out_impl::field_fmt (int fldno, int width, ui_align align,
+ const char *fldname, const char *format,
+ va_list args)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- struct ui_file *stream;
-
- if (data->suppress_output)
+ if (m_suppress_output)
return;

- stream = data->streams.back ();
- field_separator (uiout);
+ ui_file *stream = m_streams.back ();
+ field_separator ();
+
if (fldname)
fprintf_unfiltered (stream, "%s=\"", fldname);
else
@@ -254,125 +165,115 @@ mi_field_fmt (struct ui_out *uiout, int fldno, int width,
}

void
-mi_spaces (struct ui_out *uiout, int numspaces)
+mi_ui_out_impl::spaces (int numspaces)
{
}

void
-mi_text (struct ui_out *uiout, const char *string)
+mi_ui_out_impl::text (const char *string)
{
}

void
-mi_message (struct ui_out *uiout, const char *format, va_list args)
+mi_ui_out_impl::message (const char *format, va_list args)
{
}

void
-mi_wrap_hint (struct ui_out *uiout, const char *identstring)
+mi_ui_out_impl::wrap_hint (const char *identstring)
{
wrap_here (identstring);
}

void
-mi_flush (struct ui_out *uiout)
+mi_ui_out_impl::flush ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- struct ui_file *stream = data->streams.back ();

- gdb_flush (stream);
+ gdb_flush (m_streams.back ());
}

int
-mi_redirect (struct ui_out *uiout, struct ui_file *outstream)
+mi_ui_out_impl::redirect (ui_file *outstream)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
if (outstream != NULL)
- data->streams.push_back (outstream);
+ m_streams.push_back (outstream);
else
- data->streams.pop_back ();
+ m_streams.pop_back ();

return 0;
}

-/* local functions */
-
-/* access to ui_out format private members */
-
-static void
-field_separator (struct ui_out *uiout)
+void
+mi_ui_out_impl::field_separator ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- ui_file *stream = data->streams.back ();
-
- if (data->suppress_field_separator)
- data->suppress_field_separator = 0;
+ if (m_suppress_field_separator)
+ m_suppress_field_separator = 0;
else
- fputc_unfiltered (',', stream);
+ fputc_unfiltered (',', m_streams.back ());
}

-static void
-mi_open (struct ui_out *uiout, const char *name, enum ui_out_type type)
+void
+mi_ui_out_impl::open (const char *name, ui_out_type type)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- ui_file *stream = data->streams.back ();
+ ui_file *stream = m_streams.back ();
+
+ field_separator ();
+ m_suppress_field_separator = 1;

- field_separator (uiout);
- data->suppress_field_separator = 1;
if (name)
fprintf_unfiltered (stream, "%s=", name);
+
switch (type)
{
case ui_out_type_tuple:
fputc_unfiltered ('{', stream);
break;
+
case ui_out_type_list:
fputc_unfiltered ('[', stream);
break;
+
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
}

-static void
-mi_close (struct ui_out *uiout, enum ui_out_type type)
+void
+mi_ui_out_impl::close (ui_out_type type)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- ui_file *stream = data->streams.back ();
+ ui_file *stream = m_streams.back ();

switch (type)
{
case ui_out_type_tuple:
fputc_unfiltered ('}', stream);
break;
+
case ui_out_type_list:
fputc_unfiltered (']', stream);
break;
+
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
- data->suppress_field_separator = 0;
+
+ m_suppress_field_separator = 0;
}

/* Clear the buffer. */

void
-mi_out_rewind (struct ui_out *uiout)
+mi_ui_out_impl::rewind ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- ui_file *stream = data->streams.back ();
-
- ui_file_rewind (stream);
+ ui_file_rewind (m_streams.back ());
}

/* Dump the buffer onto the specified stream. */

void
-mi_out_put (struct ui_out *uiout, struct ui_file *stream)
+mi_ui_out_impl::put (ui_file *stream)
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
- ui_file *outstream = data->streams.back ();
+ ui_file *outstream = m_streams.back ();

ui_file_put (outstream, ui_file_write_for_put, stream);
ui_file_rewind (outstream);
@@ -381,35 +282,25 @@ mi_out_put (struct ui_out *uiout, struct ui_file *stream)
/* Return the current MI version. */

int
-mi_version (struct ui_out *uiout)
+mi_ui_out_impl::version ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (uiout);
-
- return data->mi_version;
+ return m_mi_version;
}

/* Constructor for an `mi_out_data' object. */

-static void
-mi_out_data_ctor (mi_out_data *self, int mi_version, struct ui_file *stream)
+mi_ui_out_impl::mi_ui_out_impl (int mi_version, ui_file *stream)
+: m_suppress_field_separator (0),
+ m_suppress_output (0),
+ m_mi_version (mi_version)
{
gdb_assert (stream != NULL);

- self->streams.push_back (stream);
-
- self->suppress_field_separator = 0;
- self->suppress_output = 0;
- self->mi_version = mi_version;
+ m_streams.push_back (stream);
}

-/* The destructor. */
-
-static void
-mi_out_data_dtor (struct ui_out *ui_out)
+mi_ui_out_impl::~mi_ui_out_impl ()
{
- mi_out_data *data = (mi_out_data *) ui_out_data (ui_out);
-
- delete data;
}

/* Initialize private members at startup. */
@@ -417,10 +308,40 @@ mi_out_data_dtor (struct ui_out *ui_out)
struct ui_out *
mi_out_new (int mi_version)
{
- int flags = 0;
- mi_out_data *data = new mi_out_data ();
- struct ui_file *stream = mem_fileopen ();
+ ui_file *stream = mem_fileopen ();
+ mi_ui_out_impl *impl = new mi_ui_out_impl (mi_version, stream);
+
+ return ui_out_new (impl);
+}
+
+/* Helper to return the implementation behind UIOUT, casted to a
+ mi_ui_out_impl *. It is an error to call this function with an ui_out that
+ is not an MI. */
+
+static mi_ui_out_impl *
+mi_ui_out_impl_from (ui_out *uiout)
+{
+ mi_ui_out_impl *impl = dynamic_cast<mi_ui_out_impl *> (ui_out_impl (uiout));
+
+ gdb_assert (impl != NULL);
+
+ return impl;
+}
+
+int
+mi_version (ui_out *uiout)
+{
+ return mi_ui_out_impl_from (uiout)->version ();
+}
+
+void
+mi_out_put (ui_out *uiout, struct ui_file *stream)
+{
+ return mi_ui_out_impl_from (uiout)->put (stream);
+}

- mi_out_data_ctor (data, mi_version, stream);
- return ui_out_new (&mi_ui_out_impl, data, flags);
+void
+mi_out_rewind (ui_out *uiout)
+{
+ return mi_ui_out_impl_from (uiout)->rewind ();
}
diff --git a/gdb/mi/mi-out.h b/gdb/mi/mi-out.h
index ba18950..a45d2e3 100644
--- a/gdb/mi/mi-out.h
+++ b/gdb/mi/mi-out.h
@@ -20,14 +20,73 @@
#ifndef MI_OUT_H
#define MI_OUT_H 1

+#include <vector>
+
struct ui_out;
struct ui_file;

-extern struct ui_out *mi_out_new (int mi_version);
-extern void mi_out_put (struct ui_out *uiout, struct ui_file *stream);
-extern void mi_out_rewind (struct ui_out *uiout);

-/* Return the version number of the current MI. */
-extern int mi_version (struct ui_out *uiout);
+class mi_ui_out_impl : public ui_out_impl_base
+{
+public:
+
+ mi_ui_out_impl (int mi_version, ui_file *stream);
+ virtual ~mi_ui_out_impl ();
+
+ virtual void table_begin (int nbrofcols, int nr_rows, const char *tblid)
+ override;
+ virtual void table_body () override;
+ virtual void table_header (int width, ui_align align,
+ const std::string &col_name,
+ const std::string &col_hdr) override;
+ virtual void table_end () override;
+
+ /* Note: level 0 is the top-level so LEVEL is always greater than
+ zero. */
+ virtual void begin (ui_out_type type, const char *id) override;
+ virtual void end (ui_out_type type) override;
+ virtual void field_int (int fldno, int width, ui_align align,
+ const char *fldname, int value) override;
+ virtual void field_skip (int fldno, int width, ui_align align,
+ const char *fldname) override;
+ virtual void field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string) override;
+ virtual void ATTRIBUTE_PRINTF(6,0)
+ field_fmt (int fldno, int width, ui_align align, const char *fldname,
+ const char *format, va_list args) override;
+ virtual void spaces (int numspaces) override;
+ virtual void text (const char *string) override;
+ virtual void ATTRIBUTE_PRINTF(2,0) message (const char *format, va_list args)
+ override;
+ virtual void wrap_hint (const char *identstring) override;
+ virtual void flush () override;
+ virtual int redirect (struct ui_file * outstream) override;
+
+ virtual int is_mi_like_p () override
+ { return 1; }
+
+ /* MI-specific */
+ void rewind ();
+ void put (struct ui_file *stream);
+ /* Return the version number of the current MI. */
+ int version ();
+
+private:
+
+ void field_separator ();
+ void open (const char *name, ui_out_type type);
+ void close (ui_out_type type);
+
+ int m_suppress_field_separator;
+ int m_suppress_output;
+ int m_mi_version;
+ std::vector<ui_file *> m_streams;
+};
+
+ui_out *mi_out_new (int mi_version);
+int mi_version (ui_out *uiout);
+void mi_out_put (ui_out *uiout, struct ui_file *stream);
+void mi_out_rewind (ui_out *uiout);
+

#endif /* MI_OUT_H */
diff --git a/gdb/tui/tui-out.c b/gdb/tui/tui-out.c
index 4856562..70633f3 100644
--- a/gdb/tui/tui-out.c
+++ b/gdb/tui/tui-out.c
@@ -24,154 +24,122 @@
#include "ui-out.h"
#include "cli-out.h"
#include "tui.h"
-struct tui_ui_out_data
- {
- struct cli_ui_out_data base;

- int line;
- int start_of_line;
- };
-typedef struct tui_ui_out_data tui_out_data;
+class tui_ui_out_impl : public cli_ui_out_impl
+{
+public:
+
+ tui_ui_out_impl (ui_file *stream);
+
+ void field_int (int fldno, int width, ui_align align, const char *fldname,
+ int value) override;
+ void field_string (int fldno, int width, ui_align align, const char *fldname,
+ const char *string) override;
+ void ATTRIBUTE_PRINTF(6,0)
+ field_fmt (int fldno, int width, ui_align align, const char *fldname,
+ const char *format, va_list args) override;
+ void text (const char *string) override;

-/* This is the TUI ui-out implementation functions vector. It is
- initialized below in _initialize_tui_out, inheriting the CLI
- version, and overriding a few methods. */
+private:

-static struct ui_out_impl tui_ui_out_impl;
+ int m_line;
+ int m_start_of_line;
+};

/* Output an int field. */

-static void
-tui_field_int (struct ui_out *uiout,
- int fldno, int width,
- enum ui_align alignment,
- const char *fldname,
- int value)
+void
+tui_ui_out_impl::field_int (int fldno, int width, ui_align alignment,
+ const char *fldname, int value)
{
- tui_out_data *data = (tui_out_data *) ui_out_data (uiout);
-
- if (data->base.suppress_output)
+ if (m_suppress_output)
return;

/* Don't print line number, keep it for later. */
- if (data->start_of_line == 0 && strcmp (fldname, "line") == 0)
+ if (m_start_of_line == 0 && strcmp (fldname, "line") == 0)
{
- data->start_of_line ++;
- data->line = value;
+ m_start_of_line++;
+ m_line = value;
return;
}
- data->start_of_line ++;
+ m_start_of_line++;

- (*cli_ui_out_impl.field_int) (uiout, fldno,
- width, alignment, fldname, value);
+ cli_ui_out_impl::field_int (fldno, width, alignment, fldname, value);
}

/* Other cli_field_* end up here so alignment and field separators are
both handled by tui_field_string. */

-static void
-tui_field_string (struct ui_out *uiout,
- int fldno, int width,
- enum ui_align align,
- const char *fldname,
- const char *string)
+void
+tui_ui_out_impl::field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string)
{
- tui_out_data *data = (tui_out_data *) ui_out_data (uiout);
-
- if (data->base.suppress_output)
+ if (m_suppress_output)
return;

- if (fldname && data->line > 0 && strcmp (fldname, "fullname") == 0)
+ if (fldname && m_line > 0 && strcmp (fldname, "fullname") == 0)
{
- data->start_of_line ++;
- if (data->line > 0)
+ m_start_of_line++;
+ if (m_line > 0)
{
- tui_show_source (string, data->line);
+ tui_show_source (string, m_line);
}
return;
}

- data->start_of_line++;
+ m_start_of_line++;

- (*cli_ui_out_impl.field_string) (uiout, fldno,
- width, align,
- fldname, string);
+ cli_ui_out_impl::field_string (fldno, width, align, fldname, string);
}

/* This is the only field function that does not align. */

-static void
-tui_field_fmt (struct ui_out *uiout, int fldno,
- int width, enum ui_align align,
- const char *fldname,
- const char *format,
- va_list args)
+void
+tui_ui_out_impl::field_fmt (int fldno, int width, ui_align align,
+ const char *fldname, const char *format,
+ va_list args)
{
- tui_out_data *data = (tui_out_data *) ui_out_data (uiout);
-
- if (data->base.suppress_output)
+ if (m_suppress_output)
return;

- data->start_of_line++;
+ m_start_of_line++;

- (*cli_ui_out_impl.field_fmt) (uiout, fldno,
- width, align,
- fldname, format, args);
+ cli_ui_out_impl::field_fmt (fldno, width, align, fldname, format, args);
}

-static void
-tui_text (struct ui_out *uiout, const char *string)
+void
+tui_ui_out_impl::text (const char *string)
{
- tui_out_data *data = (tui_out_data *) ui_out_data (uiout);
-
- if (data->base.suppress_output)
+ if (m_suppress_output)
return;
- data->start_of_line ++;
- if (data->line > 0)
+
+ m_start_of_line++;
+ if (m_line > 0)
{
if (strchr (string, '\n') != 0)
{
- data->line = -1;
- data->start_of_line = 0;
+ m_line = -1;
+ m_start_of_line = 0;
}
return;
}
if (strchr (string, '\n'))
- data->start_of_line = 0;
+ m_start_of_line = 0;

- (*cli_ui_out_impl.text) (uiout, string);
+ cli_ui_out_impl::text (string);
}

-struct ui_out *
-tui_out_new (struct ui_file *stream)
+tui_ui_out_impl::tui_ui_out_impl (ui_file *stream)
+: cli_ui_out_impl (stream),
+ m_line (0),
+ m_start_of_line (-1)
{
- int flags = 0;
-
- tui_out_data *data = new tui_out_data ();
-
- /* Initialize base "class". */
- cli_out_data_ctor (&data->base, stream);
-
- /* Initialize our fields. */
- data->line = -1;
- data->start_of_line = 0;
-
- return ui_out_new (&tui_ui_out_impl, data, flags);
}

-/* Standard gdb initialization hook. */
-
-extern void _initialize_tui_out (void);
-
-void
-_initialize_tui_out (void)
+struct ui_out *
+tui_out_new (struct ui_file *stream)
{
- /* Inherit the CLI version. */
- tui_ui_out_impl = cli_ui_out_impl;
-
- /* Override a few methods. */
- tui_ui_out_impl.field_int = tui_field_int;
- tui_ui_out_impl.field_string = tui_field_string;
- tui_ui_out_impl.field_fmt = tui_field_fmt;
- tui_ui_out_impl.text = tui_text;
+ tui_ui_out_impl *impl = new tui_ui_out_impl (stream);
+
+ return ui_out_new (impl, 0);
}
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 1717491..78db2be 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -28,6 +28,7 @@
#include <vector>
#include <memory>
#include <string>
+#include <memory>

/* A header of a ui_out_table. */

@@ -175,8 +176,7 @@ struct ui_out
{
int flags;
/* Specific implementation of ui-out. */
- const struct ui_out_impl *impl;
- void *data;
+ std::unique_ptr<ui_out_impl_base> impl;

/* Vector to store and track the ui-out levels. */
std::vector<std::unique_ptr<ui_out_level>> levels;
@@ -251,6 +251,10 @@ static void uo_message (struct ui_out *uiout,
static void uo_wrap_hint (struct ui_out *uiout, const char *identstring);
static void uo_flush (struct ui_out *uiout);
static int uo_redirect (struct ui_out *uiout, struct ui_file *outstream);
+static void uo_field_string (struct ui_out *uiout, int fldno, int width,
+ enum ui_align align, const char *fldname,
+ const char *string);
+

/* Prototypes for local functions */

@@ -603,7 +607,7 @@ ui_out_test_flags (struct ui_out *uiout, int mask)
int
ui_out_is_mi_like_p (struct ui_out *uiout)
{
- return uiout->impl->is_mi_like_p;
+ return uiout->impl->is_mi_like_p ();
}

/* Interface to the implementation functions. */
@@ -613,34 +617,26 @@ uo_table_begin (struct ui_out *uiout, int nbrofcols,
int nr_rows,
const char *tblid)
{
- if (!uiout->impl->table_begin)
- return;
- uiout->impl->table_begin (uiout, nbrofcols, nr_rows, tblid);
+ uiout->impl->table_begin (nbrofcols, nr_rows, tblid);
}

void
uo_table_body (struct ui_out *uiout)
{
- if (!uiout->impl->table_body)
- return;
- uiout->impl->table_body (uiout);
+ uiout->impl->table_body ();
}

void
uo_table_end (struct ui_out *uiout)
{
- if (!uiout->impl->table_end)
- return;
- uiout->impl->table_end (uiout);
+ uiout->impl->table_end ();
}

void
uo_table_header (struct ui_out *uiout, int width, enum ui_align align,
const std::string &col_name, const std::string &col_hdr)
{
- if (!uiout->impl->table_header)
- return;
- uiout->impl->table_header (uiout, width, align, col_name, col_hdr);
+ uiout->impl->table_header (width, align, col_name, col_hdr);
}

/* Clear the table associated with UIOUT. */
@@ -657,18 +653,14 @@ uo_begin (struct ui_out *uiout,
enum ui_out_type type,
const char *id)
{
- if (uiout->impl->begin == NULL)
- return;
- uiout->impl->begin (uiout, type, id);
+ uiout->impl->begin (type, id);
}

void
uo_end (struct ui_out *uiout,
enum ui_out_type type)
{
- if (uiout->impl->end == NULL)
- return;
- uiout->impl->end (uiout, type);
+ uiout->impl->end (type);
}

void
@@ -676,18 +668,14 @@ uo_field_int (struct ui_out *uiout, int fldno, int width, enum ui_align align,
const char *fldname,
int value)
{
- if (!uiout->impl->field_int)
- return;
- uiout->impl->field_int (uiout, fldno, width, align, fldname, value);
+ uiout->impl->field_int (fldno, width, align, fldname, value);
}

void
uo_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align align,
const char *fldname)
{
- if (!uiout->impl->field_skip)
- return;
- uiout->impl->field_skip (uiout, fldno, width, align, fldname);
+ uiout->impl->field_skip (fldno, width, align, fldname);
}

void
@@ -696,9 +684,7 @@ uo_field_string (struct ui_out *uiout, int fldno, int width,
const char *fldname,
const char *string)
{
- if (!uiout->impl->field_string)
- return;
- uiout->impl->field_string (uiout, fldno, width, align, fldname, string);
+ uiout->impl->field_string (fldno, width, align, fldname, string);
}

void
@@ -707,26 +693,20 @@ uo_field_fmt (struct ui_out *uiout, int fldno, int width, enum ui_align align,
const char *format,
va_list args)
{
- if (!uiout->impl->field_fmt)
- return;
- uiout->impl->field_fmt (uiout, fldno, width, align, fldname, format, args);
+ uiout->impl->field_fmt (fldno, width, align, fldname, format, args);
}

void
uo_spaces (struct ui_out *uiout, int numspaces)
{
- if (!uiout->impl->spaces)
- return;
- uiout->impl->spaces (uiout, numspaces);
+ uiout->impl->spaces (numspaces);
}

void
uo_text (struct ui_out *uiout,
const char *string)
{
- if (!uiout->impl->text)
- return;
- uiout->impl->text (uiout, string);
+ uiout->impl->text (string);
}

void
@@ -734,33 +714,25 @@ uo_message (struct ui_out *uiout,
const char *format,
va_list args)
{
- if (!uiout->impl->message)
- return;
- uiout->impl->message (uiout, format, args);
+ uiout->impl->message (format, args);
}

void
uo_wrap_hint (struct ui_out *uiout, const char *identstring)
{
- if (!uiout->impl->wrap_hint)
- return;
- uiout->impl->wrap_hint (uiout, identstring);
+ uiout->impl->wrap_hint (identstring);
}

void
uo_flush (struct ui_out *uiout)
{
- if (!uiout->impl->flush)
- return;
- uiout->impl->flush (uiout);
+ uiout->impl->flush ();
}

int
uo_redirect (struct ui_out *uiout, struct ui_file *outstream)
{
- if (!uiout->impl->redirect)
- return -1;
- return uiout->impl->redirect (uiout, outstream);
+ return uiout->impl->redirect (outstream);
}

/* local functions */
@@ -857,15 +829,6 @@ specified after table_body and inside a list."));
}
}

-
-/* Access to ui-out members data. */
-
-void *
-ui_out_data (struct ui_out *uiout)
-{
- return uiout->data;
-}
-
/* Access table field parameters. */
int
ui_out_query_field (struct ui_out *uiout, int colno,
@@ -896,13 +859,11 @@ ui_out_query_field (struct ui_out *uiout, int colno,
/* Initialize private members at startup. */

struct ui_out *
-ui_out_new (const struct ui_out_impl *impl, void *data,
- int flags)
+ui_out_new (ui_out_impl_base *impl, int flags)
{
struct ui_out *uiout = new ui_out ();

- uiout->data = data;
- uiout->impl = impl;
+ uiout->impl.reset (impl);
uiout->flags = flags;
uiout->table.flag = 0;
uiout->table.state = TABLE_STATE_HEADERS;
@@ -914,3 +875,9 @@ ui_out_new (const struct ui_out_impl *impl, void *data,

return uiout;
}
+
+ui_out_impl_base *
+ui_out_impl (ui_out *uiout)
+{
+ return uiout->impl.get ();
+}
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index 06c05e2..17c502e 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -140,91 +140,52 @@ extern int ui_out_query_field (struct ui_out *uiout, int colno,

extern int ui_out_is_mi_like_p (struct ui_out *uiout);

-/* From here on we have things that are only needed by implementation
- routines and main.c. We should pehaps have a separate file for that,
- like a ui-out-impl.h file. */
-
-/* User Interface Output Implementation Function Table */
-
-/* Type definition of all implementation functions. */
-
-typedef void (table_begin_ftype) (struct ui_out * uiout,
- int nbrofcols, int nr_rows,
- const char *tblid);
-typedef void (table_body_ftype) (struct ui_out * uiout);
-typedef void (table_end_ftype) (struct ui_out * uiout);
-typedef void (table_header_ftype) (struct ui_out * uiout, int width,
- enum ui_align align,
- const std::string &col_name,
- const std::string &col_hdr);
-
-typedef void (ui_out_begin_ftype) (struct ui_out *uiout,
- enum ui_out_type type,
- const char *id);
-typedef void (ui_out_end_ftype) (struct ui_out *uiout,
- enum ui_out_type type);
-typedef void (field_int_ftype) (struct ui_out * uiout, int fldno, int width,
- enum ui_align align,
- const char *fldname, int value);
-typedef void (field_skip_ftype) (struct ui_out * uiout, int fldno, int width,
- enum ui_align align,
- const char *fldname);
-typedef void (field_string_ftype) (struct ui_out * uiout, int fldno, int width,
- enum ui_align align,
- const char *fldname,
- const char *string);
-typedef void (field_fmt_ftype) (struct ui_out * uiout, int fldno, int width,
- enum ui_align align,
- const char *fldname,
- const char *format,
- va_list args) ATTRIBUTE_FPTR_PRINTF(6,0);
-typedef void (spaces_ftype) (struct ui_out * uiout, int numspaces);
-typedef void (text_ftype) (struct ui_out * uiout,
- const char *string);
-typedef void (message_ftype) (struct ui_out * uiout,
- const char *format, va_list args)
- ATTRIBUTE_FPTR_PRINTF(2,0);
-typedef void (wrap_hint_ftype) (struct ui_out * uiout, const char *identstring);
-typedef void (flush_ftype) (struct ui_out * uiout);
-typedef int (redirect_ftype) (struct ui_out * uiout,
- struct ui_file * outstream);
-typedef void (data_destroy_ftype) (struct ui_out *uiout);
-
-/* ui-out-impl */
-
-struct ui_out_impl
- {
- table_begin_ftype *table_begin;
- table_body_ftype *table_body;
- table_end_ftype *table_end;
- table_header_ftype *table_header;
- ui_out_begin_ftype *begin;
- ui_out_end_ftype *end;
- field_int_ftype *field_int;
- field_skip_ftype *field_skip;
- field_string_ftype *field_string;
- field_fmt_ftype *field_fmt;
- spaces_ftype *spaces;
- text_ftype *text;
- message_ftype *message;
- wrap_hint_ftype *wrap_hint;
- flush_ftype *flush;
- redirect_ftype *redirect;
- data_destroy_ftype *data_destroy;
- int is_mi_like_p;
- };
-
-extern void *ui_out_data (struct ui_out *uiout);
-
-extern void uo_field_string (struct ui_out *uiout, int fldno, int width,
- enum ui_align align, const char *fldname,
- const char *string);
+/* Base of all ui-out implementations. */
+
+class ui_out_impl_base
+{
+ public:
+
+ virtual ~ui_out_impl_base () {}
+
+ virtual void table_begin (int nbrofcols, int nr_rows, const char *tblid) = 0;
+ virtual void table_body () = 0;
+ virtual void table_end () = 0;
+ virtual void table_header (int width, ui_align align,
+ const std::string &col_name,
+ const std::string &col_hdr) = 0;
+
+ virtual void begin (ui_out_type type, const char *id) = 0;
+ virtual void end (ui_out_type type) = 0;
+ virtual void field_int (int fldno, int width, ui_align align,
+ const char *fldname, int value) = 0;
+ virtual void field_skip (int fldno, int width, ui_align align,
+ const char *fldname) = 0;
+ virtual void field_string (int fldno, int width, ui_align align,
+ const char *fldname, const char *string) = 0;
+ virtual void ATTRIBUTE_PRINTF(6,0)
+ field_fmt (int fldno, int width, ui_align align, const char *fldname,
+ const char *format, va_list args) = 0;
+ virtual void spaces (int numspaces) = 0;
+ virtual void text (const char *string) = 0;
+ virtual void ATTRIBUTE_PRINTF(2,0)
+ message (const char *format, va_list args) = 0;
+ virtual void wrap_hint (const char *identstring) = 0;
+ virtual void flush () = 0;
+ virtual int redirect (struct ui_file * outstream) = 0;
+
+ /* Set as not MI-like by default. It is overridden in subclasses if
+ necessary. */
+
+ virtual int is_mi_like_p ()
+ { return 0; }
+};
+
+ui_out_impl_base *ui_out_impl (ui_out *uiout);

/* Create a ui_out object */

-extern struct ui_out *ui_out_new (const struct ui_out_impl *impl,
- void *data,
- int flags);
+extern ui_out *ui_out_new (ui_out_impl_base *impl, int flags = 0);

/* Redirect the ouptut of a ui_out object temporarily. */

--
2.8.1