diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c index 80d0fa6344..cecef5dc96 100644 --- a/extmod/vfs_reader.c +++ b/extmod/vfs_reader.c @@ -49,7 +49,7 @@ typedef struct _mp_reader_vfs_t { byte buf[]; } mp_reader_vfs_t; -static mp_uint_t mp_reader_vfs_readbyte(void *data) { +static uintptr_t mp_reader_vfs_readbyte(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; if (reader->bufpos >= reader->buflen) { if (reader->buflen < reader->bufsize) { @@ -70,10 +70,16 @@ static mp_uint_t mp_reader_vfs_readbyte(void *data) { return reader->buf[reader->bufpos++]; } -static void mp_reader_vfs_close(void *data) { +static intptr_t mp_reader_vfs_ioctl(void *data, uintptr_t request, uintptr_t arg) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; - mp_stream_close(reader->file); - m_del_obj(mp_reader_vfs_t, reader); + + if (request == MP_READER_CLOSE) { + mp_stream_close(reader->file); + m_del_obj(mp_reader_vfs_t, reader); + return 0; + } + + return -MP_EINVAL; } void mp_reader_new_file(mp_reader_t *reader, qstr filename) { @@ -104,7 +110,7 @@ void mp_reader_new_file(mp_reader_t *reader, qstr filename) { rf->bufpos = 0; reader->data = rf; reader->readbyte = mp_reader_vfs_readbyte; - reader->close = mp_reader_vfs_close; + reader->ioctl = mp_reader_vfs_ioctl; } #endif // MICROPY_READER_VFS diff --git a/ports/esp8266/lexerstr32.c b/ports/esp8266/lexerstr32.c index 51d5658e43..d51c15e7c8 100644 --- a/ports/esp8266/lexerstr32.c +++ b/ports/esp8266/lexerstr32.c @@ -26,6 +26,7 @@ */ #include "py/lexer.h" +#include "py/mperrno.h" #if MICROPY_ENABLE_COMPILER @@ -35,7 +36,7 @@ typedef struct _mp_lexer_str32_buf_t { uint8_t byte_off; } mp_lexer_str32_buf_t; -static mp_uint_t str32_buf_next_byte(void *sb_in) { +static uintptr_t str32_buf_next_byte(void *sb_in) { mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t *)sb_in; byte c = sb->val & 0xff; if (c == 0) { @@ -52,9 +53,13 @@ static mp_uint_t str32_buf_next_byte(void *sb_in) { return c; } -static void str32_buf_free(void *sb_in) { +static intptr_t str32_buf_free(void *sb_in, uintptr_t request, uintptr_t arg) { mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t *)sb_in; - m_del_obj(mp_lexer_str32_buf_t, sb); + if (request == MP_READER_CLOSE) { + m_del_obj(mp_lexer_str32_buf_t, sb); + return 0; + } + return -MP_EINVAL; } mp_lexer_t *mp_lexer_new_from_str32(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len) { diff --git a/ports/nrf/modules/os/microbitfs.c b/ports/nrf/modules/os/microbitfs.c index f549e6f32e..d8ea5115c9 100644 --- a/ports/nrf/modules/os/microbitfs.c +++ b/ports/nrf/modules/os/microbitfs.c @@ -458,11 +458,18 @@ static mp_uint_t microbit_file_write(mp_obj_t obj, const void *buf, mp_uint_t si return size; } -static void microbit_file_close(file_descriptor_obj *fd) { - if (fd->writable) { - flash_write_byte((uint32_t)&(file_system_chunks[fd->start_chunk].header.end_offset), fd->seek_offset); +static intptr_t microbit_file_ioctl(void *fd_in, uintptr_t request, uintptr_t arg) { + file_descriptor_obj *fd = fd_in; + + if (request == MP_READER_CLOSE) { + if (fd->writable) { + flash_write_byte((uint32_t)&(file_system_chunks[fd->start_chunk].header.end_offset), fd->seek_offset); + } + fd->open = false; + return 0; } - fd->open = false; + + return -MP_EINVAL; } static mp_obj_t microbit_file_list(void) { @@ -495,7 +502,7 @@ static mp_obj_t microbit_file_size(mp_obj_t filename) { return mp_obj_new_int(len); } -static mp_uint_t file_read_byte(file_descriptor_obj *fd) { +static uintptr_t file_read_byte(file_descriptor_obj *fd) { if (file_system_chunks[fd->seek_chunk].next_chunk == UNUSED_CHUNK) { uint8_t end_offset = file_system_chunks[fd->start_chunk].header.end_offset; if (end_offset == UNUSED_CHUNK || fd->seek_offset == end_offset) { @@ -516,8 +523,8 @@ mp_lexer_t *os_mbfs_new_reader(const char *filename) { } mp_reader_t reader; reader.data = fd; - reader.readbyte = (mp_uint_t(*)(void*))file_read_byte; - reader.close = (void(*)(void*))microbit_file_close; // no-op + reader.readbyte = (uintptr_t(*)(void*))file_read_byte; + reader.close = microbit_file_ioctl; return mp_lexer_new(qstr_from_str(filename), reader); } @@ -538,7 +545,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(os_mbfs_file_name_obj, os_mbfs_file_name); static mp_obj_t os_mbfs_file_close(mp_obj_t self) { file_descriptor_obj *fd = (file_descriptor_obj*)self; - microbit_file_close(fd); + microbit_file_ioctl(fd, MP_READER_CLOSE, 0); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_1(os_mbfs_file_close_obj, os_mbfs_file_close); diff --git a/py/lexer.c b/py/lexer.c index bff8e63765..1f4a614c5a 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -908,7 +908,7 @@ mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) { void mp_lexer_free(mp_lexer_t *lex) { if (lex) { - lex->reader.close(lex->reader.data); + lex->reader.ioctl(lex->reader.data, MP_READER_CLOSE, 0); vstr_clear(&lex->vstr); #if MICROPY_PY_FSTRINGS vstr_clear(&lex->fstring_args); diff --git a/py/persistentcode.c b/py/persistentcode.c index 5088c05f03..208231530c 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -393,9 +393,14 @@ static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co return rc; } +static void reader_close(void *reader_in) { + mp_reader_t *reader = reader_in; + reader->ioctl(reader->data, MP_READER_CLOSE, 0); +} + void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { // Set exception handler to close the reader if an exception is raised. - MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, reader->close, reader->data); + MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, reader_close, reader); nlr_push_jump_callback(&ctx.callback, mp_call_function_1_from_nlr_jump_callback); byte header[4]; diff --git a/py/reader.c b/py/reader.c index 151e04cac2..8232de55ca 100644 --- a/py/reader.c +++ b/py/reader.c @@ -39,7 +39,7 @@ typedef struct _mp_reader_mem_t { const byte *end; } mp_reader_mem_t; -static mp_uint_t mp_reader_mem_readbyte(void *data) { +static uintptr_t mp_reader_mem_readbyte(void *data) { mp_reader_mem_t *reader = (mp_reader_mem_t *)data; if (reader->cur < reader->end) { return *reader->cur++; @@ -48,12 +48,18 @@ static mp_uint_t mp_reader_mem_readbyte(void *data) { } } -static void mp_reader_mem_close(void *data) { +static intptr_t mp_reader_mem_ioctl(void *data, uintptr_t request, uintptr_t arg) { mp_reader_mem_t *reader = (mp_reader_mem_t *)data; - if (reader->free_len > 0) { - m_del(char, (char *)reader->beg, reader->free_len); + + if (request == MP_READER_CLOSE) { + if (reader->free_len > 0) { + m_del(char, (char *)reader->beg, reader->free_len); + } + m_del_obj(mp_reader_mem_t, reader); + return 0; } - m_del_obj(mp_reader_mem_t, reader); + + return -MP_EINVAL; } void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len) { @@ -64,7 +70,7 @@ void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t rm->end = buf + len; reader->data = rm; reader->readbyte = mp_reader_mem_readbyte; - reader->close = mp_reader_mem_close; + reader->ioctl = mp_reader_mem_ioctl; } #if MICROPY_READER_POSIX @@ -81,7 +87,7 @@ typedef struct _mp_reader_posix_t { byte buf[20]; } mp_reader_posix_t; -static mp_uint_t mp_reader_posix_readbyte(void *data) { +static uintptr_t mp_reader_posix_readbyte(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t *)data; if (reader->pos >= reader->len) { if (reader->len == 0) { @@ -101,14 +107,20 @@ static mp_uint_t mp_reader_posix_readbyte(void *data) { return reader->buf[reader->pos++]; } -static void mp_reader_posix_close(void *data) { +static intptr_t mp_reader_posix_ioctl(void *data, uintptr_t request, uintptr_t arg) { mp_reader_posix_t *reader = (mp_reader_posix_t *)data; - if (reader->close_fd) { - MP_THREAD_GIL_EXIT(); - close(reader->fd); - MP_THREAD_GIL_ENTER(); + + if (request == MP_READER_CLOSE) { + if (reader->close_fd) { + MP_THREAD_GIL_EXIT(); + close(reader->fd); + MP_THREAD_GIL_ENTER(); + } + m_del_obj(mp_reader_posix_t, reader); + return 0; } - m_del_obj(mp_reader_posix_t, reader); + + return -MP_EINVAL; } void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) { @@ -129,7 +141,7 @@ void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) { rp->pos = 0; reader->data = rp; reader->readbyte = mp_reader_posix_readbyte; - reader->close = mp_reader_posix_close; + reader->ioctl = mp_reader_posix_ioctl; } #if !MICROPY_VFS_POSIX diff --git a/py/reader.h b/py/reader.h index 5cb1e67966..7d763e4ff6 100644 --- a/py/reader.h +++ b/py/reader.h @@ -28,15 +28,23 @@ #include "py/obj.h" -// the readbyte function must return the next byte in the input stream -// it must return MP_READER_EOF if end of stream -// it can be called again after returning MP_READER_EOF, and in that case must return MP_READER_EOF -#define MP_READER_EOF ((mp_uint_t)(-1)) +#define MP_READER_EOF ((uintptr_t)(-1)) + +// Reader ioctl request codes. +#define MP_READER_CLOSE (1) typedef struct _mp_reader_t { + // Pointer to the context of this reader, passed as the first argument to the methods below. void *data; - mp_uint_t (*readbyte)(void *data); - void (*close)(void *data); + + // The readbyte function must return the next byte in the input stream. + // It must return MP_READER_EOF if end of stream. It can be called again after returning + // MP_READER_EOF, and in that case must return MP_READER_EOF. + uintptr_t (*readbyte)(void *data); + + // Ioctl method for performing various control actions. + // On error it must return a negative errno value. + intptr_t (*ioctl)(void *data, uintptr_t request, uintptr_t arg); } mp_reader_t; void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t free_len); diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index a305e6a5df..144184705c 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -34,6 +34,7 @@ #include "py/repl.h" #include "py/gc.h" #include "py/frozenmod.h" +#include "py/mperrno.h" #include "py/mphal.h" #if MICROPY_HW_ENABLE_USB #include "irq.h" @@ -135,7 +136,7 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) { const mp_reader_t *reader = source; - reader->close(reader->data); + reader->ioctl(reader->data, MP_READER_CLOSE, 0); } // print EOF after normal output @@ -201,7 +202,7 @@ typedef struct _mp_reader_stdin_t { uint16_t window_remain; } mp_reader_stdin_t; -static mp_uint_t mp_reader_stdin_readbyte(void *data) { +static uintptr_t mp_reader_stdin_readbyte(void *data) { mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data; if (reader->eof) { @@ -233,18 +234,24 @@ static mp_uint_t mp_reader_stdin_readbyte(void *data) { return c; } -static void mp_reader_stdin_close(void *data) { +static intptr_t mp_reader_stdin_ioctl(void *data, uintptr_t request, uintptr_t arg) { mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data; - if (!reader->eof) { - reader->eof = true; - mp_hal_stdout_tx_strn("\x04", 1); // indicate end to host - for (;;) { - int c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C || c == CHAR_CTRL_D) { - break; + + if (request == MP_READER_CLOSE) { + if (!reader->eof) { + reader->eof = true; + mp_hal_stdout_tx_strn("\x04", 1); // indicate end to host + for (;;) { + int c = mp_hal_stdin_rx_chr(); + if (c == CHAR_CTRL_C || c == CHAR_CTRL_D) { + break; + } } } + return 0; } + + return -MP_EINVAL; } static void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_stdin, uint16_t buf_max) { @@ -260,7 +267,7 @@ static void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_s reader_stdin->window_remain = window; reader->data = reader_stdin; reader->readbyte = mp_reader_stdin_readbyte; - reader->close = mp_reader_stdin_close; + reader->ioctl = mp_reader_stdin_ioctl; } static int do_reader_stdin(int c) {