/// Internal function used by input_common_readch to read one byte from fd 0. This function should /// only be called by input_common_readch(). static char_event_t readb() { // do_loop must be set on every path through the loop; leaving it uninitialized allows the // static analyzer to assist in catching mistakes. unsigned char arr[1]; bool do_loop; do { // Flush callbacks. input_flush_callbacks(); fd_set fdset; int fd_max = 0; int ioport = iothread_port(); int res; FD_ZERO(&fdset); FD_SET(0, &fdset); if (ioport > 0) { FD_SET(ioport, &fdset); fd_max = std::max(fd_max, ioport); } // Get our uvar notifier. universal_notifier_t ¬ifier = universal_notifier_t::default_notifier(); // Get the notification fd (possibly none). int notifier_fd = notifier.notification_fd(); if (notifier_fd > 0) { FD_SET(notifier_fd, &fdset); fd_max = std::max(fd_max, notifier_fd); } // Get its suggested delay (possibly none). struct timeval tv = {}; const unsigned long usecs_delay = notifier.usec_delay_between_polls(); if (usecs_delay > 0) { unsigned long usecs_per_sec = 1000000; tv.tv_sec = (int)(usecs_delay / usecs_per_sec); tv.tv_usec = (int)(usecs_delay % usecs_per_sec); } res = select(fd_max + 1, &fdset, 0, 0, usecs_delay > 0 ? &tv : NULL); if (res == -1) { if (errno == EINTR || errno == EAGAIN) { if (interrupt_handler) { if (auto interrupt_evt = interrupt_handler()) { return *interrupt_evt; } else if (auto mc = lookahead_pop_evt()) { return *mc; } } do_loop = true; } else { // The terminal has been closed. return char_event_type_t::eof; } } else { // Assume we loop unless we see a character in stdin. do_loop = true; // Check to see if we want a universal variable barrier. bool barrier_from_poll = notifier.poll(); bool barrier_from_readability = false; if (notifier_fd > 0 && FD_ISSET(notifier_fd, &fdset)) { barrier_from_readability = notifier.notification_fd_became_readable(notifier_fd); } if (barrier_from_poll || barrier_from_readability) { env_universal_barrier(); } if (ioport > 0 && FD_ISSET(ioport, &fdset)) { iothread_service_completion(); if (auto mc = lookahead_pop_evt()) { return *mc; } } if (FD_ISSET(STDIN_FILENO, &fdset)) { if (read_blocked(0, arr, 1) != 1) { // The teminal has been closed. return char_event_type_t::eof; } // We read from stdin, so don't loop. do_loop = false; } } } while (do_loop); return arr[0]; }
/** Internal function used by input_common_readch to read one byte from fd 0. This function should only be called by input_common_readch(). */ static wint_t readb() { /* do_loop must be set on every path through the loop; leaving it uninitialized allows the static analyzer to assist in catching mistakes. */ unsigned char arr[1]; bool do_loop; do { /* Flush callbacks */ input_flush_callbacks(); fd_set fdset; int fd_max = 0; int ioport = iothread_port(); int res; FD_ZERO(&fdset); FD_SET(0, &fdset); if (ioport > 0) { FD_SET(ioport, &fdset); fd_max = maxi(fd_max, ioport); } /* Get our uvar notifier */ universal_notifier_t ¬ifier = universal_notifier_t::default_notifier(); /* Get the notification fd (possibly none) */ int notifier_fd = notifier.notification_fd(); if (notifier_fd > 0) { FD_SET(notifier_fd, &fdset); fd_max = maxi(fd_max, notifier_fd); } /* Get its suggested delay (possibly none) */ struct timeval tv = {}; const unsigned long usecs_delay = notifier.usec_delay_between_polls(); if (usecs_delay > 0) { unsigned long usecs_per_sec = 1000000; tv.tv_sec = (int)(usecs_delay / usecs_per_sec); tv.tv_usec = (int)(usecs_delay % usecs_per_sec); } res = select(fd_max + 1, &fdset, 0, 0, usecs_delay > 0 ? &tv : NULL); if (res==-1) { switch (errno) { case EINTR: case EAGAIN: { if (interrupt_handler) { int res = interrupt_handler(); if (res) { return res; } if (has_lookahead()) { return lookahead_pop(); } } do_loop = true; break; } default: { /* The terminal has been closed. Save and exit. */ return R_EOF; } } } else { /* Assume we loop unless we see a character in stdin */ do_loop = true; /* Check to see if we want a universal variable barrier */ bool barrier_from_poll = notifier.poll(); bool barrier_from_readability = false; if (notifier_fd > 0 && FD_ISSET(notifier_fd, &fdset)) { barrier_from_readability = notifier.notification_fd_became_readable(notifier_fd); } if (barrier_from_poll || barrier_from_readability) { env_universal_barrier(); } if (ioport > 0 && FD_ISSET(ioport, &fdset)) { iothread_service_completion(); if (has_lookahead()) { return lookahead_pop(); } } if (FD_ISSET(STDIN_FILENO, &fdset)) { if (read_blocked(0, arr, 1) != 1) { /* The teminal has been closed. Save and exit. */ return R_EOF; } /* We read from stdin, so don't loop */ do_loop = false; } } } while (do_loop); return arr[0]; }