2009-02-08 22:22:31 -05:00
|
|
|
#include <sys/types.h>
|
2019-08-09 12:00:17 -04:00
|
|
|
|
|
|
|
#include <assert.h>
|
2010-05-02 14:17:47 -04:00
|
|
|
#include <setjmp.h>
|
2019-08-09 12:00:17 -04:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "dtypes.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "utf8.h"
|
|
|
|
#include "ios.h"
|
|
|
|
#include "socket.h"
|
|
|
|
#include "timefuncs.h"
|
|
|
|
#include "hashing.h"
|
|
|
|
#include "htable.h"
|
|
|
|
#include "htableh_inc.h"
|
|
|
|
#include "bitvector.h"
|
|
|
|
#include "dirpath.h"
|
|
|
|
#include "random.h"
|
2009-02-08 22:22:31 -05:00
|
|
|
#include "llt.h"
|
2019-08-09 12:00:17 -04:00
|
|
|
|
2009-02-08 22:22:31 -05:00
|
|
|
#include "flisp.h"
|
|
|
|
|
2009-03-01 23:26:16 -05:00
|
|
|
static value_t iostreamsym, rdsym, wrsym, apsym, crsym, truncsym;
|
|
|
|
static value_t instrsym, outstrsym;
|
2019-08-09 12:33:04 -04:00
|
|
|
struct fltype *iostreamtype;
|
2009-02-08 22:22:31 -05:00
|
|
|
|
2019-08-09 12:26:20 -04:00
|
|
|
void print_iostream(value_t v, struct ios *f)
|
2009-02-08 22:22:31 -05:00
|
|
|
{
|
|
|
|
(void)v;
|
2009-02-09 00:38:40 -05:00
|
|
|
fl_print_str("#<io stream>", f);
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void free_iostream(value_t self)
|
|
|
|
{
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = value2c(struct ios *, self);
|
2009-02-08 22:22:31 -05:00
|
|
|
ios_close(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void relocate_iostream(value_t oldv, value_t newv)
|
|
|
|
{
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *olds = value2c(struct ios *, oldv);
|
|
|
|
struct ios *news = value2c(struct ios *, newv);
|
2014-05-22 18:09:49 -04:00
|
|
|
if (news->buf == &olds->local[0]) {
|
|
|
|
news->buf = &news->local[0];
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-09 12:21:55 -04:00
|
|
|
struct cvtable iostream_vtable = { print_iostream, relocate_iostream,
|
|
|
|
free_iostream, NULL };
|
2009-02-08 22:22:31 -05:00
|
|
|
|
2009-08-23 03:06:57 -04:00
|
|
|
int fl_isiostream(value_t v)
|
2009-02-08 22:22:31 -05:00
|
|
|
{
|
2019-08-09 12:36:20 -04:00
|
|
|
return iscvalue(v) && cv_class((struct cvalue *)ptr(v)) == iostreamtype;
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_iostreamp(value_t *args, uint32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("iostream?", nargs, 1);
|
2009-08-23 03:06:57 -04:00
|
|
|
return fl_isiostream(args[0]) ? FL_T : FL_F;
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
|
2009-08-09 14:04:03 -04:00
|
|
|
value_t fl_eof_object(value_t *args, uint32_t nargs)
|
|
|
|
{
|
|
|
|
(void)args;
|
|
|
|
argcount("eof-object", nargs, 0);
|
|
|
|
return FL_EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_eof_objectp(value_t *args, uint32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("eof-object?", nargs, 1);
|
|
|
|
return (FL_EOF == args[0]) ? FL_T : FL_F;
|
|
|
|
}
|
|
|
|
|
2019-08-09 12:26:20 -04:00
|
|
|
static struct ios *toiostream(value_t v, char *fname)
|
2009-02-08 22:22:31 -05:00
|
|
|
{
|
2009-08-23 03:06:57 -04:00
|
|
|
if (!fl_isiostream(v))
|
2009-02-08 22:22:31 -05:00
|
|
|
type_error(fname, "iostream", v);
|
2019-08-09 12:26:20 -04:00
|
|
|
return value2c(struct ios *, v);
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *fl_toiostream(value_t v, char *fname)
|
|
|
|
{
|
|
|
|
return toiostream(v, fname);
|
|
|
|
}
|
2010-05-05 01:31:46 -04:00
|
|
|
|
2009-02-08 22:22:31 -05:00
|
|
|
value_t fl_file(value_t *args, uint32_t nargs)
|
|
|
|
{
|
|
|
|
if (nargs < 1)
|
|
|
|
argcount("file", nargs, 1);
|
2019-08-09 07:02:02 -04:00
|
|
|
int i, r = 0, w = 0, c = 0, t = 0, a = 0;
|
|
|
|
for (i = 1; i < (int)nargs; i++) {
|
|
|
|
if (args[i] == wrsym)
|
|
|
|
w = 1;
|
|
|
|
else if (args[i] == apsym) {
|
|
|
|
a = 1;
|
|
|
|
w = 1;
|
|
|
|
} else if (args[i] == crsym) {
|
|
|
|
c = 1;
|
|
|
|
w = 1;
|
|
|
|
} else if (args[i] == truncsym) {
|
|
|
|
t = 1;
|
|
|
|
w = 1;
|
|
|
|
} else if (args[i] == rdsym)
|
|
|
|
r = 1;
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
2019-08-09 07:02:02 -04:00
|
|
|
if ((r | w | c | t | a) == 0)
|
|
|
|
r = 1; // default to reading
|
2019-08-09 12:26:20 -04:00
|
|
|
value_t f = cvalue(iostreamtype, sizeof(struct ios));
|
2009-02-20 00:11:05 -05:00
|
|
|
char *fname = tostring(args[0], "file");
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = value2c(struct ios *, f);
|
2009-02-08 22:22:31 -05:00
|
|
|
if (ios_file(s, fname, r, w, c, t) == NULL)
|
2009-03-24 22:28:21 -04:00
|
|
|
lerrorf(IOError, "file: could not open \"%s\"", fname);
|
2019-08-09 07:02:02 -04:00
|
|
|
if (a)
|
|
|
|
ios_seek_end(s);
|
2009-02-08 22:22:31 -05:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2009-03-04 22:48:17 -05:00
|
|
|
value_t fl_buffer(value_t *args, u_int32_t nargs)
|
2009-03-01 23:26:16 -05:00
|
|
|
{
|
2009-03-04 22:48:17 -05:00
|
|
|
argcount("buffer", nargs, 0);
|
2009-03-01 23:26:16 -05:00
|
|
|
(void)args;
|
2019-08-09 12:26:20 -04:00
|
|
|
value_t f = cvalue(iostreamtype, sizeof(struct ios));
|
|
|
|
struct ios *s = value2c(struct ios *, f);
|
2009-03-01 23:26:16 -05:00
|
|
|
if (ios_mem(s, 0) == NULL)
|
2009-03-04 22:48:17 -05:00
|
|
|
lerror(MemoryError, "buffer: could not allocate stream");
|
2009-03-01 23:26:16 -05:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2009-02-09 00:38:40 -05:00
|
|
|
value_t fl_read(value_t *args, u_int32_t nargs)
|
2009-02-08 22:22:31 -05:00
|
|
|
{
|
2013-06-08 19:29:15 -04:00
|
|
|
value_t arg = 0;
|
2009-02-20 00:11:05 -05:00
|
|
|
if (nargs > 1) {
|
2009-02-09 00:38:40 -05:00
|
|
|
argcount("read", nargs, 1);
|
2019-08-09 07:02:02 -04:00
|
|
|
} else if (nargs == 0) {
|
2009-05-18 22:54:56 -04:00
|
|
|
arg = symbol_value(instrsym);
|
2019-08-09 07:02:02 -04:00
|
|
|
} else {
|
2009-05-18 22:54:56 -04:00
|
|
|
arg = args[0];
|
|
|
|
}
|
2009-08-09 16:34:07 -04:00
|
|
|
(void)toiostream(arg, "read");
|
|
|
|
fl_gc_handle(&arg);
|
2010-04-29 14:01:26 -04:00
|
|
|
value_t v = fl_read_sexpr(arg);
|
2009-08-09 16:34:07 -04:00
|
|
|
fl_free_gc_handles(1);
|
2019-08-09 12:26:20 -04:00
|
|
|
if (ios_eof(value2c(struct ios *, arg)))
|
2009-08-09 14:04:03 -04:00
|
|
|
return FL_EOF;
|
|
|
|
return v;
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|
|
|
|
|
2009-02-18 22:31:40 -05:00
|
|
|
value_t fl_iogetc(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.getc", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.getc");
|
2009-02-18 22:31:40 -05:00
|
|
|
uint32_t wc;
|
|
|
|
if (ios_getutf8(s, &wc) == IOS_EOF)
|
2019-08-09 07:02:02 -04:00
|
|
|
// lerror(IOError, "io.getc: end of file reached");
|
2009-08-09 14:04:03 -04:00
|
|
|
return FL_EOF;
|
2009-02-18 22:31:40 -05:00
|
|
|
return mk_wchar(wc);
|
|
|
|
}
|
|
|
|
|
2009-08-23 01:07:46 -04:00
|
|
|
value_t fl_iopeekc(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.peekc", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.peekc");
|
2009-08-23 01:07:46 -04:00
|
|
|
uint32_t wc;
|
|
|
|
if (ios_peekutf8(s, &wc) == IOS_EOF)
|
|
|
|
return FL_EOF;
|
|
|
|
return mk_wchar(wc);
|
|
|
|
}
|
|
|
|
|
2009-03-04 22:48:17 -05:00
|
|
|
value_t fl_ioputc(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.putc", nargs, 2);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.putc");
|
2019-08-09 12:25:43 -04:00
|
|
|
if (!iscprim(args[1]) ||
|
|
|
|
((struct cprim *)ptr(args[1]))->type != wchartype)
|
2009-03-04 22:48:17 -05:00
|
|
|
type_error("io.putc", "wchar", args[1]);
|
2019-08-09 12:25:43 -04:00
|
|
|
uint32_t wc = *(uint32_t *)cp_data((struct cprim *)ptr(args[1]));
|
2009-03-04 22:48:17 -05:00
|
|
|
return fixnum(ios_pututf8(s, wc));
|
|
|
|
}
|
|
|
|
|
2013-06-08 19:29:15 -04:00
|
|
|
value_t fl_ioungetc(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.ungetc", nargs, 2);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.ungetc");
|
2019-08-09 12:25:43 -04:00
|
|
|
if (!iscprim(args[1]) ||
|
|
|
|
((struct cprim *)ptr(args[1]))->type != wchartype)
|
2013-06-08 19:29:15 -04:00
|
|
|
type_error("io.ungetc", "wchar", args[1]);
|
2019-08-09 12:25:43 -04:00
|
|
|
uint32_t wc = *(uint32_t *)cp_data((struct cprim *)ptr(args[1]));
|
2013-06-08 19:29:15 -04:00
|
|
|
if (wc >= 0x80) {
|
|
|
|
lerror(ArgError, "io_ungetc: unicode not yet supported");
|
|
|
|
}
|
2019-08-09 07:02:02 -04:00
|
|
|
return fixnum(ios_ungetc((int)wc, s));
|
2013-06-08 19:29:15 -04:00
|
|
|
}
|
|
|
|
|
2009-02-18 22:31:40 -05:00
|
|
|
value_t fl_ioflush(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.flush", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.flush");
|
2009-02-18 22:31:40 -05:00
|
|
|
if (ios_flush(s) != 0)
|
|
|
|
return FL_F;
|
|
|
|
return FL_T;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_ioclose(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.close", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.close");
|
2009-02-18 22:31:40 -05:00
|
|
|
ios_close(s);
|
|
|
|
return FL_T;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_iopurge(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.discardbuffer", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.discardbuffer");
|
2009-02-18 22:31:40 -05:00
|
|
|
ios_purge(s);
|
|
|
|
return FL_T;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_ioeof(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.eof?", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.eof?");
|
2009-02-18 22:31:40 -05:00
|
|
|
return (ios_eof(s) ? FL_T : FL_F);
|
|
|
|
}
|
|
|
|
|
2009-03-21 22:05:26 -04:00
|
|
|
value_t fl_ioseek(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.seek", nargs, 2);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.seek");
|
2009-03-21 22:05:26 -04:00
|
|
|
size_t pos = toulong(args[1], "io.seek");
|
|
|
|
off_t res = ios_seek(s, (off_t)pos);
|
|
|
|
if (res == -1)
|
|
|
|
return FL_F;
|
|
|
|
return FL_T;
|
|
|
|
}
|
|
|
|
|
2009-07-21 23:50:57 -04:00
|
|
|
value_t fl_iopos(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.pos", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.pos");
|
2009-07-21 23:50:57 -04:00
|
|
|
off_t res = ios_pos(s);
|
|
|
|
if (res == -1)
|
|
|
|
return FL_F;
|
|
|
|
return size_wrap((size_t)res);
|
|
|
|
}
|
|
|
|
|
2009-08-07 20:29:55 -04:00
|
|
|
value_t fl_write(value_t *args, u_int32_t nargs)
|
2009-02-09 00:38:40 -05:00
|
|
|
{
|
2009-08-07 20:29:55 -04:00
|
|
|
if (nargs < 1 || nargs > 2)
|
|
|
|
argcount("write", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s;
|
2009-08-07 20:29:55 -04:00
|
|
|
if (nargs == 2)
|
|
|
|
s = toiostream(args[1], "write");
|
|
|
|
else
|
|
|
|
s = toiostream(symbol_value(outstrsym), "write");
|
2010-04-29 14:01:26 -04:00
|
|
|
fl_print(s, args[0]);
|
2009-08-07 20:29:55 -04:00
|
|
|
return args[0];
|
2009-02-09 00:38:40 -05:00
|
|
|
}
|
|
|
|
|
2009-03-01 23:26:16 -05:00
|
|
|
value_t fl_ioread(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
if (nargs != 3)
|
|
|
|
argcount("io.read", nargs, 2);
|
|
|
|
(void)toiostream(args[0], "io.read");
|
|
|
|
size_t n;
|
2019-08-09 12:33:04 -04:00
|
|
|
struct fltype *ft;
|
2009-03-01 23:26:16 -05:00
|
|
|
if (nargs == 3) {
|
|
|
|
// form (io.read s type count)
|
|
|
|
ft = get_array_type(args[1]);
|
|
|
|
n = toulong(args[2], "io.read") * ft->elsz;
|
2019-08-09 07:02:02 -04:00
|
|
|
} else {
|
2009-03-01 23:26:16 -05:00
|
|
|
ft = get_type(args[1]);
|
|
|
|
if (ft->eltype != NULL && !iscons(cdr_(cdr_(args[1]))))
|
|
|
|
lerror(ArgError, "io.read: incomplete type");
|
|
|
|
n = ft->size;
|
|
|
|
}
|
|
|
|
value_t cv = cvalue(ft, n);
|
|
|
|
char *data;
|
2019-08-09 07:02:02 -04:00
|
|
|
if (iscvalue(cv))
|
2019-08-09 12:36:20 -04:00
|
|
|
data = cv_data((struct cvalue *)ptr(cv));
|
2019-08-09 07:02:02 -04:00
|
|
|
else
|
2019-08-09 12:25:43 -04:00
|
|
|
data = cp_data((struct cprim *)ptr(cv));
|
2019-08-09 12:26:20 -04:00
|
|
|
size_t got = ios_read(value2c(struct ios *, args[0]), data, n);
|
2009-03-01 23:26:16 -05:00
|
|
|
if (got < n)
|
2019-08-09 07:02:02 -04:00
|
|
|
// lerror(IOError, "io.read: end of input reached");
|
2009-08-09 14:04:03 -04:00
|
|
|
return FL_EOF;
|
2009-03-01 23:26:16 -05:00
|
|
|
return cv;
|
|
|
|
}
|
|
|
|
|
2009-08-09 00:04:31 -04:00
|
|
|
// args must contain data[, offset[, count]]
|
|
|
|
static void get_start_count_args(value_t *args, uint32_t nargs, size_t sz,
|
|
|
|
size_t *offs, size_t *nb, char *fname)
|
|
|
|
{
|
|
|
|
if (nargs > 1) {
|
|
|
|
*offs = toulong(args[1], fname);
|
|
|
|
if (nargs > 2)
|
|
|
|
*nb = toulong(args[2], fname);
|
|
|
|
else
|
|
|
|
*nb = sz - *offs;
|
|
|
|
if (*offs >= sz || *offs + *nb > sz)
|
|
|
|
bounds_error(fname, args[0], args[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-01 23:26:16 -05:00
|
|
|
value_t fl_iowrite(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
2009-08-09 00:04:31 -04:00
|
|
|
if (nargs < 2 || nargs > 4)
|
|
|
|
argcount("io.write", nargs, 2);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(args[0], "io.write");
|
2019-08-09 12:25:43 -04:00
|
|
|
if (iscprim(args[1]) &&
|
|
|
|
((struct cprim *)ptr(args[1]))->type == wchartype) {
|
2009-08-09 00:04:31 -04:00
|
|
|
if (nargs > 2)
|
|
|
|
lerror(ArgError,
|
|
|
|
"io.write: offset argument not supported for characters");
|
2019-08-09 12:25:43 -04:00
|
|
|
uint32_t wc = *(uint32_t *)cp_data((struct cprim *)ptr(args[1]));
|
2009-08-09 00:04:31 -04:00
|
|
|
return fixnum(ios_pututf8(s, wc));
|
|
|
|
}
|
2009-03-01 23:26:16 -05:00
|
|
|
char *data;
|
2019-08-09 07:02:02 -04:00
|
|
|
size_t sz, offs = 0;
|
2009-03-01 23:26:16 -05:00
|
|
|
to_sized_ptr(args[1], "io.write", &data, &sz);
|
2009-08-09 00:04:31 -04:00
|
|
|
size_t nb = sz;
|
|
|
|
if (nargs > 2) {
|
2019-08-09 07:02:02 -04:00
|
|
|
get_start_count_args(&args[1], nargs - 1, sz, &offs, &nb, "io.write");
|
2009-08-09 00:04:31 -04:00
|
|
|
data += offs;
|
|
|
|
}
|
|
|
|
return size_wrap(ios_write(s, data, nb));
|
2009-03-01 23:26:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_dump(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
2009-06-07 23:22:32 -04:00
|
|
|
if (nargs < 1 || nargs > 3)
|
|
|
|
argcount("dump", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *s = toiostream(symbol_value(outstrsym), "dump");
|
2009-03-01 23:26:16 -05:00
|
|
|
char *data;
|
2019-08-09 07:02:02 -04:00
|
|
|
size_t sz, offs = 0;
|
2009-03-01 23:26:16 -05:00
|
|
|
to_sized_ptr(args[0], "dump", &data, &sz);
|
2009-08-09 00:04:31 -04:00
|
|
|
size_t nb = sz;
|
2009-06-07 23:22:32 -04:00
|
|
|
if (nargs > 1) {
|
2009-08-09 00:04:31 -04:00
|
|
|
get_start_count_args(args, nargs, sz, &offs, &nb, "dump");
|
2009-06-07 23:22:32 -04:00
|
|
|
data += offs;
|
|
|
|
}
|
|
|
|
hexdump(s, data, nb, offs);
|
2009-03-01 23:26:16 -05:00
|
|
|
return FL_T;
|
|
|
|
}
|
|
|
|
|
2009-03-21 22:05:26 -04:00
|
|
|
static char get_delim_arg(value_t arg, char *fname)
|
|
|
|
{
|
|
|
|
size_t uldelim = toulong(arg, fname);
|
|
|
|
if (uldelim > 0x7f) {
|
|
|
|
// wchars > 0x7f, or anything else > 0xff, are out of range
|
2019-08-09 12:25:43 -04:00
|
|
|
if ((iscprim(arg) &&
|
|
|
|
cp_class((struct cprim *)ptr(arg)) == wchartype) ||
|
2009-03-21 22:05:26 -04:00
|
|
|
uldelim > 0xff)
|
2009-03-24 22:28:21 -04:00
|
|
|
lerrorf(ArgError, "%s: delimiter out of range", fname);
|
2009-03-21 22:05:26 -04:00
|
|
|
}
|
|
|
|
return (char)uldelim;
|
|
|
|
}
|
|
|
|
|
2009-03-02 22:16:30 -05:00
|
|
|
value_t fl_ioreaduntil(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.readuntil", nargs, 2);
|
|
|
|
value_t str = cvalue_string(80);
|
2019-08-09 12:36:20 -04:00
|
|
|
struct cvalue *cv = (struct cvalue *)ptr(str);
|
2009-03-02 22:16:30 -05:00
|
|
|
char *data = cv_data(cv);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios dest;
|
2009-03-02 22:16:30 -05:00
|
|
|
ios_mem(&dest, 0);
|
|
|
|
ios_setbuf(&dest, data, 80, 0);
|
2009-03-21 22:05:26 -04:00
|
|
|
char delim = get_delim_arg(args[1], "io.readuntil");
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *src = toiostream(args[0], "io.readuntil");
|
2009-03-02 22:16:30 -05:00
|
|
|
size_t n = ios_copyuntil(&dest, src, delim);
|
|
|
|
cv->len = n;
|
|
|
|
if (dest.buf != data) {
|
|
|
|
// outgrew initial space
|
|
|
|
cv->data = dest.buf;
|
2010-05-05 01:31:46 -04:00
|
|
|
#ifndef BOEHM_GC
|
2009-03-02 22:16:30 -05:00
|
|
|
cv_autorelease(cv);
|
2010-05-05 01:31:46 -04:00
|
|
|
#endif
|
2009-03-02 22:16:30 -05:00
|
|
|
}
|
2019-08-09 07:02:02 -04:00
|
|
|
((char *)cv->data)[n] = '\0';
|
2009-03-02 22:16:30 -05:00
|
|
|
if (n == 0 && ios_eof(src))
|
2009-08-09 14:04:03 -04:00
|
|
|
return FL_EOF;
|
2009-03-02 22:16:30 -05:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2009-03-21 22:05:26 -04:00
|
|
|
value_t fl_iocopyuntil(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.copyuntil", nargs, 3);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *dest = toiostream(args[0], "io.copyuntil");
|
|
|
|
struct ios *src = toiostream(args[1], "io.copyuntil");
|
2009-03-21 22:05:26 -04:00
|
|
|
char delim = get_delim_arg(args[2], "io.copyuntil");
|
|
|
|
return size_wrap(ios_copyuntil(dest, src, delim));
|
|
|
|
}
|
|
|
|
|
2009-08-08 19:43:12 -04:00
|
|
|
value_t fl_iocopy(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
if (nargs < 2 || nargs > 3)
|
|
|
|
argcount("io.copy", nargs, 2);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *dest = toiostream(args[0], "io.copy");
|
|
|
|
struct ios *src = toiostream(args[1], "io.copy");
|
2009-08-08 19:43:12 -04:00
|
|
|
if (nargs == 3) {
|
|
|
|
size_t n = toulong(args[2], "io.copy");
|
|
|
|
return size_wrap(ios_copy(dest, src, n));
|
|
|
|
}
|
|
|
|
return size_wrap(ios_copyall(dest, src));
|
|
|
|
}
|
|
|
|
|
2009-03-04 22:48:17 -05:00
|
|
|
value_t stream_to_string(value_t *ps)
|
|
|
|
{
|
|
|
|
value_t str;
|
|
|
|
size_t n;
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *st = value2c(struct ios *, *ps);
|
2009-03-04 22:48:17 -05:00
|
|
|
if (st->buf == &st->local[0]) {
|
|
|
|
n = st->size;
|
|
|
|
str = cvalue_string(n);
|
2019-08-09 12:26:20 -04:00
|
|
|
memcpy(cvalue_data(str), value2c(struct ios *, *ps)->buf, n);
|
|
|
|
ios_trunc(value2c(struct ios *, *ps), 0);
|
2019-08-09 07:02:02 -04:00
|
|
|
} else {
|
|
|
|
char *b = ios_takebuf(st, &n);
|
|
|
|
n--;
|
2009-03-04 22:48:17 -05:00
|
|
|
b[n] = '\0';
|
2009-08-09 14:04:03 -04:00
|
|
|
str = cvalue_from_ref(stringtype, b, n, FL_NIL);
|
2010-05-05 01:31:46 -04:00
|
|
|
#ifndef BOEHM_GC
|
2019-08-09 12:36:20 -04:00
|
|
|
cv_autorelease((struct cvalue *)ptr(str));
|
2010-05-05 01:31:46 -04:00
|
|
|
#endif
|
2009-03-04 22:48:17 -05:00
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_iotostring(value_t *args, u_int32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("io.tostring!", nargs, 1);
|
2019-08-09 12:26:20 -04:00
|
|
|
struct ios *src = toiostream(args[0], "io.tostring!");
|
2009-03-04 22:48:17 -05:00
|
|
|
if (src->bm != bm_mem)
|
|
|
|
lerror(ArgError, "io.tostring!: requires memory stream");
|
|
|
|
return stream_to_string(&args[0]);
|
|
|
|
}
|
|
|
|
|
2019-08-09 12:20:18 -04:00
|
|
|
static struct builtinspec iostreamfunc_info[] = {
|
2009-02-08 22:22:31 -05:00
|
|
|
{ "iostream?", fl_iostreamp },
|
2009-08-09 14:04:03 -04:00
|
|
|
{ "eof-object", fl_eof_object },
|
|
|
|
{ "eof-object?", fl_eof_objectp },
|
2009-03-01 23:26:16 -05:00
|
|
|
{ "dump", fl_dump },
|
2009-02-08 22:22:31 -05:00
|
|
|
{ "file", fl_file },
|
2009-03-04 22:48:17 -05:00
|
|
|
{ "buffer", fl_buffer },
|
2009-02-09 00:38:40 -05:00
|
|
|
{ "read", fl_read },
|
2009-08-07 20:29:55 -04:00
|
|
|
{ "write", fl_write },
|
2009-02-18 22:31:40 -05:00
|
|
|
{ "io.flush", fl_ioflush },
|
|
|
|
{ "io.close", fl_ioclose },
|
2019-08-09 07:02:02 -04:00
|
|
|
{ "io.eof?", fl_ioeof },
|
|
|
|
{ "io.seek", fl_ioseek },
|
|
|
|
{ "io.pos", fl_iopos },
|
|
|
|
{ "io.getc", fl_iogetc },
|
2013-06-08 19:29:15 -04:00
|
|
|
{ "io.ungetc", fl_ioungetc },
|
2019-08-09 07:02:02 -04:00
|
|
|
{ "io.putc", fl_ioputc },
|
|
|
|
{ "io.peekc", fl_iopeekc },
|
2009-02-18 22:31:40 -05:00
|
|
|
{ "io.discardbuffer", fl_iopurge },
|
2009-03-01 23:26:16 -05:00
|
|
|
{ "io.read", fl_ioread },
|
|
|
|
{ "io.write", fl_iowrite },
|
2009-08-08 19:43:12 -04:00
|
|
|
{ "io.copy", fl_iocopy },
|
2009-03-02 22:16:30 -05:00
|
|
|
{ "io.readuntil", fl_ioreaduntil },
|
2009-03-21 22:05:26 -04:00
|
|
|
{ "io.copyuntil", fl_iocopyuntil },
|
2009-03-04 22:48:17 -05:00
|
|
|
{ "io.tostring!", fl_iotostring },
|
2013-06-08 19:29:15 -04:00
|
|
|
|
2009-02-08 22:22:31 -05:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2013-06-08 19:29:15 -04:00
|
|
|
void iostream_init(void)
|
2009-02-08 22:22:31 -05:00
|
|
|
{
|
|
|
|
iostreamsym = symbol("iostream");
|
|
|
|
rdsym = symbol(":read");
|
|
|
|
wrsym = symbol(":write");
|
|
|
|
apsym = symbol(":append");
|
|
|
|
crsym = symbol(":create");
|
|
|
|
truncsym = symbol(":truncate");
|
2009-02-09 00:38:40 -05:00
|
|
|
instrsym = symbol("*input-stream*");
|
2009-03-01 23:26:16 -05:00
|
|
|
outstrsym = symbol("*output-stream*");
|
2019-08-09 12:26:20 -04:00
|
|
|
iostreamtype = define_opaque_type(iostreamsym, sizeof(struct ios),
|
|
|
|
&iostream_vtable, NULL);
|
2009-02-08 22:22:31 -05:00
|
|
|
assign_global_builtins(iostreamfunc_info);
|
|
|
|
|
2019-08-09 12:26:20 -04:00
|
|
|
setc(symbol("*stdout*"), cvalue_from_ref(iostreamtype, ios_stdout,
|
|
|
|
sizeof(struct ios), FL_NIL));
|
|
|
|
setc(symbol("*stderr*"), cvalue_from_ref(iostreamtype, ios_stderr,
|
|
|
|
sizeof(struct ios), FL_NIL));
|
|
|
|
setc(symbol("*stdin*"), cvalue_from_ref(iostreamtype, ios_stdin,
|
|
|
|
sizeof(struct ios), FL_NIL));
|
2009-02-08 22:22:31 -05:00
|
|
|
}
|