/* MI Command Set - file commands.
   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-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 "gdbsupport/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",
		       st.symtab->compunit ()->macro_table () != 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);
    }
}
