This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 19/22] Class-ify ui_out_impl


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.
	<data>: 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]