diff options
author | Damien George <damien.p.george@gmail.com> | 2017-08-14 18:21:55 +1000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2017-08-14 18:21:55 +1000 |
commit | 25e24b2c3c63e035b4c145f743f5cd7b02a23fc0 (patch) | |
tree | 2b90e3e19f0e81256cdceb5168c9ded42ca4ddd7 /py | |
parent | 022d6a979851461432fdec6c6855a73d462baf4d (diff) | |
parent | 869cdcfdfc860b1177baf9b0f8818915ba54f3f5 (diff) | |
download | micropython-25e24b2c3c63e035b4c145f743f5cd7b02a23fc0.tar.gz micropython-25e24b2c3c63e035b4c145f743f5cd7b02a23fc0.zip |
Merge tag 'v1.9.1' into parse-bytecode
Fixes for stmhal USB mass storage, lwIP bindings and VFS regressions
This release provides an important fix for the USB mass storage device in
the stmhal port by implementing the SCSI SYNCHRONIZE_CACHE command, which
is now require by some Operating Systems. There are also fixes for the
lwIP bindings to improve non-blocking sockets and error codes. The VFS has
some regressions fixed including the ability to statvfs the root.
All changes are listed below.
py core:
- modbuiltins: add core-provided version of input() function
- objstr: catch case of negative "maxsplit" arg to str.rsplit()
- persistentcode: allow to compile with complex numbers disabled
- objstr: allow to compile with obj-repr D, and unicode disabled
- modsys: allow to compile with obj-repr D and PY_ATTRTUPLE disabled
- provide mp_decode_uint_skip() to help reduce stack usage
- makeqstrdefs.py: make script run correctly with Python 2.6
- objstringio: if created from immutable object, follow copy on write policy
extmod:
- modlwip: connect: for non-blocking mode, return EINPROGRESS
- modlwip: fix error codes for duplicate calls to connect()
- modlwip: accept: fix error code for non-blocking mode
- vfs: allow to statvfs the root directory
- vfs: allow "buffering" and "encoding" args to VFS's open()
- modframebuf: fix signed/unsigned comparison pendantic warning
lib:
- libm: use isfinite instead of finitef, for C99 compatibility
- utils/interrupt_char: remove support for KBD_EXCEPTION disabled
tests:
- basics/string_rsplit: add tests for negative "maxsplit" argument
- float: convert "sys.exit()" to "raise SystemExit"
- float/builtin_float_minmax: PEP8 fixes
- basics: convert "sys.exit()" to "raise SystemExit"
- convert remaining "sys.exit()" to "raise SystemExit"
unix port:
- convert to use core-provided version of built-in import()
- Makefile: replace references to make with $(MAKE)
windows port:
- convert to use core-provided version of built-in import()
qemu-arm port:
- Makefile: adjust object-file lists to get correct dependencies
- enable micropython.mem_*() functions to allow more tests
stmhal port:
- boards: enable DAC for NUCLEO_F767ZI board
- add support for NUCLEO_F446RE board
- pass USB handler as parameter to allow more than one USB handler
- usb: use local USB handler variable in Start-of-Frame handler
- usb: make state for USB device private to top-level USB driver
- usbdev: for MSC implement SCSI SYNCHRONIZE_CACHE command
- convert from using stmhal's input() to core provided version
cc3200 port:
- convert from using stmhal's input() to core provided version
teensy port:
- convert from using stmhal's input() to core provided version
esp8266 port:
- Makefile: replace references to make with $(MAKE)
- Makefile: add clean-modules target
- convert from using stmhal's input() to core provided version
zephyr port:
- modusocket: getaddrinfo: Fix mp_obj_len() usage
- define MICROPY_PY_SYS_PLATFORM (to "zephyr")
- machine_pin: use native Zephyr types for Zephyr API calls
docs:
- machine.Pin: remove out_value() method
- machine.Pin: add on() and off() methods
- esp8266: consistently replace Pin.high/low methods with .on/off
- esp8266/quickref: polish Pin.on()/off() examples
- network: move confusingly-named cc3200 Server class to its reference
- uos: deconditionalize, remove minor port-specific details
- uos: move cc3200 port legacy VFS mounting functions to its ref doc
- machine: sort machine classes in logical order, not alphabetically
- network: first step to describe standard network class interface
examples:
- embedding: use core-provided KeyboardInterrupt object
Diffstat (limited to 'py')
-rw-r--r-- | py/asmthumb.c | 2 | ||||
-rw-r--r-- | py/bc.c | 10 | ||||
-rw-r--r-- | py/bc.h | 1 | ||||
-rw-r--r-- | py/builtinimport.c | 4 | ||||
-rw-r--r-- | py/compile.c | 4 | ||||
-rw-r--r-- | py/makeqstrdefs.py | 28 | ||||
-rw-r--r-- | py/misc.h | 2 | ||||
-rw-r--r-- | py/mkenv.mk | 2 | ||||
-rw-r--r-- | py/modbuiltins.c | 32 | ||||
-rw-r--r-- | py/modsys.c | 6 | ||||
-rw-r--r-- | py/mpconfig.h | 8 | ||||
-rw-r--r-- | py/mperrno.h | 2 | ||||
-rw-r--r-- | py/obj.c | 2 | ||||
-rw-r--r-- | py/objfun.c | 22 | ||||
-rw-r--r-- | py/objgenerator.c | 7 | ||||
-rw-r--r-- | py/objstr.c | 13 | ||||
-rw-r--r-- | py/objstringio.c | 30 | ||||
-rw-r--r-- | py/objstringio.h | 2 | ||||
-rw-r--r-- | py/persistentcode.c | 10 | ||||
-rw-r--r-- | py/py.mk | 2 | ||||
-rw-r--r-- | py/ringbuf.h | 2 | ||||
-rw-r--r-- | py/stream.c | 2 | ||||
-rw-r--r-- | py/vm.c | 17 |
23 files changed, 144 insertions, 66 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c index 749c1e405b..7e92e4de41 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -52,7 +52,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) { #if defined(MCU_SERIES_F7) if (as->base.pass == MP_ASM_PASS_EMIT) { - // flush D-cache, so the code emited is stored in memory + // flush D-cache, so the code emitted is stored in memory SCB_CleanDCache_by_Addr((uint32_t*)as->base.code_base, as->base.code_size); // invalidate I-cache SCB_InvalidateICache(); @@ -64,6 +64,14 @@ mp_uint_t mp_decode_uint_value(const byte *ptr) { return mp_decode_uint(&ptr); } +// This function is used to help reduce stack usage at the caller, for the case when +// the caller doesn't need the actual value and just wants to skip over it. +const byte *mp_decode_uint_skip(const byte *ptr) { + while ((*ptr++) & 0x80) { + } + return ptr; +} + STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues @@ -115,7 +123,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw // get params size_t n_state = mp_decode_uint(&code_state->ip); - mp_decode_uint(&code_state->ip); // skip n_exc_stack + code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack size_t scope_flags = *code_state->ip++; size_t n_pos_args = *code_state->ip++; size_t n_kwonly_args = *code_state->ip++; @@ -92,6 +92,7 @@ typedef struct _mp_code_state_t { mp_uint_t mp_decode_uint(const byte **ptr); mp_uint_t mp_decode_uint_value(const byte *ptr); +const byte *mp_decode_uint_skip(const byte *ptr); mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc); mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); diff --git a/py/builtinimport.c b/py/builtinimport.c index d01ebbe73f..6994fc48f4 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -271,7 +271,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { if (level != 0) { // What we want to do here is to take name of current module, // chop <level> trailing components, and concatenate with passed-in - // module name, thus resolving relative import name into absolue. + // module name, thus resolving relative import name into absolute. // This even appears to be correct per // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name // "Relative imports use a module's __name__ attribute to determine that @@ -441,7 +441,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules). mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj); - // Store real name in "__main__" attribute. Choosen semi-randonly, to reuse existing qstr's. + // Store real name in "__main__" attribute. Chosen semi-randonly, to reuse existing qstr's. mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name)); #endif } diff --git a/py/compile.c b/py/compile.c index 8533e0528f..3b6a264d61 100644 --- a/py/compile.c +++ b/py/compile.c @@ -939,7 +939,7 @@ STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { } } } else { - // some arbitrary statment that we can't delete (eg del 1) + // some arbitrary statement that we can't delete (eg del 1) goto cannot_delete; } @@ -1090,7 +1090,7 @@ STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_t pn_import_source = pns->nodes[0]; - // extract the preceeding .'s (if any) for a relative import, to compute the import level + // extract the preceding .'s (if any) for a relative import, to compute the import level uint import_level = 0; do { mp_parse_node_t pn_rel; diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 92a19c3920..525dec1973 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -5,8 +5,10 @@ qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'. This script works with Python 2.6, 2.7, 3.3 and 3.4. """ +from __future__ import print_function + import re -import argparse +import sys import os # Blacklist of qstrings that are specially handled in further @@ -84,18 +86,18 @@ def cat_together(): if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Generates qstr definitions from a specified source') - - parser.add_argument('command', - help='Command (split/cat)') - parser.add_argument('input_filename', - help='Name of the input file (when not specified, the script reads standard input)') - parser.add_argument('output_dir', - help='Output directory to store individual qstr files') - parser.add_argument('output_file', - help='Name of the output file with collected qstrs') - - args = parser.parse_args() + if len(sys.argv) != 5: + print('usage: %s command input_filename output_dir output_file' % sys.argv[0]) + sys.exit(2) + + class Args: + pass + args = Args() + args.command = sys.argv[1] + args.input_filename = sys.argv[2] + args.output_dir = sys.argv[3] + args.output_file = sys.argv[4] + try: os.makedirs(args.output_dir) except OSError: @@ -198,7 +198,7 @@ int DEBUG_printf(const char *fmt, ...); extern mp_uint_t mp_verbose_flag; // This is useful for unicode handling. Some CPU archs has -// special instructions for efficient implentation of this +// special instructions for efficient implementation of this // function (e.g. CLZ on ARM). // NOTE: this function is unused at the moment #ifndef count_lead_ones diff --git a/py/mkenv.mk b/py/mkenv.mk index eb1e44fef5..b167b2533d 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -32,7 +32,7 @@ ifeq ($(BUILD_VERBOSE),0) $(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) endif -# default settings; can be overriden in main Makefile +# default settings; can be overridden in main Makefile PY_SRC ?= $(TOP)/py BUILD ?= build diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 17bd30c521..fe8159953a 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -259,6 +259,35 @@ STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex); +#if MICROPY_PY_BUILTINS_INPUT + +#include "py/mphal.h" +#include "lib/mp-readline/readline.h" + +// A port can define mp_hal_readline if they want to use a custom function here +#ifndef mp_hal_readline +#define mp_hal_readline readline +#endif + +STATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { + if (n_args == 1) { + mp_obj_print(args[0], PRINT_STR); + } + vstr_t line; + vstr_init(&line, 16); + int ret = mp_hal_readline(&line, ""); + if (ret == CHAR_CTRL_C) { + nlr_raise(mp_obj_new_exception(&mp_type_KeyboardInterrupt)); + } + if (line.len == 0 && ret == CHAR_CTRL_D) { + nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); + } + return mp_obj_new_str_from_vstr(&mp_type_str, &line); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); + +#endif + STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) { return mp_getiter(o_in, NULL); } @@ -676,6 +705,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_builtin_hex_obj) }, { MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mp_builtin_id_obj) }, + #if MICROPY_PY_BUILTINS_INPUT + { MP_ROM_QSTR(MP_QSTR_input), MP_ROM_PTR(&mp_builtin_input_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_isinstance), MP_ROM_PTR(&mp_builtin_isinstance_obj) }, { MP_ROM_QSTR(MP_QSTR_issubclass), MP_ROM_PTR(&mp_builtin_issubclass_obj) }, { MP_ROM_QSTR(MP_QSTR_iter), MP_ROM_PTR(&mp_builtin_iter_obj) }, diff --git a/py/modsys.c b/py/modsys.c index 5fbcb944c4..b8c427ba87 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -74,12 +74,12 @@ STATIC MP_DEFINE_ATTRTUPLE( MP_ROM_PTR(&mp_sys_implementation_version_info_obj) ); #else -STATIC const mp_obj_tuple_t mp_sys_implementation_obj = { +STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { {&mp_type_tuple}, 2, { - MP_OBJ_NEW_QSTR(MP_QSTR_micropython), - (mp_obj_t)&mp_sys_implementation_version_info_obj, + MP_ROM_QSTR(MP_QSTR_micropython), + MP_ROM_PTR(&mp_sys_implementation_version_info_obj), } }; #endif diff --git a/py/mpconfig.h b/py/mpconfig.h index a61d431e5a..1ec8ae21c8 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -32,7 +32,7 @@ // mpconfigport.h is a file containing configuration settings for a // particular port. mpconfigport.h is actually a default name for -// such config, and it can be overriden using MP_CONFIGFILE preprocessor +// such config, and it can be overridden using MP_CONFIGFILE preprocessor // define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE="<file.h>"' // argument to make when using standard MicroPython makefiles). // This is useful to have more than one config per port, for example, @@ -791,6 +791,12 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) #endif +// Whether to provide the built-in input() function. The implementation of this +// uses mp-readline, so can only be enabled if the port uses this readline. +#ifndef MICROPY_PY_BUILTINS_INPUT +#define MICROPY_PY_BUILTINS_INPUT (0) +#endif + // Whether to support min/max functions #ifndef MICROPY_PY_BUILTINS_MIN_MAX #define MICROPY_PY_BUILTINS_MIN_MAX (1) diff --git a/py/mperrno.h b/py/mperrno.h index 4d092de452..6ea99ae227 100644 --- a/py/mperrno.h +++ b/py/mperrno.h @@ -73,6 +73,7 @@ #define MP_ECONNABORTED (103) // Software caused connection abort #define MP_ECONNRESET (104) // Connection reset by peer #define MP_ENOBUFS (105) // No buffer space available +#define MP_EISCONN (106) // Transport endpoint is already connected #define MP_ENOTCONN (107) // Transport endpoint is not connected #define MP_ETIMEDOUT (110) // Connection timed out #define MP_ECONNREFUSED (111) // Connection refused @@ -127,6 +128,7 @@ #define MP_ECONNABORTED ECONNABORTED #define MP_ECONNRESET ECONNRESET #define MP_ENOBUFS ENOBUFS +#define MP_EISCONN EISCONN #define MP_ENOTCONN ENOTCONN #define MP_ETIMEDOUT ETIMEDOUT #define MP_ECONNREFUSED ECONNREFUSED @@ -401,7 +401,7 @@ mp_obj_t mp_obj_id(mp_obj_t o_in) { return MP_OBJ_NEW_SMALL_INT(id); } else { // If that didn't work, well, let's return long int, just as - // a (big) positve value, so it will never clash with the range + // a (big) positive value, so it will never clash with the range // of small int returned in previous case. return mp_obj_new_int_from_uint((mp_uint_t)id); } diff --git a/py/objfun.c b/py/objfun.c index 08d031c8d8..9f35891243 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -141,11 +141,11 @@ const mp_obj_type_t mp_type_fun_builtin_var = { /* byte code functions */ qstr mp_obj_code_get_name(const byte *code_info) { - mp_decode_uint(&code_info); // skip code_info_size entry + code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry #if MICROPY_PERSISTENT_CODE return code_info[0] | (code_info[1] << 8); #else - return mp_decode_uint(&code_info); + return mp_decode_uint_value(code_info); #endif } @@ -163,8 +163,8 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { #endif const byte *bc = fun->bytecode; - mp_decode_uint(&bc); // skip n_state - mp_decode_uint(&bc); // skip n_exc_stack + bc = mp_decode_uint_skip(bc); // skip n_state + bc = mp_decode_uint_skip(bc); // skip n_exc_stack bc++; // skip scope_params bc++; // skip n_pos_args bc++; // skip n_kwonly_args @@ -205,12 +205,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args MP_STACK_CHECK(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); - // get start of bytecode - const byte *ip = self->bytecode; - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint(&ip); - size_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); // allocate state for locals and stack size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); @@ -243,12 +240,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); DEBUG_printf("Func n_def_args: %d\n", self->n_def_args); - // get start of bytecode - const byte *ip = self->bytecode; - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint(&ip); - size_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); #if VM_DETECT_STACK_OVERFLOW n_state += 1; diff --git a/py/objgenerator.c b/py/objgenerator.c index 2e57fdf4b6..8cb0e60ccb 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -54,12 +54,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t*)self->fun; assert(self_fun->base.type == &mp_type_fun_bc); - // get start of bytecode - const byte *ip = self_fun->bytecode; - // bytecode prelude: get state size and exception stack size - mp_uint_t n_state = mp_decode_uint(&ip); - mp_uint_t n_exc_stack = mp_decode_uint(&ip); + size_t n_state = mp_decode_uint_value(self_fun->bytecode); + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode)); // allocate the generator object, with room for local stack and exception stack mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, diff --git a/py/objstr.c b/py/objstr.c index 70de0a693a..e758dd0062 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -602,6 +602,11 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { GET_STR_DATA_LEN(args[0], s, len); mp_int_t splits = mp_obj_get_int(args[2]); + if (splits < 0) { + // Negative limit means no limit, so delegate to split(). + return mp_obj_str_split(n_args, args); + } + mp_int_t org_splits = splits; // Preallocate list to the max expected # of elements, as we // will fill it from the end. @@ -798,7 +803,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { } assert(last_good_char_pos >= first_good_char_pos); - //+1 to accomodate the last character + //+1 to accommodate the last character size_t stripped_len = last_good_char_pos - first_good_char_pos + 1; if (stripped_len == orig_str_len) { // If nothing was stripped, don't bother to dup original string @@ -1811,7 +1816,7 @@ STATIC mp_obj_t str_islower(mp_obj_t self_in) { } #if MICROPY_CPYTHON_COMPAT -// These methods are superfluous in the presense of str() and bytes() +// These methods are superfluous in the presence of str() and bytes() // constructors. // TODO: should accept kwargs too STATIC mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) { @@ -2130,7 +2135,7 @@ typedef struct _mp_obj_str8_it_t { #if !MICROPY_PY_BUILTINS_STR_UNICODE STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { - mp_obj_str8_it_t *self = self_in; + mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { mp_obj_t o_out = mp_obj_new_str((const char*)str + self->cur, 1, true); @@ -2148,7 +2153,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_bu o->iternext = str_it_iternext; o->str = str; o->cur = 0; - return o; + return MP_OBJ_FROM_PTR(o); } #endif diff --git a/py/objstringio.c b/py/objstringio.c index 9f4adeebbf..645c441cb2 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -68,10 +68,23 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er return size; } +STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) { + const void *buf = o->vstr->buf; + o->vstr->buf = m_new(char, o->vstr->len); + memcpy(o->vstr->buf, buf, o->vstr->len); + o->vstr->fixed_buf = false; + o->ref_obj = MP_OBJ_NULL; +} + STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { (void)errcode; mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in); check_stringio_is_open(o); + + if (o->vstr->fixed_buf) { + stringio_copy_on_write(o); + } + mp_uint_t new_pos = o->pos + size; if (new_pos < size) { // Writing <size> bytes will overflow o->pos beyond limit of mp_uint_t. @@ -155,11 +168,11 @@ STATIC mp_obj_t stringio___exit__(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__); -STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type, mp_uint_t alloc) { +STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); o->base.type = type; - o->vstr = vstr_new(alloc); o->pos = 0; + o->ref_obj = MP_OBJ_NULL; return o; } @@ -170,17 +183,28 @@ STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, s bool initdata = false; mp_buffer_info_t bufinfo; + mp_obj_stringio_t *o = stringio_new(type_in); + if (n_args > 0) { if (MP_OBJ_IS_INT(args[0])) { sz = mp_obj_get_int(args[0]); } else { mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + + if (MP_OBJ_IS_STR_OR_BYTES(args[0])) { + o->vstr = m_new_obj(vstr_t); + vstr_init_fixed_buf(o->vstr, bufinfo.len, bufinfo.buf); + o->vstr->len = bufinfo.len; + o->ref_obj = args[0]; + return MP_OBJ_FROM_PTR(o); + } + sz = bufinfo.len; initdata = true; } } - mp_obj_stringio_t *o = stringio_new(type_in, sz); + o->vstr = vstr_new(sz); if (initdata) { stringio_write(MP_OBJ_FROM_PTR(o), bufinfo.buf, bufinfo.len, NULL); diff --git a/py/objstringio.h b/py/objstringio.h index 853bfb11b7..56738f4e45 100644 --- a/py/objstringio.h +++ b/py/objstringio.h @@ -33,6 +33,8 @@ typedef struct _mp_obj_stringio_t { vstr_t *vstr; // StringIO has single pointer used for both reading and writing mp_uint_t pos; + // Underlying object buffered by this StringIO + mp_obj_t ref_obj; } mp_obj_stringio_t; #endif // MICROPY_INCLUDED_PY_OBJSTRINGIO_H diff --git a/py/persistentcode.c b/py/persistentcode.c index a71045a290..2fa8c1df07 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -286,11 +286,13 @@ STATIC void save_obj(mp_print_t *print, mp_obj_t o) { byte obj_type; if (MP_OBJ_IS_TYPE(o, &mp_type_int)) { obj_type = 'i'; - } else if (mp_obj_is_float(o)) { - obj_type = 'f'; - } else { - assert(MP_OBJ_IS_TYPE(o, &mp_type_complex)); + #if MICROPY_PY_BUILTINS_COMPLEX + } else if (MP_OBJ_IS_TYPE(o, &mp_type_complex)) { obj_type = 'c'; + #endif + } else { + assert(mp_obj_is_float(o)); + obj_type = 'f'; } vstr_t vstr; mp_print_t pr; @@ -25,7 +25,7 @@ ifeq ($(MICROPY_SSL_AXTLS),1) CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config LDFLAGS_MOD += -Lbuild -laxtls else ifeq ($(MICROPY_SSL_MBEDTLS),1) -# Can be overriden by ports which have "builtin" mbedTLS +# Can be overridden by ports which have "builtin" mbedTLS MICROPY_SSL_MBEDTLS_INCLUDE ?= ../lib/mbedtls/include CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE) LDFLAGS_MOD += -L../lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto diff --git a/py/ringbuf.h b/py/ringbuf.h index 5662594f76..5e108afad7 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -33,7 +33,7 @@ typedef struct _ringbuf_t { uint16_t iput; } ringbuf_t; -// Static initalization: +// Static initialization: // byte buf_array[N]; // ringbuf_t buf = {buf_array, sizeof(buf_array)}; diff --git a/py/stream.c b/py/stream.c index c915110e0b..d3fc767bbd 100644 --- a/py/stream.c +++ b/py/stream.c @@ -51,7 +51,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in); #define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes) // Returns error condition in *errcode, if non-zero, return value is number of bytes written -// before error condition occured. If *errcode == 0, returns total bytes written (which will +// before error condition occurred. If *errcode == 0, returns total bytes written (which will // be equal to input size). mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode, byte flags) { byte *buf = buf_; @@ -947,7 +947,7 @@ unwind_jump:; DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword - // We have folowing stack layout here: + // We have following stack layout here: // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2; #if MICROPY_STACKLESS @@ -1018,7 +1018,7 @@ unwind_jump:; DECODE_UINT; // unum & 0xff == n_positional // (unum >> 8) & 0xff == n_keyword - // We have folowing stack layout here: + // We have following stack layout here: // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3; #if MICROPY_STACKLESS @@ -1363,22 +1363,25 @@ unwind_loop: // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj) if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) { const byte *ip = code_state->fun_bc->bytecode; - mp_decode_uint(&ip); // skip n_state - mp_decode_uint(&ip); // skip n_exc_stack + ip = mp_decode_uint_skip(ip); // skip n_state + ip = mp_decode_uint_skip(ip); // skip n_exc_stack ip++; // skip scope_params ip++; // skip n_pos_args ip++; // skip n_kwonly_args ip++; // skip n_def_pos_args size_t bc = code_state->ip - ip; - size_t code_info_size = mp_decode_uint(&ip); + size_t code_info_size = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); // skip code_info_size bc -= code_info_size; #if MICROPY_PERSISTENT_CODE qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); ip += 4; #else - qstr block_name = mp_decode_uint(&ip); - qstr source_file = mp_decode_uint(&ip); + qstr block_name = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); + qstr source_file = mp_decode_uint_value(ip); + ip = mp_decode_uint_skip(ip); #endif size_t source_line = 1; size_t c; |