+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.
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));
(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
};
(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
};
}
+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;
+}
+
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 */
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
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++;
}
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
return cobj;
}
-
-
SCM_PROC (s_port_line, "port-line", 0, 1, 0, scm_port_line);
SCM
return EOF;
}
+static char *
+fgets_void_port (SCM strm)
+{
+ return NULL;
+}
static int
close_void_port (SCM strm)
write_void_port,
flush_void_port,
getc_void_port,
+ fgets_void_port,
close_void_port,
};
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;
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));
stwrite,
noop0,
stgetc,
+ scm_generic_fgets,
0
};
sfwrite,
sfflush,
sfgetc,
+ scm_generic_fgets,
sfclose
};