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