/* Routines for handling XML generic OS data provided by target.

   Copyright (C) 2008-2020 Free Software Foundation, Inc.

   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 "target.h"
#include "xml-support.h"
#include "osdata.h"
#include "ui-out.h"
#include "gdbcmd.h"

#if !defined(HAVE_LIBEXPAT)

std::unique_ptr<osdata>
osdata_parse (const char *xml)
{
  static int have_warned;

  if (!have_warned)
    {
      have_warned = 1;
      warning (_("Can not parse XML OS data; XML support was disabled "
                "at compile time"));
    }

  return NULL;
}

#else /* HAVE_LIBEXPAT */

/* Internal parsing data passed to all XML callbacks.  */
struct osdata_parsing_data
{
  std::unique_ptr<struct osdata> osdata;
  std::string property_name;
};

/* Handle the start of a <osdata> element.  */

static void
osdata_start_osdata (struct gdb_xml_parser *parser,
                        const struct gdb_xml_element *element,
                        void *user_data,
			std::vector<gdb_xml_value> &attributes)
{
  struct osdata_parsing_data *data = (struct osdata_parsing_data *) user_data;

  if (data->osdata != NULL)
    gdb_xml_error (parser, _("Seen more than on osdata element"));

  char *type = (char *) xml_find_attribute (attributes, "type")->value.get ();
  data->osdata.reset (new struct osdata (std::string (type)));
}

/* Handle the start of a <item> element.  */

static void
osdata_start_item (struct gdb_xml_parser *parser,
                  const struct gdb_xml_element *element,
                  void *user_data,
		  std::vector<gdb_xml_value> &attributes)
{
  struct osdata_parsing_data *data = (struct osdata_parsing_data *) user_data;
  data->osdata->items.emplace_back ();
}

/* Handle the start of a <column> element.  */

static void
osdata_start_column (struct gdb_xml_parser *parser,
                    const struct gdb_xml_element *element,
                    void *user_data,
		    std::vector<gdb_xml_value> &attributes)
{
  struct osdata_parsing_data *data = (struct osdata_parsing_data *) user_data;
  const char *name
    = (const char *) xml_find_attribute (attributes, "name")->value.get ();

  data->property_name.assign (name);
}

/* Handle the end of a <column> element.  */

static void
osdata_end_column (struct gdb_xml_parser *parser,
                  const struct gdb_xml_element *element,
                  void *user_data, const char *body_text)
{
  osdata_parsing_data *data = (struct osdata_parsing_data *) user_data;
  struct osdata *osdata = data->osdata.get ();
  osdata_item &item = osdata->items.back ();

  item.columns.emplace_back (std::move (data->property_name),
			     std::string (body_text));
}

/* The allowed elements and attributes for OS data object.
   The root element is a <osdata>.  */

const struct gdb_xml_attribute column_attributes[] = {
  { "name", GDB_XML_AF_NONE, NULL, NULL },
  { NULL, GDB_XML_AF_NONE, NULL, NULL }
};

const struct gdb_xml_element item_children[] = {
  { "column", column_attributes, NULL,
    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
    osdata_start_column, osdata_end_column },
  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};

const struct gdb_xml_attribute osdata_attributes[] = {
  { "type", GDB_XML_AF_NONE, NULL, NULL },
  { NULL, GDB_XML_AF_NONE, NULL, NULL }
};

const struct gdb_xml_element osdata_children[] = {
  { "item", NULL, item_children,
    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
    osdata_start_item, NULL },
  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};

const struct gdb_xml_element osdata_elements[] = {
  { "osdata", osdata_attributes, osdata_children,
    GDB_XML_EF_NONE, osdata_start_osdata, NULL },
  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};

std::unique_ptr<osdata>
osdata_parse (const char *xml)
{
  osdata_parsing_data data;

  if (gdb_xml_parse_quick (_("osdata"), "osdata.dtd",
			   osdata_elements, xml, &data) == 0)
    {
      /* Parsed successfully, don't need to delete the result.  */
      return std::move (data.osdata);
    }

  return NULL;
}
#endif

std::unique_ptr<osdata>
get_osdata (const char *type)
{
  std::unique_ptr<osdata> osdata;
  gdb::optional<gdb::char_vector> xml = target_get_osdata (type);

  if (xml)
    {
      if ((*xml)[0] == '\0')
	{
	  if (type)
	    warning (_("Empty data returned by target.  Wrong osdata type?"));
	  else
	    warning (_("Empty type list returned by target.  No type data?"));
	}
      else
	osdata = osdata_parse (xml->data ());
    }

  if (osdata == NULL)
    error (_("Can not fetch data now."));

  return osdata;
}

const std::string *
get_osdata_column (const osdata_item &item, const char *name)
{
  for (const osdata_column &col : item.columns)
    if (col.name == name)
      return &col.value;

  return NULL;
}

void
info_osdata (const char *type)
{
  struct ui_out *uiout = current_uiout;
  struct osdata_item *last = NULL;
  int ncols = 0;
  int col_to_skip = -1;

  if (type == NULL)
    type = "";

  std::unique_ptr<osdata> osdata = get_osdata (type);

  int nrows = osdata->items.size ();

  if (*type == '\0' && nrows == 0)
    error (_("Available types of OS data not reported."));
  
  if (!osdata->items.empty ())
    {
      last = &osdata->items.back ();
      ncols = last->columns.size ();

      /* As a special case, scan the listing of available data types
	 for a column named "Title", and only include it with MI
	 output; this column's normal use is for titles for interface
	 elements like menus, and it clutters up CLI output.  */
      if (*type == '\0' && !uiout->is_mi_like_p ())
	{
	  for (int ix = 0; ix < last->columns.size (); ix++)
	    {
	      if (last->columns[ix].name == "Title")
		col_to_skip = ix;
	    }
	  /* Be sure to reduce the total column count, otherwise
	     internal errors ensue.  */
	  if (col_to_skip >= 0)
	    --ncols;
	}
    }

  ui_out_emit_table table_emitter (uiout, ncols, nrows, "OSDataTable");

  /* With no columns/items, we just output an empty table, but we
     still output the table.  This matters for MI.  */
  if (ncols == 0)
    return;

  if (last != NULL && !last->columns.empty ())
    {
      for (int ix = 0; ix < last->columns.size (); ix++)
	{
	  char col_name[32];

	  if (ix == col_to_skip)
	    continue;

	  snprintf (col_name, 32, "col%d", ix);
	  uiout->table_header (10, ui_left,
			       col_name, last->columns[ix].name.c_str ());
        }
    }

  uiout->table_body ();

  if (nrows != 0)
    {
      for (const osdata_item &item : osdata->items)
       {
	 {
	   ui_out_emit_tuple tuple_emitter (uiout, "item");

	   for (int ix_cols = 0; ix_cols < item.columns.size (); ix_cols++)
	     {
	       char col_name[32];

	       if (ix_cols == col_to_skip)
		 continue;

	       snprintf (col_name, 32, "col%d", ix_cols);
	       uiout->field_string (col_name,
				    item.columns[ix_cols].value.c_str ());
	     }
	 }

         uiout->text ("\n");
       }
    }
}

static void
info_osdata_command (const char *arg, int from_tty)
{
  info_osdata (arg);
}

void
_initialize_osdata (void)
{
  add_info ("os", info_osdata_command,
           _("Show OS data ARG."));
}
