#include "forth_internal.h" #include #include static char getch() { char buf = 0; struct termios old = {0}; if (tcgetattr(0, &old) < 0) perror("tcsetattr()"); old.c_lflag &= ~ICANON; old.c_lflag &= ~ECHO; old.c_cc[VMIN] = 1; old.c_cc[VTIME] = 0; if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON"); if (read(0, &buf, 1) < 0) perror ("read()"); old.c_lflag |= ICANON; old.c_lflag |= ECHO; if (tcsetattr(0, TCSADRAIN, &old) < 0) perror ("tcsetattr ~ICANON"); return (buf); } static enum fh_error w_key(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; uint32_t a; a = getch(); TRY(ds_push(fh, a)); return FH_OK; } static inline bool iscrlf(char c) { return c == '\r' || c == '\n'; } static enum fh_error w_accept(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; uint32_t abuf; uint32_t count; TRY(ds_pop(fh, &count)); TRY(ds_pop(fh, &abuf)); char *s = fgets(&fh->heap[abuf], count, stdin); if (!s) { LOGE("Error reading stdin!"); count = 0; } else { count = strnlen(s, count); // remove the newline if(count > 0) { char *end = s + (count - 1); while (iscrlf(*end)) { end--; count--; } } } TRY(ds_push(fh, count)); return FH_OK; } const struct name_and_handler fh_builtins_stdin[] = { {"key", w_key, 0, 0}, {"accept", w_accept, 0, 0}, { /* end marker */ } };