VM: Refactor io.cpp/hpp to Factor style

db4
Erik Charlebois 2013-05-11 22:06:53 -04:00
parent d3d1d3bb7a
commit 894e181f31
2 changed files with 170 additions and 210 deletions

377
vm/io.cpp
View File

@ -1,7 +1,6 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
/* Simple wrappers for ANSI C I/O functions, used for bootstrapping. /* Simple wrappers for ANSI C I/O functions, used for bootstrapping.
@ -14,269 +13,231 @@ The Factor library provides platform-specific code for Unix and Windows
with many more capabilities so these words are not usually used in with many more capabilities so these words are not usually used in
normal operation. */ normal operation. */
void factor_vm::init_c_io() void factor_vm::init_c_io() {
{ special_objects[OBJ_STDIN] = allot_alien(false_object, (cell) stdin);
special_objects[OBJ_STDIN] = allot_alien(false_object,(cell)stdin); special_objects[OBJ_STDOUT] = allot_alien(false_object, (cell) stdout);
special_objects[OBJ_STDOUT] = allot_alien(false_object,(cell)stdout); special_objects[OBJ_STDERR] = allot_alien(false_object, (cell) stderr);
special_objects[OBJ_STDERR] = allot_alien(false_object,(cell)stderr);
} }
void factor_vm::io_error() void factor_vm::io_error() {
{ if (errno == EINTR)
if(errno == EINTR) return;
return;
general_error(ERROR_IO,tag_fixnum(errno),false_object); general_error(ERROR_IO, tag_fixnum(errno), false_object);
} }
FILE *factor_vm::safe_fopen(char *filename, char *mode) FILE* factor_vm::safe_fopen(char* filename, char* mode) {
{ FILE* file;
FILE *file; for (;;) {
for(;;) file = fopen(filename, mode);
{ if (file == NULL)
file = fopen(filename,mode); io_error();
if(file == NULL) else
io_error(); break;
else }
break; return file;
}
return file;
} }
int factor_vm::safe_fgetc(FILE *stream) int factor_vm::safe_fgetc(FILE* stream) {
{ int c;
int c; for (;;) {
for(;;) c = getc(stream);
{ if (c == EOF) {
c = getc(stream); if (feof(stream))
if(c == EOF) return EOF;
{ else
if(feof(stream)) io_error();
return EOF; } else
else break;
io_error(); }
} return c;
else
break;
}
return c;
} }
size_t factor_vm::safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream) size_t factor_vm::safe_fread(void* ptr, size_t size, size_t nitems,
{ FILE* stream) {
size_t items_read = 0; size_t items_read = 0;
size_t ret = 0; size_t ret = 0;
do do {
{ ret = fread((void*)((int*)ptr + items_read * size), size,
ret = fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream); nitems - items_read, stream);
if(ret == 0) if (ret == 0) {
{ if (feof(stream))
if(feof(stream)) break;
break; else
else io_error();
io_error(); }
} items_read += ret;
items_read += ret; } while (items_read != nitems);
} while(items_read != nitems);
return items_read; return items_read;
} }
void factor_vm::safe_fputc(int c, FILE *stream) void factor_vm::safe_fputc(int c, FILE* stream) {
{ for (;;) {
for(;;) if (putc(c, stream) == EOF)
{ io_error();
if(putc(c,stream) == EOF) else
io_error(); break;
else }
break;
}
} }
size_t factor_vm::safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream) size_t factor_vm::safe_fwrite(void* ptr, size_t size, size_t nitems,
{ FILE* stream) {
size_t items_written = 0; size_t items_written = 0;
size_t ret = 0; size_t ret = 0;
do { do {
ret = fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream); ret = fwrite((void*)((int*)ptr + items_written * size), size,
if(ret == 0) nitems - items_written, stream);
io_error(); if (ret == 0)
items_written += ret; io_error();
} while(items_written != nitems); items_written += ret;
} while (items_written != nitems);
return items_written; return items_written;
} }
int factor_vm::safe_ftell(FILE *stream) int factor_vm::safe_ftell(FILE* stream) {
{ off_t offset;
off_t offset; for (;;) {
for(;;) if ((offset = FTELL(stream)) == -1)
{ io_error();
if((offset = FTELL(stream)) == -1) else
io_error(); break;
else }
break; return offset;
}
return offset;
} }
void factor_vm::safe_fseek(FILE *stream, off_t offset, int whence) void factor_vm::safe_fseek(FILE* stream, off_t offset, int whence) {
{ switch (whence) {
switch(whence) case 0:
{ whence = SEEK_SET;
case 0: whence = SEEK_SET; break; break;
case 1: whence = SEEK_CUR; break; case 1:
case 2: whence = SEEK_END; break; whence = SEEK_CUR;
default: break;
critical_error("Bad value for whence",whence); case 2:
} whence = SEEK_END;
break;
default:
critical_error("Bad value for whence", whence);
}
for(;;) for (;;) {
{ if (FSEEK(stream, offset, whence) == -1)
if(FSEEK(stream,offset,whence) == -1) io_error();
io_error(); else
else break;
break; }
}
} }
void factor_vm::safe_fflush(FILE *stream) void factor_vm::safe_fflush(FILE* stream) {
{ for (;;) {
for(;;) if (fflush(stream) == EOF)
{ io_error();
if(fflush(stream) == EOF) else
io_error(); break;
else }
break;
}
} }
void factor_vm::safe_fclose(FILE *stream) void factor_vm::safe_fclose(FILE* stream) {
{ for (;;) {
for(;;) if (fclose(stream) == EOF)
{ io_error();
if(fclose(stream) == EOF) else
io_error(); break;
else }
break;
}
} }
void factor_vm::primitive_fopen() void factor_vm::primitive_fopen() {
{ data_root<byte_array> mode(ctx->pop(), this);
data_root<byte_array> mode(ctx->pop(),this); data_root<byte_array> path(ctx->pop(), this);
data_root<byte_array> path(ctx->pop(),this); mode.untag_check(this);
mode.untag_check(this); path.untag_check(this);
path.untag_check(this);
FILE *file; FILE* file;
file = safe_fopen((char *)(path.untagged() + 1), file = safe_fopen((char*)(path.untagged() + 1), (char*)(mode.untagged() + 1));
(char *)(mode.untagged() + 1)); ctx->push(allot_alien(file));
ctx->push(allot_alien(file));
} }
FILE *factor_vm::pop_file_handle() FILE* factor_vm::pop_file_handle() { return (FILE*)alien_offset(ctx->pop()); }
{
return (FILE *)alien_offset(ctx->pop());
}
FILE *factor_vm::peek_file_handle() FILE* factor_vm::peek_file_handle() { return (FILE*)alien_offset(ctx->peek()); }
{
return (FILE *)alien_offset(ctx->peek());
}
void factor_vm::primitive_fgetc() void factor_vm::primitive_fgetc() {
{ FILE* file = peek_file_handle();
FILE *file = peek_file_handle();
int c = safe_fgetc(file); int c = safe_fgetc(file);
if(c == EOF && feof(file)) if (c == EOF && feof(file)) {
{ clearerr(file);
clearerr(file); ctx->replace(false_object);
ctx->replace(false_object); } else
} ctx->replace(tag_fixnum(c));
else
ctx->replace(tag_fixnum(c));
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::primitive_fread() void factor_vm::primitive_fread() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); void* buf = (void*)alien_offset(ctx->pop());
void *buf = (void*)alien_offset(ctx->pop()); fixnum size = unbox_array_size();
fixnum size = unbox_array_size();
if(size == 0) if (size == 0) {
{ ctx->push(from_unsigned_cell(0));
ctx->push(from_unsigned_cell(0)); return;
return; }
}
size_t c = safe_fread(buf,1,size,file); size_t c = safe_fread(buf, 1, size, file);
if(c == 0 || feof(file)) if (c == 0 || feof(file))
clearerr(file); clearerr(file);
ctx->push(from_unsigned_cell(c)); ctx->push(from_unsigned_cell(c));
} }
void factor_vm::primitive_fputc() void factor_vm::primitive_fputc() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); fixnum ch = to_fixnum(ctx->pop());
fixnum ch = to_fixnum(ctx->pop()); safe_fputc((int) ch, file);
safe_fputc((int)ch, file);
} }
void factor_vm::primitive_fwrite() void factor_vm::primitive_fwrite() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); cell length = to_cell(ctx->pop());
cell length = to_cell(ctx->pop()); char* text = alien_offset(ctx->pop());
char *text = alien_offset(ctx->pop());
if(length == 0) if (length == 0)
return; return;
size_t written = safe_fwrite(text,1,length,file); size_t written = safe_fwrite(text, 1, length, file);
if(written != length) if (written != length)
io_error(); io_error();
} }
void factor_vm::primitive_ftell() void factor_vm::primitive_ftell() {
{ FILE* file = peek_file_handle();
FILE *file = peek_file_handle(); ctx->replace(from_signed_8(safe_ftell(file)));
ctx->replace(from_signed_8(safe_ftell(file)));
} }
void factor_vm::primitive_fseek() void factor_vm::primitive_fseek() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); int whence = (int) to_fixnum(ctx->pop());
int whence = (int)to_fixnum(ctx->pop()); off_t offset = (off_t) to_signed_8(ctx->pop());
off_t offset = (off_t)to_signed_8(ctx->pop()); safe_fseek(file, offset, whence);
safe_fseek(file,offset,whence);
} }
void factor_vm::primitive_fflush() void factor_vm::primitive_fflush() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); safe_fflush(file);
safe_fflush(file);
} }
void factor_vm::primitive_fclose() void factor_vm::primitive_fclose() {
{ FILE* file = pop_file_handle();
FILE *file = pop_file_handle(); safe_fclose(file);
safe_fclose(file);
} }
/* This function is used by FFI I/O. Accessing the errno global directly is /* This function is used by FFI I/O. Accessing the errno global directly is
not portable, since on some libc's errno is not a global but a funky macro that not portable, since on some libc's errno is not a global but a funky macro that
reads thread-local storage. */ reads thread-local storage. */
VM_C_API int err_no() VM_C_API int err_no() { return errno; }
{
return errno;
}
VM_C_API void set_err_no(int err) VM_C_API void set_err_no(int err) { errno = err; }
{
errno = err;
}
} }

View File

@ -1,5 +1,4 @@
namespace factor namespace factor {
{
/* Platform specific primitives */ /* Platform specific primitives */