diff --git a/eval.c b/eval.c index 302e5c94..cdd229d8 100644 --- a/eval.c +++ b/eval.c @@ -1011,17 +1011,12 @@ sexp sexp_open_input_file_op (sexp ctx, sexp self, sexp_sint_t n, sexp path) { FILE *in; int count = 0; sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, path); - loop: - in = fopen(sexp_string_data(path), "r"); - if (!in) { -#if SEXP_USE_GC_FILE_DESCRIPTORS - if (errno == EMFILE && !count++) { - sexp_gc(ctx, NULL); - goto loop; - } -#endif + do { + if (count != 0) sexp_gc(ctx, NULL); + in = fopen(sexp_string_data(path), "r"); + } while (!in && sexp_out_of_file_descriptors() && !count++); + if (!in) return sexp_user_exception(ctx, self, "couldn't open input file", path); - } #if SEXP_USE_GREEN_THREADS fcntl(fileno(in), F_SETFL, O_NONBLOCK); #endif @@ -1032,17 +1027,12 @@ sexp sexp_open_output_file_op (sexp ctx, sexp self, sexp_sint_t n, sexp path) { FILE *out; int count = 0; sexp_assert_type(ctx, sexp_stringp, SEXP_STRING, path); - loop: - out = fopen(sexp_string_data(path), "w"); - if (!out) { -#if SEXP_USE_GC_FILE_DESCRIPTORS - if (errno == EMFILE && !count++) { - sexp_gc(ctx, NULL); - goto loop; - } -#endif + do { + if (count != 0) sexp_gc(ctx, NULL); + out = fopen(sexp_string_data(path), "w"); + } while (!out && sexp_out_of_file_descriptors() && !count++); + if (!out) return sexp_user_exception(ctx, self, "couldn't open output file", path); - } return sexp_make_output_port(ctx, out, path); } diff --git a/include/chibi/features.h b/include/chibi/features.h index 1e0cf0f4..0846d313 100644 --- a/include/chibi/features.h +++ b/include/chibi/features.h @@ -507,7 +507,7 @@ #endif #ifndef SEXP_USE_GC_FILE_DESCRIPTORS -#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM) +#define SEXP_USE_GC_FILE_DESCRIPTORS (SEXP_USE_AUTOCLOSE_PORTS &&!SEXP_USE_BOEHM && !defined(PLAN9)) #endif #ifndef SEXP_USE_2010_EPOCH diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 9e032aa3..3f30cfa2 100755 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -25,9 +25,11 @@ extern "C" { #if SEXP_USE_DL #include #endif +#if SEXP_USE_GREEN_THREADS || SEXP_USE_GC_FILE_DESCRIPTORS +#include +#endif #if SEXP_USE_GREEN_THREADS #include -#include #include #endif #define sexp_isalpha(x) (isalpha(x)) @@ -37,6 +39,12 @@ extern "C" { #define sexp_toupper(x) (toupper(x)) #endif +#if SEXP_USE_GC_FILE_DESCRIPTORS +#define sexp_out_of_file_descriptors() (errno == EMFILE) +#else +#define sexp_out_of_file_descriptors() (0) +#endif + #ifdef PLAN9 #include #include @@ -430,6 +438,8 @@ void sexp_free(void* ptr); #if SEXP_USE_BOEHM +#define sexp_gc(ctx, sum) + #define sexp_gc_var(ctx, x, y) sexp x; #define sexp_gc_preserve(ctx, x, y) #define sexp_gc_release(ctx, x, y) @@ -443,6 +453,8 @@ void sexp_free(void* ptr); #else +SEXP_API sexp sexp_gc(sexp ctx, size_t *sum_freed); + #define sexp_gc_var(ctx, x, y) \ sexp x = SEXP_VOID; \ struct sexp_gc_var_t y = {NULL, NULL};