From 2c1620ce1fe3bb2d011ccaca701191927f1d49d6 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 28 Dec 2015 01:12:59 +0200 Subject: [PATCH] unix: Implement uos.dupterm(). Conditional on MICROPY_PY_OS_DUPTERM. --- unix/file.c | 7 +++++++ unix/main.c | 1 + unix/modos.c | 23 +++++++++++++++++++++++ unix/mpconfigport.h | 14 ++++++++++++++ unix/qstrdefsport.h | 3 +++ unix/unix_mphal.c | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+) diff --git a/unix/file.c b/unix/file.c index 448cd50edc..7f113d6712 100644 --- a/unix/file.c +++ b/unix/file.c @@ -35,6 +35,7 @@ #include "py/runtime.h" #include "py/stream.h" #include "py/builtin.h" +#include "py/mphal.h" #if MICROPY_PY_IO @@ -80,6 +81,12 @@ STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); + #if MICROPY_PY_OS_DUPTERM + if (o->fd <= STDERR_FILENO) { + mp_hal_stdout_tx_strn(buf, size); + return size; + } + #endif mp_int_t r = write(o->fd, buf, size); if (r == -1) { *errcode = errno; diff --git a/unix/main.c b/unix/main.c index e7fce873b2..c305c37283 100644 --- a/unix/main.c +++ b/unix/main.c @@ -61,6 +61,7 @@ long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t dummy = write(STDERR_FILENO, str, len); + mp_hal_dupterm_tx_strn(str, len); (void)dummy; } diff --git a/unix/modos.c b/unix/modos.c index 26ecdd5b13..f2e83a1643 100644 --- a/unix/modos.c +++ b/unix/modos.c @@ -215,6 +215,26 @@ STATIC mp_obj_t mod_os_errno(mp_uint_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj, 0, 1, mod_os_errno); +#if MICROPY_PY_OS_DUPTERM +STATIC mp_obj_t mod_os_dupterm(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) { + return mp_const_none; + } else { + return MP_STATE_PORT(term_obj); + } + } else { + if (args[0] == mp_const_none) { + MP_STATE_PORT(term_obj) = NULL; + } else { + MP_STATE_PORT(term_obj) = args[0]; + } + return mp_const_none; + } +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj, 0, 1, mod_os_dupterm); +#endif + STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, @@ -227,6 +247,9 @@ STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, + #if MICROPY_PY_OS_DUPTERM + { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mod_os_dupterm_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index a74345817d..2061b48950 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -210,8 +210,12 @@ void mp_unix_mark_exec(void); #define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size) #define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size) +#if MICROPY_PY_OS_DUPTERM +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) +#else #include #define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) +#endif #ifdef __linux__ // Can access physical memory using /dev/mem @@ -239,9 +243,19 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; #define MP_STATE_PORT MP_STATE_VM +#if MICROPY_PY_OS_DUPTERM +#define ROOT_POINTERS_1 mp_obj_t term_obj +#include +void mp_hal_dupterm_tx_strn(const char *str, size_t len); +#else +#define ROOT_POINTERS_1 +#define mp_hal_dupterm_tx_strn(s, l) +#endif + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[50]; \ mp_obj_t keyboard_interrupt_obj; \ + ROOT_POINTERS_1; \ void *mmap_region_head; \ // We need to provide a declaration/definition of alloca() diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index d761c0f541..167a2be28f 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -45,6 +45,9 @@ Q(getenv) Q(mkdir) Q(ilistdir) Q(errno) +#if MICROPY_PY_OS_DUPTERM +Q(dupterm) +#endif Q(uselect) Q(poll) diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c index 8d3321ef66..16e80b7ef8 100644 --- a/unix/unix_mphal.c +++ b/unix/unix_mphal.c @@ -31,6 +31,7 @@ #include "py/mpstate.h" #include "py/mphal.h" +#include "py/runtime.h" #ifndef _WIN32 #include @@ -106,8 +107,40 @@ void mp_hal_stdio_mode_orig(void) { #endif +#if MICROPY_PY_OS_DUPTERM +void mp_hal_dupterm_tx_strn(const char *str, size_t len) { + if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) { + mp_obj_t write_m[3]; + mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m); + write_m[2] = mp_obj_new_bytearray_by_ref(len, (char*)str); + mp_call_method_n_kw(1, 0, write_m); + } +} +#endif + int mp_hal_stdin_rx_chr(void) { unsigned char c; + #if MICROPY_PY_OS_DUPTERM + while (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) { + mp_obj_t read_m[3]; + mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); + read_m[2] = MP_OBJ_NEW_SMALL_INT(1); + mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); + if (res == mp_const_none) { + break; + } + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len == 0) { + break; + } + c = *(byte*)bufinfo.buf; + if (c == '\n') { + c = '\r'; + } + return c; + } + #endif int ret = read(0, &c, 1); if (ret == 0) { c = 4; // EOF, ctrl-D @@ -119,6 +152,7 @@ int mp_hal_stdin_rx_chr(void) { void mp_hal_stdout_tx_strn(const char *str, size_t len) { int ret = write(1, str, len); + mp_hal_dupterm_tx_strn(str, len); (void)ret; // to suppress compiler warning }