summaryrefslogtreecommitdiff
path: root/ext/io/console
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-10-10 15:15:21 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-10-11 01:27:15 +0900
commitb59640e155a5c1d166aaae4b7ccab936597930fc (patch)
tree98e3f0c72bb7cabe20a0dc6e35e5d27ea747c2ec /ext/io/console
parentbfc1c7205d9592b5b5be3b351fbf7b9ca8c537b6 (diff)
[ruby/io-console] Fixed "Rework console to use `rb_io_wait`."
* Fixed backward compatibility. * Added missing `rb_scheduler_timeout` declaration. https://github.com/ruby/io-console/commit/813806079f
Diffstat (limited to 'ext/io/console')
-rw-r--r--ext/io/console/console.c80
-rw-r--r--ext/io/console/extconf.rb3
2 files changed, 53 insertions, 30 deletions
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 76253ee..50baf4f 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -1,4 +1,4 @@
-/* -*- c-file-style: "ruby" -*- */
+/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
/*
* console IO module
*/
@@ -80,6 +80,10 @@ static ID id_getc, id_console, id_close, id_min, id_time, id_intr;
static ID id_gets;
#endif
+#ifdef HAVE_RB_SCHEDULER_TIMEOUT
+extern VALUE rb_scheduler_timeout(struct timeval *timeout);
+#endif
+
#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv)
#ifndef HAVE_RB_F_SEND
@@ -510,47 +514,63 @@ console_getch(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr;
VALUE str;
wint_t c;
- int w, len;
+ int len;
char buf[8];
wint_t wbuf[2];
+# ifndef HAVE_RB_IO_WAIT
+ struct timeval *to = NULL, tv;
+# else
VALUE timeout = Qnil;
+# endif
GetOpenFile(io, fptr);
if (optp) {
- if (optp->vtime) {
- struct timeval tv;
- tv.tv_sec = optp->vtime / 10;
- tv.tv_usec = (optp->vtime % 10) * 100000;
- timeout = rb_scheduler_timeout(&tv);
- }
- if (optp->vmin != 1) {
- rb_warning("min option ignored");
- }
- if (optp->intr) {
- VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout));
- if (result == Qfalse) return Qnil;
- }
- else {
- rb_warning("vtime option ignored if intr flag is unset");
- }
+ if (optp->vtime) {
+# ifndef HAVE_RB_IO_WAIT
+ to = &tv;
+# else
+ struct timeval tv;
+# endif
+ tv.tv_sec = optp->vtime / 10;
+ tv.tv_usec = (optp->vtime % 10) * 100000;
+# ifdef HAVE_RB_IO_WAIT
+ timeout = rb_scheduler_timeout(&tv);
+# endif
+ }
+ if (optp->vmin != 1) {
+ rb_warning("min option ignored");
+ }
+ if (optp->intr) {
+# ifndef HAVE_RB_IO_WAIT
+ int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
+ if (w < 0) rb_eof_error();
+ if (!(w & RB_WAITFD_IN)) return Qnil;
+# else
+ VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout));
+ if (result == Qfalse) return Qnil;
+# endif
+ }
+ else {
+ rb_warning("vtime option ignored if intr flag is unset");
+ }
}
len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
switch (len) {
case 0:
- return Qnil;
+ return Qnil;
case 2:
- buf[0] = (char)wbuf[0];
- c = wbuf[1];
- len = 1;
- do {
- buf[len++] = (unsigned char)c;
- } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
- return rb_str_new(buf, len);
+ buf[0] = (char)wbuf[0];
+ c = wbuf[1];
+ len = 1;
+ do {
+ buf[len++] = (unsigned char)c;
+ } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
+ return rb_str_new(buf, len);
default:
- c = wbuf[0];
- len = rb_uv_to_utf8(buf, c);
- str = rb_utf8_str_new(buf, len);
- return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
+ c = wbuf[0];
+ len = rb_uv_to_utf8(buf, c);
+ str = rb_utf8_str_new(buf, len);
+ return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
}
#endif
}
diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb
index 3d7e75e..3efdd6e 100644
--- a/ext/io/console/extconf.rb
+++ b/ext/io/console/extconf.rb
@@ -24,6 +24,9 @@ when true
# rb_funcallv: 2.1.0
# RARRAY_CONST_PTR: 2.1.0
# rb_sym2str: 2.2.0
+ if have_func("rb_scheduler_timeout")
+ have_func("rb_io_wait")
+ end
$defs << "-D""ENABLE_IO_GETPASS=1"
create_makefile("io/console") {|conf|
conf << "\n""VK_HEADER = #{vk_header}\n"