summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/fports.c100
-rw-r--r--libguile/fports.h10
-rw-r--r--libguile/gc.c4
-rw-r--r--libguile/gdbint.c19
-rw-r--r--libguile/ports.c285
-rw-r--r--libguile/ports.h42
-rw-r--r--libguile/scmsigs.c17
-rw-r--r--libguile/vports.c19
8 files changed, 312 insertions, 184 deletions
diff --git a/libguile/fports.c b/libguile/fports.c
index 53053aaa1..bc1e516e3 100644
--- a/libguile/fports.c
+++ b/libguile/fports.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ static void
scm_fport_buffer_add (SCM port, int read_size, int write_size)
{
struct scm_fport *fp = SCM_FSTREAM (port);
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
char *s_scm_fport_buffer_add = "scm_fport_buffer_add";
if (read_size == -1 || write_size == -1)
@@ -91,19 +91,23 @@ scm_fport_buffer_add (SCM port, int read_size, int write_size)
if (SCM_INPORTP (port) && read_size > 0)
{
- pt->read_buf = scm_must_malloc (read_size, s_scm_fport_buffer_add);
+ pt->read_buf = malloc (read_size);
+ if (pt->read_buf == NULL)
+ scm_memory_error (s_scm_fport_buffer_add);
pt->read_pos = pt->read_end = pt->read_buf;
pt->read_buf_size = read_size;
}
else
{
- pt->read_buf = pt->read_pos = pt->read_end = &pt->shortbuf;
+ pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
pt->read_buf_size = 1;
}
if (SCM_OUTPORTP (port) && write_size > 0)
{
- pt->write_buf = scm_must_malloc (write_size, s_scm_fport_buffer_add);
+ pt->write_buf = malloc (write_size);
+ if (pt->write_buf == NULL)
+ scm_memory_error (s_scm_fport_buffer_add);
pt->write_pos = pt->write_buf;
pt->write_buf_size = write_size;
}
@@ -125,7 +129,7 @@ SCM
scm_setvbuf (SCM port, SCM mode, SCM size)
{
int cmode, csize;
- struct scm_port_table *pt;
+ scm_port *pt;
port = SCM_COERCE_OUTPORT (port);
@@ -279,7 +283,7 @@ scm_fdes_to_port (int fdes, char *mode, SCM name)
{
long mode_bits = scm_mode_bits (mode);
SCM port;
- struct scm_port_table * pt;
+ scm_port *pt;
SCM_NEWCELL (port);
SCM_DEFER_INTS;
@@ -289,11 +293,12 @@ scm_fdes_to_port (int fdes, char *mode, SCM name)
{
struct scm_fport *fp
- = (struct scm_fport *) scm_must_malloc (sizeof (struct scm_fport),
- "scm_fdes_to_port");
+ = (struct scm_fport *) malloc (sizeof (struct scm_fport));
+ if (fp == NULL)
+ scm_memory_error ("scm_fdes_to_port");
fp->fdes = fdes;
- fp->random = SCM_FDES_RANDOM_P (fdes);
-
+ pt->rw_random = (mode_bits & SCM_RDNG) && (mode_bits & SCM_WRTNG)
+ && SCM_FDES_RANDOM_P (fdes);
SCM_SETSTREAM (port, fp);
if (mode_bits & SCM_BUF0)
scm_fport_buffer_add (port, 0, 0);
@@ -343,18 +348,6 @@ fport_input_waiting_p (SCM port)
#endif
}
-/* Clear an fport's read buffer and return buffered chars. */
-char *
-scm_fport_drain_input (SCM port, int *count_return)
-{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
- char *result = pt->read_pos;
-
- *count_return = pt->read_end - pt->read_pos;
- pt->read_pos = pt->read_end;
- return result;
-}
-
static int prinfport SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
@@ -419,17 +412,9 @@ static int
fport_fill_buffer (SCM port)
{
int count;
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
struct scm_fport *fp = SCM_FSTREAM (port);
- if (fp->random)
- {
- /* flush any write buffer first: fix file position and allow the
- newly written chars to be read. */
- if (pt->write_pos > pt->write_buf)
- local_fflush (port);
- pt->write_needs_seek = 1;
- }
#ifdef GUILE_ISELECT
fport_wait_for_input (port);
#endif
@@ -450,17 +435,26 @@ static off_t
local_seek (SCM port, off_t offset, int whence)
{
struct scm_fport *fp = SCM_FSTREAM (port);
-
+
return lseek (fp->fdes, offset, whence);
}
+static void
+local_ftruncate (SCM port, off_t length)
+{
+ struct scm_fport *fp = SCM_FSTREAM (port);
+
+ if (ftruncate (fp->fdes, length) == -1)
+ scm_syserror ("ftruncate");
+}
+
/* becomes 1 when process is exiting: exception handling is disabled. */
extern int terminating;
static void
local_fflush (SCM port)
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
struct scm_fport *fp = SCM_FSTREAM (port);
char *ptr = pt->write_buf;
int init_size = pt->write_pos - pt->write_buf;
@@ -505,24 +499,50 @@ local_fflush (SCM port)
remaining -= count;
}
pt->write_pos = pt->write_buf;
+ pt->rw_active = 0;
+}
+
+/* clear the read buffer and adjust the file position for unread bytes.
+ this is only called if the port has rw_random set. */
+static void
+local_read_flush (SCM port)
+{
+ struct scm_fport *fp = SCM_FSTREAM (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
+ int offset = pt->read_end - pt->read_pos;
+
+ if (SCM_CRDYP (port))
+ {
+ offset += SCM_N_READY_CHARS (port);
+ SCM_CLRDY (port);
+ }
+ if (offset > 0)
+ {
+ pt->read_pos = pt->read_end;
+ /* will throw error if unread-char used at beginning of file
+ then attempting to write. seems correct. */
+ if (lseek (fp->fdes, -offset, SEEK_CUR) == -1)
+ scm_syserror ("local_read_flush");
+ }
+ pt->rw_active = 0;
}
static int
local_fclose (SCM port)
{
struct scm_fport *fp = SCM_FSTREAM (port);
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
int rv;
-
+
local_fflush (port);
SCM_SYSCALL (rv = close (fp->fdes));
if (rv == -1 && errno != EBADF)
scm_syserror ("local_fclose");
if (pt->read_buf != &pt->shortbuf)
- scm_must_free (pt->read_buf);
+ free (pt->read_buf);
if (pt->write_buf != &pt->shortbuf)
- scm_must_free (pt->write_buf);
- scm_must_free ((char *) fp);
+ free (pt->write_buf);
+ free ((char *) fp);
return rv;
}
@@ -533,9 +553,11 @@ scm_ptobfuns scm_fptob =
prinfport,
0,
local_fflush,
+ local_read_flush,
local_fclose,
fport_fill_buffer,
local_seek,
+ local_ftruncate,
fport_input_waiting_p,
};
diff --git a/libguile/fports.h b/libguile/fports.h
index 2659318de..29bbb6446 100644
--- a/libguile/fports.h
+++ b/libguile/fports.h
@@ -2,7 +2,7 @@
#ifndef FPORTSH
#define FPORTSH
-/* Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,13 +53,6 @@
/* struct allocated for each buffered FPORT. */
struct scm_fport {
int fdes; /* file descriptor. */
-
- /* if fdes supports random access (i.e., can change position using lseek)
- then read/write ports reset the write position to account for buffered
- chars whenever switching from reading to writing. it wouldn't need to
- be done if fdes is in append mode, but that can be changed at any time
- and it would be more work to check for it. */
- int random; /* whether fdes supports random-access. */
};
#define SCM_FSTREAM(x) ((struct scm_fport *) SCM_STREAM (x))
@@ -82,7 +75,6 @@ extern void scm_setfileno (FILE *fs, int fd);
extern void scm_evict_ports (int fd);
extern SCM scm_open_file (SCM filename, SCM modes);
extern SCM scm_fdes_to_port (int fdes, char *mode, SCM name);
-extern char *scm_fport_drain_input (SCM port, int *count_return);
extern void scm_init_fports SCM_P ((void));
#endif /* FPORTSH */
diff --git a/libguile/gc.c b/libguile/gc.c
index 572d8fcf1..d434a046b 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -1922,8 +1922,8 @@ scm_init_storage (scm_sizet init_heap_size)
return 1;
/* Initialise the list of ports. */
- scm_port_table = (struct scm_port_table **) malloc ((long) (sizeof (struct scm_port_table)
- * scm_port_table_room));
+ scm_port_table = (scm_port **)
+ malloc (sizeof (scm_port *) * scm_port_table_room);
if (!scm_port_table)
return 1;
diff --git a/libguile/gdbint.c b/libguile/gdbint.c
index 867d8e7a8..73c00a1f6 100644
--- a/libguile/gdbint.c
+++ b/libguile/gdbint.c
@@ -208,11 +208,10 @@ gdb_read (str)
}
SCM_BEGIN_FOREIGN_BLOCK;
unmark_port (gdb_input_port);
- /* Replace string in input port and reset stream */
- ans = SCM_CDR (SCM_STREAM (gdb_input_port));
- SCM_SETCHARS (ans, str);
- SCM_SETLENGTH (ans, strlen (str), scm_tc7_string);
- SCM_SETCAR (SCM_STREAM (gdb_input_port), SCM_INUM0);
+ scm_lseek (gdb_input_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
+ scm_puts (str, gdb_input_port);
+ scm_ftruncate (gdb_input_port, SCM_UNDEFINED);
+ scm_lseek (gdb_input_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
/* Read one object */
tok_buf_mark_p = SCM_GC8MARKP (tok_buf);
SCM_CLRGC8MARK (tok_buf);
@@ -271,10 +270,10 @@ gdb_print (obj)
RESET_STRING;
SCM_BEGIN_FOREIGN_BLOCK;
/* Reset stream */
- SCM_SETCAR (SCM_STREAM (gdb_output_port), SCM_INUM0);
+ scm_lseek (gdb_output_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
scm_write (obj, gdb_output_port);
- scm_display (SCM_MAKICHR (0), gdb_output_port);
- SEND_STRING (SCM_CHARS (SCM_CDR (SCM_STREAM (gdb_output_port))));
+ scm_ftruncate (gdb_output_port, SCM_UNDEFINED);
+ SEND_STRING (SCM_CHARS (SCM_STREAM (gdb_output_port)));
SCM_END_FOREIGN_BLOCK;
return 0;
}
@@ -311,14 +310,14 @@ scm_init_gdbint ()
scm_print_carefully_p = 0;
port = scm_mkstrport (SCM_INUM0,
- scm_make_string (SCM_MAKINUM (80), SCM_UNDEFINED),
+ scm_make_string (SCM_MAKINUM (0), SCM_UNDEFINED),
SCM_OPN | SCM_WRTNG,
s);
gdb_output_port = scm_permanent_object (port);
port = scm_mkstrport (SCM_INUM0,
scm_make_string (SCM_MAKINUM (0), SCM_UNDEFINED),
- SCM_OPN | SCM_RDNG,
+ SCM_OPN | SCM_RDNG | SCM_WRTNG,
s);
gdb_input_port = scm_permanent_object (port);
diff --git a/libguile/ports.c b/libguile/ports.c
index be425601a..306eaacf2 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -107,8 +107,11 @@ scm_newptob (ptob)
scm_ptobs[scm_numptob].print = ptob->print;
scm_ptobs[scm_numptob].equalp = ptob->equalp;
scm_ptobs[scm_numptob].fflush = ptob->fflush;
+ scm_ptobs[scm_numptob].read_flush = ptob->read_flush;
scm_ptobs[scm_numptob].fclose = ptob->fclose;
scm_ptobs[scm_numptob].fill_buffer = ptob->fill_buffer;
+ scm_ptobs[scm_numptob].seek = ptob->seek;
+ scm_ptobs[scm_numptob].ftruncate = ptob->ftruncate;
scm_ptobs[scm_numptob].input_waiting_p = ptob->input_waiting_p;
scm_numptob++;
}
@@ -135,7 +138,7 @@ scm_char_ready_p (port)
return SCM_BOOL_T;
else
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
if (pt->read_pos < pt->read_end)
return SCM_BOOL_T;
@@ -144,7 +147,7 @@ scm_char_ready_p (port)
scm_ptobfuns *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
if (ptob->input_waiting_p)
- return ((ptob->input_waiting_p) (port)) ? SCM_BOOL_T : SCM_BOOL_F;
+ return (ptob->input_waiting_p (port)) ? SCM_BOOL_T : SCM_BOOL_F;
else
return SCM_BOOL_T;
}
@@ -156,35 +159,32 @@ SCM_PROC (s_drain_input, "drain-input", 1, 0, 0, scm_drain_input);
SCM
scm_drain_input (SCM port)
{
- char *fp_buf = NULL;
- int fp_count = 0;
+ SCM result;
+ scm_port *pt = SCM_PTAB_ENTRY (port);
+ int p_count;
+ char *dst;
+ char *p_buf;
SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port), port, SCM_ARG1,
s_drain_input);
- if (SCM_FPORTP (port))
+
+ p_count = (SCM_CRDYP (port)) ? SCM_N_READY_CHARS (port) : 0;
+ result = scm_makstr (p_count + pt->read_end - pt->read_pos, 0);
+ dst = SCM_CHARS (result);
+ p_buf = SCM_PTAB_ENTRY (port)->cp;
+
+ while (p_count > 0)
{
- fp_buf = scm_fport_drain_input (port, &fp_count);
+ *dst++ = *p_buf--;
+ p_count--;
}
- {
- int p_count = (SCM_CRDYP (port)) ? SCM_N_READY_CHARS (port) : 0;
- SCM result = scm_makstr (p_count + fp_count, 0);
- char *dst = SCM_CHARS (result);
- char *p_buf = SCM_PTAB_ENTRY (port)->cp;
-
- while (p_count > 0)
- {
- *dst++ = *p_buf--;
- p_count--;
- }
- while (fp_count > 0)
- {
- *dst++ = *fp_buf++;
- fp_count--;
- }
-
- SCM_CLRDY (port);
- return result;
- }
+ SCM_CLRDY (port);
+
+ while (pt->read_pos < pt->read_end)
+ {
+ *dst++ = *(pt->read_pos++);
+ }
+ return result;
}
@@ -263,47 +263,52 @@ scm_set_current_error_port (port)
}
-/* The port table --- a table of all the open ports. */
+/* The port table --- an array of pointers to ports. */
-struct scm_port_table **scm_port_table;
+scm_port **scm_port_table;
int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
int scm_port_table_room = 20; /* Size of the array. */
/* Add a port to the table. */
-struct scm_port_table *
+scm_port *
scm_add_to_port_table (port)
SCM port;
{
+ scm_port *entry;
+
if (scm_port_table_size == scm_port_table_room)
{
void *newt = realloc ((char *) scm_port_table,
- (scm_sizet) (sizeof (struct scm_port_table *)
+ (scm_sizet) (sizeof (scm_port *)
* scm_port_table_room * 2));
if (newt == NULL)
- {
- scm_memory_error ("scm_add_to_port_table");
- }
- scm_port_table = (struct scm_port_table **) newt;
+ scm_memory_error ("scm_add_to_port_table");
+ scm_port_table = (scm_port **) newt;
scm_port_table_room *= 2;
}
- scm_port_table[scm_port_table_size] = ((struct scm_port_table *)
- scm_must_malloc (sizeof (struct scm_port_table),
- "system port table"));
- scm_port_table[scm_port_table_size]->port = port;
- scm_port_table[scm_port_table_size]->entry = scm_port_table_size;
- scm_port_table[scm_port_table_size]->revealed = 0;
- scm_port_table[scm_port_table_size]->stream = 0;
- scm_port_table[scm_port_table_size]->file_name = SCM_BOOL_F;
- scm_port_table[scm_port_table_size]->line_number = 0;
- scm_port_table[scm_port_table_size]->column_number = 0;
- scm_port_table[scm_port_table_size]->cp
- = scm_port_table[scm_port_table_size]->cbuf;
- scm_port_table[scm_port_table_size]->cbufend
- = &scm_port_table[scm_port_table_size]->cbuf[SCM_INITIAL_CBUF_SIZE];
- scm_port_table[scm_port_table_size]->write_needs_seek = 0;
- return scm_port_table[scm_port_table_size++];
+ entry = (scm_port *) malloc (sizeof (scm_port));
+ if (entry == NULL)
+ scm_memory_error ("scm_add_to_port_table");
+
+ entry->port = port;
+ entry->entry = scm_port_table_size;
+ entry->revealed = 0;
+ entry->stream = 0;
+ entry->file_name = SCM_BOOL_F;
+ entry->line_number = 0;
+ entry->column_number = 0;
+ entry->cp
+ = entry->cbuf;
+ entry->cbufend
+ = &entry->cbuf[SCM_INITIAL_CBUF_SIZE];
+ entry->rw_active = 0;
+
+ scm_port_table[scm_port_table_size] = entry;
+ scm_port_table_size++;
+
+ return entry;
}
/* Remove a port from the table. */
@@ -312,15 +317,12 @@ void
scm_remove_from_port_table (port)
SCM port;
{
- struct scm_port_table *p = SCM_PTAB_ENTRY (port);
+ scm_port *p = SCM_PTAB_ENTRY (port);
int i = p->entry;
/* Error if not found: too violent? May occur in GC. */
if (i >= scm_port_table_size)
scm_wta (port, "Port not in table", "scm_remove_from_port_table");
- scm_mallocated -= (sizeof (*p)
- + (p->cbufend - p->cbuf)
- - SCM_INITIAL_CBUF_SIZE);
- scm_must_free ((char *)p);
+ free (p);
/* Since we have just freed slot i we can shrink the table by moving
the last entry to that slot... */
if (i < scm_port_table_size - 1)
@@ -337,7 +339,7 @@ scm_grow_port_cbuf (port, requested)
SCM port;
size_t requested;
{
- struct scm_port_table *p = SCM_PTAB_ENTRY (port);
+ scm_port *p = SCM_PTAB_ENTRY (port);
int size = p->cbufend - p->cbuf;
int new_size = size * 3 / 2;
if (new_size < requested)
@@ -626,7 +628,13 @@ scm_getc (port)
SCM port;
{
int c;
+ scm_port *pt = SCM_PTAB_ENTRY (port);
+ scm_ptobfuns *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
+ if (pt->rw_active == SCM_PORT_WRITE)
+ {
+ ptob->fflush (port);
+ }
if (SCM_CRDYP (port))
{
c = SCM_CGETUN (port);
@@ -634,20 +642,19 @@ scm_getc (port)
}
else
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
-
if (pt->read_pos < pt->read_end)
{
c = *(pt->read_pos++);
}
else
{
- scm_sizet i = SCM_PTOBNUM (port);
-
- c = (scm_ptobs [i].fill_buffer) (port);
+ c = ptob->fill_buffer (port);
}
}
+ if (pt->rw_random)
+ pt->rw_active = SCM_PORT_READ;
+
if (c == '\n')
{
SCM_INCLINE (port);
@@ -664,48 +671,22 @@ scm_getc (port)
return c;
}
-/* a macro used whenever writing to a port. in the case of fports,
- if fdes is random access and the last access was a
- read, then clear the read and put-back buffers and adjust the file position
- to account for unread chars. */
-#define SCM_MAYBE_DRAIN_INPUT(port, pt, ptob)\
-{\
- if (pt->write_needs_seek)\
- {\
- int offset = pt->read_end - pt->read_pos;\
- if (SCM_CRDYP (port))\
- {\
- offset += SCM_N_READY_CHARS (port);\
- SCM_CLRDY (port);\
- }\
- if (offset > 0)\
- {\
- pt->read_pos = pt->read_end;\
- /* will throw error if unread-char used at beginning of file\
- then attempting to write. seems correct. */\
- if ((ptob->seek) (port, -offset, SEEK_CUR) == -1)\
- scm_syserror ("scm_maybe_drain_input");\
- }\
- pt->write_needs_seek = 0;\
- }\
-}
-
void
scm_putc (c, port)
int c;
SCM port;
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
scm_ptobfuns *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
- SCM_MAYBE_DRAIN_INPUT (port, pt, ptob)
+ if (pt->rw_active == SCM_PORT_READ)
+ ptob->read_flush (port);
*(pt->write_pos++) = (char) c;
- if (pt->write_pos == pt->write_end
- || (c == '\n'
- && (SCM_CAR (port) & SCM_BUFLINE)))
- {
- (ptob->fflush) (port);
- }
+ if (pt->write_pos == pt->write_end)
+ ptob->fflush (port);
+
+ if (pt->rw_random)
+ pt->rw_active = SCM_PORT_WRITE;
}
void
@@ -713,21 +694,24 @@ scm_puts (s, port)
char *s;
SCM port;
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
scm_ptobfuns *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
- SCM_MAYBE_DRAIN_INPUT (port, pt, ptob);
+ if (pt->rw_active == SCM_PORT_READ)
+ ptob->read_flush (port);
while (*s != 0)
{
*pt->write_pos++ = *s++;
if (pt->write_pos == pt->write_end)
- (ptob->fflush) (port);
+ ptob->fflush (port);
}
-
/* If the port is line-buffered, flush it. */
if ((SCM_CAR (port) & SCM_BUFLINE)
&& memchr (pt->write_buf, '\n', pt->write_pos - pt->write_buf))
- (ptob->fflush) (port);
+ ptob->fflush (port);
+
+ if (pt->rw_random)
+ pt->rw_active = SCM_PORT_WRITE;
}
void
@@ -736,10 +720,11 @@ scm_lfwrite (ptr, size, port)
scm_sizet size;
SCM port;
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
scm_ptobfuns *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
- SCM_MAYBE_DRAIN_INPUT (port, pt, ptob);
+ if (pt->rw_active == SCM_PORT_READ)
+ ptob->read_flush (port);
while (size > 0)
{
int space = pt->write_end - pt->write_pos;
@@ -750,13 +735,15 @@ scm_lfwrite (ptr, size, port)
size -= write_len;
ptr += write_len;
if (write_len == space)
- (ptob->fflush) (port);
+ ptob->fflush (port);
}
-
/* If the port is line-buffered, flush it. */
if ((SCM_CAR (port) & SCM_BUFLINE)
&& memchr (pt->write_buf, '\n', pt->write_pos - pt->write_buf))
(ptob->fflush) (port);
+
+ if (pt->rw_random)
+ pt->rw_active = SCM_PORT_WRITE;
}
@@ -776,8 +763,13 @@ scm_ungetc (c, port)
int c;
SCM port;
{
+ scm_port *pt = SCM_PTAB_ENTRY (port);
+
SCM_CUNGET (c, port);
+ if (pt->rw_random)
+ pt->rw_active = SCM_PORT_READ;
+
if (c == '\n')
{
/* What should col be in this case?
@@ -869,6 +861,80 @@ scm_unread_string (str, port)
return str;
}
+SCM_PROC (s_lseek, "lseek", 3, 0, 0, scm_lseek);
+SCM
+scm_lseek (SCM object, SCM offset, SCM whence)
+{
+ off_t off;
+ off_t rv;
+ int how;
+
+ object = SCM_COERCE_OUTPORT (object);
+
+ off = scm_num2long (offset, (char *)SCM_ARG2, s_lseek);
+ SCM_ASSERT (SCM_INUMP (whence), whence, SCM_ARG3, s_lseek);
+ how = SCM_INUM (whence);
+ if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
+ scm_out_of_range (s_lseek, whence);
+ if (SCM_NIMP (object) && SCM_OPPORTP (object))
+ {
+ scm_port *pt = SCM_PTAB_ENTRY (object);
+ scm_ptobfuns *ptob = scm_ptobs + SCM_PTOBNUM (object);
+
+ if (!ptob->seek)
+ scm_misc_error (s_lseek, "port is not seekable",
+ scm_cons (object, SCM_EOL));
+ else
+ {
+ if (pt->rw_active == SCM_PORT_READ)
+ ptob->read_flush (object);
+ else if (pt->rw_active == SCM_PORT_WRITE)
+ ptob->fflush (object);
+
+ rv = ptob->seek (object, off, how);
+ if (rv == -1)
+ scm_syserror (s_lseek);
+ }
+ }
+ else /* file descriptor?. */
+ {
+ SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_lseek);
+ rv = lseek (SCM_INUM (object), off, how);
+ if (rv == -1)
+ scm_syserror (s_lseek);
+ }
+ return scm_long2num (rv);
+}
+
+SCM_PROC (s_ftruncate, "ftruncate", 1, 1, 0, scm_ftruncate);
+
+SCM
+scm_ftruncate (SCM port, SCM length)
+{
+ scm_port *pt;
+ scm_ptobfuns *ptob;
+
+ port = SCM_COERCE_OUTPORT (port);
+ SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1,
+ s_ftruncate);
+ pt = SCM_PTAB_ENTRY (port);
+ ptob = scm_ptobs + SCM_PTOBNUM (port);
+ if (!ptob->ftruncate)
+ scm_misc_error (s_ftruncate, "port is not truncatable",
+ scm_cons (port, SCM_EOL));
+ if (SCM_UNBNDP (length))
+ {
+ length = scm_lseek (port, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
+ }
+ if (pt->rw_active == SCM_PORT_READ)
+ ptob->read_flush (port);
+ else if (pt->rw_active == SCM_PORT_WRITE)
+ ptob->fflush (port);
+
+ ptob->ftruncate (port, scm_num2long (length, (char *)SCM_ARG2, s_ftruncate));
+ return SCM_UNSPECIFIED;
+}
+
SCM_PROC (s_port_line, "port-line", 1, 0, 0, scm_port_line);
SCM
@@ -1054,10 +1120,12 @@ static struct scm_ptobfuns void_port_ptob =
print_void_port,
0, /* equal? */
flush_void_port,
+ flush_void_port,
close_void_port,
0,
0,
0,
+ 0,
};
SCM
@@ -1066,7 +1134,7 @@ scm_void_port (mode_str)
{
int mode_bits;
SCM answer;
- struct scm_port_table * pt;
+ scm_port * pt;
SCM_NEWCELL (answer);
SCM_DEFER_INTS;
@@ -1099,6 +1167,11 @@ scm_sys_make_void_port (mode)
void
scm_init_ports ()
{
+ /* lseek() symbols. */
+ scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
+ scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
+ scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
+
scm_tc16_void_port = scm_newptob (&void_port_ptob);
#include "ports.x"
}
diff --git a/libguile/ports.h b/libguile/ports.h
index d3f88720c..1756abaee 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -2,7 +2,7 @@
#ifndef PORTSH
#define PORTSH
-/* Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,14 +53,17 @@
#define SCM_INITIAL_CBUF_SIZE 4
-struct scm_port_table
+/* C representation of a Scheme port. */
+
+typedef struct
{
SCM port; /* Link back to the port object. */
int entry; /* Index in port table. */
int revealed; /* 0 not revealed, > 1 revealed.
* Revealed ports do not get GC'd.
*/
- /* ptob specific data. may be SCM data or cast to a pointer to C data. */
+ /* data for the underlying port implementation. may be an SCM cell or
+ cast to a pointer to C data. */
SCM stream;
SCM file_name; /* debugging support. */
@@ -77,9 +80,9 @@ struct scm_port_table
it reaches read_end. */
unsigned char *read_buf; /* buffer start. */
- unsigned char *read_pos; /* the next unread char. */
+ const unsigned char *read_pos;/* the next unread char. */
unsigned char *read_end; /* pointer to last buffered char + 1. */
- int read_buf_size; /* size of the buffer. */
+ off_t read_buf_size; /* size of the buffer. */
/* write requests are saved into this buffer at write_pos until it
reaches write_buf + write_buf_size, then the ptob flush is
@@ -88,21 +91,32 @@ struct scm_port_table
unsigned char *write_buf; /* buffer start. */
unsigned char *write_pos; /* pointer to last buffered char + 1. */
unsigned char *write_end; /* pointer to end of buffer + 1. */
- int write_buf_size; /* size of the buffer. */
+ off_t write_buf_size; /* size of the buffer. */
unsigned char shortbuf; /* buffer for "unbuffered" streams. */
- int write_needs_seek; /* whether port position needs to be adjusted
- before writing to it. */
+ int rw_random; /* true if the port is bidirectional and
+ random access. implies that the buffers
+ must be flushed before switching between
+ reading and writing. */
+
+ int rw_active; /* for bidirectional random ports, indicates
+ which of the buffers is currently in use.
+ can be SCM_PORT_WRITE, SCM_PORT_READ,
+ or 0. */
/* a completely separate buffer which is only used for un-read chars
and strings. */
unsigned char *cp; /* where to put and get unget chars */
unsigned char *cbufend; /* points after this struct */
unsigned char cbuf[SCM_INITIAL_CBUF_SIZE]; /* must be last: may grow */
-};
+} scm_port;
+
+/* values for the rw_active flag. */
+#define SCM_PORT_READ 1
+#define SCM_PORT_WRITE 2
-extern struct scm_port_table **scm_port_table;
+extern scm_port **scm_port_table;
extern int scm_port_table_size; /* Number of ports in scm_port_table. */
@@ -133,7 +147,7 @@ extern int scm_port_table_size; /* Number of ports in scm_port_table. */
#define SCM_OUTPORTP(x) (((0x7f | SCM_WRTNG) & SCM_CAR(x))==(scm_tc7_port | SCM_WRTNG))
#define SCM_OPENP(x) (SCM_OPN & SCM_CAR(x))
#define SCM_CLOSEDP(x) (!SCM_OPENP(x))
-#define SCM_PTAB_ENTRY(x) ((struct scm_port_table *)SCM_CDR(x))
+#define SCM_PTAB_ENTRY(x) ((scm_port *) SCM_CDR(x))
#define SCM_SETPTAB_ENTRY(x,ent) SCM_SETCDR ((x), (SCM)(ent))
#define SCM_STREAM(x) SCM_PTAB_ENTRY(x)->stream
#define SCM_SETSTREAM(x,s) (SCM_PTAB_ENTRY(x)->stream = (SCM) s)
@@ -194,9 +208,11 @@ typedef struct scm_ptobfuns
int (*print) (SCM exp, SCM port, scm_print_state *pstate);
SCM (*equalp) (SCM, SCM);
void (*fflush) (SCM port);
+ void (*read_flush) (SCM port);
int (*fclose) (SCM port);
int (*fill_buffer) (SCM port);
off_t (*seek) (SCM port, off_t OFFSET, int WHENCE);
+ void (*ftruncate) (SCM port, off_t length);
int (*input_waiting_p) (SCM port);
} scm_ptobfuns;
@@ -221,7 +237,7 @@ extern SCM scm_current_load_port SCM_P ((void));
extern SCM scm_set_current_input_port SCM_P ((SCM port));
extern SCM scm_set_current_output_port SCM_P ((SCM port));
extern SCM scm_set_current_error_port SCM_P ((SCM port));
-extern struct scm_port_table * scm_add_to_port_table SCM_P ((SCM port));
+extern scm_port * scm_add_to_port_table SCM_P ((SCM port));
extern void scm_remove_from_port_table SCM_P ((SCM port));
extern void scm_grow_port_cbuf SCM_P ((SCM port, size_t requested));
extern SCM scm_pt_size SCM_P ((void));
@@ -250,6 +266,8 @@ extern SCM scm_peek_char SCM_P ((SCM port));
extern SCM scm_unread_char SCM_P ((SCM cobj, SCM port));
extern SCM scm_unread_string SCM_P ((SCM str, SCM port));
extern char *scm_generic_fgets SCM_P ((SCM port, int *len));
+extern SCM scm_lseek (SCM object, SCM offset, SCM whence);
+extern SCM scm_ftruncate (SCM port, SCM length);
extern SCM scm_port_line SCM_P ((SCM port));
extern SCM scm_set_port_line_x SCM_P ((SCM port, SCM line));
extern SCM scm_port_column SCM_P ((SCM port));
diff --git a/libguile/scmsigs.c b/libguile/scmsigs.c
index f3970eb20..072613492 100644
--- a/libguile/scmsigs.c
+++ b/libguile/scmsigs.c
@@ -434,9 +434,26 @@ scm_init_scmsigs ()
got_signal[i] = 0;
#ifdef HAVE_SIGACTION
orig_handlers[i].sa_handler = SIG_ERR;
+
#else
orig_handlers[i] = SIG_ERR;
#endif
+
+#ifdef HAVE_RESTARTS
+ /* ensure that system calls will be restarted for all signals. */
+ /* sigintterupt would be simpler, but it seems better to avoid
+ dependency on another system call. */
+ {
+ struct sigaction action;
+
+ sigaction (i, NULL, &action);
+ if (!(action.sa_flags & SA_RESTART))
+ {
+ action.sa_flags &= SA_RESTART;
+ sigaction (i, &action, NULL);
+ }
+ }
+#endif
}
scm_sysintern ("NSIG", scm_long2num (NSIG));
diff --git a/libguile/vports.c b/libguile/vports.c
index b3e3c6a35..c122bf1ad 100644
--- a/libguile/vports.c
+++ b/libguile/vports.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -72,16 +72,15 @@ prinsfpt (exp, port, pstate)
return !0;
}
-/* called with a single char at most. */
static void
sfflush (SCM port)
{
- struct scm_port_table *pt = SCM_PTAB_ENTRY (port);
+ scm_port *pt = SCM_PTAB_ENTRY (port);
SCM stream = pt->stream;
if (pt->write_pos > pt->write_buf)
{
- /* write the char. */
+ /* write the byte. */
scm_apply (SCM_VELTS (stream)[0], SCM_MAKICHR (*pt->write_buf),
scm_listofnull);
pt->write_pos = pt->write_buf;
@@ -96,6 +95,11 @@ sfflush (SCM port)
}
}
+static void
+sf_read_flush (SCM port)
+{
+}
+
/* string output proc (element 1) is no longer called. */
/* calling the flush proc (element 2) is in case old code needs it,
@@ -138,7 +142,7 @@ scm_make_soft_port (pv, modes)
SCM pv;
SCM modes;
{
- struct scm_port_table * pt;
+ scm_port *pt;
SCM z;
SCM_ASSERT (SCM_NIMP (pv) && SCM_VECTORP (pv) && 5 == SCM_LENGTH (pv), pv, SCM_ARG1, s_make_soft_port);
SCM_ASSERT (SCM_NIMP (modes) && SCM_ROSTRINGP (modes), modes, SCM_ARG2, s_make_soft_port);
@@ -149,10 +153,11 @@ scm_make_soft_port (pv, modes)
SCM_SETCAR (z, scm_tc16_sfport | scm_mode_bits (SCM_ROCHARS (modes)));
SCM_SETPTAB_ENTRY (z, pt);
SCM_SETSTREAM (z, pv);
- pt->read_buf = pt->read_pos = pt->read_end = &pt->shortbuf;
+ pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
pt->write_buf = pt->write_pos = &pt->shortbuf;
pt->read_buf_size = pt->write_buf_size = 1;
pt->write_end = pt->write_buf + pt->write_buf_size;
+ pt->rw_random = 0;
SCM_ALLOW_INTS;
return z;
}
@@ -172,10 +177,12 @@ scm_ptobfuns scm_sfptob =
prinsfpt,
0,
sfflush,
+ sf_read_flush,
sfclose,
sf_fill_buffer,
0,
0,
+ 0,
};