Skip to content

Commit 42bfad9

Browse files
committed
ports/unix: Add full uos.dupterm support.
1 parent cae77da commit 42bfad9

File tree

3 files changed

+87
-39
lines changed

3 files changed

+87
-39
lines changed

ports/unix/main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
6464

6565
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
6666
(void)env;
67+
#if MICROPY_PY_OS_DUPTERM
68+
mp_uos_dupterm_tx_strn(str, len);
69+
#else
6770
ssize_t ret;
6871
MP_HAL_RETRY_SYSCALL(ret, write(STDERR_FILENO, str, len), {});
69-
mp_uos_dupterm_tx_strn(str, len);
72+
#endif
7073
}
7174

7275
const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
@@ -535,6 +538,10 @@ MP_NOINLINE int main_(int argc, char **argv) {
535538
}
536539
#endif
537540

541+
#if MICROPY_PY_OS_DUPTERM
542+
init_dupterm_stdio();
543+
#endif
544+
538545
// Here is some example code to create a class and instance of that class.
539546
// First is the Python, then the C code.
540547
//

ports/unix/mphalport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,7 @@ enum {
103103

104104
void mp_hal_get_mac(int idx, uint8_t buf[6]);
105105
#endif
106+
107+
#if MICROPY_PY_OS_DUPTERM
108+
void init_dupterm_stdio();
109+
#endif

ports/unix/unix_mphal.c

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "py/mphal.h"
3434
#include "py/mpthread.h"
3535
#include "py/runtime.h"
36+
#include "py/stream.h"
37+
#include "py/mperrno.h"
3638
#include "extmod/misc.h"
3739

3840
#ifndef _WIN32
@@ -64,8 +66,11 @@ STATIC void sighandler(int signum) {
6466
}
6567
#endif
6668

69+
int mp_interrupt_char = -1;
70+
6771
void mp_hal_set_interrupt_char(char c) {
6872
// configure terminal settings to (not) let ctrl-C through
73+
mp_interrupt_char = c;
6974
if (c == CHAR_CTRL_C) {
7075
#ifndef _WIN32
7176
// enable signal handler
@@ -114,57 +119,85 @@ void mp_hal_stdio_mode_orig(void) {
114119
#endif
115120

116121
#if MICROPY_PY_OS_DUPTERM
117-
static int call_dupterm_read(size_t idx) {
118-
nlr_buf_t nlr;
119-
if (nlr_push(&nlr) == 0) {
120-
mp_obj_t read_m[3];
121-
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m);
122-
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
123-
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
124-
if (res == mp_const_none) {
125-
return -2;
126-
}
127-
mp_buffer_info_t bufinfo;
128-
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
129-
if (bufinfo.len == 0) {
130-
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
131-
MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
132-
return -1;
133-
}
134-
nlr_pop();
135-
return *(byte *)bufinfo.buf;
136-
} else {
137-
// Temporarily disable dupterm to avoid infinite recursion
138-
mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]);
139-
MP_STATE_VM(dupterm_objs[idx]) = NULL;
140-
mp_printf(&mp_plat_print, "dupterm: ");
141-
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
142-
MP_STATE_VM(dupterm_objs[idx]) = save_term;
122+
STATIC mp_uint_t unix_stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
123+
ssize_t ret;
124+
MP_HAL_RETRY_SYSCALL(ret, read(STDIN_FILENO, (byte *)buf, size), {});
125+
if (ret == 0) {
126+
// return EAGAIN error to indicate non-blocking
127+
*errcode = MP_EAGAIN;
128+
return MP_STREAM_ERROR;
143129
}
130+
return ret;
131+
}
132+
133+
STATIC mp_uint_t unix_stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
134+
int ret;
135+
MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, (const byte *)buf, size), {});
136+
if (ret == 0) {
137+
// return EAGAIN error to indicate non-blocking
138+
*errcode = MP_EAGAIN;
139+
return MP_STREAM_ERROR;
140+
}
141+
return ret;
142+
}
143+
144+
STATIC mp_uint_t unix_stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
145+
*errcode = MP_EINVAL;
146+
return MP_STREAM_ERROR;
147+
}
144148

145-
return -1;
149+
STATIC mp_obj_t unix_stdio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
150+
151+
STATIC const mp_stream_p_t unix_stdio_stream_p = {
152+
.read = unix_stdio_read,
153+
.write = unix_stdio_write,
154+
.ioctl = unix_stdio_ioctl,
155+
};
156+
157+
STATIC const mp_rom_map_elem_t unix_stdio_locals_dict_table[] = {
158+
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
159+
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
160+
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
161+
{ MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)},
162+
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
163+
};
164+
STATIC MP_DEFINE_CONST_DICT(unix_stdio_locals_dict, unix_stdio_locals_dict_table);
165+
166+
const mp_obj_type_t unix_stdio_type = {
167+
{ &mp_type_type },
168+
.name = MP_QSTR_UNIX_STDIO,
169+
.make_new = unix_stdio_make_new,
170+
.protocol = &unix_stdio_stream_p,
171+
.locals_dict = (mp_obj_dict_t *)&unix_stdio_locals_dict,
172+
};
173+
174+
typedef struct _unix_stdio_obj_t {
175+
mp_obj_base_t base;
176+
} unix_stdio_obj_t;
177+
178+
STATIC const unix_stdio_obj_t unix_stdio_obj = {{&unix_stdio_type}};
179+
180+
STATIC mp_obj_t unix_stdio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
181+
mp_arg_check_num(n_args, n_kw, 0, 0, false);
182+
return MP_OBJ_FROM_PTR(&unix_stdio_obj);
183+
}
184+
185+
void init_dupterm_stdio() {
186+
MP_STATE_VM(dupterm_objs[0]) = MP_OBJ_FROM_PTR(&unix_stdio_obj);
146187
}
147188
#endif
148189

149190
int mp_hal_stdin_rx_chr(void) {
150191
#if MICROPY_PY_OS_DUPTERM
151-
// TODO only support dupterm one slot at the moment
152-
if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) {
153192
int c;
154193
do {
155-
c = call_dupterm_read(0);
194+
c = mp_uos_dupterm_rx_chr();
156195
} while (c == -2);
157-
if (c == -1) {
158-
goto main_term;
159-
}
160196
if (c == '\n') {
161197
c = '\r';
162198
}
163199
return c;
164-
}
165-
main_term:;
166-
#endif
167-
200+
#else
168201
unsigned char c;
169202
ssize_t ret;
170203
MP_HAL_RETRY_SYSCALL(ret, read(STDIN_FILENO, &c, 1), {});
@@ -174,12 +207,16 @@ main_term:;
174207
c = '\r';
175208
}
176209
return c;
210+
#endif
177211
}
178212

179213
void mp_hal_stdout_tx_strn(const char *str, size_t len) {
214+
#if MICROPY_PY_OS_DUPTERM
215+
mp_uos_dupterm_tx_strn(str, len);
216+
#else
180217
ssize_t ret;
181218
MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, str, len), {});
182-
mp_uos_dupterm_tx_strn(str, len);
219+
#endif
183220
}
184221

185222
// cooked is same as uncooked because the terminal does some postprocessing

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy