From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 7C733386F47D for ; Fri, 12 Jun 2020 14:14:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7C733386F47D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 610A3AC6E; Fri, 12 Jun 2020 14:14:21 +0000 (UTC) Subject: Re: [PATCH 1/2] guile: Add support for Guile 2.2. To: =?UTF-8?Q?Ludovic_Court=c3=a8s?= , gdb-patches@sourceware.org References: <20200612132710.14364-1-ludo@gnu.org> <20200612132710.14364-2-ludo@gnu.org> From: Tom de Vries Autocrypt: addr=tdevries@suse.de; keydata= xsBNBF0ltCcBCADDhsUnMMdEXiHFfqJdXeRvgqSEUxLCy/pHek88ALuFnPTICTwkf4g7uSR7 HvOFUoUyu8oP5mNb4VZHy3Xy8KRZGaQuaOHNhZAT1xaVo6kxjswUi3vYgGJhFMiLuIHdApoc u5f7UbV+egYVxmkvVLSqsVD4pUgHeSoAcIlm3blZ1sDKviJCwaHxDQkVmSsGXImaAU+ViJ5l CwkvyiiIifWD2SoOuFexZyZ7RUddLosgsO0npVUYbl6dEMq2a5ijGF6/rBs1m3nAoIgpXk6P TCKlSWVW6OCneTaKM5C387972qREtiArTakRQIpvDJuiR2soGfdeJ6igGA1FZjU+IsM5ABEB AAHNH1RvbSBkZSBWcmllcyA8dGRldnJpZXNAc3VzZS5kZT7CwKsEEwEIAD4WIQSsnSe5hKbL MK1mGmjuhV2rbOJEoAUCXSW0JwIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAh CRDuhV2rbOJEoBYhBKydJ7mEpsswrWYaaO6FXats4kSgc48H/Ra2lq5p3dHsrlQLqM7N68Fo eRDf3PMevXyMlrCYDGLVncQwMw3O/AkousktXKQ42DPJh65zoXB22yUt8m0g12xkLax98KFJ 5NyUloa6HflLl+wQL/uZjIdNUQaHQLw3HKwRMVi4l0/Jh/TygYG1Dtm8I4o708JS4y8GQxoQ UL0z1OM9hyM3gI2WVTTyprsBHy2EjMOu/2Xpod95pF8f90zBLajy6qXEnxlcsqreMaqmkzKn 3KTZpWRxNAS/IH3FbGQ+3RpWkNGSJpwfEMVCeyK5a1n7yt1podd1ajY5mA1jcaUmGppqx827 8TqyteNe1B/pbiUt2L/WhnTgW1NC1QDOwE0EXSW0JwEIAM99H34Bu4MKM7HDJVt864MXbx7B 1M93wVlpJ7Uq+XDFD0A0hIal028j+h6jA6bhzWto4RUfDl/9mn1StngNVFovvwtfzbamp6+W pKHZm9X5YvlIwCx131kTxCNDcF+/adRW4n8CU3pZWYmNVqhMUiPLxElA6QhXTtVBh1RkjCZQ Kmbd1szvcOfaD8s+tJABJzNZsmO2hVuFwkDrRN8Jgrh92a+yHQPd9+RybW2l7sJv26nkUH5Z 5s84P6894ebgimcprJdAkjJTgprl1nhgvptU5M9Uv85Pferoh2groQEAtRPlCGrZ2/2qVNe9 XJfSYbiyedvApWcJs5DOByTaKkcAEQEAAcLAkwQYAQgAJhYhBKydJ7mEpsswrWYaaO6FXats 4kSgBQJdJbQnAhsMBQkDwmcAACEJEO6FXats4kSgFiEErJ0nuYSmyzCtZhpo7oVdq2ziRKD3 twf7BAQBZ8TqR812zKAD7biOnWIJ0McV72PFBxmLIHp24UVe0ZogtYMxSWKLg3csh0yLVwc7 H3vldzJ9AoK3Qxp0Q6K/rDOeUy3HMqewQGcqrsRRh0NXDIQk5CgSrZslPe47qIbe3O7ik/MC q31FNIAQJPmKXX25B115MMzkSKlv4udfx7KdyxHrTSkwWZArLQiEZj5KG4cCKhIoMygPTA3U yGaIvI/BGOtHZ7bEBVUCFDFfOWJ26IOCoPnSVUvKPEOH9dv+sNy7jyBsP5QxeTqwxC/1ZtNS DUCSFQjqA6bEGwM22dP8OUY6SC94x1G81A9/xbtm9LQxKm0EiDH8KBMLfQ== Message-ID: <513a8d32-70c0-939c-ccbb-f57c2165f25d@suse.de> Date: Fri, 12 Jun 2020 16:14:14 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: <20200612132710.14364-2-ludo@gnu.org> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-15.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jun 2020 14:14:22 -0000 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{} > -@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{} > -@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{} > -@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{} > -@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 > + > > /* 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 > } > > /* 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 > } > > /* 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))" \ > "= #" >