py: Overhaul and simplify printf/pfenv mechanism.

Previous to this patch the printing mechanism was a bit of a tangled
mess.  This patch attempts to consolidate printing into one interface.

All (non-debug) printing now uses the mp_print* family of functions,
mainly mp_printf.  All these functions take an mp_print_t structure as
their first argument, and this structure defines the printing backend
through the "print_strn" function of said structure.

Printing from the uPy core can reach the platform-defined print code via
two paths: either through mp_sys_stdout_obj (defined pert port) in
conjunction with mp_stream_write; or through the mp_plat_print structure
which uses the MP_PLAT_PRINT_STRN macro to define how string are printed
on the platform.  The former is only used when MICROPY_PY_IO is defined.

With this new scheme printing is generally more efficient (less layers
to go through, less arguments to pass), and, given an mp_print_t*
structure, one can call mp_print_str for efficiency instead of
mp_printf("%s", ...).  Code size is also reduced by around 200 bytes on
Thumb2 archs.
This commit is contained in:
Damien George 2015-04-09 23:56:15 +01:00
parent 56beb01724
commit 7f9d1d6ab9
91 changed files with 671 additions and 716 deletions

View File

@ -6,7 +6,6 @@
#include "py/compile.h" #include "py/compile.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/repl.h" #include "py/repl.h"
#include "py/pfenv.h"
void do_str(const char *src) { void do_str(const char *src) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
@ -23,7 +22,7 @@ void do_str(const char *src) {
nlr_pop(); nlr_pop();
} else { } else {
// uncaught exception // uncaught exception
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
} }

View File

@ -37,9 +37,9 @@
#include "pybpin.h" #include "pybpin.h"
#include MICROPY_HAL_H #include MICROPY_HAL_H
STATIC void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_named_pins_obj_t *self = self_in; pin_named_pins_obj_t *self = self_in;
print(env, "<Pin.%s>", qstr_str(self->name)); mp_printf(print, "<Pin.%s>", qstr_str(self->name));
} }
const mp_obj_type_t pin_cpu_pins_obj_type = { const mp_obj_type_t pin_cpu_pins_obj_type = {

View File

@ -691,19 +691,19 @@ STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
return &wlan_obj; return &wlan_obj;
} }
STATIC void wlan_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void wlan_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
wlan_obj_t *self = self_in; wlan_obj_t *self = self_in;
print(env, "<WLAN, mode=%u", self->mode); mp_printf(print, "<WLAN, mode=%u", self->mode);
// only print the bssid if in station mode // only print the bssid if in station mode
if (self->mode != ROLE_AP && GET_STATUS_BIT(self->status, STATUS_BIT_CONNECTION)) { if (self->mode != ROLE_AP && GET_STATUS_BIT(self->status, STATUS_BIT_CONNECTION)) {
print(env, ", connected to: ssid=%s, bssid=%02x:%02x:%02x:%02x:%02x:%02x", self->ssid, mp_printf(print, ", connected to: ssid=%s, bssid=%02x:%02x:%02x:%02x:%02x:%02x", self->ssid,
self->bssid[0], self->bssid[1], self->bssid[2], self->bssid[3], self->bssid[4], self->bssid[5]); self->bssid[0], self->bssid[1], self->bssid[2], self->bssid[3], self->bssid[4], self->bssid[5]);
} }
else { else {
print(env, ", ssid=%s", self->ssid); mp_printf(print, ", ssid=%s", self->ssid);
} }
print(env, ", security=%u>", self->security); mp_printf(print, ", security=%u>", self->security);
} }
/// \method connect(ssid, security=OPEN, key=None, bssid=None) /// \method connect(ssid, security=OPEN, key=None, bssid=None)

View File

@ -100,9 +100,9 @@ STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS];
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings : adc object */ /* Micro Python bindings : adc object */
STATIC void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_obj_t *self = self_in; pyb_adc_obj_t *self = self_in;
print(env, "<ADC, channel=%u>", self->num); mp_printf(print, "<ADC, channel=%u>", self->num);
} }
/// \classmethod \constructor(channel) /// \classmethod \constructor(channel)

View File

@ -294,13 +294,13 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
return (mp_obj_t)self; return (mp_obj_t)self;
} }
STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in; pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) { if (self->baudrate > 0) {
print(env, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate); mp_printf(print, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
} }
else { else {
print(env, "<I2C0>"); mp_print_str(print, "<I2C0>");
} }
} }

View File

@ -429,14 +429,14 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
/// \method print() /// \method print()
/// Return a string describing the pin object. /// Return a string describing the pin object.
STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_obj_t *self = self_in; pin_obj_t *self = self_in;
uint32_t af = MAP_PinModeGet(self->pin_num); uint32_t af = MAP_PinModeGet(self->pin_num);
uint32_t type = pin_get_type(self); uint32_t type = pin_get_type(self);
uint32_t strength = pin_get_strenght(self); uint32_t strength = pin_get_strenght(self);
// pin name // pin name
print(env, "<Pin.cpu.%s, af=%u", qstr_str(self->name), af); mp_printf(print, "<Pin.cpu.%s, af=%u", qstr_str(self->name), af);
if (af == PIN_MODE_0) { if (af == PIN_MODE_0) {
// IO mode // IO mode
@ -447,7 +447,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
} else { } else {
mode_qst = MP_QSTR_OUT; mode_qst = MP_QSTR_OUT;
} }
print(env, ", mode=Pin.%s", qstr_str(mode_qst)); // safe because mode_qst has no formatting chars mp_printf(print, ", mode=Pin.%s", qstr_str(mode_qst));
} }
// pin type // pin type
@ -465,7 +465,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
} else { } else {
type_qst = MP_QSTR_OD_PD; type_qst = MP_QSTR_OD_PD;
} }
print(env, ", pull=Pin.%s", qstr_str(type_qst)); mp_printf(print, ", pull=Pin.%s", qstr_str(type_qst));
// Strength // Strength
qstr str_qst; qstr str_qst;
@ -476,7 +476,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
} else { } else {
str_qst = MP_QSTR_S6MA; str_qst = MP_QSTR_S6MA;
} }
print(env, ", strength=Pin.%s>", qstr_str(str_qst)); mp_printf(print, ", strength=Pin.%s>", qstr_str(str_qst));
} }
/// \classmethod \constructor(id, ...) /// \classmethod \constructor(id, ...)

View File

@ -163,15 +163,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
/******************************************************************************/ /******************************************************************************/
STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in; pyb_spi_obj_t *self = self_in;
if (self->baudrate > 0) { if (self->baudrate > 0) {
print(env, "<SPI0, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>", mp_printf(print, "<SPI0, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>",
self->baudrate, self->config, self->submode, (self->wlen * 8)); self->baudrate, self->config, self->submode, (self->wlen * 8));
} }
else { else {
print(env, "<SPI0>"); mp_print_str(print, "<SPI0>");
} }
} }

View File

@ -312,37 +312,37 @@ STATIC void uart_callback_disable (mp_obj_t self_in) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = self_in; pyb_uart_obj_t *self = self_in;
if (self->baudrate > 0) { if (self->baudrate > 0) {
print(env, "<UART%u, baudrate=%u, bits=", self->uart_id, self->baudrate); mp_printf(print, "<UART%u, baudrate=%u, bits=", self->uart_id, self->baudrate);
switch (self->config & UART_CONFIG_WLEN_MASK) { switch (self->config & UART_CONFIG_WLEN_MASK) {
case UART_CONFIG_WLEN_5: case UART_CONFIG_WLEN_5:
print(env, "5"); mp_print_str(print, "5");
break; break;
case UART_CONFIG_WLEN_6: case UART_CONFIG_WLEN_6:
print(env, "6"); mp_print_str(print, "6");
break; break;
case UART_CONFIG_WLEN_7: case UART_CONFIG_WLEN_7:
print(env, "7"); mp_print_str(print, "7");
break; break;
case UART_CONFIG_WLEN_8: case UART_CONFIG_WLEN_8:
print(env, "8"); mp_print_str(print, "8");
break; break;
default: default:
break; break;
} }
if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) { if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) {
print(env, ", parity=None"); mp_print_str(print, ", parity=None");
} else { } else {
print(env, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1); mp_printf(print, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1);
} }
print(env, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u>", mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u>",
(self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2, (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2,
self->timeout, self->timeout_char, self->read_buf_len); self->timeout, self->timeout_char, self->read_buf_len);
} }
else { else {
print(env, "<UART%u>", self->uart_id); mp_printf(print, "<UART%u>", self->uart_id);
} }
} }

View File

@ -146,6 +146,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t; typedef long mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)

View File

@ -32,7 +32,6 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/pfenv.h"
#include MICROPY_HAL_H #include MICROPY_HAL_H
#include "queue.h" #include "queue.h"
#include "user_interface.h" #include "user_interface.h"
@ -52,7 +51,7 @@ mp_obj_t call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
return mp_call_function_1(fun, arg); return mp_call_function_1(fun, arg);
} else { } else {
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
return (mp_obj_t)nlr.ret_val; return (mp_obj_t)nlr.ret_val;
} }
} }

View File

@ -65,11 +65,11 @@ STATIC const pyb_pin_obj_t pyb_pin_obj[] = {
{{&pyb_pin_type}, 15, 15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15}, {{&pyb_pin_type}, 15, 15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15},
}; };
STATIC void pyb_pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_pin_obj_t *self = self_in; pyb_pin_obj_t *self = self_in;
// pin name // pin name
print(env, "Pin(%u)", self->pin_id); mp_printf(print, "Pin(%u)", self->pin_id);
} }
// pin.init(mode, pull=Pin.PULL_NONE, af=-1) // pin.init(mode, pull=Pin.PULL_NONE, af=-1)

View File

@ -52,6 +52,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t; typedef long mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// extra built in names to add to the global namespace // extra built in names to add to the global namespace
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \ #define MICROPY_PORT_BUILTINS \

View File

@ -137,7 +137,7 @@ STATIC mp_obj_t uctypes_struct_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_u
return o; return o;
} }
STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_uctypes_struct_t *self = self_in; mp_obj_uctypes_struct_t *self = self_in;
const char *typen = "unk"; const char *typen = "unk";
@ -154,7 +154,7 @@ STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...),
} else { } else {
typen = "ERROR"; typen = "ERROR";
} }
print(env, "<struct %s %p>", typen, self->addr); mp_printf(print, "<struct %s %p>", typen, self->addr);
} }
// Get size of any type descriptor // Get size of any type descriptor

View File

@ -35,8 +35,9 @@
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
vstr_t vstr; vstr_t vstr;
vstr_init(&vstr, 8); mp_print_t print;
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, obj, PRINT_JSON); vstr_init_print(&vstr, 8, &print);
mp_obj_print_helper(&print, obj, PRINT_JSON);
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);

View File

@ -51,10 +51,10 @@ typedef struct _mp_obj_match_t {
} mp_obj_match_t; } mp_obj_match_t;
STATIC void match_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_match_t *self = self_in; mp_obj_match_t *self = self_in;
print(env, "<match num=%d>", self->num_matches); mp_printf(print, "<match num=%d>", self->num_matches);
} }
STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) { STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
@ -86,10 +86,10 @@ STATIC const mp_obj_type_t match_type = {
.locals_dict = (mp_obj_t)&match_locals_dict, .locals_dict = (mp_obj_t)&match_locals_dict,
}; };
STATIC void re_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_re_t *self = self_in; mp_obj_re_t *self = self_in;
print(env, "<re %p>", self); mp_printf(print, "<re %p>", self);
} }
STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {

View File

@ -6,7 +6,6 @@
#include "py/compile.h" #include "py/compile.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/repl.h" #include "py/repl.h"
#include "py/pfenv.h"
#include "py/gc.h" #include "py/gc.h"
#include "pyexec.h" #include "pyexec.h"
@ -26,7 +25,7 @@ void do_str(const char *src) {
nlr_pop(); nlr_pop();
} else { } else {
// uncaught exception // uncaught exception
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
} }

View File

@ -60,6 +60,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t; typedef long mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// extra built in names to add to the global namespace // extra built in names to add to the global namespace
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \ #define MICROPY_PORT_BUILTINS \

View File

@ -41,9 +41,9 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = {
#define NUM_LED MP_ARRAY_SIZE(pyb_led_obj) #define NUM_LED MP_ARRAY_SIZE(pyb_led_obj)
#define LED_ID(obj) ((obj) - &pyb_led_obj[0] + 1) #define LED_ID(obj) ((obj) - &pyb_led_obj[0] + 1)
void pyb_led_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void pyb_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in; pyb_led_obj_t *self = self_in;
print(env, "LED(%u)", LED_ID(self)); mp_printf(print, "LED(%u)", LED_ID(self));
} }
STATIC mp_obj_t pyb_led_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t pyb_led_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {

View File

@ -40,9 +40,9 @@ STATIC const pyb_switch_obj_t pyb_switch_obj[] = {
#define NUM_SWITCH MP_ARRAY_SIZE(pyb_switch_obj) #define NUM_SWITCH MP_ARRAY_SIZE(pyb_switch_obj)
#define SWITCH_ID(obj) ((obj) - &pyb_switch_obj[0] + 1) #define SWITCH_ID(obj) ((obj) - &pyb_switch_obj[0] + 1)
void pyb_switch_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_switch_obj_t *self = self_in; pyb_switch_obj_t *self = self_in;
print(env, "Switch(%u)", SWITCH_ID(self)); mp_printf(print, "Switch(%u)", SWITCH_ID(self));
} }
STATIC mp_obj_t pyb_switch_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t pyb_switch_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {

View File

@ -86,6 +86,9 @@ typedef void *machine_ptr_t; // must be pointer size
typedef const void *machine_const_ptr_t; // must be pointer size typedef const void *machine_const_ptr_t; // must be pointer size
typedef int mp_off_t; typedef int mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// extra builtin names to add to the global namespace // extra builtin names to add to the global namespace
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \ #define MICROPY_PORT_BUILTINS \

View File

@ -147,6 +147,8 @@ typedef struct _vstr_t {
void vstr_init(vstr_t *vstr, size_t alloc); void vstr_init(vstr_t *vstr, size_t alloc);
void vstr_init_len(vstr_t *vstr, size_t len); void vstr_init_len(vstr_t *vstr, size_t len);
void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf); void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf);
struct _mp_print_t;
void vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print);
void vstr_clear(vstr_t *vstr); void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void); vstr_t *vstr_new(void);
vstr_t *vstr_new_size(size_t alloc); vstr_t *vstr_new_size(size_t alloc);

View File

@ -35,7 +35,6 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/builtin.h" #include "py/builtin.h"
#include "py/stream.h" #include "py/stream.h"
#include "py/pfenv.h"
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
#include <math.h> #include <math.h>
@ -413,9 +412,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
stream_obj = file_elem->value; stream_obj = file_elem->value;
} }
pfenv_t pfenv; mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
pfenv.data = stream_obj;
pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
#endif #endif
for (mp_uint_t i = 0; i < n_args; i++) { for (mp_uint_t i = 0; i < n_args; i++) {
if (i > 0) { if (i > 0) {
@ -426,7 +423,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
#endif #endif
} }
#if MICROPY_PY_IO #if MICROPY_PY_IO
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[i], PRINT_STR); mp_obj_print_helper(&print, args[i], PRINT_STR);
#else #else
mp_obj_print(args[i], PRINT_STR); mp_obj_print(args[i], PRINT_STR);
#endif #endif
@ -443,10 +440,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
if (o != mp_const_none) { if (o != mp_const_none) {
#if MICROPY_PY_IO #if MICROPY_PY_IO
pfenv_t pfenv; mp_print_t print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write};
pfenv.data = &mp_sys_stdout_obj; mp_obj_print_helper(&print, o, PRINT_REPR);
pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, o, PRINT_REPR);
mp_stream_write(&mp_sys_stdout_obj, "\n", 1); mp_stream_write(&mp_sys_stdout_obj, "\n", 1);
#else #else
mp_obj_print(o, PRINT_REPR); mp_obj_print(o, PRINT_REPR);
@ -459,8 +454,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print
STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
vstr_t vstr; vstr_t vstr;
vstr_init(&vstr, 16); mp_print_t print;
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, o_in, PRINT_REPR); vstr_init_print(&vstr, 16, &print);
mp_obj_print_helper(&print, o_in, PRINT_REPR);
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
} }
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);

View File

@ -31,7 +31,6 @@
#include "py/objtuple.h" #include "py/objtuple.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/objint.h" #include "py/objint.h"
#include "py/pfenv.h"
#include "py/stream.h" #include "py/stream.h"
#if MICROPY_PY_SYS #if MICROPY_PY_SYS
@ -78,12 +77,10 @@ STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
stream_obj = args[1]; stream_obj = args[1];
} }
pfenv_t pfenv; mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
pfenv.data = stream_obj; mp_obj_print_exception(&print, args[0]);
pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
mp_obj_print_exception((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[0]);
#else #else
mp_obj_print_exception(printf_wrapper, NULL, args[0]); mp_obj_print_exception(&mp_plat_print, args[0]);
#endif #endif
return mp_const_none; return mp_const_none;

View File

@ -691,7 +691,7 @@ typedef double mp_float_t;
#define MICROPY_MAKE_POINTER_CALLABLE(p) (p) #define MICROPY_MAKE_POINTER_CALLABLE(p) (p)
#endif #endif
// If these MP_PLAT_* macros are overridden then the memory allocated by them // If these MP_PLAT_*_EXEC macros are overridden then the memory allocated by them
// must be somehow reachable for marking by the GC, since the native code // must be somehow reachable for marking by the GC, since the native code
// generators store pointers to GC managed memory in the code. // generators store pointers to GC managed memory in the code.
#ifndef MP_PLAT_ALLOC_EXEC #ifndef MP_PLAT_ALLOC_EXEC
@ -702,6 +702,11 @@ typedef double mp_float_t;
#define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size) #define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size)
#endif #endif
// This macro is used to do all output (except when MICROPY_PY_IO is defined)
#ifndef MP_PLAT_PRINT_STRN
#define MP_PLAT_PRINT_STRN(str, len) printf("%.*s", (int)len, str)
#endif
#ifndef MP_SSIZE_MAX #ifndef MP_SSIZE_MAX
#define MP_SSIZE_MAX SSIZE_MAX #define MP_SSIZE_MAX SSIZE_MAX
#endif #endif

View File

@ -3,7 +3,7 @@
* *
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2013-2015 Damien P. George
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -24,11 +24,16 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <assert.h>
#include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include "py/mpprint.h"
#include "py/obj.h"
#include "py/objint.h" #include "py/objint.h"
#include "py/pfenv.h" #include "py/runtime.h"
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
#include <stdio.h> #include <stdio.h>
@ -41,11 +46,22 @@
static const char pad_spaces[] = " "; static const char pad_spaces[] = " ";
static const char pad_zeroes[] = "0000000000000000"; static const char pad_zeroes[] = "0000000000000000";
void pfenv_vstr_add_strn(void *data, const char *str, mp_uint_t len) { STATIC void plat_print_strn(void *env, const char *str, mp_uint_t len) {
vstr_add_strn(data, str, len); (void)env;
MP_PLAT_PRINT_STRN(str, len);
} }
int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int flags, char fill, int width) { const mp_print_t mp_plat_print = {NULL, plat_print_strn};
int mp_print_str(const mp_print_t *print, const char *str) {
mp_uint_t len = strlen(str);
if (len) {
print->print_strn(print->data, str, len);
}
return len;
}
int mp_print_strn(const mp_print_t *print, const char *str, mp_uint_t len, int flags, char fill, int width) {
int left_pad = 0; int left_pad = 0;
int right_pad = 0; int right_pad = 0;
int pad = width - len; int pad = width - len;
@ -53,7 +69,7 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
int total_chars_printed = 0; int total_chars_printed = 0;
const char *pad_chars; const char *pad_chars;
if (!fill || fill == ' ' ) { if (!fill || fill == ' ') {
pad_chars = pad_spaces; pad_chars = pad_spaces;
pad_size = sizeof(pad_spaces) - 1; pad_size = sizeof(pad_spaces) - 1;
} else if (fill == '0') { } else if (fill == '0') {
@ -82,12 +98,12 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
if (p > pad_size) { if (p > pad_size) {
p = pad_size; p = pad_size;
} }
pfenv->print_strn(pfenv->data, pad_chars, p); print->print_strn(print->data, pad_chars, p);
left_pad -= p; left_pad -= p;
} }
} }
if (len) { if (len) {
pfenv->print_strn(pfenv->data, str, len); print->print_strn(print->data, str, len);
total_chars_printed += len; total_chars_printed += len;
} }
if (right_pad > 0) { if (right_pad > 0) {
@ -97,7 +113,7 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
if (p > pad_size) { if (p > pad_size) {
p = pad_size; p = pad_size;
} }
pfenv->print_strn(pfenv->data, pad_chars, p); print->print_strn(print->data, pad_chars, p);
right_pad -= p; right_pad -= p;
} }
} }
@ -109,8 +125,8 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int f
#define INT_BUF_SIZE (sizeof(mp_int_t) * 4) #define INT_BUF_SIZE (sizeof(mp_int_t) * 4)
// This function is used by stmhal port to implement printf. // This function is used by stmhal port to implement printf.
// It needs to be a separate function to pfenv_print_mp_int, since converting to a mp_int looses the MSB. // It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB.
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) { int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
char sign = 0; char sign = 0;
if (sgn) { if (sgn) {
if ((mp_int_t)x < 0) { if ((mp_int_t)x < 0) {
@ -156,12 +172,12 @@ int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int ba
int len = 0; int len = 0;
if (flags & PF_FLAG_PAD_AFTER_SIGN) { if (flags & PF_FLAG_PAD_AFTER_SIGN) {
if (sign) { if (sign) {
len += pfenv_print_strn(pfenv, &sign, 1, flags, fill, 1); len += mp_print_strn(print, &sign, 1, flags, fill, 1);
width--; width--;
} }
if (prefix_char) { if (prefix_char) {
len += pfenv_print_strn(pfenv, "0", 1, flags, fill, 1); len += mp_print_strn(print, "0", 1, flags, fill, 1);
len += pfenv_print_strn(pfenv, &prefix_char, 1, flags, fill, 1); len += mp_print_strn(print, &prefix_char, 1, flags, fill, 1);
width -= 2; width -= 2;
} }
} else { } else {
@ -174,11 +190,11 @@ int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int ba
} }
} }
len += pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, fill, width); len += mp_print_strn(print, b, buf + INT_BUF_SIZE - b, flags, fill, width);
return len; return len;
} }
int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) { int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) {
if (!MP_OBJ_IS_INT(x)) { if (!MP_OBJ_IS_INT(x)) {
// This will convert booleans to int, or raise an error for // This will convert booleans to int, or raise an error for
// non-integer types. // non-integer types.
@ -282,16 +298,16 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
int len = 0; int len = 0;
if (spaces_before) { if (spaces_before) {
len += pfenv_print_strn(pfenv, "", 0, 0, ' ', spaces_before); len += mp_print_strn(print, "", 0, 0, ' ', spaces_before);
} }
if (flags & PF_FLAG_PAD_AFTER_SIGN) { if (flags & PF_FLAG_PAD_AFTER_SIGN) {
// pad after sign implies pad after prefix as well. // pad after sign implies pad after prefix as well.
if (sign) { if (sign) {
len += pfenv_print_strn(pfenv, &sign, 1, 0, 0, 1); len += mp_print_strn(print, &sign, 1, 0, 0, 1);
width--; width--;
} }
if (prefix_len) { if (prefix_len) {
len += pfenv_print_strn(pfenv, prefix, prefix_len, 0, 0, 1); len += mp_print_strn(print, prefix, prefix_len, 0, 0, 1);
width -= prefix_len; width -= prefix_len;
} }
} }
@ -299,10 +315,10 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
width = prec; width = prec;
} }
len += pfenv_print_strn(pfenv, str, fmt_size, flags, fill, width); len += mp_print_strn(print, str, fmt_size, flags, fill, width);
if (spaces_after) { if (spaces_after) {
len += pfenv_print_strn(pfenv, "", 0, 0, ' ', spaces_after); len += mp_print_strn(print, "", 0, 0, ' ', spaces_after);
} }
if (buf != stack_buf) { if (buf != stack_buf) {
@ -312,7 +328,7 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char
} }
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec) { int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) {
char buf[32]; char buf[32];
char sign = '\0'; char sign = '\0';
int chrs = 0; int chrs = 0;
@ -361,7 +377,7 @@ int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, c
if (*s <= '9' || (flags & PF_FLAG_PAD_NAN_INF)) { if (*s <= '9' || (flags & PF_FLAG_PAD_NAN_INF)) {
// We have a number, or we have a inf/nan and PAD_NAN_INF is set // We have a number, or we have a inf/nan and PAD_NAN_INF is set
// With '{:06e}'.format(float('-inf')) you get '-00inf' // With '{:06e}'.format(float('-inf')) you get '-00inf'
chrs += pfenv_print_strn(pfenv, &buf[0], 1, 0, 0, 1); chrs += mp_print_strn(print, &buf[0], 1, 0, 0, 1);
width--; width--;
len--; len--;
} }
@ -373,8 +389,168 @@ int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, c
// so suppress the zero fill. // so suppress the zero fill.
fill = ' '; fill = ' ';
} }
chrs += pfenv_print_strn(pfenv, s, len, flags, fill, width); chrs += mp_print_strn(print, s, len, flags, fill, width);
return chrs; return chrs;
} }
#endif #endif
int mp_printf(const mp_print_t *print, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = mp_vprintf(print, fmt, ap);
va_end(ap);
return ret;
}
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
int chrs = 0;
for (;;) {
{
const char *f = fmt;
while (*f != '\0' && *f != '%') {
++f; // XXX UTF8 advance char
}
if (f > fmt) {
print->print_strn(print->data, fmt, f - fmt);
chrs += f - fmt;
fmt = f;
}
}
if (*fmt == '\0') {
break;
}
// move past % character
++fmt;
// parse flags, if they exist
int flags = 0;
char fill = ' ';
while (*fmt != '\0') {
if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
else if (*fmt == '0') {
flags |= PF_FLAG_PAD_AFTER_SIGN;
fill = '0';
} else break;
++fmt;
}
// parse width, if it exists
int width = 0;
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
width = width * 10 + *fmt - '0';
}
// parse precision, if it exists
int prec = -1;
if (*fmt == '.') {
++fmt;
if (*fmt == '*') {
++fmt;
prec = va_arg(args, int);
} else {
prec = 0;
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
prec = prec * 10 + *fmt - '0';
}
}
if (prec < 0) {
prec = 0;
}
}
// parse long specifiers (current not used)
//bool long_arg = false;
if (*fmt == 'l') {
++fmt;
//long_arg = true;
}
if (*fmt == '\0') {
break;
}
switch (*fmt) {
case 'b':
if (va_arg(args, int)) {
chrs += mp_print_strn(print, "true", 4, flags, fill, width);
} else {
chrs += mp_print_strn(print, "false", 5, flags, fill, width);
}
break;
case 'c':
{
char str = va_arg(args, int);
chrs += mp_print_strn(print, &str, 1, flags, fill, width);
break;
}
case 's':
{
const char *str = va_arg(args, const char*);
if (str) {
if (prec < 0) {
prec = strlen(str);
}
chrs += mp_print_strn(print, str, prec, flags, fill, width);
} else {
chrs += mp_print_strn(print, "(null)", 6, flags, fill, width);
}
break;
}
case 'u':
chrs += mp_print_int(print, va_arg(args, int), 0, 10, 'a', flags, fill, width);
break;
case 'd':
chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width);
break;
case 'x':
chrs += mp_print_int(print, va_arg(args, int), 0, 16, 'a', flags, fill, width);
break;
case 'X':
chrs += mp_print_int(print, va_arg(args, int), 0, 16, 'A', flags, fill, width);
break;
case 'p':
case 'P': // don't bother to handle upcase for 'P'
chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
break;
#if MICROPY_PY_BUILTINS_FLOAT
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
{
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
mp_float_t f = va_arg(args, double);
chrs += mp_print_float(print, f, *fmt, flags, fill, width, prec);
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
// Currently mp_print_float uses snprintf, but snprintf
// itself may be implemented in terms of mp_vprintf() for
// some ports. So, for extra caution, this case is handled
// with assert below. Note that currently ports which
// use MICROPY_FLOAT_IMPL_DOUBLE, don't call mp_vprintf()
// with float format specifier at all.
// TODO: resolve this completely
assert(0);
//#error Calling mp_print_float with double not supported from within printf
#else
#error Unknown MICROPY FLOAT IMPL
#endif
break;
}
#endif
default:
print->print_strn(print->data, fmt, 1);
chrs += 1;
break;
}
++fmt;
}
return chrs;
}

View File

@ -23,12 +23,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef __MICROPY_INCLUDED_PY_PFENV_H__ #ifndef __MICROPY_INCLUDED_PY_MPPRINT_H__
#define __MICROPY_INCLUDED_PY_PFENV_H__ #define __MICROPY_INCLUDED_PY_MPPRINT_H__
#include <stdarg.h> #include "py/mpconfig.h"
#include "py/obj.h"
#define PF_FLAG_LEFT_ADJUST (0x001) #define PF_FLAG_LEFT_ADJUST (0x001)
#define PF_FLAG_SHOW_SIGN (0x002) #define PF_FLAG_SHOW_SIGN (0x002)
@ -42,24 +40,28 @@
#define PF_FLAG_PAD_NAN_INF (0x200) #define PF_FLAG_PAD_NAN_INF (0x200)
#define PF_FLAG_SHOW_OCTAL_LETTER (0x400) #define PF_FLAG_SHOW_OCTAL_LETTER (0x400)
typedef struct _pfenv_t { typedef void (*mp_print_strn_t)(void *data, const char *str, mp_uint_t len);
typedef struct _mp_print_t {
void *data; void *data;
void (*print_strn)(void *, const char *str, mp_uint_t len); mp_print_strn_t print_strn;
} pfenv_t; } mp_print_t;
void pfenv_vstr_add_strn(void *data, const char *str, mp_uint_t len); // Wrapper for platform print function, which wraps MP_PLAT_PRINT_STRN.
// All (non-debug) prints go through this interface (except some which
// go through mp_sys_stdout_obj if MICROPY_PY_IO is defined).
extern const mp_print_t mp_plat_print;
int pfenv_print_strn(const pfenv_t *pfenv, const char *str, mp_uint_t len, int flags, char fill, int width); int mp_print_str(const mp_print_t *print, const char *str);
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width); int mp_print_strn(const mp_print_t *print, const char *str, mp_uint_t len, int flags, char fill, int width);
int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec); int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec); int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
#endif #endif
int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args); int mp_printf(const mp_print_t *print, const char *fmt, ...);
int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...); #ifdef va_start
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
#endif
// Wrapper for system printf #endif // __MICROPY_INCLUDED_PY_MPPRINT_H__
void printf_wrapper(void *env, const char *fmt, ...);
#endif // __MICROPY_INCLUDED_PY_PFENV_H__

View File

@ -36,7 +36,7 @@
#include "py/runtime0.h" #include "py/runtime0.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/stackctrl.h" #include "py/stackctrl.h"
#include "py/pfenv.h" //#include "py/pfenv.h"
#include "py/stream.h" // for mp_obj_print #include "py/stream.h" // for mp_obj_print
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
@ -54,20 +54,20 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in) {
return qstr_str(mp_obj_get_type(o_in)->name); return qstr_str(mp_obj_get_type(o_in)->name);
} }
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
// There can be data structures nested too deep, or just recursive // There can be data structures nested too deep, or just recursive
MP_STACK_CHECK(); MP_STACK_CHECK();
#ifndef NDEBUG #ifndef NDEBUG
if (o_in == NULL) { if (o_in == NULL) {
print(env, "(nil)"); mp_print_str(print, "(nil)");
return; return;
} }
#endif #endif
mp_obj_type_t *type = mp_obj_get_type(o_in); mp_obj_type_t *type = mp_obj_get_type(o_in);
if (type->print != NULL) { if (type->print != NULL) {
type->print(print, env, o_in, kind); type->print((mp_print_t*)print, o_in, kind);
} else { } else {
print(env, "<%s>", qstr_str(type->name)); mp_printf(print, "<%s>", qstr_str(type->name));
} }
} }
@ -75,41 +75,41 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
#if MICROPY_PY_IO #if MICROPY_PY_IO
// defined per port; type of these is irrelevant, just need pointer // defined per port; type of these is irrelevant, just need pointer
extern struct _mp_dummy_t mp_sys_stdout_obj; extern struct _mp_dummy_t mp_sys_stdout_obj;
pfenv_t pfenv; mp_print_t print;
pfenv.data = &mp_sys_stdout_obj; print.data = &mp_sys_stdout_obj;
pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write; print.print_strn = (mp_print_strn_t)mp_stream_write;
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, o_in, kind); mp_obj_print_helper(&print, o_in, kind);
#else #else
mp_obj_print_helper(printf_wrapper, NULL, o_in, kind); mp_obj_print_helper(&mp_plat_print, o_in, kind);
#endif #endif
} }
// helper function to print an exception with traceback // helper function to print an exception with traceback
void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc) { void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {
if (mp_obj_is_exception_instance(exc)) { if (mp_obj_is_exception_instance(exc)) {
mp_uint_t n, *values; mp_uint_t n, *values;
mp_obj_exception_get_traceback(exc, &n, &values); mp_obj_exception_get_traceback(exc, &n, &values);
if (n > 0) { if (n > 0) {
assert(n % 3 == 0); assert(n % 3 == 0);
print(env, "Traceback (most recent call last):\n"); mp_print_str(print, "Traceback (most recent call last):\n");
for (int i = n - 3; i >= 0; i -= 3) { for (int i = n - 3; i >= 0; i -= 3) {
#if MICROPY_ENABLE_SOURCE_LINE #if MICROPY_ENABLE_SOURCE_LINE
print(env, " File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]); mp_printf(print, " File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
#else #else
print(env, " File \"%s\"", qstr_str(values[i])); mp_printf(print, " File \"%s\"", qstr_str(values[i]));
#endif #endif
// the block name can be NULL if it's unknown // the block name can be NULL if it's unknown
qstr block = values[i + 2]; qstr block = values[i + 2];
if (block == MP_QSTR_NULL) { if (block == MP_QSTR_NULL) {
print(env, "\n"); mp_print_str(print, "\n");
} else { } else {
print(env, ", in %s\n", qstr_str(block)); mp_printf(print, ", in %s\n", qstr_str(block));
} }
} }
} }
} }
mp_obj_print_helper(print, env, exc, PRINT_EXC); mp_obj_print_helper(print, exc, PRINT_EXC);
print(env, "\n"); mp_print_str(print, "\n");
} }
bool mp_obj_is_true(mp_obj_t arg) { bool mp_obj_is_true(mp_obj_t arg) {

View File

@ -29,6 +29,7 @@
#include "py/mpconfig.h" #include "py/mpconfig.h"
#include "py/misc.h" #include "py/misc.h"
#include "py/qstr.h" #include "py/qstr.h"
#include "py/mpprint.h"
// All Micro Python objects are at least this type // All Micro Python objects are at least this type
// It must be of pointer size // It must be of pointer size
@ -260,7 +261,7 @@ typedef enum {
PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
} mp_print_kind_t; } mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind); typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args); typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args); typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t); typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);
@ -499,9 +500,9 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in);
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects
mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type); mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type);
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind); void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc); void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc);
bool mp_obj_is_true(mp_obj_t arg); bool mp_obj_is_true(mp_obj_t arg);
bool mp_obj_is_callable(mp_obj_t o_in); bool mp_obj_is_callable(mp_obj_t o_in);
@ -561,7 +562,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len); const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str); mp_obj_t mp_obj_str_intern(mp_obj_t str);
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len, bool is_bytes); void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
// float // float

View File

@ -76,26 +76,26 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
// array // array
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_array_t *o = o_in; mp_obj_array_t *o = o_in;
if (o->typecode == BYTEARRAY_TYPECODE) { if (o->typecode == BYTEARRAY_TYPECODE) {
print(env, "bytearray(b"); mp_print_str(print, "bytearray(b");
mp_str_print_quoted(print, env, o->items, o->len, true); mp_str_print_quoted(print, o->items, o->len, true);
} else { } else {
print(env, "array('%c'", o->typecode); mp_printf(print, "array('%c'", o->typecode);
if (o->len > 0) { if (o->len > 0) {
print(env, ", ["); mp_print_str(print, ", [");
for (mp_uint_t i = 0; i < o->len; i++) { for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) { if (i > 0) {
print(env, ", "); mp_print_str(print, ", ");
} }
mp_obj_print_helper(print, env, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR); mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);
} }
print(env, "]"); mp_print_str(print, "]");
} }
} }
print(env, ")"); mp_print_str(print, ")");
} }
#endif #endif

View File

@ -35,19 +35,19 @@ typedef struct _mp_obj_bool_t {
bool value; bool value;
} mp_obj_bool_t; } mp_obj_bool_t;
STATIC void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_bool_t *self = self_in; mp_obj_bool_t *self = self_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
if (self->value) { if (self->value) {
print(env, "true"); mp_print_str(print, "true");
} else { } else {
print(env, "false"); mp_print_str(print, "false");
} }
} else { } else {
if (self->value) { if (self->value) {
print(env, "True"); mp_print_str(print, "True");
} else { } else {
print(env, "False"); mp_print_str(print, "False");
} }
} }
} }

View File

@ -36,14 +36,14 @@ typedef struct _mp_obj_bound_meth_t {
} mp_obj_bound_meth_t; } mp_obj_bound_meth_t;
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
STATIC void bound_meth_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_bound_meth_t *o = o_in; mp_obj_bound_meth_t *o = o_in;
print(env, "<bound_method %p ", o); mp_printf(print, "<bound_method %p ", o);
mp_obj_print_helper(print, env, o->self, PRINT_REPR); mp_obj_print_helper(print, o->self, PRINT_REPR);
print(env, "."); mp_print_str(print, ".");
mp_obj_print_helper(print, env, o->meth, PRINT_REPR); mp_obj_print_helper(print, o->meth, PRINT_REPR);
print(env, ">"); mp_print_str(print, ">");
} }
#endif #endif

View File

@ -42,16 +42,16 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {
} }
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
STATIC void cell_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_cell_t *o = o_in; mp_obj_cell_t *o = o_in;
print(env, "<cell %p ", o->obj); mp_printf(print, "<cell %p ", o->obj);
if (o->obj == MP_OBJ_NULL) { if (o->obj == MP_OBJ_NULL) {
print(env, "(nil)"); mp_print_str(print, "(nil)");
} else { } else {
mp_obj_print_helper(print, env, o->obj, PRINT_REPR); mp_obj_print_helper(print, o->obj, PRINT_REPR);
} }
print(env, ">"); mp_print_str(print, ">");
} }
#endif #endif

View File

@ -60,21 +60,21 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
} }
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
STATIC void closure_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_closure_t *o = o_in; mp_obj_closure_t *o = o_in;
print(env, "<closure "); mp_print_str(print, "<closure ");
mp_obj_print_helper(print, env, o->fun, PRINT_REPR); mp_obj_print_helper(print, o->fun, PRINT_REPR);
print(env, " at %p, n_closed=%u ", o, o->n_closed); mp_printf(print, " at %p, n_closed=%u ", o, o->n_closed);
for (mp_uint_t i = 0; i < o->n_closed; i++) { for (mp_uint_t i = 0; i < o->n_closed; i++) {
if (o->closed[i] == MP_OBJ_NULL) { if (o->closed[i] == MP_OBJ_NULL) {
print(env, "(nil)"); mp_print_str(print, "(nil)");
} else { } else {
mp_obj_print_helper(print, env, o->closed[i], PRINT_REPR); mp_obj_print_helper(print, o->closed[i], PRINT_REPR);
} }
print(env, " "); mp_print_str(print, " ");
} }
print(env, ">"); mp_print_str(print, ">");
} }
#endif #endif

View File

@ -48,36 +48,36 @@ typedef struct _mp_obj_complex_t {
mp_float_t imag; mp_float_t imag;
} mp_obj_complex_t; } mp_obj_complex_t;
STATIC void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_complex_t *o = o_in; mp_obj_complex_t *o = o_in;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16]; char buf[16];
if (o->real == 0) { if (o->real == 0) {
mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0'); mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
print(env, "%sj", buf); mp_printf(print, "%sj", buf);
} else { } else {
mp_format_float(o->real, buf, sizeof(buf), 'g', 7, '\0'); mp_format_float(o->real, buf, sizeof(buf), 'g', 7, '\0');
print(env, "(%s", buf); mp_printf(print, "(%s", buf);
if (o->imag >= 0) { if (o->imag >= 0) {
print(env, "+"); mp_print_str(print, "+");
} }
mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0'); mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
print(env, "%sj)", buf); mp_printf(print, "%sj)", buf);
} }
#else #else
char buf[32]; char buf[32];
if (o->real == 0) { if (o->real == 0) {
sprintf(buf, "%.16g", (double)o->imag); sprintf(buf, "%.16g", (double)o->imag);
print(env, "%sj", buf); mp_printf(print, "%sj", buf);
} else { } else {
sprintf(buf, "%.16g", (double)o->real); sprintf(buf, "%.16g", (double)o->real);
print(env, "(%s", buf); mp_printf(print, "(%s", buf);
if (o->imag >= 0) { if (o->imag >= 0) {
print(env, "+"); mp_print_str(print, "+");
} }
sprintf(buf, "%.16g", (double)o->imag); sprintf(buf, "%.16g", (double)o->imag);
print(env, "%sj)", buf); mp_printf(print, "%sj)", buf);
} }
#endif #endif
} }

View File

@ -55,30 +55,30 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
return NULL; return NULL;
} }
STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_dict_t *self = MP_OBJ_CAST(self_in); mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
bool first = true; bool first = true;
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
kind = PRINT_REPR; kind = PRINT_REPR;
} }
if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) { if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {
print(env, "%s(", qstr_str(self->base.type->name)); mp_printf(print, "%s(", qstr_str(self->base.type->name));
} }
print(env, "{"); mp_print_str(print, "{");
mp_uint_t cur = 0; mp_uint_t cur = 0;
mp_map_elem_t *next = NULL; mp_map_elem_t *next = NULL;
while ((next = dict_iter_next(self, &cur)) != NULL) { while ((next = dict_iter_next(self, &cur)) != NULL) {
if (!first) { if (!first) {
print(env, ", "); mp_print_str(print, ", ");
} }
first = false; first = false;
mp_obj_print_helper(print, env, next->key, kind); mp_obj_print_helper(print, next->key, kind);
print(env, ": "); mp_print_str(print, ": ");
mp_obj_print_helper(print, env, next->value, kind); mp_obj_print_helper(print, next->value, kind);
} }
print(env, "}"); mp_print_str(print, "}");
if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) { if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) {
print(env, ")"); mp_print_str(print, ")");
} }
} }
@ -473,23 +473,23 @@ STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
return o_out; return o_out;
} }
STATIC void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type)); assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
mp_obj_dict_view_t *self = MP_OBJ_CAST(self_in); mp_obj_dict_view_t *self = MP_OBJ_CAST(self_in);
bool first = true; bool first = true;
print(env, mp_dict_view_names[self->kind]); mp_print_str(print, mp_dict_view_names[self->kind]);
print(env, "(["); mp_print_str(print, "([");
mp_obj_t self_iter = dict_view_getiter(self_in); mp_obj_t self_iter = dict_view_getiter(self_in);
mp_obj_t next = MP_OBJ_NULL; mp_obj_t next = MP_OBJ_NULL;
while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) { while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
if (!first) { if (!first) {
print(env, ", "); mp_print_str(print, ", ");
} }
first = false; first = false;
mp_obj_print_helper(print, env, next, PRINT_REPR); mp_obj_print_helper(print, next, PRINT_REPR);
} }
print(env, "])"); mp_print_str(print, "])");
} }
STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {

View File

@ -90,28 +90,28 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {
// definition module-private so far, have it here. // definition module-private so far, have it here.
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple}; const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple};
STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_exception_t *o = o_in; mp_obj_exception_t *o = o_in;
mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
bool is_subclass = kind & PRINT_EXC_SUBCLASS; bool is_subclass = kind & PRINT_EXC_SUBCLASS;
if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) { if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {
print(env, "%s", qstr_str(o->base.type->name)); mp_printf(print, "%s", qstr_str(o->base.type->name));
} }
if (k == PRINT_EXC) { if (k == PRINT_EXC) {
print(env, ": "); mp_print_str(print, ": ");
} }
if (k == PRINT_STR || k == PRINT_EXC) { if (k == PRINT_STR || k == PRINT_EXC) {
if (o->args == NULL || o->args->len == 0) { if (o->args == NULL || o->args->len == 0) {
print(env, ""); mp_print_str(print, "");
return; return;
} else if (o->args->len == 1) { } else if (o->args->len == 1) {
mp_obj_print_helper(print, env, o->args->items[0], PRINT_STR); mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
return; return;
} }
} }
mp_obj_tuple_print(print, env, o->args, kind); mp_obj_tuple_print(print, o->args, kind);
} }
mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {

View File

@ -42,24 +42,24 @@
#include "py/formatfloat.h" #include "py/formatfloat.h"
#endif #endif
STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_float_t *o = o_in; mp_obj_float_t *o = o_in;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16]; char buf[16];
mp_format_float(o->value, buf, sizeof(buf), 'g', 7, '\0'); mp_format_float(o->value, buf, sizeof(buf), 'g', 7, '\0');
print(env, "%s", buf); mp_print_str(print, buf);
if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) { if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) {
// Python floats always have decimal point // Python floats always have decimal point
print(env, ".0"); mp_print_str(print, ".0");
} }
#else #else
char buf[32]; char buf[32];
sprintf(buf, "%.16g", (double) o->value); sprintf(buf, "%.16g", (double) o->value);
print(env, buf); mp_print_str(print, buf);
if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) { if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) {
// Python floats always have decimal point // Python floats always have decimal point
print(env, ".0"); mp_print_str(print, ".0");
} }
#endif #endif
} }

View File

@ -125,10 +125,10 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
} }
#if MICROPY_CPYTHON_COMPAT #if MICROPY_CPYTHON_COMPAT
STATIC void fun_bc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_fun_bc_t *o = o_in; mp_obj_fun_bc_t *o = o_in;
print(env, "<function %s at 0x%x>", qstr_str(mp_obj_fun_get_name(o)), o); mp_printf(print, "<function %s at 0x%x>", qstr_str(mp_obj_fun_get_name(o)), o);
} }
#endif #endif

View File

@ -95,10 +95,10 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
/******************************************************************************/ /******************************************************************************/
/* generator instance */ /* generator instance */
STATIC void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_gen_instance_t *self = self_in; mp_obj_gen_instance_t *self = self_in;
print(env, "<generator object '%s' at %p>", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in); mp_printf(print, "<generator object '%s' at %p>", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in);
} }
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {

View File

@ -124,7 +124,7 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
#undef MP_FLOAT_EXP_SHIFT_I32 #undef MP_FLOAT_EXP_SHIFT_I32
#endif #endif
void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
// The size of this buffer is rather arbitrary. If it's not large // The size of this buffer is rather arbitrary. If it's not large
// enough, a dynamic one will be allocated. // enough, a dynamic one will be allocated.
@ -134,7 +134,7 @@ void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env,
mp_uint_t fmt_size; mp_uint_t fmt_size;
char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0'); char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0');
print(env, "%s", str); mp_print_str(print, str);
if (buf != stack_buf) { if (buf != stack_buf) {
m_del(char, buf, buf_size); m_del(char, buf, buf_size);

View File

@ -50,7 +50,7 @@ typedef enum {
mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val); mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val);
#endif // MICROPY_PY_BUILTINS_FLOAT #endif // MICROPY_PY_BUILTINS_FLOAT
void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind); void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,
int base, const char *prefix, char base_char, char comma); int base, const char *prefix, char base_char, char comma);
char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,

View File

@ -44,19 +44,19 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
/******************************************************************************/ /******************************************************************************/
/* list */ /* list */
STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_list_t *o = MP_OBJ_CAST(o_in); mp_obj_list_t *o = MP_OBJ_CAST(o_in);
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
kind = PRINT_REPR; kind = PRINT_REPR;
} }
print(env, "["); mp_print_str(print, "[");
for (mp_uint_t i = 0; i < o->len; i++) { for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) { if (i > 0) {
print(env, ", "); mp_print_str(print, ", ");
} }
mp_obj_print_helper(print, env, o->items[i], kind); mp_obj_print_helper(print, o->items[i], kind);
} }
print(env, "]"); mp_print_str(print, "]");
} }
STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {

View File

@ -33,7 +33,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/builtin.h" #include "py/builtin.h"
STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_module_t *self = self_in; mp_obj_module_t *self = self_in;
const char *name = qstr_str(self->name); const char *name = qstr_str(self->name);
@ -43,12 +43,12 @@ STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *e
// symbol to give more information about the module. // symbol to give more information about the module.
mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP);
if (elem != NULL) { if (elem != NULL) {
print(env, "<module '%s' from '%s'>", name, mp_obj_str_get_str(elem->value)); mp_printf(print, "<module '%s' from '%s'>", name, mp_obj_str_get_str(elem->value));
return; return;
} }
#endif #endif
print(env, "<module '%s'>", name); mp_printf(print, "<module '%s'>", name);
} }
STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {

View File

@ -53,19 +53,19 @@ STATIC mp_uint_t namedtuple_find_field(mp_obj_namedtuple_type_t *type, qstr name
return -1; return -1;
} }
STATIC void namedtuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_namedtuple_t *o = o_in; mp_obj_namedtuple_t *o = o_in;
print(env, "%s(", qstr_str(o->tuple.base.type->name)); mp_printf(print, "%s(", qstr_str(o->tuple.base.type->name));
const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields; const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields;
for (mp_uint_t i = 0; i < o->tuple.len; i++) { for (mp_uint_t i = 0; i < o->tuple.len; i++) {
if (i > 0) { if (i > 0) {
print(env, ", "); mp_print_str(print, ", ");
} }
print(env, "%s=", qstr_str(fields[i])); mp_printf(print, "%s=", qstr_str(fields[i]));
mp_obj_print_helper(print, env, o->tuple.items[i], PRINT_REPR); mp_obj_print_helper(print, o->tuple.items[i], PRINT_REPR);
} }
print(env, ")"); mp_print_str(print, ")");
} }
STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {

View File

@ -34,12 +34,12 @@ typedef struct _mp_obj_none_t {
mp_obj_base_t base; mp_obj_base_t base;
} mp_obj_none_t; } mp_obj_none_t;
STATIC void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)self_in; (void)self_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
print(env, "null"); mp_print_str(print, "null");
} else { } else {
print(env, "None"); mp_print_str(print, "None");
} }
} }

View File

@ -79,14 +79,14 @@ typedef struct _mp_obj_range_t {
mp_int_t step; mp_int_t step;
} mp_obj_range_t; } mp_obj_range_t;
STATIC void range_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_range_t *self = self_in; mp_obj_range_t *self = self_in;
print(env, "range(%d, %d", self->start, self->stop); mp_printf(print, "range(%d, %d", self->start, self->stop);
if (self->step == 1) { if (self->step == 1) {
print(env, ")"); mp_print_str(print, ")");
} else { } else {
print(env, ", %d)", self->step); mp_printf(print, ", %d)", self->step);
} }
} }

View File

@ -79,7 +79,7 @@ STATIC void check_set(mp_obj_t o) {
} }
} }
STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_set_t *self = self_in; mp_obj_set_t *self = self_in;
#if MICROPY_PY_BUILTINS_FROZENSET #if MICROPY_PY_BUILTINS_FROZENSET
@ -88,37 +88,36 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env,
if (self->set.used == 0) { if (self->set.used == 0) {
#if MICROPY_PY_BUILTINS_FROZENSET #if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) { if (is_frozen) {
print(env, "frozen"); mp_print_str(print, "frozen");
} }
#endif #endif
print(env, "set()"); mp_print_str(print, "set()");
return; return;
} }
bool first = true; bool first = true;
#if MICROPY_PY_BUILTINS_FROZENSET #if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) { if (is_frozen) {
print(env, "frozenset("); mp_print_str(print, "frozenset(");
} }
#endif #endif
print(env, "{"); mp_print_str(print, "{");
for (mp_uint_t i = 0; i < self->set.alloc; i++) { for (mp_uint_t i = 0; i < self->set.alloc; i++) {
if (MP_SET_SLOT_IS_FILLED(&self->set, i)) { if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {
if (!first) { if (!first) {
print(env, ", "); mp_print_str(print, ", ");
} }
first = false; first = false;
mp_obj_print_helper(print, env, self->set.table[i], PRINT_REPR); mp_obj_print_helper(print, self->set.table[i], PRINT_REPR);
} }
} }
print(env, "}"); mp_print_str(print, "}");
#if MICROPY_PY_BUILTINS_FROZENSET #if MICROPY_PY_BUILTINS_FROZENSET
if (is_frozen) { if (is_frozen) {
print(env, ")"); mp_print_str(print, ")");
} }
#endif #endif
} }
STATIC mp_obj_t set_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t set_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_arg_check_num(n_args, n_kw, 0, 1, false);

View File

@ -38,10 +38,10 @@ typedef struct _mp_obj_ellipsis_t {
mp_obj_base_t base; mp_obj_base_t base;
} mp_obj_ellipsis_t; } mp_obj_ellipsis_t;
STATIC void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void ellipsis_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)self_in; (void)self_in;
(void)kind; (void)kind;
print(env, "Ellipsis"); mp_print_str(print, "Ellipsis");
} }
const mp_obj_type_t mp_type_ellipsis = { const mp_obj_type_t mp_type_ellipsis = {
@ -66,16 +66,16 @@ typedef struct _mp_obj_slice_t {
mp_obj_t step; mp_obj_t step;
} mp_obj_slice_t; } mp_obj_slice_t;
STATIC void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_slice_t *o = o_in; mp_obj_slice_t *o = o_in;
print(env, "slice("); mp_print_str(print, "slice(");
mp_obj_print_helper(print, env, o->start, PRINT_REPR); mp_obj_print_helper(print, o->start, PRINT_REPR);
print(env, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, env, o->stop, PRINT_REPR); mp_obj_print_helper(print, o->stop, PRINT_REPR);
print(env, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, env, o->step, PRINT_REPR); mp_obj_print_helper(print, o->step, PRINT_REPR);
print(env, ")"); mp_print_str(print, ")");
} }
const mp_obj_type_t mp_type_slice = { const mp_obj_type_t mp_type_slice = {

View File

@ -34,7 +34,6 @@
#include "py/objlist.h" #include "py/objlist.h"
#include "py/runtime0.h" #include "py/runtime0.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/pfenv.h"
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_obj_t *args, mp_obj_t dict); STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_obj_t *args, mp_obj_t dict);
@ -45,8 +44,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
/******************************************************************************/ /******************************************************************************/
/* str */ /* str */
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes) {
const byte *str_data, mp_uint_t str_len, bool is_bytes) {
// this escapes characters, but it will be very slow to print (calling print many times) // this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false; bool has_single_quote = false;
bool has_double_quote = false; bool has_double_quote = false;
@ -61,72 +59,72 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
if (has_single_quote && !has_double_quote) { if (has_single_quote && !has_double_quote) {
quote_char = '"'; quote_char = '"';
} }
print(env, "%c", quote_char); mp_printf(print, "%c", quote_char);
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) { for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
if (*s == quote_char) { if (*s == quote_char) {
print(env, "\\%c", quote_char); mp_printf(print, "\\%c", quote_char);
} else if (*s == '\\') { } else if (*s == '\\') {
print(env, "\\\\"); mp_print_str(print, "\\\\");
} else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) { } else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {
// In strings, anything which is not ascii control character // In strings, anything which is not ascii control character
// is printed as is, this includes characters in range 0x80-0xff // is printed as is, this includes characters in range 0x80-0xff
// (which can be non-Latin letters, etc.) // (which can be non-Latin letters, etc.)
print(env, "%c", *s); mp_printf(print, "%c", *s);
} else if (*s == '\n') { } else if (*s == '\n') {
print(env, "\\n"); mp_print_str(print, "\\n");
} else if (*s == '\r') { } else if (*s == '\r') {
print(env, "\\r"); mp_print_str(print, "\\r");
} else if (*s == '\t') { } else if (*s == '\t') {
print(env, "\\t"); mp_print_str(print, "\\t");
} else { } else {
print(env, "\\x%02x", *s); mp_printf(print, "\\x%02x", *s);
} }
} }
print(env, "%c", quote_char); mp_printf(print, "%c", quote_char);
} }
#if MICROPY_PY_UJSON #if MICROPY_PY_UJSON
void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) { void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len) {
// for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt // for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt
// if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way // if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way
print(env, "\""); mp_print_str(print, "\"");
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) { for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
if (*s == '"' || *s == '\\') { if (*s == '"' || *s == '\\') {
print(env, "\\%c", *s); mp_printf(print, "\\%c", *s);
} else if (*s >= 32) { } else if (*s >= 32) {
// this will handle normal and utf-8 encoded chars // this will handle normal and utf-8 encoded chars
print(env, "%c", *s); mp_printf(print, "%c", *s);
} else if (*s == '\n') { } else if (*s == '\n') {
print(env, "\\n"); mp_print_str(print, "\\n");
} else if (*s == '\r') { } else if (*s == '\r') {
print(env, "\\r"); mp_print_str(print, "\\r");
} else if (*s == '\t') { } else if (*s == '\t') {
print(env, "\\t"); mp_print_str(print, "\\t");
} else { } else {
// this will handle control chars // this will handle control chars
print(env, "\\u%04x", *s); mp_printf(print, "\\u%04x", *s);
} }
} }
print(env, "\""); mp_print_str(print, "\"");
} }
#endif #endif
STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len); GET_STR_DATA_LEN(self_in, str_data, str_len);
#if MICROPY_PY_UJSON #if MICROPY_PY_UJSON
if (kind == PRINT_JSON) { if (kind == PRINT_JSON) {
mp_str_print_json(print, env, str_data, str_len); mp_str_print_json(print, str_data, str_len);
return; return;
} }
#endif #endif
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes); bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
if (kind == PRINT_STR && !is_bytes) { if (kind == PRINT_STR && !is_bytes) {
print(env, "%.*s", str_len, str_data); mp_printf(print, "%.*s", str_len, str_data);
} else { } else {
if (is_bytes) { if (is_bytes) {
print(env, "b"); mp_print_str(print, "b");
} }
mp_str_print_quoted(print, env, str_data, str_len, is_bytes); mp_str_print_quoted(print, str_data, str_len, is_bytes);
} }
} }
@ -145,8 +143,9 @@ mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
case 1: { case 1: {
vstr_t vstr; vstr_t vstr;
vstr_init(&vstr, 16); mp_print_t print;
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &vstr, args[0], PRINT_STR); vstr_init_print(&vstr, 16, &print);
mp_obj_print_helper(&print, args[0], PRINT_STR);
return mp_obj_new_str_from_vstr(type_in, &vstr); return mp_obj_new_str_from_vstr(type_in, &vstr);
} }
@ -840,10 +839,8 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
GET_STR_DATA_LEN(args[0], str, len); GET_STR_DATA_LEN(args[0], str, len);
int arg_i = 0; int arg_i = 0;
vstr_t vstr; vstr_t vstr;
vstr_init(&vstr, 16); mp_print_t print;
pfenv_t pfenv_vstr; vstr_init_print(&vstr, 16, &print);
pfenv_vstr.data = &vstr;
pfenv_vstr.print_strn = pfenv_vstr_add_strn;
for (const byte *top = str + len; str < top; str++) { for (const byte *top = str + len; str < top; str++) {
if (*str == '}') { if (*str == '}') {
@ -998,8 +995,9 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
} }
} }
vstr_t arg_vstr; vstr_t arg_vstr;
vstr_init(&arg_vstr, 16); mp_print_t arg_print;
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &arg_vstr, arg, print_kind); vstr_init_print(&arg_vstr, 16, &arg_print);
mp_obj_print_helper(&arg_print, arg, print_kind);
arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr); arg = mp_obj_new_str_from_vstr(&mp_type_str, &arg_vstr);
} }
@ -1108,20 +1106,20 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
if (arg_looks_integer(arg)) { if (arg_looks_integer(arg)) {
switch (type) { switch (type) {
case 'b': case 'b':
pfenv_print_mp_int(&pfenv_vstr, arg, 2, 'a', flags, fill, width, 0); mp_print_mp_int(&print, arg, 2, 'a', flags, fill, width, 0);
continue; continue;
case 'c': case 'c':
{ {
char ch = mp_obj_get_int(arg); char ch = mp_obj_get_int(arg);
pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, fill, width); mp_print_strn(&print, &ch, 1, flags, fill, width);
continue; continue;
} }
case '\0': // No explicit format type implies 'd' case '\0': // No explicit format type implies 'd'
case 'n': // I don't think we support locales in uPy so use 'd' case 'n': // I don't think we support locales in uPy so use 'd'
case 'd': case 'd':
pfenv_print_mp_int(&pfenv_vstr, arg, 10, 'a', flags, fill, width, 0); mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0);
continue; continue;
case 'o': case 'o':
@ -1129,12 +1127,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
flags |= PF_FLAG_SHOW_OCTAL_LETTER; flags |= PF_FLAG_SHOW_OCTAL_LETTER;
} }
pfenv_print_mp_int(&pfenv_vstr, arg, 8, 'a', flags, fill, width, 0); mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, 0);
continue; continue;
case 'X': case 'X':
case 'x': case 'x':
pfenv_print_mp_int(&pfenv_vstr, arg, 16, type - ('X' - 'A'), flags, fill, width, 0); mp_print_mp_int(&print, arg, 16, type - ('X' - 'A'), flags, fill, width, 0);
continue; continue;
case 'e': case 'e':
@ -1206,7 +1204,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
case 'F': case 'F':
case 'g': case 'g':
case 'G': case 'G':
pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), type, flags, fill, width, precision); mp_print_float(&print, mp_obj_get_float(arg), type, flags, fill, width, precision);
break; break;
case '%': case '%':
@ -1216,7 +1214,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
#else #else
#define F100 100.0 #define F100 100.0
#endif #endif
pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision); mp_print_float(&print, mp_obj_get_float(arg) * F100, 'f', flags, fill, width, precision);
#undef F100 #undef F100
break; break;
#endif #endif
@ -1244,7 +1242,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
switch (type) { switch (type) {
case '\0': case '\0':
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &vstr, arg, PRINT_STR); mp_obj_print_helper(&print, arg, PRINT_STR);
break; break;
case 's': { case 's': {
@ -1256,7 +1254,7 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
if (slen > (mp_uint_t)precision) { if (slen > (mp_uint_t)precision) {
slen = precision; slen = precision;
} }
pfenv_print_strn(&pfenv_vstr, s, slen, flags, fill, width); mp_print_strn(&print, s, slen, flags, fill, width);
break; break;
} }
@ -1282,10 +1280,8 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
const byte *start_str = str; const byte *start_str = str;
int arg_i = 0; int arg_i = 0;
vstr_t vstr; vstr_t vstr;
vstr_init(&vstr, 16); mp_print_t print;
pfenv_t pfenv_vstr; vstr_init_print(&vstr, 16, &print);
pfenv_vstr.data = &vstr;
pfenv_vstr.print_strn = pfenv_vstr_add_strn;
for (const byte *top = str + len; str < top; str++) { for (const byte *top = str + len; str < top; str++) {
mp_obj_t arg = MP_OBJ_NULL; mp_obj_t arg = MP_OBJ_NULL;
@ -1389,10 +1385,10 @@ not_enough_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"%%c requires int or char")); "%%c requires int or char"));
} }
pfenv_print_strn(&pfenv_vstr, s, 1, flags, ' ', width); mp_print_strn(&print, s, 1, flags, ' ', width);
} else if (arg_looks_integer(arg)) { } else if (arg_looks_integer(arg)) {
char ch = mp_obj_get_int(arg); char ch = mp_obj_get_int(arg);
pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width); mp_print_strn(&print, &ch, 1, flags, ' ', width);
} else { } else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"integer required")); "integer required"));
@ -1402,7 +1398,7 @@ not_enough_args:
case 'd': case 'd':
case 'i': case 'i':
case 'u': case 'u':
pfenv_print_mp_int(&pfenv_vstr, arg_as_int(arg), 10, 'a', flags, fill, width, prec); mp_print_mp_int(&print, arg_as_int(arg), 10, 'a', flags, fill, width, prec);
break; break;
#if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_PY_BUILTINS_FLOAT
@ -1412,7 +1408,7 @@ not_enough_args:
case 'F': case 'F':
case 'g': case 'g':
case 'G': case 'G':
pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), *str, flags, fill, width, prec); mp_print_float(&print, mp_obj_get_float(arg), *str, flags, fill, width, prec);
break; break;
#endif #endif
@ -1420,16 +1416,16 @@ not_enough_args:
if (alt) { if (alt) {
flags |= (PF_FLAG_SHOW_PREFIX | PF_FLAG_SHOW_OCTAL_LETTER); flags |= (PF_FLAG_SHOW_PREFIX | PF_FLAG_SHOW_OCTAL_LETTER);
} }
pfenv_print_mp_int(&pfenv_vstr, arg, 8, 'a', flags, fill, width, prec); mp_print_mp_int(&print, arg, 8, 'a', flags, fill, width, prec);
break; break;
case 'r': case 'r':
case 's': case 's':
{ {
vstr_t arg_vstr; vstr_t arg_vstr;
vstr_init(&arg_vstr, 16); mp_print_t arg_print;
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr_init_print(&arg_vstr, 16, &arg_print);
&arg_vstr, arg, *str == 'r' ? PRINT_REPR : PRINT_STR); mp_obj_print_helper(&arg_print, arg, *str == 'r' ? PRINT_REPR : PRINT_STR);
uint vlen = arg_vstr.len; uint vlen = arg_vstr.len;
if (prec < 0) { if (prec < 0) {
prec = vlen; prec = vlen;
@ -1437,14 +1433,14 @@ not_enough_args:
if (vlen > (uint)prec) { if (vlen > (uint)prec) {
vlen = prec; vlen = prec;
} }
pfenv_print_strn(&pfenv_vstr, arg_vstr.buf, vlen, flags, ' ', width); mp_print_strn(&print, arg_vstr.buf, vlen, flags, ' ', width);
vstr_clear(&arg_vstr); vstr_clear(&arg_vstr);
break; break;
} }
case 'X': case 'X':
case 'x': case 'x':
pfenv_print_mp_int(&pfenv_vstr, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec); mp_print_mp_int(&print, arg, 16, *str - ('X' - 'A'), flags | alt, fill, width, prec);
break; break;
default: default:

View File

@ -55,7 +55,7 @@ typedef struct _mp_obj_str_t {
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args); mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len); void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len);
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
mp_obj_t mp_obj_str_split(mp_uint_t n_args, const mp_obj_t *args); mp_obj_t mp_obj_str_split(mp_uint_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len); mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len);

View File

@ -52,10 +52,10 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {
#define check_stringio_is_open(o) #define check_stringio_is_open(o)
#endif #endif
STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_stringio_t *self = self_in; mp_obj_stringio_t *self = self_in;
print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self); mp_printf(print, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self);
} }
STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {

View File

@ -33,7 +33,6 @@
#include "py/objlist.h" #include "py/objlist.h"
#include "py/runtime0.h" #include "py/runtime0.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/pfenv.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE #if MICROPY_PY_BUILTINS_STR_UNICODE
@ -42,7 +41,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
/******************************************************************************/ /******************************************************************************/
/* str */ /* str */
STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) { STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) {
// this escapes characters, but it will be very slow to print (calling print many times) // this escapes characters, but it will be very slow to print (calling print many times)
bool has_single_quote = false; bool has_single_quote = false;
bool has_double_quote = false; bool has_double_quote = false;
@ -57,47 +56,47 @@ STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), voi
if (has_single_quote && !has_double_quote) { if (has_single_quote && !has_double_quote) {
quote_char = '"'; quote_char = '"';
} }
print(env, "%c", quote_char); mp_printf(print, "%c", quote_char);
const byte *s = str_data, *top = str_data + str_len; const byte *s = str_data, *top = str_data + str_len;
while (s < top) { while (s < top) {
unichar ch; unichar ch;
ch = utf8_get_char(s); ch = utf8_get_char(s);
s = utf8_next_char(s); s = utf8_next_char(s);
if (ch == quote_char) { if (ch == quote_char) {
print(env, "\\%c", quote_char); mp_printf(print, "\\%c", quote_char);
} else if (ch == '\\') { } else if (ch == '\\') {
print(env, "\\\\"); mp_print_str(print, "\\\\");
} else if (32 <= ch && ch <= 126) { } else if (32 <= ch && ch <= 126) {
print(env, "%c", ch); mp_printf(print, "%c", ch);
} else if (ch == '\n') { } else if (ch == '\n') {
print(env, "\\n"); mp_print_str(print, "\\n");
} else if (ch == '\r') { } else if (ch == '\r') {
print(env, "\\r"); mp_print_str(print, "\\r");
} else if (ch == '\t') { } else if (ch == '\t') {
print(env, "\\t"); mp_print_str(print, "\\t");
} else if (ch < 0x100) { } else if (ch < 0x100) {
print(env, "\\x%02x", ch); mp_printf(print, "\\x%02x", ch);
} else if (ch < 0x10000) { } else if (ch < 0x10000) {
print(env, "\\u%04x", ch); mp_printf(print, "\\u%04x", ch);
} else { } else {
print(env, "\\U%08x", ch); mp_printf(print, "\\U%08x", ch);
} }
} }
print(env, "%c", quote_char); mp_printf(print, "%c", quote_char);
} }
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len); GET_STR_DATA_LEN(self_in, str_data, str_len);
#if MICROPY_PY_UJSON #if MICROPY_PY_UJSON
if (kind == PRINT_JSON) { if (kind == PRINT_JSON) {
mp_str_print_json(print, env, str_data, str_len); mp_str_print_json(print, str_data, str_len);
return; return;
} }
#endif #endif
if (kind == PRINT_STR) { if (kind == PRINT_STR) {
print(env, "%.*s", str_len, str_data); mp_printf(print, "%.*s", str_len, str_data);
} else { } else {
uni_print_quoted(print, env, str_data, str_len); uni_print_quoted(print, str_data, str_len);
} }
} }

View File

@ -37,27 +37,27 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
/******************************************************************************/ /******************************************************************************/
/* tuple */ /* tuple */
void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_tuple_t *o = o_in; mp_obj_tuple_t *o = o_in;
if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
print(env, "["); mp_print_str(print, "[");
} else { } else {
print(env, "("); mp_print_str(print, "(");
kind = PRINT_REPR; kind = PRINT_REPR;
} }
for (mp_uint_t i = 0; i < o->len; i++) { for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) { if (i > 0) {
print(env, ", "); mp_print_str(print, ", ");
} }
mp_obj_print_helper(print, env, o->items[i], kind); mp_obj_print_helper(print, o->items[i], kind);
} }
if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
print(env, "]"); mp_print_str(print, "]");
} else { } else {
if (o->len == 1) { if (o->len == 1) {
print(env, ","); mp_print_str(print, ",");
} }
print(env, ")"); mp_print_str(print, ")");
} }
} }

View File

@ -34,7 +34,7 @@ typedef struct _mp_obj_tuple_t {
mp_obj_t items[]; mp_obj_t items[];
} mp_obj_tuple_t; } mp_obj_tuple_t;
void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in); mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value); mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);

View File

@ -196,7 +196,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
} }
} }
STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_instance_t *self = self_in; mp_obj_instance_t *self = self_in;
qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__; qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
mp_obj_t member[2] = {MP_OBJ_NULL}; mp_obj_t member[2] = {MP_OBJ_NULL};
@ -219,23 +219,23 @@ STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void
// Handle Exception subclasses specially // Handle Exception subclasses specially
if (mp_obj_is_native_exception_instance(self->subobj[0])) { if (mp_obj_is_native_exception_instance(self->subobj[0])) {
if (kind != PRINT_STR) { if (kind != PRINT_STR) {
print(env, "%s", qstr_str(self->base.type->name)); mp_print_str(print, qstr_str(self->base.type->name));
} }
mp_obj_print_helper(print, env, self->subobj[0], kind | PRINT_EXC_SUBCLASS); mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
} else { } else {
mp_obj_print_helper(print, env, self->subobj[0], kind); mp_obj_print_helper(print, self->subobj[0], kind);
} }
return; return;
} }
if (member[0] != MP_OBJ_NULL) { if (member[0] != MP_OBJ_NULL) {
mp_obj_t r = mp_call_function_1(member[0], self_in); mp_obj_t r = mp_call_function_1(member[0], self_in);
mp_obj_print_helper(print, env, r, PRINT_STR); mp_obj_print_helper(print, r, PRINT_STR);
return; return;
} }
// TODO: CPython prints fully-qualified type name // TODO: CPython prints fully-qualified type name
print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in); mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
} }
mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@ -737,10 +737,10 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
// - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object // - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object
// - creating a new class (a new type) creates a new mp_obj_type_t // - creating a new class (a new type) creates a new mp_obj_type_t
STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_type_t *self = self_in; mp_obj_type_t *self = self_in;
print(env, "<class '%s'>", qstr_str(self->name)); mp_printf(print, "<class '%s'>", qstr_str(self->name));
} }
STATIC mp_obj_t type_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t type_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@ -911,14 +911,14 @@ typedef struct _mp_obj_super_t {
mp_obj_t obj; mp_obj_t obj;
} mp_obj_super_t; } mp_obj_super_t;
STATIC void super_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_super_t *self = self_in; mp_obj_super_t *self = self_in;
print(env, "<super: "); mp_print_str(print, "<super: ");
mp_obj_print_helper(print, env, self->type, PRINT_STR); mp_obj_print_helper(print, self->type, PRINT_STR);
print(env, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, env, self->obj, PRINT_STR); mp_obj_print_helper(print, self->obj, PRINT_STR);
print(env, ">"); mp_print_str(print, ">");
} }
STATIC mp_obj_t super_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t super_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {

View File

@ -1,204 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "py/pfenv.h"
#if MICROPY_PY_BUILTINS_FLOAT
#include "py/formatfloat.h"
#endif
int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args) {
int chrs = 0;
for (;;) {
{
const char *f = fmt;
while (*f != '\0' && *f != '%') {
++f; // XXX UTF8 advance char
}
if (f > fmt) {
pfenv->print_strn(pfenv->data, fmt, f - fmt);
chrs += f - fmt;
fmt = f;
}
}
if (*fmt == '\0') {
break;
}
// move past % character
++fmt;
// parse flags, if they exist
int flags = 0;
char fill = ' ';
while (*fmt != '\0') {
if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST;
else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN;
else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN;
else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ;
else if (*fmt == '0') {
flags |= PF_FLAG_PAD_AFTER_SIGN;
fill = '0';
} else break;
++fmt;
}
// parse width, if it exists
int width = 0;
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
width = width * 10 + *fmt - '0';
}
// parse precision, if it exists
int prec = -1;
if (*fmt == '.') {
++fmt;
if (*fmt == '*') {
++fmt;
prec = va_arg(args, int);
} else {
prec = 0;
for (; '0' <= *fmt && *fmt <= '9'; ++fmt) {
prec = prec * 10 + *fmt - '0';
}
}
if (prec < 0) {
prec = 0;
}
}
// parse long specifiers (current not used)
//bool long_arg = false;
if (*fmt == 'l') {
++fmt;
//long_arg = true;
}
if (*fmt == '\0') {
break;
}
switch (*fmt) {
case 'b':
if (va_arg(args, int)) {
chrs += pfenv_print_strn(pfenv, "true", 4, flags, fill, width);
} else {
chrs += pfenv_print_strn(pfenv, "false", 5, flags, fill, width);
}
break;
case 'c':
{
char str = va_arg(args, int);
chrs += pfenv_print_strn(pfenv, &str, 1, flags, fill, width);
break;
}
case 's':
{
const char *str = va_arg(args, const char*);
if (str) {
if (prec < 0) {
prec = strlen(str);
}
chrs += pfenv_print_strn(pfenv, str, prec, flags, fill, width);
} else {
chrs += pfenv_print_strn(pfenv, "(null)", 6, flags, fill, width);
}
break;
}
case 'u':
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 10, 'a', flags, fill, width);
break;
case 'd':
chrs += pfenv_print_int(pfenv, va_arg(args, int), 1, 10, 'a', flags, fill, width);
break;
case 'x':
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'a', flags, fill, width);
break;
case 'X':
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, fill, width);
break;
case 'p':
case 'P': // don't bother to handle upcase for 'P'
chrs += pfenv_print_int(pfenv, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width);
break;
#if MICROPY_PY_BUILTINS_FLOAT
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
{
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
mp_float_t f = va_arg(args, double);
chrs += pfenv_print_float(pfenv, f, *fmt, flags, fill, width, prec);
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
// Currently pfenv_print_float uses snprintf, but snprintf
// itself may be implemented in terms of pfenv_vprintf() for
// some ports. So, for extra caution, this case is handled
// with assert below. Note that currently ports which
// use MICROPY_FLOAT_IMPL_DOUBLE, don't call pfenv_vprintf()
// with float format specifier at all.
// TODO: resolve this completely
assert(0);
//#error Calling pfenv_print_float with double not supported from within printf
#else
#error Unknown MICROPY FLOAT IMPL
#endif
break;
}
#endif
default:
pfenv->print_strn(pfenv->data, fmt, 1);
chrs += 1;
break;
}
++fmt;
}
return chrs;
}
int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = pfenv_vprintf(pfenv, fmt, ap);
va_end(ap);
return ret;
}
void printf_wrapper(void *env, const char *fmt, ...) {
(void)env;
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}

View File

@ -22,6 +22,7 @@ PY_O_BASENAME = \
gc.o \ gc.o \
qstr.o \ qstr.o \
vstr.o \ vstr.o \
mpprint.o \
unicode.o \ unicode.o \
mpz.o \ mpz.o \
lexer.o \ lexer.o \
@ -108,8 +109,6 @@ PY_O_BASENAME = \
showbc.o \ showbc.o \
repl.o \ repl.o \
smallint.o \ smallint.o \
pfenv.o \
pfenv_printf.o \
frozenmod.o \ frozenmod.o \
../extmod/moductypes.o \ ../extmod/moductypes.o \
../extmod/modujson.o \ ../extmod/modujson.o \

View File

@ -63,6 +63,9 @@ extern const qstr mp_binary_op_method_name[];
void mp_init(void); void mp_init(void);
void mp_deinit(void); void mp_deinit(void);
// extra printing method specifically for mp_obj_t's which are integral type
int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);
void mp_arg_check_num(mp_uint_t n_args, mp_uint_t n_kw, mp_uint_t n_args_min, mp_uint_t n_args_max, bool takes_kw); void mp_arg_check_num(mp_uint_t n_args, mp_uint_t n_kw, mp_uint_t n_args_min, mp_uint_t n_args_max, bool takes_kw);
void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);
void mp_arg_parse_all_kw_array(mp_uint_t n_pos, mp_uint_t n_kw, const mp_obj_t *args, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all_kw_array(mp_uint_t n_pos, mp_uint_t n_kw, const mp_obj_t *args, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);

View File

@ -31,6 +31,7 @@
#include "py/mpconfig.h" #include "py/mpconfig.h"
#include "py/misc.h" #include "py/misc.h"
#include "py/mpprint.h"
// returned value is always at least 1 greater than argument // returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8) #define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
@ -65,6 +66,12 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) {
vstr->fixed_buf = true; vstr->fixed_buf = true;
} }
void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) {
vstr_init(vstr, alloc);
print->data = vstr;
print->print_strn = (mp_print_strn_t)vstr_add_strn;
}
void vstr_clear(vstr_t *vstr) { void vstr_clear(vstr_t *vstr) {
if (!vstr->fixed_buf) { if (!vstr->fixed_buf) {
m_del(char, vstr->buf, vstr->alloc); m_del(char, vstr->buf, vstr->alloc);
@ -322,32 +329,6 @@ void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) {
return; return;
} }
while (1) { mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn};
// try to print in the allocated space mp_vprintf(&print, fmt, ap);
// need to make a copy of the va_list because we may call vsnprintf multiple times
size_t size = vstr->alloc - vstr->len;
va_list ap2;
va_copy(ap2, ap);
int n = vsnprintf(vstr->buf + vstr->len, size, fmt, ap2);
va_end(ap2);
// if that worked, return
if (n > -1 && (size_t)n < size) {
vstr->len += n;
return;
}
// else try again with more space
if (n > -1) { // glibc 2.1
// n + 1 is precisely what is needed
if (!vstr_ensure_extra(vstr, n + 1)) {
return;
}
} else { // glibc 2.0
// increase to twice the old size
if (!vstr_ensure_extra(vstr, size * 2)) {
return;
}
}
}
} }

View File

@ -11,7 +11,6 @@
#include "py/stackctrl.h" #include "py/stackctrl.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/repl.h" #include "py/repl.h"
#include "py/pfenv.h"
void do_str(const char *src) { void do_str(const char *src) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
@ -28,7 +27,7 @@ void do_str(const char *src) {
nlr_pop(); nlr_pop();
} else { } else {
// uncaught exception // uncaught exception
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_extern_printf_wrapper, (mp_obj_t)nlr.ret_val);
} }
} }

View File

@ -11,7 +11,6 @@
#include "py/stackctrl.h" #include "py/stackctrl.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/repl.h" #include "py/repl.h"
#include "py/pfenv.h"
#include "tinytest.h" #include "tinytest.h"
#include "tinytest_macros.h" #include "tinytest_macros.h"
@ -39,7 +38,7 @@ inline void do_str(const char *src) {
tinytest_set_test_skipped_(); tinytest_set_test_skipped_();
return; return;
} }
mp_obj_print_exception(printf_wrapper, NULL, exc); mp_obj_print_exception(&mp_extern_printf_wrapper, exc);
tt_abort_msg("Uncaught exception"); tt_abort_msg("Uncaught exception");
} }
end: end:

View File

@ -138,11 +138,11 @@ STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings : adc object (single channel) */ /* Micro Python bindings : adc object (single channel) */
STATIC void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_obj_adc_t *self = self_in; pyb_obj_adc_t *self = self_in;
print(env, "<ADC on "); mp_print_str(print, "<ADC on ");
mp_obj_print_helper(print, env, self->pin_name, PRINT_STR); mp_obj_print_helper(print, self->pin_name, PRINT_STR);
print(env, " channel=%lu>", self->channel); mp_printf(print, " channel=%lu>", self->channel);
} }
/// \classmethod \constructor(pin) /// \classmethod \constructor(pin)

View File

@ -33,7 +33,6 @@
#include "py/objtuple.h" #include "py/objtuple.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/pfenv.h"
#include "bufhelper.h" #include "bufhelper.h"
#include "can.h" #include "can.h"
#include "pybioctl.h" #include "pybioctl.h"
@ -174,12 +173,12 @@ STATIC void can_clearfilter(uint32_t f) {
/******************************************************************************/ /******************************************************************************/
// Micro Python bindings // Micro Python bindings
STATIC void pyb_can_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_can_obj_t *self = self_in; pyb_can_obj_t *self = self_in;
if (!self->is_enabled) { if (!self->is_enabled) {
print(env, "CAN(%u)", self->can_id); mp_printf(print, "CAN(%u)", self->can_id);
} else { } else {
print(env, "CAN(%u, CAN.", self->can_id); mp_printf(print, "CAN(%u, CAN.", self->can_id);
qstr mode; qstr mode;
switch (self->can.Init.Mode) { switch (self->can.Init.Mode) {
case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break;
@ -187,13 +186,13 @@ STATIC void pyb_can_print(void (*print)(void *env, const char *fmt, ...), void *
case CAN_MODE_SILENT: mode = MP_QSTR_SILENT; break; case CAN_MODE_SILENT: mode = MP_QSTR_SILENT; break;
case CAN_MODE_SILENT_LOOPBACK: default: mode = MP_QSTR_SILENT_LOOPBACK; break; case CAN_MODE_SILENT_LOOPBACK: default: mode = MP_QSTR_SILENT_LOOPBACK; break;
} }
print(env, "%s, extframe=", qstr_str(mode)); mp_printf(print, "%s, extframe=", qstr_str(mode));
if (self->extframe) { if (self->extframe) {
mode = MP_QSTR_True; mode = MP_QSTR_True;
} else { } else {
mode = MP_QSTR_False; mode = MP_QSTR_False;
} }
print(env, "%s)", qstr_str(mode)); mp_printf(print, "%s)", qstr_str(mode));
} }
} }
@ -714,7 +713,7 @@ void can_rx_irq_handler(uint can_id, uint fifo_id) {
// Uncaught exception; disable the callback so it doesn't run again. // Uncaught exception; disable the callback so it doesn't run again.
pyb_can_rxcallback(self, MP_OBJ_NEW_SMALL_INT(fifo_id), mp_const_none); pyb_can_rxcallback(self, MP_OBJ_NEW_SMALL_INT(fifo_id), mp_const_none);
printf("uncaught exception in CAN(%u) rx interrupt handler\n", self->can_id); printf("uncaught exception in CAN(%u) rx interrupt handler\n", self->can_id);
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
gc_unlock(); gc_unlock();
} }

View File

@ -31,7 +31,7 @@
#include "py/nlr.h" #include "py/nlr.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/pfenv.h" #include MICROPY_HAL_H
#include "pin.h" #include "pin.h"
#include "extint.h" #include "extint.h"
@ -296,9 +296,9 @@ STATIC mp_obj_t extint_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_
return self; return self;
} }
STATIC void extint_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
extint_obj_t *self = self_in; extint_obj_t *self = self_in;
print(env, "<ExtInt line=%u>", self->line); mp_printf(print, "<ExtInt line=%u>", self->line);
} }
STATIC const mp_map_elem_t extint_locals_dict_table[] = { STATIC const mp_map_elem_t extint_locals_dict_table[] = {
@ -356,7 +356,7 @@ void Handle_EXTI_Irq(uint32_t line) {
*cb = mp_const_none; *cb = mp_const_none;
extint_disable(line); extint_disable(line);
printf("Uncaught exception in ExtInt interrupt handler line %lu\n", line); printf("Uncaught exception in ExtInt interrupt handler line %lu\n", line);
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
gc_unlock(); gc_unlock();
} }

View File

@ -65,8 +65,8 @@ typedef struct _pyb_file_obj_t {
FIL fp; FIL fp;
} pyb_file_obj_t; } pyb_file_obj_t;
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
print(env, "<io.%s %p>", mp_obj_get_type_str(self_in), self_in); mp_printf(print, "<io.%s %p>", mp_obj_get_type_str(self_in), self_in);
} }
STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {

View File

@ -183,7 +183,7 @@ STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
{{&pyb_i2c_type}, &I2CHandle2} {{&pyb_i2c_type}, &I2CHandle2}
}; };
STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in; pyb_i2c_obj_t *self = self_in;
uint i2c_num; uint i2c_num;
@ -191,12 +191,12 @@ STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *
else { i2c_num = 2; } else { i2c_num = 2; }
if (self->i2c->State == HAL_I2C_STATE_RESET) { if (self->i2c->State == HAL_I2C_STATE_RESET) {
print(env, "I2C(%u)", i2c_num); mp_printf(print, "I2C(%u)", i2c_num);
} else { } else {
if (in_master_mode(self)) { if (in_master_mode(self)) {
print(env, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, self->i2c->Init.ClockSpeed); mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, self->i2c->Init.ClockSpeed);
} else { } else {
print(env, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f); mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f);
} }
} }
} }

View File

@ -210,9 +210,9 @@ void led_debug(int n, int delay) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in; pyb_led_obj_t *self = self_in;
print(env, "LED(%lu)", self->led_id); mp_printf(print, "LED(%lu)", self->led_id);
} }
/// \classmethod \constructor(id) /// \classmethod \constructor(id)

View File

@ -68,9 +68,9 @@ typedef struct _stm_mem_obj_t {
uint32_t elem_size; // in bytes uint32_t elem_size; // in bytes
} stm_mem_obj_t; } stm_mem_obj_t;
STATIC void stm_mem_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void stm_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
stm_mem_obj_t *self = self_in; stm_mem_obj_t *self = self_in;
print(env, "<%u-bit memory>", 8 * self->elem_size); mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
} }
STATIC mp_obj_t stm_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { STATIC mp_obj_t stm_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {

View File

@ -183,6 +183,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t; typedef long mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// We have inlined IRQ functions for efficiency (they are generally // We have inlined IRQ functions for efficiency (they are generally
// 1 machine instruction). // 1 machine instruction).
// //

View File

@ -180,17 +180,17 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
/// \method __str__() /// \method __str__()
/// Return a string describing the pin object. /// Return a string describing the pin object.
STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_obj_t *self = self_in; pin_obj_t *self = self_in;
// pin name // pin name
print(env, "Pin(Pin.cpu.%s, mode=Pin.", qstr_str(self->name)); mp_printf(print, "Pin(Pin.cpu.%s, mode=Pin.", qstr_str(self->name));
uint32_t mode = pin_get_mode(self); uint32_t mode = pin_get_mode(self);
if (mode == GPIO_MODE_ANALOG) { if (mode == GPIO_MODE_ANALOG) {
// analog // analog
print(env, "ANALOG)"); mp_print_str(print, "ANALOG)");
} else { } else {
// IO mode // IO mode
@ -210,7 +210,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
mode_qst = MP_QSTR_AF_OD; mode_qst = MP_QSTR_AF_OD;
} }
} }
print(env, qstr_str(mode_qst)); // safe because mode_qst has no formating chars mp_print_str(print, qstr_str(mode_qst));
// pull mode // pull mode
qstr pull_qst = MP_QSTR_NULL; qstr pull_qst = MP_QSTR_NULL;
@ -221,7 +221,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
pull_qst = MP_QSTR_PULL_DOWN; pull_qst = MP_QSTR_PULL_DOWN;
} }
if (pull_qst != MP_QSTR_NULL) { if (pull_qst != MP_QSTR_NULL) {
print(env, ", pull=Pin.%s", qstr_str(pull_qst)); mp_printf(print, ", pull=Pin.%s", qstr_str(pull_qst));
} }
// AF mode // AF mode
@ -229,12 +229,12 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
mp_uint_t af_idx = pin_get_af(self); mp_uint_t af_idx = pin_get_af(self);
const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx); const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx);
if (af_obj == NULL) { if (af_obj == NULL) {
print(env, ", af=%d)", af_idx); mp_printf(print, ", af=%d)", af_idx);
} else { } else {
print(env, ", af=Pin.%s)", qstr_str(af_obj->name)); mp_printf(print, ", af=Pin.%s)", qstr_str(af_obj->name));
} }
} else { } else {
print(env, ")"); mp_print_str(print, ")");
} }
} }
} }
@ -616,9 +616,9 @@ const mp_obj_type_t pin_type = {
/// \method __str__() /// \method __str__()
/// Return a string describing the alternate function. /// Return a string describing the alternate function.
STATIC void pin_af_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pin_af_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_af_obj_t *self = self_in; pin_af_obj_t *self = self_in;
print(env, "Pin.%s", qstr_str(self->name)); mp_printf(print, "Pin.%s", qstr_str(self->name));
} }
/// \method index() /// \method index()

View File

@ -31,9 +31,9 @@
#include MICROPY_HAL_H #include MICROPY_HAL_H
#include "pin.h" #include "pin.h"
STATIC void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_named_pins_obj_t *self = self_in; pin_named_pins_obj_t *self = self_in;
print(env, "<Pin.%s>", qstr_str(self->name)); mp_printf(print, "<Pin.%s>", qstr_str(self->name));
} }
const mp_obj_type_t pin_cpu_pins_obj_type = { const mp_obj_type_t pin_cpu_pins_obj_type = {

View File

@ -29,7 +29,6 @@
#include <stdarg.h> #include <stdarg.h>
#include "py/obj.h" #include "py/obj.h"
#include "py/pfenv.h"
#ifdef MICROPY_HAL_H #ifdef MICROPY_HAL_H
#include MICROPY_HAL_H #include MICROPY_HAL_H
#endif #endif
@ -38,22 +37,16 @@
#include "py/formatfloat.h" #include "py/formatfloat.h"
#endif #endif
STATIC void stdout_print_strn(void *dummy_env, const char *str, mp_uint_t len) {
mp_hal_stdout_tx_strn_cooked(str, len);
}
STATIC const pfenv_t pfenv_stdout = {0, stdout_print_strn};
int printf(const char *fmt, ...) { int printf(const char *fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap); int ret = mp_vprintf(&mp_plat_print, fmt, ap);
va_end(ap); va_end(ap);
return ret; return ret;
} }
int vprintf(const char *fmt, va_list ap) { int vprintf(const char *fmt, va_list ap) {
return pfenv_vprintf(&pfenv_stdout, fmt, ap); return mp_vprintf(&mp_plat_print, fmt, ap);
} }
#if MICROPY_DEBUG_PRINTERS #if MICROPY_DEBUG_PRINTERS
@ -62,7 +55,7 @@ mp_uint_t mp_verbose_flag = 1;
int DEBUG_printf(const char *fmt, ...) { int DEBUG_printf(const char *fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap); int ret = mp_vprintf(&mp_plat_print, fmt, ap);
va_end(ap); va_end(ap);
return ret; return ret;
} }
@ -71,47 +64,43 @@ int DEBUG_printf(const char *fmt, ...) {
// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a') // need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
int putchar(int c) { int putchar(int c) {
char chr = c; char chr = c;
stdout_print_strn(0, &chr, 1); mp_hal_stdout_tx_strn_cooked(&chr, 1);
return chr; return chr;
} }
// need this because gcc optimises printf("string\n") -> puts("string") // need this because gcc optimises printf("string\n") -> puts("string")
int puts(const char *s) { int puts(const char *s) {
stdout_print_strn(0, s, strlen(s)); mp_hal_stdout_tx_strn_cooked(s, strlen(s));
char chr = '\n'; char chr = '\n';
stdout_print_strn(0, &chr, 1); mp_hal_stdout_tx_strn_cooked(&chr, 1);
return 1; return 1;
} }
typedef struct _strn_pfenv_t { typedef struct _strn_print_env_t {
char *cur; char *cur;
size_t remain; size_t remain;
} strn_pfenv_t; } strn_print_env_t;
STATIC void strn_print_strn(void *data, const char *str, mp_uint_t len) { STATIC void strn_print_strn(void *data, const char *str, mp_uint_t len) {
strn_pfenv_t *strn_pfenv = data; strn_print_env_t *strn_print_env = data;
if (len > strn_pfenv->remain) { if (len > strn_print_env->remain) {
len = strn_pfenv->remain; len = strn_print_env->remain;
} }
memcpy(strn_pfenv->cur, str, len); memcpy(strn_print_env->cur, str, len);
strn_pfenv->cur += len; strn_print_env->cur += len;
strn_pfenv->remain -= len; strn_print_env->remain -= len;
} }
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
strn_pfenv_t strn_pfenv; strn_print_env_t strn_print_env = {str, size};
strn_pfenv.cur = str; mp_print_t print = {&strn_print_env, strn_print_strn};
strn_pfenv.remain = size; int len = mp_vprintf(&print, fmt, ap);
pfenv_t pfenv;
pfenv.data = &strn_pfenv;
pfenv.print_strn = strn_print_strn;
int len = pfenv_vprintf(&pfenv, fmt, ap);
// add terminating null byte // add terminating null byte
if (size > 0) { if (size > 0) {
if (strn_pfenv.remain == 0) { if (strn_print_env.remain == 0) {
strn_pfenv.cur[-1] = 0; strn_print_env.cur[-1] = 0;
} else { } else {
strn_pfenv.cur[0] = 0; strn_print_env.cur[0] = 0;
} }
} }
return len; return len;

View File

@ -48,9 +48,9 @@ typedef struct _pyb_stdio_obj_t {
int fd; int fd;
} pyb_stdio_obj_t; } pyb_stdio_obj_t;
void stdio_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_stdio_obj_t *self = self_in; pyb_stdio_obj_t *self = self_in;
print(env, "<io.FileIO %d>", self->fd); mp_printf(print, "<io.FileIO %d>", self->fd);
} }
STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {

View File

@ -33,7 +33,6 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/repl.h" #include "py/repl.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/pfenv.h"
#ifdef MICROPY_HAL_H #ifdef MICROPY_HAL_H
#include MICROPY_HAL_H #include MICROPY_HAL_H
#endif #endif
@ -87,7 +86,7 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
// at the moment, the value of SystemExit is unused // at the moment, the value of SystemExit is unused
ret = PYEXEC_FORCED_EXIT; ret = PYEXEC_FORCED_EXIT;
} else { } else {
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
ret = 0; ret = 0;
} }
} }

View File

@ -178,9 +178,9 @@ STATIC mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) {
MP_DEFINE_CONST_FUN_OBJ_2(pyb_pwm_set_obj, pyb_pwm_set); MP_DEFINE_CONST_FUN_OBJ_2(pyb_pwm_set_obj, pyb_pwm_set);
STATIC void pyb_servo_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_servo_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_servo_obj_t *self = self_in; pyb_servo_obj_t *self = self_in;
print(env, "<Servo %lu at %luus>", self->servo_id, 10 * self->pulse_cur); mp_printf(print, "<Servo %lu at %luus>", self->servo_id, 10 * self->pulse_cur);
} }
/// \classmethod \constructor(id) /// \classmethod \constructor(id)

View File

@ -335,7 +335,7 @@ SPI_HandleTypeDef *spi_get_handle(mp_obj_t o) {
return self->spi; return self->spi;
} }
STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in; pyb_spi_obj_t *self = self_in;
uint spi_num; uint spi_num;
@ -344,7 +344,7 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
else { spi_num = 3; } else { spi_num = 3; }
if (self->spi->State == HAL_SPI_STATE_RESET) { if (self->spi->State == HAL_SPI_STATE_RESET) {
print(env, "SPI(%u)", spi_num); mp_printf(print, "SPI(%u)", spi_num);
} else { } else {
if (self->spi->Init.Mode == SPI_MODE_MASTER) { if (self->spi->Init.Mode == SPI_MODE_MASTER) {
// compute baudrate // compute baudrate
@ -358,15 +358,15 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
} }
uint log_prescaler = (self->spi->Init.BaudRatePrescaler >> 3) + 1; uint log_prescaler = (self->spi->Init.BaudRatePrescaler >> 3) + 1;
uint baudrate = spi_clock >> log_prescaler; uint baudrate = spi_clock >> log_prescaler;
print(env, "SPI(%u, SPI.MASTER, baudrate=%u, prescaler=%u", spi_num, baudrate, 1 << log_prescaler); mp_printf(print, "SPI(%u, SPI.MASTER, baudrate=%u, prescaler=%u", spi_num, baudrate, 1 << log_prescaler);
} else { } else {
print(env, "SPI(%u, SPI.SLAVE", spi_num); mp_printf(print, "SPI(%u, SPI.SLAVE", spi_num);
} }
print(env, ", polarity=%u, phase=%u, bits=%u", self->spi->Init.CLKPolarity == SPI_POLARITY_LOW ? 0 : 1, self->spi->Init.CLKPhase == SPI_PHASE_1EDGE ? 0 : 1, self->spi->Init.DataSize == SPI_DATASIZE_8BIT ? 8 : 16); mp_printf(print, ", polarity=%u, phase=%u, bits=%u", self->spi->Init.CLKPolarity == SPI_POLARITY_LOW ? 0 : 1, self->spi->Init.CLKPhase == SPI_PHASE_1EDGE ? 0 : 1, self->spi->Init.DataSize == SPI_DATASIZE_8BIT ? 8 : 16);
if (self->spi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLED) { if (self->spi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLED) {
print(env, ", crc=0x%x", self->spi->Init.CRCPolynomial); mp_printf(print, ", crc=0x%x", self->spi->Init.CRCPolynomial);
} }
print(env, ")"); mp_print_str(print, ")");
} }
} }

View File

@ -35,7 +35,7 @@
#include "py/nlr.h" #include "py/nlr.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/pfenv.h" #include MICROPY_HAL_H
#include "timer.h" #include "timer.h"
#include "servo.h" #include "servo.h"
#include "pin.h" #include "pin.h"
@ -468,17 +468,17 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks) {
HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig); HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig);
} }
STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_obj_t *self = self_in; pyb_timer_obj_t *self = self_in;
if (self->tim.State == HAL_TIM_STATE_RESET) { if (self->tim.State == HAL_TIM_STATE_RESET) {
print(env, "Timer(%u)", self->tim_id); mp_printf(print, "Timer(%u)", self->tim_id);
} else { } else {
uint32_t prescaler = self->tim.Instance->PSC & 0xffff; uint32_t prescaler = self->tim.Instance->PSC & 0xffff;
uint32_t period = __HAL_TIM_GetAutoreload(&self->tim) & TIMER_CNT_MASK(self); uint32_t period = __HAL_TIM_GetAutoreload(&self->tim) & TIMER_CNT_MASK(self);
// for efficiency, we compute and print freq as an int (not a float) // for efficiency, we compute and print freq as an int (not a float)
uint32_t freq = timer_get_source_freq(self->tim_id) / ((prescaler + 1) * (period + 1)); uint32_t freq = timer_get_source_freq(self->tim_id) / ((prescaler + 1) * (period + 1));
print(env, "Timer(%u, freq=%u, prescaler=%u, period=%u, mode=%s, div=%u", mp_printf(print, "Timer(%u, freq=%u, prescaler=%u, period=%u, mode=%s, div=%u",
self->tim_id, self->tim_id,
freq, freq,
prescaler, prescaler,
@ -488,9 +488,10 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 : self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 :
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1); self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1);
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) { if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) {
print(env, ", deadtime=%u", compute_ticks_from_dtg(self->tim.Instance->BDTR & TIM_BDTR_DTG)); mp_printf(print, ", deadtime=%u",
compute_ticks_from_dtg(self->tim.Instance->BDTR & TIM_BDTR_DTG));
} }
print(env, ")"); mp_print_str(print, ")");
} }
} }
@ -1166,10 +1167,10 @@ const mp_obj_type_t pyb_timer_type = {
/// Timer channels are used to generate/capture a signal using a timer. /// Timer channels are used to generate/capture a signal using a timer.
/// ///
/// TimerChannel objects are created using the Timer.channel() method. /// TimerChannel objects are created using the Timer.channel() method.
STATIC void pyb_timer_channel_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_channel_obj_t *self = self_in; pyb_timer_channel_obj_t *self = self_in;
print(env, "TimerChannel(timer=%u, channel=%u, mode=%s)", mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)",
self->timer->tim_id, self->timer->tim_id,
self->channel, self->channel,
qstr_str(channel_mode_info[self->mode].name)); qstr_str(channel_mode_info[self->mode].name));
@ -1308,7 +1309,7 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o
} else { } else {
printf("uncaught exception in Timer(%u) channel %u interrupt handler\n", tim->tim_id, channel); printf("uncaught exception in Timer(%u) channel %u interrupt handler\n", tim->tim_id, channel);
} }
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
gc_unlock(); gc_unlock();
} }

View File

@ -330,23 +330,23 @@ void uart_irq_handler(mp_uint_t uart_id) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = self_in; pyb_uart_obj_t *self = self_in;
if (!self->is_enabled) { if (!self->is_enabled) {
print(env, "UART(%u)", self->uart_id); mp_printf(print, "UART(%u)", self->uart_id);
} else { } else {
mp_int_t bits = (self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9); mp_int_t bits = (self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9);
if (self->uart.Init.Parity != UART_PARITY_NONE) { if (self->uart.Init.Parity != UART_PARITY_NONE) {
bits -= 1; bits -= 1;
} }
print(env, "UART(%u, baudrate=%u, bits=%u, parity=", mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=",
self->uart_id, self->uart.Init.BaudRate, bits); self->uart_id, self->uart.Init.BaudRate, bits);
if (self->uart.Init.Parity == UART_PARITY_NONE) { if (self->uart.Init.Parity == UART_PARITY_NONE) {
print(env, "None"); mp_print_str(print, "None");
} else { } else {
print(env, "%u", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); mp_printf(print, "%u", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1);
} }
print(env, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u)", mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u)",
self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2, self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2,
self->timeout, self->timeout_char, self->read_buf_len); self->timeout, self->timeout_char, self->read_buf_len);
} }

View File

@ -314,8 +314,8 @@ typedef struct _pyb_usb_vcp_obj_t {
STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}}; STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}};
STATIC void pyb_usb_vcp_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
print(env, "USB_VCP()"); mp_print_str(print, "USB_VCP()");
} }
/// \classmethod \constructor() /// \classmethod \constructor()

View File

@ -75,8 +75,8 @@ typedef struct _pyb_switch_obj_t {
STATIC const pyb_switch_obj_t pyb_switch_obj = {{&pyb_switch_type}}; STATIC const pyb_switch_obj_t pyb_switch_obj = {{&pyb_switch_type}};
void pyb_switch_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
print(env, "Switch()"); mp_print_str(print, "Switch()");
} }
/// \classmethod \constructor() /// \classmethod \constructor()

View File

@ -83,10 +83,10 @@ void led_toggle(pyb_led_t led) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { void led_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_led_obj_t *self = self_in; pyb_led_obj_t *self = self_in;
(void)kind; (void)kind;
print(env, "<LED %lu>", self->led_id); mp_printf(print, "<LED %lu>", self->led_id);
} }
STATIC mp_obj_t led_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { STATIC mp_obj_t led_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {

View File

@ -66,6 +66,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t; typedef long mp_off_t;
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// We have inlined IRQ functions for efficiency (they are generally // We have inlined IRQ functions for efficiency (they are generally
// 1 machine instruction). // 1 machine instruction).
// //

View File

@ -31,7 +31,6 @@
#include "py/nlr.h" #include "py/nlr.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/pfenv.h"
#include "py/gc.h" #include "py/gc.h"
#include MICROPY_HAL_H #include MICROPY_HAL_H
#include "pin.h" #include "pin.h"
@ -188,13 +187,13 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
#endif #endif
} }
STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_obj_t *self = self_in; pyb_timer_obj_t *self = self_in;
if (self->ftm.State == HAL_FTM_STATE_RESET) { if (self->ftm.State == HAL_FTM_STATE_RESET) {
print(env, "Timer(%u)", self->tim_id); mp_printf(print, "Timer(%u)", self->tim_id);
} else { } else {
print(env, "Timer(%u, prescaler=%u, period=%u, mode=%s)", mp_printf(print, "Timer(%u, prescaler=%u, period=%u, mode=%s)",
self->tim_id, self->tim_id,
1 << (self->ftm.Instance->SC & 7), 1 << (self->ftm.Instance->SC & 7),
self->ftm.Instance->MOD & 0xffff, self->ftm.Instance->MOD & 0xffff,
@ -752,10 +751,10 @@ const mp_obj_type_t pyb_timer_type = {
/// Timer channels are used to generate/capture a signal using a timer. /// Timer channels are used to generate/capture a signal using a timer.
/// ///
/// TimerChannel objects are created using the Timer.channel() method. /// TimerChannel objects are created using the Timer.channel() method.
STATIC void pyb_timer_channel_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_channel_obj_t *self = self_in; pyb_timer_channel_obj_t *self = self_in;
print(env, "TimerChannel(timer=%u, channel=%u, mode=%s)", mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)",
self->timer->tim_id, self->timer->tim_id,
self->channel, self->channel,
qstr_str(channel_mode_info[self->mode].name)); qstr_str(channel_mode_info[self->mode].name));
@ -913,7 +912,7 @@ STATIC bool ftm_handle_irq_callback(pyb_timer_obj_t *self, mp_uint_t channel, mp
printf("Uncaught exception in Timer(" UINT_FMT ") channel " printf("Uncaught exception in Timer(" UINT_FMT ") channel "
UINT_FMT " interrupt handler\n", self->tim_id, channel); UINT_FMT " interrupt handler\n", self->tim_id, channel);
} }
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
} }
gc_unlock(); gc_unlock();
return handled; return handled;

View File

@ -224,20 +224,20 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
/******************************************************************************/ /******************************************************************************/
/* Micro Python bindings */ /* Micro Python bindings */
STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = self_in; pyb_uart_obj_t *self = self_in;
if (!self->is_enabled) { if (!self->is_enabled) {
print(env, "UART(%lu)", self->uart_id); mp_printf(print, "UART(%lu)", self->uart_id);
} else { } else {
#if 0 #if 0
print(env, "UART(%lu, baudrate=%u, bits=%u, stop=%u", mp_printf(print, "UART(%lu, baudrate=%u, bits=%u, stop=%u",
self->uart_id, self->uart.Init.BaudRate, self->uart_id, self->uart.Init.BaudRate,
self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9, self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9,
self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2); self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2);
if (self->uart.Init.Parity == UART_PARITY_NONE) { if (self->uart.Init.Parity == UART_PARITY_NONE) {
print(env, ", parity=None)"); mp_print_str(print, ", parity=None)");
} else { } else {
print(env, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); mp_printf(print, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1);
} }
#endif #endif
} }

View File

@ -32,7 +32,6 @@
#include "py/nlr.h" #include "py/nlr.h"
#include "py/compile.h" #include "py/compile.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/pfenv.h"
void do_file(const char *file) { void do_file(const char *file) {
mp_lexer_t *lex = mp_lexer_new_from_file(file); mp_lexer_t *lex = mp_lexer_new_from_file(file);

View File

@ -60,10 +60,10 @@ STATIC void check_fd_is_open(const mp_obj_fdfile_t *o) {
extern const mp_obj_type_t mp_type_fileio; extern const mp_obj_type_t mp_type_fileio;
extern const mp_obj_type_t mp_type_textio; extern const mp_obj_type_t mp_type_textio;
STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_fdfile_t *self = self_in; mp_obj_fdfile_t *self = self_in;
print(env, "<io.%s %d>", mp_obj_get_type_str(self), self->fd); mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self), self->fd);
} }
STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {

View File

@ -43,7 +43,6 @@
#include "py/repl.h" #include "py/repl.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/stackctrl.h" #include "py/stackctrl.h"
#include "py/pfenv.h"
#include "genhdr/py-version.h" #include "genhdr/py-version.h"
#include "input.h" #include "input.h"
@ -91,7 +90,7 @@ STATIC int handle_uncaught_exception(mp_obj_t exc) {
} }
// Report all other exceptions // Report all other exceptions
mp_obj_print_exception(printf_wrapper, NULL, exc); mp_obj_print_exception(&mp_plat_print, exc);
return 1; return 1;
} }

View File

@ -167,10 +167,10 @@ STATIC mp_obj_t return_ffi_value(ffi_arg val, char type)
// FFI module // FFI module
STATIC void ffimod_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_ffimod_t *self = self_in; mp_obj_ffimod_t *self = self_in;
print(env, "<ffimod %p>", self->handle); mp_printf(print, "<ffimod %p>", self->handle);
} }
STATIC mp_obj_t ffimod_close(mp_obj_t self_in) { STATIC mp_obj_t ffimod_close(mp_obj_t self_in) {
@ -338,10 +338,10 @@ STATIC const mp_obj_type_t ffimod_type = {
// FFI function // FFI function
STATIC void ffifunc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_ffifunc_t *self = self_in; mp_obj_ffifunc_t *self = self_in;
print(env, "<ffifunc %p>", self->func); mp_printf(print, "<ffifunc %p>", self->func);
} }
STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@ -410,10 +410,10 @@ STATIC const mp_obj_type_t ffifunc_type = {
// FFI callback for Python function // FFI callback for Python function
STATIC void fficallback_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_fficallback_t *self = self_in; mp_obj_fficallback_t *self = self_in;
print(env, "<fficallback %p>", self->func); mp_printf(print, "<fficallback %p>", self->func);
} }
STATIC const mp_obj_type_t fficallback_type = { STATIC const mp_obj_type_t fficallback_type = {
@ -424,11 +424,11 @@ STATIC const mp_obj_type_t fficallback_type = {
// FFI variable // FFI variable
STATIC void ffivar_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_ffivar_t *self = self_in; mp_obj_ffivar_t *self = self_in;
// Variable value printed as cast to int // Variable value printed as cast to int
print(env, "<ffivar @%p: 0x%x>", self->var, *(int*)self->var); mp_printf(print, "<ffivar @%p: 0x%x>", self->var, *(int*)self->var);
} }
STATIC mp_obj_t ffivar_get(mp_obj_t self_in) { STATIC mp_obj_t ffivar_get(mp_obj_t self_in) {

View File

@ -82,10 +82,10 @@ STATIC mp_obj_socket_t *socket_new(int fd) {
} }
STATIC void socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind; (void)kind;
mp_obj_socket_t *self = self_in; mp_obj_socket_t *self = self_in;
print(env, "<_socket %d>", self->fd); mp_printf(print, "<_socket %d>", self->fd);
} }
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {

View File

@ -170,6 +170,8 @@ 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_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) #define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size)
#define MP_PLAT_PRINT_STRN(str, len) fwrite(str, 1, len, stdout)
extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj;
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \ #define MICROPY_PORT_BUILTINS \

View File

@ -115,6 +115,8 @@ typedef long mp_off_t;
typedef void *machine_ptr_t; // must be of pointer size typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size
#define MP_PLAT_PRINT_STRN(str, len) fwrite(str, 1, len, stdout)
extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj;
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \ #define MICROPY_PORT_BUILTINS \