/* Support for connecting Guile's stdio to GDB's.
as well as r/w memory via ports.
- Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ Copyright (C) 2014-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "top.h"
#include "target.h"
#include "guile-internal.h"
+#include "gdbsupport/gdb_optional.h"
#ifdef HAVE_POLL
#if defined (HAVE_POLL_H)
/* A ui-file for sending output to Guile. */
-typedef struct
+class ioscm_file_port : public ui_file
{
- int *magic;
- SCM port;
-} ioscm_file_port;
+public:
+ /* Return a ui_file that writes to PORT. */
+ explicit ioscm_file_port (SCM port);
+
+ void flush () override;
+ void write (const char *buf, long length_buf) override;
+
+private:
+ SCM m_port;
+};
/* Data for a memory port. */
static SCM output_port_scm;
static SCM error_port_scm;
-/* Magic number to identify port ui-files.
- Actually, the address of this variable is the magic number. */
-static int file_port_magic;
-
/* Internal enum for specifying output port. */
enum oport { GDB_STDOUT, GDB_STDERR };
if (scm_is_eq (port, input_port_scm))
return;
- TRY
+ gdbscm_gdb_exception exc {};
+ try
{
if (scm_is_eq (port, error_port_scm))
fputsn_filtered ((const char *) data, size, gdb_stderr);
else
fputsn_filtered ((const char *) data, size, gdb_stdout);
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
- GDBSCM_HANDLE_GDB_EXCEPTION (except);
+ exc = unpack (except);
}
- END_CATCH
+ GDBSCM_HANDLE_GDB_EXCEPTION (exc);
}
/* Flush gdb's stdout or stderr. */
\f
/* Support for sending GDB I/O to Guile ports. */
-static void
-ioscm_file_port_delete (struct ui_file *file)
-{
- ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
-
- if (stream->magic != &file_port_magic)
- internal_error (__FILE__, __LINE__,
- _("ioscm_file_port_delete: bad magic number"));
- xfree (stream);
-}
-
-static void
-ioscm_file_port_rewind (struct ui_file *file)
-{
- ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
-
- if (stream->magic != &file_port_magic)
- internal_error (__FILE__, __LINE__,
- _("ioscm_file_port_rewind: bad magic number"));
-
- scm_truncate_file (stream->port, 0);
-}
+ioscm_file_port::ioscm_file_port (SCM port)
+ : m_port (port)
+{}
-static void
-ioscm_file_port_put (struct ui_file *file,
- ui_file_put_method_ftype *write,
- void *dest)
+void
+ioscm_file_port::flush ()
{
- ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
-
- if (stream->magic != &file_port_magic)
- internal_error (__FILE__, __LINE__,
- _("ioscm_file_port_put: bad magic number"));
-
- /* This function doesn't meld with ports very well. */
}
-static void
-ioscm_file_port_write (struct ui_file *file,
- const char *buffer,
- long length_buffer)
+void
+ioscm_file_port::write (const char *buffer, long length_buffer)
{
- ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
-
- if (stream->magic != &file_port_magic)
- internal_error (__FILE__, __LINE__,
- _("ioscm_pot_file_write: bad magic number"));
-
- scm_c_write (stream->port, buffer, length_buffer);
+ scm_c_write (m_port, buffer, length_buffer);
}
-/* Return a ui_file that writes to PORT. */
-
-static struct ui_file *
-ioscm_file_port_new (SCM port)
-{
- ioscm_file_port *stream = XCNEW (ioscm_file_port);
- struct ui_file *file = ui_file_new ();
-
- set_ui_file_data (file, stream, ioscm_file_port_delete);
- set_ui_file_rewind (file, ioscm_file_port_rewind);
- set_ui_file_put (file, ioscm_file_port_put);
- set_ui_file_write (file, ioscm_file_port_write);
- stream->magic = &file_port_magic;
- stream->port = port;
-
- return file;
-}
\f
/* Helper routine for with-{output,error}-to-port. */
ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
const char *func_name)
{
- struct ui_file *port_file;
- struct cleanup *cleanups;
SCM result;
SCM_ASSERT_TYPE (gdbscm_is_true (scm_output_port_p (port)), port,
SCM_ASSERT_TYPE (gdbscm_is_true (scm_thunk_p (thunk)), thunk,
SCM_ARG2, func_name, _("thunk"));
- cleanups = set_batch_flag_and_make_cleanup_restore_page_info ();
-
- make_cleanup_restore_integer (¤t_ui->async);
- current_ui->async = 0;
+ set_batch_flag_and_restore_page_info save_page_info;
- port_file = ioscm_file_port_new (port);
+ scoped_restore restore_async = make_scoped_restore (¤t_ui->async, 0);
- make_cleanup_ui_file_delete (port_file);
+ ui_file_up port_file (new ioscm_file_port (port));
scoped_restore save_file = make_scoped_restore (oport == GDB_STDERR
? &gdb_stderr : &gdb_stdout);
- if (oport == GDB_STDERR)
- gdb_stderr = port_file;
- else
- {
- current_uiout->redirect (port_file);
- make_cleanup_ui_out_redirect_pop (current_uiout);
-
- gdb_stdout = port_file;
- }
+ {
+ gdb::optional<ui_out_redirect_pop> redirect_popper;
+ if (oport == GDB_STDERR)
+ gdb_stderr = port_file.get ();
+ else
+ {
+ current_uiout->redirect (port_file.get ());
+ redirect_popper.emplace (current_uiout);
- result = gdbscm_safe_call_0 (thunk, NULL);
+ gdb_stdout = port_file.get ();
+ }
- do_cleanups (cleanups);
+ result = gdbscm_safe_call_0 (thunk, NULL);
+ }
if (gdbscm_is_exception (result))
gdbscm_throw (result);