|
20 | 20 | #if defined(OS_MACOS) |
21 | 21 | #include <crt_externs.h> |
22 | 22 | #else |
23 | | -extern char** environ; |
| 23 | +extern "C" char** environ; |
| 24 | +#endif |
| 25 | + |
| 26 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 27 | +#include <sys/ioctl.h> |
| 28 | +#include <termios.h> |
| 29 | +#include <unistd.h> |
24 | 30 | #endif |
25 | 31 |
|
26 | 32 | #include "vm/assert.h" |
@@ -274,6 +280,11 @@ const bool kFailure = false; |
274 | 280 | V(355, Pipe_write) \ |
275 | 281 | V(356, Pipe_close) \ |
276 | 282 | V(357, Process_environment) \ |
| 283 | + V(500, Term_start) \ |
| 284 | + V(501, Term_stop) \ |
| 285 | + V(502, Term_read) \ |
| 286 | + V(503, Term_write) \ |
| 287 | + V(504, Term_size) \ |
277 | 288 | V(509, print) \ |
278 | 289 | V(510, readFileAsBytes) \ |
279 | 290 | V(511, writeBytesToFile) |
@@ -4007,6 +4018,95 @@ DEFINE_PRIMITIVE(Object_yourself) { |
4007 | 4018 | return kSuccess; |
4008 | 4019 | } |
4009 | 4020 |
|
| 4021 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4022 | +static struct termios original_term; |
| 4023 | +#endif |
| 4024 | + |
| 4025 | +DEFINE_PRIMITIVE(Term_start) { |
| 4026 | + ASSERT(num_args == 0); |
| 4027 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4028 | + intptr_t status = tcgetattr(STDIN_FILENO, &original_term); |
| 4029 | + if (status == 0) { |
| 4030 | + struct termios term; |
| 4031 | + status = tcgetattr(STDIN_FILENO, &term); |
| 4032 | + if (status == 0) { |
| 4033 | + term.c_iflag &= ~(IXON|IXOFF|ICRNL); |
| 4034 | + term.c_oflag &= ~(OPOST); |
| 4035 | + term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); |
| 4036 | + status = tcsetattr(STDIN_FILENO, TCSANOW, &term); |
| 4037 | + } |
| 4038 | + } |
| 4039 | + RETURN_SMI(status); |
| 4040 | +#else |
| 4041 | + return kFailure; |
| 4042 | +#endif |
| 4043 | +} |
| 4044 | + |
| 4045 | +DEFINE_PRIMITIVE(Term_stop) { |
| 4046 | + ASSERT(num_args == 0); |
| 4047 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4048 | + intptr_t status = tcsetattr(STDIN_FILENO, TCSANOW, &original_term); |
| 4049 | + RETURN_SMI(status); |
| 4050 | +#else |
| 4051 | + return kFailure; |
| 4052 | +#endif |
| 4053 | +} |
| 4054 | + |
| 4055 | +DEFINE_PRIMITIVE(Term_size) { |
| 4056 | + ASSERT(num_args == 0); |
| 4057 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4058 | + struct winsize w; |
| 4059 | + w.ws_col = 0; |
| 4060 | + w.ws_row = 0; |
| 4061 | + intptr_t status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); |
| 4062 | + if (status != 0) { |
| 4063 | + RETURN_SMI(status); |
| 4064 | + } |
| 4065 | + Array result = H->AllocateArray(2); |
| 4066 | + result.set_element(0, SmallInteger::New(w.ws_row)); |
| 4067 | + result.set_element(1, SmallInteger::New(w.ws_col)); |
| 4068 | + RETURN(result); |
| 4069 | +#else |
| 4070 | + return kFailure; |
| 4071 | +#endif |
| 4072 | +} |
| 4073 | + |
| 4074 | +DEFINE_PRIMITIVE(Term_write) { |
| 4075 | + ASSERT(num_args == 1); |
| 4076 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4077 | + Bytes buffer = static_cast<Bytes>(I->Stack(0)); |
| 4078 | + if (!buffer->IsBytes()) return kFailure; |
| 4079 | + |
| 4080 | + size_t length = buffer->Size(); |
| 4081 | + size_t start = 0; |
| 4082 | + while (start != length) { |
| 4083 | + size_t written = write(STDOUT_FILENO, |
| 4084 | + buffer->element_addr(start), |
| 4085 | + length - start); |
| 4086 | + if (written == 0) { |
| 4087 | + FATAL("Failed to write"); |
| 4088 | + } |
| 4089 | + start += written; |
| 4090 | + } |
| 4091 | + RETURN_SELF(); |
| 4092 | +#else |
| 4093 | + return kFailure; |
| 4094 | +#endif |
| 4095 | +} |
| 4096 | + |
| 4097 | +DEFINE_PRIMITIVE(Term_read) { |
| 4098 | + ASSERT(num_args == 0); |
| 4099 | +#if defined(OS_MACOS) || defined(OS_LINUX) |
| 4100 | + uint8_t byte; |
| 4101 | + if (read(STDIN_FILENO, &byte, 1) <= 0) { |
| 4102 | + FATAL("Failed to read"); |
| 4103 | + } |
| 4104 | + RETURN_SMI(static_cast<intptr_t>(byte)); |
| 4105 | +#else |
| 4106 | + return kFailure; |
| 4107 | +#endif |
| 4108 | +} |
| 4109 | + |
4010 | 4110 | PrimitiveFunction* Primitives::primitive_table_[kNumPrimitives] = {}; |
4011 | 4111 |
|
4012 | 4112 | void Primitives::Startup() { |
|
0 commit comments