/* MI Command Set - output generating routines.

   Copyright (C) 2000-2022 Free Software Foundation, Inc.

   Contributed by Cygnus Solutions (a Red Hat company).

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "mi-out.h"

#include <vector>

#include "interps.h"
#include "ui-out.h"
#include "utils.h"

/* Mark beginning of a table.  */

void
mi_ui_out::do_table_begin (int nr_cols, int nr_rows,
			   const char *tblid)
{
  open (tblid, ui_out_type_tuple);
  do_field_signed (-1, -1, ui_left, "nr_rows", nr_rows);
  do_field_signed (-1, -1, ui_left, "nr_cols", nr_cols);
  open ("hdr", ui_out_type_list);
}

/* Mark beginning of a table body.  */

void
mi_ui_out::do_table_body ()
{
  /* close the table header line if there were any headers */
  close (ui_out_type_list);
  open ("body", ui_out_type_list);
}

/* Mark end of a table.  */

void
mi_ui_out::do_table_end ()
{
  close (ui_out_type_list); /* body */
  close (ui_out_type_tuple);
}

/* Specify table header.  */

void
mi_ui_out::do_table_header (int width, ui_align alignment,
			    const std::string &col_name,
			    const std::string &col_hdr)
{
  open (NULL, ui_out_type_tuple);
  do_field_signed (0, 0, ui_center, "width", width);
  do_field_signed (0, 0, ui_center, "alignment", alignment);
  do_field_string (0, 0, ui_center, "col_name", col_name.c_str (),
		   ui_file_style ());
  do_field_string (0, width, alignment, "colhdr", col_hdr.c_str (),
		   ui_file_style ());
  close (ui_out_type_tuple);
}

/* Mark beginning of a list.  */

void
mi_ui_out::do_begin (ui_out_type type, const char *id)
{
  open (id, type);
}

/* Mark end of a list.  */

void
mi_ui_out::do_end (ui_out_type type)
{
  close (type);
}

/* Output an int field.  */

void
mi_ui_out::do_field_signed (int fldno, int width, ui_align alignment,
			    const char *fldname, LONGEST value)
{
  do_field_string (fldno, width, alignment, fldname, plongest (value),
		   ui_file_style ());
}

/* Output an unsigned field.  */

void
mi_ui_out::do_field_unsigned (int fldno, int width, ui_align alignment,
			      const char *fldname, ULONGEST value)
{
  do_field_string (fldno, width, alignment, fldname, pulongest (value),
		   ui_file_style ());
}

/* Used to omit a field.  */

void
mi_ui_out::do_field_skip (int fldno, int width, ui_align alignment,
			  const char *fldname)
{
}

/* Other specific mi_field_* end up here so alignment and field
   separators are both handled by mi_field_string. */

void
mi_ui_out::do_field_string (int fldno, int width, ui_align align,
			    const char *fldname, const char *string,
			    const ui_file_style &style)
{
  ui_file *stream = m_streams.back ();
  field_separator ();

  if (fldname)
    gdb_printf (stream, "%s=", fldname);
  gdb_printf (stream, "\"");
  if (string)
    stream->putstr (string, '"');
  gdb_printf (stream, "\"");
}

void
mi_ui_out::do_field_fmt (int fldno, int width, ui_align align,
			 const char *fldname, const ui_file_style &style,
			 const char *format, va_list args)
{
  ui_file *stream = m_streams.back ();
  field_separator ();

  if (fldname)
    gdb_printf (stream, "%s=\"", fldname);
  else
    gdb_puts ("\"", stream);
  gdb_vprintf (stream, format, args);
  gdb_puts ("\"", stream);
}

void
mi_ui_out::do_spaces (int numspaces)
{
}

void
mi_ui_out::do_text (const char *string)
{
}

void
mi_ui_out::do_message (const ui_file_style &style,
		       const char *format, va_list args)
{
}

void
mi_ui_out::do_wrap_hint (int indent)
{
  m_streams.back ()->wrap_here (indent);
}

void
mi_ui_out::do_flush ()
{

  gdb_flush (m_streams.back ());
}

void
mi_ui_out::do_redirect (ui_file *outstream)
{
  if (outstream != NULL)
    m_streams.push_back (outstream);
  else
    m_streams.pop_back ();
}

void
mi_ui_out::field_separator ()
{
  if (m_suppress_field_separator)
    m_suppress_field_separator = false;
  else
    gdb_putc (',', m_streams.back ());
}

void
mi_ui_out::open (const char *name, ui_out_type type)
{
  ui_file *stream = m_streams.back ();

  field_separator ();
  m_suppress_field_separator = true;

  if (name)
    gdb_printf (stream, "%s=", name);

  switch (type)
    {
    case ui_out_type_tuple:
      gdb_putc ('{', stream);
      break;

    case ui_out_type_list:
      gdb_putc ('[', stream);
      break;

    default:
      internal_error (__FILE__, __LINE__, _("bad switch"));
    }
}

void
mi_ui_out::close (ui_out_type type)
{
  ui_file *stream = m_streams.back ();

  switch (type)
    {
    case ui_out_type_tuple:
      gdb_putc ('}', stream);
      break;

    case ui_out_type_list:
      gdb_putc (']', stream);
      break;

    default:
      internal_error (__FILE__, __LINE__, _("bad switch"));
    }

  m_suppress_field_separator = false;
}

string_file *
mi_ui_out::main_stream ()
{
  gdb_assert (m_streams.size () == 1);

  return (string_file *) m_streams.back ();
}

/* Clear the buffer.  */

void
mi_ui_out::rewind ()
{
  main_stream ()->clear ();
}

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

void
mi_ui_out::put (ui_file *where)
{
  string_file *mi_stream = main_stream ();

  where->write (mi_stream->data (), mi_stream->size ());
  mi_stream->clear ();
}

/* Return the current MI version.  */

int
mi_ui_out::version ()
{
  return m_mi_version;
}

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

mi_ui_out::mi_ui_out (int mi_version)
: ui_out (mi_version >= 3
	  ? fix_multi_location_breakpoint_output : (ui_out_flag) 0),
  m_suppress_field_separator (false),
  m_suppress_output (false),
  m_mi_version (mi_version)
{
  string_file *stream = new string_file ();
  m_streams.push_back (stream);
}

mi_ui_out::~mi_ui_out ()
{
}

/* See mi/mi-out.h.  */

mi_ui_out *
mi_out_new (const char *mi_version)
{
  if (streq (mi_version, INTERP_MI3) ||  streq (mi_version, INTERP_MI))
    return new mi_ui_out (3);

  if (streq (mi_version, INTERP_MI2))
    return new mi_ui_out (2);

  if (streq (mi_version, INTERP_MI1))
    return new mi_ui_out (1);

  return nullptr;
}

/* Helper function to return the given UIOUT as an mi_ui_out.  It is an error
   to call this function with an ui_out that is not an MI.  */

static mi_ui_out *
as_mi_ui_out (ui_out *uiout)
{
  mi_ui_out *mi_uiout = dynamic_cast<mi_ui_out *> (uiout);

  gdb_assert (mi_uiout != NULL);

  return mi_uiout;
}

int
mi_version (ui_out *uiout)
{
  return as_mi_ui_out (uiout)->version ();
}

void
mi_out_put (ui_out *uiout, struct ui_file *stream)
{
  return as_mi_ui_out (uiout)->put (stream);
}

void
mi_out_rewind (ui_out *uiout)
{
  return as_mi_ui_out (uiout)->rewind ();
}
