Add builtin wrappers for the basic POSIX file APIs.
This commit is contained in:
parent
b74f0cddda
commit
c1a0850bcf
5
Makefile
5
Makefile
|
|
@ -25,10 +25,11 @@ endif
|
||||||
clean:
|
clean:
|
||||||
-rm -f rosella *.o *.gcda *.gcno
|
-rm -f rosella *.o *.gcda *.gcno
|
||||||
|
|
||||||
rosella: rosella.o gc.o builtin.o interp.o reader.o
|
rosella: rosella.o gc.o builtin.o interp.o reader.o io_builtin.o
|
||||||
|
|
||||||
rosella.o: rosella.c gc.h builtin.h interp.h
|
rosella.o: rosella.c gc.h builtin.h interp.h
|
||||||
gc.o: gc.c gc.h
|
gc.o: gc.c gc.h
|
||||||
builtin.o: builtin.c builtin.h gc.h
|
builtin.o: builtin.c builtin.h interp.h gc.h
|
||||||
interp.o: interp.c interp.h gc.h builtin.h
|
interp.o: interp.c interp.h gc.h builtin.h
|
||||||
reader.o: reader.c reader.h gc.h builtin.h
|
reader.o: reader.c reader.h gc.h builtin.h
|
||||||
|
io_builtin.o: io_builtin.c io_builtin.h builtin.h interp.h gc.h
|
||||||
|
|
|
||||||
5
gc.h
5
gc.h
|
|
@ -259,6 +259,11 @@ static inline fixnum_t _get_fixnum(value_t n)
|
||||||
return ((fixnum_t)n) >> 1;
|
return ((fixnum_t)n) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_valid_fixnum(fixnum_t n)
|
||||||
|
{
|
||||||
|
return _get_fixnum(fixnum_value(n)) == n;
|
||||||
|
}
|
||||||
|
|
||||||
static inline value_t object_value(void *obj)
|
static inline value_t object_value(void *obj)
|
||||||
{
|
{
|
||||||
assert((uintptr_t)obj >= 4096);
|
assert((uintptr_t)obj >= 4096);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gc.h"
|
||||||
|
#include "builtin.h"
|
||||||
|
#include "interp.h"
|
||||||
|
#include "io_builtin.h"
|
||||||
|
|
||||||
|
static void bi_posix_open(interp_state_t *state);
|
||||||
|
//static void bi_posix_openat(interp_state_t *state);
|
||||||
|
static void bi_posix_dup(interp_state_t *state);
|
||||||
|
static void bi_posix_dup2(interp_state_t *state);
|
||||||
|
static void bi_posix_read(interp_state_t *state);
|
||||||
|
static void bi_posix_write(interp_state_t *state);
|
||||||
|
static void bi_posix_lseek(interp_state_t *state);
|
||||||
|
static void bi_posix_close(interp_state_t *state);
|
||||||
|
|
||||||
|
void io_builtin_init(void)
|
||||||
|
{
|
||||||
|
register_builtin(BI_IO_POSIX_OPEN, make_builtin_fn(bi_posix_open));
|
||||||
|
//register_builtin(BI_IO_POSIX_OPENAT, make_builtin_fn(bi_posix_openat));
|
||||||
|
register_builtin(BI_IO_POSIX_OPENAT, UNDEFINED);
|
||||||
|
|
||||||
|
register_builtin(BI_IO_POSIX_DUP, make_builtin_fn(bi_posix_dup));
|
||||||
|
register_builtin(BI_IO_POSIX_DUP2, make_builtin_fn(bi_posix_dup2));
|
||||||
|
|
||||||
|
register_builtin(BI_IO_POSIX_READ, make_builtin_fn(bi_posix_read));
|
||||||
|
register_builtin(BI_IO_POSIX_WRITE, make_builtin_fn(bi_posix_write));
|
||||||
|
register_builtin(BI_IO_POSIX_LSEEK, make_builtin_fn(bi_posix_lseek));
|
||||||
|
|
||||||
|
register_builtin(BI_IO_POSIX_CLOSE, make_builtin_fn(bi_posix_close));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_return(interp_state_t *state, value_t rval)
|
||||||
|
{
|
||||||
|
state->lambda.value = state->k.value;
|
||||||
|
state->argv.value = rval;
|
||||||
|
state->k.value = FALSE_VALUE;
|
||||||
|
state->ctx.value = FALSE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_return2(interp_state_t *state, value_t v1, value_t v2)
|
||||||
|
{
|
||||||
|
simple_return(state, cons(v1, cons(v2, NIL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_open(interp_state_t *state)
|
||||||
|
{
|
||||||
|
char *pathname;
|
||||||
|
int flags;
|
||||||
|
mode_t mode;
|
||||||
|
int fd;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_nil(CDDR(state->argv.value)) || is_nil(CDR(_CDDR(state->argv.value))));
|
||||||
|
|
||||||
|
pathname = value_to_string(CAR(state->argv.value));
|
||||||
|
flags = get_fixnum(CAR(_CDR(state->argv.value)));
|
||||||
|
|
||||||
|
if (!is_nil(_CDDR(state->argv.value)))
|
||||||
|
{
|
||||||
|
mode = get_fixnum(CAR(_CDDR(state->argv.value)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
release_assert((flags & O_CREAT) == 0);
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
fd = open(pathname, flags, mode);
|
||||||
|
saved_errno = errno;
|
||||||
|
free(pathname);
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(fd));
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
simple_return2(state, (fd >= 0) ? fixnum_value(fd) : FALSE_VALUE,
|
||||||
|
fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
//static void bi_posix_openat(interp_state_t *state) {}
|
||||||
|
|
||||||
|
static void bi_posix_dup(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int oldfd = get_fixnum(CAR(state->argv.value));
|
||||||
|
int newfd;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_nil(_CDR(state->argv.value)));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
newfd = dup(oldfd);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(newfd));
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
simple_return2(state, (newfd >= 0) ? fixnum_value(newfd) : FALSE_VALUE,
|
||||||
|
fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_dup2(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int oldfd = get_fixnum(CAR(state->argv.value));
|
||||||
|
int newfd = get_fixnum(CAR(_CDR(state->argv.value)));
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_nil(_CDDR(state->argv.value)));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
newfd = dup2(oldfd, newfd);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(newfd));
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
simple_return2(state, (newfd >= 0) ? fixnum_value(newfd) : FALSE_VALUE,
|
||||||
|
fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_read(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int fd = get_fixnum(CAR(state->argv.value));
|
||||||
|
value_t str = CAR(_CDR(state->argv.value));
|
||||||
|
fixnum_t count = get_fixnum(CAR(_CDDR(state->argv.value)));
|
||||||
|
ssize_t result;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_byte_string(str));
|
||||||
|
release_assert(is_nil(_CDR(_CDDR(state->argv.value))));
|
||||||
|
release_assert((0 <= count) && (count <= _get_byte_string(str)->size));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
result = read(fd, _get_byte_string(str)->bytes, count);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(result));
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
simple_return2(state, (result >= 0) ? fixnum_value(result) : FALSE_VALUE,
|
||||||
|
fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_write(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int fd = get_fixnum(CAR(state->argv.value));
|
||||||
|
value_t str = CAR(_CDR(state->argv.value));
|
||||||
|
fixnum_t count = get_fixnum(CAR(_CDDR(state->argv.value)));
|
||||||
|
ssize_t result;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_byte_string(str));
|
||||||
|
release_assert(is_nil(_CDR(_CDDR(state->argv.value))));
|
||||||
|
release_assert((0 <= count) && (count <= _get_byte_string(str)->size));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
result = write(fd, _get_byte_string(str)->bytes, count);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(result));
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
simple_return2(state, (result >= 0) ? fixnum_value(result) : FALSE_VALUE,
|
||||||
|
fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_lseek(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int fd = get_fixnum(CAR(state->argv.value));
|
||||||
|
fixnum_t off = get_fixnum(CAR(_CDR(state->argv.value)));
|
||||||
|
fixnum_t whence = get_fixnum(CAR(_CDDR(state->argv.value)));
|
||||||
|
off_t result;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_nil(_CDR(_CDDR(state->argv.value))));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
result = lseek(fd, off, whence);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
release_assert(is_valid_fixnum(saved_errno));
|
||||||
|
|
||||||
|
if (result == (off_t)(-1))
|
||||||
|
{
|
||||||
|
simple_return2(state, FALSE_VALUE, fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
release_assert((result >= 0) && (result <= FIXNUM_MAX));
|
||||||
|
simple_return2(state, fixnum_value(result), fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bi_posix_close(interp_state_t *state)
|
||||||
|
{
|
||||||
|
int fd = get_fixnum(CAR(state->argv.value));
|
||||||
|
ssize_t result;
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
release_assert(is_nil(_CDR(state->argv.value)));
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
result = close(fd);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
simple_return2(state, boolean_value(!result), fixnum_value(saved_errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set sw=2 expandtab: */
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef IO_BUILTIN_H_a9dd5b4902aa45e05dcf2b0fdb33ec74
|
||||||
|
#define IO_BUILTIN_H_a9dd5b4902aa45e05dcf2b0fdb33ec74
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define BI_IO_POSIX_OPEN "posix-open"
|
||||||
|
#define BI_IO_POSIX_OPENAT "posix-openat"
|
||||||
|
|
||||||
|
#define BI_IO_POSIX_DUP "posix-dup"
|
||||||
|
#define BI_IO_POSIX_DUP2 "posix-dup2"
|
||||||
|
|
||||||
|
#define BI_IO_POSIX_READ "posix-read"
|
||||||
|
#define BI_IO_POSIX_WRITE "posix-write"
|
||||||
|
#define BI_IO_POSIX_LSEEK "posix-lseek"
|
||||||
|
|
||||||
|
#define BI_IO_POSIX_CLOSE "posix-close"
|
||||||
|
|
||||||
|
void io_builtin_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* vim:set sw=2 expandtab: */
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "interp.h"
|
#include "interp.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
|
#include "io_builtin.h"
|
||||||
|
|
||||||
static void test_builtins(void);
|
static void test_builtins(void);
|
||||||
static void test_weak_boxes_and_wills(void);
|
static void test_weak_boxes_and_wills(void);
|
||||||
|
|
@ -34,6 +35,7 @@ int main(int argc, char **argv)
|
||||||
gc_init(256*1024, 1024*1024);
|
gc_init(256*1024, 1024*1024);
|
||||||
builtin_init();
|
builtin_init();
|
||||||
interpreter_init();
|
interpreter_init();
|
||||||
|
io_builtin_init();
|
||||||
|
|
||||||
if (argc < 2 || (strcmp(argv[1], "-k") == 0))
|
if (argc < 2 || (strcmp(argv[1], "-k") == 0))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue