Trying to build a forth runtime in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
forth/src/fh_builtins_stdin.c

77 lines
1.6 KiB

#include "forth_internal.h"
#include <unistd.h>
#include <termios.h>
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 */ }
};