Add builtin wrappers for the basic POSIX file APIs.

This commit is contained in:
Jesse D. McDonald 2009-11-17 21:49:31 -06:00
parent b74f0cddda
commit c1a0850bcf
5 changed files with 251 additions and 2 deletions

View File

@ -25,10 +25,11 @@ endif
clean:
-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
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
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
View File

@ -259,6 +259,11 @@ static inline fixnum_t _get_fixnum(value_t n)
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)
{
assert((uintptr_t)obj >= 4096);

219
io_builtin.c Normal file
View File

@ -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: */

22
io_builtin.h Normal file
View File

@ -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: */

View File

@ -11,6 +11,7 @@
#include "builtin.h"
#include "interp.h"
#include "reader.h"
#include "io_builtin.h"
static void test_builtins(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);
builtin_init();
interpreter_init();
io_builtin_init();
if (argc < 2 || (strcmp(argv[1], "-k") == 0))
{