* ioext.c (scm_do_read_line, scm_read_line): Use scm_must_malloc,
[bpt/guile.git] / libguile / ioext.c
index 54edd54..cb62a60 100644 (file)
@@ -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"
 }