mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
#ifndef MT_TERMINAL_SUPPORT_H
|
|
2
|
+
#define MT_TERMINAL_SUPPORT_H
|
|
3
|
+
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
#if defined(_WIN32)
|
|
11
|
+
#include <errno.h>
|
|
12
|
+
#include <io.h>
|
|
13
|
+
#include <windows.h>
|
|
14
|
+
#else
|
|
15
|
+
#include <errno.h>
|
|
16
|
+
#include <poll.h>
|
|
17
|
+
#include <sys/ioctl.h>
|
|
18
|
+
#include <termios.h>
|
|
19
|
+
#include <unistd.h>
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
typedef struct mt_terminal_size {
|
|
23
|
+
int width;
|
|
24
|
+
int height;
|
|
25
|
+
} mt_terminal_size;
|
|
26
|
+
|
|
27
|
+
typedef struct mt_terminal_error {
|
|
28
|
+
int code;
|
|
29
|
+
char* message_data;
|
|
30
|
+
uintptr_t message_len;
|
|
31
|
+
} mt_terminal_error;
|
|
32
|
+
|
|
33
|
+
static inline void mt_terminal_reset_error(mt_terminal_error* error) {
|
|
34
|
+
if (error == NULL) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
error->code = 0;
|
|
39
|
+
error->message_data = NULL;
|
|
40
|
+
error->message_len = 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static inline int mt_terminal_set_message(mt_terminal_error* error, int code, const char* prefix, const char* detail) {
|
|
44
|
+
if (error == NULL) {
|
|
45
|
+
return code == 0 ? -1 : code;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
|
|
49
|
+
size_t detail_len = detail == NULL ? 0 : strlen(detail);
|
|
50
|
+
size_t separator_len = prefix_len != 0 && detail_len != 0 ? 2 : 0;
|
|
51
|
+
size_t total_len = prefix_len + separator_len + detail_len;
|
|
52
|
+
|
|
53
|
+
char* message = NULL;
|
|
54
|
+
if (total_len != 0) {
|
|
55
|
+
message = (char*) malloc(total_len);
|
|
56
|
+
if (message != NULL) {
|
|
57
|
+
size_t offset = 0;
|
|
58
|
+
if (prefix_len != 0) {
|
|
59
|
+
memcpy(message + offset, prefix, prefix_len);
|
|
60
|
+
offset += prefix_len;
|
|
61
|
+
}
|
|
62
|
+
if (separator_len != 0) {
|
|
63
|
+
memcpy(message + offset, ": ", separator_len);
|
|
64
|
+
offset += separator_len;
|
|
65
|
+
}
|
|
66
|
+
if (detail_len != 0) {
|
|
67
|
+
memcpy(message + offset, detail, detail_len);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
error->code = code;
|
|
73
|
+
error->message_data = message;
|
|
74
|
+
error->message_len = (uintptr_t) total_len;
|
|
75
|
+
return code == 0 ? -1 : code;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static inline int mt_terminal_set_errno_error(mt_terminal_error* error, int code, const char* prefix) {
|
|
79
|
+
if (code == 0) {
|
|
80
|
+
code = errno == 0 ? EIO : errno;
|
|
81
|
+
}
|
|
82
|
+
return mt_terminal_set_message(error, code, prefix, strerror(code));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#if defined(_WIN32)
|
|
86
|
+
static inline int mt_terminal_set_windows_error(mt_terminal_error* error, DWORD code, const char* prefix) {
|
|
87
|
+
char buffer[256];
|
|
88
|
+
DWORD written = FormatMessageA(
|
|
89
|
+
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
90
|
+
NULL,
|
|
91
|
+
code,
|
|
92
|
+
0,
|
|
93
|
+
buffer,
|
|
94
|
+
(DWORD) sizeof(buffer),
|
|
95
|
+
NULL);
|
|
96
|
+
if (written == 0) {
|
|
97
|
+
return mt_terminal_set_message(error, (int) code, prefix, "windows terminal error");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
while (written > 0 && (buffer[written - 1] == '\r' || buffer[written - 1] == '\n')) {
|
|
101
|
+
written -= 1;
|
|
102
|
+
}
|
|
103
|
+
buffer[written] = '\0';
|
|
104
|
+
return mt_terminal_set_message(error, (int) code, prefix, buffer);
|
|
105
|
+
}
|
|
106
|
+
#endif
|
|
107
|
+
|
|
108
|
+
static inline bool mt_terminal_stdin_is_tty(void) {
|
|
109
|
+
#if defined(_WIN32)
|
|
110
|
+
return _isatty(_fileno(stdin)) != 0;
|
|
111
|
+
#else
|
|
112
|
+
return isatty(STDIN_FILENO) != 0;
|
|
113
|
+
#endif
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static inline bool mt_terminal_stdout_is_tty(void) {
|
|
117
|
+
#if defined(_WIN32)
|
|
118
|
+
return _isatty(_fileno(stdout)) != 0;
|
|
119
|
+
#else
|
|
120
|
+
return isatty(STDOUT_FILENO) != 0;
|
|
121
|
+
#endif
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static inline bool mt_terminal_stderr_is_tty(void) {
|
|
125
|
+
#if defined(_WIN32)
|
|
126
|
+
return _isatty(_fileno(stderr)) != 0;
|
|
127
|
+
#else
|
|
128
|
+
return isatty(STDERR_FILENO) != 0;
|
|
129
|
+
#endif
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#if defined(_WIN32)
|
|
133
|
+
static DWORD mt_terminal_saved_input_mode = 0;
|
|
134
|
+
static DWORD mt_terminal_saved_output_mode = 0;
|
|
135
|
+
static bool mt_terminal_raw_mode_active = false;
|
|
136
|
+
#else
|
|
137
|
+
static struct termios mt_terminal_saved_mode;
|
|
138
|
+
static bool mt_terminal_raw_mode_active = false;
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
static inline int mt_terminal_get_size(mt_terminal_size* result, mt_terminal_error* error) {
|
|
142
|
+
mt_terminal_reset_error(error);
|
|
143
|
+
if (result != NULL) {
|
|
144
|
+
result->width = 0;
|
|
145
|
+
result->height = 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#if defined(_WIN32)
|
|
149
|
+
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
150
|
+
if (output == INVALID_HANDLE_VALUE) {
|
|
151
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal size query failed");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
CONSOLE_SCREEN_BUFFER_INFO info;
|
|
155
|
+
if (!GetConsoleScreenBufferInfo(output, &info)) {
|
|
156
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal size query failed");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (result != NULL) {
|
|
160
|
+
result->width = (int) (info.srWindow.Right - info.srWindow.Left + 1);
|
|
161
|
+
result->height = (int) (info.srWindow.Bottom - info.srWindow.Top + 1);
|
|
162
|
+
}
|
|
163
|
+
return 0;
|
|
164
|
+
#else
|
|
165
|
+
if (!mt_terminal_stdout_is_tty()) {
|
|
166
|
+
return mt_terminal_set_message(error, ENOTTY, "terminal size query failed", "stdout is not a tty");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
struct winsize window;
|
|
170
|
+
memset(&window, 0, sizeof(window));
|
|
171
|
+
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window) != 0) {
|
|
172
|
+
return mt_terminal_set_errno_error(error, errno, "terminal size query failed");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (result != NULL) {
|
|
176
|
+
result->width = (int) window.ws_col;
|
|
177
|
+
result->height = (int) window.ws_row;
|
|
178
|
+
}
|
|
179
|
+
return 0;
|
|
180
|
+
#endif
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static inline int mt_terminal_enter_raw_mode(mt_terminal_error* error) {
|
|
184
|
+
mt_terminal_reset_error(error);
|
|
185
|
+
if (mt_terminal_raw_mode_active) {
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#if defined(_WIN32)
|
|
190
|
+
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
|
|
191
|
+
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
192
|
+
if (input == INVALID_HANDLE_VALUE || output == INVALID_HANDLE_VALUE) {
|
|
193
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode failed");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
DWORD input_mode = 0;
|
|
197
|
+
DWORD output_mode = 0;
|
|
198
|
+
if (!GetConsoleMode(input, &input_mode)) {
|
|
199
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode failed");
|
|
200
|
+
}
|
|
201
|
+
if (!GetConsoleMode(output, &output_mode)) {
|
|
202
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode failed");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
DWORD raw_input_mode = input_mode;
|
|
206
|
+
raw_input_mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
|
207
|
+
raw_input_mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
|
208
|
+
if (!SetConsoleMode(input, raw_input_mode)) {
|
|
209
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode failed");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
DWORD ansi_output_mode = output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
213
|
+
if (!SetConsoleMode(output, ansi_output_mode)) {
|
|
214
|
+
SetConsoleMode(input, input_mode);
|
|
215
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode failed");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
mt_terminal_saved_input_mode = input_mode;
|
|
219
|
+
mt_terminal_saved_output_mode = output_mode;
|
|
220
|
+
mt_terminal_raw_mode_active = true;
|
|
221
|
+
return 0;
|
|
222
|
+
#else
|
|
223
|
+
if (!mt_terminal_stdin_is_tty()) {
|
|
224
|
+
return mt_terminal_set_message(error, ENOTTY, "terminal raw mode failed", "stdin is not a tty");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
struct termios raw;
|
|
228
|
+
if (tcgetattr(STDIN_FILENO, &mt_terminal_saved_mode) != 0) {
|
|
229
|
+
return mt_terminal_set_errno_error(error, errno, "terminal raw mode failed");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
raw = mt_terminal_saved_mode;
|
|
233
|
+
raw.c_iflag &= (tcflag_t) ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
|
234
|
+
raw.c_oflag &= (tcflag_t) ~(OPOST);
|
|
235
|
+
raw.c_cflag |= (tcflag_t) CS8;
|
|
236
|
+
raw.c_lflag &= (tcflag_t) ~(ECHO | ICANON | IEXTEN | ISIG);
|
|
237
|
+
raw.c_cc[VMIN] = 1;
|
|
238
|
+
raw.c_cc[VTIME] = 0;
|
|
239
|
+
|
|
240
|
+
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) != 0) {
|
|
241
|
+
return mt_terminal_set_errno_error(error, errno, "terminal raw mode failed");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
mt_terminal_raw_mode_active = true;
|
|
245
|
+
return 0;
|
|
246
|
+
#endif
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
static inline int mt_terminal_leave_raw_mode(mt_terminal_error* error) {
|
|
250
|
+
mt_terminal_reset_error(error);
|
|
251
|
+
if (!mt_terminal_raw_mode_active) {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#if defined(_WIN32)
|
|
256
|
+
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
|
|
257
|
+
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
258
|
+
if (input == INVALID_HANDLE_VALUE || output == INVALID_HANDLE_VALUE) {
|
|
259
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode restore failed");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (!SetConsoleMode(input, mt_terminal_saved_input_mode)) {
|
|
263
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode restore failed");
|
|
264
|
+
}
|
|
265
|
+
if (!SetConsoleMode(output, mt_terminal_saved_output_mode)) {
|
|
266
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal raw mode restore failed");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
mt_terminal_raw_mode_active = false;
|
|
270
|
+
return 0;
|
|
271
|
+
#else
|
|
272
|
+
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &mt_terminal_saved_mode) != 0) {
|
|
273
|
+
return mt_terminal_set_errno_error(error, errno, "terminal raw mode restore failed");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
mt_terminal_raw_mode_active = false;
|
|
277
|
+
return 0;
|
|
278
|
+
#endif
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
static inline int mt_terminal_write_stream(FILE* stream, const unsigned char* data, uintptr_t len, uintptr_t* out_written, mt_terminal_error* error) {
|
|
282
|
+
mt_terminal_reset_error(error);
|
|
283
|
+
if (out_written != NULL) {
|
|
284
|
+
*out_written = 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (len == 0) {
|
|
288
|
+
return 0;
|
|
289
|
+
}
|
|
290
|
+
if (stream == NULL || data == NULL) {
|
|
291
|
+
return mt_terminal_set_message(error, EINVAL, "terminal write failed", "missing output buffer");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if ((uintptr_t) ((size_t) len) != len) {
|
|
295
|
+
return mt_terminal_set_message(error, EOVERFLOW, "terminal write failed", "buffer too large");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
size_t written = fwrite(data, 1, (size_t) len, stream);
|
|
299
|
+
if (out_written != NULL) {
|
|
300
|
+
*out_written = (uintptr_t) written;
|
|
301
|
+
}
|
|
302
|
+
if (written != (size_t) len) {
|
|
303
|
+
int code = errno == 0 ? EIO : errno;
|
|
304
|
+
return mt_terminal_set_errno_error(error, code, "terminal write failed");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
static inline int mt_terminal_write_stdout(const unsigned char* data, uintptr_t len, uintptr_t* out_written, mt_terminal_error* error) {
|
|
311
|
+
return mt_terminal_write_stream(stdout, data, len, out_written, error);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
static inline int mt_terminal_write_stderr(const unsigned char* data, uintptr_t len, uintptr_t* out_written, mt_terminal_error* error) {
|
|
315
|
+
return mt_terminal_write_stream(stderr, data, len, out_written, error);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
static inline int mt_terminal_flush_stdout(mt_terminal_error* error) {
|
|
319
|
+
mt_terminal_reset_error(error);
|
|
320
|
+
if (fflush(stdout) != 0) {
|
|
321
|
+
return mt_terminal_set_errno_error(error, errno, "terminal flush failed");
|
|
322
|
+
}
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static inline int mt_terminal_flush_stderr(mt_terminal_error* error) {
|
|
327
|
+
mt_terminal_reset_error(error);
|
|
328
|
+
if (fflush(stderr) != 0) {
|
|
329
|
+
return mt_terminal_set_errno_error(error, errno, "terminal flush failed");
|
|
330
|
+
}
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
static inline int mt_terminal_read_stdin(unsigned char* buffer, uintptr_t capacity, int timeout_ms, uintptr_t* out_read, mt_terminal_error* error) {
|
|
335
|
+
mt_terminal_reset_error(error);
|
|
336
|
+
if (out_read != NULL) {
|
|
337
|
+
*out_read = 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (capacity == 0) {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
if (buffer == NULL) {
|
|
344
|
+
return mt_terminal_set_message(error, EINVAL, "terminal read failed", "missing input buffer");
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
#if defined(_WIN32)
|
|
348
|
+
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
|
|
349
|
+
if (input == INVALID_HANDLE_VALUE) {
|
|
350
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal read failed");
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
DWORD wait_ms = timeout_ms < 0 ? INFINITE : (DWORD) timeout_ms;
|
|
354
|
+
DWORD wait_result = WaitForSingleObject(input, wait_ms);
|
|
355
|
+
if (wait_result == WAIT_TIMEOUT) {
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
if (wait_result != WAIT_OBJECT_0) {
|
|
359
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal read failed");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
DWORD requested = capacity > (uintptr_t) UINT32_MAX ? UINT32_MAX : (DWORD) capacity;
|
|
363
|
+
DWORD read_count = 0;
|
|
364
|
+
if (!ReadFile(input, buffer, requested, &read_count, NULL)) {
|
|
365
|
+
return mt_terminal_set_windows_error(error, GetLastError(), "terminal read failed");
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (out_read != NULL) {
|
|
369
|
+
*out_read = (uintptr_t) read_count;
|
|
370
|
+
}
|
|
371
|
+
return 0;
|
|
372
|
+
#else
|
|
373
|
+
if (timeout_ms >= 0) {
|
|
374
|
+
struct pollfd descriptor;
|
|
375
|
+
descriptor.fd = STDIN_FILENO;
|
|
376
|
+
descriptor.events = POLLIN;
|
|
377
|
+
descriptor.revents = 0;
|
|
378
|
+
|
|
379
|
+
int poll_status;
|
|
380
|
+
do {
|
|
381
|
+
poll_status = poll(&descriptor, 1, timeout_ms);
|
|
382
|
+
} while (poll_status < 0 && errno == EINTR);
|
|
383
|
+
|
|
384
|
+
if (poll_status == 0) {
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
if (poll_status < 0) {
|
|
388
|
+
return mt_terminal_set_errno_error(error, errno, "terminal read failed");
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
ssize_t read_count;
|
|
393
|
+
do {
|
|
394
|
+
read_count = read(STDIN_FILENO, buffer, (size_t) capacity);
|
|
395
|
+
} while (read_count < 0 && errno == EINTR);
|
|
396
|
+
|
|
397
|
+
if (read_count < 0) {
|
|
398
|
+
return mt_terminal_set_errno_error(error, errno, "terminal read failed");
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (out_read != NULL) {
|
|
402
|
+
*out_read = (uintptr_t) read_count;
|
|
403
|
+
}
|
|
404
|
+
return 0;
|
|
405
|
+
#endif
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
#endif
|
data/std/c/time.mt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
external
|
|
2
|
+
|
|
3
|
+
include "time.h"
|
|
4
|
+
compiler_flag "-D_POSIX_C_SOURCE=200809L"
|
|
5
|
+
|
|
6
|
+
type time_t = ptr_int
|
|
7
|
+
type clockid_t = int
|
|
8
|
+
|
|
9
|
+
opaque tm = c"struct tm"
|
|
10
|
+
|
|
11
|
+
struct timespec = c"struct timespec":
|
|
12
|
+
tv_sec: ptr_int
|
|
13
|
+
tv_nsec: ptr_int
|
|
14
|
+
|
|
15
|
+
const CLOCK_REALTIME: clockid_t = 0
|
|
16
|
+
const CLOCK_MONOTONIC: clockid_t = 1
|
|
17
|
+
|
|
18
|
+
external function time(timer: ptr[time_t]?) -> time_t
|
|
19
|
+
external function localtime(timer: ptr[time_t]) -> ptr[tm]?
|
|
20
|
+
external function gmtime(timer: ptr[time_t]) -> ptr[tm]?
|
|
21
|
+
external function mktime(value: ptr[tm]) -> time_t
|
|
22
|
+
external function difftime(left: time_t, right: time_t) -> double
|
|
23
|
+
external function strftime(s: ptr[char], maxsize: ptr_uint, format: cstr, tp: ptr[tm]) -> ptr_uint
|
|
24
|
+
external function clock_getres(clock_id: clockid_t, resolution: ptr[timespec]) -> int
|
|
25
|
+
external function clock_gettime(clock_id: clockid_t, value: ptr[timespec]) -> int
|
|
26
|
+
external function nanosleep(duration: const_ptr[timespec], remaining: ptr[timespec]?) -> int
|
data/std/c/tls.mt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
external
|
|
2
|
+
|
|
3
|
+
link "ssl"
|
|
4
|
+
link "crypto"
|
|
5
|
+
include "tls_support.h"
|
|
6
|
+
|
|
7
|
+
struct mt_tls_bytes = c"mt_tls_bytes":
|
|
8
|
+
data: ptr[ubyte]?
|
|
9
|
+
len: ptr_uint
|
|
10
|
+
|
|
11
|
+
struct mt_tls_error = c"mt_tls_error":
|
|
12
|
+
code: int
|
|
13
|
+
message_data: ptr[char]?
|
|
14
|
+
message_len: ptr_uint
|
|
15
|
+
|
|
16
|
+
opaque mt_tls_client = c"mt_tls_client"
|
|
17
|
+
|
|
18
|
+
external function mt_tls_client_create(host: cstr, fd: int, out out_client: ptr[mt_tls_client]?, out out_error: mt_tls_error) -> int
|
|
19
|
+
external function mt_tls_client_handshake(client: ptr[mt_tls_client], out out_error: mt_tls_error) -> int
|
|
20
|
+
external function mt_tls_client_write(client: ptr[mt_tls_client], data: ptr[ubyte]?, len: ptr_uint, out out_written: ptr_uint, out out_error: mt_tls_error) -> int
|
|
21
|
+
external function mt_tls_client_read(client: ptr[mt_tls_client], buffer: ptr[ubyte]?, capacity: ptr_uint, out out_read: ptr_uint, out out_error: mt_tls_error) -> int
|
|
22
|
+
external function mt_tls_client_shutdown(client: ptr[mt_tls_client], out out_error: mt_tls_error) -> int
|
|
23
|
+
external function mt_tls_client_release(client: ptr[mt_tls_client]?) -> void
|
|
24
|
+
external function mt_tls_exchange(host: cstr, port: int, request_data: ptr[ubyte]?, request_len: ptr_uint, out out_response: mt_tls_bytes, out out_error: mt_tls_error) -> int
|