/* 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 (data, size, gdb_stderr);
+ fputsn_filtered ((const char *) data, size, gdb_stderr);
else
- fputsn_filtered (data, size, gdb_stdout);
+ 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. */
if (!writing && size > 0)
{
- pt->read_buf = scm_gc_malloc_pointerless (size, "port buffer");
+ pt->read_buf
+ = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
pt->read_pos = pt->read_end = pt->read_buf;
pt->read_buf_size = size;
}
if (writing && size > 0)
{
- pt->write_buf = scm_gc_malloc_pointerless (size, "port buffer");
+ pt->write_buf
+ = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
pt->write_pos = pt->write_buf;
pt->write_buf_size = size;
}
{
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 = 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 = 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 = 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 = 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);
/* "write" method for memory ports. */
static void
-gdbscm_memory_port_write (SCM port, const void *data, size_t size)
+gdbscm_memory_port_write (SCM port, const void *void_data, size_t size)
{
scm_t_port *pt = SCM_PTAB_ENTRY (port);
ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+ const gdb_byte *data = (const gdb_byte *) void_data;
/* There's no way to indicate a short write, so if the request goes past
the end of the port's memory range, flag an error. */
pt->write_pos = pt->write_end;
gdbscm_memory_port_flush (port);
{
- const void *ptr = ((const char *) data) + space;
+ const gdb_byte *ptr = data + space;
size_t remaining = size - space;
if (remaining >= pt->write_buf_size)
pt->write_buf_size = iomem->write_buf_size;
if (buffered)
{
- pt->read_buf = xmalloc (pt->read_buf_size);
- pt->write_buf = xmalloc (pt->write_buf_size);
+ pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
+ pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
}
else
{
iomem->read_buf_size = read_buf_size;
pt->read_buf_size = read_buf_size;
xfree (pt->read_buf);
- pt->read_buf = xmalloc (pt->read_buf_size);
+ pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
pt->read_pos = pt->read_end = pt->read_buf;
}
iomem->write_buf_size = write_buf_size;
pt->write_buf_size = write_buf_size;
xfree (pt->write_buf);
- pt->write_buf = xmalloc (pt->write_buf_size);
+ pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
pt->write_pos = pt->write_buf;
pt->write_end = pt->write_buf + pt->write_buf_size;
}
&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");
static const scheme_function port_functions[] =
{
- { "input-port", 0, 0, 0, gdbscm_input_port,
+ { "input-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_input_port),
"\
Return gdb's input port." },
- { "output-port", 0, 0, 0, gdbscm_output_port,
+ { "output-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_output_port),
"\
Return gdb's output port." },
- { "error-port", 0, 0, 0, gdbscm_error_port,
+ { "error-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_error_port),
"\
Return gdb's error port." },
- { "stdio-port?", 1, 0, 0, gdbscm_stdio_port_p,
+ { "stdio-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_stdio_port_p),
"\
Return #t if the object is a gdb:stdio-port." },
- { "open-memory", 0, 0, 1, gdbscm_open_memory,
+ { "open-memory", 0, 0, 1, as_a_scm_t_subr (gdbscm_open_memory),
"\
Return a port that can be used for reading/writing inferior memory.\n\
\n\
Arguments: [#:mode string] [#:start address] [#:size integer]\n\
Returns: A port object." },
- { "memory-port?", 1, 0, 0, gdbscm_memory_port_p,
+ { "memory-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_p),
"\
Return #t if the object is a memory port." },
- { "memory-port-range", 1, 0, 0, gdbscm_memory_port_range,
+ { "memory-port-range", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_range),
"\
Return the memory range of the port as (start end)." },
{ "memory-port-read-buffer-size", 1, 0, 0,
- gdbscm_memory_port_read_buffer_size,
+ as_a_scm_t_subr (gdbscm_memory_port_read_buffer_size),
"\
Return the size of the read buffer for the memory port." },
{ "set-memory-port-read-buffer-size!", 2, 0, 0,
- gdbscm_set_memory_port_read_buffer_size_x,
+ as_a_scm_t_subr (gdbscm_set_memory_port_read_buffer_size_x),
"\
Set the size of the read buffer for the memory port.\n\
\n\
Returns: unspecified." },
{ "memory-port-write-buffer-size", 1, 0, 0,
- gdbscm_memory_port_write_buffer_size,
+ as_a_scm_t_subr (gdbscm_memory_port_write_buffer_size),
"\
Return the size of the write buffer for the memory port." },
{ "set-memory-port-write-buffer-size!", 2, 0, 0,
- gdbscm_set_memory_port_write_buffer_size_x,
+ as_a_scm_t_subr (gdbscm_set_memory_port_write_buffer_size_x),
"\
Set the size of the write buffer for the memory port.\n\
\n\
{
#if 0 /* TODO */
{ "%with-gdb-input-from-port", 2, 0, 0,
- gdbscm_percent_with_gdb_input_from_port,
+ as_a_scm_t_subr (gdbscm_percent_with_gdb_input_from_port),
"\
Temporarily set GDB's input port to PORT and then invoke THUNK.\n\
\n\
#endif
{ "%with-gdb-output-to-port", 2, 0, 0,
- gdbscm_percent_with_gdb_output_to_port,
+ as_a_scm_t_subr (gdbscm_percent_with_gdb_output_to_port),
"\
Temporarily set GDB's output port to PORT and then invoke THUNK.\n\
\n\
This procedure is experimental." },
{ "%with-gdb-error-to-port", 2, 0, 0,
- gdbscm_percent_with_gdb_error_to_port,
+ as_a_scm_t_subr (gdbscm_percent_with_gdb_error_to_port),
"\
Temporarily set GDB's error port to PORT and then invoke THUNK.\n\
\n\