mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-08 13:37:35 +02:00
Finalizing stream/fd backed ports will properly flush them.
However, don't try to flush string/custom ports which could result in alloc during gc.
This commit is contained in:
parent
90ff32e3bd
commit
9da98bd68d
2 changed files with 26 additions and 23 deletions
|
@ -1254,6 +1254,7 @@ SEXP_API sexp sexp_push_op(sexp ctx, sexp* loc, sexp x);
|
||||||
#define sexp_write_string(x, s, p) (fputs(s, sexp_port_stream(p)))
|
#define sexp_write_string(x, s, p) (fputs(s, sexp_port_stream(p)))
|
||||||
#define sexp_write_string_n(x, s, n, p) (fwrite(s, 1, n, sexp_port_stream(p)))
|
#define sexp_write_string_n(x, s, n, p) (fwrite(s, 1, n, sexp_port_stream(p)))
|
||||||
#define sexp_flush(x, p) (fflush(sexp_port_stream(p)))
|
#define sexp_flush(x, p) (fflush(sexp_port_stream(p)))
|
||||||
|
#define sexp_flush_forced sexp_flush
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -1262,13 +1263,14 @@ SEXP_API sexp sexp_push_op(sexp ctx, sexp* loc, sexp x);
|
||||||
#define sexp_write_char(x, c, p) (sexp_port_buf(p) ? ((sexp_port_offset(p) < sexp_port_size(p)) ? ((((sexp_port_buf(p))[sexp_port_offset(p)++]) = (char)(c)), 0) : sexp_buffered_write_char(x, c, p)) : putc(c, sexp_port_stream(p)))
|
#define sexp_write_char(x, c, p) (sexp_port_buf(p) ? ((sexp_port_offset(p) < sexp_port_size(p)) ? ((((sexp_port_buf(p))[sexp_port_offset(p)++]) = (char)(c)), 0) : sexp_buffered_write_char(x, c, p)) : putc(c, sexp_port_stream(p)))
|
||||||
#define sexp_write_string(x, s, p) (sexp_port_buf(p) ? sexp_buffered_write_string(x, s, p) : fputs(s, sexp_port_stream(p)))
|
#define sexp_write_string(x, s, p) (sexp_port_buf(p) ? sexp_buffered_write_string(x, s, p) : fputs(s, sexp_port_stream(p)))
|
||||||
#define sexp_write_string_n(x, s, n, p) (sexp_port_buf(p) ? sexp_buffered_write_string_n(x, s, n, p) : fwrite(s, 1, n, sexp_port_stream(p)))
|
#define sexp_write_string_n(x, s, n, p) (sexp_port_buf(p) ? sexp_buffered_write_string_n(x, s, n, p) : fwrite(s, 1, n, sexp_port_stream(p)))
|
||||||
#define sexp_flush(x, p) (sexp_port_buf(p) ? sexp_buffered_flush(x, p) : fflush(sexp_port_stream(p)))
|
#define sexp_flush(x, p) (sexp_port_buf(p) ? sexp_buffered_flush(x, p, 0) : fflush(sexp_port_stream(p)))
|
||||||
|
#define sexp_flush_forced(x, p) (sexp_port_buf(p) ? sexp_buffered_flush(x, p, 1) : fflush(sexp_port_stream(p)))
|
||||||
|
|
||||||
SEXP_API int sexp_buffered_read_char (sexp ctx, sexp p);
|
SEXP_API int sexp_buffered_read_char (sexp ctx, sexp p);
|
||||||
SEXP_API int sexp_buffered_write_char (sexp ctx, int c, sexp p);
|
SEXP_API int sexp_buffered_write_char (sexp ctx, int c, sexp p);
|
||||||
SEXP_API int sexp_buffered_write_string_n (sexp ctx, const char *str, sexp_uint_t len, sexp p);
|
SEXP_API int sexp_buffered_write_string_n (sexp ctx, const char *str, sexp_uint_t len, sexp p);
|
||||||
SEXP_API int sexp_buffered_write_string (sexp ctx, const char *str, sexp p);
|
SEXP_API int sexp_buffered_write_string (sexp ctx, const char *str, sexp p);
|
||||||
SEXP_API int sexp_buffered_flush (sexp ctx, sexp p);
|
SEXP_API int sexp_buffered_flush (sexp ctx, sexp p, int forcep);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
39
sexp.c
39
sexp.c
|
@ -127,6 +127,19 @@ sexp sexp_finalize_port (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
||||||
sexp res = SEXP_VOID;
|
sexp res = SEXP_VOID;
|
||||||
if (sexp_port_openp(port)) {
|
if (sexp_port_openp(port)) {
|
||||||
sexp_port_openp(port) = 0;
|
sexp_port_openp(port) = 0;
|
||||||
|
if (sexp_oportp(port)) sexp_flush_forced(ctx, port);
|
||||||
|
#ifndef PLAN9
|
||||||
|
if (sexp_filenop(sexp_port_fd(port))
|
||||||
|
&& sexp_fileno_openp(sexp_port_fd(port))) {
|
||||||
|
if (sexp_port_shutdownp(port)) {
|
||||||
|
/* shutdown the socket if requested */
|
||||||
|
if (sexp_iportp(port))
|
||||||
|
shutdown(sexp_port_fileno(port), sexp_oportp(port) ? SHUT_RDWR : SHUT_RD);
|
||||||
|
if (sexp_oportp(port))
|
||||||
|
shutdown(sexp_port_fileno(port), SHUT_WR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (sexp_port_stream(port) && ! sexp_port_no_closep(port)) {
|
if (sexp_port_stream(port) && ! sexp_port_no_closep(port)) {
|
||||||
/* close the stream */
|
/* close the stream */
|
||||||
fclose(sexp_port_stream(port));
|
fclose(sexp_port_stream(port));
|
||||||
|
@ -143,20 +156,6 @@ sexp sexp_finalize_port (sexp ctx, sexp self, sexp_sint_t n, sexp port) {
|
||||||
)
|
)
|
||||||
free(sexp_port_buf(port));
|
free(sexp_port_buf(port));
|
||||||
}
|
}
|
||||||
#ifndef PLAN9
|
|
||||||
if (sexp_filenop(sexp_port_fd(port))
|
|
||||||
&& sexp_fileno_openp(sexp_port_fd(port))) {
|
|
||||||
if (sexp_oportp(port)) res = sexp_flush_output(ctx, port);
|
|
||||||
if (sexp_exceptionp(res)) return res;
|
|
||||||
if (sexp_port_shutdownp(port)) {
|
|
||||||
/* shutdown the socket if requested */
|
|
||||||
if (sexp_iportp(port))
|
|
||||||
shutdown(sexp_port_fileno(port), sexp_oportp(port) ? SHUT_RDWR : SHUT_RD);
|
|
||||||
if (sexp_oportp(port))
|
|
||||||
shutdown(sexp_port_fileno(port), SHUT_WR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1428,7 @@ int sexp_buffered_read_char (sexp ctx, sexp p) {
|
||||||
int sexp_buffered_write_char (sexp ctx, int c, sexp p) {
|
int sexp_buffered_write_char (sexp ctx, int c, sexp p) {
|
||||||
int res;
|
int res;
|
||||||
if (sexp_port_offset(p)+1 >= sexp_port_size(p))
|
if (sexp_port_offset(p)+1 >= sexp_port_size(p))
|
||||||
if ((res = sexp_buffered_flush(ctx, p)))
|
if ((res = sexp_buffered_flush(ctx, p, 0)))
|
||||||
return res;
|
return res;
|
||||||
sexp_port_buf(p)[sexp_port_offset(p)++] = c;
|
sexp_port_buf(p)[sexp_port_offset(p)++] = c;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1442,7 +1441,7 @@ int sexp_buffered_write_string_n (sexp ctx, const char *str,
|
||||||
diff = sexp_port_size(p) - sexp_port_offset(p);
|
diff = sexp_port_size(p) - sexp_port_offset(p);
|
||||||
memcpy(sexp_port_buf(p)+sexp_port_offset(p), str, diff);
|
memcpy(sexp_port_buf(p)+sexp_port_offset(p), str, diff);
|
||||||
sexp_port_offset(p) = sexp_port_size(p);
|
sexp_port_offset(p) = sexp_port_size(p);
|
||||||
if ((res = sexp_buffered_flush(ctx, p)))
|
if ((res = sexp_buffered_flush(ctx, p, 0)))
|
||||||
return written + diff;
|
return written + diff;
|
||||||
written += sexp_port_size(p);
|
written += sexp_port_size(p);
|
||||||
str += diff;
|
str += diff;
|
||||||
|
@ -1457,10 +1456,10 @@ int sexp_buffered_write_string (sexp ctx, const char *str, sexp p) {
|
||||||
return sexp_buffered_write_string_n(ctx, str, strlen(str), p);
|
return sexp_buffered_write_string_n(ctx, str, strlen(str), p);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sexp_buffered_flush (sexp ctx, sexp p) {
|
int sexp_buffered_flush (sexp ctx, sexp p, int forcep) {
|
||||||
long res = 0, off;
|
long res = 0, off;
|
||||||
sexp_gc_var1(tmp);
|
sexp_gc_var1(tmp);
|
||||||
if (! (sexp_oportp(p) && sexp_port_openp(p)))
|
if (!sexp_oportp(p) || (!forcep && !sexp_port_openp(p)))
|
||||||
return -1;
|
return -1;
|
||||||
off = sexp_port_offset(p);
|
off = sexp_port_offset(p);
|
||||||
if (sexp_port_stream(p)) {
|
if (sexp_port_stream(p)) {
|
||||||
|
@ -1478,6 +1477,8 @@ int sexp_buffered_flush (sexp ctx, sexp p) {
|
||||||
sexp_port_offset(p) = 0;
|
sexp_port_offset(p) = 0;
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
|
} else if (!sexp_port_openp(p)) {
|
||||||
|
return -1;
|
||||||
} else if (sexp_port_offset(p) > 0) {
|
} else if (sexp_port_offset(p) > 0) {
|
||||||
sexp_gc_preserve1(ctx, tmp);
|
sexp_gc_preserve1(ctx, tmp);
|
||||||
if (sexp_port_customp(p)) { /* custom port */
|
if (sexp_port_customp(p)) { /* custom port */
|
||||||
|
@ -2051,7 +2052,7 @@ int sexp_write_utf8_char (sexp ctx, int c, sexp out) {
|
||||||
sexp sexp_flush_output_op (sexp ctx, sexp self, sexp_sint_t n, sexp out) {
|
sexp sexp_flush_output_op (sexp ctx, sexp self, sexp_sint_t n, sexp out) {
|
||||||
int res;
|
int res;
|
||||||
sexp_assert_type(ctx, sexp_oportp, SEXP_OPORT, out);
|
sexp_assert_type(ctx, sexp_oportp, SEXP_OPORT, out);
|
||||||
res = sexp_flush(ctx, out);
|
res = sexp_flush_forced(ctx, out);
|
||||||
if (res == EOF) {
|
if (res == EOF) {
|
||||||
#if SEXP_USE_GREEN_THREADS
|
#if SEXP_USE_GREEN_THREADS
|
||||||
if (sexp_port_stream(out) && ferror(sexp_port_stream(out)) && (errno == EAGAIN))
|
if (sexp_port_stream(out) && ferror(sexp_port_stream(out)) && (errno == EAGAIN))
|
||||||
|
|
Loading…
Add table
Reference in a new issue