public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Add support for Guile 3.0 and 2.2
@ 2020-06-12 13:27 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:27 ` [PATCH 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
  0 siblings, 2 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-12 13:27 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

Hello,

This is a long overdue update to the Guile bindings to support versions
2.2 (legacy) and 3.0 (current stable), in addition to the old 2.0.

For the record, the last 2.0 release was made in February 2017, but I
think keeping 2.0 support for a while will make the transition smoother.

Most of the work is about updating code that uses Guile’s I/O ports to
the new API that was introduced in Guile 2.2.  The new API leads to more
concise and less error-prone code but of course, since we’re also keeping
the 2.0 version, we’d only adding code at this point.

Tested with Guile 3.0.2, 2.2.7, and 2.0.14 on x86_64-linux-gnu (GNU Guix).
Specifically, this passes for all three versions:

  make check -C gdb TESTS=gdb.guile/*.exp

Let me know what you think!

Thanks,
Ludo’.

Ludovic Courtès (2):
  guile: Add support for Guile 2.2.
  guile: Add support for Guile 3.0.

 gdb/configure                            |   2 +-
 gdb/configure.ac                         |   2 +-
 gdb/doc/guile.texi                       |  23 +-
 gdb/guile/scm-math.c                     |   4 +-
 gdb/guile/scm-ports.c                    | 545 ++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp    |   2 +-
 gdb/testsuite/gdb.guile/scm-ports.exp    |   2 +-
 gdb/testsuite/gdb.guile/source2.scm      |   2 +-
 gdb/testsuite/gdb.guile/types-module.exp |   6 +-
 9 files changed, 400 insertions(+), 188 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 1/2] guile: Add support for Guile 2.2.
  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 ` Ludovic Courtès
  2020-06-12 13:50   ` Eli Zaretskii
  2020-06-12 14:14   ` [PATCH 1/2] guile: Add support for Guile 2.2 Tom de Vries
  2020-06-12 13:27 ` [PATCH 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
  1 sibling, 2 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-12 13:27 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

This primarily updates code that uses the I/O port API of Guile.

gdb/ChangeLog:

	* 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>"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 2/2] guile: Add support for Guile 3.0.
  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:27 ` Ludovic Courtès
  2020-06-15 15:02   ` Tom Tromey
  1 sibling, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-12 13:27 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

gdb/ChangeLog:

	* guile/scm-math.c (vlscm_integer_fits_p): Use 'uintmax_t'
	and 'intmax_t' instead of 'scm_t_uintmax' and 'scm_t_intmax',
	which are deprecated in Guile 3.0.
	* testsuite/gdb.guile/source2.scm: Add #f first argument to
	'format'.
	* testsuite/gdb.guile/types-module.exp: Remove "ERROR:" from
	regexps since Guile 3.0 no longer prints that.
	* configure.ac (try_guile_versions): Add "guile-3.0".
	* configure (try_guile_versions): Regenerate.
	* doc/guile.texi (Guile Introduction): Mention Guile 3.0.
---
 gdb/configure                            | 2 +-
 gdb/configure.ac                         | 2 +-
 gdb/doc/guile.texi                       | 2 +-
 gdb/guile/scm-math.c                     | 4 ++--
 gdb/testsuite/gdb.guile/source2.scm      | 2 +-
 gdb/testsuite/gdb.guile/types-module.exp | 6 +++---
 6 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/gdb/configure b/gdb/configure
index bd12695291..5ad1e53ac4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10954,7 +10954,7 @@ fi
 
 
 
-try_guile_versions="guile-2.2 guile-2.0"
+try_guile_versions="guile-3.0 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 87afc26581..d8cef1e914 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.2 guile-2.0"
+try_guile_versions="guile-3.0 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 0e6c74ef8b..45c8f3f197 100644
--- a/gdb/doc/guile.texi
+++ b/gdb/doc/guile.texi
@@ -38,7 +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.2 or 2.0.
+@value{GDBN} requires Guile version 3.0, 2.2, or 2.0.
 
 @cindex guile scripts directory
 Guile scripts used by @value{GDBN} should be installed in
diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c
index 7c63fa2ae0..419f5099bf 100644
--- a/gdb/guile/scm-math.c
+++ b/gdb/guile/scm-math.c
@@ -578,7 +578,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       ULONGEST max;
 
       /* If scm_is_unsigned_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
+      if (TYPE_LENGTH (type) > sizeof (uintmax_t))
 	return 0;
       get_unsigned_type_max (type, &max);
       return scm_is_unsigned_integer (obj, 0, max);
@@ -588,7 +588,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       LONGEST min, max;
 
       /* If scm_is_signed_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_intmax))
+      if (TYPE_LENGTH (type) > sizeof (intmax_t))
 	return 0;
       get_signed_type_minmax (type, &min, &max);
       return scm_is_signed_integer (obj, min, max);
diff --git a/gdb/testsuite/gdb.guile/source2.scm b/gdb/testsuite/gdb.guile/source2.scm
index 39638053d9..c39f03801a 100644
--- a/gdb/testsuite/gdb.guile/source2.scm
+++ b/gdb/testsuite/gdb.guile/source2.scm
@@ -15,5 +15,5 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-(display (format "y~As" "e"))
+(display (format #f "y~As" "e"))
 (newline)
diff --git a/gdb/testsuite/gdb.guile/types-module.exp b/gdb/testsuite/gdb.guile/types-module.exp
index 5a631dca8e..8ced6fbffb 100644
--- a/gdb/testsuite/gdb.guile/types-module.exp
+++ b/gdb/testsuite/gdb.guile/types-module.exp
@@ -44,7 +44,7 @@ gdb_test "guile (print (type-has-field-deep? d \"base_member\"))" \
     "= #t" "type-has-field-deep? member in baseclass"
 
 gdb_test "guile (print (type-has-field-deep? (lookup-type \"int\") \"base_member\"))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
     "type-has-field-deep? from int"
 
 gdb_scm_test_silent_cmd "guile (define enum-htab (make-enum-hashtable (lookup-type \"enum_type\")))" \
@@ -54,9 +54,9 @@ gdb_test "guile (print (hash-ref enum-htab \"B\"))" \
     "= 1" "verify make-enum-hashtable"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable #f))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
+    "Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
     "make-enum-hashtable from #f"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable (lookup-type \"int\")))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
     "make-enum-hashtable from int"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  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-12 14:14   ` [PATCH 1/2] guile: Add support for Guile 2.2 Tom de Vries
  1 sibling, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-12 13:50 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Date: Fri, 12 Jun 2020 15:27:09 +0200
> Cc: Ludovic Courtès <ludo@gnu.org>
> 
> This primarily updates code that uses the I/O port API of Guile.
> 
> 	* 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/doc/ has a separate ChangeLog file; please use that to describe
changes in the manual.

More importantly, I don't understand why we'd want to remove the
documentation of these functions.  Are we removing the functions as
well (I don't think I saw the code being removed)?  If we are not
removing the functions, why remove their docs?  You say that the
corresponding Guile functionality is superseded by setvbuf, but
doesn't it mean the GDB-specific capability based on that will be
rewritten using the new Guile features, and we can continue supporting
them?

Sorry for my confusion; perhaps more detailed log messages would have
prevented that.

Also, does any of this need to be called out in NEWS?

Thanks.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  2020-06-12 13:50   ` Eli Zaretskii
@ 2020-06-12 14:04     ` Ludovic Courtès
  2020-06-13  6:44       ` Eli Zaretskii
  0 siblings, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-12 14:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Hello,

Eli Zaretskii <eliz@gnu.org> skribis:

>> From: Ludovic Courtès <ludo@gnu.org>
>> Date: Fri, 12 Jun 2020 15:27:09 +0200
>> Cc: Ludovic Courtès <ludo@gnu.org>
>> 
>> This primarily updates code that uses the I/O port API of Guile.
>> 
>> 	* 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/doc/ has a separate ChangeLog file; please use that to describe
> changes in the manual.

Oops, will do.

> More importantly, I don't understand why we'd want to remove the
> documentation of these functions.  Are we removing the functions as
> well (I don't think I saw the code being removed)?  If we are not
> removing the functions, why remove their docs?  You say that the
> corresponding Guile functionality is superseded by setvbuf, but
> doesn't it mean the GDB-specific capability based on that will be
> rewritten using the new Guile features, and we can continue supporting
> them?

These four functions are not used in tests, in documented examples, nor
in Guile’s own GDB plugin.

‘setvbuf’ is not entirely a drop-in replacement because: (1) it doesn’t
allow you to query a port’s buffer size, only to change it, and (2) it
doesn’t distinguish between the read and write buffers.  Consequently,
these functions cannot be implemented on 2.2/3.0, or at least not
easily.

Since they are unused, and I can’t see a valid use case for those over
‘setvbuf’, I chose to remove them from the manual as a way to deprecate
them.

WDYT?

> Also, does any of this need to be called out in NEWS?

Oh sure.  Should that go in a separate commit or in the same?

I’ll wait for additional feedback and send a v2 afterwards, if that’s
fine with you.

Thanks for the quick reply,
Ludo’.

PS: I lost Git access to sourceware.org some years ago because my
    registered SSH key was DSA, IIRC.  Should I apply to restore it?
    What’s the procedure?

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  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:14   ` Tom de Vries
  2020-06-12 14:36     ` Ludovic Courtès
  1 sibling, 1 reply; 40+ messages in thread
From: Tom de Vries @ 2020-06-12 14:14 UTC (permalink / raw)
  To: Ludovic Courtès, gdb-patches

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>"
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  2020-06-12 14:14   ` [PATCH 1/2] guile: Add support for Guile 2.2 Tom de Vries
@ 2020-06-12 14:36     ` Ludovic Courtès
  0 siblings, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-12 14:36 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gdb-patches

Tom de Vries <tdevries@suse.de> skribis:

> 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.

Yes, thanks for the heads-up!  I’ll add it to the commit log.

Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  2020-06-12 14:04     ` Ludovic Courtès
@ 2020-06-13  6:44       ` Eli Zaretskii
  2020-06-13 15:04         ` Ludovic Courtès
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-13  6:44 UTC (permalink / raw)
  To: Ludovic Courtès, Doug Evans; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Cc: gdb-patches@sourceware.org
> Date: Fri, 12 Jun 2020 16:04:22 +0200
> 
> > More importantly, I don't understand why we'd want to remove the
> > documentation of these functions.  Are we removing the functions as
> > well (I don't think I saw the code being removed)?  If we are not
> > removing the functions, why remove their docs?  You say that the
> > corresponding Guile functionality is superseded by setvbuf, but
> > doesn't it mean the GDB-specific capability based on that will be
> > rewritten using the new Guile features, and we can continue supporting
> > them?
> 
> These four functions are not used in tests, in documented examples, nor
> in Guile’s own GDB plugin.
> 
> ‘setvbuf’ is not entirely a drop-in replacement because: (1) it doesn’t
> allow you to query a port’s buffer size, only to change it, and (2) it
> doesn’t distinguish between the read and write buffers.  Consequently,
> these functions cannot be implemented on 2.2/3.0, or at least not
> easily.
> 
> Since they are unused, and I can’t see a valid use case for those over
> ‘setvbuf’, I chose to remove them from the manual as a way to deprecate
> them.
> 
> WDYT?

So what is the plan wrt GDB accessing memory of the inferior via
Guile?  Specifically, which parts of the features described in "Memory
Ports in Guile" in the manual will continue be supported with Guile 2.2
and later?  can we make at least the accessors work with those newer
versions of Guile?

In any case, I don't like the method of deprecating features by
removing their documentation.  I think we should say explicitly in
that section which methods are deprecated and why.  The fact that they
are deprecated should also be in NEWS.  This all assumes that other
GDB developers agree that they are not needed; I don't have enough
relevant experience to have an opinion.  Maybe Doug (CC'ed) could
chime in.

I also think that Guile should provide proper replacements for the
functionality you mentioned, because evidently at least GDB thought
they could be put to good use.  But this is outside of the scope of
GDB maintenance, something for the Guile developers to consider.

> > Also, does any of this need to be called out in NEWS?
> 
> Oh sure.  Should that go in a separate commit or in the same?

The same is better.

> PS: I lost Git access to sourceware.org some years ago because my
>     registered SSH key was DSA, IIRC.  Should I apply to restore it?
>     What’s the procedure?

I think you should write to overseers@sourceware.org and ask them what
to do.

Thanks.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/2] guile: Add support for Guile 2.2.
  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
  0 siblings, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-13 15:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Doug Evans, gdb-patches

Hi,

In the meantime I found that Doug had already done that work in 2018:

  https://sourceware.org/bugzilla/show_bug.cgi?id=21104#c8

Too bad I didn’t notice earlier.  I’ll check if there are significant
differences between the two.

Eli Zaretskii <eliz@gnu.org> skribis:

>> These four functions are not used in tests, in documented examples, nor
>> in Guile’s own GDB plugin.
>> 
>> ‘setvbuf’ is not entirely a drop-in replacement because: (1) it doesn’t
>> allow you to query a port’s buffer size, only to change it, and (2) it
>> doesn’t distinguish between the read and write buffers.  Consequently,
>> these functions cannot be implemented on 2.2/3.0, or at least not
>> easily.
>> 
>> Since they are unused, and I can’t see a valid use case for those over
>> ‘setvbuf’, I chose to remove them from the manual as a way to deprecate
>> them.
>> 
>> WDYT?
>
> So what is the plan wrt GDB accessing memory of the inferior via
> Guile?  Specifically, which parts of the features described in "Memory
> Ports in Guile" in the manual will continue be supported with Guile 2.2
> and later?  can we make at least the accessors work with those newer
> versions of Guile?

Yes, everything remains supported, it’s just setting read/write
buffering size in that way that is unsupported.

In most cases, I suspect one just wants an unbuffered memory port
anyway.

> In any case, I don't like the method of deprecating features by
> removing their documentation.  I think we should say explicitly in
> that section which methods are deprecated and why.  The fact that they
> are deprecated should also be in NEWS.  This all assumes that other
> GDB developers agree that they are not needed; I don't have enough
> relevant experience to have an opinion.  Maybe Doug (CC'ed) could
> chime in.

Yes, I think we should mention it in ‘NEWS’.

> I also think that Guile should provide proper replacements for the
> functionality you mentioned, because evidently at least GDB thought
> they could be put to good use.  But this is outside of the scope of
> GDB maintenance, something for the Guile developers to consider.

Right.  For I/O ports in general, I don’t think this functionality would
be very useful.  (Even for GDB memory ports, I think ‘setvbuf’ is
enough.)

>> > Also, does any of this need to be called out in NEWS?
>> 
>> Oh sure.  Should that go in a separate commit or in the same?
>
> The same is better.

Sounds good.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/2] guile: Add support for Guile 3.0.
  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
  0 siblings, 2 replies; 40+ messages in thread
From: Tom Tromey @ 2020-06-15 15:02 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

>>>>> "Ludovic" == Ludovic Courtès <ludo@gnu.org> writes:

Ludovic> 	* testsuite/gdb.guile/source2.scm: Add #f first argument to
Ludovic> 	'format'.
Ludovic> 	* testsuite/gdb.guile/types-module.exp: Remove "ERROR:" from
Ludovic> 	regexps since Guile 3.0 no longer prints that.

testsuite/ (unfortunately IMO) has its own ChangeLog.

Ludovic>        /* If scm_is_unsigned_integer can't work with this type, just punt.  */
Ludovic> -      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
Ludovic> +      if (TYPE_LENGTH (type) > sizeof (uintmax_t))

I suppose these can't differ in Guile 2.0 or 2.2?

Anyway, this patch seems fine to me.

Tom

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 0/2] Add support for Guile 3.0 and 2.2
  2020-06-13 15:04         ` Ludovic Courtès
@ 2020-06-15 15:14           ` 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 15:14             ` [PATCH v2 " Ludovic Courtès
  0 siblings, 2 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-15 15:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Doug Evans, Ludovic Courtès

Hi,

Here’s v2 of these patches.  Changes since v1:

  • Add natural buffer size function as implemented by Doug
    in <https://sourceware.org/legacy-ml/gdb-patches/2018-01/msg00438.html>.
    That, in turn, means we no longer need to open ‘zero-mem-port’
    in ‘gdb.guile/scm-ports.exp’ as explicitly unbuffered like I
    did in v1.  (I added Doug as co-author in the ChangeLog entry.)

  • Add NEWS entry, documenting procedure deprecation.

  • Separate ChangeLog entry for gdb/doc, and claim PR gdb/21104.

Doug, I feel stupid for redoing the work you had done two years ago—I’ll do
my homework better next time!—but hopefully we’ll soon be done with it.

Thanks,
Ludo’.

Ludovic Courtès (2):
  guile: Add support for Guile 2.2.
  guile: Add support for Guile 3.0.

 gdb/NEWS                                 |  10 +
 gdb/configure                            |   2 +-
 gdb/configure.ac                         |   2 +-
 gdb/doc/guile.texi                       |  23 +-
 gdb/guile/scm-math.c                     |   4 +-
 gdb/guile/scm-ports.c                    | 619 ++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp    |   2 +-
 gdb/testsuite/gdb.guile/source2.scm      |   2 +-
 gdb/testsuite/gdb.guile/types-module.exp |   6 +-
 9 files changed, 469 insertions(+), 201 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 1/2] guile: Add support for Guile 2.2.
  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             ` Ludovic Courtès
  2020-06-15 17:00               ` Eli Zaretskii
  2020-06-15 15:14             ` [PATCH v2 " Ludovic Courtès
  1 sibling, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-15 15:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Doug Evans, Ludovic Courtès

This primarily updates code that uses the I/O port API of Guile.

gdb/ChangeLog
2020-06-15  Ludovic Courtès  <ludo@gnu.org>
            Doug Evans  <dje@google.com>

	PR gdb/21104
	* 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 *'.
	(natural_buffer_size) [!USING_GUILE_BEFORE_2_2]: New variable.
	(ioscm_open_port) [USING_GUILE_BEFORE_2_2]: Add 'stream'
	parameter and honor it.  Update callers.
	(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.
	(gdbscm_get_natural_buffer_sizes) [!USING_GUILE_BEFORE_2_2]: New
	function.
	(ioscm_init_memory_port): Remove.
	(ioscm_init_memory_port_stream): New function
	(ioscm_init_memory_port_buffers) [USING_GUILE_BEFORE_2_2]: New
	function.
	(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.
	* configure.ac (try_guile_versions): Add "guile-2.2".
	* configure: Regenerate.
	* NEWS: Add entry.

gdb/doc/ChangeLog
2020-06-15  Ludovic Courtès  <ludo@gnu.org>

	* 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/NEWS                              |  10 +
 gdb/configure                         |   2 +-
 gdb/configure.ac                      |   2 +-
 gdb/doc/guile.texi                    |  23 +-
 gdb/guile/scm-ports.c                 | 619 +++++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp |   2 +-
 6 files changed, 463 insertions(+), 195 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 9ef85ab3ca..d8a9de4179 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -83,6 +83,16 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
   ** Commands written in Python can be in the "TUI" help class by
      registering with the new constant gdb.COMMAND_TUI.
 
+* Guile API
+
+  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+
+  ** Procedures 'memory-port-read-buffer-size',
+     'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
+     and 'set-memory-port-write-buffer-size!' are deprecated.  When
+     using Guile 2.2 and later, users who need to control the size of
+     a memory port's internal buffer can use the 'setvbuf' procedure.
+
 *** Changes in GDB 9
 
 * 'thread-exited' event is now available in the annotations interface.
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..36b339ecff 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,11 +115,17 @@ 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";
 
+#if USING_GUILE_BEFORE_2_2
+
 /* The default amount of memory to fetch for each read/write request.
    Scheme ports don't provide a way to specify the size of a read,
    which is important to us to minimize the number of inferior interactions,
@@ -123,16 +142,24 @@ static const unsigned max_memory_port_buf_size = 4096;
 /* "out of range" error message for buf sizes.  */
 static char *out_of_range_buf_size;
 
+#else
+
+/* The maximum values to use for get_natural_buffer_sizes.  */
+static const unsigned natural_buf_size = 16;
+
+#endif
+
 /* Keywords used by open-memory.  */
 static SCM mode_keyword;
 static SCM start_keyword;
 static SCM size_keyword;
 \f
-/* Helper to do the low level work of opening a port.
-   Newer versions of Guile (2.1.x) have scm_c_make_port.  */
+/* Helper to do the low level work of opening a port.  */
+
+#if USING_GUILE_BEFORE_2_2
 
 static SCM
-ioscm_open_port (scm_t_bits port_type, long mode_bits)
+ioscm_open_port (scm_t_bits port_type, long mode_bits, scm_t_bits stream)
 {
   SCM port;
 
@@ -143,6 +170,7 @@ ioscm_open_port (scm_t_bits port_type, long mode_bits)
   port = scm_new_port_table_entry (port_type);
 
   SCM_SET_CELL_TYPE (port, port_type | mode_bits);
+  SCM_SETSTREAM (port, stream);
 
 #if 0 /* TODO: Guile doesn't export this.  What to do?  */
   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
@@ -150,9 +178,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, scm_t_bits stream)
+{
+  return scm_c_make_port (port_type, mode_bits, stream);
+}
+
+#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 +303,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 +343,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 +408,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 +435,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 +468,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
@@ -389,7 +512,7 @@ ioscm_make_gdb_stdio_port (int fd)
     }
 
   mode_bits = scm_mode_bits ((char *) mode_str);
-  port = ioscm_open_port (stdio_port_desc, mode_bits);
+  port = ioscm_open_port (stdio_port_desc, mode_bits, 0);
 
   scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
 
@@ -403,9 +526,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 +696,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 +791,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 +883,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 +981,178 @@ 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 */
+
+/* The semantics get weird if the buffer size is larger than the port range,
+   so provide a better default buffer size.  */
+
+static void
+gdbscm_get_natural_buffer_sizes (SCM port, size_t *read_size,
+				 size_t *write_size)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  size_t size = natural_buf_size;
+  if (iomem != NULL && iomem->size < size)
+    size = iomem->size;
+  *read_size = *write_size = size;
+}
+
+/* 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);
+  int rc;
+
+  rc = ioscm_lseek_address (iomem, offset, whence);
+  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 iomem->current;
+}
+
+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 +1164,23 @@ 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);
+#else
+  scm_set_port_get_natural_buffer_sizes (memory_port_desc,
+					 gdbscm_get_natural_buffer_sizes);
+#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);
 }
 
@@ -922,17 +1221,13 @@ ioscm_parse_mode_bits (const char *func_name, const char *mode)
   return mode_bits;
 }
 
-/* Helper for gdbscm_open_memory to finish initializing the port.
-   The port has address range [start,end).
-   This means that address of 0xff..ff is not accessible.
-   I can live with that.  */
+/* Return the memory object to be used as a "stream" associated with a memory
+   port for the START--END range.  */
 
-static void
-ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
+static ioscm_memory_port *
+ioscm_init_memory_port_stream (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 +1238,23 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
   iomem->end = end;
   iomem->size = end - start;
   iomem->current = 0;
+
+  return iomem;
+}
+
+#if USING_GUILE_BEFORE_2_2
+
+/* Helper for gdbscm_open_memory to finish initializing the port.
+   The port has address range [start,end).
+   This means that address of 0xff..ff is not accessible.
+   I can live with that.  */
+
+static void
+ioscm_init_memory_port_buffers (SCM port)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
   if (buffered)
     {
       iomem->read_buf_size = default_read_buf_size;
@@ -954,7 +1266,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 +1285,9 @@ 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;
-
-  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;
-    }
-}
+#endif
 
 /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
    Return a port that can be used for reading and writing memory.
@@ -1109,9 +1356,19 @@ gdbscm_open_memory (SCM rest)
 
   mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode);
 
-  port = ioscm_open_port (memory_port_desc, mode_bits);
+  /* Edge case: empty range -> unbuffered.
+     There's no need to disallow empty ranges, but we need an unbuffered port
+     to get the semantics right.  */
+  if (size == 0)
+    mode_bits |= SCM_BUF0;
+
+  auto stream = ioscm_init_memory_port_stream (start, end);
+  port = ioscm_open_port (memory_port_desc, mode_bits,
+			  (scm_t_bits) stream);
 
-  ioscm_init_memory_port (port, start, end);
+#if USING_GUILE_BEFORE_2_2
+  ioscm_init_memory_port_buffers (port);
+#endif
 
   scm_dynwind_end ();
 
@@ -1124,7 +1381,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 +1416,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 +1424,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 +1436,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 +1456,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 +1466,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 +1474,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 +1486,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 +1506,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.  */
@@ -1366,9 +1643,11 @@ gdbscm_initialize_ports (void)
   start_keyword = scm_from_latin1_keyword ("start");
   size_keyword = scm_from_latin1_keyword ("size");
 
+#if USING_GUILE_BEFORE_2_2
   /* Error message text for "out of range" memory port buffer sizes.  */
 
   out_of_range_buf_size = xstrprintf ("size not between %u - %u",
 				      min_memory_port_buf_size,
 				      max_memory_port_buf_size);
+#endif
 }
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"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 2/2] guile: Add support for Guile 3.0.
  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 15:14             ` Ludovic Courtès
  1 sibling, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-15 15:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Doug Evans, Ludovic Courtès

gdb/ChangeLog
2020-06-15  Ludovic Courtès  <ludo@gnu.org>

	* guile/scm-math.c (vlscm_integer_fits_p): Use 'uintmax_t'
	and 'intmax_t' instead of 'scm_t_uintmax' and 'scm_t_intmax',
	which are deprecated in Guile 3.0.
	* testsuite/gdb.guile/source2.scm: Add #f first argument to
	'format'.
	* testsuite/gdb.guile/types-module.exp: Remove "ERROR:" from
	regexps since Guile 3.0 no longer prints that.
	* configure.ac (try_guile_versions): Add "guile-3.0".
	* configure (try_guile_versions): Regenerate.
	* NEWS: Update entry.

gdb/doc/ChangeLog
2020-06-15  Ludovic Courtès  <ludo@gnu.org>

	* doc/guile.texi (Guile Introduction): Mention Guile 3.0.
---
 gdb/NEWS                                 | 2 +-
 gdb/configure                            | 2 +-
 gdb/configure.ac                         | 2 +-
 gdb/doc/guile.texi                       | 2 +-
 gdb/guile/scm-math.c                     | 4 ++--
 gdb/testsuite/gdb.guile/source2.scm      | 2 +-
 gdb/testsuite/gdb.guile/types-module.exp | 6 +++---
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index d8a9de4179..23705e1c65 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -85,7 +85,7 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
 
 * Guile API
 
-  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+  ** GDB can now be built with GNU Guile 3.0 and 2.2 in addition to 2.0.
 
   ** Procedures 'memory-port-read-buffer-size',
      'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
diff --git a/gdb/configure b/gdb/configure
index bd12695291..5ad1e53ac4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10954,7 +10954,7 @@ fi
 
 
 
-try_guile_versions="guile-2.2 guile-2.0"
+try_guile_versions="guile-3.0 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 87afc26581..d8cef1e914 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.2 guile-2.0"
+try_guile_versions="guile-3.0 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 0e6c74ef8b..45c8f3f197 100644
--- a/gdb/doc/guile.texi
+++ b/gdb/doc/guile.texi
@@ -38,7 +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.2 or 2.0.
+@value{GDBN} requires Guile version 3.0, 2.2, or 2.0.
 
 @cindex guile scripts directory
 Guile scripts used by @value{GDBN} should be installed in
diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c
index 7c63fa2ae0..419f5099bf 100644
--- a/gdb/guile/scm-math.c
+++ b/gdb/guile/scm-math.c
@@ -578,7 +578,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       ULONGEST max;
 
       /* If scm_is_unsigned_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
+      if (TYPE_LENGTH (type) > sizeof (uintmax_t))
 	return 0;
       get_unsigned_type_max (type, &max);
       return scm_is_unsigned_integer (obj, 0, max);
@@ -588,7 +588,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       LONGEST min, max;
 
       /* If scm_is_signed_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_intmax))
+      if (TYPE_LENGTH (type) > sizeof (intmax_t))
 	return 0;
       get_signed_type_minmax (type, &min, &max);
       return scm_is_signed_integer (obj, min, max);
diff --git a/gdb/testsuite/gdb.guile/source2.scm b/gdb/testsuite/gdb.guile/source2.scm
index 39638053d9..c39f03801a 100644
--- a/gdb/testsuite/gdb.guile/source2.scm
+++ b/gdb/testsuite/gdb.guile/source2.scm
@@ -15,5 +15,5 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-(display (format "y~As" "e"))
+(display (format #f "y~As" "e"))
 (newline)
diff --git a/gdb/testsuite/gdb.guile/types-module.exp b/gdb/testsuite/gdb.guile/types-module.exp
index 5a631dca8e..8ced6fbffb 100644
--- a/gdb/testsuite/gdb.guile/types-module.exp
+++ b/gdb/testsuite/gdb.guile/types-module.exp
@@ -44,7 +44,7 @@ gdb_test "guile (print (type-has-field-deep? d \"base_member\"))" \
     "= #t" "type-has-field-deep? member in baseclass"
 
 gdb_test "guile (print (type-has-field-deep? (lookup-type \"int\") \"base_member\"))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
     "type-has-field-deep? from int"
 
 gdb_scm_test_silent_cmd "guile (define enum-htab (make-enum-hashtable (lookup-type \"enum_type\")))" \
@@ -54,9 +54,9 @@ gdb_test "guile (print (hash-ref enum-htab \"B\"))" \
     "= 1" "verify make-enum-hashtable"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable #f))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
+    "Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
     "make-enum-hashtable from #f"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable (lookup-type \"int\")))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
     "make-enum-hashtable from int"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/2] guile: Add support for Guile 3.0.
  2020-06-15 15:02   ` Tom Tromey
@ 2020-06-15 15:17     ` Ludovic Courtès
  2020-06-17 16:58     ` Ludovic Courtès
  1 sibling, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-15 15:17 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi,

Tom Tromey <tom@tromey.com> skribis:

>>>>>> "Ludovic" == Ludovic Courtès <ludo@gnu.org> writes:
>
> Ludovic> 	* testsuite/gdb.guile/source2.scm: Add #f first argument to
> Ludovic> 	'format'.
> Ludovic> 	* testsuite/gdb.guile/types-module.exp: Remove "ERROR:" from
> Ludovic> 	regexps since Guile 3.0 no longer prints that.
>
> testsuite/ (unfortunately IMO) has its own ChangeLog.

Oops, will change it.

> Ludovic>        /* If scm_is_unsigned_integer can't work with this type, just punt.  */
> Ludovic> -      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
> Ludovic> +      if (TYPE_LENGTH (type) > sizeof (uintmax_t))
>
> I suppose these can't differ in Guile 2.0 or 2.2?

Correct.  ‘scm_t_uintmax’ used to be provided by Guile but it no longer
makes sense now that C99 <stdint.h> and its C++ counterpart are widely
available.

> Anyway, this patch seems fine to me.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 1/2] guile: Add support for Guile 2.2.
  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
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-15 17:00 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Date: Mon, 15 Jun 2020 17:14:52 +0200
> Cc: Ludovic Courtès <ludo@gnu.org>
> 
> This primarily updates code that uses the I/O port API of Guile.
> 
> gdb/ChangeLog
> 2020-06-15  Ludovic Courtès  <ludo@gnu.org>
>             Doug Evans  <dje@google.com>
> 
> 	PR gdb/21104
> 	* 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 *'.
> 	(natural_buffer_size) [!USING_GUILE_BEFORE_2_2]: New variable.
> 	(ioscm_open_port) [USING_GUILE_BEFORE_2_2]: Add 'stream'
> 	parameter and honor it.  Update callers.
> 	(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.
> 	(gdbscm_get_natural_buffer_sizes) [!USING_GUILE_BEFORE_2_2]: New
> 	function.
> 	(ioscm_init_memory_port): Remove.
> 	(ioscm_init_memory_port_stream): New function
> 	(ioscm_init_memory_port_buffers) [USING_GUILE_BEFORE_2_2]: New
> 	function.
> 	(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.
> 	* configure.ac (try_guile_versions): Add "guile-2.2".
> 	* configure: Regenerate.
> 	* NEWS: Add entry.
> 
> gdb/doc/ChangeLog
> 2020-06-15  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* 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.

The documentation parts are okay, thanks.

I still am not convinced we should remove the description of those
functions from the manual, but I'll let others speak up if they have
an opinion.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/2] guile: Add support for Guile 3.0.
  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
  1 sibling, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-17 16:58 UTC (permalink / raw)
  To: Tom Tromey, Eli Zaretskii; +Cc: gdb-patches

Hello Tom & Eli,

Tom Tromey <tom@tromey.com> skribis:

>>>>>> "Ludovic" == Ludovic Courtès <ludo@gnu.org> writes:

[...]

> Anyway, this patch seems fine to me.

[...]

> The documentation parts are okay, thanks.
>
> I still am not convinced we should remove the description of those
> functions from the manual, but I'll let others speak up if they have
> an opinion.

We haven’t gotten more feedback.

Should I interpret your messages above as formal approval?  For the
first patch or both?  (I can also wait for more feedback, I just want to
make sure there’s no misunderstanding.)

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/2] guile: Add support for Guile 3.0.
  2020-06-17 16:58     ` Ludovic Courtès
@ 2020-06-17 17:21       ` Eli Zaretskii
  0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-17 17:21 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: tom, gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Cc: gdb-patches@sourceware.org
> Date: Wed, 17 Jun 2020 18:58:15 +0200
> 
> > Anyway, this patch seems fine to me.
> 
> [...]
> 
> > The documentation parts are okay, thanks.
> >
> > I still am not convinced we should remove the description of those
> > functions from the manual, but I'll let others speak up if they have
> > an opinion.
> 
> We haven’t gotten more feedback.
> 
> Should I interpret your messages above as formal approval?  For the
> first patch or both?  (I can also wait for more feedback, I just want to
> make sure there’s no misunderstanding.)

I approved the documentation parts.  I'll leave it to Tom to decide
whether we need to wait for more opinions.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 1/2] guile: Add support for Guile 2.2.
  2020-06-15 17:00               ` Eli Zaretskii
@ 2020-06-18 20:31                 ` Tom Tromey
  2020-06-19  6:08                   ` Eli Zaretskii
  0 siblings, 1 reply; 40+ messages in thread
From: Tom Tromey @ 2020-06-18 20:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Ludovic Courtès, gdb-patches

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> I still am not convinced we should remove the description of those
Eli> functions from the manual, but I'll let others speak up if they have
Eli> an opinion.

When do we plan to remove them?

Maybe it would be better to leave the docs and say "these will be
removed in gdb 11", then once 10 branches we could go ahead with that.

IIUC maybe they are sometimes needed by Guile 2.0?  How long is that
expected to be around?

Tom

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 1/2] guile: Add support for Guile 2.2.
  2020-06-18 20:31                 ` Tom Tromey
@ 2020-06-19  6:08                   ` Eli Zaretskii
  2020-06-19  7:37                     ` Ludovic Courtès
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-19  6:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: ludo, gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Ludovic Courtès <ludo@gnu.org>,
>   gdb-patches@sourceware.org
> Date: Thu, 18 Jun 2020 14:31:51 -0600
> 
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
> 
> Eli> I still am not convinced we should remove the description of those
> Eli> functions from the manual, but I'll let others speak up if they have
> Eli> an opinion.
> 
> When do we plan to remove them?
> 
> Maybe it would be better to leave the docs and say "these will be
> removed in gdb 11", then once 10 branches we could go ahead with that.

Those were my thoughts, yes.  And also to state that they are only
available with Guile 2.0.

> IIUC maybe they are sometimes needed by Guile 2.0?  How long is that
> expected to be around?

Something for Ludo to answer, I guess.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 1/2] guile: Add support for Guile 2.2.
  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
  0 siblings, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-19  7:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches

Hi,

Eli Zaretskii <eliz@gnu.org> skribis:

>> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> Eli> I still am not convinced we should remove the description of those
>> Eli> functions from the manual, but I'll let others speak up if they have
>> Eli> an opinion.
>> 
>> When do we plan to remove them?
>> 
>> Maybe it would be better to leave the docs and say "these will be
>> removed in gdb 11", then once 10 branches we could go ahead with that.
>
> Those were my thoughts, yes.  And also to state that they are only
> available with Guile 2.0.

OK, sounds good to me.

>> IIUC maybe they are sometimes needed by Guile 2.0?

They’re the only way to change the size of the memory port’s internal
buffer on 2.0, but I can’t think of a use case where one really needs
that control.

>> How long is that expected to be around?

If this goes into gdb 10, my suggestion is to remove Guile 2.0 support
in gdb 11.  We’re keeping it just to make the transition smoother.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v3 0/2] Add support for Guile 3.0 and 2.2
  2020-06-19  7:37                     ` Ludovic Courtès
@ 2020-06-26  8:13                       ` 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  8:13                         ` [PATCH v3 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
  0 siblings, 2 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-26  8:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

Hello,

Here’s an updated patch series; changes compared to v2:

  • Reinstate documentation of the buffering procedures for
    memory ports, but with a note stating they’re deprecated.

  • Separate ChangeLog for gdb/testsuite.

Let me know what you think.

Thanks in advance,
Ludo’.

Ludovic Courtès (2):
  guile: Add support for Guile 2.2.
  guile: Add support for Guile 3.0.

 gdb/NEWS                                 |  10 +
 gdb/configure                            |   2 +-
 gdb/configure.ac                         |   2 +-
 gdb/doc/guile.texi                       |  17 +-
 gdb/guile/scm-math.c                     |   4 +-
 gdb/guile/scm-ports.c                    | 619 ++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp    |   2 +-
 gdb/testsuite/gdb.guile/source2.scm      |   2 +-
 gdb/testsuite/gdb.guile/types-module.exp |   6 +-
 9 files changed, 483 insertions(+), 181 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v3 1/2] guile: Add support for Guile 2.2.
  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                         ` Ludovic Courtès
  2020-06-26 10:23                           ` Eli Zaretskii
  2020-06-26  8:13                         ` [PATCH v3 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
  1 sibling, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-26  8:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

This primarily updates code that uses the I/O port API of Guile.

gdb/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>
            Doug Evans  <dje@google.com>

	PR gdb/21104
	* 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 *'.
	(natural_buffer_size) [!USING_GUILE_BEFORE_2_2]: New variable.
	(ioscm_open_port) [USING_GUILE_BEFORE_2_2]: Add 'stream'
	parameter and honor it.  Update callers.
	(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.
	(gdbscm_get_natural_buffer_sizes) [!USING_GUILE_BEFORE_2_2]: New
	function.
	(ioscm_init_memory_port): Remove.
	(ioscm_init_memory_port_stream): New function
	(ioscm_init_memory_port_buffers) [USING_GUILE_BEFORE_2_2]: New
	function.
	(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'.
	* configure.ac (try_guile_versions): Add "guile-2.2".
	* configure: Regenerate.
	* NEWS: Add entry.

gdb/testsuite/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>

	* gdb.guile/scm-error.exp ("source $remote_guile_file_1"): Relax
	error regexp to match on Guile 2.2.

gdb/doc/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>

	* guile.texi (Memory Ports in Guile): Mark
	'memory-port-read-buffer-size',
	'set-memory-port-read-buffer-size!',
	'memory-port-write-buffer-size',
	'set-memory-port-read-buffer-size!' as deprecated.
	* doc/guile.texi (Guile Introduction): Clarify which Guile
	versions are supported.
---
 gdb/NEWS                              |  10 +
 gdb/configure                         |   2 +-
 gdb/configure.ac                      |   2 +-
 gdb/doc/guile.texi                    |  17 +-
 gdb/guile/scm-ports.c                 | 619 +++++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp |   2 +-
 6 files changed, 477 insertions(+), 175 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index a116d62bca..37ab83618e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -117,6 +117,16 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
   ** Commands written in Python can be in the "TUI" help class by
      registering with the new constant gdb.COMMAND_TUI.
 
+* Guile API
+
+  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+
+  ** Procedures 'memory-port-read-buffer-size',
+     'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
+     and 'set-memory-port-write-buffer-size!' are deprecated.  When
+     using Guile 2.2 and later, users who need to control the size of
+     a memory port's internal buffer can use the 'setvbuf' procedure.
+
 *** Changes in GDB 9
 
 * 'thread-exited' event is now available in the annotations interface.
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..63e76a8bf8 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
@@ -3559,21 +3558,35 @@ inclusive.
 @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}.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+It returns 0 when using Guile 2.2 or later.
 @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.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+When using Guile 2.2 or later, you can call @code{setvbuf} instead
+(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).
 @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}.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+It returns 0 when using Guile 2.2 or later.
 @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.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+When using Guile 2.2 or later, you can call @code{setvbuf} instead
+(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).
 @end deffn
 
 A memory port is closed like any other port, with @code{close-port}.
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index 407d1d36f1..36b339ecff 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,11 +115,17 @@ 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";
 
+#if USING_GUILE_BEFORE_2_2
+
 /* The default amount of memory to fetch for each read/write request.
    Scheme ports don't provide a way to specify the size of a read,
    which is important to us to minimize the number of inferior interactions,
@@ -123,16 +142,24 @@ static const unsigned max_memory_port_buf_size = 4096;
 /* "out of range" error message for buf sizes.  */
 static char *out_of_range_buf_size;
 
+#else
+
+/* The maximum values to use for get_natural_buffer_sizes.  */
+static const unsigned natural_buf_size = 16;
+
+#endif
+
 /* Keywords used by open-memory.  */
 static SCM mode_keyword;
 static SCM start_keyword;
 static SCM size_keyword;
 \f
-/* Helper to do the low level work of opening a port.
-   Newer versions of Guile (2.1.x) have scm_c_make_port.  */
+/* Helper to do the low level work of opening a port.  */
+
+#if USING_GUILE_BEFORE_2_2
 
 static SCM
-ioscm_open_port (scm_t_bits port_type, long mode_bits)
+ioscm_open_port (scm_t_bits port_type, long mode_bits, scm_t_bits stream)
 {
   SCM port;
 
@@ -143,6 +170,7 @@ ioscm_open_port (scm_t_bits port_type, long mode_bits)
   port = scm_new_port_table_entry (port_type);
 
   SCM_SET_CELL_TYPE (port, port_type | mode_bits);
+  SCM_SETSTREAM (port, stream);
 
 #if 0 /* TODO: Guile doesn't export this.  What to do?  */
   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
@@ -150,9 +178,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, scm_t_bits stream)
+{
+  return scm_c_make_port (port_type, mode_bits, stream);
+}
+
+#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 +303,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 +343,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 +408,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 +435,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 +468,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
@@ -389,7 +512,7 @@ ioscm_make_gdb_stdio_port (int fd)
     }
 
   mode_bits = scm_mode_bits ((char *) mode_str);
-  port = ioscm_open_port (stdio_port_desc, mode_bits);
+  port = ioscm_open_port (stdio_port_desc, mode_bits, 0);
 
   scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
 
@@ -403,9 +526,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 +696,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 +791,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 +883,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 +981,178 @@ 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 */
+
+/* The semantics get weird if the buffer size is larger than the port range,
+   so provide a better default buffer size.  */
+
+static void
+gdbscm_get_natural_buffer_sizes (SCM port, size_t *read_size,
+				 size_t *write_size)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  size_t size = natural_buf_size;
+  if (iomem != NULL && iomem->size < size)
+    size = iomem->size;
+  *read_size = *write_size = size;
+}
+
+/* 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);
+  int rc;
+
+  rc = ioscm_lseek_address (iomem, offset, whence);
+  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 iomem->current;
+}
+
+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 +1164,23 @@ 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);
+#else
+  scm_set_port_get_natural_buffer_sizes (memory_port_desc,
+					 gdbscm_get_natural_buffer_sizes);
+#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);
 }
 
@@ -922,17 +1221,13 @@ ioscm_parse_mode_bits (const char *func_name, const char *mode)
   return mode_bits;
 }
 
-/* Helper for gdbscm_open_memory to finish initializing the port.
-   The port has address range [start,end).
-   This means that address of 0xff..ff is not accessible.
-   I can live with that.  */
+/* Return the memory object to be used as a "stream" associated with a memory
+   port for the START--END range.  */
 
-static void
-ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
+static ioscm_memory_port *
+ioscm_init_memory_port_stream (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 +1238,23 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
   iomem->end = end;
   iomem->size = end - start;
   iomem->current = 0;
+
+  return iomem;
+}
+
+#if USING_GUILE_BEFORE_2_2
+
+/* Helper for gdbscm_open_memory to finish initializing the port.
+   The port has address range [start,end).
+   This means that address of 0xff..ff is not accessible.
+   I can live with that.  */
+
+static void
+ioscm_init_memory_port_buffers (SCM port)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
   if (buffered)
     {
       iomem->read_buf_size = default_read_buf_size;
@@ -954,7 +1266,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 +1285,9 @@ 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;
-
-  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;
-    }
-}
+#endif
 
 /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
    Return a port that can be used for reading and writing memory.
@@ -1109,9 +1356,19 @@ gdbscm_open_memory (SCM rest)
 
   mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode);
 
-  port = ioscm_open_port (memory_port_desc, mode_bits);
+  /* Edge case: empty range -> unbuffered.
+     There's no need to disallow empty ranges, but we need an unbuffered port
+     to get the semantics right.  */
+  if (size == 0)
+    mode_bits |= SCM_BUF0;
+
+  auto stream = ioscm_init_memory_port_stream (start, end);
+  port = ioscm_open_port (memory_port_desc, mode_bits,
+			  (scm_t_bits) stream);
 
-  ioscm_init_memory_port (port, start, end);
+#if USING_GUILE_BEFORE_2_2
+  ioscm_init_memory_port_buffers (port);
+#endif
 
   scm_dynwind_end ();
 
@@ -1124,7 +1381,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 +1416,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 +1424,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 +1436,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 +1456,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 +1466,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 +1474,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 +1486,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 +1506,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.  */
@@ -1366,9 +1643,11 @@ gdbscm_initialize_ports (void)
   start_keyword = scm_from_latin1_keyword ("start");
   size_keyword = scm_from_latin1_keyword ("size");
 
+#if USING_GUILE_BEFORE_2_2
   /* Error message text for "out of range" memory port buffer sizes.  */
 
   out_of_range_buf_size = xstrprintf ("size not between %u - %u",
 				      min_memory_port_buf_size,
 				      max_memory_port_buf_size);
+#endif
 }
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"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v3 2/2] guile: Add support for Guile 3.0.
  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  8:13                         ` Ludovic Courtès
  2020-06-26 10:13                           ` Eli Zaretskii
  1 sibling, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-26  8:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

gdb/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>

	* guile/scm-math.c (vlscm_integer_fits_p): Use 'uintmax_t'
	and 'intmax_t' instead of 'scm_t_uintmax' and 'scm_t_intmax',
	which are deprecated in Guile 3.0.
	* configure.ac (try_guile_versions): Add "guile-3.0".
	* configure (try_guile_versions): Regenerate.
	* NEWS: Update entry.

gdb/testsuite/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>

	* gdb.guile/source2.scm: Add #f first argument to 'format'.
	* gdb.guile/types-module.exp: Remove "ERROR:" from
	regexps since Guile 3.0 no longer prints that.

gdb/doc/ChangeLog
2020-06-26  Ludovic Courtès  <ludo@gnu.org>

	* doc/guile.texi (Guile Introduction): Mention Guile 3.0.
---
 gdb/NEWS                                 | 2 +-
 gdb/configure                            | 2 +-
 gdb/configure.ac                         | 2 +-
 gdb/doc/guile.texi                       | 2 +-
 gdb/guile/scm-math.c                     | 4 ++--
 gdb/testsuite/gdb.guile/source2.scm      | 2 +-
 gdb/testsuite/gdb.guile/types-module.exp | 6 +++---
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 37ab83618e..985dbb0497 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -119,7 +119,7 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
 
 * Guile API
 
-  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+  ** GDB can now be built with GNU Guile 3.0 and 2.2 in addition to 2.0.
 
   ** Procedures 'memory-port-read-buffer-size',
      'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
diff --git a/gdb/configure b/gdb/configure
index bd12695291..5ad1e53ac4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10954,7 +10954,7 @@ fi
 
 
 
-try_guile_versions="guile-2.2 guile-2.0"
+try_guile_versions="guile-3.0 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 87afc26581..d8cef1e914 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.2 guile-2.0"
+try_guile_versions="guile-3.0 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 63e76a8bf8..71f3241cdf 100644
--- a/gdb/doc/guile.texi
+++ b/gdb/doc/guile.texi
@@ -38,7 +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.2 or 2.0.
+@value{GDBN} requires Guile version 3.0, 2.2, or 2.0.
 
 @cindex guile scripts directory
 Guile scripts used by @value{GDBN} should be installed in
diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c
index 7c63fa2ae0..419f5099bf 100644
--- a/gdb/guile/scm-math.c
+++ b/gdb/guile/scm-math.c
@@ -578,7 +578,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       ULONGEST max;
 
       /* If scm_is_unsigned_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
+      if (TYPE_LENGTH (type) > sizeof (uintmax_t))
 	return 0;
       get_unsigned_type_max (type, &max);
       return scm_is_unsigned_integer (obj, 0, max);
@@ -588,7 +588,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       LONGEST min, max;
 
       /* If scm_is_signed_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_intmax))
+      if (TYPE_LENGTH (type) > sizeof (intmax_t))
 	return 0;
       get_signed_type_minmax (type, &min, &max);
       return scm_is_signed_integer (obj, min, max);
diff --git a/gdb/testsuite/gdb.guile/source2.scm b/gdb/testsuite/gdb.guile/source2.scm
index 39638053d9..c39f03801a 100644
--- a/gdb/testsuite/gdb.guile/source2.scm
+++ b/gdb/testsuite/gdb.guile/source2.scm
@@ -15,5 +15,5 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-(display (format "y~As" "e"))
+(display (format #f "y~As" "e"))
 (newline)
diff --git a/gdb/testsuite/gdb.guile/types-module.exp b/gdb/testsuite/gdb.guile/types-module.exp
index 5a631dca8e..8ced6fbffb 100644
--- a/gdb/testsuite/gdb.guile/types-module.exp
+++ b/gdb/testsuite/gdb.guile/types-module.exp
@@ -44,7 +44,7 @@ gdb_test "guile (print (type-has-field-deep? d \"base_member\"))" \
     "= #t" "type-has-field-deep? member in baseclass"
 
 gdb_test "guile (print (type-has-field-deep? (lookup-type \"int\") \"base_member\"))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
     "type-has-field-deep? from int"
 
 gdb_scm_test_silent_cmd "guile (define enum-htab (make-enum-hashtable (lookup-type \"enum_type\")))" \
@@ -54,9 +54,9 @@ gdb_test "guile (print (hash-ref enum-htab \"B\"))" \
     "= 1" "verify make-enum-hashtable"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable #f))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
+    "Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
     "make-enum-hashtable from #f"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable (lookup-type \"int\")))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
     "make-enum-hashtable from int"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v3 2/2] guile: Add support for Guile 3.0.
  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
  0 siblings, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-26 10:13 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Date: Fri, 26 Jun 2020 10:13:33 +0200
> Cc: Ludovic Courtès <ludo@gnu.org>
> 
> gdb/ChangeLog
> 2020-06-26  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* guile/scm-math.c (vlscm_integer_fits_p): Use 'uintmax_t'
> 	and 'intmax_t' instead of 'scm_t_uintmax' and 'scm_t_intmax',
> 	which are deprecated in Guile 3.0.
> 	* configure.ac (try_guile_versions): Add "guile-3.0".
> 	* configure (try_guile_versions): Regenerate.
> 	* NEWS: Update entry.
> 
> gdb/testsuite/ChangeLog
> 2020-06-26  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* gdb.guile/source2.scm: Add #f first argument to 'format'.
> 	* gdb.guile/types-module.exp: Remove "ERROR:" from
> 	regexps since Guile 3.0 no longer prints that.
> 
> gdb/doc/ChangeLog
> 2020-06-26  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* doc/guile.texi (Guile Introduction): Mention Guile 3.0.

Thanks, the documentation parts are OK.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v3 1/2] guile: Add support for Guile 2.2.
  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
  0 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-26 10:23 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Date: Fri, 26 Jun 2020 10:13:32 +0200
> Cc: Ludovic Courtès <ludo@gnu.org>
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index a116d62bca..37ab83618e 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -117,6 +117,16 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
>    ** Commands written in Python can be in the "TUI" help class by
>       registering with the new constant gdb.COMMAND_TUI.
>  
> +* Guile API
> +
> +  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
> +
> +  ** Procedures 'memory-port-read-buffer-size',
> +     'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
> +     and 'set-memory-port-write-buffer-size!' are deprecated.  When
> +     using Guile 2.2 and later, users who need to control the size of
> +     a memory port's internal buffer can use the 'setvbuf' procedure.
> +

This part is OK.

>  @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.
> +
> +This procedure is deprecated and will be removed in @value{GDBN} 11.
> +When using Guile 2.2 or later, you can call @code{setvbuf} instead
> +(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).

First, instead of "When using" I'd suggest to say "When @value{GDBN}
was built with".  And second, there's a certain conundrum here: the
node "Buffering" doesn't exist in the Guile v2.0.x manual, so I wonder
whether we should say something here about that to prevent user
surprise when the hyperlink causes an error.

>  @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.
> +
> +This procedure is deprecated and will be removed in @value{GDBN} 11.
> +When using Guile 2.2 or later, you can call @code{setvbuf} instead
> +(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).
>  @end deffn

Here, I'd remove the @pxref: we already have the same hyperlink a
short ways above, so repetition is not necessary.

The documentation parts are okay with those nits fixed.

> +/* 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))

Since Guile < 2.0 is not supported, do we need the first part of the
macro?

Thanks.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v3 1/2] guile: Add support for Guile 2.2.
  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
                                                 ` (3 more replies)
  0 siblings, 4 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-28 14:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Hello Eli,

Eli Zaretskii <eliz@gnu.org> skribis:

>>  @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.
>> +
>> +This procedure is deprecated and will be removed in @value{GDBN} 11.
>> +When using Guile 2.2 or later, you can call @code{setvbuf} instead
>> +(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).
>
> First, instead of "When using" I'd suggest to say "When @value{GDBN}
> was built with".

Agreed.

> And second, there's a certain conundrum here: the node "Buffering"
> doesn't exist in the Guile v2.0.x manual, so I wonder whether we
> should say something here about that to prevent user surprise when the
> hyperlink causes an error.

We explicitly write “When GDB is built with Guile 2.2”, so I think we
can’t really do better; removing the link would annoy users of current
Guile versions.  WDYT?

>>  @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.
>> +
>> +This procedure is deprecated and will be removed in @value{GDBN} 11.
>> +When using Guile 2.2 or later, you can call @code{setvbuf} instead
>> +(@pxref{Buffering, @code{setvbuf},, guile, GNU Guile Reference Manual}).
>>  @end deffn
>
> Here, I'd remove the @pxref: we already have the same hyperlink a
> short ways above, so repetition is not necessary.

Agreed.

> The documentation parts are okay with those nits fixed.
>
>> +/* 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))
>
> Since Guile < 2.0 is not supported, do we need the first part of the
> macro?

It’s not.

I’m sending v4; changes since v3:

  • Adjust wording for deprecated procedures as you suggested above.

  • Simplify USING_GUILE_BEFORE_2_2 C macro.

Any other suggestions?  It would be perfect if this could land in time
for GDB 10.

Thank you,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-06-28 14:20                             ` Ludovic Courtès
@ 2020-06-28 14:25                               ` Ludovic Courtès
  2020-06-28 16:40                                 ` Eli Zaretskii
  2020-07-03  0:31                                 ` Simon Marchi
  2020-06-28 14:25                               ` [PATCH v4 2/2] guile: Add support for Guile 3.0 Ludovic Courtès
                                                 ` (2 subsequent siblings)
  3 siblings, 2 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-28 14:25 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

This primarily updates code that uses the I/O port API of Guile.

gdb/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>
            Doug Evans  <dje@google.com>

	PR gdb/21104
	* 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 *'.
	(natural_buffer_size) [!USING_GUILE_BEFORE_2_2]: New variable.
	(ioscm_open_port) [USING_GUILE_BEFORE_2_2]: Add 'stream'
	parameter and honor it.  Update callers.
	(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.
	(gdbscm_get_natural_buffer_sizes) [!USING_GUILE_BEFORE_2_2]: New
	function.
	(ioscm_init_memory_port): Remove.
	(ioscm_init_memory_port_stream): New function
	(ioscm_init_memory_port_buffers) [USING_GUILE_BEFORE_2_2]: New
	function.
	(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'.
	* configure.ac (try_guile_versions): Add "guile-2.2".
	* configure: Regenerate.
	* NEWS: Add entry.

gdb/testsuite/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>

	* gdb.guile/scm-error.exp ("source $remote_guile_file_1"): Relax
	error regexp to match on Guile 2.2.

gdb/doc/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>

	* guile.texi (Memory Ports in Guile): Mark
	'memory-port-read-buffer-size',
	'set-memory-port-read-buffer-size!',
	'memory-port-write-buffer-size',
	'set-memory-port-read-buffer-size!' as deprecated.
	* doc/guile.texi (Guile Introduction): Clarify which Guile
	versions are supported.
---
 gdb/NEWS                              |  10 +
 gdb/configure                         |   2 +-
 gdb/configure.ac                      |   2 +-
 gdb/doc/guile.texi                    |  18 +-
 gdb/guile/scm-ports.c                 | 618 +++++++++++++++++++-------
 gdb/testsuite/gdb.guile/scm-error.exp |   2 +-
 6 files changed, 477 insertions(+), 175 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index a116d62bca..37ab83618e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -117,6 +117,16 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
   ** Commands written in Python can be in the "TUI" help class by
      registering with the new constant gdb.COMMAND_TUI.
 
+* Guile API
+
+  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+
+  ** Procedures 'memory-port-read-buffer-size',
+     'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
+     and 'set-memory-port-write-buffer-size!' are deprecated.  When
+     using Guile 2.2 and later, users who need to control the size of
+     a memory port's internal buffer can use the 'setvbuf' procedure.
+
 *** Changes in GDB 9
 
 * 'thread-exited' event is now available in the annotations interface.
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..52da7e7c17 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
@@ -3559,21 +3558,36 @@ inclusive.
 @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}.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+It returns 0 when using Guile 2.2 or later.
 @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.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+When @value{GDBN} is built with Guile 2.2 or later, you can call
+@code{setvbuf} instead (@pxref{Buffering, @code{setvbuf},, guile, GNU
+Guile Reference Manual}).
 @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}.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+It returns 0 when @value{GDBN} is built with Guile 2.2 or later.
 @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.
+
+This procedure is deprecated and will be removed in @value{GDBN} 11.
+When @value{GDBN} is built with Guile 2.2 or later, you can call
+@code{setvbuf} instead.
 @end deffn
 
 A memory port is closed like any other port, with @code{close-port}.
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index 407d1d36f1..17f8a30b11 100644
--- a/gdb/guile/scm-ports.c
+++ b/gdb/guile/scm-ports.c
@@ -36,6 +36,12 @@
 #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_MINOR_VERSION == 0)
+
+
 /* A ui-file for sending output to Guile.  */
 
 class ioscm_file_port : public ui_file
@@ -66,12 +72,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 +89,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,11 +114,17 @@ 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";
 
+#if USING_GUILE_BEFORE_2_2
+
 /* The default amount of memory to fetch for each read/write request.
    Scheme ports don't provide a way to specify the size of a read,
    which is important to us to minimize the number of inferior interactions,
@@ -123,16 +141,24 @@ static const unsigned max_memory_port_buf_size = 4096;
 /* "out of range" error message for buf sizes.  */
 static char *out_of_range_buf_size;
 
+#else
+
+/* The maximum values to use for get_natural_buffer_sizes.  */
+static const unsigned natural_buf_size = 16;
+
+#endif
+
 /* Keywords used by open-memory.  */
 static SCM mode_keyword;
 static SCM start_keyword;
 static SCM size_keyword;
 \f
-/* Helper to do the low level work of opening a port.
-   Newer versions of Guile (2.1.x) have scm_c_make_port.  */
+/* Helper to do the low level work of opening a port.  */
+
+#if USING_GUILE_BEFORE_2_2
 
 static SCM
-ioscm_open_port (scm_t_bits port_type, long mode_bits)
+ioscm_open_port (scm_t_bits port_type, long mode_bits, scm_t_bits stream)
 {
   SCM port;
 
@@ -143,6 +169,7 @@ ioscm_open_port (scm_t_bits port_type, long mode_bits)
   port = scm_new_port_table_entry (port_type);
 
   SCM_SET_CELL_TYPE (port, port_type | mode_bits);
+  SCM_SETSTREAM (port, stream);
 
 #if 0 /* TODO: Guile doesn't export this.  What to do?  */
   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
@@ -150,9 +177,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, scm_t_bits stream)
+{
+  return scm_c_make_port (port_type, mode_bits, stream);
+}
+
+#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 +302,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 +342,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 +407,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 +434,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 +467,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
@@ -389,7 +511,7 @@ ioscm_make_gdb_stdio_port (int fd)
     }
 
   mode_bits = scm_mode_bits ((char *) mode_str);
-  port = ioscm_open_port (stdio_port_desc, mode_bits);
+  port = ioscm_open_port (stdio_port_desc, mode_bits, 0);
 
   scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
 
@@ -403,9 +525,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 +695,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 +790,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 +882,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 +980,178 @@ 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 */
+
+/* The semantics get weird if the buffer size is larger than the port range,
+   so provide a better default buffer size.  */
+
+static void
+gdbscm_get_natural_buffer_sizes (SCM port, size_t *read_size,
+				 size_t *write_size)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  size_t size = natural_buf_size;
+  if (iomem != NULL && iomem->size < size)
+    size = iomem->size;
+  *read_size = *write_size = size;
+}
+
+/* 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);
+  int rc;
+
+  rc = ioscm_lseek_address (iomem, offset, whence);
+  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 iomem->current;
+}
+
+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 +1163,23 @@ 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);
+#else
+  scm_set_port_get_natural_buffer_sizes (memory_port_desc,
+					 gdbscm_get_natural_buffer_sizes);
+#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);
 }
 
@@ -922,17 +1220,13 @@ ioscm_parse_mode_bits (const char *func_name, const char *mode)
   return mode_bits;
 }
 
-/* Helper for gdbscm_open_memory to finish initializing the port.
-   The port has address range [start,end).
-   This means that address of 0xff..ff is not accessible.
-   I can live with that.  */
+/* Return the memory object to be used as a "stream" associated with a memory
+   port for the START--END range.  */
 
-static void
-ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
+static ioscm_memory_port *
+ioscm_init_memory_port_stream (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 +1237,23 @@ ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
   iomem->end = end;
   iomem->size = end - start;
   iomem->current = 0;
+
+  return iomem;
+}
+
+#if USING_GUILE_BEFORE_2_2
+
+/* Helper for gdbscm_open_memory to finish initializing the port.
+   The port has address range [start,end).
+   This means that address of 0xff..ff is not accessible.
+   I can live with that.  */
+
+static void
+ioscm_init_memory_port_buffers (SCM port)
+{
+  ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
+
+  int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
   if (buffered)
     {
       iomem->read_buf_size = default_read_buf_size;
@@ -954,7 +1265,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 +1284,9 @@ 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;
-
-  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;
-    }
-}
+#endif
 
 /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
    Return a port that can be used for reading and writing memory.
@@ -1109,9 +1355,19 @@ gdbscm_open_memory (SCM rest)
 
   mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode);
 
-  port = ioscm_open_port (memory_port_desc, mode_bits);
+  /* Edge case: empty range -> unbuffered.
+     There's no need to disallow empty ranges, but we need an unbuffered port
+     to get the semantics right.  */
+  if (size == 0)
+    mode_bits |= SCM_BUF0;
+
+  auto stream = ioscm_init_memory_port_stream (start, end);
+  port = ioscm_open_port (memory_port_desc, mode_bits,
+			  (scm_t_bits) stream);
 
-  ioscm_init_memory_port (port, start, end);
+#if USING_GUILE_BEFORE_2_2
+  ioscm_init_memory_port_buffers (port);
+#endif
 
   scm_dynwind_end ();
 
@@ -1124,7 +1380,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 +1415,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 +1423,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 +1435,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 +1455,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 +1465,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 +1473,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 +1485,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 +1505,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.  */
@@ -1366,9 +1642,11 @@ gdbscm_initialize_ports (void)
   start_keyword = scm_from_latin1_keyword ("start");
   size_keyword = scm_from_latin1_keyword ("size");
 
+#if USING_GUILE_BEFORE_2_2
   /* Error message text for "out of range" memory port buffer sizes.  */
 
   out_of_range_buf_size = xstrprintf ("size not between %u - %u",
 				      min_memory_port_buf_size,
 				      max_memory_port_buf_size);
+#endif
 }
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"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v4 2/2] guile: Add support for Guile 3.0.
  2020-06-28 14:20                             ` Ludovic Courtès
  2020-06-28 14:25                               ` [PATCH v4 " Ludovic Courtès
@ 2020-06-28 14:25                               ` Ludovic Courtès
  2020-06-28 16:38                               ` [PATCH v3 1/2] guile: Add support for Guile 2.2 Eli Zaretskii
  2020-07-02 12:57                               ` [PING] Add support for Guile 2.2/3.0 Ludovic Courtès
  3 siblings, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-28 14:25 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ludovic Courtès

gdb/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>

	* guile/scm-math.c (vlscm_integer_fits_p): Use 'uintmax_t'
	and 'intmax_t' instead of 'scm_t_uintmax' and 'scm_t_intmax',
	which are deprecated in Guile 3.0.
	* configure.ac (try_guile_versions): Add "guile-3.0".
	* configure (try_guile_versions): Regenerate.
	* NEWS: Update entry.

gdb/testsuite/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>

	* gdb.guile/source2.scm: Add #f first argument to 'format'.
	* gdb.guile/types-module.exp: Remove "ERROR:" from
	regexps since Guile 3.0 no longer prints that.

gdb/doc/ChangeLog
2020-06-28  Ludovic Courtès  <ludo@gnu.org>

	* doc/guile.texi (Guile Introduction): Mention Guile 3.0.
---
 gdb/NEWS                                 | 2 +-
 gdb/configure                            | 2 +-
 gdb/configure.ac                         | 2 +-
 gdb/doc/guile.texi                       | 2 +-
 gdb/guile/scm-math.c                     | 4 ++--
 gdb/testsuite/gdb.guile/source2.scm      | 2 +-
 gdb/testsuite/gdb.guile/types-module.exp | 6 +++---
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 37ab83618e..985dbb0497 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -119,7 +119,7 @@ GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
 
 * Guile API
 
-  ** GDB can now be built with GNU Guile 2.2 in addition to 2.0.
+  ** GDB can now be built with GNU Guile 3.0 and 2.2 in addition to 2.0.
 
   ** Procedures 'memory-port-read-buffer-size',
      'set-memory-port-read-buffer-size!', 'memory-port-write-buffer-size',
diff --git a/gdb/configure b/gdb/configure
index bd12695291..5ad1e53ac4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10954,7 +10954,7 @@ fi
 
 
 
-try_guile_versions="guile-2.2 guile-2.0"
+try_guile_versions="guile-3.0 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 87afc26581..d8cef1e914 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.2 guile-2.0"
+try_guile_versions="guile-3.0 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 52da7e7c17..9d1f55a839 100644
--- a/gdb/doc/guile.texi
+++ b/gdb/doc/guile.texi
@@ -38,7 +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.2 or 2.0.
+@value{GDBN} requires Guile version 3.0, 2.2, or 2.0.
 
 @cindex guile scripts directory
 Guile scripts used by @value{GDBN} should be installed in
diff --git a/gdb/guile/scm-math.c b/gdb/guile/scm-math.c
index 7c63fa2ae0..419f5099bf 100644
--- a/gdb/guile/scm-math.c
+++ b/gdb/guile/scm-math.c
@@ -578,7 +578,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       ULONGEST max;
 
       /* If scm_is_unsigned_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_uintmax))
+      if (TYPE_LENGTH (type) > sizeof (uintmax_t))
 	return 0;
       get_unsigned_type_max (type, &max);
       return scm_is_unsigned_integer (obj, 0, max);
@@ -588,7 +588,7 @@ vlscm_integer_fits_p (SCM obj, struct type *type)
       LONGEST min, max;
 
       /* If scm_is_signed_integer can't work with this type, just punt.  */
-      if (TYPE_LENGTH (type) > sizeof (scm_t_intmax))
+      if (TYPE_LENGTH (type) > sizeof (intmax_t))
 	return 0;
       get_signed_type_minmax (type, &min, &max);
       return scm_is_signed_integer (obj, min, max);
diff --git a/gdb/testsuite/gdb.guile/source2.scm b/gdb/testsuite/gdb.guile/source2.scm
index 39638053d9..c39f03801a 100644
--- a/gdb/testsuite/gdb.guile/source2.scm
+++ b/gdb/testsuite/gdb.guile/source2.scm
@@ -15,5 +15,5 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-(display (format "y~As" "e"))
+(display (format #f "y~As" "e"))
 (newline)
diff --git a/gdb/testsuite/gdb.guile/types-module.exp b/gdb/testsuite/gdb.guile/types-module.exp
index 5a631dca8e..8ced6fbffb 100644
--- a/gdb/testsuite/gdb.guile/types-module.exp
+++ b/gdb/testsuite/gdb.guile/types-module.exp
@@ -44,7 +44,7 @@ gdb_test "guile (print (type-has-field-deep? d \"base_member\"))" \
     "= #t" "type-has-field-deep? member in baseclass"
 
 gdb_test "guile (print (type-has-field-deep? (lookup-type \"int\") \"base_member\"))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting struct or union\\): #<gdb:type int>.*" \
     "type-has-field-deep? from int"
 
 gdb_scm_test_silent_cmd "guile (define enum-htab (make-enum-hashtable (lookup-type \"enum_type\")))" \
@@ -54,9 +54,9 @@ gdb_test "guile (print (hash-ref enum-htab \"B\"))" \
     "= 1" "verify make-enum-hashtable"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable #f))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
+    "Wrong type argument in position 1 \\(expecting gdb:type\\): #f.*" \
     "make-enum-hashtable from #f"
 
 gdb_test "guile (define bad-enum-htab (make-enum-hashtable (lookup-type \"int\")))" \
-    "ERROR: .*Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
+    "Wrong type argument in position 1 \\(expecting enum\\): #<gdb:type int>.*" \
     "make-enum-hashtable from int"
-- 
2.26.2


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v3 1/2] guile: Add support for Guile 2.2.
  2020-06-28 14:20                             ` Ludovic Courtès
  2020-06-28 14:25                               ` [PATCH v4 " 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                               ` 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
  3 siblings, 1 reply; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-28 16:38 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Cc: gdb-patches@sourceware.org
> Date: Sun, 28 Jun 2020 16:20:54 +0200
> 
> > And second, there's a certain conundrum here: the node "Buffering"
> > doesn't exist in the Guile v2.0.x manual, so I wonder whether we
> > should say something here about that to prevent user surprise when the
> > hyperlink causes an error.
> 
> We explicitly write “When GDB is built with Guile 2.2”, so I think we
> can’t really do better; removing the link would annoy users of current
> Guile versions.  WDYT?

I didn't mean to remove the reference, that would be unwise.  But
maybe a note in parentheses about this?

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-06-28 14:25                               ` [PATCH v4 " Ludovic Courtès
@ 2020-06-28 16:40                                 ` Eli Zaretskii
  2020-07-03  0:31                                 ` Simon Marchi
  1 sibling, 0 replies; 40+ messages in thread
From: Eli Zaretskii @ 2020-06-28 16:40 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

> From: Ludovic Courtès <ludo@gnu.org>
> Date: Sun, 28 Jun 2020 16:25:39 +0200
> Cc: Ludovic Courtès <ludo@gnu.org>
> 
> This primarily updates code that uses the I/O port API of Guile.
> 
> gdb/ChangeLog
> 2020-06-28  Ludovic Courtès  <ludo@gnu.org>
>             Doug Evans  <dje@google.com>
> 
> 	PR gdb/21104
> 	* 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 *'.
> 	(natural_buffer_size) [!USING_GUILE_BEFORE_2_2]: New variable.
> 	(ioscm_open_port) [USING_GUILE_BEFORE_2_2]: Add 'stream'
> 	parameter and honor it.  Update callers.
> 	(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.
> 	(gdbscm_get_natural_buffer_sizes) [!USING_GUILE_BEFORE_2_2]: New
> 	function.
> 	(ioscm_init_memory_port): Remove.
> 	(ioscm_init_memory_port_stream): New function
> 	(ioscm_init_memory_port_buffers) [USING_GUILE_BEFORE_2_2]: New
> 	function.
> 	(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'.
> 	* configure.ac (try_guile_versions): Add "guile-2.2".
> 	* configure: Regenerate.
> 	* NEWS: Add entry.
> 
> gdb/testsuite/ChangeLog
> 2020-06-28  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* gdb.guile/scm-error.exp ("source $remote_guile_file_1"): Relax
> 	error regexp to match on Guile 2.2.
> 
> gdb/doc/ChangeLog
> 2020-06-28  Ludovic Courtès  <ludo@gnu.org>
> 
> 	* guile.texi (Memory Ports in Guile): Mark
> 	'memory-port-read-buffer-size',
> 	'set-memory-port-read-buffer-size!',
> 	'memory-port-write-buffer-size',
> 	'set-memory-port-read-buffer-size!' as deprecated.
> 	* doc/guile.texi (Guile Introduction): Clarify which Guile
> 	versions are supported.

The documentation parts are okay, thanks.  (If you agree with my last
comment about reference to the Guile 2.2 manual, I'd appreciate a fix;
otherwise we can handle that later.)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v3 1/2] guile: Add support for Guile 2.2.
  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
  0 siblings, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-06-28 16:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Eli Zaretskii <eliz@gnu.org> skribis:

>> From: Ludovic Courtès <ludo@gnu.org>
>> Cc: gdb-patches@sourceware.org
>> Date: Sun, 28 Jun 2020 16:20:54 +0200
>> 
>> > And second, there's a certain conundrum here: the node "Buffering"
>> > doesn't exist in the Guile v2.0.x manual, so I wonder whether we
>> > should say something here about that to prevent user surprise when the
>> > hyperlink causes an error.
>> 
>> We explicitly write “When GDB is built with Guile 2.2”, so I think we
>> can’t really do better; removing the link would annoy users of current
>> Guile versions.  WDYT?
>
> I didn't mean to remove the reference, that would be unwise.  But
> maybe a note in parentheses about this?

I don’t think it’s necessary: we’d have two parenthetical expressions
next to one another, it’d be redundant with the beginning of the
sentence, and it’d only be useful for those who only have Guile 2.0,
which has long been deprecated.

Thanks for your review,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PING] Add support for Guile 2.2/3.0
  2020-06-28 14:20                             ` Ludovic Courtès
                                                 ` (2 preceding siblings ...)
  2020-06-28 16:38                               ` [PATCH v3 1/2] guile: Add support for Guile 2.2 Eli Zaretskii
@ 2020-07-02 12:57                               ` Ludovic Courtès
  2020-07-13 15:36                                 ` Tom Tromey
  3 siblings, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-07-02 12:57 UTC (permalink / raw)
  To: gdb-patches

Hello,

Ludovic Courtès <ludo@gnu.org> skribis:

> I’m sending v4; changes since v3:
>
>   • Adjust wording for deprecated procedures as you suggested above.
>
>   • Simplify USING_GUILE_BEFORE_2_2 C macro.
>
> Any other suggestions?  It would be perfect if this could land in time
> for GDB 10.

Just a friendly reminder that this series is waiting for approval (apart
from the documentation bits).

You can find v4 here:

  https://sourceware.org/pipermail/gdb-patches/2020-June/169936.html
  https://sourceware.org/pipermail/gdb-patches/2020-June/169935.html

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  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
  1 sibling, 2 replies; 40+ messages in thread
From: Simon Marchi @ 2020-07-03  0:31 UTC (permalink / raw)
  To: Ludovic Courtès, gdb-patches

On 2020-06-28 10:25 a.m., Ludovic Courtès wrote:
> This primarily updates code that uses the I/O port API of Guile.

I know nothing about Guile, so I just scanned the patch for any obvious
red flags, but didn't see any.  The mess of #if statements sure is not
the best, but I don't have a concrete suggestion to make it better.

Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-07-03  0:31                                 ` Simon Marchi
@ 2020-07-03  7:06                                   ` Ludovic Courtès
  2020-07-18 19:00                                   ` Joel Brobecker
  1 sibling, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-07-03  7:06 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

Hi Simon,

Simon Marchi <simark@simark.ca> skribis:

> On 2020-06-28 10:25 a.m., Ludovic Courtès wrote:
>> This primarily updates code that uses the I/O port API of Guile.
>
> I know nothing about Guile, so I just scanned the patch for any obvious
> red flags, but didn't see any.  The mess of #if statements sure is not
> the best, but I don't have a concrete suggestion to make it better.

I agree the #ifdefs are not pretty, but it’s a temporary measure until
GDB 11 when Guile 2.0 support will be dropped.

Thanks for taking a look!

Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PING] Add support for Guile 2.2/3.0
  2020-07-02 12:57                               ` [PING] Add support for Guile 2.2/3.0 Ludovic Courtès
@ 2020-07-13 15:36                                 ` Tom Tromey
  0 siblings, 0 replies; 40+ messages in thread
From: Tom Tromey @ 2020-07-13 15:36 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches

>>>>> "Ludovic" == Ludovic Courtès <ludo@gnu.org> writes:

Ludovic> Just a friendly reminder that this series is waiting for approval (apart
Ludovic> from the documentation bits).

Ludovic> You can find v4 here:

Ludovic>   https://sourceware.org/pipermail/gdb-patches/2020-June/169936.html
Ludovic>   https://sourceware.org/pipermail/gdb-patches/2020-June/169935.html

Thanks for doing this.  These are ok.

Tom

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  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
  1 sibling, 1 reply; 40+ messages in thread
From: Joel Brobecker @ 2020-07-18 19:00 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Ludovic Courtès, gdb-patches

Hi Simon,

> > This primarily updates code that uses the I/O port API of Guile.
> 
> I know nothing about Guile, so I just scanned the patch for any obvious
> red flags, but didn't see any.  The mess of #if statements sure is not
> the best, but I don't have a concrete suggestion to make it better.

I'm not confident that we'll be able to find a reviewer who has
more experience with this part of the Code. What do you think of
approving this patch series based on your review?

-- 
Joel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-07-18 19:00                                   ` Joel Brobecker
@ 2020-07-19 15:45                                     ` Simon Marchi
  2020-07-20  8:05                                       ` Ludovic Courtès
  0 siblings, 1 reply; 40+ messages in thread
From: Simon Marchi @ 2020-07-19 15:45 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Ludovic Courtès, gdb-patches

On 2020-07-18 3:00 p.m., Joel Brobecker wrote:
> Hi Simon,
> 
>>> This primarily updates code that uses the I/O port API of Guile.
>>
>> I know nothing about Guile, so I just scanned the patch for any obvious
>> red flags, but didn't see any.  The mess of #if statements sure is not
>> the best, but I don't have a concrete suggestion to make it better.
> 
> I'm not confident that we'll be able to find a reviewer who has
> more experience with this part of the Code. What do you think of
> approving this patch series based on your review?

Yeah, I think we can go ahead.  Ludovic, do you have push access or would you like me to push it?

Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-07-19 15:45                                     ` Simon Marchi
@ 2020-07-20  8:05                                       ` Ludovic Courtès
  2020-07-20 15:01                                         ` Simon Marchi
  0 siblings, 1 reply; 40+ messages in thread
From: Ludovic Courtès @ 2020-07-20  8:05 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Joel Brobecker, gdb-patches

Hi Simon,

Simon Marchi <simark@simark.ca> skribis:

> On 2020-07-18 3:00 p.m., Joel Brobecker wrote:
>> Hi Simon,
>> 
>>>> This primarily updates code that uses the I/O port API of Guile.
>>>
>>> I know nothing about Guile, so I just scanned the patch for any obvious
>>> red flags, but didn't see any.  The mess of #if statements sure is not
>>> the best, but I don't have a concrete suggestion to make it better.
>> 
>> I'm not confident that we'll be able to find a reviewer who has
>> more experience with this part of the Code. What do you think of
>> approving this patch series based on your review?
>
> Yeah, I think we can go ahead.  Ludovic, do you have push access or would you like me to push it?

I do have access but I’m happy if you can push it for me.

Thank you!

Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-07-20  8:05                                       ` Ludovic Courtès
@ 2020-07-20 15:01                                         ` Simon Marchi
  2020-07-21 21:10                                           ` Ludovic Courtès
  0 siblings, 1 reply; 40+ messages in thread
From: Simon Marchi @ 2020-07-20 15:01 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: gdb-patches, Joel Brobecker

On 2020-07-20 4:05 a.m., Ludovic Courtès wrote:
> Hi Simon,
> 
> Simon Marchi <simark@simark.ca> skribis:
> 
>> On 2020-07-18 3:00 p.m., Joel Brobecker wrote:
>>> Hi Simon,
>>>
>>>>> This primarily updates code that uses the I/O port API of Guile.
>>>>
>>>> I know nothing about Guile, so I just scanned the patch for any obvious
>>>> red flags, but didn't see any.  The mess of #if statements sure is not
>>>> the best, but I don't have a concrete suggestion to make it better.
>>>
>>> I'm not confident that we'll be able to find a reviewer who has
>>> more experience with this part of the Code. What do you think of
>>> approving this patch series based on your review?
>>
>> Yeah, I think we can go ahead.  Ludovic, do you have push access or would you like me to push it?
> 
> I do have access but I’m happy if you can push it for me.

Done, thanks.

Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v4 1/2] guile: Add support for Guile 2.2.
  2020-07-20 15:01                                         ` Simon Marchi
@ 2020-07-21 21:10                                           ` Ludovic Courtès
  0 siblings, 0 replies; 40+ messages in thread
From: Ludovic Courtès @ 2020-07-21 21:10 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, Joel Brobecker

Simon Marchi <simark@simark.ca> skribis:

> On 2020-07-20 4:05 a.m., Ludovic Courtès wrote:
>> Hi Simon,
>> 
>> Simon Marchi <simark@simark.ca> skribis:
>> 
>>> On 2020-07-18 3:00 p.m., Joel Brobecker wrote:
>>>> Hi Simon,
>>>>
>>>>>> This primarily updates code that uses the I/O port API of Guile.
>>>>>
>>>>> I know nothing about Guile, so I just scanned the patch for any obvious
>>>>> red flags, but didn't see any.  The mess of #if statements sure is not
>>>>> the best, but I don't have a concrete suggestion to make it better.
>>>>
>>>> I'm not confident that we'll be able to find a reviewer who has
>>>> more experience with this part of the Code. What do you think of
>>>> approving this patch series based on your review?
>>>
>>> Yeah, I think we can go ahead.  Ludovic, do you have push access or would you like me to push it?
>> 
>> I do have access but I’m happy if you can push it for me.
>
> Done, thanks.

Awesome, thank you!

Ludo’.

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2020-07-21 21:10 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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   ` [PATCH 1/2] guile: Add support for Guile 2.2 Tom de Vries
2020-06-12 14:36     ` 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

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).