/* Copyright (C) 2023-2026 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 "ui.h"

#include "cli/cli-cmds.h"
#include "event-top.h"
#include "gdbsupport/buildargv.h"
#include "gdbsupport/filestuff.h"
#include "gdbsupport/gdb_file.h"
#include "gdbsupport/scoped_fd.h"
#include "interps.h"
#include "pager.h"
#include "main.h"
#include "top.h"
#include "logging-file.h"

/* See top.h.  */

struct ui *main_ui;
struct ui *current_ui;
struct ui *ui_list;

/* The highest UI number ever assigned.  */

static int highest_ui_num;

/* See top.h.  */

ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
  : num (++highest_ui_num),
    stdin_stream (instream_),
    instream (instream_),
    outstream (outstream_),
    errstream (errstream_),
    input_fd (fileno (instream)),
    m_input_interactive_p (ISATTY (instream)),
    m_ui_stdout (new pager_file
		 (std::make_unique<logging_file<ui_file_up>>
		  (std::make_unique<stdio_file> (outstream)))),
    m_gdb_stdin (new stdio_file (instream)),
    m_ui_stderr (new logging_file<ui_file_up>
		 (std::make_unique<stderr_file> (errstream))),
    m_ui_stdlog (new timestamped_file
		 (std::make_unique<logging_file<ui_file_up>>
		  (std::make_unique<stderr_file> (errstream), true))),
    m_ui_stdtarg (m_ui_stderr)
{
  unbuffer_stream (instream_);

  if (ui_list == NULL)
    ui_list = this;
  else
    {
      struct ui *last;

      for (last = ui_list; last->next != NULL; last = last->next)
	;
      last->next = this;
    }
}

ui::~ui ()
{
  struct ui *ui, *uiprev;

  uiprev = NULL;

  for (ui = ui_list; ui != NULL; uiprev = ui, ui = ui->next)
    if (ui == this)
      break;

  gdb_assert (ui != NULL);

  if (uiprev != NULL)
    uiprev->next = next;
  else
    ui_list = next;

  delete m_gdb_stdin;
  delete m_ui_stdout;
  delete m_ui_stderr;
}


/* Returns whether GDB is running on an interactive terminal.  */

bool
ui::input_interactive_p () const
{
  if (batch_flag)
    return false;

  if (interactive_mode != AUTO_BOOLEAN_AUTO)
    return interactive_mode == AUTO_BOOLEAN_TRUE;

  return m_input_interactive_p;
}


/* When there is an event ready on the stdin file descriptor, instead
   of calling readline directly through the callback function, or
   instead of calling gdb_readline_no_editing_callback, give gdb a
   chance to detect errors and do something.  */

static void
stdin_event_handler (int error, gdb_client_data client_data)
{
  struct ui *ui = (struct ui *) client_data;

  if (error)
    {
      /* Switch to the main UI, so diagnostics always go there.  */
      current_ui = main_ui;

      ui->unregister_file_handler ();
      if (main_ui == ui)
	{
	  /* If stdin died, we may as well kill gdb.  */
	  gdb_printf (gdb_stderr, _("error detected on stdin\n"));
	  quit_command ((char *) 0, 0);
	}
      else
	{
	  /* Simply delete the UI.  */
	  delete ui;
	}
    }
  else
    {
      /* Switch to the UI whose input descriptor woke up the event
	 loop.  */
      current_ui = ui;

      /* This makes sure a ^C immediately followed by further input is
	 always processed in that order.  E.g,. with input like
	 "^Cprint 1\n", the SIGINT handler runs, marks the async
	 signal handler, and then select/poll may return with stdin
	 ready, instead of -1/EINTR.  The
	 gdb.base/double-prompt-target-event-error.exp test exercises
	 this.  */
      QUIT;

      do
	{
	  call_stdin_event_handler_again_p = 0;
	  ui->call_readline (client_data);
	}
      while (call_stdin_event_handler_again_p != 0);
    }
}

/* See top.h.  */

void
ui::register_file_handler ()
{
  if (input_fd != -1)
    add_file_handler (input_fd, stdin_event_handler, this,
		      string_printf ("ui-%d", num), true);
}

/* See top.h.  */

void
ui::unregister_file_handler ()
{
  if (input_fd != -1)
    delete_file_handler (input_fd);
}

/* Open file named NAME for read/write, making sure not to make it the
   controlling terminal.  */

static gdb_file_up
open_terminal_stream (const char *name)
{
  scoped_fd fd = gdb_open_cloexec (name, O_RDWR | O_NOCTTY, 0);
  if (fd.get () < 0)
    perror_with_name  (_("opening terminal failed"));

  return fd.to_file ("w+");
}

/* Implementation of the "new-ui" command.  */

static void
new_ui_command (const char *args, int from_tty)
{
  int argc;
  const char *interpreter_name;
  const char *tty_name;

  dont_repeat ();

  gdb_argv argv (args);
  argc = argv.count ();

  if (argc < 2)
    error (_("Usage: new-ui INTERPRETER TTY"));

  interpreter_name = argv[0];
  tty_name = argv[1];

  {
    scoped_restore save_ui = make_scoped_restore (&current_ui);

    /* Open specified terminal.  Note: we used to open it three times,
       once for each of stdin/stdout/stderr, but that does not work
       with Windows named pipes.  */
    gdb_file_up stream = open_terminal_stream (tty_name);

    std::unique_ptr<ui> ui
      (new struct ui (stream.get (), stream.get (), stream.get ()));

    ui->async = 1;

    current_ui = ui.get ();

    set_top_level_interpreter (interpreter_name, true);

    top_level_interpreter ()->pre_command_loop ();

    /* Make sure the file is not closed.  */
    stream.release ();

    ui.release ();
  }

  gdb_printf ("New UI allocated\n");
}

INIT_GDB_FILE (ui)
{
  cmd_list_element *c = add_cmd ("new-ui", class_support, new_ui_command, _("\
Create a new UI.\n\
Usage: new-ui INTERPRETER TTY\n\
The first argument is the name of the interpreter to run.\n\
The second argument is the terminal the UI runs on."), &cmdlist);
  set_cmd_completer (c, interpreter_completer);
}
