diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 905fe358..33742a26 100755 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -32,6 +32,7 @@ extern "C" { #if SEXP_USE_GREEN_THREADS #include #include +#include #endif #define sexp_isalpha(x) (isalpha(x)) #define sexp_isxdigit(x) (isxdigit(x)) @@ -1352,6 +1353,7 @@ SEXP_API sexp sexp_read_complex_tail(sexp ctx, sexp in, sexp res); #endif SEXP_API sexp sexp_read_raw (sexp ctx, sexp in); SEXP_API sexp sexp_read_op (sexp ctx, sexp self, sexp_sint_t n, sexp in); +SEXP_API sexp sexp_char_ready_p (sexp ctx, sexp self, sexp_sint_t n, sexp in); SEXP_API sexp sexp_read_from_string (sexp ctx, const char *str, sexp_sint_t len); SEXP_API sexp sexp_read_error (sexp ctx, const char *msg, sexp ir, sexp port); SEXP_API sexp sexp_write_to_string (sexp ctx, sexp obj); diff --git a/lib/init-7.scm b/lib/init-7.scm index 2c9c315b..d2d50515 100644 --- a/lib/init-7.scm +++ b/lib/init-7.scm @@ -498,9 +498,6 @@ (define textual-port? port?) -(define (char-ready? . o) - (not (eof-object? (peek-char (if (pair? o) (car o) (current-input-port)))))) - (define (call-with-input-string str proc) (let* ((in (open-input-string str)) (res (proc in))) diff --git a/opcodes.c b/opcodes.c index 31934921..5af07da6 100644 --- a/opcodes.c +++ b/opcodes.c @@ -142,6 +142,7 @@ _OP(SEXP_OPC_IO, SEXP_OP_WRITE_STRING, 2, 3, SEXP_VOID, _I(SEXP_STRING), _I(SEXP _OP(SEXP_OPC_IO, SEXP_OP_READ_CHAR, 0, 3, _I(SEXP_CHAR), _I(SEXP_IPORT), SEXP_FALSE, SEXP_FALSE, 0, "read-char", (sexp)"current-input-port", NULL), _OP(SEXP_OPC_IO, SEXP_OP_PEEK_CHAR, 0, 3, _I(SEXP_CHAR), _I(SEXP_IPORT), SEXP_FALSE, SEXP_FALSE, 0, "peek-char", (sexp)"current-input-port", NULL), #endif +_FN1OPTP(_I(SEXP_BOOLEAN), _I(SEXP_IPORT), "char-ready?", (sexp)"current-input-port", sexp_char_ready_p), _FN1OPTP(_I(SEXP_OBJECT), _I(SEXP_IPORT), "read", (sexp)"current-input-port", sexp_read_op), _FN2OPTP(SEXP_VOID,_I(SEXP_OBJECT), _I(SEXP_OPORT), "write", (sexp)"current-output-port", sexp_write_op), _FN1OPTP(SEXP_VOID, _I(SEXP_OPORT), "flush-output", (sexp)"current-output-port", sexp_flush_output_op), diff --git a/sexp.c b/sexp.c index 18a8d6d7..7ac2b9c3 100644 --- a/sexp.c +++ b/sexp.c @@ -1732,6 +1732,44 @@ void sexp_maybe_unblock_port (sexp ctx, sexp port) { } #endif +#if SEXP_USE_GREEN_THREADS +static int sexp_fileno_ready_p (int fd) { + struct pollfd pfd; + if (fd < 0) return -1; + pfd.fd = fd; + pfd.events = POLLIN; + return poll(&pfd, 1, 0) == 1; +} + +static int sexp_stream_ready_p (FILE* in) { + int flags = fcntl(fileno(in), F_GETFL), res; + if (! (flags & O_NONBLOCK)) fcntl(fileno(in), F_SETFL, flags & O_NONBLOCK); + res = getc(in); + if (! (flags & O_NONBLOCK)) fcntl(fileno(in), F_SETFL, flags); + return (res == EOF) ? feof(in) : 1; +} +#endif + +sexp sexp_char_ready_p (sexp ctx, sexp self, sexp_sint_t n, sexp in) { + sexp_assert_type(ctx, sexp_iportp, SEXP_IPORT, in); + if (!sexp_port_openp(in)) + return SEXP_FALSE; +#if !SEXP_USE_STRING_STREAMS + if (sexp_port_buf(in)) + if (sexp_port_offset(in) < sexp_port_size(in) + || (!sexp_filenop(sexp_port_fd(in)) && !sexp_port_stream(in))) + return SEXP_TRUE; +#endif +#if SEXP_USE_GREEN_THREADS /* maybe not just when threads are enabled */ + if (sexp_filenop(sexp_port_fd(in))) + return sexp_make_boolean(sexp_fileno_ready_p(sexp_port_fileno(in))); + else if (sexp_port_stream(in)) + return sexp_make_boolean(sexp_stream_ready_p(sexp_port_stream(in))); +#endif + /* for custom ports and unthreaded compiles we just return true for now */ + return SEXP_TRUE; +} + #define NUMBUF_LEN 32 static struct {const char* name; char ch;} sexp_char_names[] = {