From 7f9d1d6ab923096582622b700bedb6a571518eac Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 Apr 2015 23:56:15 +0100 Subject: [PATCH] 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. --- bare-arm/main.c | 3 +- cc3200/misc/pin_named_pins.c | 4 +- cc3200/mods/modwlan.c | 10 +- cc3200/mods/pybadc.c | 4 +- cc3200/mods/pybi2c.c | 6 +- cc3200/mods/pybpin.c | 10 +- cc3200/mods/pybspi.c | 6 +- cc3200/mods/pybuart.c | 20 ++-- cc3200/mpconfigport.h | 3 + esp8266/modesp.c | 3 +- esp8266/modpybpin.c | 4 +- esp8266/mpconfigport.h | 3 + extmod/moductypes.c | 4 +- extmod/modujson.c | 5 +- extmod/modure.c | 8 +- minimal/main.c | 3 +- minimal/mpconfigport.h | 3 + pic16bit/modpybled.c | 4 +- pic16bit/modpybswitch.c | 4 +- pic16bit/mpconfigport.h | 3 + py/misc.h | 2 + py/modbuiltins.c | 18 ++- py/modsys.c | 9 +- py/mpconfig.h | 7 +- py/{pfenv.c => mpprint.c} | 224 +++++++++++++++++++++++++++++++---- py/{pfenv.h => mpprint.h} | 40 ++++--- py/obj.c | 36 +++--- py/obj.h | 9 +- py/objarray.c | 18 +-- py/objbool.c | 10 +- py/objboundmeth.c | 12 +- py/objcell.c | 10 +- py/objclosure.c | 16 +-- py/objcomplex.c | 18 +-- py/objdict.c | 30 ++--- py/objexcept.c | 12 +- py/objfloat.c | 10 +- py/objfun.c | 4 +- py/objgenerator.c | 4 +- py/objint.c | 4 +- py/objint.h | 2 +- py/objlist.c | 10 +- py/objmodule.c | 6 +- py/objnamedtuple.c | 12 +- py/objnone.c | 6 +- py/objrange.c | 8 +- py/objset.c | 19 ++- py/objslice.c | 20 ++-- py/objstr.c | 110 +++++++++-------- py/objstr.h | 2 +- py/objstringio.c | 4 +- py/objstrunicode.c | 33 +++--- py/objtuple.c | 16 +-- py/objtuple.h | 2 +- py/objtype.c | 28 ++--- py/pfenv_printf.c | 204 ------------------------------- py/py.mk | 3 +- py/runtime.h | 3 + py/vstr.c | 37 ++---- qemu-arm/main.c | 3 +- qemu-arm/test_main.c | 3 +- stmhal/adc.c | 8 +- stmhal/can.c | 13 +- stmhal/extint.c | 8 +- stmhal/file.c | 4 +- stmhal/i2c.c | 8 +- stmhal/led.c | 4 +- stmhal/modstm.c | 4 +- stmhal/mpconfigport.h | 3 + stmhal/pin.c | 20 ++-- stmhal/pin_named_pins.c | 4 +- stmhal/printf.c | 51 ++++---- stmhal/pybstdio.c | 4 +- stmhal/pyexec.c | 3 +- stmhal/servo.c | 4 +- stmhal/spi.c | 14 +-- stmhal/timer.c | 19 +-- stmhal/uart.c | 12 +- stmhal/usb.c | 4 +- stmhal/usrsw.c | 4 +- teensy/led.c | 4 +- teensy/mpconfigport.h | 3 + teensy/timer.c | 13 +- teensy/uart.c | 10 +- unix-cpy/main.c | 1 - unix/file.c | 4 +- unix/main.c | 3 +- unix/modffi.c | 16 +-- unix/modsocket.c | 4 +- unix/mpconfigport.h | 2 + windows/mpconfigport.h | 2 + 91 files changed, 671 insertions(+), 716 deletions(-) rename py/{pfenv.c => mpprint.c} (58%) rename py/{pfenv.h => mpprint.h} (66%) delete mode 100644 py/pfenv_printf.c diff --git a/bare-arm/main.c b/bare-arm/main.c index 61a43beec1..ca32dc459d 100644 --- a/bare-arm/main.c +++ b/bare-arm/main.c @@ -6,7 +6,6 @@ #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" -#include "py/pfenv.h" 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); @@ -23,7 +22,7 @@ void do_str(const char *src) { nlr_pop(); } else { // 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); } } diff --git a/cc3200/misc/pin_named_pins.c b/cc3200/misc/pin_named_pins.c index 590e013d44..a3e99757e3 100644 --- a/cc3200/misc/pin_named_pins.c +++ b/cc3200/misc/pin_named_pins.c @@ -37,9 +37,9 @@ #include "pybpin.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; - print(env, "", qstr_str(self->name)); + mp_printf(print, "", qstr_str(self->name)); } const mp_obj_type_t pin_cpu_pins_obj_type = { diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index 9a7a86775e..cf7519a0dd 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -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; } -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; - print(env, "mode); + mp_printf(print, "mode); // only print the bssid if in station mode 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]); } 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) diff --git a/cc3200/mods/pybadc.c b/cc3200/mods/pybadc.c index c377d51089..ae7de73eb9 100644 --- a/cc3200/mods/pybadc.c +++ b/cc3200/mods/pybadc.c @@ -100,9 +100,9 @@ STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS]; /******************************************************************************/ /* 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; - print(env, "", self->num); + mp_printf(print, "", self->num); } /// \classmethod \constructor(channel) diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c index 6fd58b0c07..79a425d217 100644 --- a/cc3200/mods/pybi2c.c +++ b/cc3200/mods/pybi2c.c @@ -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; } -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; if (self->baudrate > 0) { - print(env, ")", self->baudrate); + mp_printf(print, ")", self->baudrate); } else { - print(env, ""); + mp_print_str(print, ""); } } diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index b8db319419..dbfc34866e 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -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() /// 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; uint32_t af = MAP_PinModeGet(self->pin_num); uint32_t type = pin_get_type(self); uint32_t strength = pin_get_strenght(self); // pin name - print(env, "name), af); + mp_printf(print, "name), af); if (af == PIN_MODE_0) { // IO mode @@ -447,7 +447,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, } else { 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 @@ -465,7 +465,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, } else { 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 qstr str_qst; @@ -476,7 +476,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, } else { 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, ...) diff --git a/cc3200/mods/pybspi.c b/cc3200/mods/pybspi.c index ceddd22804..bcd673225d 100644 --- a/cc3200/mods/pybspi.c +++ b/cc3200/mods/pybspi.c @@ -163,15 +163,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda /******************************************************************************/ /* 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; if (self->baudrate > 0) { - print(env, "", + mp_printf(print, "", self->baudrate, self->config, self->submode, (self->wlen * 8)); } else { - print(env, ""); + mp_print_str(print, ""); } } diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c index 8b998872a5..9465cef080 100644 --- a/cc3200/mods/pybuart.c +++ b/cc3200/mods/pybuart.c @@ -312,37 +312,37 @@ STATIC void uart_callback_disable (mp_obj_t self_in) { /******************************************************************************/ /* 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; if (self->baudrate > 0) { - print(env, "config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) { - print(env, ", parity=None"); + mp_print_str(print, ", parity=None"); } 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->timeout, self->timeout_char, self->read_buf_len); } else { - print(env, "", self->uart_id); + mp_printf(print, "", self->uart_id); } } diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h index c5caa21209..fa1207d745 100644 --- a/cc3200/mpconfigport.h +++ b/cc3200/mpconfigport.h @@ -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 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_END_ATOMIC_SECTION(state) enable_irq(state) diff --git a/esp8266/modesp.c b/esp8266/modesp.c index 29ef42ab2a..3b5a0b7d74 100644 --- a/esp8266/modesp.c +++ b/esp8266/modesp.c @@ -32,7 +32,6 @@ #include "py/obj.h" #include "py/gc.h" #include "py/runtime.h" -#include "py/pfenv.h" #include MICROPY_HAL_H #include "queue.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) { return mp_call_function_1(fun, arg); } 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; } } diff --git a/esp8266/modpybpin.c b/esp8266/modpybpin.c index 0089e71ab2..8b09c7f655 100644 --- a/esp8266/modpybpin.c +++ b/esp8266/modpybpin.c @@ -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}, }; -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; // 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) diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 7e7f0fdbac..dcd9407f82 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -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 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 extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; #define MICROPY_PORT_BUILTINS \ diff --git a/extmod/moductypes.c b/extmod/moductypes.c index f9f0ca79bc..dff8abd8d4 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -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; } -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; mp_obj_uctypes_struct_t *self = self_in; const char *typen = "unk"; @@ -154,7 +154,7 @@ STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...), } else { typen = "ERROR"; } - print(env, "", typen, self->addr); + mp_printf(print, "", typen, self->addr); } // Get size of any type descriptor diff --git a/extmod/modujson.c b/extmod/modujson.c index 747a86ac6a..d6095cbb8b 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -35,8 +35,9 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { vstr_t vstr; - vstr_init(&vstr, 8); - mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, obj, PRINT_JSON); + mp_print_t print; + 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); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); diff --git a/extmod/modure.c b/extmod/modure.c index 66fb51aefd..9bc72add21 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -51,10 +51,10 @@ typedef struct _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; mp_obj_match_t *self = self_in; - print(env, "", self->num_matches); + mp_printf(print, "", self->num_matches); } 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, }; -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; mp_obj_re_t *self = self_in; - print(env, "", self); + mp_printf(print, "", self); } STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { diff --git a/minimal/main.c b/minimal/main.c index 1d600d5847..29b5af1af7 100644 --- a/minimal/main.c +++ b/minimal/main.c @@ -6,7 +6,6 @@ #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" -#include "py/pfenv.h" #include "py/gc.h" #include "pyexec.h" @@ -26,7 +25,7 @@ void do_str(const char *src) { nlr_pop(); } else { // 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); } } diff --git a/minimal/mpconfigport.h b/minimal/mpconfigport.h index 02ad5bd627..b08bdf8b7d 100644 --- a/minimal/mpconfigport.h +++ b/minimal/mpconfigport.h @@ -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 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 extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; #define MICROPY_PORT_BUILTINS \ diff --git a/pic16bit/modpybled.c b/pic16bit/modpybled.c index c44bb1d243..1610dc5680 100644 --- a/pic16bit/modpybled.c +++ b/pic16bit/modpybled.c @@ -41,9 +41,9 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = { #define NUM_LED MP_ARRAY_SIZE(pyb_led_obj) #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; - 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) { diff --git a/pic16bit/modpybswitch.c b/pic16bit/modpybswitch.c index f5047b78f4..901e478cc9 100644 --- a/pic16bit/modpybswitch.c +++ b/pic16bit/modpybswitch.c @@ -40,9 +40,9 @@ STATIC const pyb_switch_obj_t pyb_switch_obj[] = { #define NUM_SWITCH MP_ARRAY_SIZE(pyb_switch_obj) #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; - 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) { diff --git a/pic16bit/mpconfigport.h b/pic16bit/mpconfigport.h index 06ed6669ea..d58401a905 100644 --- a/pic16bit/mpconfigport.h +++ b/pic16bit/mpconfigport.h @@ -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 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 extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; #define MICROPY_PORT_BUILTINS \ diff --git a/py/misc.h b/py/misc.h index f920d52a17..2c00b6880f 100644 --- a/py/misc.h +++ b/py/misc.h @@ -147,6 +147,8 @@ typedef struct _vstr_t { void vstr_init(vstr_t *vstr, size_t alloc); void vstr_init_len(vstr_t *vstr, size_t len); 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); vstr_t *vstr_new(void); vstr_t *vstr_new_size(size_t alloc); diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 04141edec9..f080f457b6 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -35,7 +35,6 @@ #include "py/runtime.h" #include "py/builtin.h" #include "py/stream.h" -#include "py/pfenv.h" #if MICROPY_PY_BUILTINS_FLOAT #include @@ -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; } - pfenv_t pfenv; - pfenv.data = stream_obj; - pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write; + mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write}; #endif for (mp_uint_t i = 0; i < n_args; i++) { 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 } #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 mp_obj_print(args[i], PRINT_STR); #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) { if (o != mp_const_none) { #if MICROPY_PY_IO - pfenv_t pfenv; - pfenv.data = &mp_sys_stdout_obj; - 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_print_t print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write}; + mp_obj_print_helper(&print, o, PRINT_REPR); mp_stream_write(&mp_sys_stdout_obj, "\n", 1); #else 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) { vstr_t vstr; - vstr_init(&vstr, 16); - mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, o_in, PRINT_REPR); + mp_print_t print; + 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); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); diff --git a/py/modsys.c b/py/modsys.c index 5051e72951..09e72e98ad 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -31,7 +31,6 @@ #include "py/objtuple.h" #include "py/objstr.h" #include "py/objint.h" -#include "py/pfenv.h" #include "py/stream.h" #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]; } - pfenv_t pfenv; - pfenv.data = stream_obj; - 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]); + mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write}; + mp_obj_print_exception(&print, args[0]); #else - mp_obj_print_exception(printf_wrapper, NULL, args[0]); + mp_obj_print_exception(&mp_plat_print, args[0]); #endif return mp_const_none; diff --git a/py/mpconfig.h b/py/mpconfig.h index 21ae0c3f53..c78221f3a5 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -691,7 +691,7 @@ typedef double mp_float_t; #define MICROPY_MAKE_POINTER_CALLABLE(p) (p) #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 // generators store pointers to GC managed memory in the code. #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) #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 #define MP_SSIZE_MAX SSIZE_MAX #endif diff --git a/py/pfenv.c b/py/mpprint.c similarity index 58% rename from py/pfenv.c rename to py/mpprint.c index f0a894e49b..cb39aa8131 100644 --- a/py/pfenv.c +++ b/py/mpprint.c @@ -3,7 +3,7 @@ * * 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 * of this software and associated documentation files (the "Software"), to deal @@ -24,11 +24,16 @@ * THE SOFTWARE. */ +#include +#include #include +#include #include +#include "py/mpprint.h" +#include "py/obj.h" #include "py/objint.h" -#include "py/pfenv.h" +#include "py/runtime.h" #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE #include @@ -41,11 +46,22 @@ static const char pad_spaces[] = " "; static const char pad_zeroes[] = "0000000000000000"; -void pfenv_vstr_add_strn(void *data, const char *str, mp_uint_t len) { - vstr_add_strn(data, str, len); +STATIC void plat_print_strn(void *env, const char *str, mp_uint_t 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 right_pad = 0; 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; const char *pad_chars; - if (!fill || fill == ' ' ) { + if (!fill || fill == ' ') { pad_chars = pad_spaces; pad_size = sizeof(pad_spaces) - 1; } 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) { p = pad_size; } - pfenv->print_strn(pfenv->data, pad_chars, p); + print->print_strn(print->data, pad_chars, p); left_pad -= p; } } if (len) { - pfenv->print_strn(pfenv->data, str, len); + print->print_strn(print->data, str, len); total_chars_printed += len; } 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) { p = pad_size; } - pfenv->print_strn(pfenv->data, pad_chars, p); + print->print_strn(print->data, pad_chars, 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) // 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. -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) { +// It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB. +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; if (sgn) { 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; if (flags & PF_FLAG_PAD_AFTER_SIGN) { if (sign) { - len += pfenv_print_strn(pfenv, &sign, 1, flags, fill, 1); + len += mp_print_strn(print, &sign, 1, flags, fill, 1); width--; } if (prefix_char) { - len += pfenv_print_strn(pfenv, "0", 1, flags, fill, 1); - len += pfenv_print_strn(pfenv, &prefix_char, 1, flags, fill, 1); + len += mp_print_strn(print, "0", 1, flags, fill, 1); + len += mp_print_strn(print, &prefix_char, 1, flags, fill, 1); width -= 2; } } 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; } -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)) { // This will convert booleans to int, or raise an error for // 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; 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) { // pad after sign implies pad after prefix as well. if (sign) { - len += pfenv_print_strn(pfenv, &sign, 1, 0, 0, 1); + len += mp_print_strn(print, &sign, 1, 0, 0, 1); width--; } 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; } } @@ -299,10 +315,10 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int base, int base_char 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) { - len += pfenv_print_strn(pfenv, "", 0, 0, ' ', spaces_after); + len += mp_print_strn(print, "", 0, 0, ' ', spaces_after); } 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 -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 sign = '\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)) { // We have a number, or we have a inf/nan and PAD_NAN_INF is set // 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--; 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. fill = ' '; } - chrs += pfenv_print_strn(pfenv, s, len, flags, fill, width); + chrs += mp_print_strn(print, s, len, flags, fill, width); return chrs; } #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; +} diff --git a/py/pfenv.h b/py/mpprint.h similarity index 66% rename from py/pfenv.h rename to py/mpprint.h index 3d2b31b5d0..60fa18acf9 100644 --- a/py/pfenv.h +++ b/py/mpprint.h @@ -23,12 +23,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef __MICROPY_INCLUDED_PY_PFENV_H__ -#define __MICROPY_INCLUDED_PY_PFENV_H__ +#ifndef __MICROPY_INCLUDED_PY_MPPRINT_H__ +#define __MICROPY_INCLUDED_PY_MPPRINT_H__ -#include - -#include "py/obj.h" +#include "py/mpconfig.h" #define PF_FLAG_LEFT_ADJUST (0x001) #define PF_FLAG_SHOW_SIGN (0x002) @@ -42,24 +40,28 @@ #define PF_FLAG_PAD_NAN_INF (0x200) #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 (*print_strn)(void *, const char *str, mp_uint_t len); -} pfenv_t; + mp_print_strn_t print_strn; +} 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 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 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_str(const mp_print_t *print, const char *str); +int mp_print_strn(const mp_print_t *print, const char *str, mp_uint_t len, 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); #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 -int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args); -int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...); +int mp_printf(const mp_print_t *print, 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 -void printf_wrapper(void *env, const char *fmt, ...); - -#endif // __MICROPY_INCLUDED_PY_PFENV_H__ +#endif // __MICROPY_INCLUDED_PY_MPPRINT_H__ diff --git a/py/obj.c b/py/obj.c index 6c851dfb08..0d318fa14d 100644 --- a/py/obj.c +++ b/py/obj.c @@ -36,7 +36,7 @@ #include "py/runtime0.h" #include "py/runtime.h" #include "py/stackctrl.h" -#include "py/pfenv.h" +//#include "py/pfenv.h" #include "py/stream.h" // for mp_obj_print 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); } -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 MP_STACK_CHECK(); #ifndef NDEBUG if (o_in == NULL) { - print(env, "(nil)"); + mp_print_str(print, "(nil)"); return; } #endif mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->print != NULL) { - type->print(print, env, o_in, kind); + type->print((mp_print_t*)print, o_in, kind); } 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 // defined per port; type of these is irrelevant, just need pointer extern struct _mp_dummy_t mp_sys_stdout_obj; - pfenv_t pfenv; - pfenv.data = &mp_sys_stdout_obj; - 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_in, kind); + mp_print_t print; + print.data = &mp_sys_stdout_obj; + print.print_strn = (mp_print_strn_t)mp_stream_write; + mp_obj_print_helper(&print, o_in, kind); #else - mp_obj_print_helper(printf_wrapper, NULL, o_in, kind); + mp_obj_print_helper(&mp_plat_print, o_in, kind); #endif } // 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)) { mp_uint_t n, *values; mp_obj_exception_get_traceback(exc, &n, &values); if (n > 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) { #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 - print(env, " File \"%s\"", qstr_str(values[i])); + mp_printf(print, " File \"%s\"", qstr_str(values[i])); #endif // the block name can be NULL if it's unknown qstr block = values[i + 2]; if (block == MP_QSTR_NULL) { - print(env, "\n"); + mp_print_str(print, "\n"); } 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); - print(env, "\n"); + mp_obj_print_helper(print, exc, PRINT_EXC); + mp_print_str(print, "\n"); } bool mp_obj_is_true(mp_obj_t arg) { diff --git a/py/obj.h b/py/obj.h index a5423f0824..86f560ff51 100644 --- a/py/obj.h +++ b/py/obj.h @@ -29,6 +29,7 @@ #include "py/mpconfig.h" #include "py/misc.h" #include "py/qstr.h" +#include "py/mpprint.h" // All Micro Python objects are at least this type // It must be of pointer size @@ -260,7 +261,7 @@ typedef enum { PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses } 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_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); @@ -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 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_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_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_data(mp_obj_t self_in, mp_uint_t *len); 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 // float diff --git a/py/objarray.c b/py/objarray.c index cb2b2b6a1a..33cd7ecc3b 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -76,26 +76,26 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui // 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; mp_obj_array_t *o = o_in; if (o->typecode == BYTEARRAY_TYPECODE) { - print(env, "bytearray(b"); - mp_str_print_quoted(print, env, o->items, o->len, true); + mp_print_str(print, "bytearray(b"); + mp_str_print_quoted(print, o->items, o->len, true); } else { - print(env, "array('%c'", o->typecode); + mp_printf(print, "array('%c'", o->typecode); if (o->len > 0) { - print(env, ", ["); + mp_print_str(print, ", ["); for (mp_uint_t i = 0; i < o->len; i++) { 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 diff --git a/py/objbool.c b/py/objbool.c index d60dc8c0bd..478491bfc2 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -35,19 +35,19 @@ typedef struct _mp_obj_bool_t { bool value; } 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; if (MICROPY_PY_UJSON && kind == PRINT_JSON) { if (self->value) { - print(env, "true"); + mp_print_str(print, "true"); } else { - print(env, "false"); + mp_print_str(print, "false"); } } else { if (self->value) { - print(env, "True"); + mp_print_str(print, "True"); } else { - print(env, "False"); + mp_print_str(print, "False"); } } } diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 0f9ff08c81..b961592359 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -36,14 +36,14 @@ typedef struct _mp_obj_bound_meth_t { } mp_obj_bound_meth_t; #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; mp_obj_bound_meth_t *o = o_in; - print(env, "self, PRINT_REPR); - print(env, "."); - mp_obj_print_helper(print, env, o->meth, PRINT_REPR); - print(env, ">"); + mp_printf(print, "self, PRINT_REPR); + mp_print_str(print, "."); + mp_obj_print_helper(print, o->meth, PRINT_REPR); + mp_print_str(print, ">"); } #endif diff --git a/py/objcell.c b/py/objcell.c index 9adbc16aea..97f1ecd63c 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -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 -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; mp_obj_cell_t *o = o_in; - print(env, "obj); + mp_printf(print, "obj); if (o->obj == MP_OBJ_NULL) { - print(env, "(nil)"); + mp_print_str(print, "(nil)"); } 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 diff --git a/py/objclosure.c b/py/objclosure.c index 95c1adde0c..a4000e5ddb 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -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 -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; mp_obj_closure_t *o = o_in; - print(env, "fun, PRINT_REPR); - print(env, " at %p, n_closed=%u ", o, o->n_closed); + mp_print_str(print, "fun, PRINT_REPR); + mp_printf(print, " at %p, n_closed=%u ", o, o->n_closed); for (mp_uint_t i = 0; i < o->n_closed; i++) { if (o->closed[i] == MP_OBJ_NULL) { - print(env, "(nil)"); + mp_print_str(print, "(nil)"); } 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 diff --git a/py/objcomplex.c b/py/objcomplex.c index f4a68851a5..12f10ec10b 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -48,36 +48,36 @@ typedef struct _mp_obj_complex_t { mp_float_t imag; } 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; mp_obj_complex_t *o = o_in; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT char buf[16]; if (o->real == 0) { mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0'); - print(env, "%sj", buf); + mp_printf(print, "%sj", buf); } else { mp_format_float(o->real, buf, sizeof(buf), 'g', 7, '\0'); - print(env, "(%s", buf); + mp_printf(print, "(%s", buf); if (o->imag >= 0) { - print(env, "+"); + mp_print_str(print, "+"); } mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0'); - print(env, "%sj)", buf); + mp_printf(print, "%sj)", buf); } #else char buf[32]; if (o->real == 0) { sprintf(buf, "%.16g", (double)o->imag); - print(env, "%sj", buf); + mp_printf(print, "%sj", buf); } else { sprintf(buf, "%.16g", (double)o->real); - print(env, "(%s", buf); + mp_printf(print, "(%s", buf); if (o->imag >= 0) { - print(env, "+"); + mp_print_str(print, "+"); } sprintf(buf, "%.16g", (double)o->imag); - print(env, "%sj)", buf); + mp_printf(print, "%sj)", buf); } #endif } diff --git a/py/objdict.c b/py/objdict.c index 3e255ec883..23024d5496 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -55,30 +55,30 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) { 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); bool first = true; if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { kind = PRINT_REPR; } 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_map_elem_t *next = NULL; while ((next = dict_iter_next(self, &cur)) != NULL) { if (!first) { - print(env, ", "); + mp_print_str(print, ", "); } first = false; - mp_obj_print_helper(print, env, next->key, kind); - print(env, ": "); - mp_obj_print_helper(print, env, next->value, kind); + mp_obj_print_helper(print, next->key, kind); + mp_print_str(print, ": "); + 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) { - 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; } -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; assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type)); mp_obj_dict_view_t *self = MP_OBJ_CAST(self_in); bool first = true; - print(env, mp_dict_view_names[self->kind]); - print(env, "(["); + mp_print_str(print, mp_dict_view_names[self->kind]); + mp_print_str(print, "(["); mp_obj_t self_iter = dict_view_getiter(self_in); mp_obj_t next = MP_OBJ_NULL; while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) { if (!first) { - print(env, ", "); + mp_print_str(print, ", "); } 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) { diff --git a/py/objexcept.c b/py/objexcept.c index 2d23f160a2..8a008d1fff 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -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. 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_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; bool is_subclass = kind & PRINT_EXC_SUBCLASS; 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) { - print(env, ": "); + mp_print_str(print, ": "); } if (k == PRINT_STR || k == PRINT_EXC) { if (o->args == NULL || o->args->len == 0) { - print(env, ""); + mp_print_str(print, ""); return; } 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; } } - 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) { diff --git a/py/objfloat.c b/py/objfloat.c index b94caf3c06..eb59cc5b78 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -42,24 +42,24 @@ #include "py/formatfloat.h" #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; mp_obj_float_t *o = o_in; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT char buf[16]; 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) { // Python floats always have decimal point - print(env, ".0"); + mp_print_str(print, ".0"); } #else char buf[32]; sprintf(buf, "%.16g", (double) o->value); - print(env, buf); + mp_print_str(print, buf); if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL) { // Python floats always have decimal point - print(env, ".0"); + mp_print_str(print, ".0"); } #endif } diff --git a/py/objfun.c b/py/objfun.c index f00a90a089..8b9d3f553b 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -125,10 +125,10 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { } #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; mp_obj_fun_bc_t *o = o_in; - print(env, "", qstr_str(mp_obj_fun_get_name(o)), o); + mp_printf(print, "", qstr_str(mp_obj_fun_get_name(o)), o); } #endif diff --git a/py/objgenerator.c b/py/objgenerator.c index f672b8d99d..ed4e1fd151 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -95,10 +95,10 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) { /******************************************************************************/ /* 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; mp_obj_gen_instance_t *self = self_in; - print(env, "", qstr_str(mp_obj_code_get_name(self->code_state.code_info)), self_in); + mp_printf(print, "", 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) { diff --git a/py/objint.c b/py/objint.c index 26e1cc048f..64faed636f 100644 --- a/py/objint.c +++ b/py/objint.c @@ -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 #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; // The size of this buffer is rather arbitrary. If it's not large // 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; 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) { m_del(char, buf, buf_size); diff --git a/py/objint.h b/py/objint.h index 63cd91a698..daeb3c499d 100644 --- a/py/objint.h +++ b/py/objint.h @@ -50,7 +50,7 @@ typedef enum { mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val); #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, 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, diff --git a/py/objlist.c b/py/objlist.c index e1343d9b32..9404032128 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -44,19 +44,19 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args); /******************************************************************************/ /* 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); if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { kind = PRINT_REPR; } - print(env, "["); + mp_print_str(print, "["); for (mp_uint_t i = 0; i < o->len; i++) { 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) { diff --git a/py/objmodule.c b/py/objmodule.c index 971c7f38c5..84d97f4948 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -33,7 +33,7 @@ #include "py/runtime.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; mp_obj_module_t *self = self_in; 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. mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); if (elem != NULL) { - print(env, "", name, mp_obj_str_get_str(elem->value)); + mp_printf(print, "", name, mp_obj_str_get_str(elem->value)); return; } #endif - print(env, "", name); + mp_printf(print, "", name); } STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 9cc6da1b7a..ef635a7a9c 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -53,19 +53,19 @@ STATIC mp_uint_t namedtuple_find_field(mp_obj_namedtuple_type_t *type, qstr name 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; 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; for (mp_uint_t i = 0; i < o->tuple.len; i++) { if (i > 0) { - print(env, ", "); + mp_print_str(print, ", "); } - print(env, "%s=", qstr_str(fields[i])); - mp_obj_print_helper(print, env, o->tuple.items[i], PRINT_REPR); + mp_printf(print, "%s=", qstr_str(fields[i])); + 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) { diff --git a/py/objnone.c b/py/objnone.c index 523158d00e..d47452bb4d 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -34,12 +34,12 @@ typedef struct _mp_obj_none_t { mp_obj_base_t base; } 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; if (MICROPY_PY_UJSON && kind == PRINT_JSON) { - print(env, "null"); + mp_print_str(print, "null"); } else { - print(env, "None"); + mp_print_str(print, "None"); } } diff --git a/py/objrange.c b/py/objrange.c index 9f7e6591e1..58d90a75e6 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -79,14 +79,14 @@ typedef struct _mp_obj_range_t { mp_int_t step; } 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; 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) { - print(env, ")"); + mp_print_str(print, ")"); } else { - print(env, ", %d)", self->step); + mp_printf(print, ", %d)", self->step); } } diff --git a/py/objset.c b/py/objset.c index c4e59280e1..6e303fe4bb 100644 --- a/py/objset.c +++ b/py/objset.c @@ -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; mp_obj_set_t *self = self_in; #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 MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { - print(env, "frozen"); + mp_print_str(print, "frozen"); } #endif - print(env, "set()"); + mp_print_str(print, "set()"); return; } bool first = true; #if MICROPY_PY_BUILTINS_FROZENSET if (is_frozen) { - print(env, "frozenset("); + mp_print_str(print, "frozenset("); } #endif - print(env, "{"); + mp_print_str(print, "{"); for (mp_uint_t i = 0; i < self->set.alloc; i++) { if (MP_SET_SLOT_IS_FILLED(&self->set, i)) { if (!first) { - print(env, ", "); + mp_print_str(print, ", "); } 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 (is_frozen) { - print(env, ")"); + mp_print_str(print, ")"); } #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) { mp_arg_check_num(n_args, n_kw, 0, 1, false); diff --git a/py/objslice.c b/py/objslice.c index 4f3d054c68..7983864b2c 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -38,10 +38,10 @@ typedef struct _mp_obj_ellipsis_t { mp_obj_base_t base; } 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)kind; - print(env, "Ellipsis"); + mp_print_str(print, "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_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; mp_obj_slice_t *o = o_in; - print(env, "slice("); - mp_obj_print_helper(print, env, o->start, PRINT_REPR); - print(env, ", "); - mp_obj_print_helper(print, env, o->stop, PRINT_REPR); - print(env, ", "); - mp_obj_print_helper(print, env, o->step, PRINT_REPR); - print(env, ")"); + mp_print_str(print, "slice("); + mp_obj_print_helper(print, o->start, PRINT_REPR); + mp_print_str(print, ", "); + mp_obj_print_helper(print, o->stop, PRINT_REPR); + mp_print_str(print, ", "); + mp_obj_print_helper(print, o->step, PRINT_REPR); + mp_print_str(print, ")"); } const mp_obj_type_t mp_type_slice = { diff --git a/py/objstr.c b/py/objstr.c index e35fc2976e..50fe10378b 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -34,7 +34,6 @@ #include "py/objlist.h" #include "py/runtime0.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); @@ -45,8 +44,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); /******************************************************************************/ /* 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) { // this escapes characters, but it will be very slow to print (calling print many times) bool has_single_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) { 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++) { if (*s == quote_char) { - print(env, "\\%c", quote_char); + mp_printf(print, "\\%c", quote_char); } else if (*s == '\\') { - print(env, "\\\\"); + mp_print_str(print, "\\\\"); } else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) { // In strings, anything which is not ascii control character // is printed as is, this includes characters in range 0x80-0xff // (which can be non-Latin letters, etc.) - print(env, "%c", *s); + mp_printf(print, "%c", *s); } else if (*s == '\n') { - print(env, "\\n"); + mp_print_str(print, "\\n"); } else if (*s == '\r') { - print(env, "\\r"); + mp_print_str(print, "\\r"); } else if (*s == '\t') { - print(env, "\\t"); + mp_print_str(print, "\\t"); } 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 -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 // 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++) { if (*s == '"' || *s == '\\') { - print(env, "\\%c", *s); + mp_printf(print, "\\%c", *s); } else if (*s >= 32) { // this will handle normal and utf-8 encoded chars - print(env, "%c", *s); + mp_printf(print, "%c", *s); } else if (*s == '\n') { - print(env, "\\n"); + mp_print_str(print, "\\n"); } else if (*s == '\r') { - print(env, "\\r"); + mp_print_str(print, "\\r"); } else if (*s == '\t') { - print(env, "\\t"); + mp_print_str(print, "\\t"); } else { // this will handle control chars - print(env, "\\u%04x", *s); + mp_printf(print, "\\u%04x", *s); } } - print(env, "\""); + mp_print_str(print, "\""); } #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); #if MICROPY_PY_UJSON if (kind == PRINT_JSON) { - mp_str_print_json(print, env, str_data, str_len); + mp_str_print_json(print, str_data, str_len); return; } #endif bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes); if (kind == PRINT_STR && !is_bytes) { - print(env, "%.*s", str_len, str_data); + mp_printf(print, "%.*s", str_len, str_data); } else { 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: { vstr_t vstr; - vstr_init(&vstr, 16); - mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &vstr, args[0], PRINT_STR); + mp_print_t print; + 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); } @@ -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); int arg_i = 0; vstr_t vstr; - vstr_init(&vstr, 16); - pfenv_t pfenv_vstr; - pfenv_vstr.data = &vstr; - pfenv_vstr.print_strn = pfenv_vstr_add_strn; + mp_print_t print; + vstr_init_print(&vstr, 16, &print); for (const byte *top = str + len; str < top; 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_init(&arg_vstr, 16); - mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, &arg_vstr, arg, print_kind); + mp_print_t arg_print; + 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); } @@ -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)) { switch (type) { 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; case 'c': { 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; } case '\0': // No explicit format type implies 'd' case 'n': // I don't think we support locales in uPy so use '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; 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; } - 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; 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; 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 '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; 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 #define F100 100.0 #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 break; #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) { 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; 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) { slen = precision; } - pfenv_print_strn(&pfenv_vstr, s, slen, flags, fill, width); + mp_print_strn(&print, s, slen, flags, fill, width); 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; int arg_i = 0; vstr_t vstr; - vstr_init(&vstr, 16); - pfenv_t pfenv_vstr; - pfenv_vstr.data = &vstr; - pfenv_vstr.print_strn = pfenv_vstr_add_strn; + mp_print_t print; + vstr_init_print(&vstr, 16, &print); for (const byte *top = str + len; str < top; str++) { mp_obj_t arg = MP_OBJ_NULL; @@ -1389,10 +1385,10 @@ not_enough_args: nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "%%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)) { 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 { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "integer required")); @@ -1402,7 +1398,7 @@ not_enough_args: case 'd': case 'i': 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; #if MICROPY_PY_BUILTINS_FLOAT @@ -1412,7 +1408,7 @@ not_enough_args: case 'F': 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; #endif @@ -1420,16 +1416,16 @@ not_enough_args: if (alt) { 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; case 'r': case 's': { vstr_t arg_vstr; - vstr_init(&arg_vstr, 16); - mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, - &arg_vstr, arg, *str == 'r' ? PRINT_REPR : PRINT_STR); + mp_print_t arg_print; + vstr_init_print(&arg_vstr, 16, &arg_print); + mp_obj_print_helper(&arg_print, arg, *str == 'r' ? PRINT_REPR : PRINT_STR); uint vlen = arg_vstr.len; if (prec < 0) { prec = vlen; @@ -1437,14 +1433,14 @@ not_enough_args: if (vlen > (uint)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); break; } 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; default: diff --git a/py/objstr.h b/py/objstr.h index 291f49a096..9c00c914b3 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -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; } 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_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); diff --git a/py/objstringio.c b/py/objstringio.c index c7e8395b49..1823ed3981 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -52,10 +52,10 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { #define check_stringio_is_open(o) #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; mp_obj_stringio_t *self = self_in; - print(env, self->base.type == &mp_type_stringio ? "" : "", self); + mp_printf(print, self->base.type == &mp_type_stringio ? "" : "", self); } STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 406eaad49f..63ca6a8bf8 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -33,7 +33,6 @@ #include "py/objlist.h" #include "py/runtime0.h" #include "py/runtime.h" -#include "py/pfenv.h" #if MICROPY_PY_BUILTINS_STR_UNICODE @@ -42,7 +41,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t 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) bool has_single_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) { quote_char = '"'; } - print(env, "%c", quote_char); + mp_printf(print, "%c", quote_char); const byte *s = str_data, *top = str_data + str_len; while (s < top) { unichar ch; ch = utf8_get_char(s); s = utf8_next_char(s); if (ch == quote_char) { - print(env, "\\%c", quote_char); + mp_printf(print, "\\%c", quote_char); } else if (ch == '\\') { - print(env, "\\\\"); + mp_print_str(print, "\\\\"); } else if (32 <= ch && ch <= 126) { - print(env, "%c", ch); + mp_printf(print, "%c", ch); } else if (ch == '\n') { - print(env, "\\n"); + mp_print_str(print, "\\n"); } else if (ch == '\r') { - print(env, "\\r"); + mp_print_str(print, "\\r"); } else if (ch == '\t') { - print(env, "\\t"); + mp_print_str(print, "\\t"); } else if (ch < 0x100) { - print(env, "\\x%02x", ch); + mp_printf(print, "\\x%02x", ch); } else if (ch < 0x10000) { - print(env, "\\u%04x", ch); + mp_printf(print, "\\u%04x", ch); } 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); #if MICROPY_PY_UJSON if (kind == PRINT_JSON) { - mp_str_print_json(print, env, str_data, str_len); + mp_str_print_json(print, str_data, str_len); return; } #endif if (kind == PRINT_STR) { - print(env, "%.*s", str_len, str_data); + mp_printf(print, "%.*s", str_len, str_data); } else { - uni_print_quoted(print, env, str_data, str_len); + uni_print_quoted(print, str_data, str_len); } } diff --git a/py/objtuple.c b/py/objtuple.c index d575decfd4..3ba37d0278 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -37,27 +37,27 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur); /******************************************************************************/ /* 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; if (MICROPY_PY_UJSON && kind == PRINT_JSON) { - print(env, "["); + mp_print_str(print, "["); } else { - print(env, "("); + mp_print_str(print, "("); kind = PRINT_REPR; } for (mp_uint_t i = 0; i < o->len; i++) { 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) { - print(env, "]"); + mp_print_str(print, "]"); } else { if (o->len == 1) { - print(env, ","); + mp_print_str(print, ","); } - print(env, ")"); + mp_print_str(print, ")"); } } diff --git a/py/objtuple.h b/py/objtuple.h index 4cac487557..5fb82ba529 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -34,7 +34,7 @@ typedef struct _mp_obj_tuple_t { mp_obj_t items[]; } 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_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); diff --git a/py/objtype.c b/py/objtype.c index cb7110572d..5b6a011ed4 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -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; qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__; 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 if (mp_obj_is_native_exception_instance(self->subobj[0])) { 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 { - mp_obj_print_helper(print, env, self->subobj[0], kind); + mp_obj_print_helper(print, self->subobj[0], kind); } return; } if (member[0] != MP_OBJ_NULL) { 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; } // 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) { @@ -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 // - 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; mp_obj_type_t *self = self_in; - print(env, "", qstr_str(self->name)); + mp_printf(print, "", 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) { @@ -911,14 +911,14 @@ typedef struct _mp_obj_super_t { mp_obj_t obj; } 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; mp_obj_super_t *self = self_in; - print(env, "type, PRINT_STR); - print(env, ", "); - mp_obj_print_helper(print, env, self->obj, PRINT_STR); - print(env, ">"); + mp_print_str(print, "type, PRINT_STR); + mp_print_str(print, ", "); + mp_obj_print_helper(print, self->obj, PRINT_STR); + 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) { diff --git a/py/pfenv_printf.c b/py/pfenv_printf.c deleted file mode 100644 index 599700edcf..0000000000 --- a/py/pfenv_printf.c +++ /dev/null @@ -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 -#include -#include -#include - -#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); -} diff --git a/py/py.mk b/py/py.mk index e120f8be4a..98c6041156 100644 --- a/py/py.mk +++ b/py/py.mk @@ -22,6 +22,7 @@ PY_O_BASENAME = \ gc.o \ qstr.o \ vstr.o \ + mpprint.o \ unicode.o \ mpz.o \ lexer.o \ @@ -108,8 +109,6 @@ PY_O_BASENAME = \ showbc.o \ repl.o \ smallint.o \ - pfenv.o \ - pfenv_printf.o \ frozenmod.o \ ../extmod/moductypes.o \ ../extmod/modujson.o \ diff --git a/py/runtime.h b/py/runtime.h index f05a7d0a89..d171f1582c 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -63,6 +63,9 @@ extern const qstr mp_binary_op_method_name[]; void mp_init(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_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); diff --git a/py/vstr.c b/py/vstr.c index 953e8edb51..45915e7c42 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -31,6 +31,7 @@ #include "py/mpconfig.h" #include "py/misc.h" +#include "py/mpprint.h" // returned value is always at least 1 greater than argument #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; } +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) { if (!vstr->fixed_buf) { m_del(char, vstr->buf, vstr->alloc); @@ -322,32 +329,6 @@ void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) { return; } - while (1) { - // try to print in the allocated space - // 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; - } - } - } + mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn}; + mp_vprintf(&print, fmt, ap); } diff --git a/qemu-arm/main.c b/qemu-arm/main.c index 860014493b..1673c82afd 100644 --- a/qemu-arm/main.c +++ b/qemu-arm/main.c @@ -11,7 +11,6 @@ #include "py/stackctrl.h" #include "py/gc.h" #include "py/repl.h" -#include "py/pfenv.h" 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); @@ -28,7 +27,7 @@ void do_str(const char *src) { nlr_pop(); } else { // 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); } } diff --git a/qemu-arm/test_main.c b/qemu-arm/test_main.c index a48bcd3221..a529133532 100644 --- a/qemu-arm/test_main.c +++ b/qemu-arm/test_main.c @@ -11,7 +11,6 @@ #include "py/stackctrl.h" #include "py/gc.h" #include "py/repl.h" -#include "py/pfenv.h" #include "tinytest.h" #include "tinytest_macros.h" @@ -39,7 +38,7 @@ inline void do_str(const char *src) { tinytest_set_test_skipped_(); return; } - mp_obj_print_exception(printf_wrapper, NULL, exc); + mp_obj_print_exception(&mp_extern_printf_wrapper, exc); tt_abort_msg("Uncaught exception"); } end: diff --git a/stmhal/adc.c b/stmhal/adc.c index e88119567a..bc48f7b179 100644 --- a/stmhal/adc.c +++ b/stmhal/adc.c @@ -138,11 +138,11 @@ STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) { /******************************************************************************/ /* 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; - print(env, "pin_name, PRINT_STR); - print(env, " channel=%lu>", self->channel); + mp_print_str(print, "pin_name, PRINT_STR); + mp_printf(print, " channel=%lu>", self->channel); } /// \classmethod \constructor(pin) diff --git a/stmhal/can.c b/stmhal/can.c index 654daddf6f..66693f30da 100644 --- a/stmhal/can.c +++ b/stmhal/can.c @@ -33,7 +33,6 @@ #include "py/objtuple.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/pfenv.h" #include "bufhelper.h" #include "can.h" #include "pybioctl.h" @@ -174,12 +173,12 @@ STATIC void can_clearfilter(uint32_t f) { /******************************************************************************/ // 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; if (!self->is_enabled) { - print(env, "CAN(%u)", self->can_id); + mp_printf(print, "CAN(%u)", self->can_id); } else { - print(env, "CAN(%u, CAN.", self->can_id); + mp_printf(print, "CAN(%u, CAN.", self->can_id); qstr mode; switch (self->can.Init.Mode) { 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_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) { mode = MP_QSTR_True; } else { 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. 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); - 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(); } diff --git a/stmhal/extint.c b/stmhal/extint.c index 40254ac4dd..cda393ed8a 100644 --- a/stmhal/extint.c +++ b/stmhal/extint.c @@ -31,7 +31,7 @@ #include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/pfenv.h" +#include MICROPY_HAL_H #include "pin.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; } -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; - print(env, "", self->line); + mp_printf(print, "", self->line); } 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; extint_disable(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(); } diff --git a/stmhal/file.c b/stmhal/file.c index 62e5828747..3f7342bd6e 100644 --- a/stmhal/file.c +++ b/stmhal/file.c @@ -65,8 +65,8 @@ typedef struct _pyb_file_obj_t { FIL fp; } 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) { - print(env, "", mp_obj_get_type_str(self_in), self_in); +void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "", 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) { diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 80b40b8876..e742b21008 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -183,7 +183,7 @@ STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = { {{&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; uint i2c_num; @@ -191,12 +191,12 @@ STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void * else { i2c_num = 2; } if (self->i2c->State == HAL_I2C_STATE_RESET) { - print(env, "I2C(%u)", i2c_num); + mp_printf(print, "I2C(%u)", i2c_num); } else { 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 { - 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); } } } diff --git a/stmhal/led.c b/stmhal/led.c index 31665ed5a8..cd553c3912 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -210,9 +210,9 @@ void led_debug(int n, int delay) { /******************************************************************************/ /* 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; - print(env, "LED(%lu)", self->led_id); + mp_printf(print, "LED(%lu)", self->led_id); } /// \classmethod \constructor(id) diff --git a/stmhal/modstm.c b/stmhal/modstm.c index 72f4c67a76..b795d296b4 100644 --- a/stmhal/modstm.c +++ b/stmhal/modstm.c @@ -68,9 +68,9 @@ typedef struct _stm_mem_obj_t { uint32_t elem_size; // in bytes } 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; - 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) { diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 07db263d5e..0f38eb030b 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -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 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 // 1 machine instruction). // diff --git a/stmhal/pin.c b/stmhal/pin.c index 0d28ffd54d..f655aaaa59 100644 --- a/stmhal/pin.c +++ b/stmhal/pin.c @@ -180,17 +180,17 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { /// \method __str__() /// 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 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); if (mode == GPIO_MODE_ANALOG) { // analog - print(env, "ANALOG)"); + mp_print_str(print, "ANALOG)"); } else { // 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; } } - print(env, qstr_str(mode_qst)); // safe because mode_qst has no formating chars + mp_print_str(print, qstr_str(mode_qst)); // pull mode 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; } 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 @@ -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); const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx); if (af_obj == NULL) { - print(env, ", af=%d)", af_idx); + mp_printf(print, ", af=%d)", af_idx); } else { - print(env, ", af=Pin.%s)", qstr_str(af_obj->name)); + mp_printf(print, ", af=Pin.%s)", qstr_str(af_obj->name)); } } else { - print(env, ")"); + mp_print_str(print, ")"); } } } @@ -616,9 +616,9 @@ const mp_obj_type_t pin_type = { /// \method __str__() /// 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; - print(env, "Pin.%s", qstr_str(self->name)); + mp_printf(print, "Pin.%s", qstr_str(self->name)); } /// \method index() diff --git a/stmhal/pin_named_pins.c b/stmhal/pin_named_pins.c index f6ee165711..973c080f1a 100644 --- a/stmhal/pin_named_pins.c +++ b/stmhal/pin_named_pins.c @@ -31,9 +31,9 @@ #include MICROPY_HAL_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; - print(env, "", qstr_str(self->name)); + mp_printf(print, "", qstr_str(self->name)); } const mp_obj_type_t pin_cpu_pins_obj_type = { diff --git a/stmhal/printf.c b/stmhal/printf.c index 038ee99376..fed57a7762 100644 --- a/stmhal/printf.c +++ b/stmhal/printf.c @@ -29,7 +29,6 @@ #include #include "py/obj.h" -#include "py/pfenv.h" #ifdef MICROPY_HAL_H #include MICROPY_HAL_H #endif @@ -38,22 +37,16 @@ #include "py/formatfloat.h" #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, ...) { va_list ap; va_start(ap, fmt); - int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap); + int ret = mp_vprintf(&mp_plat_print, fmt, ap); va_end(ap); return ret; } 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 @@ -62,7 +55,7 @@ mp_uint_t mp_verbose_flag = 1; int DEBUG_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int ret = pfenv_vprintf(&pfenv_stdout, fmt, ap); + int ret = mp_vprintf(&mp_plat_print, fmt, ap); va_end(ap); 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') int putchar(int c) { char chr = c; - stdout_print_strn(0, &chr, 1); + mp_hal_stdout_tx_strn_cooked(&chr, 1); return chr; } // need this because gcc optimises printf("string\n") -> puts("string") int puts(const char *s) { - stdout_print_strn(0, s, strlen(s)); + mp_hal_stdout_tx_strn_cooked(s, strlen(s)); char chr = '\n'; - stdout_print_strn(0, &chr, 1); + mp_hal_stdout_tx_strn_cooked(&chr, 1); return 1; } -typedef struct _strn_pfenv_t { +typedef struct _strn_print_env_t { char *cur; size_t remain; -} strn_pfenv_t; +} strn_print_env_t; STATIC void strn_print_strn(void *data, const char *str, mp_uint_t len) { - strn_pfenv_t *strn_pfenv = data; - if (len > strn_pfenv->remain) { - len = strn_pfenv->remain; + strn_print_env_t *strn_print_env = data; + if (len > strn_print_env->remain) { + len = strn_print_env->remain; } - memcpy(strn_pfenv->cur, str, len); - strn_pfenv->cur += len; - strn_pfenv->remain -= len; + memcpy(strn_print_env->cur, str, len); + strn_print_env->cur += len; + strn_print_env->remain -= len; } int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { - strn_pfenv_t strn_pfenv; - strn_pfenv.cur = str; - strn_pfenv.remain = size; - pfenv_t pfenv; - pfenv.data = &strn_pfenv; - pfenv.print_strn = strn_print_strn; - int len = pfenv_vprintf(&pfenv, fmt, ap); + strn_print_env_t strn_print_env = {str, size}; + mp_print_t print = {&strn_print_env, strn_print_strn}; + int len = mp_vprintf(&print, fmt, ap); // add terminating null byte if (size > 0) { - if (strn_pfenv.remain == 0) { - strn_pfenv.cur[-1] = 0; + if (strn_print_env.remain == 0) { + strn_print_env.cur[-1] = 0; } else { - strn_pfenv.cur[0] = 0; + strn_print_env.cur[0] = 0; } } return len; diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c index 6b99049817..bf8b3717d3 100644 --- a/stmhal/pybstdio.c +++ b/stmhal/pybstdio.c @@ -48,9 +48,9 @@ typedef struct _pyb_stdio_obj_t { int fd; } 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; - print(env, "", self->fd); + mp_printf(print, "", self->fd); } STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c index 27c206ce39..95776f3ec8 100644 --- a/stmhal/pyexec.c +++ b/stmhal/pyexec.c @@ -33,7 +33,6 @@ #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" -#include "py/pfenv.h" #ifdef MICROPY_HAL_H #include MICROPY_HAL_H #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 ret = PYEXEC_FORCED_EXIT; } 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; } } diff --git a/stmhal/servo.c b/stmhal/servo.c index a9b37a54f3..4c4f95da4f 100644 --- a/stmhal/servo.c +++ b/stmhal/servo.c @@ -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); -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; - print(env, "", self->servo_id, 10 * self->pulse_cur); + mp_printf(print, "", self->servo_id, 10 * self->pulse_cur); } /// \classmethod \constructor(id) diff --git a/stmhal/spi.c b/stmhal/spi.c index 6f8b8f1dbe..19f62e42ab 100644 --- a/stmhal/spi.c +++ b/stmhal/spi.c @@ -335,7 +335,7 @@ SPI_HandleTypeDef *spi_get_handle(mp_obj_t o) { 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; uint spi_num; @@ -344,7 +344,7 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void * else { spi_num = 3; } if (self->spi->State == HAL_SPI_STATE_RESET) { - print(env, "SPI(%u)", spi_num); + mp_printf(print, "SPI(%u)", spi_num); } else { if (self->spi->Init.Mode == SPI_MODE_MASTER) { // 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 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 { - 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) { - 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, ")"); } } diff --git a/stmhal/timer.c b/stmhal/timer.c index 6068526595..0180cf4423 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -35,7 +35,7 @@ #include "py/nlr.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/pfenv.h" +#include MICROPY_HAL_H #include "timer.h" #include "servo.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); } -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; if (self->tim.State == HAL_TIM_STATE_RESET) { - print(env, "Timer(%u)", self->tim_id); + mp_printf(print, "Timer(%u)", self->tim_id); } else { uint32_t prescaler = self->tim.Instance->PSC & 0xffff; 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) 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, freq, 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_DIV2 ? 2 : 1); 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. /// /// 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; - print(env, "TimerChannel(timer=%u, channel=%u, mode=%s)", + mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)", self->timer->tim_id, self->channel, 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 { 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(); } diff --git a/stmhal/uart.c b/stmhal/uart.c index 4821da95fd..2da99c2212 100644 --- a/stmhal/uart.c +++ b/stmhal/uart.c @@ -330,23 +330,23 @@ void uart_irq_handler(mp_uint_t uart_id) { /******************************************************************************/ /* 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; if (!self->is_enabled) { - print(env, "UART(%u)", self->uart_id); + mp_printf(print, "UART(%u)", self->uart_id); } else { mp_int_t bits = (self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9); if (self->uart.Init.Parity != UART_PARITY_NONE) { 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); if (self->uart.Init.Parity == UART_PARITY_NONE) { - print(env, "None"); + mp_print_str(print, "None"); } 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->timeout, self->timeout_char, self->read_buf_len); } diff --git a/stmhal/usb.c b/stmhal/usb.c index 96833175ff..cb08f9c5dd 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -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 void pyb_usb_vcp_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { - print(env, "USB_VCP()"); +STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_print_str(print, "USB_VCP()"); } /// \classmethod \constructor() diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c index b6320054a1..821df60107 100644 --- a/stmhal/usrsw.c +++ b/stmhal/usrsw.c @@ -75,8 +75,8 @@ typedef struct _pyb_switch_obj_t { 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) { - print(env, "Switch()"); +void pyb_switch_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_print_str(print, "Switch()"); } /// \classmethod \constructor() diff --git a/teensy/led.c b/teensy/led.c index fc60167b98..500900ffce 100644 --- a/teensy/led.c +++ b/teensy/led.c @@ -83,10 +83,10 @@ void led_toggle(pyb_led_t led) { /******************************************************************************/ /* 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; (void)kind; - print(env, "", self->led_id); + mp_printf(print, "", 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) { diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h index 57e4c36b08..d4bfd1cd3b 100644 --- a/teensy/mpconfigport.h +++ b/teensy/mpconfigport.h @@ -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 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 // 1 machine instruction). // diff --git a/teensy/timer.c b/teensy/timer.c index e048f61d8a..5d6237d006 100644 --- a/teensy/timer.c +++ b/teensy/timer.c @@ -31,7 +31,6 @@ #include "py/nlr.h" #include "py/runtime.h" -#include "py/pfenv.h" #include "py/gc.h" #include MICROPY_HAL_H #include "pin.h" @@ -188,13 +187,13 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) { #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; if (self->ftm.State == HAL_FTM_STATE_RESET) { - print(env, "Timer(%u)", self->tim_id); + mp_printf(print, "Timer(%u)", self->tim_id); } 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, 1 << (self->ftm.Instance->SC & 7), 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. /// /// 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; - print(env, "TimerChannel(timer=%u, channel=%u, mode=%s)", + mp_printf(print, "TimerChannel(timer=%u, channel=%u, mode=%s)", self->timer->tim_id, self->channel, 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 " 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(); return handled; diff --git a/teensy/uart.c b/teensy/uart.c index 7e08366b2e..1a04bb0d69 100644 --- a/teensy/uart.c +++ b/teensy/uart.c @@ -224,20 +224,20 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) { /******************************************************************************/ /* 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; if (!self->is_enabled) { - print(env, "UART(%lu)", self->uart_id); + mp_printf(print, "UART(%lu)", self->uart_id); } else { #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.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9, self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2); if (self->uart.Init.Parity == UART_PARITY_NONE) { - print(env, ", parity=None)"); + mp_print_str(print, ", parity=None)"); } 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 } diff --git a/unix-cpy/main.c b/unix-cpy/main.c index 058de06d52..219e3e6048 100644 --- a/unix-cpy/main.c +++ b/unix-cpy/main.c @@ -32,7 +32,6 @@ #include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" -#include "py/pfenv.h" void do_file(const char *file) { mp_lexer_t *lex = mp_lexer_new_from_file(file); diff --git a/unix/file.c b/unix/file.c index 6688028a4c..dfe2d6e113 100644 --- a/unix/file.c +++ b/unix/file.c @@ -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_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; mp_obj_fdfile_t *self = self_in; - print(env, "", mp_obj_get_type_str(self), self->fd); + mp_printf(print, "", 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) { diff --git a/unix/main.c b/unix/main.c index 02809d89b4..4729b63f64 100644 --- a/unix/main.c +++ b/unix/main.c @@ -43,7 +43,6 @@ #include "py/repl.h" #include "py/gc.h" #include "py/stackctrl.h" -#include "py/pfenv.h" #include "genhdr/py-version.h" #include "input.h" @@ -91,7 +90,7 @@ STATIC int handle_uncaught_exception(mp_obj_t exc) { } // Report all other exceptions - mp_obj_print_exception(printf_wrapper, NULL, exc); + mp_obj_print_exception(&mp_plat_print, exc); return 1; } diff --git a/unix/modffi.c b/unix/modffi.c index b3dbaa0507..9e81b1e334 100644 --- a/unix/modffi.c +++ b/unix/modffi.c @@ -167,10 +167,10 @@ STATIC mp_obj_t return_ffi_value(ffi_arg val, char type) // 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; mp_obj_ffimod_t *self = self_in; - print(env, "", self->handle); + mp_printf(print, "", self->handle); } 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 -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; mp_obj_ffifunc_t *self = self_in; - print(env, "", self->func); + mp_printf(print, "", 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) { @@ -410,10 +410,10 @@ STATIC const mp_obj_type_t ffifunc_type = { // 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; mp_obj_fficallback_t *self = self_in; - print(env, "", self->func); + mp_printf(print, "", self->func); } STATIC const mp_obj_type_t fficallback_type = { @@ -424,11 +424,11 @@ STATIC const mp_obj_type_t fficallback_type = { // 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; mp_obj_ffivar_t *self = self_in; // Variable value printed as cast to int - print(env, "", self->var, *(int*)self->var); + mp_printf(print, "", self->var, *(int*)self->var); } STATIC mp_obj_t ffivar_get(mp_obj_t self_in) { diff --git a/unix/modsocket.c b/unix/modsocket.c index 8f6ac26c6d..738581a0af 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -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; 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) { diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 00cb12139d..694db88fc1 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -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_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_open_obj; #define MICROPY_PORT_BUILTINS \ diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index 01f8775fab..2de523c78c 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -115,6 +115,8 @@ typedef long mp_off_t; typedef void *machine_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_open_obj; #define MICROPY_PORT_BUILTINS \