X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/ee149d0368eea641c5d05c6cafc888a3cd76ea5e..66a1057524917259b9c111e0a2f100597fd89cf2:/libguile/ioext.c diff --git a/libguile/ioext.c b/libguile/ioext.c index 54edd547a..cb62a6011 100644 --- a/libguile/ioext.c +++ b/libguile/ioext.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 @@ -143,55 +143,19 @@ scm_read_delimited_x (delims, buf, gobble, port, start, end) static unsigned char * scm_do_read_line (SCM port, int *len_p) { - struct scm_port_table *pt = SCM_PTAB_ENTRY (port); + scm_port *pt = SCM_PTAB_ENTRY (port); unsigned char *end; /* I thought reading lines was simple. Mercy me. */ - /* If there are any pushed-back characters, read the line character - by character. */ - if (SCM_CRDYP (port)) - { - int buf_size = 60; - /* Invariant: buf always has buf_size + 1 characters allocated; - the `+ 1' is for the final '\0'. */ - unsigned char *buf = malloc (buf_size + 1); - int buf_len = 0; - int c; - - while ((c = scm_getc (port)) != EOF) - { - if (buf_len >= buf_size) - { - buf = realloc (buf, buf_size * 2 + 1); - buf_size *= 2; - } - - buf[buf_len++] = c; - - if (c == '\n') - break; - } - - /* Since SCM_CRDYP returned true, we ought to have gotten at - least one character. */ - if (buf_len == 0) - abort (); - - buf[buf_len] = '\0'; - - *len_p = buf_len; - return buf; - } - - /* The common case: no unread characters, and the buffer contains - a complete line. This needs to be fast. */ + /* The common case: the buffer contains a complete line. + This needs to be fast. */ if ((end = memchr (pt->read_pos, '\n', (pt->read_end - pt->read_pos))) != 0) { int buf_len = (end + 1) - pt->read_pos; /* Allocate a buffer of the perfect size. */ - unsigned char *buf = malloc (buf_len + 1); + unsigned char *buf = scm_must_malloc (buf_len + 1, "%read-line"); memcpy (buf, pt->read_pos, buf_len); pt->read_pos += buf_len; @@ -202,7 +166,7 @@ scm_do_read_line (SCM port, int *len_p) return buf; } - /* There are no unread characters, and the buffer contains no newlines. */ + /* The buffer contains no newlines. */ { /* When live, len is always the number of characters in the current buffer that are part of the current line. */ @@ -210,16 +174,16 @@ scm_do_read_line (SCM port, int *len_p) int buf_size = (len < 50) ? 60 : len * 2; /* Invariant: buf always has buf_size + 1 characters allocated; the `+ 1' is for the final '\0'. */ - unsigned char *buf = malloc (buf_size + 1); + unsigned char *buf = scm_must_malloc (buf_size + 1, "%read-line"); int buf_len = 0; - int c; for (;;) { if (buf_len + len > buf_size) { int new_size = (buf_len + len) * 2; - buf = realloc (buf, new_size + 1); + buf = scm_must_realloc (buf, buf_size + 1, new_size + 1, + "%read-line"); buf_size = new_size; } @@ -232,10 +196,8 @@ scm_do_read_line (SCM port, int *len_p) if (end) break; - /* Get more characters. I think having fill_buffer return a - character is not terribly graceful... */ - c = (scm_ptobs[SCM_PTOBNUM (port)].fill_buffer) (port); - if (c == EOF) + /* Get more characters. */ + if (scm_fill_input (port) == EOF) { /* If we're missing a final newline in the file, return what we did get, sans newline. */ @@ -246,20 +208,6 @@ scm_do_read_line (SCM port, int *len_p) return 0; } - /* ... because it makes us duplicate code here... */ - if (buf_len + 1 > buf_size) - { - int new_size = buf_size * 2; - buf = realloc (buf, new_size + 1); - buf_size = new_size; - } - - /* ... and this is really a duplication of the memcpy and - memchr calls, on a single-byte buffer. */ - buf[buf_len++] = c; - if (c == '\n') - break; - /* Search the buffer for newlines. */ if ((end = memchr (pt->read_pos, '\n', (len = (pt->read_end - pt->read_pos)))) @@ -268,7 +216,7 @@ scm_do_read_line (SCM port, int *len_p) } /* I wonder how expensive this realloc is. */ - buf = realloc (buf, buf_len + 1); + buf = scm_must_realloc (buf, buf_size + 1, buf_len + 1, "%read-line"); buf[buf_len] = '\0'; *len_p = buf_len; return buf; @@ -290,6 +238,7 @@ SCM scm_read_line (port) SCM port; { + scm_port *pt; char *s; int slen; SCM line, term; @@ -302,6 +251,10 @@ scm_read_line (port) port, SCM_ARG1, s_read_line); } + pt = SCM_PTAB_ENTRY (port); + if (pt->rw_active == SCM_PORT_WRITE) + scm_ptobs[SCM_PTOBNUM (port)].flush (port); + s = scm_do_read_line (port, &slen); if (s == NULL) @@ -313,6 +266,7 @@ scm_read_line (port) term = SCM_MAKICHR ('\n'); s[slen-1] = '\0'; line = scm_take_str (s, slen-1); + scm_done_malloc (-1); SCM_INCLINE (port); } else @@ -320,9 +274,13 @@ scm_read_line (port) /* Fix: we should check for eof on the port before assuming this. */ term = SCM_EOF_VAL; line = scm_take_str (s, slen); + SCM_COL (port) += slen; } } + if (pt->rw_random) + pt->rw_active = SCM_PORT_READ; + return scm_cons (line, term); } @@ -343,56 +301,7 @@ SCM scm_ftell (object) SCM object; { - if (SCM_INUMP (object)) - { - int fdes = SCM_INUM (object); - fpos_t pos; - - pos = lseek (fdes, 0, SEEK_CUR); - if (pos == -1) - scm_syserror (s_ftell); - return scm_long2num (pos); - } - else - { - struct scm_fport *fp; - struct scm_port_table *pt; - int fdes; - fpos_t pos; - - object = SCM_COERCE_OUTPORT (object); - SCM_ASSERT (SCM_NIMP (object) && SCM_OPFPORTP (object), - object, SCM_ARG1, s_ftell); - fp = SCM_FSTREAM (object); - pt = SCM_PTAB_ENTRY (object); - fdes = fp->fdes; - pos = lseek (fdes, 0, SEEK_CUR); - if (pos == -1) - scm_syserror (s_ftell); - /* the seek will only have succeeded if fdes is random access, - in which case only one buffer can be filled. */ - if (pt->write_pos > pt->write_buf) - { - pos += pt->write_pos - pt->write_buf; - } - else - { - pos -= pt->read_end - pt->read_pos; - if (SCM_CRDYP (object)) - pos -= SCM_N_READY_CHARS (object); - } - return scm_long2num (pos); - } -} - -/* clear the three buffers in a port. */ -#define SCM_CLEAR_BUFFERS(port, pt)\ -{\ - if (pt->write_pos > pt->write_buf)\ - scm_fflush (port);\ - pt->read_pos = pt->read_end = pt->read_buf;\ - pt->write_needs_seek = 0;\ - SCM_CLRDY (port);\ + return scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR)); } SCM_PROC (s_fseek, "fseek", 3, 0, 0, scm_fseek); @@ -403,35 +312,8 @@ scm_fseek (object, offset, whence) SCM offset; SCM whence; { - int rv; - long loff; - - object = SCM_COERCE_OUTPORT (object); - - loff = scm_num2long (offset, (char *)SCM_ARG2, s_fseek); - SCM_ASSERT (SCM_INUMP (whence), whence, SCM_ARG3, s_fseek); - if (SCM_NIMP (object) && SCM_OPFPORTP (object)) - { - struct scm_fport *fp = SCM_FSTREAM (object); - struct scm_port_table *pt = SCM_PTAB_ENTRY (object); + scm_seek (object, offset, whence); - /* clear the three buffers. the write buffer should be flushed - before changing the position. */ - if (fp->random) - { - SCM_CLEAR_BUFFERS (object, pt); - } /* if not random, lseek will fail. */ - rv = lseek (fp->fdes, loff, SCM_INUM (whence)); - if (rv == -1) - scm_syserror (s_fseek); - } - else - { - SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_fseek); - rv = lseek (SCM_INUM (object), loff, SCM_INUM (whence)); - if (rv == -1) - scm_syserror (s_fseek); - } return SCM_UNSPECIFIED; } @@ -455,18 +337,20 @@ scm_redirect_port (old, new) newfd = fp->fdes; if (oldfd != newfd) { - struct scm_port_table *pt = SCM_PTAB_ENTRY (new); - - /* must flush to old fdes. don't clear all buffers here - in case dup2 fails. */ - if (pt->write_pos > pt->write_buf) - scm_fflush (new); + scm_port *pt = SCM_PTAB_ENTRY (new); + scm_port *old_pt = SCM_PTAB_ENTRY (old); + scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (new)]; + + /* must flush to old fdes. */ + if (pt->rw_active == SCM_PORT_WRITE) + ptob->flush (new); + else if (pt->rw_active == SCM_PORT_READ) + scm_end_input (new); ans = dup2 (oldfd, newfd); if (ans == -1) scm_syserror (s_redirect_port); - fp->random = SCM_FDES_RANDOM_P (fp->fdes); + pt->rw_random = old_pt->rw_random; /* continue using existing buffers, even if inappropriate. */ - SCM_CLEAR_BUFFERS (new, pt); } return SCM_UNSPECIFIED; } @@ -624,11 +508,6 @@ scm_fdes_to_ports (fd) void scm_init_ioext () { - /* fseek() 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)); - #include "ioext.x" }