diff --git a/Makefile b/Makefile index 925f7479..61c5bd60 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ LIBPICRIN_SRCS = \ lib/weak.c\ lib/ext/boot.c\ lib/ext/lib.c\ + lib/ext/file.c\ lib/ext/load.c\ lib/ext/read.c\ lib/ext/write.c diff --git a/lib/ext/file.c b/lib/ext/file.c new file mode 100644 index 00000000..02b07a55 --- /dev/null +++ b/lib/ext/file.c @@ -0,0 +1,87 @@ +/** + * See Copyright Notice in picrin.h + */ + +#include + +#include "picrin.h" + +#if PIC_USE_LIBC + +static int +file_read(pic_state *PIC_UNUSED(pic), void *cookie, char *ptr, int size) { + FILE *file = cookie; + int r; + + size = 1; /* override size */ + + r = (int)fread(ptr, 1, (size_t)size, file); + if (r < size && ferror(file)) { + return -1; + } + if (r == 0 && feof(file)) { + clearerr(file); + } + return r; +} + +static int +file_write(pic_state *PIC_UNUSED(pic), void *cookie, const char *ptr, int size) { + FILE *file = cookie; + int r; + + r = (int)fwrite(ptr, 1, (size_t)size, file); + if (r < size) { + return -1; + } + fflush(cookie); + return r; +} + +static long +file_seek(pic_state *PIC_UNUSED(pic), void *cookie, long pos, int whence) { + switch (whence) { + case PIC_SEEK_CUR: + whence = SEEK_CUR; + break; + case PIC_SEEK_SET: + whence = SEEK_SET; + break; + case PIC_SEEK_END: + whence = SEEK_END; + break; + } + if (fseek(cookie, pos, whence) == 0) { + return ftell(cookie); + } + return -1; +} + +static int +file_close(pic_state *PIC_UNUSED(pic), void *cookie) { + return fclose(cookie); +} + +pic_value +pic_fopen(pic_state *pic, FILE *fp, const char *mode) { + static const pic_port_type file_rd = { file_read, 0, file_seek, file_close }; + static const pic_port_type file_wr = { 0, file_write, file_seek, file_close }; + + if (*mode == 'r') { + return pic_funopen(pic, fp, &file_rd); + } else { + return pic_funopen(pic, fp, &file_wr); + } +} + +void +pic_init_file(pic_state *PIC_UNUSED(pic)) +{ +#if PIC_USE_STDIO + pic_defvar(pic, "current-input-port", pic_fopen(pic, stdin, "r")); + pic_defvar(pic, "current-output-port", pic_fopen(pic, stdout, "w")); + pic_defvar(pic, "current-error-port", pic_fopen(pic, stdout, "w")); +#endif +} + +#endif diff --git a/lib/port.c b/lib/port.c index 2550cb77..0a7a84f3 100644 --- a/lib/port.c +++ b/lib/port.c @@ -10,15 +10,6 @@ # define EOF (-1) #endif -bool -pic_port_p(pic_state *pic, pic_value obj, const pic_port_type *type) -{ - if (pic_type(pic, obj) != PIC_TYPE_PORT) { - return false; - } - return type == NULL || port_ptr(pic, obj)->file.vtable == type; -} - pic_value pic_funopen(pic_state *pic, void *cookie, const pic_port_type *type) { @@ -316,80 +307,6 @@ pic_fseek(pic_state *pic, pic_value port, long offset, int whence) return 0; } -#if PIC_USE_STDIO - -static int -file_read(pic_state *PIC_UNUSED(pic), void *cookie, char *ptr, int size) { - FILE *file = cookie; - int r; - - size = 1; /* override size */ - - r = (int)fread(ptr, 1, (size_t)size, file); - if (r < size && ferror(file)) { - return -1; - } - if (r == 0 && feof(file)) { - clearerr(file); - } - return r; -} - -static int -file_write(pic_state *PIC_UNUSED(pic), void *cookie, const char *ptr, int size) { - FILE *file = cookie; - int r; - - r = (int)fwrite(ptr, 1, (size_t)size, file); - if (r < size) { - return -1; - } - fflush(cookie); - return r; -} - -static long -file_seek(pic_state *PIC_UNUSED(pic), void *cookie, long pos, int whence) { - switch (whence) { - case PIC_SEEK_CUR: - whence = SEEK_CUR; - break; - case PIC_SEEK_SET: - whence = SEEK_SET; - break; - case PIC_SEEK_END: - whence = SEEK_END; - break; - } - if (fseek(cookie, pos, whence) == 0) { - return ftell(cookie); - } - return -1; -} - -static int -file_close(pic_state *PIC_UNUSED(pic), void *cookie) { - return fclose(cookie); -} - -static const pic_port_type file_rd = { - file_read, 0, file_seek, file_close -}; -static const pic_port_type file_wr = { - 0, file_write, file_seek, file_close -}; - -pic_value -pic_fopen(pic_state *pic, FILE *fp, const char *mode) { - if (*mode == 'r') { - return pic_funopen(pic, fp, &file_rd); - } else { - return pic_funopen(pic, fp, &file_wr); - } -} - -#endif - typedef struct { char *buf; long pos, end, capa; } xbuf_t; static int @@ -450,16 +367,11 @@ string_close(pic_state *pic, void *cookie) return 0; } -static const pic_port_type string_rd = { - string_read, 0, string_seek, string_close -}; -static const pic_port_type string_wr = { - 0, string_write, string_seek, string_close -}; - pic_value pic_fmemopen(pic_state *pic, const char *data, int size, const char *mode) { + static const pic_port_type string_rd = { string_read, 0, string_seek, string_close }; + static const pic_port_type string_wr = { 0, string_write, string_seek, string_close }; xbuf_t *m; m = pic_malloc(pic, sizeof(xbuf_t)); @@ -493,6 +405,15 @@ pic_fgetbuf(pic_state *pic, pic_value port, const char **buf, int *len) return 0; } +bool +pic_port_p(pic_state *pic, pic_value obj, const pic_port_type *type) +{ + if (pic_type(pic, obj) != PIC_TYPE_PORT) { + return false; + } + return type == NULL || port_ptr(pic, obj)->file.vtable == type; +} + static pic_value pic_port_input_port_p(pic_state *pic) { @@ -746,12 +667,6 @@ pic_port_flush(pic_state *pic) void pic_init_port(pic_state *pic) { -#if PIC_USE_STDIO - pic_defvar(pic, "current-input-port", pic_fopen(pic, stdin, "r")); - pic_defvar(pic, "current-output-port", pic_fopen(pic, stdout, "w")); - pic_defvar(pic, "current-error-port", pic_fopen(pic, stdout, "w")); -#endif - pic_defun(pic, "port?", pic_port_port_p); pic_defun(pic, "input-port?", pic_port_input_port_p); pic_defun(pic, "output-port?", pic_port_output_port_p); diff --git a/lib/state.c b/lib/state.c index 94da5cc5..3c9295b3 100644 --- a/lib/state.c +++ b/lib/state.c @@ -7,18 +7,33 @@ #include "object.h" #include "state.h" +void +pic_add_feature(pic_state *pic, const char *feature) +{ + pic_push(pic, pic_intern_cstr(pic, feature), pic->features); +} + static pic_value -pic_features(pic_state *pic) +pic_state_features(pic_state *pic) { pic_get_args(pic, ""); return pic->features; } -static void -pic_init_features(pic_state *pic) +static pic_value +pic_state_global_objects(pic_state *pic) { - pic_defun(pic, "features", pic_features); + pic_get_args(pic, ""); + + return pic->globals; +} + +static void +pic_init_state(pic_state *pic) +{ + pic_defun(pic, "features", pic_state_features); + pic_defun(pic, "global-objects", pic_state_global_objects); pic_add_feature(pic, "picrin"); @@ -75,20 +90,6 @@ pic_init_features(pic_state *pic) #endif } -void -pic_add_feature(pic_state *pic, const char *feature) -{ - pic_push(pic, pic_intern_cstr(pic, feature), pic->features); -} - -static pic_value -pic_global_objects(pic_state *pic) -{ - pic_get_args(pic, ""); - - return pic->globals; -} - void pic_init_bool(pic_state *); void pic_init_pair(pic_state *); void pic_init_port(pic_state *); @@ -108,6 +109,8 @@ void pic_init_dict(pic_state *); void pic_init_record(pic_state *); void pic_init_weak(pic_state *); void pic_init_load(pic_state *); +void pic_init_file(pic_state *); +void pic_init_state(pic_state *); void pic_boot(pic_state *); @@ -118,9 +121,6 @@ pic_init_core(pic_state *pic) { size_t ai = pic_enter(pic); - pic_defun(pic, "global-objects", pic_global_objects); - - pic_init_features(pic); DONE; pic_init_bool(pic); DONE; pic_init_pair(pic); DONE; pic_init_port(pic); DONE; @@ -134,15 +134,19 @@ pic_init_core(pic_state *pic) pic_init_error(pic); DONE; pic_init_str(pic); DONE; pic_init_var(pic); DONE; - pic_init_read(pic); DONE; pic_init_dict(pic); DONE; pic_init_record(pic); DONE; pic_init_weak(pic); DONE; + pic_init_state(pic); DONE; pic_init_load(pic); DONE; + pic_init_read(pic); DONE; #if PIC_USE_WRITE pic_init_write(pic); DONE; #endif +#if PIC_USE_LIBC + pic_init_file(pic); DONE; +#endif pic_boot(pic); DONE; }