diff options
-rw-r--r-- | libguile/fports.c | 100 | ||||
-rw-r--r-- | libguile/fports.h | 10 | ||||
-rw-r--r-- | libguile/gc.c | 4 | ||||
-rw-r--r-- | libguile/gdbint.c | 19 | ||||
-rw-r--r-- | libguile/ports.c | 285 | ||||
-rw-r--r-- | libguile/ports.h | 42 | ||||
-rw-r--r-- | libguile/scmsigs.c | 17 | ||||
-rw-r--r-- | libguile/vports.c | 19 |
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, }; |