ports.c, ports.h (scm_c_read, scm_c_write): New functions.
[bpt/guile.git] / libguile / ports.c
index 36f59fa..fd73620 100644 (file)
@@ -1,4 +1,4 @@
-/*     Copyright (C) 1995,1996,1997,1998,1999, 2000 Free Software Foundation, Inc.
+/*     Copyright (C) 1995,1996,1997,1998,1999, 2000, 2001 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
@@ -306,8 +306,8 @@ size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
 /* Clear a port's read buffers, returning the contents.  */
 SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0, 
             (SCM port),
-           "Drains @var{PORT}'s read buffers (including any pushed-back characters)\n"
-           "and returns the contents as a single string.")
+           "Drain @var{port}'s read buffers (including any pushed-back\n"
+           "characters) and returns the content as a single string.")
 #define FUNC_NAME s_scm_drain_input
 {
   SCM result;
@@ -331,10 +331,10 @@ SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
 /* Standard ports --- current input, output, error, and more(!).  */
 
 SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
-           (),
-           "Returns the current input port.  This is the default port used by many\n"
-            "input procedures.  Initially, @code{current-input-port} returns the\n"
-            "value of @code{???}.")
+           (),
+           "Return the current input port.  This is the default port used\n"
+           "by many input procedures.  Initially, @code{current-input-port}\n"
+           "returns the @dfn{standard input} in Unix and C terminology.")
 #define FUNC_NAME s_scm_current_input_port
 {
   return scm_cur_inp;
@@ -342,10 +342,11 @@ SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
-           (),
-            "Returns the current output port.  This is the default port used by many\n"
-            "output procedures.  Initially, @code{current-output-port} returns the\n"
-            "value of @code{???}.")
+           (),
+            "Return the current output port.  This is the default port used\n"
+           "by many output procedures.  Initially, \n"
+           "@code{current-output-port} returns the @dfn{standard output} in\n"
+           "Unix and C terminology.")
 #define FUNC_NAME s_scm_current_output_port
 {
   return scm_cur_outp;
@@ -363,9 +364,9 @@ SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
-           (),
+           (),
            "Return the current-load-port.\n"
-            "The load port is used internally by `primitive-load'.")
+            "The load port is used internally by @code{primitive-load}.")
 #define FUNC_NAME s_scm_current_load_port
 {
   return scm_cur_loadp;
@@ -390,8 +391,8 @@ SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
 
 
 SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
-           (SCM port),
-           "Set the current default output port to PORT.")
+           (SCM port),
+           "Set the current default output port to @var{port}.")
 #define FUNC_NAME s_scm_set_current_output_port
 {
   SCM ooutp = scm_cur_outp;
@@ -404,8 +405,8 @@ SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
 
 
 SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
-           (SCM port),
-           "Set the current default error port to PORT.")
+           (SCM port),
+           "Set the current default error port to @var{port}.")
 #define FUNC_NAME s_scm_set_current_error_port
 {
   SCM oerrp = scm_cur_errp;
@@ -693,7 +694,11 @@ SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
 SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
            (SCM proc),
            "Apply @var{proc} to each port in the Guile port table\n"
-           "in turn.  The return value is unspecified.")
+           "in turn.  The return value is unspecified.  More specifically,\n"
+           "@var{proc} is applied exactly once to every port that exists\n"
+           "in the system at the time @var{port-for-each} is invoked.\n"
+           "Changes to the port table while @var{port-for-each} is running\n"
+           "have no effect as far as @var{port-for-each} is concerned.\n") 
 #define FUNC_NAME s_scm_port_for_each
 {
   int i;
@@ -958,6 +963,14 @@ scm_puts (const char *s, SCM port)
   scm_lfwrite (s, strlen (s), port);
 }
 
+/* scm_lfwrite
+ *
+ * Currently, this function has an identical implementation to
+ * scm_c_write.  We could have turned it into a macro expanding into a
+ * call to scm_c_write.  However, the implementation is small and
+ * might differ in the future.
+ */
+
 void 
 scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
 {
@@ -973,6 +986,81 @@ scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
     pt->rw_active = SCM_PORT_WRITE;
 }
 
+/* scm_c_read
+ *
+ * Used by an application to read arbitrary number of bytes from an
+ * SCM port.  Same semantics as libc read, except that scm_c_read only
+ * returns less than SIZE bytes if at end-of-file.
+ *
+ * Warning: Doesn't update port line and column counts!  */
+
+scm_sizet
+scm_c_read (SCM port, void *buffer, scm_sizet size)
+{
+  scm_port *pt = SCM_PTAB_ENTRY (port);
+  scm_sizet n_read = 0, n_available;
+
+  if (pt->rw_active == SCM_PORT_WRITE)
+    scm_ptobs[SCM_PTOBNUM (port)].flush (port);
+
+  if (pt->rw_random)
+    pt->rw_active = SCM_PORT_READ;
+
+  if (SCM_READ_BUFFER_EMPTY_P (pt))
+    {
+      if (scm_fill_input (port) == EOF)
+       return 0;
+    }
+  
+  n_available = pt->read_end - pt->read_pos;
+  
+  while (n_available < size)
+    {
+      memcpy (buffer, pt->read_pos, n_available);
+      buffer += n_available;
+      pt->read_pos += n_available;
+      n_read += n_available;
+      
+      if (SCM_READ_BUFFER_EMPTY_P (pt))
+       {
+         if (scm_fill_input (port) == EOF)
+           return n_read;
+       }
+
+      size -= n_available;
+      n_available = pt->read_end - pt->read_pos;
+    }
+
+  memcpy (buffer, pt->read_pos, size);
+  pt->read_pos += size;
+
+  return n_read + size;
+}
+
+/* scm_c_write
+ *
+ * Used by an application to write arbitrary number of bytes to an SCM
+ * port.  Similar semantics as libc write.  However, unlike libc
+ * write, scm_c_write writes the requested number of bytes and has no
+ * return value.
+ *
+ * Warning: Doesn't update port line and column counts!
+ */
+
+void 
+scm_c_write (SCM port, const void *ptr, scm_sizet size)
+{
+  scm_port *pt = SCM_PTAB_ENTRY (port);
+  scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
+
+  if (pt->rw_active == SCM_PORT_READ)
+    scm_end_input (port);
+
+  ptob->write (port, ptr, size);
+
+  if (pt->rw_random)
+    pt->rw_active = SCM_PORT_WRITE;
+}
 
 void 
 scm_flush (SCM port)
@@ -1194,8 +1282,8 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
 
   object = SCM_COERCE_OUTPORT (object);
 
-  off = SCM_NUM2LONG (2,offset);
-  SCM_VALIDATE_INUM_COPY (3,whence,how);
+  off = SCM_NUM2LONG (2, offset);
+  SCM_VALIDATE_INUM_COPY (3, whence, how);
   if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
     SCM_OUT_OF_RANGE (3, whence);
   if (SCM_OPPORTP (object))
@@ -1280,7 +1368,7 @@ SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
 
 SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
             (SCM port),
-           "Return the current line number for PORT.")
+           "Return the current line number for @var{port}.")
 #define FUNC_NAME s_scm_port_line
 {
   port = SCM_COERCE_OUTPORT (port);
@@ -1291,7 +1379,7 @@ SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
 
 SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
             (SCM port, SCM line),
-           "Set the current line number for PORT to LINE.")
+           "Set the current line number for @var{port} to @var{line}.")
 #define FUNC_NAME s_scm_set_port_line_x
 {
   port = SCM_COERCE_OUTPORT (port);