2950b1e39ec9e98157f01a54e9b99134dd17f72a
[external/binutils.git] / gdb / guile / scm-ports.c
1 /* Support for connecting Guile's stdio to GDB's.
2    as well as r/w memory via ports.
3
4    Copyright (C) 2014-2019 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 /* See README file in this directory for implementation notes, coding
22    conventions, et.al.  */
23
24 #include "defs.h"
25 #include "gdb_select.h"
26 #include "top.h"
27 #include "target.h"
28 #include "guile-internal.h"
29 #include "common/gdb_optional.h"
30
31 #ifdef HAVE_POLL
32 #if defined (HAVE_POLL_H)
33 #include <poll.h>
34 #elif defined (HAVE_SYS_POLL_H)
35 #include <sys/poll.h>
36 #endif
37 #endif
38
39 /* A ui-file for sending output to Guile.  */
40
41 class ioscm_file_port : public ui_file
42 {
43 public:
44   /* Return a ui_file that writes to PORT.  */
45   explicit ioscm_file_port (SCM port);
46
47   void flush () override;
48   void write (const char *buf, long length_buf) override;
49
50 private:
51   SCM m_port;
52 };
53
54 /* Data for a memory port.  */
55
56 typedef struct
57 {
58   /* Bounds of memory range this port is allowed to access: [start, end).
59      This means that 0xff..ff is not accessible.  I can live with that.  */
60   CORE_ADDR start, end;
61
62   /* (end - start), recorded for convenience.  */
63   ULONGEST size;
64
65   /* Think of this as the lseek value maintained by the kernel.
66      This value is always in the range [0, size].  */
67   ULONGEST current;
68
69   /* The size of the internal r/w buffers.
70      Scheme ports aren't a straightforward mapping to memory r/w.
71      Generally the user specifies how much to r/w and all access is
72      unbuffered.  We don't try to provide equivalent access, but we allow
73      the user to specify these values to help get something similar.  */
74   unsigned read_buf_size, write_buf_size;
75 } ioscm_memory_port;
76
77 /* Copies of the original system input/output/error ports.
78    These are recorded for debugging purposes.  */
79 static SCM orig_input_port_scm;
80 static SCM orig_output_port_scm;
81 static SCM orig_error_port_scm;
82
83 /* This is the stdio port descriptor, scm_ptob_descriptor.  */
84 static scm_t_bits stdio_port_desc;
85
86 /* Note: scm_make_port_type takes a char * instead of a const char *.  */
87 static /*const*/ char stdio_port_desc_name[] = "gdb:stdio-port";
88
89 /* Names of each gdb port.  */
90 static const char input_port_name[] = "gdb:stdin";
91 static const char output_port_name[] = "gdb:stdout";
92 static const char error_port_name[] = "gdb:stderr";
93
94 /* This is the actual port used from Guile.
95    We don't expose these to the user though, to ensure they're not
96    overwritten.  */
97 static SCM input_port_scm;
98 static SCM output_port_scm;
99 static SCM error_port_scm;
100
101 /* Internal enum for specifying output port.  */
102 enum oport { GDB_STDOUT, GDB_STDERR };
103
104 /* This is the memory port descriptor, scm_ptob_descriptor.  */
105 static scm_t_bits memory_port_desc;
106
107 /* Note: scm_make_port_type takes a char * instead of a const char *.  */
108 static /*const*/ char memory_port_desc_name[] = "gdb:memory-port";
109
110 /* The default amount of memory to fetch for each read/write request.
111    Scheme ports don't provide a way to specify the size of a read,
112    which is important to us to minimize the number of inferior interactions,
113    which over a remote link can be important.  To compensate we augment the
114    port API with a new function that let's the user specify how much the next
115    read request should fetch.  This is the initial value for each new port.  */
116 static const unsigned default_read_buf_size = 16;
117 static const unsigned default_write_buf_size = 16;
118
119 /* Arbitrarily limit memory port buffers to 1 byte to 4K.  */
120 static const unsigned min_memory_port_buf_size = 1;
121 static const unsigned max_memory_port_buf_size = 4096;
122
123 /* "out of range" error message for buf sizes.  */
124 static char *out_of_range_buf_size;
125
126 /* Keywords used by open-memory.  */
127 static SCM mode_keyword;
128 static SCM start_keyword;
129 static SCM size_keyword;
130 \f
131 /* Helper to do the low level work of opening a port.
132    Newer versions of Guile (2.1.x) have scm_c_make_port.  */
133
134 static SCM
135 ioscm_open_port (scm_t_bits port_type, long mode_bits)
136 {
137   SCM port;
138
139 #if 0 /* TODO: Guile doesn't export this.  What to do?  */
140   scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
141 #endif
142
143   port = scm_new_port_table_entry (port_type);
144
145   SCM_SET_CELL_TYPE (port, port_type | mode_bits);
146
147 #if 0 /* TODO: Guile doesn't export this.  What to do?  */
148   scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
149 #endif
150
151   return port;
152 }
153 \f
154 /* Support for connecting Guile's stdio ports to GDB's stdio ports.  */
155
156 /* The scm_t_ptob_descriptor.input_waiting "method".
157    Return a lower bound on the number of bytes available for input.  */
158
159 static int
160 ioscm_input_waiting (SCM port)
161 {
162   int fdes = 0;
163
164   if (! scm_is_eq (port, input_port_scm))
165     return 0;
166
167 #ifdef HAVE_POLL
168   {
169     /* This is copied from libguile/fports.c.  */
170     struct pollfd pollfd = { fdes, POLLIN, 0 };
171     static int use_poll = -1;
172
173     if (use_poll < 0)
174       {
175         /* This is copied from event-loop.c: poll cannot be used for stdin on
176            m68k-motorola-sysv.  */
177         struct pollfd test_pollfd = { fdes, POLLIN, 0 };
178
179         if (poll (&test_pollfd, 1, 0) == 1 && (test_pollfd.revents & POLLNVAL))
180           use_poll = 0;
181         else
182           use_poll = 1;
183       }
184
185     if (use_poll)
186       {
187         /* Guile doesn't export SIGINT hooks like Python does.
188            For now pass EINTR to scm_syserror, that's what fports.c does.  */
189         if (poll (&pollfd, 1, 0) < 0)
190           scm_syserror (FUNC_NAME);
191
192         return pollfd.revents & POLLIN ? 1 : 0;
193       }
194   }
195   /* Fall through.  */
196 #endif
197
198   {
199     struct timeval timeout;
200     fd_set input_fds;
201     int num_fds = fdes + 1;
202     int num_found;
203
204     memset (&timeout, 0, sizeof (timeout));
205     FD_ZERO (&input_fds);
206     FD_SET (fdes, &input_fds);
207
208     num_found = interruptible_select (num_fds,
209                                       &input_fds, NULL, NULL,
210                                       &timeout);
211     if (num_found < 0)
212       {
213         /* Guile doesn't export SIGINT hooks like Python does.
214            For now pass EINTR to scm_syserror, that's what fports.c does.  */
215         scm_syserror (FUNC_NAME);
216       }
217     return num_found > 0 && FD_ISSET (fdes, &input_fds);
218   }
219 }
220
221 /* The scm_t_ptob_descriptor.fill_input "method".  */
222
223 static int
224 ioscm_fill_input (SCM port)
225 {
226   /* Borrowed from libguile/fports.c.  */
227   long count;
228   scm_t_port *pt = SCM_PTAB_ENTRY (port);
229
230   /* If we're called on stdout,stderr, punt.  */
231   if (! scm_is_eq (port, input_port_scm))
232     return (scm_t_wchar) EOF; /* Set errno and return -1?  */
233
234   gdb_flush (gdb_stdout);
235   gdb_flush (gdb_stderr);
236
237   count = ui_file_read (gdb_stdin, (char *) pt->read_buf, pt->read_buf_size);
238   if (count == -1)
239     scm_syserror (FUNC_NAME);
240   if (count == 0)
241     return (scm_t_wchar) EOF;
242
243   pt->read_pos = pt->read_buf;
244   pt->read_end = pt->read_buf + count;
245   return *pt->read_buf;
246 }
247
248 /* Like fputstrn_filtered, but don't escape characters, except nul.
249    Also like fputs_filtered, but a length is specified.  */
250
251 static void
252 fputsn_filtered (const char *s, size_t size, struct ui_file *stream)
253 {
254   size_t i;
255
256   for (i = 0; i < size; ++i)
257     {
258       if (s[i] == '\0')
259         fputs_filtered ("\\000", stream);
260       else
261         fputc_filtered (s[i], stream);
262     }
263 }
264
265 /* Write to gdb's stdout or stderr.  */
266
267 static void
268 ioscm_write (SCM port, const void *data, size_t size)
269 {
270
271   /* If we're called on stdin, punt.  */
272   if (scm_is_eq (port, input_port_scm))
273     return;
274
275   TRY
276     {
277       if (scm_is_eq (port, error_port_scm))
278         fputsn_filtered ((const char *) data, size, gdb_stderr);
279       else
280         fputsn_filtered ((const char *) data, size, gdb_stdout);
281     }
282   CATCH (except, RETURN_MASK_ALL)
283     {
284       GDBSCM_HANDLE_GDB_EXCEPTION (except);
285     }
286   END_CATCH
287 }
288
289 /* Flush gdb's stdout or stderr.  */
290
291 static void
292 ioscm_flush (SCM port)
293 {
294   /* If we're called on stdin, punt.  */
295   if (scm_is_eq (port, input_port_scm))
296     return;
297
298   if (scm_is_eq (port, error_port_scm))
299     gdb_flush (gdb_stderr);
300   else
301     gdb_flush (gdb_stdout);
302 }
303
304 /* Initialize the gdb stdio port type.
305
306    N.B. isatty? will fail on these ports, it is only supported for file
307    ports.  IWBN if we could "subclass" file ports.  */
308
309 static void
310 ioscm_init_gdb_stdio_port (void)
311 {
312   stdio_port_desc = scm_make_port_type (stdio_port_desc_name,
313                                         ioscm_fill_input, ioscm_write);
314
315   scm_set_port_input_waiting (stdio_port_desc, ioscm_input_waiting);
316   scm_set_port_flush (stdio_port_desc, ioscm_flush);
317 }
318
319 /* Subroutine of ioscm_make_gdb_stdio_port to simplify it.
320    Set up the buffers of port PORT.
321    MODE_BITS are the mode bits of PORT.  */
322
323 static void
324 ioscm_init_stdio_buffers (SCM port, long mode_bits)
325 {
326   scm_t_port *pt = SCM_PTAB_ENTRY (port);
327 #define GDB_STDIO_BUFFER_DEFAULT_SIZE 1024
328   int size = mode_bits & SCM_BUF0 ? 0 : GDB_STDIO_BUFFER_DEFAULT_SIZE;
329   int writing = (mode_bits & SCM_WRTNG) != 0;
330
331   /* This is heavily copied from scm_fport_buffer_add.  */
332
333   if (!writing && size > 0)
334     {
335       pt->read_buf
336         = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
337       pt->read_pos = pt->read_end = pt->read_buf;
338       pt->read_buf_size = size;
339     }
340   else
341     {
342       pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
343       pt->read_buf_size = 1;
344     }
345
346   if (writing && size > 0)
347     {
348       pt->write_buf
349         = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
350       pt->write_pos = pt->write_buf;
351       pt->write_buf_size = size;
352     }
353   else
354     {
355       pt->write_buf = pt->write_pos = &pt->shortbuf;
356       pt->write_buf_size = 1;
357     }
358   pt->write_end = pt->write_buf + pt->write_buf_size;
359 }
360
361 /* Create a gdb stdio port.  */
362
363 static SCM
364 ioscm_make_gdb_stdio_port (int fd)
365 {
366   int is_a_tty = isatty (fd);
367   const char *name;
368   const char *mode_str;
369   long mode_bits;
370   SCM port;
371
372   switch (fd)
373     {
374     case 0:
375       name = input_port_name;
376       mode_str = is_a_tty ? "r0" : "r";
377       break;
378     case 1:
379       name = output_port_name;
380       mode_str = is_a_tty ? "w0" : "w";
381       break;
382     case 2:
383       name = error_port_name;
384       mode_str = is_a_tty ? "w0" : "w";
385       break;
386     default:
387       gdb_assert_not_reached ("bad stdio file descriptor");
388     }
389
390   mode_bits = scm_mode_bits ((char *) mode_str);
391   port = ioscm_open_port (stdio_port_desc, mode_bits);
392
393   scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
394
395   ioscm_init_stdio_buffers (port, mode_bits);
396
397   return port;
398 }
399
400 /* (stdio-port? object) -> boolean */
401
402 static SCM
403 gdbscm_stdio_port_p (SCM scm)
404 {
405   /* This is copied from SCM_FPORTP.  */
406   return scm_from_bool (!SCM_IMP (scm)
407                         && (SCM_TYP16 (scm) == stdio_port_desc));
408 }
409 \f
410 /* GDB's ports are accessed via functions to keep them read-only.  */
411
412 /* (input-port) -> port */
413
414 static SCM
415 gdbscm_input_port (void)
416 {
417   return input_port_scm;
418 }
419
420 /* (output-port) -> port */
421
422 static SCM
423 gdbscm_output_port (void)
424 {
425   return output_port_scm;
426 }
427
428 /* (error-port) -> port */
429
430 static SCM
431 gdbscm_error_port (void)
432 {
433   return error_port_scm;
434 }
435 \f
436 /* Support for sending GDB I/O to Guile ports.  */
437
438 ioscm_file_port::ioscm_file_port (SCM port)
439   : m_port (port)
440 {}
441
442 void
443 ioscm_file_port::flush ()
444 {
445 }
446
447 void
448 ioscm_file_port::write (const char *buffer, long length_buffer)
449 {
450   scm_c_write (m_port, buffer, length_buffer);
451 }
452
453 \f
454 /* Helper routine for with-{output,error}-to-port.  */
455
456 static SCM
457 ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
458                                   const char *func_name)
459 {
460   SCM result;
461
462   SCM_ASSERT_TYPE (gdbscm_is_true (scm_output_port_p (port)), port,
463                    SCM_ARG1, func_name, _("output port"));
464   SCM_ASSERT_TYPE (gdbscm_is_true (scm_thunk_p (thunk)), thunk,
465                    SCM_ARG2, func_name, _("thunk"));
466
467   set_batch_flag_and_restore_page_info save_page_info;
468
469   scoped_restore restore_async = make_scoped_restore (&current_ui->async, 0);
470
471   ui_file_up port_file (new ioscm_file_port (port));
472
473   scoped_restore save_file = make_scoped_restore (oport == GDB_STDERR
474                                                   ? &gdb_stderr : &gdb_stdout);
475
476   {
477     gdb::optional<ui_out_redirect_pop> redirect_popper;
478     if (oport == GDB_STDERR)
479       gdb_stderr = port_file.get ();
480     else
481       {
482         current_uiout->redirect (port_file.get ());
483         redirect_popper.emplace (current_uiout);
484
485         gdb_stdout = port_file.get ();
486       }
487
488     result = gdbscm_safe_call_0 (thunk, NULL);
489   }
490
491   if (gdbscm_is_exception (result))
492     gdbscm_throw (result);
493
494   return result;
495 }
496
497 /* (%with-gdb-output-to-port port thunk) -> object
498    This function is experimental.
499    IWBN to not include "gdb" in the name, but it would collide with a standard
500    procedure, and it's common to import the gdb module without a prefix.
501    There are ways around this, but they're more cumbersome.
502
503    This has % in the name because it's experimental, and we want the
504    user-visible version to come from module (gdb experimental).  */
505
506 static SCM
507 gdbscm_percent_with_gdb_output_to_port (SCM port, SCM thunk)
508 {
509   return ioscm_with_output_to_port_worker (port, thunk, GDB_STDOUT, FUNC_NAME);
510 }
511
512 /* (%with-gdb-error-to-port port thunk) -> object
513    This function is experimental.
514    IWBN to not include "gdb" in the name, but it would collide with a standard
515    procedure, and it's common to import the gdb module without a prefix.
516    There are ways around this, but they're more cumbersome.
517
518    This has % in the name because it's experimental, and we want the
519    user-visible version to come from module (gdb experimental).  */
520
521 static SCM
522 gdbscm_percent_with_gdb_error_to_port (SCM port, SCM thunk)
523 {
524   return ioscm_with_output_to_port_worker (port, thunk, GDB_STDERR, FUNC_NAME);
525 }
526 \f
527 /* Support for r/w memory via ports.  */
528
529 /* Perform an "lseek" to OFFSET,WHENCE on memory port IOMEM.
530    OFFSET must be in the range [0,size].
531    The result is non-zero for success, zero for failure.  */
532
533 static int
534 ioscm_lseek_address (ioscm_memory_port *iomem, LONGEST offset, int whence)
535 {
536   CORE_ADDR new_current;
537
538   gdb_assert (iomem->current <= iomem->size);
539
540   switch (whence)
541     {
542     case SEEK_CUR:
543       /* Catch over/underflow.  */
544       if ((offset < 0 && iomem->current + offset > iomem->current)
545           || (offset > 0 && iomem->current + offset < iomem->current))
546         return 0;
547       new_current = iomem->current + offset;
548       break;
549     case SEEK_SET:
550       new_current = offset;
551       break;
552     case SEEK_END:
553       if (offset == 0)
554         {
555           new_current = iomem->size;
556           break;
557         }
558       /* TODO: Not supported yet.  */
559       return 0;
560     default:
561       return 0;
562     }
563
564   if (new_current > iomem->size)
565     return 0;
566   iomem->current = new_current;
567   return 1;
568 }
569
570 /* "fill_input" method for memory ports.  */
571
572 static int
573 gdbscm_memory_port_fill_input (SCM port)
574 {
575   scm_t_port *pt = SCM_PTAB_ENTRY (port);
576   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
577   size_t to_read;
578
579   /* "current" is the offset of the first byte we want to read.  */
580   gdb_assert (iomem->current <= iomem->size);
581   if (iomem->current == iomem->size)
582     return EOF;
583
584   /* Don't read outside the allowed memory range.  */
585   to_read = pt->read_buf_size;
586   if (to_read > iomem->size - iomem->current)
587     to_read = iomem->size - iomem->current;
588
589   if (target_read_memory (iomem->start + iomem->current, pt->read_buf,
590                           to_read) != 0)
591     gdbscm_memory_error (FUNC_NAME, _("error reading memory"), SCM_EOL);
592
593   iomem->current += to_read;
594   pt->read_pos = pt->read_buf;
595   pt->read_end = pt->read_buf + to_read;
596   return *pt->read_buf;
597 }
598
599 /* "end_input" method for memory ports.
600    Clear the read buffer and adjust the file position for unread bytes.  */
601
602 static void
603 gdbscm_memory_port_end_input (SCM port, int offset)
604 {
605   scm_t_port *pt = SCM_PTAB_ENTRY (port);
606   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
607   size_t remaining = pt->read_end - pt->read_pos;
608
609   /* Note: Use of "int offset" is specified by Guile ports API.  */
610   if ((offset < 0 && remaining + offset > remaining)
611       || (offset > 0 && remaining + offset < remaining))
612     {
613       gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset),
614                                  _("overflow in offset calculation"));
615     }
616   offset += remaining;
617
618   if (offset > 0)
619     {
620       pt->read_pos = pt->read_end;
621       /* Throw error if unread-char used at beginning of file
622          then attempting to write.  Seems correct.  */
623       if (!ioscm_lseek_address (iomem, -offset, SEEK_CUR))
624         {
625           gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset),
626                                      _("bad offset"));
627         }
628     }
629
630   pt->rw_active = SCM_PORT_NEITHER;
631 }
632
633 /* "flush" method for memory ports.  */
634
635 static void
636 gdbscm_memory_port_flush (SCM port)
637 {
638   scm_t_port *pt = SCM_PTAB_ENTRY (port);
639   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
640   size_t to_write = pt->write_pos - pt->write_buf;
641
642   if (to_write == 0)
643     return;
644
645   /* There's no way to indicate a short write, so if the request goes past
646      the end of the port's memory range, flag an error.  */
647   if (to_write > iomem->size - iomem->current)
648     {
649       gdbscm_out_of_range_error (FUNC_NAME, 0,
650                                  gdbscm_scm_from_ulongest (to_write),
651                                  _("writing beyond end of memory range"));
652     }
653
654   if (target_write_memory (iomem->start + iomem->current, pt->write_buf,
655                            to_write) != 0)
656     gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
657
658   iomem->current += to_write;
659   pt->write_pos = pt->write_buf;
660   pt->rw_active = SCM_PORT_NEITHER;
661 }
662
663 /* "write" method for memory ports.  */
664
665 static void
666 gdbscm_memory_port_write (SCM port, const void *void_data, size_t size)
667 {
668   scm_t_port *pt = SCM_PTAB_ENTRY (port);
669   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
670   const gdb_byte *data = (const gdb_byte *) void_data;
671
672   /* There's no way to indicate a short write, so if the request goes past
673      the end of the port's memory range, flag an error.  */
674   if (size > iomem->size - iomem->current)
675     {
676       gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (size),
677                                  _("writing beyond end of memory range"));
678     }
679
680   if (pt->write_buf == &pt->shortbuf)
681     {
682       /* Unbuffered port.  */
683       if (target_write_memory (iomem->start + iomem->current, data, size) != 0)
684         gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
685       iomem->current += size;
686       return;
687     }
688
689   /* Note: The edge case of what to do when the buffer exactly fills is
690      debatable.  Guile flushes when the buffer exactly fills up, so we
691      do too.  It's counter-intuitive to my mind, but in case there's a
692      subtlety somewhere that depends on this, we do the same.  */
693
694   {
695     size_t space = pt->write_end - pt->write_pos;
696
697     if (size < space)
698       {
699         /* Data fits in buffer, and does not fill it.  */
700         memcpy (pt->write_pos, data, size);
701         pt->write_pos += size;
702       }
703     else
704       {
705         memcpy (pt->write_pos, data, space);
706         pt->write_pos = pt->write_end;
707         gdbscm_memory_port_flush (port);
708         {
709           const gdb_byte *ptr = data + space;
710           size_t remaining = size - space;
711
712           if (remaining >= pt->write_buf_size)
713             {
714               if (target_write_memory (iomem->start + iomem->current, ptr,
715                                        remaining) != 0)
716                 gdbscm_memory_error (FUNC_NAME, _("error writing memory"),
717                                      SCM_EOL);
718               iomem->current += remaining;
719             }
720           else
721             {
722               memcpy (pt->write_pos, ptr, remaining);
723               pt->write_pos += remaining;
724             }
725         }
726       }
727   }
728 }
729
730 /* "seek" method for memory ports.  */
731
732 static scm_t_off
733 gdbscm_memory_port_seek (SCM port, scm_t_off offset, int whence)
734 {
735   scm_t_port *pt = SCM_PTAB_ENTRY (port);
736   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
737   CORE_ADDR result;
738   int rc;
739
740   if (pt->rw_active == SCM_PORT_WRITE)
741     {
742       if (offset != 0 || whence != SEEK_CUR)
743         {
744           gdbscm_memory_port_flush (port);
745           rc = ioscm_lseek_address (iomem, offset, whence);
746           result = iomem->current;
747         }
748       else
749         {
750           /* Read current position without disturbing the buffer,
751              but flag an error if what's in the buffer goes outside the
752              allowed range.  */
753           CORE_ADDR current = iomem->current;
754           size_t delta = pt->write_pos - pt->write_buf;
755
756           if (current + delta < current
757               || current + delta > iomem->size)
758             rc = 0;
759           else
760             {
761               result = current + delta;
762               rc = 1;
763             }
764         }
765     }
766   else if (pt->rw_active == SCM_PORT_READ)
767     {
768       if (offset != 0 || whence != SEEK_CUR)
769         {
770           scm_end_input (port);
771           rc = ioscm_lseek_address (iomem, offset, whence);
772           result = iomem->current;
773         }
774       else
775         {
776           /* Read current position without disturbing the buffer
777              (particularly the unread-char buffer).  */
778           CORE_ADDR current = iomem->current;
779           size_t remaining = pt->read_end - pt->read_pos;
780
781           if (current - remaining > current
782               || current - remaining < iomem->start)
783             rc = 0;
784           else
785             {
786               result = current - remaining;
787               rc = 1;
788             }
789
790           if (rc != 0 && pt->read_buf == pt->putback_buf)
791             {
792               size_t saved_remaining = pt->saved_read_end - pt->saved_read_pos;
793
794               if (result - saved_remaining > result
795                   || result - saved_remaining < iomem->start)
796                 rc = 0;
797               else
798                 result -= saved_remaining;
799             }
800         }
801     }
802   else /* SCM_PORT_NEITHER */
803     {
804       rc = ioscm_lseek_address (iomem, offset, whence);
805       result = iomem->current;
806     }
807
808   if (rc == 0)
809     {
810       gdbscm_out_of_range_error (FUNC_NAME, 0,
811                                  gdbscm_scm_from_longest (offset),
812                                  _("bad seek"));
813     }
814
815   /* TODO: The Guile API doesn't support 32x64.  We can't fix that here,
816      and there's no need to throw an error if the new address can't be
817      represented in a scm_t_off.  But we could return something less
818      clumsy.  */
819   return result;
820 }
821
822 /* "close" method for memory ports.  */
823
824 static int
825 gdbscm_memory_port_close (SCM port)
826 {
827   scm_t_port *pt = SCM_PTAB_ENTRY (port);
828   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
829
830   gdbscm_memory_port_flush (port);
831
832   if (pt->read_buf == pt->putback_buf)
833     pt->read_buf = pt->saved_read_buf;
834   if (pt->read_buf != &pt->shortbuf)
835     xfree (pt->read_buf);
836   if (pt->write_buf != &pt->shortbuf)
837     xfree (pt->write_buf);
838   scm_gc_free (iomem, sizeof (*iomem), "memory port");
839
840   return 0;
841 }
842
843 /* "free" method for memory ports.  */
844
845 static size_t
846 gdbscm_memory_port_free (SCM port)
847 {
848   gdbscm_memory_port_close (port);
849
850   return 0;
851 }
852
853 /* "print" method for memory ports.  */
854
855 static int
856 gdbscm_memory_port_print (SCM exp, SCM port, scm_print_state *pstate)
857 {
858   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (exp);
859   char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
860
861   scm_puts ("#<", port);
862   scm_print_port_mode (exp, port);
863   /* scm_print_port_mode includes a trailing space.  */
864   gdbscm_printf (port, "%s %s-%s", type,
865                  hex_string (iomem->start), hex_string (iomem->end));
866   scm_putc ('>', port);
867   return 1;
868 }
869
870 /* Create the port type used for memory.  */
871
872 static void
873 ioscm_init_memory_port_type (void)
874 {
875   memory_port_desc = scm_make_port_type (memory_port_desc_name,
876                                          gdbscm_memory_port_fill_input,
877                                          gdbscm_memory_port_write);
878
879   scm_set_port_end_input (memory_port_desc, gdbscm_memory_port_end_input);
880   scm_set_port_flush (memory_port_desc, gdbscm_memory_port_flush);
881   scm_set_port_seek (memory_port_desc, gdbscm_memory_port_seek);
882   scm_set_port_close (memory_port_desc, gdbscm_memory_port_close);
883   scm_set_port_free (memory_port_desc, gdbscm_memory_port_free);
884   scm_set_port_print (memory_port_desc, gdbscm_memory_port_print);
885 }
886
887 /* Helper for gdbscm_open_memory to parse the mode bits.
888    An exception is thrown if MODE is invalid.  */
889
890 static long
891 ioscm_parse_mode_bits (const char *func_name, const char *mode)
892 {
893   const char *p;
894   long mode_bits;
895
896   if (*mode != 'r' && *mode != 'w')
897     {
898       gdbscm_out_of_range_error (func_name, 0,
899                                  gdbscm_scm_from_c_string (mode),
900                                  _("bad mode string"));
901     }
902   for (p = mode + 1; *p != '\0'; ++p)
903     {
904       switch (*p)
905         {
906         case '0':
907         case 'b':
908         case '+':
909           break;
910         default:
911           gdbscm_out_of_range_error (func_name, 0,
912                                      gdbscm_scm_from_c_string (mode),
913                                      _("bad mode string"));
914         }
915     }
916
917   /* Kinda awkward to convert the mode from SCM -> string only to have Guile
918      convert it back to SCM, but that's the API we have to work with.  */
919   mode_bits = scm_mode_bits ((char *) mode);
920
921   return mode_bits;
922 }
923
924 /* Helper for gdbscm_open_memory to finish initializing the port.
925    The port has address range [start,end).
926    This means that address of 0xff..ff is not accessible.
927    I can live with that.  */
928
929 static void
930 ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
931 {
932   scm_t_port *pt;
933   ioscm_memory_port *iomem;
934   int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
935
936   gdb_assert (start <= end);
937
938   iomem = (ioscm_memory_port *) scm_gc_malloc_pointerless (sizeof (*iomem),
939                                                            "memory port");
940
941   iomem->start = start;
942   iomem->end = end;
943   iomem->size = end - start;
944   iomem->current = 0;
945   if (buffered)
946     {
947       iomem->read_buf_size = default_read_buf_size;
948       iomem->write_buf_size = default_write_buf_size;
949     }
950   else
951     {
952       iomem->read_buf_size = 1;
953       iomem->write_buf_size = 1;
954     }
955
956   pt = SCM_PTAB_ENTRY (port);
957   /* Match the expectation of `binary-port?'.  */
958   pt->encoding = NULL;
959   pt->rw_random = 1;
960   pt->read_buf_size = iomem->read_buf_size;
961   pt->write_buf_size = iomem->write_buf_size;
962   if (buffered)
963     {
964       pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
965       pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
966     }
967   else
968     {
969       pt->read_buf = &pt->shortbuf;
970       pt->write_buf = &pt->shortbuf;
971     }
972   pt->read_pos = pt->read_end = pt->read_buf;
973   pt->write_pos = pt->write_buf;
974   pt->write_end = pt->write_buf + pt->write_buf_size;
975
976   SCM_SETSTREAM (port, iomem);
977 }
978
979 /* Re-initialize a memory port, updating its read/write buffer sizes.
980    An exception is thrown if the port is unbuffered.
981    TODO: Allow switching buffered/unbuffered.
982    An exception is also thrown if data is still buffered, except in the case
983    where the buffer size isn't changing (since that's just a nop).  */
984
985 static void
986 ioscm_reinit_memory_port (SCM port, size_t read_buf_size,
987                           size_t write_buf_size, const char *func_name)
988 {
989   scm_t_port *pt = SCM_PTAB_ENTRY (port);
990   ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
991
992   gdb_assert (read_buf_size >= min_memory_port_buf_size
993               && read_buf_size <= max_memory_port_buf_size);
994   gdb_assert (write_buf_size >= min_memory_port_buf_size
995               && write_buf_size <= max_memory_port_buf_size);
996
997   /* First check if the port is unbuffered.  */
998
999   if (pt->read_buf == &pt->shortbuf)
1000     {
1001       gdb_assert (pt->write_buf == &pt->shortbuf);
1002       scm_misc_error (func_name, _("port is unbuffered: ~a"),
1003                       scm_list_1 (port));
1004     }
1005
1006   /* Next check if anything is buffered.  */
1007
1008   if (read_buf_size != pt->read_buf_size
1009       && pt->read_end != pt->read_buf)
1010     {
1011       scm_misc_error (func_name, _("read buffer not empty: ~a"),
1012                       scm_list_1 (port));
1013     }
1014
1015   if (write_buf_size != pt->write_buf_size
1016       && pt->write_pos != pt->write_buf)
1017     {
1018       scm_misc_error (func_name, _("write buffer not empty: ~a"),
1019                       scm_list_1 (port));
1020     }
1021
1022   /* Now we can update the buffer sizes, but only if the size has changed.  */
1023
1024   if (read_buf_size != pt->read_buf_size)
1025     {
1026       iomem->read_buf_size = read_buf_size;
1027       pt->read_buf_size = read_buf_size;
1028       xfree (pt->read_buf);
1029       pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
1030       pt->read_pos = pt->read_end = pt->read_buf;
1031     }
1032
1033   if (write_buf_size != pt->write_buf_size)
1034     {
1035       iomem->write_buf_size = write_buf_size;
1036       pt->write_buf_size = write_buf_size;
1037       xfree (pt->write_buf);
1038       pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
1039       pt->write_pos = pt->write_buf;
1040       pt->write_end = pt->write_buf + pt->write_buf_size;
1041     }
1042 }
1043
1044 /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
1045    Return a port that can be used for reading and writing memory.
1046    MODE is a string, and must be one of "r", "w", or "r+".
1047    "0" may be appended to MODE to mark the port as unbuffered.
1048    For compatibility "b" (binary) may also be appended, but we ignore it:
1049    memory ports are binary only.
1050
1051    The chunk of memory that can be accessed can be bounded.
1052    If both START,SIZE are unspecified, all of memory can be accessed
1053    (except 0xff..ff).  If only START is specified, all of memory from that
1054    point on can be accessed (except 0xff..ff).  If only SIZE if specified,
1055    all memory in [0,SIZE) can be accessed.  If both are specified, all memory
1056    in [START,START+SIZE) can be accessed.
1057
1058    Note: If it becomes useful enough we can later add #:end as an alternative
1059    to #:size.  For now it is left out.
1060
1061    The result is a Scheme port, and its semantics are a bit odd for accessing
1062    memory (e.g., unget), but we don't try to hide this.  It's a port.
1063
1064    N.B. Seeks on the port must be in the range [0,size].
1065    This is for similarity with bytevector ports, and so that one can seek
1066    to the first byte.  */
1067
1068 static SCM
1069 gdbscm_open_memory (SCM rest)
1070 {
1071   const SCM keywords[] = {
1072     mode_keyword, start_keyword, size_keyword, SCM_BOOL_F
1073   };
1074   char *mode = NULL;
1075   CORE_ADDR start = 0;
1076   CORE_ADDR end;
1077   int mode_arg_pos = -1, start_arg_pos = -1, size_arg_pos = -1;
1078   ULONGEST size;
1079   SCM port;
1080   long mode_bits;
1081
1082   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "#sUU", rest,
1083                               &mode_arg_pos, &mode,
1084                               &start_arg_pos, &start,
1085                               &size_arg_pos, &size);
1086
1087   scm_dynwind_begin ((scm_t_dynwind_flags) 0);
1088
1089   if (mode == NULL)
1090     mode = xstrdup ("r");
1091   scm_dynwind_free (mode);
1092
1093   if (size_arg_pos > 0)
1094     {
1095       /* For now be strict about start+size overflowing.  If it becomes
1096          a nuisance we can relax things later.  */
1097       if (start + size < start)
1098         {
1099           gdbscm_out_of_range_error (FUNC_NAME, 0,
1100                                 scm_list_2 (gdbscm_scm_from_ulongest (start),
1101                                             gdbscm_scm_from_ulongest (size)),
1102                                      _("start+size overflows"));
1103         }
1104       end = start + size;
1105     }
1106   else
1107     end = ~(CORE_ADDR) 0;
1108
1109   mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode);
1110
1111   port = ioscm_open_port (memory_port_desc, mode_bits);
1112
1113   ioscm_init_memory_port (port, start, end);
1114
1115   scm_dynwind_end ();
1116
1117   /* TODO: Set the file name as "memory-start-end"?  */
1118   return port;
1119 }
1120
1121 /* Return non-zero if OBJ is a memory port.  */
1122
1123 static int
1124 gdbscm_is_memory_port (SCM obj)
1125 {
1126   return !SCM_IMP (obj) && (SCM_TYP16 (obj) == memory_port_desc);
1127 }
1128
1129 /* (memory-port? obj) -> boolean */
1130
1131 static SCM
1132 gdbscm_memory_port_p (SCM obj)
1133 {
1134   return scm_from_bool (gdbscm_is_memory_port (obj));
1135 }
1136
1137 /* (memory-port-range port) -> (start end) */
1138
1139 static SCM
1140 gdbscm_memory_port_range (SCM port)
1141 {
1142   ioscm_memory_port *iomem;
1143
1144   SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1145                    memory_port_desc_name);
1146
1147   iomem = (ioscm_memory_port *) SCM_STREAM (port);
1148   return scm_list_2 (gdbscm_scm_from_ulongest (iomem->start),
1149                      gdbscm_scm_from_ulongest (iomem->end));
1150 }
1151
1152 /* (memory-port-read-buffer-size port) -> integer */
1153
1154 static SCM
1155 gdbscm_memory_port_read_buffer_size (SCM port)
1156 {
1157   ioscm_memory_port *iomem;
1158
1159   SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1160                    memory_port_desc_name);
1161
1162   iomem = (ioscm_memory_port *) SCM_STREAM (port);
1163   return scm_from_uint (iomem->read_buf_size);
1164 }
1165
1166 /* (set-memory-port-read-buffer-size! port size) -> unspecified
1167    An exception is thrown if read data is still buffered or if the port
1168    is unbuffered.  */
1169
1170 static SCM
1171 gdbscm_set_memory_port_read_buffer_size_x (SCM port, SCM size)
1172 {
1173   ioscm_memory_port *iomem;
1174
1175   SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1176                    memory_port_desc_name);
1177   SCM_ASSERT_TYPE (scm_is_integer (size), size, SCM_ARG2, FUNC_NAME,
1178                    _("integer"));
1179
1180   if (!scm_is_unsigned_integer (size, min_memory_port_buf_size,
1181                                 max_memory_port_buf_size))
1182     {
1183       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, size,
1184                                  out_of_range_buf_size);
1185     }
1186
1187   iomem = (ioscm_memory_port *) SCM_STREAM (port);
1188   ioscm_reinit_memory_port (port, scm_to_uint (size), iomem->write_buf_size,
1189                             FUNC_NAME);
1190
1191   return SCM_UNSPECIFIED;
1192 }
1193
1194 /* (memory-port-write-buffer-size port) -> integer */
1195
1196 static SCM
1197 gdbscm_memory_port_write_buffer_size (SCM port)
1198 {
1199   ioscm_memory_port *iomem;
1200
1201   SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1202                    memory_port_desc_name);
1203
1204   iomem = (ioscm_memory_port *) SCM_STREAM (port);
1205   return scm_from_uint (iomem->write_buf_size);
1206 }
1207
1208 /* (set-memory-port-write-buffer-size! port size) -> unspecified
1209    An exception is thrown if write data is still buffered or if the port
1210    is unbuffered.  */
1211
1212 static SCM
1213 gdbscm_set_memory_port_write_buffer_size_x (SCM port, SCM size)
1214 {
1215   ioscm_memory_port *iomem;
1216
1217   SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1218                    memory_port_desc_name);
1219   SCM_ASSERT_TYPE (scm_is_integer (size), size, SCM_ARG2, FUNC_NAME,
1220                    _("integer"));
1221
1222   if (!scm_is_unsigned_integer (size, min_memory_port_buf_size,
1223                                 max_memory_port_buf_size))
1224     {
1225       gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, size,
1226                                  out_of_range_buf_size);
1227     }
1228
1229   iomem = (ioscm_memory_port *) SCM_STREAM (port);
1230   ioscm_reinit_memory_port (port, iomem->read_buf_size, scm_to_uint (size),
1231                             FUNC_NAME);
1232
1233   return SCM_UNSPECIFIED;
1234 }
1235 \f
1236 /* Initialize gdb ports.  */
1237
1238 static const scheme_function port_functions[] =
1239 {
1240   { "input-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_input_port),
1241     "\
1242 Return gdb's input port." },
1243
1244   { "output-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_output_port),
1245     "\
1246 Return gdb's output port." },
1247
1248   { "error-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_error_port),
1249     "\
1250 Return gdb's error port." },
1251
1252   { "stdio-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_stdio_port_p),
1253     "\
1254 Return #t if the object is a gdb:stdio-port." },
1255
1256   { "open-memory", 0, 0, 1, as_a_scm_t_subr (gdbscm_open_memory),
1257     "\
1258 Return a port that can be used for reading/writing inferior memory.\n\
1259 \n\
1260   Arguments: [#:mode string] [#:start address] [#:size integer]\n\
1261   Returns: A port object." },
1262
1263   { "memory-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_p),
1264     "\
1265 Return #t if the object is a memory port." },
1266
1267   { "memory-port-range", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_range),
1268     "\
1269 Return the memory range of the port as (start end)." },
1270
1271   { "memory-port-read-buffer-size", 1, 0, 0,
1272     as_a_scm_t_subr (gdbscm_memory_port_read_buffer_size),
1273     "\
1274 Return the size of the read buffer for the memory port." },
1275
1276   { "set-memory-port-read-buffer-size!", 2, 0, 0,
1277     as_a_scm_t_subr (gdbscm_set_memory_port_read_buffer_size_x),
1278     "\
1279 Set the size of the read buffer for the memory port.\n\
1280 \n\
1281   Arguments: port integer\n\
1282   Returns: unspecified." },
1283
1284   { "memory-port-write-buffer-size", 1, 0, 0,
1285     as_a_scm_t_subr (gdbscm_memory_port_write_buffer_size),
1286     "\
1287 Return the size of the write buffer for the memory port." },
1288
1289   { "set-memory-port-write-buffer-size!", 2, 0, 0,
1290     as_a_scm_t_subr (gdbscm_set_memory_port_write_buffer_size_x),
1291     "\
1292 Set the size of the write buffer for the memory port.\n\
1293 \n\
1294   Arguments: port integer\n\
1295   Returns: unspecified." },
1296
1297   END_FUNCTIONS
1298 };
1299
1300 static const scheme_function private_port_functions[] =
1301 {
1302 #if 0 /* TODO */
1303   { "%with-gdb-input-from-port", 2, 0, 0,
1304     as_a_scm_t_subr (gdbscm_percent_with_gdb_input_from_port),
1305     "\
1306 Temporarily set GDB's input port to PORT and then invoke THUNK.\n\
1307 \n\
1308   Arguments: port thunk\n\
1309   Returns: The result of calling THUNK.\n\
1310 \n\
1311 This procedure is experimental." },
1312 #endif
1313
1314   { "%with-gdb-output-to-port", 2, 0, 0,
1315     as_a_scm_t_subr (gdbscm_percent_with_gdb_output_to_port),
1316     "\
1317 Temporarily set GDB's output port to PORT and then invoke THUNK.\n\
1318 \n\
1319   Arguments: port thunk\n\
1320   Returns: The result of calling THUNK.\n\
1321 \n\
1322 This procedure is experimental." },
1323
1324   { "%with-gdb-error-to-port", 2, 0, 0,
1325     as_a_scm_t_subr (gdbscm_percent_with_gdb_error_to_port),
1326     "\
1327 Temporarily set GDB's error port to PORT and then invoke THUNK.\n\
1328 \n\
1329   Arguments: port thunk\n\
1330   Returns: The result of calling THUNK.\n\
1331 \n\
1332 This procedure is experimental." },
1333
1334   END_FUNCTIONS
1335 };
1336
1337 void
1338 gdbscm_initialize_ports (void)
1339 {
1340   /* Save the original stdio ports for debugging purposes.  */
1341
1342   orig_input_port_scm = scm_current_input_port ();
1343   orig_output_port_scm = scm_current_output_port ();
1344   orig_error_port_scm = scm_current_error_port ();
1345
1346   /* Set up the stdio ports.  */
1347
1348   ioscm_init_gdb_stdio_port ();
1349   input_port_scm = ioscm_make_gdb_stdio_port (0);
1350   output_port_scm = ioscm_make_gdb_stdio_port (1);
1351   error_port_scm = ioscm_make_gdb_stdio_port (2);
1352
1353   /* Set up memory ports.  */
1354
1355   ioscm_init_memory_port_type ();
1356
1357   /* Install the accessor functions.  */
1358
1359   gdbscm_define_functions (port_functions, 1);
1360   gdbscm_define_functions (private_port_functions, 0);
1361
1362   /* Keyword args for open-memory.  */
1363
1364   mode_keyword = scm_from_latin1_keyword ("mode");
1365   start_keyword = scm_from_latin1_keyword ("start");
1366   size_keyword = scm_from_latin1_keyword ("size");
1367
1368   /* Error message text for "out of range" memory port buffer sizes.  */
1369
1370   out_of_range_buf_size = xstrprintf ("size not between %u - %u",
1371                                       min_memory_port_buf_size,
1372                                       max_memory_port_buf_size);
1373 }