scm_setvbuf doesn't throw away current buffers
authorAndy Wingo <wingo@pobox.com>
Mon, 6 Dec 2010 18:59:15 +0000 (19:59 +0100)
committerAndy Wingo <wingo@pobox.com>
Mon, 6 Dec 2010 18:59:15 +0000 (19:59 +0100)
* libguile/ports.c (scm_drain_input): Slight optimization.

* libguile/fports.c (scm_setvbuf): If there is buffered output, flush
  it.  If there is input, drain it, and then unread it after updating
  the buffers.  Much more sensible than dropping it silently...

libguile/fports.c
libguile/ports.c

index 4b190e1..fdc8f46 100644 (file)
@@ -170,6 +170,7 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
 {
   int cmode;
   long csize;
+  SCM drained;
   scm_t_port *pt;
 
   port = SCM_COERCE_OUTPORT (port);
@@ -205,7 +206,14 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
 
   pt = SCM_PTAB_ENTRY (port);
 
-  /* silently discards buffered and put-back chars.  */
+  if (SCM_INPUT_PORT_P (port))
+    drained = scm_drain_input (port);
+  else
+    drained = scm_nullstr;
+
+  if (SCM_OUTPUT_PORT_P (port))
+    scm_flush (port);
+
   if (pt->read_buf == pt->putback_buf)
     {
       pt->read_buf = pt->saved_read_buf;
@@ -219,6 +227,10 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
     scm_gc_free (pt->write_buf, pt->write_buf_size, "port buffer");
 
   scm_fport_buffer_add (port, csize, csize);
+
+  if (scm_is_true (drained) && scm_c_string_length (drained))
+    scm_unread_string (drained, port);
+
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
index ff40a33..a9ba08e 100644 (file)
@@ -347,8 +347,14 @@ SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
   if (pt->read_buf == pt->putback_buf)
     count += pt->saved_read_end - pt->saved_read_pos;
 
-  result = scm_i_make_string (count, &data);
-  scm_take_from_input_buffers (port, data, count);
+  if (count)
+    {
+      result = scm_i_make_string (count, &data);
+      scm_take_from_input_buffers (port, data, count);
+    }
+  else
+    result = scm_nullstr;
+  
   return result;
 }
 #undef FUNC_NAME