/* MI Command Set - file commands.
   Copyright (C) 2000-2021 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-cmds.h"
#include "mi-getopt.h"
#include "mi-interp.h"
#include "ui-out.h"
#include "symtab.h"
#include "source.h"
#include "objfiles.h"
#include "psymtab.h"
#include "solib.h"
#include "solist.h"
#include "gdb_regex.h"

/* Return to the client the absolute path and line number of the 
   current file being executed.  */

void
mi_cmd_file_list_exec_source_file (const char *command, char **argv, int argc)
{
  struct symtab_and_line st;
  struct ui_out *uiout = current_uiout;
  
  if (!mi_valid_noargs ("-file-list-exec-source-file", argc, argv))
    error (_("-file-list-exec-source-file: Usage: No args"));

  /* Set the default file and line, also get them.  */
  set_default_source_symtab_and_line ();
  st = get_current_source_symtab_and_line ();

  /* We should always get a symtab.  Apparently, filename does not
     need to be tested for NULL.  The documentation in symtab.h
     suggests it will always be correct.  */
  if (!st.symtab)
    error (_("-file-list-exec-source-file: No symtab"));

  /* Print to the user the line, filename and fullname.  */
  uiout->field_signed ("line", st.line);
  uiout->field_string ("file", symtab_to_filename_for_display (st.symtab));

  uiout->field_string ("fullname", symtab_to_fullname (st.symtab));

  uiout->field_signed ("macro-info",
		       COMPUNIT_MACRO_TABLE (SYMTAB_COMPUNIT (st.symtab)) != NULL);
}

/* Implement -file-list-exec-source-files command.  */

void
mi_cmd_file_list_exec_source_files (const char *command, char **argv, int argc)
{
  enum opt
    {
      GROUP_BY_OBJFILE_OPT,
      MATCH_BASENAME_OPT,
      MATCH_DIRNAME_OPT
    };
  static const struct mi_opt opts[] =
  {
    {"-group-by-objfile", GROUP_BY_OBJFILE_OPT, 0},
    {"-basename", MATCH_BASENAME_OPT, 0},
    {"-dirname", MATCH_DIRNAME_OPT, 0},
    { 0, 0, 0 }
  };

  /* Parse arguments.  */
  int oind = 0;
  char *oarg;

  bool group_by_objfile = false;
  bool match_on_basename = false;
  bool match_on_dirname = false;

  while (1)
    {
      int opt = mi_getopt ("-file-list-exec-source-files", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case GROUP_BY_OBJFILE_OPT:
	  group_by_objfile = true;
	  break;
	case MATCH_BASENAME_OPT:
	  match_on_basename = true;
	  break;
	case MATCH_DIRNAME_OPT:
	  match_on_dirname = true;
	  break;
	}
    }

  if ((argc - oind > 1) || (match_on_basename && match_on_dirname))
    error (_("-file-list-exec-source-files: Usage: [--group-by-objfile] [--basename | --dirname] [--] REGEXP"));

  const char *regexp = nullptr;
  if (argc - oind == 1)
    regexp = argv[oind];

  info_sources_filter::match_on match_type;
  if (match_on_dirname)
    match_type = info_sources_filter::match_on::DIRNAME;
  else if (match_on_basename)
    match_type = info_sources_filter::match_on::BASENAME;
  else
    match_type = info_sources_filter::match_on::FULLNAME;

  info_sources_filter filter (match_type, regexp);
  info_sources_worker (current_uiout, group_by_objfile, filter);
}

/* See mi-cmds.h.  */

void
mi_cmd_file_list_shared_libraries (const char *command, char **argv, int argc)
{
  struct ui_out *uiout = current_uiout;
  const char *pattern;

  switch (argc)
    {
    case 0:
      pattern = NULL;
      break;
    case 1:
      pattern = argv[0];
      break;
    default:
      error (_("Usage: -file-list-shared-libraries [REGEXP]"));
    }

  if (pattern != NULL)
    {
      const char *re_err = re_comp (pattern);

      if (re_err != NULL)
	error (_("Invalid regexp: %s"), re_err);
    }

  update_solib_list (1);

  /* Print the table header.  */
  ui_out_emit_list list_emitter (uiout, "shared-libraries");

  for (struct so_list *so : current_program_space->solibs ())
    {
      if (so->so_name[0] == '\0')
	continue;
      if (pattern != NULL && !re_exec (so->so_name))
	continue;

      ui_out_emit_tuple tuple_emitter (uiout, NULL);
      mi_output_solib_attribs (uiout, so);
    }
}
