diff --git a/eval.c b/eval.c index eb5be667..a3b2a0d7 100644 --- a/eval.c +++ b/eval.c @@ -2058,14 +2058,7 @@ static sexp sexp_close_port (sexp ctx, sexp port) { return sexp_type_exception(ctx, "not a port", port); if (! sexp_port_openp(port)) return sexp_user_exception(ctx, SEXP_FALSE, "port already closed", port); - if (sexp_port_stream(port)) - fclose(sexp_port_stream(port)); -#if ! SEXP_USE_STRING_STREAMS - if (sexp_port_buf(port) && sexp_oportp(port)) - free(sexp_port_buf(port)); -#endif - sexp_port_openp(port) = 0; - return SEXP_VOID; + return sexp_finalize_port(ctx, port); } void sexp_warn_undefs (sexp ctx, sexp from, sexp to, sexp out) { @@ -2588,12 +2581,15 @@ sexp sexp_add_module_directory (sexp ctx, sexp dir, sexp appendp) { sexp sexp_load_standard_parameters (sexp ctx, sexp e) { /* add io port and interaction env parameters */ - sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_IN_SYMBOL), - sexp_make_input_port(ctx, stdin, SEXP_FALSE)); - sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_OUT_SYMBOL), - sexp_make_output_port(ctx, stdout, SEXP_FALSE)); - sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_ERR_SYMBOL), - sexp_make_output_port(ctx, stderr, SEXP_FALSE)); + sexp p = sexp_make_input_port(ctx, stdin, SEXP_FALSE); + sexp_port_no_closep(p) = 1; + sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_IN_SYMBOL), p); + p = sexp_make_output_port(ctx, stdout, SEXP_FALSE); + sexp_port_no_closep(p) = 1; + sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_OUT_SYMBOL), p); + p = sexp_make_output_port(ctx, stderr, SEXP_FALSE); + sexp_port_no_closep(p) = 1; + sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_CUR_ERR_SYMBOL), p); sexp_env_define(ctx, e, sexp_global(ctx, SEXP_G_INTERACTION_ENV_SYMBOL), e); return SEXP_VOID; } diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index fa668c2f..56315ef3 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -190,7 +190,7 @@ struct sexp_struct { struct { FILE *stream; char *buf; - char openp, sourcep; + char openp, no_closep, sourcep; sexp_uint_t offset, line; size_t size; sexp name; @@ -544,6 +544,7 @@ SEXP_API sexp sexp_make_unsigned_integer(sexp ctx, sexp_luint_t x); #define sexp_port_name(p) ((p)->value.port.name) #define sexp_port_line(p) ((p)->value.port.line) #define sexp_port_openp(p) ((p)->value.port.openp) +#define sexp_port_no_closep(p) ((p)->value.port.no_closep) #define sexp_port_sourcep(p) ((p)->value.port.sourcep) #define sexp_port_cookie(p) ((p)->value.port.cookie) #define sexp_port_buf(p) ((p)->value.port.buf) @@ -848,6 +849,7 @@ SEXP_API sexp sexp_read_raw(sexp ctx, sexp in); SEXP_API sexp sexp_read(sexp ctx, sexp in); SEXP_API sexp sexp_read_from_string(sexp ctx, char *str); SEXP_API sexp sexp_write_to_string(sexp ctx, sexp obj); +SEXP_API sexp sexp_finalize_port (sexp ctx, sexp port); SEXP_API sexp sexp_make_input_port(sexp ctx, FILE* in, sexp name); SEXP_API sexp sexp_make_output_port(sexp ctx, FILE* out, sexp name); SEXP_API sexp sexp_make_input_string_port(sexp ctx, sexp str); diff --git a/sexp.c b/sexp.c index 4d2baed7..517a0d70 100644 --- a/sexp.c +++ b/sexp.c @@ -53,13 +53,20 @@ sexp sexp_alloc_tagged(sexp ctx, size_t size, sexp_uint_t tag) { return res; } -#if SEXP_USE_AUTOCLOSE_PORTS -static sexp sexp_finalize_port (sexp ctx, sexp port) { - if (sexp_port_openp(port) && sexp_port_stream(port) - && sexp_stringp(sexp_port_name(port))) - fclose(sexp_port_stream(port)); +sexp sexp_finalize_port (sexp ctx, sexp port) { + if (sexp_port_openp(port)) { + sexp_port_openp(port) = 0; + if (sexp_port_stream(port) && ! sexp_port_no_closep(port)) + fclose(sexp_port_stream(port)); +#if ! SEXP_USE_STRING_STREAMS + if (sexp_port_buf(port) && sexp_oportp(port)) + free(sexp_port_buf(port)); +#endif + } return SEXP_VOID; } + +#if SEXP_USE_AUTOCLOSE_PORTS #define SEXP_FINALIZE_PORT sexp_finalize_port #else #define SEXP_FINALIZE_PORT NULL @@ -1032,6 +1039,7 @@ sexp sexp_make_input_port (sexp ctx, FILE* in, sexp name) { sexp_port_line(p) = 1; sexp_port_buf(p) = NULL; sexp_port_openp(p) = 1; + sexp_port_no_closep(p) = 0; sexp_port_sourcep(p) = 1; sexp_port_cookie(p) = SEXP_VOID; return p;