/* GDB/Scheme exception support.

   Copyright (C) 2014-2025 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/>.  */

/* See README file in this directory for implementation notes, coding
   conventions, et.al.  */

/* Notes:

   IWBN to support SRFI 34/35.  At the moment we follow Guile's own
   exception mechanism.

   The non-static functions in this file have prefix gdbscm_ and
   not exscm_ on purpose.  */

#include <signal.h>
#include "guile-internal.h"

/* The <gdb:exception> smob.
   This is used to record and handle Scheme exceptions.
   One important invariant is that <gdb:exception> smobs are never a valid
   result of a function, other than to signify an exception occurred.  */

struct exception_smob
{
  /* This always appears first.  */
  gdb_smob base;

  /* The key and args parameters to "throw".  */
  SCM key;
  SCM args;
};

static const char exception_smob_name[] = "gdb:exception";

/* The tag Guile knows the exception smob by.  */
static scm_t_bits exception_smob_tag;

/* A generic error in struct gdb_exception.
   I.e., not RETURN_QUIT and not MEMORY_ERROR.  */
static SCM error_symbol;

/* An error occurred accessing inferior memory.
   This is not a Scheme programming error.  */
static SCM memory_error_symbol;

/* User interrupt, e.g., RETURN_QUIT in struct gdb_exception.  */
static SCM signal_symbol;

/* A user error, e.g., bad arg to gdb command.  */
static SCM user_error_symbol;

/* Printing the stack is done by first capturing the stack and recording it in
   a <gdb:exception> object with this key and with the ARGS field set to
   (cons real-key (cons stack real-args)).
   See gdbscm_make_exception_with_stack.  */
static SCM with_stack_error_symbol;

/* The key to use for an invalid object exception.  An invalid object is one
   where the underlying object has been removed from GDB.  */
SCM gdbscm_invalid_object_error_symbol;

/* Values for "guile print-stack" as symbols.  */
static SCM none_symbol;
static SCM message_symbol;
static SCM full_symbol;

static const char percent_print_exception_message_name[] =
  "%print-exception-message";

/* Variable containing %print-exception-message.
   It is not defined until late in initialization, after our init routine
   has run.  Cope by looking it up lazily.  */
static SCM percent_print_exception_message_var = SCM_BOOL_F;

static const char percent_print_exception_with_stack_name[] =
  "%print-exception-with-stack";

/* Variable containing %print-exception-with-stack.
   It is not defined until late in initialization, after our init routine
   has run.  Cope by looking it up lazily.  */
static SCM percent_print_exception_with_stack_var = SCM_BOOL_F;

/* Counter to keep track of the number of times we create a <gdb:exception>
   object, for performance monitoring purposes.  */
static unsigned long gdbscm_exception_count = 0;

/* Administrivia for exception smobs.  */

/* The smob "print" function for <gdb:exception>.  */

static int
exscm_print_exception_smob (SCM self, SCM port, scm_print_state *pstate)
{
  exception_smob *e_smob = (exception_smob *) SCM_SMOB_DATA (self);

  gdbscm_printf (port, "#<%s ", exception_smob_name);
  scm_write (e_smob->key, port);
  scm_puts (" ", port);
  scm_write (e_smob->args, port);
  scm_puts (">", port);

  scm_remember_upto_here_1 (self);

  /* Non-zero means success.  */
  return 1;
}

/* (make-exception key args) -> <gdb:exception> */

SCM
gdbscm_make_exception (SCM key, SCM args)
{
  exception_smob *e_smob = (exception_smob *)
    scm_gc_malloc (sizeof (exception_smob), exception_smob_name);
  SCM smob;

  e_smob->key = key;
  e_smob->args = args;
  smob = scm_new_smob (exception_smob_tag, (scm_t_bits) e_smob);
  gdbscm_init_gsmob (&e_smob->base);

  ++gdbscm_exception_count;

  return smob;
}

/* Return non-zero if SCM is a <gdb:exception> object.  */

int
gdbscm_is_exception (SCM scm)
{
  return SCM_SMOB_PREDICATE (exception_smob_tag, scm);
}

/* (exception? scm) -> boolean */

static SCM
gdbscm_exception_p (SCM scm)
{
  return scm_from_bool (gdbscm_is_exception (scm));
}

/* (exception-key <gdb:exception>) -> key */

SCM
gdbscm_exception_key (SCM self)
{
  exception_smob *e_smob;

  SCM_ASSERT_TYPE (gdbscm_is_exception (self), self, SCM_ARG1, FUNC_NAME,
		   "gdb:exception");

  e_smob = (exception_smob *) SCM_SMOB_DATA (self);
  return e_smob->key;
}

/* (exception-args <gdb:exception>) -> arg-list */

SCM
gdbscm_exception_args (SCM self)
{
  exception_smob *e_smob;

  SCM_ASSERT_TYPE (gdbscm_is_exception (self), self, SCM_ARG1, FUNC_NAME,
		   "gdb:exception");

  e_smob = (exception_smob *) SCM_SMOB_DATA (self);
  return e_smob->args;
}

/* Wrap an exception in a <gdb:exception> object that includes STACK.
   gdbscm_print_exception_with_stack knows how to unwrap it.  */

SCM
gdbscm_make_exception_with_stack (SCM key, SCM args, SCM stack)
{
  return gdbscm_make_exception (with_stack_error_symbol,
				scm_cons (key, scm_cons (stack, args)));
}

/* Version of scm_error_scm that creates a gdb:exception object that can later
   be passed to gdbscm_throw.
   KEY is a symbol denoting the kind of error.
   SUBR is either #f or a string marking the function in which the error
   occurred.
   MESSAGE is either #f or the error message string.  It may contain ~a and ~s
   modifiers, provided by ARGS.
   ARGS is a list of args to MESSAGE.
   DATA is an arbitrary object, its value depends on KEY.  The value to pass
   here is a bit underspecified by Guile.  */

SCM
gdbscm_make_error_scm (SCM key, SCM subr, SCM message, SCM args, SCM data)
{
  return gdbscm_make_exception (key, scm_list_4 (subr, message, args, data));
}

/* Version of scm_error that creates a gdb:exception object that can later
   be passed to gdbscm_throw.
   See gdbscm_make_error_scm for a description of the arguments.  */

SCM
gdbscm_make_error (SCM key, const char *subr, const char *message,
		   SCM args, SCM data)
{
  return gdbscm_make_error_scm
    (key,
     subr == NULL ? SCM_BOOL_F : scm_from_latin1_string (subr),
     message == NULL ? SCM_BOOL_F : scm_from_latin1_string (message),
     args, data);
}

/* Version of SCM_ASSERT_TYPE/scm_wrong_type_arg_msg that creates a
   gdb:exception object that can later be passed to gdbscm_throw.  */

SCM
gdbscm_make_type_error (const char *subr, int arg_pos, SCM bad_value,
			const char *expected_type)
{
  gdb::unique_xmalloc_ptr<char> msg;
  SCM result;

  if (arg_pos > 0)
    {
      if (expected_type != NULL)
	{
	  msg = xstrprintf (_("Wrong type argument in position %d"
			      " (expecting %s): ~S"),
			    arg_pos, expected_type);
	}
      else
	{
	  msg = xstrprintf (_("Wrong type argument in position %d: ~S"),
			    arg_pos);
	}
    }
  else
    {
      if (expected_type != NULL)
	{
	  msg = xstrprintf (_("Wrong type argument (expecting %s): ~S"),
			    expected_type);
	}
      else
	msg = xstrprintf (_("Wrong type argument: ~S"));
    }

  result = gdbscm_make_error (scm_arg_type_key, subr, msg.get (),
			      scm_list_1 (bad_value), scm_list_1 (bad_value));
  return result;
}

/* A variant of gdbscm_make_type_error for non-type argument errors.
   ERROR_PREFIX and ERROR are combined to build the error message.
   Care needs to be taken so that the i18n composed form is still
   reasonable, but no one is going to translate these anyway so we don't
   worry too much.
   ERROR_PREFIX may be NULL, ERROR may not be NULL.  */

static SCM
gdbscm_make_arg_error (SCM key, const char *subr, int arg_pos, SCM bad_value,
		       const char *error_prefix, const char *error)
{
  gdb::unique_xmalloc_ptr<char> msg;
  SCM result;

  if (error_prefix != NULL)
    {
      if (arg_pos > 0)
	{
	  msg = xstrprintf (_("%s %s in position %d: ~S"),
			    error_prefix, error, arg_pos);
	}
      else
	msg = xstrprintf (_("%s %s: ~S"), error_prefix, error);
    }
  else
    {
      if (arg_pos > 0)
	msg = xstrprintf (_("%s in position %d: ~S"), error, arg_pos);
      else
	msg = xstrprintf (_("%s: ~S"), error);
    }

  result = gdbscm_make_error (key, subr, msg.get (), scm_list_1 (bad_value),
			      scm_list_1 (bad_value));
  return result;
}

/* Make an invalid-object error <gdb:exception> object.
   OBJECT is the name of the kind of object that is invalid.  */

SCM
gdbscm_make_invalid_object_error (const char *subr, int arg_pos, SCM bad_value,
				  const char *object)
{
  return gdbscm_make_arg_error (gdbscm_invalid_object_error_symbol,
				subr, arg_pos, bad_value,
				_("Invalid object:"), object);
}

/* Throw an invalid-object error.
   OBJECT is the name of the kind of object that is invalid.  */

void
gdbscm_invalid_object_error (const char *subr, int arg_pos, SCM bad_value,
			     const char *object)
{
  SCM exception
    = gdbscm_make_invalid_object_error (subr, arg_pos, bad_value, object);

  gdbscm_throw (exception);
}

/* Make an out-of-range error <gdb:exception> object.  */

SCM
gdbscm_make_out_of_range_error (const char *subr, int arg_pos, SCM bad_value,
				const char *error)
{
  return gdbscm_make_arg_error (scm_out_of_range_key,
				subr, arg_pos, bad_value,
				_("Out of range:"), error);
}

/* Throw an out-of-range error.
   This is the standard Guile out-of-range exception.  */

void
gdbscm_out_of_range_error (const char *subr, int arg_pos, SCM bad_value,
			   const char *error)
{
  SCM exception
    = gdbscm_make_out_of_range_error (subr, arg_pos, bad_value, error);

  gdbscm_throw (exception);
}

/* Make a misc-error <gdb:exception> object.  */

SCM
gdbscm_make_misc_error (const char *subr, int arg_pos, SCM bad_value,
			const char *error)
{
  return gdbscm_make_arg_error (scm_misc_error_key,
				subr, arg_pos, bad_value, NULL, error);
}

/* Throw a misc-error error.  */

void
gdbscm_misc_error (const char *subr, int arg_pos, SCM bad_value,
		   const char *error)
{
  SCM exception = gdbscm_make_misc_error (subr, arg_pos, bad_value, error);

  gdbscm_throw (exception);
}

/* Return a <gdb:exception> object for gdb:memory-error.  */

SCM
gdbscm_make_memory_error (const char *subr, const char *msg, SCM args)
{
  return gdbscm_make_error (memory_error_symbol, subr, msg, args,
			    SCM_EOL);
}

/* Throw a gdb:memory-error exception.  */

void
gdbscm_memory_error (const char *subr, const char *msg, SCM args)
{
  SCM exception = gdbscm_make_memory_error (subr, msg, args);

  gdbscm_throw (exception);
}

/* Return non-zero if KEY is gdb:memory-error.
   Note: This is an excp_matcher_func function.  */

int
gdbscm_memory_error_p (SCM key)
{
  return scm_is_eq (key, memory_error_symbol);
}

/* Return non-zero if KEY is gdb:user-error.
   Note: This is an excp_matcher_func function.  */

int
gdbscm_user_error_p (SCM key)
{
  return scm_is_eq (key, user_error_symbol);
}

/* Wrapper around scm_throw to throw a gdb:exception.
   This function does not return.
   This function cannot be called from inside TRY_CATCH.  */

void
gdbscm_throw (SCM exception)
{
  scm_throw (gdbscm_exception_key (exception),
	     gdbscm_exception_args (exception));
  gdb_assert_not_reached ("scm_throw returned");
}

/* Convert a GDB exception to a <gdb:exception> object.  */

SCM
gdbscm_scm_from_gdb_exception (const gdbscm_gdb_exception &exception)
{
  SCM key;

  if (exception.reason == RETURN_QUIT)
    {
      /* Handle this specially to be consistent with top-repl.scm.  */
      return gdbscm_make_error (signal_symbol, NULL, _("User interrupt"),
				SCM_EOL, scm_list_1 (scm_from_int (SIGINT)));
    }

  if (exception.error == MEMORY_ERROR)
    key = memory_error_symbol;
  else
    key = error_symbol;

  return gdbscm_make_error (key, NULL, "~A",
			    scm_list_1 (gdbscm_scm_from_c_string
					(exception.message)),
			    SCM_BOOL_F);
}

/* Convert a GDB exception to the appropriate Scheme exception and throw it.
   This function does not return.  */

void
gdbscm_throw_gdb_exception (gdbscm_gdb_exception exception)
{
  SCM scm_exception = gdbscm_scm_from_gdb_exception (exception);
  xfree (exception.message);
  gdbscm_throw (scm_exception);
}

/* Print the error message portion of an exception.
   If PORT is #f, use the standard error port.
   KEY cannot be gdb:with-stack.

   Basically this function is just a wrapper around calling
   %print-exception-message.  */

static void
gdbscm_print_exception_message (SCM port, SCM frame, SCM key, SCM args)
{
  SCM printer, status;

  if (gdbscm_is_false (port))
    port = scm_current_error_port ();

  gdb_assert (!scm_is_eq (key, with_stack_error_symbol));

  /* This does not use scm_print_exception because we tweak the output a bit.
     Compare Guile's print-exception with our %print-exception-message for
     details.  */
  if (gdbscm_is_false (percent_print_exception_message_var))
    {
      percent_print_exception_message_var
	= scm_c_private_variable (gdbscm_init_module_name,
				  percent_print_exception_message_name);
      /* If we can't find %print-exception-message, there's a problem on the
	 Scheme side.  Don't kill GDB, just flag an error and leave it at
	 that.  */
      if (gdbscm_is_false (percent_print_exception_message_var))
	{
	  gdbscm_printf (port, _("Error in Scheme exception printing,"
				 " can't find %s.\n"),
			 percent_print_exception_message_name);
	  return;
	}
    }
  printer = scm_variable_ref (percent_print_exception_message_var);

  status = gdbscm_safe_call_4 (printer, port, frame, key, args, NULL);

  /* If that failed still tell the user something.
     But don't use the exception printing machinery!  */
  if (gdbscm_is_exception (status))
    {
      gdbscm_printf (port, _("Error in Scheme exception printing:\n"));
      scm_display (status, port);
      scm_newline (port);
    }
}

/* Print the description of exception KEY, ARGS to PORT, according to the
   setting of "set guile print-stack".
   If PORT is #f, use the standard error port.
   If STACK is #f, never print the stack, regardless of whether printing it
   is enabled.  If STACK is #t, then print it if it is contained in ARGS
   (i.e., KEY is gdb:with-stack).  Otherwise STACK is the result of calling
   scm_make_stack (which will be ignored in favor of the stack in ARGS if
   KEY is gdb:with-stack).
   KEY, ARGS are the standard arguments to scm_throw, et.al.

   Basically this function is just a wrapper around calling
   %print-exception-with-stack.  */

void
gdbscm_print_exception_with_stack (SCM port, SCM stack, SCM key, SCM args)
{
  SCM printer, status;

  if (gdbscm_is_false (port))
    port = scm_current_error_port ();

  if (gdbscm_is_false (percent_print_exception_with_stack_var))
    {
      percent_print_exception_with_stack_var
	= scm_c_private_variable (gdbscm_init_module_name,
				  percent_print_exception_with_stack_name);
      /* If we can't find %print-exception-with-stack, there's a problem on the
	 Scheme side.  Don't kill GDB, just flag an error and leave it at
	 that.  */
      if (gdbscm_is_false (percent_print_exception_with_stack_var))
	{
	  gdbscm_printf (port, _("Error in Scheme exception printing,"
				 " can't find %s.\n"),
			 percent_print_exception_with_stack_name);
	  return;
	}
    }
  printer = scm_variable_ref (percent_print_exception_with_stack_var);

  status = gdbscm_safe_call_4 (printer, port, stack, key, args, NULL);

  /* If that failed still tell the user something.
     But don't use the exception printing machinery!  */
  if (gdbscm_is_exception (status))
    {
      gdbscm_printf (port, _("Error in Scheme exception printing:\n"));
      scm_display (status, port);
      scm_newline (port);
    }
}

/* Print EXCEPTION, a <gdb:exception> object, to PORT.
   If PORT is #f, use the standard error port.  */

void
gdbscm_print_gdb_exception (SCM port, SCM exception)
{
  gdb_assert (gdbscm_is_exception (exception));

  gdbscm_print_exception_with_stack (port, SCM_BOOL_T,
				     gdbscm_exception_key (exception),
				     gdbscm_exception_args (exception));
}

/* Return a string description of <gdb:exception> EXCEPTION.
   If EXCEPTION is a gdb:with-stack exception, unwrap it, a backtrace
   is never returned as part of the result.  */

gdb::unique_xmalloc_ptr<char>
gdbscm_exception_message_to_string (SCM exception)
{
  SCM port = scm_open_output_string ();
  SCM key, args;

  gdb_assert (gdbscm_is_exception (exception));

  key = gdbscm_exception_key (exception);
  args = gdbscm_exception_args (exception);

  if (scm_is_eq (key, with_stack_error_symbol)
      /* Don't crash on a badly generated gdb:with-stack exception.  */
      && scm_is_pair (args)
      && scm_is_pair (scm_cdr (args)))
    {
      key = scm_car (args);
      args = scm_cddr (args);
    }

  gdbscm_print_exception_message (port, SCM_BOOL_F, key, args);
  gdb::unique_xmalloc_ptr<char> result
    = gdbscm_scm_to_c_string (scm_get_output_string (port));
  scm_close_port (port);
  return result;
}

/* Return the value of the "guile print-stack" option as one of:
   'none, 'message, 'full.  */

static SCM
gdbscm_percent_exception_print_style (void)
{
  if (gdbscm_print_excp == gdbscm_print_excp_none)
    return none_symbol;
  if (gdbscm_print_excp == gdbscm_print_excp_message)
    return message_symbol;
  if (gdbscm_print_excp == gdbscm_print_excp_full)
    return full_symbol;
  gdb_assert_not_reached ("bad value for \"guile print-stack\"");
}

/* Return the current <gdb:exception> counter.
   This is for debugging purposes.  */

static SCM
gdbscm_percent_exception_count (void)
{
  return scm_from_ulong (gdbscm_exception_count);
}

/* Initialize the Scheme exception support.  */

static const scheme_function exception_functions[] =
{
  { "make-exception", 2, 0, 0, as_a_scm_t_subr (gdbscm_make_exception),
    "\
Create a <gdb:exception> object.\n\
\n\
  Arguments: key args\n\
    These are the standard key,args arguments of \"throw\"." },

  { "exception?", 1, 0, 0, as_a_scm_t_subr (gdbscm_exception_p),
    "\
Return #t if the object is a <gdb:exception> object." },

  { "exception-key", 1, 0, 0, as_a_scm_t_subr (gdbscm_exception_key),
    "\
Return the exception's key." },

  { "exception-args", 1, 0, 0, as_a_scm_t_subr (gdbscm_exception_args),
    "\
Return the exception's arg list." },

  END_FUNCTIONS
};

static const scheme_function private_exception_functions[] =
{
  { "%exception-print-style", 0, 0, 0,
    as_a_scm_t_subr (gdbscm_percent_exception_print_style),
    "\
Return the value of the \"guile print-stack\" option." },

  { "%exception-count", 0, 0, 0,
    as_a_scm_t_subr (gdbscm_percent_exception_count),
    "\
Return a count of the number of <gdb:exception> objects created.\n\
This is for debugging purposes." },

  END_FUNCTIONS
};

void
gdbscm_initialize_exceptions (void)
{
  exception_smob_tag = gdbscm_make_smob_type (exception_smob_name,
					      sizeof (exception_smob));
  scm_set_smob_print (exception_smob_tag, exscm_print_exception_smob);

  gdbscm_define_functions (exception_functions, 1);
  gdbscm_define_functions (private_exception_functions, 0);

  error_symbol = scm_from_latin1_symbol ("gdb:error");

  memory_error_symbol = scm_from_latin1_symbol ("gdb:memory-error");

  user_error_symbol = scm_from_latin1_symbol ("gdb:user-error");

  gdbscm_invalid_object_error_symbol
    = scm_from_latin1_symbol ("gdb:invalid-object-error");

  with_stack_error_symbol = scm_from_latin1_symbol ("gdb:with-stack");

  /* The text of this symbol is taken from Guile's top-repl.scm.  */
  signal_symbol = scm_from_latin1_symbol ("signal");

  none_symbol = scm_from_latin1_symbol ("none");
  message_symbol = scm_from_latin1_symbol ("message");
  full_symbol = scm_from_latin1_symbol ("full");
}
