extmod/uos_dupterm: Update uos.dupterm() and helper funcs to have index.

The uos.dupterm() signature and behaviour is updated to reflect the latest
enhancements in the docs.  It has minor backwards incompatibility in that
it no longer accepts zero arguments.

The dupterm_rx helper function is moved from esp8266 to extmod and
generalised to support multiple dupterm slots.

A port can specify multiple slots by defining the MICROPY_PY_OS_DUPTERM
config macro to an integer, being the number of slots it wants to have;
0 means to disable the dupterm feature altogether.

The unix and esp8266 ports are updated to work with the new interface and
are otherwise unchanged with respect to functionality.
This commit is contained in:
Damien George
2017-10-13 20:01:57 +11:00
parent e39fcda8eb
commit 37282f8fc1
8 changed files with 97 additions and 75 deletions

View File

@@ -35,8 +35,9 @@
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
int mp_uos_dupterm_rx_chr(void);
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
void mp_uos_deactivate(const char *msg, mp_obj_t exc);
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else
#define mp_uos_dupterm_tx_strn(s, l)
#endif

View File

@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
* Copyright (c) 2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,12 +32,13 @@
#include "py/objtuple.h"
#include "py/objarray.h"
#include "py/stream.h"
#include "lib/utils/interrupt_char.h"
#if MICROPY_PY_OS_DUPTERM
void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
mp_obj_t term = MP_STATE_PORT(term_obj);
MP_STATE_PORT(term_obj) = NULL;
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
mp_printf(&mp_plat_print, msg);
if (exc != MP_OBJ_NULL) {
mp_obj_print_exception(&mp_plat_print, exc);
@@ -44,48 +46,94 @@ void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
mp_stream_close(term);
}
int mp_uos_dupterm_rx_chr(void) {
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
continue;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t readinto_m[3];
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m);
readinto_m[2] = MP_STATE_VM(dupterm_arr_obj);
mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
if (res == mp_const_none) {
nlr_pop();
} else if (res == MP_OBJ_NEW_SMALL_INT(0)) {
mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
nlr_pop();
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
nlr_pop();
if (*(byte*)bufinfo.buf == mp_interrupt_char) {
// Signal keyboard interrupt to be raised as soon as the VM resumes
mp_keyboard_interrupt();
return -2;
}
return *(byte*)bufinfo.buf;
}
} else {
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
}
}
// No chars available
return -1;
}
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
continue;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t write_m[3];
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m);
mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m);
mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
void *org_items = arr->items;
arr->items = (void*)str;
arr->len = len;
write_m[2] = MP_STATE_PORT(dupterm_arr_obj);
write_m[2] = MP_STATE_VM(dupterm_arr_obj);
mp_call_method_n_kw(1, 0, write_m);
arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
arr->items = org_items;
arr->len = 1;
nlr_pop();
} else {
mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
}
}
}
STATIC mp_obj_t mp_uos_dupterm(size_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) = MP_OBJ_NULL;
} else {
MP_STATE_PORT(term_obj) = args[0];
if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
}
return mp_const_none;
mp_int_t idx = 0;
if (n_args == 2) {
idx = mp_obj_get_int(args[1]);
}
if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
mp_raise_ValueError("invalid dupterm index");
}
mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
if (previous_obj == MP_OBJ_NULL) {
previous_obj = mp_const_none;
}
if (args[0] == mp_const_none) {
MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
} else {
MP_STATE_VM(dupterm_objs[idx]) = args[0];
if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) {
MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
}
return previous_obj;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 0, 1, mp_uos_dupterm);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
#endif