diff options
| author | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-06-20 10:56:05 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-06-20 10:56:05 -0700 |
| commit | 30ee7019ca651bce1fe966c1089fe977d51dc92b (patch) | |
| tree | 0114b6f744dd175b7722dd8edcbe24f4ee84bb45 /unix | |
| parent | 97fcdfbd08c922efd7470d6482d7c7c703ffc0ae (diff) | |
| parent | 869cdcfdfc860b1177baf9b0f8818915ba54f3f5 (diff) | |
Merge tag 'v1.9.1'2.0.0-alpha.0
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 'unix')
| -rw-r--r-- | unix/.gitignore | 2 | ||||
| -rw-r--r-- | unix/Makefile | 28 | ||||
| -rw-r--r-- | unix/alloc.c | 6 | ||||
| -rw-r--r-- | unix/coverage-frzmpy/frzmpy2.py | 1 | ||||
| -rw-r--r-- | unix/coverage.c | 175 | ||||
| -rw-r--r-- | unix/fatfs_port.c | 3 | ||||
| -rw-r--r-- | unix/file.c | 4 | ||||
| -rw-r--r-- | unix/input.c | 57 | ||||
| -rw-r--r-- | unix/main.c | 87 | ||||
| -rw-r--r-- | unix/modffi.c | 9 | ||||
| -rw-r--r-- | unix/modmachine.c | 2 | ||||
| -rw-r--r-- | unix/modos.c | 25 | ||||
| -rw-r--r-- | unix/modsocket.c | 2 | ||||
| -rw-r--r-- | unix/modtermios.c | 3 | ||||
| -rw-r--r-- | unix/modtime.c | 4 | ||||
| l--------- | unix/modules/upip.py (renamed from unix/scripts/upip.py) | 0 | ||||
| l--------- | unix/modules/upip_utarfile.py (renamed from unix/scripts/upip_utarfile.py) | 0 | ||||
| -rw-r--r-- | unix/moduos_vfs.c | 67 | ||||
| -rw-r--r-- | unix/moduselect.c | 78 | ||||
| -rw-r--r-- | unix/mpconfigport.h | 28 | ||||
| -rw-r--r-- | unix/mpconfigport.mk | 3 | ||||
| -rw-r--r-- | unix/mpconfigport_coverage.h | 10 | ||||
| -rw-r--r-- | unix/mpconfigport_freedos.h | 6 | ||||
| -rw-r--r-- | unix/mpconfigport_minimal.h | 5 | ||||
| -rw-r--r-- | unix/mphalport.h | 13 | ||||
| -rw-r--r-- | unix/unix_mphal.c | 10 |
26 files changed, 462 insertions, 166 deletions
diff --git a/unix/.gitignore b/unix/.gitignore index eeafecf18..706b7732d 100644 --- a/unix/.gitignore +++ b/unix/.gitignore @@ -3,10 +3,12 @@ build-fast build-minimal build-coverage build-nanbox +build-freedos micropython micropython_fast micropython_minimal micropython_coverage micropython_nanbox +micropython_freedos* *.py *.gcov diff --git a/unix/Makefile b/unix/Makefile index a24962a29..be324dd3d 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -2,6 +2,7 @@ include ../py/mkenv.mk FROZEN_DIR = scripts +FROZEN_MPY_DIR = modules # define main target PROG = micropython @@ -17,13 +18,12 @@ include ../py/py.mk INC += -I. INC += -I.. -INC += -I../lib/timeutils INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -143,6 +143,7 @@ SRC_C = \ file.c \ modmachine.c \ modos.c \ + moduos_vfs.c \ modtime.c \ moduselect.c \ alloc.c \ @@ -157,8 +158,8 @@ LIB_SRC_C = $(addprefix lib/,\ # FatFS VFS support LIB_SRC_C += $(addprefix lib/,\ - fatfs/ff.c \ - fatfs/option/ccsbcs.c \ + oofatfs/ff.c \ + oofatfs/option/unicode.c \ ) OBJ = $(PY_O) @@ -210,10 +211,10 @@ fast: # build a minimal interpreter minimal: $(MAKE) COPT="-Os -DNDEBUG" CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_minimal.h>"' \ - BUILD=build-minimal PROG=micropython_minimal FROZEN_DIR= \ + BUILD=build-minimal PROG=micropython_minimal FROZEN_DIR= FROZEN_MPY_DIR= \ MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \ MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \ - MICROPY_USE_READLINE=0 MICROPY_FATFS=0 + MICROPY_USE_READLINE=0 # build interpreter with nan-boxing as object model nanbox: @@ -234,7 +235,10 @@ freedos: PROG=micropython_freedos \ MICROPY_PY_SOCKET=0 \ MICROPY_PY_FFI=0 \ - MICROPY_PY_JNI=0 + MICROPY_PY_JNI=0 \ + MICROPY_PY_BTREE=0 \ + MICROPY_PY_THREAD=0 \ + MICROPY_PY_USSL=0 # build an interpreter for coverage testing and do the testing coverage: @@ -258,7 +262,7 @@ coverage_test: coverage gcov -o build-coverage/extmod ../extmod/*.c # Value of configure's --host= option (required for cross-compilation). -# Deduce it from CROSS_COMPILE by default, but can be overriden. +# Deduce it from CROSS_COMPILE by default, but can be overridden. ifneq ($(CROSS_COMPILE),) CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) else @@ -274,15 +278,15 @@ libffi: cd ../lib/libffi; ./autogen.sh mkdir -p ../lib/libffi/build_dir; cd ../lib/libffi/build_dir; \ ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \ - make install-exec-recursive; make -C include install-data-am + $(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am axtls: $(BUILD)/libaxtls.a $(BUILD)/libaxtls.a: ../lib/axtls/README | $(OBJ_DIRS) cd ../lib/axtls; cp config/upyconfig config/.config - cd ../lib/axtls; make oldconfig -B - cd ../lib/axtls; make clean - cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)" + cd ../lib/axtls; $(MAKE) oldconfig -B + cd ../lib/axtls; $(MAKE) clean + cd ../lib/axtls; $(MAKE) all CC="$(CC)" LD="$(LD)" cp ../lib/axtls/_stage/libaxtls.a $@ ../lib/axtls/README: diff --git a/unix/alloc.c b/unix/alloc.c index 04c635ee9..54fc1d3c4 100644 --- a/unix/alloc.c +++ b/unix/alloc.c @@ -49,7 +49,7 @@ typedef struct _mmap_region_t { struct _mmap_region_t *next; } mmap_region_t; -void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) { +void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size) { // size needs to be a multiple of the page size *size = (min_size + 0xfff) & (~0xfff); *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -65,7 +65,7 @@ void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) { MP_STATE_VM(mmap_region_head) = rg; } -void mp_unix_free_exec(void *ptr, mp_uint_t size) { +void mp_unix_free_exec(void *ptr, size_t size) { munmap(ptr, size); // unlink the mmap'd region from the list @@ -93,7 +93,7 @@ void *ffi_closure_alloc(size_t size, void **code); void ffi_closure_free(void *ptr); void *ffi_closure_alloc(size_t size, void **code) { - mp_uint_t dummy; + size_t dummy; mp_unix_alloc_exec(size, code, &dummy); return *code; } diff --git a/unix/coverage-frzmpy/frzmpy2.py b/unix/coverage-frzmpy/frzmpy2.py new file mode 100644 index 000000000..1ad930db2 --- /dev/null +++ b/unix/coverage-frzmpy/frzmpy2.py @@ -0,0 +1 @@ +raise ZeroDivisionError diff --git a/unix/coverage.c b/unix/coverage.c index 7140be41b..09959525a 100644 --- a/unix/coverage.c +++ b/unix/coverage.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <string.h> #include "py/obj.h" #include "py/objstr.h" @@ -8,9 +9,130 @@ #include "py/builtin.h" #include "py/emit.h" #include "py/formatfloat.h" +#include "py/stream.h" +#include "py/binary.h" #if defined(MICROPY_UNIX_COVERAGE) +// stream testing object +typedef struct _mp_obj_streamtest_t { + mp_obj_base_t base; + uint8_t *buf; + size_t len; + size_t pos; + int error_code; +} mp_obj_streamtest_t; + +STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { + mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + o->buf = m_new(uint8_t, bufinfo.len); + memcpy(o->buf, bufinfo.buf, bufinfo.len); + o->len = bufinfo.len; + o->pos = 0; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf); + +STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) { + mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); + o->error_code = mp_obj_get_int(err_in); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error); + +STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); + if (o->pos < o->len) { + if (size > o->len - o->pos) { + size = o->len - o->pos; + } + memcpy(buf, o->buf + o->pos, size); + o->pos += size; + return size; + } else if (o->error_code == 0) { + return 0; + } else { + *errcode = o->error_code; + return MP_STREAM_ERROR; + } +} + +STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { + mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); + (void)buf; + (void)size; + *errcode = o->error_code; + return MP_STREAM_ERROR; +} + +STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); + (void)arg; + (void)request; + (void)errcode; + if (o->error_code != 0) { + *errcode = o->error_code; + return MP_STREAM_ERROR; + } + return 0; +} + +STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_read1), MP_ROM_PTR(&mp_stream_read1_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); + +STATIC const mp_stream_p_t fileio_stream_p = { + .read = stest_read, + .write = stest_write, + .ioctl = stest_ioctl, +}; + +STATIC const mp_obj_type_t mp_type_stest_fileio = { + { &mp_type_type }, + .protocol = &fileio_stream_p, + .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, +}; + +// stream read returns non-blocking error +STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + (void)o_in; + (void)buf; + (void)size; + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; +} + +STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); + +STATIC const mp_stream_p_t textio_stream_p2 = { + .read = stest_read2, + .write = NULL, + .is_text = true, +}; + +STATIC const mp_obj_type_t mp_type_stest_textio2 = { + { &mp_type_type }, + .protocol = &textio_stream_p2, + .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict2, +}; + // str/bytes objects without a valid hash STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte*)"0123456789"}; STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte*)"0123456789"}; @@ -157,8 +279,59 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%s\n", buf2); } + // binary + { + mp_printf(&mp_plat_print, "# binary\n"); + + // call function with float and double typecodes + float far[1]; + double dar[1]; + mp_binary_set_val_array_from_int('f', far, 0, 123); + mp_printf(&mp_plat_print, "%.0f\n", (double)far[0]); + mp_binary_set_val_array_from_int('d', dar, 0, 456); + mp_printf(&mp_plat_print, "%.0lf\n", dar[0]); + } + + // scheduler + { + mp_printf(&mp_plat_print, "# scheduler\n"); + + // lock scheduler + mp_sched_lock(); + + // schedule multiple callbacks; last one should fail + for (int i = 0; i < 5; ++i) { + mp_printf(&mp_plat_print, "sched(%d)=%d\n", i, mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(i))); + } + + // test nested locking/unlocking + mp_sched_lock(); + mp_sched_unlock(); + + // shouldn't do anything while scheduler is locked + mp_handle_pending(); + + // unlock scheduler + mp_sched_unlock(); + mp_printf(&mp_plat_print, "unlocked\n"); + + // drain pending callbacks + while (mp_sched_num_pending()) { + mp_handle_pending(); + } + } + + mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); + s->base.type = &mp_type_stest_fileio; + s->buf = NULL; + s->len = 0; + s->pos = 0; + s->error_code = 0; + mp_obj_streamtest_t *s2 = m_new_obj(mp_obj_streamtest_t); + s2->base.type = &mp_type_stest_textio2; + // return a tuple of data for testing on the Python side - mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj}; + mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items); } MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage); diff --git a/unix/fatfs_port.c b/unix/fatfs_port.c index c62ae2e7d..30f1959f5 100644 --- a/unix/fatfs_port.c +++ b/unix/fatfs_port.c @@ -1,5 +1,4 @@ -#include "lib/fatfs/ff.h" -#include "lib/fatfs/diskio.h" +#include "lib/oofatfs/ff.h" DWORD get_fattime(void) { return 0; diff --git a/unix/file.c b/unix/file.c index 96fe78c49..a60840c81 100644 --- a/unix/file.c +++ b/unix/file.c @@ -244,7 +244,7 @@ const mp_obj_type_t mp_type_fileio = { .name = MP_QSTR_FileIO, .print = fdfile_print, .make_new = fdfile_make_new, - .getiter = mp_identity, + .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &fileio_stream_p, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, @@ -263,7 +263,7 @@ const mp_obj_type_t mp_type_textio = { .name = MP_QSTR_TextIOWrapper, .print = fdfile_print, .make_new = fdfile_make_new, - .getiter = mp_identity, + .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, .protocol = &textio_stream_p, .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, diff --git a/unix/input.c b/unix/input.c index 15ee60e75..4b10350df 100644 --- a/unix/input.c +++ b/unix/input.c @@ -35,44 +35,10 @@ #if MICROPY_USE_READLINE == 1 #include "lib/mp-readline/readline.h" -#elif MICROPY_USE_READLINE == 2 -#include <readline/readline.h> -#include <readline/history.h> -#include <readline/tilde.h> #endif +#if MICROPY_USE_READLINE == 0 char *prompt(char *p) { -#if MICROPY_USE_READLINE == 1 - // MicroPython supplied readline - vstr_t vstr; - vstr_init(&vstr, 16); - mp_hal_stdio_mode_raw(); - int ret = readline(&vstr, p); - mp_hal_stdio_mode_orig(); - if (ret != 0) { - vstr_clear(&vstr); - if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - return NULL; - } else { - printf("\n"); - char *line = malloc(1); - line[0] = '\0'; - return line; - } - } - vstr_null_terminated_str(&vstr); - char *line = malloc(vstr.len + 1); - memcpy(line, vstr.buf, vstr.len + 1); - vstr_clear(&vstr); -#elif MICROPY_USE_READLINE == 2 - // GNU readline - char *line = readline(p); - if (line) { - add_history(line); - } -#else // simple read string static char buf[256]; fputs(p, stdout); @@ -88,9 +54,9 @@ char *prompt(char *p) { } char *line = malloc(l); memcpy(line, buf, l); -#endif return line; } +#endif void prompt_read_history(void) { #if MICROPY_USE_READLINE_HISTORY @@ -124,8 +90,6 @@ void prompt_read_history(void) { } vstr_clear(&vstr); } - #elif MICROPY_USE_READLINE == 2 - read_history(tilde_expand("~/.micropython.history")); #endif #endif } @@ -152,23 +116,6 @@ void prompt_write_history(void) { close(fd); } } - #elif MICROPY_USE_READLINE == 2 - write_history(tilde_expand("~/.micropython.history")); #endif #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); - } - - char *line = prompt(""); - if (line == NULL) { - nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); - } - mp_obj_t o = mp_obj_new_str(line, strlen(line), false); - free(line); - return o; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input); diff --git a/unix/main.c b/unix/main.c index f67c257cd..633144c86 100644 --- a/unix/main.c +++ b/unix/main.c @@ -35,6 +35,7 @@ #include <sys/stat.h> #include <sys/types.h> #include <errno.h> +#include <signal.h> #include "py/mpstate.h" #include "py/nlr.h" @@ -90,19 +91,33 @@ STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { return 1; } +#define LEX_SRC_STR (1) +#define LEX_SRC_VSTR (2) +#define LEX_SRC_FILENAME (3) +#define LEX_SRC_STDIN (4) + // Returns standard error codes: 0 for success, 1 for all other errors, // except if FORCED_EXIT bit is set then script raised SystemExit and the // value of the exit is in the lower 8 bits of the return value -STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { - if (lex == NULL) { - printf("MemoryError: lexer could not allocate memory\n"); - return 1; - } - +STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { mp_hal_set_interrupt_char(CHAR_CTRL_C); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + // create lexer based on source kind + mp_lexer_t *lex; + if (source_kind == LEX_SRC_STR) { + const char *line = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); + } else if (source_kind == LEX_SRC_VSTR) { + const vstr_t *vstr = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); + } else if (source_kind == LEX_SRC_FILENAME) { + lex = mp_lexer_new_from_file((const char*)source); + } else { // LEX_SRC_STDIN + lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); + } + qstr source_name = lex->source_name; #if MICROPY_PY___FILE__ @@ -240,8 +255,7 @@ STATIC int do_repl(void) { mp_hal_stdio_mode_orig(); - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, false); - ret = execute_from_lexer(lex, parse_input_kind, true); + ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); if (ret & FORCED_EXIT) { return ret; } @@ -249,7 +263,7 @@ STATIC int do_repl(void) { #else - // use GNU or simple readline + // use simple readline for (;;) { char *line = prompt(">>> "); @@ -268,8 +282,7 @@ STATIC int do_repl(void) { line = line3; } - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); - int ret = execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, true); + int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); if (ret & FORCED_EXIT) { return ret; } @@ -280,13 +293,11 @@ STATIC int do_repl(void) { } STATIC int do_file(const char *file) { - mp_lexer_t *lex = mp_lexer_new_from_file(file); - return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); + return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); } STATIC int do_str(const char *str) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false); - return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); + return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); } STATIC int usage(char **argv) { @@ -364,6 +375,10 @@ STATIC void pre_process_options(int argc, char **argv) { if (word_adjust) { heap_size = heap_size * BYTES_PER_WORD / 4; } + // If requested size too small, we'll crash anyway + if (heap_size < 700) { + goto invalid_arg; + } #endif } else { invalid_arg: @@ -404,6 +419,20 @@ int main(int argc, char **argv) { } MP_NOINLINE int main_(int argc, char **argv) { + #ifdef SIGPIPE + // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing + // to peer-closed socket will lead to sudden termination of MicroPython + // process. SIGPIPE is particularly nasty, because unix shell doesn't + // print anything for it, so the above looks like completely sudden and + // silent termination for unknown reason. Ignoring SIGPIPE is also what + // CPython does. Note that this may lead to problems using MicroPython + // scripts as pipe filters, but again, that's what CPython does. So, + // scripts which want to follow unix shell pipe semantics (where SIGPIPE + // means "pipe was requested to terminate, it's not an error"), should + // catch EPIPE themselves. + signal(SIGPIPE, SIG_IGN); + #endif + mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); pre_process_options(argc, argv); @@ -415,9 +444,6 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_init(); - // create keyboard interrupt object - MP_STATE_VM(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); - char *home = getenv("HOME"); char *path = getenv("MICROPYPATH"); if (path == NULL) { @@ -427,7 +453,10 @@ MP_NOINLINE int main_(int argc, char **argv) { path = "~/.micropython/lib:/usr/lib/micropython"; #endif } - mp_uint_t path_num = 1; // [0] is for current dir (or base dir of the script) + size_t path_num = 1; // [0] is for current dir (or base dir of the script) + if (*path == ':') { + path_num++; + } for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { path_num++; if (p != NULL) { @@ -524,6 +553,9 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_obj_t mod; nlr_buf_t nlr; + bool subpkg_tried = false; + + reimport: if (nlr_push(&nlr) == 0) { mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); nlr_pop(); @@ -532,11 +564,17 @@ MP_NOINLINE int main_(int argc, char **argv) { return handle_uncaught_exception(nlr.ret_val) & 0xff; } - if (mp_obj_is_package(mod)) { - // TODO - mp_printf(&mp_stderr_print, "%s: -m for packages not yet implemented\n", argv[0]); - exit(1); + if (mp_obj_is_package(mod) && !subpkg_tried) { + subpkg_tried = true; + vstr_t vstr; + int len = strlen(argv[a + 1]); + vstr_init(&vstr, len + sizeof(".__main__")); + vstr_add_strn(&vstr, argv[a + 1], len); + vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); + import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + goto reimport; } + ret = 0; break; } else if (strcmp(argv[a], "-X") == 0) { @@ -582,8 +620,7 @@ MP_NOINLINE int main_(int argc, char **argv) { ret = do_repl(); prompt_write_history(); } else { - mp_lexer_t *lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); - ret = execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); + ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); } } diff --git a/unix/modffi.c b/unix/modffi.c index 92c4058e8..0a784710e 100644 --- a/unix/modffi.c +++ b/unix/modffi.c @@ -126,8 +126,7 @@ STATIC ffi_type *char2ffi_type(char c) STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { - mp_uint_t len; - const char *s = mp_obj_str_get_data(o_in, &len); + const char *s = mp_obj_str_get_str(o_in); ffi_type *t = char2ffi_type(*s); if (t != NULL) { return t; @@ -194,7 +193,8 @@ STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) o->rettype = *rettype; o->argtypes = argtypes; - mp_obj_t iterable = mp_getiter(argtypes_in); + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(argtypes_in, &iter_buf); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { @@ -251,7 +251,8 @@ STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t o->rettype = *rettype; - mp_obj_t iterable = mp_getiter(paramtypes_in); + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(paramtypes_in, &iter_buf); mp_obj_t item; int i = 0; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { diff --git a/unix/modmachine.c b/unix/modmachine.c index e5f9ec8d7..33a3b098e 100644 --- a/unix/modmachine.c +++ b/unix/modmachine.c @@ -32,6 +32,7 @@ #include "extmod/machine_mem.h" #include "extmod/machine_pinbase.h" +#include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" #if MICROPY_PLAT_DEV_MEM @@ -82,6 +83,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) }, + { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, #if MICROPY_PY_MACHINE_PULSE { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, #endif diff --git a/unix/modos.c b/unix/modos.c index 72f5d872e..8e746c163 100644 --- a/unix/modos.c +++ b/unix/modos.c @@ -40,22 +40,13 @@ #include "py/mphal.h" #include "extmod/misc.h" -// Can't include this, as FATFS structure definition is required, -// and FatFs header defining it conflicts with POSIX. -//#include "extmod/fsusermount.h" -MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mount_obj); -MP_DECLARE_CONST_FUN_OBJ_1(fsuser_umount_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mkfs_obj); -extern const mp_obj_type_t mp_fat_vfs_type; - #ifdef __ANDROID__ #define USE_STATFS 1 #endif STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { struct stat sb; - mp_uint_t len; - const char *path = mp_obj_str_get_data(path_in, &len); + const char *path = mp_obj_str_get_str(path_in); int res = stat(path, &sb); RAISE_ERRNO(res, errno); @@ -95,8 +86,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat); STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { STRUCT_STATVFS sb; - mp_uint_t len; - const char *path = mp_obj_str_get_data(path_in, &len); + const char *path = mp_obj_str_get_str(path_in); int res = STATVFS(path, &sb); RAISE_ERRNO(res, errno); @@ -118,8 +108,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs); #endif STATIC mp_obj_t mod_os_unlink(mp_obj_t path_in) { - mp_uint_t len; - const char *path = mp_obj_str_get_data(path_in, &len); + const char *path = mp_obj_str_get_str(path_in); int r = unlink(path); @@ -233,14 +222,6 @@ STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, - #if MICROPY_FSUSERMOUNT - { MP_ROM_QSTR(MP_QSTR_vfs_mount), MP_ROM_PTR(&fsuser_mount_obj) }, - { MP_ROM_QSTR(MP_QSTR_vfs_umount), MP_ROM_PTR(&fsuser_umount_obj) }, - { MP_ROM_QSTR(MP_QSTR_vfs_mkfs), MP_ROM_PTR(&fsuser_mkfs_obj) }, - #endif - #if MICROPY_VFS_FAT - { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, - #endif #if MICROPY_PY_OS_DUPTERM { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, #endif diff --git a/unix/modsocket.c b/unix/modsocket.c index 9ca04b88b..c7be6461e 100644 --- a/unix/modsocket.c +++ b/unix/modsocket.c @@ -58,7 +58,7 @@ from socket_more_funcs2 import * ------------------- I.e. this module should stay lean, and more functions (if needed) - should be add to seperate modules (C or Python level). + should be add to separate modules (C or Python level). */ #define MICROPY_SOCKET_EXTRA (0) diff --git a/unix/modtermios.c b/unix/modtermios.c index 2cb5f26df..5e82e772a 100644 --- a/unix/modtermios.c +++ b/unix/modtermios.c @@ -90,8 +90,7 @@ STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t if (i == VMIN || i == VTIME) { term.c_cc[i] = mp_obj_get_int(cc->items[i]); } else { - mp_uint_t len; - term.c_cc[i] = *mp_obj_str_get_data(cc->items[i], &len); + term.c_cc[i] = *mp_obj_str_get_str(cc->items[i]); } } diff --git a/unix/modtime.c b/unix/modtime.c index e4a3af165..06abfe4b3 100644 --- a/unix/modtime.c +++ b/unix/modtime.c @@ -108,9 +108,7 @@ STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { if (res != -1 || errno != EINTR) { break; } - if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { - return mp_const_none; - } + mp_handle_pending(); //printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec); #else break; diff --git a/unix/scripts/upip.py b/unix/modules/upip.py index 20d52a4ab..20d52a4ab 120000 --- a/unix/scripts/upip.py +++ b/unix/modules/upip.py diff --git a/unix/scripts/upip_utarfile.py b/unix/modules/upip_utarfile.py index 149886291..149886291 120000 --- a/unix/scripts/upip_utarfile.py +++ b/unix/modules/upip_utarfile.py diff --git a/unix/moduos_vfs.c b/unix/moduos_vfs.c new file mode 100644 index 000000000..96defa554 --- /dev/null +++ b/unix/moduos_vfs.c @@ -0,0 +1,67 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * 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 <stdint.h> +#include <string.h> + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#if MICROPY_VFS + +STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos_vfs) }, + { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, + + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, + { MP_ROM_QSTR(MP_QSTR_vfs_open), MP_ROM_PTR(&mp_vfs_open_obj) }, + + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, + { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove + + #if MICROPY_VFS_FAT + { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, + #endif +}; + +STATIC MP_DEFINE_CONST_DICT(uos_vfs_module_globals, uos_vfs_module_globals_table); + +const mp_obj_module_t mp_module_uos_vfs = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&uos_vfs_module_globals, +}; + +#endif // MICROPY_VFS diff --git a/unix/moduselect.c b/unix/moduselect.c index e74c44be6..37a3a33b2 100644 --- a/unix/moduselect.c +++ b/unix/moduselect.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George - * Copyright (c) 2015 Paul Sokolovsky + * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -55,6 +55,11 @@ typedef struct _mp_obj_poll_t { unsigned short len; struct pollfd *entries; mp_obj_t *obj_map; + short iter_cnt; + short iter_idx; + int flags; + // callee-owned tuple + mp_obj_t ret_tuple; } mp_obj_poll_t; STATIC int get_fd(mp_obj_t fdlike) { @@ -164,9 +169,7 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); -/// \method poll([timeout]) -/// Timeout is in milliseconds. -STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { +STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); // work out timeout (it's given already in ms) @@ -184,12 +187,24 @@ STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { } } + self->flags = flags; + int n_ready = poll(self->entries, self->len, timeout); RAISE_ERRNO(n_ready, errno); + return n_ready; +} + +/// \method poll([timeout]) +/// Timeout is in milliseconds. +STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { + int n_ready = poll_poll_internal(n_args, args); + if (n_ready == 0) { return mp_const_empty_tuple; } + mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); + mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL)); int ret_i = 0; struct pollfd *entries = self->entries; @@ -204,7 +219,7 @@ STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { } t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t); - if (flags & FLAG_ONESHOT) { + if (self->flags & FLAG_ONESHOT) { entries->events = 0; } } @@ -214,17 +229,68 @@ STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll); +STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { + mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); + + if (self->ret_tuple == MP_OBJ_NULL) { + self->ret_tuple = mp_obj_new_tuple(2, NULL); + } + + int n_ready = poll_poll_internal(n_args, args); + self->iter_cnt = n_ready; + self->iter_idx = 0; + + return args[0]; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); + +STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { + mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->iter_cnt == 0) { + return MP_OBJ_STOP_ITERATION; + } + + self->iter_cnt--; + + struct pollfd *entries = self->entries + self->iter_idx; + for (int i = self->iter_idx; i < self->len; i++, entries++) { + self->iter_idx++; + if (entries->revents != 0) { + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple); + // If there's an object stored, return it, otherwise raw fd + if (self->obj_map && self->obj_map[i] != MP_OBJ_NULL) { + t->items[0] = self->obj_map[i]; + } else { + t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd); + } + t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents); + if (self->flags & FLAG_ONESHOT) { + entries->events = 0; + } + return MP_OBJ_FROM_PTR(t); + } + } + + assert(!"inconsistent number of poll active entries"); + self->iter_cnt = 0; + return MP_OBJ_STOP_ITERATION; +} + STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, }; STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); STATIC const mp_obj_type_t mp_type_poll = { { &mp_type_type }, .name = MP_QSTR_poll, + .getiter = mp_identity_getiter, + .iternext = poll_iternext, .locals_dict = (void*)&poll_locals_dict, }; @@ -239,6 +305,8 @@ STATIC mp_obj_t select_poll(size_t n_args, const mp_obj_t *args) { poll->alloc = alloc; poll->len = 0; poll->obj_map = NULL; + poll->iter_cnt = 0; + poll->ret_tuple = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(poll); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll); diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index eb4656546..047121fe6 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -45,6 +45,7 @@ #endif #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) +#define MICROPY_COMP_RETURN_IF_EXPR (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) @@ -80,6 +81,8 @@ #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) +#define MICROPY_PY_BUILTINS_INPUT (1) +#define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) @@ -99,6 +102,7 @@ #endif #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_IO_RESOURCE_STREAM (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) #define MICROPY_MODULE_FROZEN_STR (1) @@ -133,12 +137,8 @@ #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) -// Can't have less than 3 values because diskio.h uses volume numbers -// as volume types and PD_USER == 2. -#define MICROPY_FATFS_VOLUMES (3) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_FSUSERMOUNT (0) #define MICROPY_VFS_FAT (0) // Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. @@ -159,10 +159,12 @@ #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) +#define MICROPY_KBD_EXCEPTION (1) #define MICROPY_ASYNC_KBD_INTR (1) extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_os; +extern const struct _mp_obj_module_t mp_module_uos_vfs; extern const struct _mp_obj_module_t mp_module_uselect; extern const struct _mp_obj_module_t mp_module_time; extern const struct _mp_obj_module_t mp_module_termios; @@ -170,6 +172,11 @@ extern const struct _mp_obj_module_t mp_module_socket; extern const struct _mp_obj_module_t mp_module_ffi; extern const struct _mp_obj_module_t mp_module_jni; +#if MICROPY_PY_UOS_VFS +#define MICROPY_PY_UOS_VFS_DEF { MP_ROM_QSTR(MP_QSTR_uos_vfs), MP_ROM_PTR(&mp_module_uos_vfs) }, +#else +#define MICROPY_PY_UOS_VFS_DEF +#endif #if MICROPY_PY_FFI #define MICROPY_PY_FFI_DEF { MP_ROM_QSTR(MP_QSTR_ffi), MP_ROM_PTR(&mp_module_ffi) }, #else @@ -208,11 +215,15 @@ extern const struct _mp_obj_module_t mp_module_jni; MICROPY_PY_SOCKET_DEF \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ + MICROPY_PY_UOS_VFS_DEF \ MICROPY_PY_USELECT_DEF \ MICROPY_PY_TERMIOS_DEF \ // type definitions for the specific machine +// For size_t and ssize_t +#include <unistd.h> + // assume that if we already defined the obj repr then we also defined types #ifndef MICROPY_OBJ_REPR #ifdef __LP64__ @@ -226,8 +237,6 @@ typedef unsigned int mp_uint_t; // must be pointer size #endif #endif -#define BYTES_PER_WORD sizeof(mp_int_t) - // Cannot include <sys/types.h>, as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; @@ -235,8 +244,8 @@ typedef long long mp_off_t; typedef long mp_off_t; #endif -void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size); -void mp_unix_free_exec(void *ptr, mp_uint_t size); +void mp_unix_alloc_exec(size_t min_size, void** ptr, size_t *size); +void mp_unix_free_exec(void *ptr, size_t size); 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) @@ -249,7 +258,6 @@ void mp_unix_mark_exec(void); #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #else -#include <unistd.h> #define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) #endif @@ -272,14 +280,12 @@ void mp_unix_mark_exec(void); #endif #define MICROPY_PORT_BUILTINS \ - { MP_ROM_QSTR(MP_QSTR_input), MP_ROM_PTR(&mp_builtin_input_obj) }, \ { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[50]; \ - mp_obj_t keyboard_interrupt_obj; \ void *mmap_region_head; \ // We need to provide a declaration/definition of alloca() diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk index 3b335ae78..8819546bf 100644 --- a/unix/mpconfigport.mk +++ b/unix/mpconfigport.mk @@ -8,9 +8,6 @@ MICROPY_FORCE_32BIT = 0 # 1 - use MicroPython version of readline MICROPY_USE_READLINE = 1 -# Whether to enable FatFs VFS -MICROPY_FATFS = 1 - # btree module using Berkeley DB 1.xx MICROPY_PY_BTREE = 1 diff --git a/unix/mpconfigport_coverage.h b/unix/mpconfigport_coverage.h index 5fd5b82c1..5fc8d7107 100644 --- a/unix/mpconfigport_coverage.h +++ b/unix/mpconfigport_coverage.h @@ -27,12 +27,18 @@ // Default unix config while intended to be comprehensive, may still not enable // all the features, this config should enable more (testable) options. +#define MICROPY_VFS (1) +#define MICROPY_PY_UOS_VFS (1) + #include <mpconfigport.h> +#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_PY_DELATTR_SETATTR (1) +#define MICROPY_PY_BUILTINS_HELP (1) +#define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) -#undef MICROPY_FSUSERMOUNT #undef MICROPY_VFS_FAT -#define MICROPY_FSUSERMOUNT (1) #define MICROPY_VFS_FAT (1) #define MICROPY_PY_FRAMEBUF (1) diff --git a/unix/mpconfigport_freedos.h b/unix/mpconfigport_freedos.h index b2ba06da0..09c85ab1e 100644 --- a/unix/mpconfigport_freedos.h +++ b/unix/mpconfigport_freedos.h @@ -37,8 +37,4 @@ // djgpp dirent struct does not have d_ino field #undef _DIRENT_HAVE_D_INO -// djgpp errno.h have no ENOTSUP -#include <errno.h> -#ifndef ENOTSUP -#define ENOTSUP 88 -#endif +#define MICROPY_USE_INTERNAL_ERRNO (1) diff --git a/unix/mpconfigport_minimal.h b/unix/mpconfigport_minimal.h index 15a5f7d85..b4d9f8143 100644 --- a/unix/mpconfigport_minimal.h +++ b/unix/mpconfigport_minimal.h @@ -40,12 +40,14 @@ #define MICROPY_COMP_CONST (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) +#define MICROPY_READER_POSIX (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) #define MICROPY_WARNINGS (0) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) +#define MICROPY_KBD_EXCEPTION (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_STREAMS_NON_BLOCK (0) @@ -98,7 +100,6 @@ extern const struct _mp_obj_module_t mp_module_os; { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \ #define MICROPY_PORT_ROOT_POINTERS \ - mp_obj_t keyboard_interrupt_obj; ////////////////////////////////////////// // Do not change anything beyond this line @@ -126,8 +127,6 @@ typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size #endif -#define BYTES_PER_WORD sizeof(mp_int_t) - // Cannot include <sys/types.h>, as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; diff --git a/unix/mphalport.h b/unix/mphalport.h index 00e79ec17..cf227872f 100644 --- a/unix/mphalport.h +++ b/unix/mphalport.h @@ -34,6 +34,19 @@ void mp_hal_set_interrupt_char(char c); void mp_hal_stdio_mode_raw(void); void mp_hal_stdio_mode_orig(void); +#if MICROPY_USE_READLINE == 1 && MICROPY_PY_BUILTINS_INPUT +#include "py/misc.h" +#include "lib/mp-readline/readline.h" +// For built-in input() we need to wrap the standard readline() to enable raw mode +#define mp_hal_readline mp_hal_readline +static inline int mp_hal_readline(vstr_t *vstr, const char *p) { + mp_hal_stdio_mode_raw(); + int ret = readline(vstr, p); + mp_hal_stdio_mode_orig(); + return ret; +} +#endif + // TODO: POSIX et al. define usleep() as guaranteedly capable only of 1s sleep: // "The useconds argument shall be less than one million." static inline void mp_hal_delay_ms(mp_uint_t ms) { usleep((ms) * 1000); } diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c index 6c6666236..800484498 100644 --- a/unix/unix_mphal.c +++ b/unix/unix_mphal.c @@ -40,20 +40,20 @@ STATIC void sighandler(int signum) { if (signum == SIGINT) { #if MICROPY_ASYNC_KBD_INTR - mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); + mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); sigset_t mask; sigemptyset(&mask); // On entry to handler, its signal is blocked, and unblocked on // normal exit. As we instead perform longjmp, unblock it manually. sigprocmask(SIG_SETMASK, &mask, NULL); - nlr_raise(MP_STATE_VM(keyboard_interrupt_obj)); + nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); #else - if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) { + if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { // this is the second time we are called, so die straight away exit(1); } - mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); - MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj); + mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); + MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); #endif } } |
