public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: "Ludovic Courtès" <ludo@gnu.org>, gdb-patches@sourceware.org
Subject: Re: [PATCH 1/2] guile: Add support for Guile 2.2.
Date: Fri, 12 Jun 2020 16:14:14 +0200	[thread overview]
Message-ID: <513a8d32-70c0-939c-ccbb-f57c2165f25d@suse.de> (raw)
In-Reply-To: <20200612132710.14364-2-ludo@gnu.org>

On 12-06-2020 15:27, Ludovic Courtès wrote:
> This primarily updates code that uses the I/O port API of Guile.
> 
> gdb/ChangeLog:
> 

It looks like you could claim fixing PR guile/21104 here.

Thanks,
- Tom

> 	* guile/scm-ports.c (USING_GUILE_BEFORE_2_2): New macro.
> 	(ioscm_memory_port)[read_buf_size, write_buf_size]: Wrap in #if
> 	USING_GUILE_BEFORE_2_2.
> 	(stdio_port_desc, memory_port_desc) [!USING_GUILE_BEFORE_2_2]:
> 	Change type to 'scm_t_port_type *'.
> 	(ioscm_open_port) [!USING_GUILE_BEFORE_2_2]: New function.
> 	(ioscm_read_from_port, ioscm_write) [!USING_GUILE_BEFORE_2_2]: New
> 	functions.
> 	(ioscm_fill_input, ioscm_input_waiting, ioscm_flush): Wrap in #if
> 	USING_GUILE_BEFORE_2_2.
> 	(ioscm_init_gdb_stdio_port) [!USING_GUILE_BEFORE_2_2]: Use
> 	'ioscm_read_from_port'.  Call 'scm_set_port_read_wait_fd'.
> 	(ioscm_init_stdio_buffers) [!USING_GUILE_BEFORE_2_2]: New function.
> 	(gdbscm_stdio_port_p) [!USING_GUILE_BEFORE_2_2]: Use 'SCM_PORTP'
> 	and 'SCM_PORT_TYPE'.
> 	(gdbscm_memory_port_end_input, gdbscm_memory_port_seek)
> 	(ioscm_reinit_memory_port): Wrap in #if USING_GUILE_BEFORE_2_2.
> 	(gdbscm_memory_port_read, gdbscm_memory_port_write)
> 	(gdbscm_memory_port_seek, gdbscm_memory_port_close)
> 	[!USING_GUILE_BEFORE_2_2]: New functions.
> 	(gdbscm_memory_port_print): Remove use of 'SCM_PTOB_NAME'.
> 	(ioscm_init_memory_port_type) [!USING_GUILE_BEFORE_2_2]: Use
> 	'gdbscm_memory_port_read'.
> 	Wrap 'scm_set_port_end_input', 'scm_set_port_flush', and
> 	'scm_set_port_free' calls in #if USING_GUILE_BEFORE_2_2.
> 	(ioscm_init_memory_port): Wrap buffer-related code in #if
> 	USING_GUILE_BEFORE_2_2.
> 	(gdbscm_memory_port_read_buffer_size) [!USING_GUILE_BEFORE_2_2]:
> 	Return scm_from_uint (0).
> 	(gdbscm_set_memory_port_read_buffer_size_x)
> 	[!USING_GUILE_BEFORE_2_2]: Call 'scm_setvbuf'.
> 	(gdbscm_memory_port_write_buffer_size) [!USING_GUILE_BEFORE_2_2]:
> 	Return scm_from_uint (0).
> 	(gdbscm_set_memory_port_write_buffer_size_x)
> 	[!USING_GUILE_BEFORE_2_2]: Call 'scm_setvbuf'.
> 	* testsuite/gdb.guile/scm-error.exp ("source
> 	$remote_guile_file_1"): Relax error regexp to match on Guile 2.2.
> 	* testsuite/gdb.guile/scm-ports.exp (test_mem_port_rw): Pass
> 	"r0+" instead of "r+" to 'open-memory' so make it explicitly
> 	unbuffered (it's buffered by default on 2.2/3.0).
> 	* configure.ac (try_guile_versions): Add "guile-2.2".
> 	* configure: Regenerate.
> 	* doc/guile.texi (Memory Ports in Guile): Remove
> 	documentation of 'memory-port-read-buffer-size',
> 	'set-memory-port-read-buffer-size!',
> 	'memory-port-write-buffer-size',
> 	'set-memory-port-read-buffer-size!', which are no longer
> 	supported with Guile 2.2/3.0 and superseded by 'setvbuf'.
> 	* doc/guile.texi (Guile Introduction): Clarify which Guile
> 	versions are supported.
> ---
>  gdb/configure                         |   2 +-
>  gdb/configure.ac                      |   2 +-
>  gdb/doc/guile.texi                    |  23 +-
>  gdb/guile/scm-ports.c                 | 545 ++++++++++++++++++--------
>  gdb/testsuite/gdb.guile/scm-error.exp |   2 +-
>  gdb/testsuite/gdb.guile/scm-ports.exp |   2 +-
>  6 files changed, 394 insertions(+), 182 deletions(-)
> 
> diff --git a/gdb/configure b/gdb/configure
> index ef10aa717f..bd12695291 100755
> --- a/gdb/configure
> +++ b/gdb/configure
> @@ -10954,7 +10954,7 @@ fi
>  
>  
>  
> -try_guile_versions="guile-2.0"
> +try_guile_versions="guile-2.2 guile-2.0"
>  have_libguile=no
>  case "${with_guile}" in
>  no)
> diff --git a/gdb/configure.ac b/gdb/configure.ac
> index 62750804fa..87afc26581 100644
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -1088,7 +1088,7 @@ AC_MSG_RESULT([$with_guile])
>  dnl We check guile with pkg-config.
>  AC_PATH_PROG(pkg_config_prog_path, pkg-config, missing)
>  
> -try_guile_versions="guile-2.0"
> +try_guile_versions="guile-2.2 guile-2.0"
>  have_libguile=no
>  case "${with_guile}" in
>  no)
> diff --git a/gdb/doc/guile.texi b/gdb/doc/guile.texi
> index c0bff7972f..0e6c74ef8b 100644
> --- a/gdb/doc/guile.texi
> +++ b/gdb/doc/guile.texi
> @@ -38,8 +38,7 @@ Guile support in @value{GDBN} follows the Python support in @value{GDBN}
>  reasonably closely, so concepts there should carry over.
>  However, some things are done differently where it makes sense.
>  
> -@value{GDBN} requires Guile version 2.0 or greater.
> -Older versions are not supported.
> +@value{GDBN} requires Guile version 2.2 or 2.0.
>  
>  @cindex guile scripts directory
>  Guile scripts used by @value{GDBN} should be installed in
> @@ -3556,26 +3555,6 @@ of two elements: @code{(start end)}.  The range is @var{start} to @var{end}
>  inclusive.
>  @end deffn
>  
> -@deffn {Scheme Procedure} memory-port-read-buffer-size memory-port
> -Return the size of the read buffer of @code{<gdb:memory-port>}
> -@var{memory-port}.
> -@end deffn
> -
> -@deffn {Scheme Procedure} set-memory-port-read-buffer-size! memory-port size
> -Set the size of the read buffer of @code{<gdb:memory-port>}
> -@var{memory-port} to @var{size}.  The result is unspecified.
> -@end deffn
> -
> -@deffn {Scheme Procedure} memory-port-write-buffer-size memory-port
> -Return the size of the write buffer of @code{<gdb:memory-port>}
> -@var{memory-port}.
> -@end deffn
> -
> -@deffn {Scheme Procedure} set-memory-port-write-buffer-size! memory-port size
> -Set the size of the write buffer of @code{<gdb:memory-port>}
> -@var{memory-port} to @var{size}.  The result is unspecified.
> -@end deffn
> -
>  A memory port is closed like any other port, with @code{close-port}.
>  
>  Combined with Guile's @code{bytevectors}, memory ports provide a lot
> diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
> index 407d1d36f1..5c39cc1ddf 100644
> --- a/gdb/guile/scm-ports.c
> +++ b/gdb/guile/scm-ports.c
> @@ -36,6 +36,13 @@
>  #endif
>  #endif
>  
> +/* Whether we're using Guile < 2.2 and its clumsy port API.  */
> +
> +#define USING_GUILE_BEFORE_2_2					\
> +  (SCM_MAJOR_VERSION < 2					\
> +   || (SCM_MAJOR_VERSION == 2 && SCM_MINOR_VERSION == 0))
> +
> +
>  /* A ui-file for sending output to Guile.  */
>  
>  class ioscm_file_port : public ui_file
> @@ -66,12 +73,14 @@ typedef struct
>       This value is always in the range [0, size].  */
>    ULONGEST current;
>  
> +#if USING_GUILE_BEFORE_2_2
>    /* The size of the internal r/w buffers.
>       Scheme ports aren't a straightforward mapping to memory r/w.
>       Generally the user specifies how much to r/w and all access is
>       unbuffered.  We don't try to provide equivalent access, but we allow
>       the user to specify these values to help get something similar.  */
>    unsigned read_buf_size, write_buf_size;
> +#endif
>  } ioscm_memory_port;
>  
>  /* Copies of the original system input/output/error ports.
> @@ -81,7 +90,11 @@ static SCM orig_output_port_scm;
>  static SCM orig_error_port_scm;
>  
>  /* This is the stdio port descriptor, scm_ptob_descriptor.  */
> +#if USING_GUILE_BEFORE_2_2
>  static scm_t_bits stdio_port_desc;
> +#else
> +static scm_t_port_type *stdio_port_desc;
> +#endif
>  
>  /* Note: scm_make_port_type takes a char * instead of a const char *.  */
>  static /*const*/ char stdio_port_desc_name[] = "gdb:stdio-port";
> @@ -102,7 +115,11 @@ static SCM error_port_scm;
>  enum oport { GDB_STDOUT, GDB_STDERR };
>  
>  /* This is the memory port descriptor, scm_ptob_descriptor.  */
> +#if USING_GUILE_BEFORE_2_2
>  static scm_t_bits memory_port_desc;
> +#else
> +static scm_t_port_type *memory_port_desc;
> +#endif
>  
>  /* Note: scm_make_port_type takes a char * instead of a const char *.  */
>  static /*const*/ char memory_port_desc_name[] = "gdb:memory-port";
> @@ -131,6 +148,8 @@ static SCM size_keyword;
>  /* Helper to do the low level work of opening a port.
>     Newer versions of Guile (2.1.x) have scm_c_make_port.  */
>  
> +#if USING_GUILE_BEFORE_2_2
> +
>  static SCM
>  ioscm_open_port (scm_t_bits port_type, long mode_bits)
>  {
> @@ -150,9 +169,39 @@ ioscm_open_port (scm_t_bits port_type, long mode_bits)
>  
>    return port;
>  }
> +
> +#else
> +
> +static SCM
> +ioscm_open_port (scm_t_port_type *port_type, long mode_bits)
> +{
> +  return scm_c_make_port (port_type, mode_bits, 0);
> +}
> +
> +#endif
> +
>  \f
>  /* Support for connecting Guile's stdio ports to GDB's stdio ports.  */
>  
> +/* Like fputstrn_filtered, but don't escape characters, except nul.
> +   Also like fputs_filtered, but a length is specified.  */
> +
> +static void
> +fputsn_filtered (const char *s, size_t size, struct ui_file *stream)
> +{
> +  size_t i;
> +
> +  for (i = 0; i < size; ++i)
> +    {
> +      if (s[i] == '\0')
> +	fputs_filtered ("\\000", stream);
> +      else
> +	fputc_filtered (s[i], stream);
> +    }
> +}
> +
> +#if USING_GUILE_BEFORE_2_2
> +
>  /* The scm_t_ptob_descriptor.input_waiting "method".
>     Return a lower bound on the number of bytes available for input.  */
>  
> @@ -245,23 +294,6 @@ ioscm_fill_input (SCM port)
>    return *pt->read_buf;
>  }
>  
> -/* Like fputstrn_filtered, but don't escape characters, except nul.
> -   Also like fputs_filtered, but a length is specified.  */
> -
> -static void
> -fputsn_filtered (const char *s, size_t size, struct ui_file *stream)
> -{
> -  size_t i;
> -
> -  for (i = 0; i < size; ++i)
> -    {
> -      if (s[i] == '\0')
> -	fputs_filtered ("\\000", stream);
> -      else
> -	fputc_filtered (s[i], stream);
> -    }
> -}
> -
>  /* Write to gdb's stdout or stderr.  */
>  
>  static void
> @@ -302,6 +334,62 @@ ioscm_flush (SCM port)
>      gdb_flush (gdb_stdout);
>  }
>  
> +#else /* !USING_GUILE_BEFORE_2_2 */
> +
> +/* Read up to COUNT bytes into bytevector DST at offset START.  Return the
> +   number of bytes read, zero for the end of file.  */
> +
> +static size_t
> +ioscm_read_from_port (SCM port, SCM dst, size_t start, size_t count)
> +{
> +  long read;
> +  char *read_buf;
> +
> +  /* If we're called on stdout,stderr, punt.  */
> +  if (! scm_is_eq (port, input_port_scm))
> +    return 0;
> +
> +  gdb_flush (gdb_stdout);
> +  gdb_flush (gdb_stderr);
> +
> +  read_buf = (char *) SCM_BYTEVECTOR_CONTENTS (dst) + start;
> +  read = gdb_stdin->read (read_buf, count);
> +  if (read == -1)
> +    scm_syserror (FUNC_NAME);
> +
> +  return (size_t) read;
> +}
> +
> +/* Write to gdb's stdout or stderr.  */
> +
> +static size_t
> +ioscm_write (SCM port, SCM src, size_t start, size_t count)
> +{
> +  const char *data = (char *) SCM_BYTEVECTOR_CONTENTS (src) + start;
> +
> +  /* If we're called on stdin, punt.  */
> +  if (scm_is_eq (port, input_port_scm))
> +    return 0;
> +
> +  gdbscm_gdb_exception exc {};
> +  try
> +    {
> +      if (scm_is_eq (port, error_port_scm))
> +	fputsn_filtered ((const char *) data, count, gdb_stderr);
> +      else
> +	fputsn_filtered ((const char *) data, count, gdb_stdout);
> +    }
> +  catch (const gdb_exception &except)
> +    {
> +      exc = unpack (except);
> +    }
> +  GDBSCM_HANDLE_GDB_EXCEPTION (exc);
> +
> +  return count;
> +}
> +
> +#endif /* !USING_GUILE_BEFORE_2_2 */
> +
>  /* Initialize the gdb stdio port type.
>  
>     N.B. isatty? will fail on these ports, it is only supported for file
> @@ -311,12 +399,25 @@ static void
>  ioscm_init_gdb_stdio_port (void)
>  {
>    stdio_port_desc = scm_make_port_type (stdio_port_desc_name,
> -					ioscm_fill_input, ioscm_write);
> +#if USING_GUILE_BEFORE_2_2
> +					ioscm_fill_input,
> +#else
> +					ioscm_read_from_port,
> +#endif
> +					ioscm_write);
>  
> +#if USING_GUILE_BEFORE_2_2
>    scm_set_port_input_waiting (stdio_port_desc, ioscm_input_waiting);
>    scm_set_port_flush (stdio_port_desc, ioscm_flush);
> +#else
> +  scm_set_port_read_wait_fd (stdio_port_desc, STDIN_FILENO);
> +#endif
>  }
>  
> +#define GDB_STDIO_BUFFER_DEFAULT_SIZE 1024
> +
> +#if USING_GUILE_BEFORE_2_2
> +
>  /* Subroutine of ioscm_make_gdb_stdio_port to simplify it.
>     Set up the buffers of port PORT.
>     MODE_BITS are the mode bits of PORT.  */
> @@ -325,7 +426,6 @@ static void
>  ioscm_init_stdio_buffers (SCM port, long mode_bits)
>  {
>    scm_t_port *pt = SCM_PTAB_ENTRY (port);
> -#define GDB_STDIO_BUFFER_DEFAULT_SIZE 1024
>    int size = mode_bits & SCM_BUF0 ? 0 : GDB_STDIO_BUFFER_DEFAULT_SIZE;
>    int writing = (mode_bits & SCM_WRTNG) != 0;
>  
> @@ -359,6 +459,20 @@ ioscm_init_stdio_buffers (SCM port, long mode_bits)
>    pt->write_end = pt->write_buf + pt->write_buf_size;
>  }
>  
> +#else
> +
> +static void
> +ioscm_init_stdio_buffers (SCM port, long mode_bits)
> +{
> +  if (mode_bits & SCM_BUF0)
> +    scm_setvbuf (port, scm_from_utf8_symbol ("none"), scm_from_size_t (0));
> +  else
> +    scm_setvbuf (port, scm_from_utf8_symbol ("block"),
> +		 scm_from_size_t (GDB_STDIO_BUFFER_DEFAULT_SIZE));
> +}
> +
> +#endif
> +
>  /* Create a gdb stdio port.  */
>  
>  static SCM
> @@ -403,9 +517,14 @@ ioscm_make_gdb_stdio_port (int fd)
>  static SCM
>  gdbscm_stdio_port_p (SCM scm)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    /* This is copied from SCM_FPORTP.  */
>    return scm_from_bool (!SCM_IMP (scm)
>  			&& (SCM_TYP16 (scm) == stdio_port_desc));
> +#else
> +  return scm_from_bool (SCM_PORTP (scm)
> +			&& (SCM_PORT_TYPE (scm) == stdio_port_desc));
> +#endif
>  }
>  \f
>  /* GDB's ports are accessed via functions to keep them read-only.  */
> @@ -568,6 +687,8 @@ ioscm_lseek_address (ioscm_memory_port *iomem, LONGEST offset, int whence)
>    return 1;
>  }
>  
> +#if USING_GUILE_BEFORE_2_2
> +
>  /* "fill_input" method for memory ports.  */
>  
>  static int
> @@ -661,73 +782,6 @@ gdbscm_memory_port_flush (SCM port)
>    pt->rw_active = SCM_PORT_NEITHER;
>  }
>  
> -/* "write" method for memory ports.  */
> -
> -static void
> -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.  */
> -  if (size > iomem->size - iomem->current)
> -    {
> -      gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (size),
> -				 _("writing beyond end of memory range"));
> -    }
> -
> -  if (pt->write_buf == &pt->shortbuf)
> -    {
> -      /* Unbuffered port.  */
> -      if (target_write_memory (iomem->start + iomem->current, data, size) != 0)
> -	gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
> -      iomem->current += size;
> -      return;
> -    }
> -
> -  /* Note: The edge case of what to do when the buffer exactly fills is
> -     debatable.  Guile flushes when the buffer exactly fills up, so we
> -     do too.  It's counter-intuitive to my mind, but in case there's a
> -     subtlety somewhere that depends on this, we do the same.  */
> -
> -  {
> -    size_t space = pt->write_end - pt->write_pos;
> -
> -    if (size < space)
> -      {
> -	/* Data fits in buffer, and does not fill it.  */
> -	memcpy (pt->write_pos, data, size);
> -	pt->write_pos += size;
> -      }
> -    else
> -      {
> -	memcpy (pt->write_pos, data, space);
> -	pt->write_pos = pt->write_end;
> -	gdbscm_memory_port_flush (port);
> -	{
> -	  const gdb_byte *ptr = data + space;
> -	  size_t remaining = size - space;
> -
> -	  if (remaining >= pt->write_buf_size)
> -	    {
> -	      if (target_write_memory (iomem->start + iomem->current, ptr,
> -				       remaining) != 0)
> -		gdbscm_memory_error (FUNC_NAME, _("error writing memory"),
> -				     SCM_EOL);
> -	      iomem->current += remaining;
> -	    }
> -	  else
> -	    {
> -	      memcpy (pt->write_pos, ptr, remaining);
> -	      pt->write_pos += remaining;
> -	    }
> -	}
> -      }
> -  }
> -}
> -
>  /* "seek" method for memory ports.  */
>  
>  static scm_t_off
> @@ -820,6 +874,73 @@ gdbscm_memory_port_seek (SCM port, scm_t_off offset, int whence)
>    return result;
>  }
>  
> +/* "write" method for memory ports.  */
> +
> +static void
> +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.  */
> +  if (size > iomem->size - iomem->current)
> +    {
> +      gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (size),
> +				 _("writing beyond end of memory range"));
> +    }
> +
> +  if (pt->write_buf == &pt->shortbuf)
> +    {
> +      /* Unbuffered port.  */
> +      if (target_write_memory (iomem->start + iomem->current, data, size) != 0)
> +	gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
> +      iomem->current += size;
> +      return;
> +    }
> +
> +  /* Note: The edge case of what to do when the buffer exactly fills is
> +     debatable.  Guile flushes when the buffer exactly fills up, so we
> +     do too.  It's counter-intuitive to my mind, but in case there's a
> +     subtlety somewhere that depends on this, we do the same.  */
> +
> +  {
> +    size_t space = pt->write_end - pt->write_pos;
> +
> +    if (size < space)
> +      {
> +	/* Data fits in buffer, and does not fill it.  */
> +	memcpy (pt->write_pos, data, size);
> +	pt->write_pos += size;
> +      }
> +    else
> +      {
> +	memcpy (pt->write_pos, data, space);
> +	pt->write_pos = pt->write_end;
> +	gdbscm_memory_port_flush (port);
> +	{
> +	  const gdb_byte *ptr = data + space;
> +	  size_t remaining = size - space;
> +
> +	  if (remaining >= pt->write_buf_size)
> +	    {
> +	      if (target_write_memory (iomem->start + iomem->current, ptr,
> +				       remaining) != 0)
> +		gdbscm_memory_error (FUNC_NAME, _("error writing memory"),
> +				     SCM_EOL);
> +	      iomem->current += remaining;
> +	    }
> +	  else
> +	    {
> +	      memcpy (pt->write_pos, ptr, remaining);
> +	      pt->write_pos += remaining;
> +	    }
> +	}
> +      }
> +  }
> +}
> +
>  /* "close" method for memory ports.  */
>  
>  static int
> @@ -851,18 +972,166 @@ gdbscm_memory_port_free (SCM port)
>    return 0;
>  }
>  
> +/* Re-initialize a memory port, updating its read/write buffer sizes.
> +   An exception is thrown if the port is unbuffered.
> +   TODO: Allow switching buffered/unbuffered.
> +   An exception is also thrown if data is still buffered, except in the case
> +   where the buffer size isn't changing (since that's just a nop).  */
> +
> +static void
> +ioscm_reinit_memory_port (SCM port, size_t read_buf_size,
> +			  size_t write_buf_size, const char *func_name)
> +{
> +  scm_t_port *pt = SCM_PTAB_ENTRY (port);
> +  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> +
> +  gdb_assert (read_buf_size >= min_memory_port_buf_size
> +	      && read_buf_size <= max_memory_port_buf_size);
> +  gdb_assert (write_buf_size >= min_memory_port_buf_size
> +	      && write_buf_size <= max_memory_port_buf_size);
> +
> +  /* First check if the port is unbuffered.  */
> +
> +  if (pt->read_buf == &pt->shortbuf)
> +    {
> +      gdb_assert (pt->write_buf == &pt->shortbuf);
> +      scm_misc_error (func_name, _("port is unbuffered: ~a"),
> +		      scm_list_1 (port));
> +    }
> +
> +  /* Next check if anything is buffered.  */
> +
> +  if (read_buf_size != pt->read_buf_size
> +      && pt->read_end != pt->read_buf)
> +    {
> +      scm_misc_error (func_name, _("read buffer not empty: ~a"),
> +		      scm_list_1 (port));
> +    }
> +
> +  if (write_buf_size != pt->write_buf_size
> +      && pt->write_pos != pt->write_buf)
> +    {
> +      scm_misc_error (func_name, _("write buffer not empty: ~a"),
> +		      scm_list_1 (port));
> +    }
> +
> +  /* Now we can update the buffer sizes, but only if the size has changed.  */
> +
> +  if (read_buf_size != pt->read_buf_size)
> +    {
> +      iomem->read_buf_size = read_buf_size;
> +      pt->read_buf_size = read_buf_size;
> +      xfree (pt->read_buf);
> +      pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
> +      pt->read_pos = pt->read_end = pt->read_buf;
> +    }
> +
> +  if (write_buf_size != pt->write_buf_size)
> +    {
> +      iomem->write_buf_size = write_buf_size;
> +      pt->write_buf_size = write_buf_size;
> +      xfree (pt->write_buf);
> +      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;
> +    }
> +}
> +
> +#else /* !USING_GUILE_BEFORE_2_2 */
> +
> +/* Read up to COUNT bytes into bytevector DST at offset START.  Return the
> +   number of bytes read, zero for the end of file.  */
> +
> +static size_t
> +gdbscm_memory_port_read (SCM port, SCM dst, size_t start, size_t count)
> +{
> +  gdb_byte *read_buf;
> +  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> +
> +  /* "current" is the offset of the first byte we want to read.  */
> +  gdb_assert (iomem->current <= iomem->size);
> +  if (iomem->current == iomem->size)
> +    return 0;
> +
> +  /* Don't read outside the allowed memory range.  */
> +  if (count > iomem->size - iomem->current)
> +    count = iomem->size - iomem->current;
> +
> +  read_buf = (gdb_byte *) SCM_BYTEVECTOR_CONTENTS (dst) + start;
> +  if (target_read_memory (iomem->start + iomem->current, read_buf,
> +			  count) != 0)
> +    gdbscm_memory_error (FUNC_NAME, _("error reading memory"), SCM_EOL);
> +
> +  iomem->current += count;
> +  return count;
> +}
> +
> +static size_t
> +gdbscm_memory_port_write (SCM port, SCM src, size_t start, size_t count)
> +{
> +  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> +  const gdb_byte *data =
> +    (const gdb_byte *) SCM_BYTEVECTOR_CONTENTS (src) + start;
> +
> +  /* If the request goes past the end of the port's memory range, flag an
> +     error.  */
> +  if (count > iomem->size - iomem->current)
> +    gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_size_t (count),
> +			       _("writing beyond end of memory range"));
> +
> +  if (target_write_memory (iomem->start + iomem->current, data,
> +			   count) != 0)
> +    gdbscm_memory_error (FUNC_NAME, _("error writing memory"),
> +			 SCM_EOL);
> +
> +  iomem->current += count;
> +
> +  return count;
> +}
> +
> +static scm_t_off
> +gdbscm_memory_port_seek (SCM port, scm_t_off offset, int whence)
> +{
> +  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> +  CORE_ADDR result;
> +  int rc;
> +
> +  rc = ioscm_lseek_address (iomem, offset, whence);
> +  result = iomem->current;
> +
> +  if (rc == 0)
> +    gdbscm_out_of_range_error (FUNC_NAME, 0,
> +			       gdbscm_scm_from_longest (offset),
> +			       _("bad seek"));
> +
> +  /* TODO: The Guile API doesn't support 32x64.  We can't fix that here,
> +     and there's no need to throw an error if the new address can't be
> +     represented in a scm_t_off.  But we could return something less
> +     clumsy.  */
> +  return result;
> +}
> +
> +static void
> +gdbscm_memory_port_close (SCM port)
> +{
> +  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> +  scm_gc_free (iomem, sizeof (*iomem), "memory port");
> +  SCM_SETSTREAM (port, NULL);
> +}
> +
> +#endif /* !USING_GUILE_BEFORE_2_2 */
> +
>  /* "print" method for memory ports.  */
>  
>  static int
>  gdbscm_memory_port_print (SCM exp, SCM port, scm_print_state *pstate)
>  {
>    ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (exp);
> -  char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
>  
>    scm_puts ("#<", port);
>    scm_print_port_mode (exp, port);
>    /* scm_print_port_mode includes a trailing space.  */
> -  gdbscm_printf (port, "%s %s-%s", type,
> +  gdbscm_printf (port, "%s %s-%s", memory_port_desc_name,
>  		 hex_string (iomem->start), hex_string (iomem->end));
>    scm_putc ('>', port);
>    return 1;
> @@ -874,14 +1143,20 @@ static void
>  ioscm_init_memory_port_type (void)
>  {
>    memory_port_desc = scm_make_port_type (memory_port_desc_name,
> +#if USING_GUILE_BEFORE_2_2
>  					 gdbscm_memory_port_fill_input,
> +#else
> +					 gdbscm_memory_port_read,
> +#endif
>  					 gdbscm_memory_port_write);
>  
> +#if USING_GUILE_BEFORE_2_2
>    scm_set_port_end_input (memory_port_desc, gdbscm_memory_port_end_input);
>    scm_set_port_flush (memory_port_desc, gdbscm_memory_port_flush);
> +  scm_set_port_free (memory_port_desc, gdbscm_memory_port_free);
> +#endif
>    scm_set_port_seek (memory_port_desc, gdbscm_memory_port_seek);
>    scm_set_port_close (memory_port_desc, gdbscm_memory_port_close);
> -  scm_set_port_free (memory_port_desc, gdbscm_memory_port_free);
>    scm_set_port_print (memory_port_desc, gdbscm_memory_port_print);
>  }
>  
> @@ -930,9 +1205,7 @@ ioscm_parse_mode_bits (const char *func_name, const char *mode)
>  static void
>  ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
>  {
> -  scm_t_port *pt;
>    ioscm_memory_port *iomem;
> -  int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
>  
>    gdb_assert (start <= end);
>  
> @@ -943,6 +1216,9 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
>    iomem->end = end;
>    iomem->size = end - start;
>    iomem->current = 0;
> +
> +#if USING_GUILE_BEFORE_2_2
> +  int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
>    if (buffered)
>      {
>        iomem->read_buf_size = default_read_buf_size;
> @@ -954,7 +1230,7 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
>        iomem->write_buf_size = 1;
>      }
>  
> -  pt = SCM_PTAB_ENTRY (port);
> +  scm_t_port *pt = SCM_PTAB_ENTRY (port);
>    /* Match the expectation of `binary-port?'.  */
>    pt->encoding = NULL;
>    pt->rw_random = 1;
> @@ -973,74 +1249,11 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
>    pt->read_pos = pt->read_end = pt->read_buf;
>    pt->write_pos = pt->write_buf;
>    pt->write_end = pt->write_buf + pt->write_buf_size;
> +#endif
>  
>    SCM_SETSTREAM (port, iomem);
>  }
>  
> -/* Re-initialize a memory port, updating its read/write buffer sizes.
> -   An exception is thrown if the port is unbuffered.
> -   TODO: Allow switching buffered/unbuffered.
> -   An exception is also thrown if data is still buffered, except in the case
> -   where the buffer size isn't changing (since that's just a nop).  */
> -
> -static void
> -ioscm_reinit_memory_port (SCM port, size_t read_buf_size,
> -			  size_t write_buf_size, const char *func_name)
> -{
> -  scm_t_port *pt = SCM_PTAB_ENTRY (port);
> -  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
> -
> -  gdb_assert (read_buf_size >= min_memory_port_buf_size
> -	      && read_buf_size <= max_memory_port_buf_size);
> -  gdb_assert (write_buf_size >= min_memory_port_buf_size
> -	      && write_buf_size <= max_memory_port_buf_size);
> -
> -  /* First check if the port is unbuffered.  */
> -
> -  if (pt->read_buf == &pt->shortbuf)
> -    {
> -      gdb_assert (pt->write_buf == &pt->shortbuf);
> -      scm_misc_error (func_name, _("port is unbuffered: ~a"),
> -		      scm_list_1 (port));
> -    }
> -
> -  /* Next check if anything is buffered.  */
> -
> -  if (read_buf_size != pt->read_buf_size
> -      && pt->read_end != pt->read_buf)
> -    {
> -      scm_misc_error (func_name, _("read buffer not empty: ~a"),
> -		      scm_list_1 (port));
> -    }
> -
> -  if (write_buf_size != pt->write_buf_size
> -      && pt->write_pos != pt->write_buf)
> -    {
> -      scm_misc_error (func_name, _("write buffer not empty: ~a"),
> -		      scm_list_1 (port));
> -    }
> -
> -  /* Now we can update the buffer sizes, but only if the size has changed.  */
> -
> -  if (read_buf_size != pt->read_buf_size)
> -    {
> -      iomem->read_buf_size = read_buf_size;
> -      pt->read_buf_size = read_buf_size;
> -      xfree (pt->read_buf);
> -      pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
> -      pt->read_pos = pt->read_end = pt->read_buf;
> -    }
> -
> -  if (write_buf_size != pt->write_buf_size)
> -    {
> -      iomem->write_buf_size = write_buf_size;
> -      pt->write_buf_size = write_buf_size;
> -      xfree (pt->write_buf);
> -      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;
> -    }
> -}
>  
>  /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
>     Return a port that can be used for reading and writing memory.
> @@ -1124,7 +1337,11 @@ gdbscm_open_memory (SCM rest)
>  static int
>  gdbscm_is_memory_port (SCM obj)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    return !SCM_IMP (obj) && (SCM_TYP16 (obj) == memory_port_desc);
> +#else
> +  return SCM_PORTP (obj) && (SCM_PORT_TYPE (obj) == memory_port_desc);
> +#endif
>  }
>  
>  /* (memory-port? obj) -> boolean */
> @@ -1155,6 +1372,7 @@ gdbscm_memory_port_range (SCM port)
>  static SCM
>  gdbscm_memory_port_read_buffer_size (SCM port)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    ioscm_memory_port *iomem;
>  
>    SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
> @@ -1162,6 +1380,9 @@ gdbscm_memory_port_read_buffer_size (SCM port)
>  
>    iomem = (ioscm_memory_port *) SCM_STREAM (port);
>    return scm_from_uint (iomem->read_buf_size);
> +#else
> +  return scm_from_uint (0);
> +#endif
>  }
>  
>  /* (set-memory-port-read-buffer-size! port size) -> unspecified
> @@ -1171,6 +1392,7 @@ gdbscm_memory_port_read_buffer_size (SCM port)
>  static SCM
>  gdbscm_set_memory_port_read_buffer_size_x (SCM port, SCM size)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    ioscm_memory_port *iomem;
>  
>    SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
> @@ -1190,6 +1412,9 @@ gdbscm_set_memory_port_read_buffer_size_x (SCM port, SCM size)
>  			    FUNC_NAME);
>  
>    return SCM_UNSPECIFIED;
> +#else
> +  return scm_setvbuf (port, scm_from_utf8_symbol ("block"), size);
> +#endif
>  }
>  
>  /* (memory-port-write-buffer-size port) -> integer */
> @@ -1197,6 +1422,7 @@ gdbscm_set_memory_port_read_buffer_size_x (SCM port, SCM size)
>  static SCM
>  gdbscm_memory_port_write_buffer_size (SCM port)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    ioscm_memory_port *iomem;
>  
>    SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
> @@ -1204,6 +1430,9 @@ gdbscm_memory_port_write_buffer_size (SCM port)
>  
>    iomem = (ioscm_memory_port *) SCM_STREAM (port);
>    return scm_from_uint (iomem->write_buf_size);
> +#else
> +  return scm_from_uint (0);
> +#endif
>  }
>  
>  /* (set-memory-port-write-buffer-size! port size) -> unspecified
> @@ -1213,6 +1442,7 @@ gdbscm_memory_port_write_buffer_size (SCM port)
>  static SCM
>  gdbscm_set_memory_port_write_buffer_size_x (SCM port, SCM size)
>  {
> +#if USING_GUILE_BEFORE_2_2
>    ioscm_memory_port *iomem;
>  
>    SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
> @@ -1232,6 +1462,9 @@ gdbscm_set_memory_port_write_buffer_size_x (SCM port, SCM size)
>  			    FUNC_NAME);
>  
>    return SCM_UNSPECIFIED;
> +#else
> +  return scm_setvbuf (port, scm_from_utf8_symbol ("block"), size);
> +#endif
>  }
>  \f
>  /* Initialize gdb ports.  */
> diff --git a/gdb/testsuite/gdb.guile/scm-error.exp b/gdb/testsuite/gdb.guile/scm-error.exp
> index 799bfe5db0..f073200b6e 100644
> --- a/gdb/testsuite/gdb.guile/scm-error.exp
> +++ b/gdb/testsuite/gdb.guile/scm-error.exp
> @@ -34,7 +34,7 @@ set remote_guile_file_2 [gdb_remote_download host \
>  			     ${srcdir}/${subdir}/${testfile}-2.scm]
>  
>  gdb_test "source $remote_guile_file_1" \
> -    "(ERROR: )?In procedure \[+\]: Wrong type: #f.*" \
> +    "(ERROR: )?In procedure \[+\]: Wrong type.*: #f.*" \
>      "error loading scm file caught"
>  
>  gdb_test "p 1" " = 1" "no delayed error"
> diff --git a/gdb/testsuite/gdb.guile/scm-ports.exp b/gdb/testsuite/gdb.guile/scm-ports.exp
> index b2835ddc75..47da3d43d3 100644
> --- a/gdb/testsuite/gdb.guile/scm-ports.exp
> +++ b/gdb/testsuite/gdb.guile/scm-ports.exp
> @@ -154,7 +154,7 @@ test_mem_port_rw unbuffered
>  
>  # Test zero-length memory ports.
>  
> -gdb_test_no_output "guile (define zero-mem-port (open-memory #:start 0 #:size 0 #:mode \"r+\"))" \
> +gdb_test_no_output "guile (define zero-mem-port (open-memory #:start 0 #:size 0 #:mode \"r0+\"))" \
>      "create zero length memory port"
>  gdb_test "guile (print (read-char zero-mem-port))" \
>      "= #<eof>"
> 

  parent reply	other threads:[~2020-06-12 14:14 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-12 13:27 [PATCH 0/2] Add support for Guile 3.0 and 2.2 Ludovic Courtès
2020-06-12 13:27 ` [PATCH 1/2] guile: Add support for Guile 2.2 Ludovic Courtès
2020-06-12 13:50   ` Eli Zaretskii
2020-06-12 14:04     ` Ludovic Courtès
2020-06-13  6:44       ` Eli Zaretskii
2020-06-13 15:04         ` Ludovic Courtès
2020-06-15 15:14           ` [PATCH v2 0/2] Add support for Guile 3.0 and 2.2 Ludovic Courtès
2020-06-15 15:14             ` [PATCH v2 1/2] guile: Add support for Guile 2.2 Ludovic Courtès
2020-06-15 17:00               ` Eli Zaretskii
2020-06-18 20:31                 ` Tom Tromey
2020-06-19  6:08                   ` Eli Zaretskii
2020-06-19  7:37                     ` Ludovic Courtès
2020-06-26  8:13                       ` [PATCH v3 0/2] Add support for Guile 3.0 and 2.2 Ludovic Courtès
2020-06-26  8:13                         ` [PATCH v3 1/2] guile: Add support for Guile 2.2 Ludovic Courtès
2020-06-26 10:23                           ` Eli Zaretskii
2020-06-28 14:20                             ` Ludovic Courtès
2020-06-28 14:25                               ` [PATCH v4 " Ludovic Courtès
2020-06-28 16:40                                 ` Eli Zaretskii
2020-07-03  0:31                                 ` Simon Marchi
2020-07-03  7:06                                   ` Ludovic Courtès
2020-07-18 19:00                                   ` Joel Brobecker
2020-07-19 15:45                                     ` Simon Marchi
2020-07-20  8:05                                       ` Ludovic Courtès
2020-07-20 15:01                                         ` Simon Marchi
2020-07-21 21:10                                           ` Ludovic Courtès
2020-06-28 14:25                               ` [PATCH v4 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
2020-06-28 16:38                               ` [PATCH v3 1/2] guile: Add support for Guile 2.2 Eli Zaretskii
2020-06-28 16:51                                 ` Ludovic Courtès
2020-07-02 12:57                               ` [PING] Add support for Guile 2.2/3.0 Ludovic Courtès
2020-07-13 15:36                                 ` Tom Tromey
2020-06-26  8:13                         ` [PATCH v3 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
2020-06-26 10:13                           ` Eli Zaretskii
2020-06-15 15:14             ` [PATCH v2 " Ludovic Courtès
2020-06-12 14:14   ` Tom de Vries [this message]
2020-06-12 14:36     ` [PATCH 1/2] guile: Add support for Guile 2.2 Ludovic Courtès
2020-06-12 13:27 ` [PATCH 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
2020-06-15 15:02   ` Tom Tromey
2020-06-15 15:17     ` Ludovic Courtès
2020-06-17 16:58     ` Ludovic Courtès
2020-06-17 17:21       ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=513a8d32-70c0-939c-ccbb-f57c2165f25d@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    --cc=ludo@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).