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

   Copyright (C) 2008-2019 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 "gdbsupport/vec.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."));
}
