/* places a single char in the input buffer. */ static int sf_fill_input (SCM port) { SCM p = SCM_PACK (SCM_STREAM (port)); SCM ans; scm_t_port *pt; ans = scm_call_0 (SCM_SIMPLE_VECTOR_REF (p, 3)); /* get char. */ if (scm_is_false (ans) || SCM_EOF_OBJECT_P (ans)) return EOF; SCM_ASSERT (SCM_CHARP (ans), ans, SCM_ARG1, "sf_fill_input"); pt = SCM_PTAB_ENTRY (port); if (pt->encoding == NULL) { scm_t_port *pt = SCM_PTAB_ENTRY (port); *pt->read_buf = SCM_CHAR (ans); pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + 1; return *pt->read_buf; } else scm_ungetc_unlocked (SCM_CHAR (ans), port); return SCM_CHAR (ans); }
static int gdbscm_memory_port_fill_input (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); size_t to_read; /* "current" is the offset of the first byte we want to read. */ gdb_assert (iomem->current <= iomem->size); if (iomem->current == iomem->size) return EOF; /* Don't read outside the allowed memory range. */ to_read = pt->read_buf_size; if (to_read > iomem->size - iomem->current) to_read = iomem->size - iomem->current; if (target_read_memory (iomem->start + iomem->current, pt->read_buf, to_read) != 0) gdbscm_memory_error (FUNC_NAME, _("error reading memory"), SCM_EOL); iomem->current += to_read; pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + to_read; return *pt->read_buf; }
static void gdbscm_memory_port_flush (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); size_t to_write = pt->write_pos - pt->write_buf; if (to_write == 0) return; /* 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 (to_write > iomem->size - iomem->current) { gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (to_write), _("writing beyond end of memory range")); } if (target_write_memory (iomem->start + iomem->current, pt->write_buf, to_write) != 0) gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL); iomem->current += to_write; pt->write_pos = pt->write_buf; pt->rw_active = SCM_PORT_NEITHER; }
/* Return a new port of type PORT_TYPE. */ static inline SCM make_port (scm_t_bits port_type) { SCM port; char *c_buffer; scm_t_port *c_port; c_buffer = scm_gc_calloc (PORT_BUFFER_SIZE, "custom-port-buffer"); port = scm_new_port_table_entry (port_type); /* Associate C_BUFFER with PORT, for test purposes. */ SCM_SETSTREAM (port, (scm_t_bits) c_buffer); /* Use C_BUFFER as PORT's internal buffer. */ c_port = SCM_PTAB_ENTRY (port); c_port->read_pos = c_port->read_buf = (unsigned char *) c_buffer; c_port->read_end = (unsigned char *) c_buffer + PORT_BUFFER_SIZE; c_port->read_buf_size = PORT_BUFFER_SIZE; /* Mark PORT as open and readable. */ SCM_SET_CELL_TYPE (port, port_type | SCM_OPN | SCM_RDNG); return port; }
static void gdbscm_memory_port_end_input (SCM port, int offset) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); size_t remaining = pt->read_end - pt->read_pos; /* Note: Use of "int offset" is specified by Guile ports API. */ if ((offset < 0 && remaining + offset > remaining) || (offset > 0 && remaining + offset < remaining)) { gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset), _("overflow in offset calculation")); } offset += remaining; if (offset > 0) { pt->read_pos = pt->read_end; /* Throw error if unread-char used at beginning of file then attempting to write. Seems correct. */ if (!ioscm_lseek_address (iomem, -offset, SEEK_CUR)) { gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset), _("bad offset")); } } pt->rw_active = SCM_PORT_NEITHER; }
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; } }
/* Create a new string from the buffer of PORT, a string port, converting from PORT's encoding to the standard string representation. */ SCM scm_strport_to_string (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (pt->read_buf_size == 0) return scm_nullstr; return scm_from_port_stringn ((char *)pt->read_buf, pt->read_buf_size, port); }
static int st_fill_input (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (pt->read_pos >= pt->read_end) return EOF; else return *pt->read_pos; }
/* create FPORT buffer with specified sizes (or -1 to use default size or 0 for no buffer. */ static void scm_fport_buffer_add (SCM port, long read_size, int write_size) #define FUNC_NAME "scm_fport_buffer_add" { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (read_size == -1 || write_size == -1) { size_t default_size; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE struct stat st; scm_t_fport *fp = SCM_FSTREAM (port); default_size = (fstat (fp->fdes, &st) == -1) ? default_buffer_size : st.st_blksize; #else default_size = default_buffer_size; #endif if (read_size == -1) read_size = default_size; if (write_size == -1) write_size = default_size; } if (SCM_INPUT_PORT_P (port) && read_size > 0) { pt->read_buf = scm_gc_malloc_pointerless (read_size, "port buffer"); pt->read_pos = pt->read_end = pt->read_buf; pt->read_buf_size = read_size; } else { pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf; pt->read_buf_size = 1; } if (SCM_OUTPUT_PORT_P (port) && write_size > 0) { pt->write_buf = scm_gc_malloc_pointerless (write_size, "port buffer"); pt->write_pos = pt->write_buf; pt->write_buf_size = write_size; } else { pt->write_buf = pt->write_pos = &pt->shortbuf; pt->write_buf_size = 1; } pt->write_end = pt->write_buf + pt->write_buf_size; if (read_size > 0 || write_size > 0) SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~SCM_BUF0); else SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0); }
static void st_end_input (SCM port, int offset) { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (pt->read_pos - pt->read_buf < offset) scm_misc_error ("st_end_input", "negative position", SCM_EOL); pt->write_pos = (unsigned char *) (pt->read_pos = pt->read_pos - offset); pt->rw_active = SCM_PORT_NEITHER; }
static void sf_flush (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); SCM stream = SCM_PACK (pt->stream); SCM f = SCM_SIMPLE_VECTOR_REF (stream, 2); if (scm_is_true (f)) scm_call_0 (f); }
static void st_truncate (SCM port, scm_t_off length) { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (length > pt->write_buf_size) st_resize_port (pt, length); pt->read_buf_size = length; pt->read_end = pt->read_buf + length; if (pt->read_pos > pt->read_end) pt->read_pos = pt->write_pos = pt->read_end; }
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); iomem = (ioscm_memory_port *) scm_gc_malloc_pointerless (sizeof (*iomem), "memory port"); iomem->start = start; iomem->end = end; iomem->size = end - start; iomem->current = 0; if (buffered) { iomem->read_buf_size = default_read_buf_size; iomem->write_buf_size = default_write_buf_size; } else { iomem->read_buf_size = 1; iomem->write_buf_size = 1; } pt = SCM_PTAB_ENTRY (port); /* Match the expectation of `binary-port?'. */ pt->encoding = NULL; pt->rw_random = 1; pt->read_buf_size = iomem->read_buf_size; pt->write_buf_size = iomem->write_buf_size; if (buffered) { pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size); pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size); } else { pt->read_buf = &pt->shortbuf; pt->write_buf = &pt->shortbuf; } pt->read_pos = pt->read_end = pt->read_buf; pt->write_pos = pt->write_buf; pt->write_end = pt->write_buf + pt->write_buf_size; SCM_SETSTREAM (port, iomem); }
/* Perform the synchronisation required for switching from input to output on the port. Clear the read buffer and adjust the file position for unread bytes. */ static void mu_port_end_input (SCM port, int offset) { struct mu_port *mp = MU_PORT (port); scm_port *pt = SCM_PTAB_ENTRY (port); int delta = pt->read_end - pt->read_pos; offset += delta; if (offset > 0) { pt->read_pos = pt->read_end; mp->offset -= delta; } pt->rw_active = SCM_PORT_NEITHER; }
static int mu_port_close (SCM port) { struct mu_port *mp = MU_PORT (port); scm_port *pt = SCM_PTAB_ENTRY (port); mu_port_flush (port); mu_stream_close (mp->stream); SCM_SETSTREAM (port, NULL); if (pt->read_buf != &pt->shortbuf) free (pt->read_buf); if (pt->write_buf != &pt->shortbuf) free (pt->write_buf); free (mp); return 0; }
static int gdbscm_memory_port_close (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); gdbscm_memory_port_flush (port); if (pt->read_buf == pt->putback_buf) pt->read_buf = pt->saved_read_buf; if (pt->read_buf != &pt->shortbuf) xfree (pt->read_buf); if (pt->write_buf != &pt->shortbuf) xfree (pt->write_buf); scm_gc_free (iomem, sizeof (*iomem), "memory port"); return 0; }
static void st_write (SCM port, const void *data, size_t size) { scm_t_port *pt = SCM_PTAB_ENTRY (port); if (size > pt->write_end - pt->write_pos) st_resize_port (pt, max (pt->write_buf_size * 2, pt->write_end - pt->write_pos + size)); memcpy ((char *) pt->write_pos, data, size); pt->read_pos = (pt->write_pos += size); if (pt->read_pos > pt->read_end) { pt->read_end = (unsigned char *) pt->read_pos; pt->read_buf_size = pt->read_end - pt->read_buf; } }
static void mu_port_flush (SCM port) { struct mu_port *mp = MU_PORT (port); scm_port *pt = SCM_PTAB_ENTRY (port); int wrsize = pt->write_pos - pt->write_buf; size_t n; if (wrsize) { if (mu_stream_write (mp->stream, (const char*)pt->write_buf, wrsize, mp->offset, &n)) return; mp->offset += n; } pt->write_pos = pt->write_buf; pt->rw_active = SCM_PORT_NEITHER; }
/* Read one byte from PORT. */ static int fill_input (SCM port) { int result; scm_t_port *c_port = SCM_PTAB_ENTRY (port); /* Make sure that C_PORT's internal buffer wasn't changed behind our back. See http://lists.gnu.org/archive/html/guile-devel/2008-11/msg00042.html for an example where this assumption matters. */ assert (c_port->read_buf == (unsigned char *) SCM_STREAM (port)); assert (c_port->read_buf_size == PORT_BUFFER_SIZE); if (c_port->read_pos >= c_port->read_end) result = EOF; else result = (int) *c_port->read_pos++; return result; }
static void mu_port_alloc_buffer (SCM port, size_t read_size, size_t write_size) { scm_port *pt = SCM_PTAB_ENTRY (port); static char *s_mu_port_alloc_buffer = "mu_port_alloc_buffer"; if (!read_size) read_size = DEFAULT_BUF_SIZE; if (!write_size) write_size = DEFAULT_BUF_SIZE; if (SCM_INPUT_PORT_P (port)) { pt->read_buf = malloc (read_size); if (pt->read_buf == NULL) scm_memory_error (s_mu_port_alloc_buffer); pt->read_pos = pt->read_end = pt->read_buf; pt->read_buf_size = read_size; } else { pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf; pt->read_buf_size = 1; } if (SCM_OUTPUT_PORT_P (port)) { pt->write_buf = malloc (write_size); if (pt->write_buf == NULL) scm_memory_error (s_mu_port_alloc_buffer); pt->write_pos = pt->write_buf; pt->write_buf_size = write_size; pt->write_end = pt->write_buf + pt->write_buf_size; } else { pt->write_buf = pt->write_pos = &pt->shortbuf; pt->write_buf_size = 1; } SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) & ~SCM_BUF0); }
/* Complete the processing of buffered output data. Currently this callback makes no effect because the channel CHANNEL uses unbuffered output. */ static void ptob_flush (SCM channel) #define FUNC_NAME "ptob_flush" { scm_port *pt = SCM_PTAB_ENTRY (channel); struct channel_data *cd = _scm_to_channel_data (channel); size_t wrsize = pt->write_pos - pt->write_buf; if (wrsize) { int res = ssh_channel_write (cd->ssh_channel, pt->write_buf, wrsize); if (res == SSH_ERROR) { ssh_session session = ssh_channel_get_session (cd->ssh_channel); guile_ssh_session_error1 (FUNC_NAME, session, channel); } } pt->write_pos = pt->write_buf; }
static void mu_port_write (SCM port, const void *data, size_t size) { scm_port *pt = SCM_PTAB_ENTRY (port); size_t remaining = size; char *input = (char*) data; while (remaining > 0) { int space = pt->write_end - pt->write_pos; int write_len = (remaining > space) ? space : remaining; memcpy (pt->write_pos, input, write_len); pt->write_pos += write_len; remaining -= write_len; input += write_len; if (write_len == space) mu_port_flush (port); } }
SCM mu_port_make_from_stream (SCM msg, mu_stream_t stream, long mode) { struct mu_port *mp; SCM port; scm_port *pt; mp = scm_gc_malloc (sizeof (struct mu_port), "mu-port"); mp->msg = msg; mp->stream = stream; mp->offset = 0; port = scm_new_port_table_entry (scm_tc16_smuport | mode); pt = SCM_PTAB_ENTRY (port); pt->rw_random = mu_stream_is_seekable (stream); SCM_SETSTREAM (port, mp); mu_port_alloc_buffer (port, 0, 0); /* FIXME: SCM_PTAB_ENTRY (port)->file_name = "name";*/ return port; }
static int mu_port_fill_input (SCM port) { struct mu_port *mp = MU_PORT (port); scm_port *pt = SCM_PTAB_ENTRY (port); size_t nread = 0; int status; status = mu_stream_read (mp->stream, (char*) pt->read_buf, pt->read_buf_size, mp->offset, &nread); if (status) mu_scm_error ("mu_port_fill_input", status, "Error reading from stream", SCM_BOOL_F); if (nread == 0) return EOF; mp->offset += nread; pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + nread; return *pt->read_buf; }
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; /* This is heavily copied from scm_fport_buffer_add. */ if (!writing && size > 0) { pt->read_buf = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer"); pt->read_pos = pt->read_end = pt->read_buf; pt->read_buf_size = size; } else { pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf; pt->read_buf_size = 1; } if (writing && size > 0) { pt->write_buf = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer"); pt->write_pos = pt->write_buf; pt->write_buf_size = size; } else { pt->write_buf = pt->write_pos = &pt->shortbuf; pt->write_buf_size = 1; } pt->write_end = pt->write_buf + pt->write_buf_size; }
/* Read data from the channel. Return EOF if no data is available or throw `guile-ssh-error' if an error occured. */ static int ptob_fill_input (SCM channel) #define FUNC_NAME "ptob_fill_input" { struct channel_data *cd = _scm_to_channel_data (channel); scm_port *pt = SCM_PTAB_ENTRY (channel); int res; if (! ssh_channel_is_open (cd->ssh_channel)) return EOF; /* Update state of the underlying channel and check whether we have data to read or not. */ res = ssh_channel_poll (cd->ssh_channel, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error polling channel", channel); else if (res == SSH_EOF) return EOF; res = ssh_channel_read (cd->ssh_channel, pt->read_buf, pt->read_buf_size, cd->is_stderr); if (res == SSH_ERROR) guile_ssh_error1 (FUNC_NAME, "Error reading from the channel", channel); /* `ssh_channel_read' sometimes returns 0 even if `ssh_channel_poll' returns a positive value. So we must ensure that res != 0 otherwise an assertion in `scm_i_fill_input' won't be meet (see `ports.c' in Guile 2.0.9). */ if ((! res) || (res == SSH_AGAIN)) return EOF; pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + res; return *pt->read_buf; }
static int ioscm_fill_input (SCM port) { /* Borrowed from libguile/fports.c. */ long count; scm_t_port *pt = SCM_PTAB_ENTRY (port); /* If we're called on stdout,stderr, punt. */ if (! scm_is_eq (port, input_port_scm)) return (scm_t_wchar) EOF; /* Set errno and return -1? */ gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); count = ui_file_read (gdb_stdin, (char *) pt->read_buf, pt->read_buf_size); if (count == -1) scm_syserror (FUNC_NAME); if (count == 0) return (scm_t_wchar) EOF; pt->read_pos = pt->read_buf; pt->read_end = pt->read_buf + count; return *pt->read_buf; }
static int #else static void #endif ptob_close (SCM channel) { struct channel_data *ch = _scm_to_channel_data (channel); #if USING_GUILE_BEFORE_2_2 scm_port *pt = SCM_PTAB_ENTRY (channel); ptob_flush (channel); #endif if (ch && ssh_channel_is_open (ch->ssh_channel)) { _gssh_log_debug ("ptob_close", "closing and freeing the channel...", channel); ssh_channel_close (ch->ssh_channel); ssh_channel_free (ch->ssh_channel); _gssh_log_debug1 ("ptob_close", "closing and freeing the channel... done"); } else { _gssh_log_debug1 ("ptob_close", "the channel is already freeed."); } SCM_SETSTREAM (channel, NULL); #if USING_GUILE_BEFORE_2_2 scm_gc_free (pt->write_buf, pt->write_buf_size, "port write buffer"); scm_gc_free (pt->read_buf, pt->read_buf_size, "port read buffer"); return 0; #endif }
/* Print the CHANNEL object to port PORT. */ static int print_channel (SCM channel, SCM port, scm_print_state *pstate) { struct channel_data *ch = NULL; #if USING_GUILE_BEFORE_2_2 if (SCM_PTAB_ENTRY (channel)) ch = _scm_to_channel_data (channel); #else ch = _scm_to_channel_data (channel); #endif scm_puts ("#<", port); if (! ch) { scm_puts ("unknown channel (freed) ", port); } else { scm_print_port_mode (channel, port); scm_puts ("channel ", port); if (SCM_OPPORTP (channel)) { int is_open = ssh_channel_is_open (ch->ssh_channel); scm_puts (is_open ? "(open) " : "(closed) ", port); } else { scm_puts ("(closed) ", port); } } scm_display (_scm_object_hex_address (channel), port); scm_puts (">", port); return 1; }
static mu_off_t mu_port_seek (SCM port, mu_off_t offset, int whence) { struct mu_port *mp = MU_PORT (port); scm_port *pt = SCM_PTAB_ENTRY (port); mu_off_t size = 0; if (whence == SEEK_CUR && offset == 0) return mp->offset; if (pt->rw_active == SCM_PORT_WRITE) { mu_port_flush (port); } else if (pt->rw_active == SCM_PORT_READ) { scm_end_input (port); } mu_stream_size (mp->stream, &size); switch (whence) { case SEEK_SET: break; case SEEK_CUR: offset += mp->offset; break; case SEEK_END: offset += size; } if (offset > size) return -1; mp->offset = offset; return offset; }