Line-oriented i/o:
authorTim Pierce <twp@skepsis.com>
Wed, 23 Jul 1997 21:20:55 +0000 (21:20 +0000)
committerTim Pierce <twp@skepsis.com>
Wed, 23 Jul 1997 21:20:55 +0000 (21:20 +0000)
scm_gen_read_line
scm_read_line
scm_fgets
scm_generic_fgets

libguile/ChangeLog
libguile/fports.c
libguile/genio.c
libguile/genio.h
libguile/ioext.c
libguile/ports.c
libguile/ports.h
libguile/strports.c
libguile/vports.c

index 193b58b..fb7251c 100644 (file)
@@ -1,3 +1,17 @@
+Wed Jul 23 16:17:46 1997  Tim Pierce  <twpierce@bio-5.bsd.uchicago.edu>
+
+       Supply an `fgets' method for port objects to do fast line i/o.
+       * ioext.c (scm_read_line): New function.
+       * genio.c (scm_gen_read_line): New function.
+       * fports.c (scm_fgets): New function.
+       (scm_fptob, scm_pipob): Add scm_fgets method.
+       * ports.c (fgets_void_port, scm_generic_fgets): New functions.
+       (void_port_ptob): Add void fgets method.
+       (scm_newptob): Initialize fgets method from ptob struct.
+       * ports.h (scm_ptobfuns): Add fgets method.
+       * vports.c (scm_sfptob): Supply generic fgets method.
+       * strports.c (scm_stptob): Supply generic fgets method.
+
 Mon Jul 21 04:03:42 1997  Gary Houston  <ghouston@actrix.gen.nz>
 
        * ioext.h: removed scm_duplicate_port prototype.
index 9354c5a..fd8d3d7 100644 (file)
@@ -262,6 +262,57 @@ scm_fgetc (s)
     return fgetc (s);
 }
 
+/*
+ * The fgets method must take a port as its argument, rather than
+ * the underlying file handle.  The reason is that we also provide
+ * a generic fgets method for ports which can't use fgets(3) (e.g.
+ * string ports).  This generic method calls the port's own
+ * fgetc method.  In order for it to know how to get that method,
+ * we must pass the original Scheme port object.
+ */
+
+static char * scm_fgets SCM_P ((SCM port));
+
+static char *
+scm_fgets (port)
+     SCM port;
+{
+  FILE *f;
+
+  char *buf   = NULL;
+  char *p;             /* pointer to current buffer position */
+  int   i     = 0;     /* index into current buffer position */
+  int   limit = 80;    /* current size of buffer */
+  int   lp;
+
+  f = SCM_STREAM (port);
+  if (feof (f))
+    return NULL;
+
+  buf = (char *) scm_must_malloc (limit * sizeof(char), "fgets");
+
+  while (1) {
+    p = buf + i;
+    if (fgets (p, limit - i, f) == NULL) {
+      if (i)
+       return buf;
+      scm_must_free (buf);
+      return NULL;
+    }
+
+    if (strlen(p) < limit - i - 1)
+      return buf;
+
+    buf = (char *) scm_must_realloc (buf,
+                                    sizeof(char) * limit,
+                                    sizeof(char) * limit * 2,
+                                    "fgets");
+
+    i = limit - 1;
+    limit *= 2;
+  }
+}
+
 #ifdef vms
 
 static scm_sizet pwrite SCM_P ((char *ptr, scm_sizet size, nitems, FILE *port));
@@ -372,6 +423,7 @@ scm_ptobfuns scm_fptob =
   (scm_sizet (*) SCM_P ((char *, scm_sizet, scm_sizet, SCM))) local_ffwrite,
   (int (*) SCM_P ((SCM))) local_fflush,
   (int (*) SCM_P ((SCM))) scm_fgetc,
+  (char * (*) SCM_P ((SCM))) scm_fgets,
   (int (*) SCM_P ((SCM))) local_fclose
 };
 
@@ -387,6 +439,7 @@ scm_ptobfuns scm_pipob =
   (scm_sizet (*) SCM_P ((char *, scm_sizet, scm_sizet, SCM))) local_ffwrite,
   (int (*) SCM_P ((SCM))) local_fflush,
   (int (*) SCM_P ((SCM))) scm_fgetc,
+  (char * (*) SCM_P ((SCM))) scm_fgets,
   (int (*) SCM_P ((SCM))) local_pclose
 };
 
index a29e023..889323e 100644 (file)
@@ -507,3 +507,15 @@ scm_gen_ungetc (c, port)
 }
 
 
+char *
+scm_gen_read_line (port)
+     SCM port;
+{
+  char *s;
+  scm_sizet i;
+
+  i = SCM_PTOBNUM (port);
+  SCM_SYSCALL (s = (scm_ptobs[i].fgets) (port));
+  return s;
+}
+
index e475fff..25272d0 100644 (file)
@@ -55,5 +55,6 @@ extern void scm_gen_puts SCM_P ((enum scm_string_representation_type rep,
 extern void scm_gen_write SCM_P ((enum scm_string_representation_type rep, char *str_data, scm_sizet nitems, SCM port));
 extern int scm_gen_getc SCM_P ((SCM port));
 extern void scm_gen_ungetc SCM_P ((int c, SCM port));
+extern char *scm_gen_read_line SCM_P ((SCM port));
 
 #endif  /* GENIOH */
index 04e3fa4..5e1f79a 100644 (file)
@@ -138,6 +138,26 @@ scm_read_delimited_x (delims, buf, gobble, port, start, end)
   return scm_cons (SCM_BOOL_F, scm_long2num (j - cstart));
 }
 
+SCM_PROC (s_read_line, "%read-line", 0, 1, 0, scm_read_line);
+
+SCM
+scm_read_line (port)
+     SCM port;
+{
+  char *s;
+
+  if (SCM_UNBNDP (port))
+    port = scm_cur_inp;
+  else
+    {
+      SCM_ASSERT (SCM_NIMP (port) && SCM_OPINPORTP (port),
+                 port, SCM_ARG1, s_read_line);
+    }
+
+  s = scm_gen_read_line (port);
+  return (s == NULL ? SCM_EOF_VAL : scm_makfrom0str (s));
+}
+
 SCM_PROC (s_write_line, "write-line", 1, 1, 0, scm_write_line);
 
 SCM 
index b545ad3..e687b87 100644 (file)
@@ -114,6 +114,7 @@ scm_newptob (ptob)
       scm_ptobs[scm_numptob].fwrite = ptob->fwrite;
       scm_ptobs[scm_numptob].fflush = ptob->fflush;
       scm_ptobs[scm_numptob].fgetc = ptob->fgetc;
+      scm_ptobs[scm_numptob].fgets = ptob->fgets;
       scm_ptobs[scm_numptob].fclose = ptob->fclose;
       scm_numptob++;
     }
@@ -567,6 +568,61 @@ scm_peek_char (port)
   return SCM_MAKICHR (c);
 }
 
+/*
+ * A generic fgets method.  We supply this method so that ports which
+ * can't use fgets(3) (like string ports or soft ports) can still use
+ * line-based i/o.  The generic method calls the port's own fgetc method
+ * for input.  It should be possible to write a more efficient
+ * method for any given port representation -- this is supplied just
+ * to ensure that you don't have to.
+ */
+
+char * scm_generic_fgets SCM_P ((SCM port));
+
+char *
+scm_generic_fgets (port)
+     SCM port;
+{
+  SCM f                = SCM_STREAM (port);
+  scm_sizet p  = SCM_PTOBNUM (port);
+
+  char *buf   = NULL;
+  int   i     = 0;     /* index into current buffer position */
+  int   limit = 80;    /* current size of buffer */
+  int   c;
+
+  if (feof ((FILE *)f))
+    return NULL;
+
+  buf = (char *) scm_must_malloc (limit * sizeof(char), "generic_fgets");
+
+  while (1) {
+    if (i >= limit-1)
+      {
+       buf = (char *) scm_must_realloc (buf,
+                                        sizeof(char) * limit,
+                                        sizeof(char) * limit * 2,
+                                        "generic_fgets");
+       limit *= 2;
+      }
+
+    c = (scm_ptobs[p].fgetc) (f);
+    if (c != EOF)
+      buf[i++] = c;
+
+    if (c == EOF || c == '\n')
+      {
+       if (i)
+         {
+           buf[i] = '\0';
+           return buf;
+         }
+       scm_must_free (buf);
+       return NULL;
+      }
+  }
+}
+
 SCM_PROC (s_unread_char, "unread-char", 2, 0, 0, scm_unread_char);
 
 SCM 
@@ -590,8 +646,6 @@ scm_unread_char (cobj, port)
   return cobj;
 }
 
-
-
 SCM_PROC (s_port_line, "port-line", 0, 1, 0, scm_port_line);
 
 SCM 
@@ -807,6 +861,11 @@ getc_void_port (SCM strm)
   return EOF;
 }
 
+static char *
+fgets_void_port (SCM strm)
+{
+  return NULL;
+}
 
 static int
 close_void_port (SCM strm)
@@ -834,6 +893,7 @@ static struct scm_ptobfuns  void_port_ptob =
   write_void_port,
   flush_void_port,
   getc_void_port,
+  fgets_void_port,
   close_void_port,
 };
 
index 120c443..3a4457a 100644 (file)
@@ -147,6 +147,7 @@ typedef struct scm_ptobfuns
   scm_sizet (*fwrite) SCM_P ((char *ptr, scm_sizet size, scm_sizet nitems, SCM stream));
   int (*fflush) SCM_P ((SCM stream));
   int (*fgetc) SCM_P ((SCM stream));
+  SCM (*fgets) SCM_P ((SCM stream));
   int (*fclose) SCM_P ((SCM stream));
 } scm_ptobfuns;
 
@@ -189,6 +190,7 @@ extern SCM scm_flush_all_ports SCM_P ((void));
 extern SCM scm_read_char SCM_P ((SCM port));
 extern SCM scm_peek_char SCM_P ((SCM port));
 extern SCM scm_unread_char SCM_P ((SCM cobj, SCM port));
+extern char *scm_generic_fgets SCM_P ((SCM port));
 extern SCM scm_port_line SCM_P ((SCM port));
 extern SCM scm_port_column SCM_P ((SCM port));
 extern SCM scm_port_filename SCM_P ((SCM port));
index d4a5720..cf5c3cc 100644 (file)
@@ -300,6 +300,7 @@ scm_ptobfuns scm_stptob =
   stwrite,
   noop0,
   stgetc,
+  scm_generic_fgets,
   0
 };
 
index 26f572b..16489f1 100644 (file)
@@ -214,6 +214,7 @@ scm_ptobfuns scm_sfptob =
   sfwrite,
   sfflush,
   sfgetc,
+  scm_generic_fgets,
   sfclose
 };