/* Support for connecting Guile's stdio to GDB's.
as well as r/w memory via ports.
- Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Copyright (C) 2014-2020 Free Software Foundation, Inc.
This file is part of GDB.
conventions, et.al. */
#include "defs.h"
-#include "gdb_select.h"
-#include "interps.h"
+#include "gdbsupport/gdb_select.h"
+#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 };
FD_ZERO (&input_fds);
FD_SET (fdes, &input_fds);
- num_found = gdb_select (num_fds, &input_fds, NULL, NULL, &timeout);
+ num_found = interruptible_select (num_fds,
+ &input_fds, NULL, NULL,
+ &timeout);
if (num_found < 0)
{
/* Guile doesn't export SIGINT hooks like Python does.
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
- count = ui_file_read (gdb_stdin, (char *) pt->read_buf, pt->read_buf_size);
+ count = gdb_stdin->read ((char *) pt->read_buf, pt->read_buf_size);
if (count == -1)
scm_syserror (FUNC_NAME);
if (count == 0)
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. */
{
int is_a_tty = isatty (fd);
const char *name;
+ const char *mode_str;
long mode_bits;
SCM port;
{
case 0:
name = input_port_name;
- mode_bits = scm_mode_bits (is_a_tty ? "r0" : "r");
+ mode_str = is_a_tty ? "r0" : "r";
break;
case 1:
name = output_port_name;
- mode_bits = scm_mode_bits (is_a_tty ? "w0" : "w");
+ mode_str = is_a_tty ? "w0" : "w";
break;
case 2:
name = error_port_name;
- mode_bits = scm_mode_bits (is_a_tty ? "w0" : "w");
+ mode_str = is_a_tty ? "w0" : "w";
break;
default:
gdb_assert_not_reached ("bad stdio file descriptor");
}
+ mode_bits = scm_mode_bits ((char *) mode_str);
port = ioscm_open_port (stdio_port_desc, mode_bits);
scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
\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);
+ioscm_file_port::ioscm_file_port (SCM port)
+ : m_port (port)
+{}
- 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);
-}
-
-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 ();
+ set_batch_flag_and_restore_page_info save_page_info;
- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ scoped_restore restore_async = make_scoped_restore (¤t_ui->async, 0);
- port_file = ioscm_file_port_new (port);
+ ui_file_up port_file (new ioscm_file_port (port));
- make_cleanup_ui_file_delete (port_file);
+ scoped_restore save_file = make_scoped_restore (oport == GDB_STDERR
+ ? &gdb_stderr : &gdb_stdout);
- if (oport == GDB_STDERR)
- {
- make_cleanup_restore_ui_file (&gdb_stderr);
- gdb_stderr = port_file;
- }
- else
- {
- make_cleanup_restore_ui_file (&gdb_stdout);
-
- if (ui_out_redirect (current_uiout, port_file) < 0)
- warning (_("Current output protocol does not support redirection"));
- else
- 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);
&start_arg_pos, &start,
&size_arg_pos, &size);
- scm_dynwind_begin (0);
+ scm_dynwind_begin ((scm_t_dynwind_flags) 0);
if (mode == NULL)
mode = xstrdup ("r");