diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index ec20daff4b23d..bdaf83cfc80ed 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -50,32 +50,29 @@ int pyexec_system_exit = 0; STATIC bool repl_display_debugging_info = 0; #endif -#define EXEC_FLAG_PRINT_EOF (1) -#define EXEC_FLAG_ALLOW_DEBUGGING (2) -#define EXEC_FLAG_IS_REPL (4) -#define EXEC_FLAG_SOURCE_IS_RAW_CODE (8) -#define EXEC_FLAG_SOURCE_IS_VSTR (16) -#define EXEC_FLAG_SOURCE_IS_FILENAME (32) - -// parses, compiles and executes the code in the lexer -// frees the lexer before returning -// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output -// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code -// EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) -STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) { +// Parses, compiles and executes the code in the lexer. +// Frees the lexer before returning. +// Returns 0 for success, non-zero for an error or SystemExit. +// PYEXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output +// PYEXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code +// PYEXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) +int pyexec_exec_src(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; #if MICROPY_REPL_INFO uint32_t start = 0; #endif - // by default a SystemExit exception returns 0 - pyexec_system_exit = 0; + // By default a SystemExit exception returns a value based on its argument. + #ifndef MICROPY_PYEXEC_SYSTEM_EXIT_DEFAULT + #define MICROPY_PYEXEC_SYSTEM_EXIT_DEFAULT (0) + #endif + pyexec_system_exit = MICROPY_PYEXEC_SYSTEM_EXIT_DEFAULT; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t module_fun; #if MICROPY_MODULE_FROZEN_MPY - if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { + if (exec_flags & PYEXEC_FLAG_SOURCE_IS_RAW_CODE) { // source is a raw_code object, create the function module_fun = mp_make_function_from_raw_code(source, MP_OBJ_NULL, MP_OBJ_NULL); } else @@ -83,34 +80,55 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input { #if MICROPY_ENABLE_COMPILER mp_lexer_t *lex; - if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { + if (exec_flags & PYEXEC_FLAG_SOURCE_IS_VSTR) { const vstr_t *vstr = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); - } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { + } else if (exec_flags & PYEXEC_FLAG_SOURCE_IS_FILENAME) { lex = mp_lexer_new_from_file(source); + #if MICROPY_HELPER_LEXER_UNIX + } else if (exec_flags & PYEXEC_FLAG_SOURCE_IS_FD) { + int fd = (int)(intptr_t)source; + lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, fd, false); + #endif } else { lex = (mp_lexer_t *)source; } // source is a lexer, parse and compile the script qstr source_name = lex->source_name; + #if MICROPY_PY___FILE__ + if (input_kind == MP_PARSE_FILE_INPUT) { + mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); + } + #endif mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); + #if defined(MICROPY_UNIX_COVERAGE) + // allow to print the parse tree in the coverage build + if (mp_verbose_flag >= 3) { + printf("----------------\n"); + mp_parse_node_print(parse_tree.root, 0); + printf("----------------\n"); + } + #endif + module_fun = mp_compile(&parse_tree, source_name, exec_flags & PYEXEC_FLAG_IS_REPL); #else mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported"); #endif } // execute code - mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us - #if MICROPY_REPL_INFO - start = mp_hal_ticks_ms(); - #endif - mp_call_function_0(module_fun); - mp_hal_set_interrupt_char(-1); // disable interrupt - mp_handle_pending(true); // handle any pending exceptions (and any callbacks) + if (!(exec_flags & PYEXEC_FLAG_COMPILE_ONLY)) { + mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us + #if MICROPY_REPL_INFO + start = mp_hal_ticks_ms(); + #endif + mp_call_function_0(module_fun); + mp_hal_set_interrupt_char(-1); // disable interrupt + mp_handle_pending(true); // handle any pending exceptions (and any callbacks) + } + nlr_pop(); - ret = 1; - if (exec_flags & EXEC_FLAG_PRINT_EOF) { + ret = 0; + if (exec_flags & PYEXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } } else { @@ -118,22 +136,15 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input mp_hal_set_interrupt_char(-1); // disable interrupt mp_handle_pending(false); // clear any pending exceptions (and run any callbacks) // print EOF after normal output - if (exec_flags & EXEC_FLAG_PRINT_EOF) { + if (exec_flags & PYEXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } - // check for SystemExit - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // at the moment, the value of SystemExit is unused - ret = pyexec_system_exit; - } else { - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); - ret = 0; - } + ret = pyexec_handle_uncaught_exception(nlr.ret_val); } #if MICROPY_REPL_INFO // display debugging info if wanted - if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { + if ((exec_flags & PYEXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly printf("took " UINT_FMT " ms\n", ticks); // qstr info @@ -153,13 +164,34 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input } #endif - if (exec_flags & EXEC_FLAG_PRINT_EOF) { + if (exec_flags & PYEXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } return ret; } +// If exc is SystemExit, return pyexec_system_exit or'd with lower 8 bits of SystemExit value. +// For all other exceptions, return 1. +int pyexec_handle_uncaught_exception(mp_obj_base_t *exc) { + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { + // SystemExit was raised, evaluate its argument: + // - None is an exit value of 0; + // - an int is its value; + // - anything else is 1. + mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); + mp_int_t val = 0; + if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { + val = 1; + } + return pyexec_system_exit | (val & 255); + } else { + // Report all other exceptions and return 1 to indicate error. + mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(exc)); + return 1; + } +} + #if MICROPY_ENABLE_COMPILER #if MICROPY_REPL_EVENT_DRIVEN @@ -226,7 +258,7 @@ STATIC int pyexec_raw_repl_process_char(int c) { return PYEXEC_FORCED_EXIT; } - int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR); + int ret = pyexec_exec_src(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, PYEXEC_FLAG_PRINT_EOF | PYEXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -247,7 +279,7 @@ STATIC int pyexec_friendly_repl_process_char(int c) { } else if (c == CHAR_CTRL_D) { // end of input mp_hal_stdout_tx_str("\r\n"); - int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); + int ret = pyexec_exec_src(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, PYEXEC_FLAG_ALLOW_DEBUGGING | PYEXEC_FLAG_IS_REPL | PYEXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -336,7 +368,7 @@ STATIC int pyexec_friendly_repl_process_char(int c) { } exec:; - int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); + int ret = pyexec_exec_src(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, PYEXEC_FLAG_ALLOW_DEBUGGING | PYEXEC_FLAG_IS_REPL | PYEXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -408,7 +440,7 @@ int pyexec_raw_repl(void) { return PYEXEC_FORCED_EXIT; } - int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR); + int ret = pyexec_exec_src(&line, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_PRINT_EOF | PYEXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -426,7 +458,12 @@ int pyexec_friendly_repl(void) { #endif friendly_repl_reset: + #ifdef MICROPY_HW_BOARD_NAME mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); + #else + mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_PY_SYS_PLATFORM " version\r\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); + #endif + #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); #endif @@ -450,6 +487,8 @@ int pyexec_friendly_repl(void) { */ for (;;) { + mp_hal_stdio_mode_raw(); + input_restart: #if MICROPY_HW_ENABLE_USB @@ -478,20 +517,23 @@ int pyexec_friendly_repl(void) { if (ret == CHAR_CTRL_A) { // change to raw REPL mp_hal_stdout_tx_str("\r\n"); + mp_hal_stdio_mode_orig(); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); + mp_hal_stdio_mode_orig(); goto friendly_repl_reset; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); - continue; + goto input_restart; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); + mp_hal_stdio_mode_orig(); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { @@ -520,7 +562,10 @@ int pyexec_friendly_repl(void) { } parse_input_kind = MP_PARSE_FILE_INPUT; } else if (vstr_len(&line) == 0) { - continue; + if (ret != 0) { + mp_hal_stdout_tx_str("\r\n"); + } + goto input_restart; } else { // got a line with non-zero length, see if it needs continuing while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { @@ -537,7 +582,9 @@ int pyexec_friendly_repl(void) { } } - ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); + mp_hal_stdio_mode_orig(); + + ret = pyexec_exec_src(&line, parse_input_kind, PYEXEC_FLAG_ALLOW_DEBUGGING | PYEXEC_FLAG_IS_REPL | PYEXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -548,7 +595,7 @@ int pyexec_friendly_repl(void) { #endif // MICROPY_ENABLE_COMPILER int pyexec_file(const char *filename) { - return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME); + return pyexec_exec_src(filename, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_SOURCE_IS_FILENAME); } int pyexec_file_if_exists(const char *filename) { @@ -571,12 +618,12 @@ int pyexec_frozen_module(const char *name) { switch (frozen_type) { #if MICROPY_MODULE_FROZEN_STR case MP_FROZEN_STR: - return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0); + return pyexec_exec_src(frozen_data, MP_PARSE_FILE_INPUT, 0); #endif #if MICROPY_MODULE_FROZEN_MPY case MP_FROZEN_MPY: - return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE); + return pyexec_exec_src(frozen_data, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_SOURCE_IS_RAW_CODE); #endif default: diff --git a/lib/utils/pyexec.h b/lib/utils/pyexec.h index f69c5ce9a884e..962a3422970d0 100644 --- a/lib/utils/pyexec.h +++ b/lib/utils/pyexec.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H #include "py/obj.h" +#include "py/parse.h" typedef enum { PYEXEC_MODE_FRIENDLY_REPL, @@ -40,9 +41,22 @@ extern pyexec_mode_kind_t pyexec_mode_kind; // It will reset to 0 at the start of each execution (eg each REPL entry). extern int pyexec_system_exit; +#define PYEXEC_FLAG_PRINT_EOF (0x0001) +#define PYEXEC_FLAG_ALLOW_DEBUGGING (0x0002) +#define PYEXEC_FLAG_IS_REPL (0x0004) +#define PYEXEC_FLAG_COMPILE_ONLY (0x0008) +#define PYEXEC_FLAG_SOURCE_IS_RAW_CODE (0x0010) +#define PYEXEC_FLAG_SOURCE_IS_VSTR (0x0020) +#define PYEXEC_FLAG_SOURCE_IS_FILENAME (0x0040) +#if MICROPY_HELPER_LEXER_UNIX +#define PYEXEC_FLAG_SOURCE_IS_FD (0x0080) +#endif + #define PYEXEC_FORCED_EXIT (0x100) #define PYEXEC_SWITCH_MODE (0x200) +int pyexec_exec_src(const void *source, mp_parse_input_kind_t input_kind, int exec_flags); +int pyexec_handle_uncaught_exception(mp_obj_base_t *exc); int pyexec_raw_repl(void); int pyexec_friendly_repl(void); int pyexec_file(const char *filename); diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index f06a502776087..be7688316e07f 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -185,7 +185,7 @@ void TASK_MicroPython (void *pvParameters) { if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } - if (!ret) { + if (ret) { // flash the system led mperror_signal_error(); } @@ -210,7 +210,7 @@ void TASK_MicroPython (void *pvParameters) { if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } - if (!ret) { + if (ret) { // flash the system led mperror_signal_error(); } diff --git a/ports/stm32/main.c b/ports/stm32/main.c index b5dbfa50fd5cc..4c762f8d9ad89 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -660,7 +660,7 @@ void stm32_main(uint32_t reset_mode) { if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } - if (!ret) { + if (ret) { flash_error(4); } } @@ -721,7 +721,7 @@ void stm32_main(uint32_t reset_mode) { if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } - if (!ret) { + if (ret) { flash_error(3); } } diff --git a/ports/teensy/main.c b/ports/teensy/main.c index df3fd1ffcf5ac..1f27686266dbb 100644 --- a/ports/teensy/main.c +++ b/ports/teensy/main.c @@ -302,7 +302,7 @@ int main(void) { #if MICROPY_MODULE_FROZEN pyexec_frozen_module("boot.py"); #else - if (!pyexec_file_if_exists("/boot.py")) { + if (pyexec_file_if_exists("/boot.py")) { flash_error(4); } #endif @@ -322,7 +322,7 @@ int main(void) { } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } - if (!pyexec_file_if_exists(vstr_null_terminated_str(vstr))) { + if (pyexec_file_if_exists(vstr_null_terminated_str(vstr))) { flash_error(3); } vstr_free(vstr); diff --git a/ports/unix/Makefile b/ports/unix/Makefile index ec14166149ba8..00ac7f82aa430 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -206,6 +206,7 @@ LIB_SRC_C += $(addprefix lib/,\ $(LIB_SRC_C_EXTRA) \ timeutils/timeutils.c \ utils/gchelper_generic.c \ + utils/pyexec.c \ ) OBJ = $(PY_O) diff --git a/ports/unix/main.c b/ports/unix/main.c index 5251fe8ae29a6..3910dffc7617a 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -46,6 +46,7 @@ #include "py/stackctrl.h" #include "py/mphal.h" #include "py/mpthread.h" +#include "lib/utils/pyexec.h" #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_posix.h" @@ -53,7 +54,7 @@ #include "input.h" // Command line options, with their defaults -STATIC bool compile_only = false; +STATIC int compile_only = 0; STATIC uint emit_opt = MP_EMIT_OPT_NONE; #if MICROPY_ENABLE_GC @@ -71,93 +72,6 @@ STATIC void stderr_print_strn(void *env, const char *str, size_t len) { const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; -#define FORCED_EXIT (0x100) -// If exc is SystemExit, return value where FORCED_EXIT bit set, -// and lower 8 bits are SystemExit value. For all other exceptions, -// return 1. -STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { - // check for SystemExit - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // None is an exit value of 0; an int is its value; anything else is 1 - mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); - mp_int_t val = 0; - if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { - val = 1; - } - return FORCED_EXIT | (val & 255); - } - - // Report all other exceptions - mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(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(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__ - if (input_kind == MP_PARSE_FILE_INPUT) { - mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); - } - #endif - - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - - #if defined(MICROPY_UNIX_COVERAGE) - // allow to print the parse tree in the coverage build - if (mp_verbose_flag >= 3) { - printf("----------------\n"); - mp_parse_node_print(parse_tree.root, 0); - printf("----------------\n"); - } - #endif - - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); - - if (!compile_only) { - // execute it - mp_call_function_0(module_fun); - } - - mp_hal_set_interrupt_char(-1); - mp_handle_pending(true); - nlr_pop(); - return 0; - - } else { - // uncaught exception - mp_hal_set_interrupt_char(-1); - mp_handle_pending(false); - return handle_uncaught_exception(nlr.ret_val); - } -} - #if MICROPY_USE_READLINE == 1 #include "lib/mp-readline/readline.h" #else @@ -177,91 +91,18 @@ STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { #endif STATIC int do_repl(void) { - mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " - MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - #if MICROPY_USE_READLINE == 1 // use MicroPython supplied readline - - vstr_t line; - vstr_init(&line, 16); - for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, ">>> "); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; - - if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); - } - goto input_restart; - } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, "... "); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } - } - } - - mp_hal_stdio_mode_orig(); - - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } - } + return pyexec_friendly_repl(); #else // use simple readline + mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " + MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); + for (;;) { char *line = prompt(">>> "); if (line == NULL) { @@ -279,8 +120,11 @@ STATIC int do_repl(void) { line = line3; } - int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); - if (ret & FORCED_EXIT) { + vstr_t vstr; + vstr.buf = (char *)line; + vstr.len = strlen(line); + int ret = pyexec_exec_src(&vstr, MP_PARSE_SINGLE_INPUT, PYEXEC_FLAG_IS_REPL | PYEXEC_FLAG_SOURCE_IS_VSTR | compile_only); + if (ret & PYEXEC_FORCED_EXIT) { return ret; } free(line); @@ -290,11 +134,14 @@ STATIC int do_repl(void) { } STATIC int do_file(const char *file) { - return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); + return pyexec_exec_src(file, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_SOURCE_IS_FILENAME | compile_only); } STATIC int do_str(const char *str) { - return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); + vstr_t vstr; + vstr.buf = (char *)str; + vstr.len = strlen(str); + return pyexec_exec_src(&vstr, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_SOURCE_IS_VSTR | compile_only); } STATIC void print_help(char **argv) { @@ -351,7 +198,7 @@ STATIC void pre_process_options(int argc, char **argv) { } if (0) { } else if (strcmp(argv[a + 1], "compile-only") == 0) { - compile_only = true; + compile_only = PYEXEC_FLAG_COMPILE_ONLY; } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE @@ -567,7 +414,7 @@ MP_NOINLINE int main_(int argc, char **argv) { return invalid_args(); } ret = do_str(argv[a + 1]); - if (ret & FORCED_EXIT) { + if (ret & PYEXEC_FORCED_EXIT) { break; } a += 1; @@ -598,7 +445,7 @@ MP_NOINLINE int main_(int argc, char **argv) { nlr_pop(); } else { // uncaught exception - return handle_uncaught_exception(nlr.ret_val) & 0xff; + return pyexec_handle_uncaught_exception(nlr.ret_val) & 0xff; } if (mp_obj_is_package(mod) && !subpkg_tried) { @@ -662,7 +509,7 @@ MP_NOINLINE int main_(int argc, char **argv) { ret = do_repl(); prompt_write_history(); } else { - ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); + ret = pyexec_exec_src((void*)(uintptr_t)STDIN_FILENO, MP_PARSE_FILE_INPUT, PYEXEC_FLAG_SOURCE_IS_FD | compile_only); } } diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index f3c61c18f100d..055752a6b9996 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -357,4 +357,6 @@ struct _mp_bluetooth_btstack_root_pointers_t; #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); +#define MICROPY_PYEXEC_SYSTEM_EXIT_DEFAULT (PYEXEC_FORCED_EXIT) + #endif // MICROPY_UNIX_MINIMAL diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h index 95ad63221ef95..2dec22e94be11 100644 --- a/ports/unix/mphalport.h +++ b/ports/unix/mphalport.h @@ -32,10 +32,13 @@ void mp_hal_set_interrupt_char(char c); -#define mp_hal_stdio_poll unused // this is not implemented, nor needed +#define mp_hal_stdio_mode_raw mp_hal_stdio_mode_raw +#define mp_hal_stdio_mode_orig mp_hal_stdio_mode_orig void mp_hal_stdio_mode_raw(void); void mp_hal_stdio_mode_orig(void); +#define mp_hal_stdio_poll unused // this is not implemented, nor needed + #if MICROPY_PY_BUILTINS_INPUT && MICROPY_USE_READLINE == 0 #include diff --git a/py/mphal.h b/py/mphal.h index 66d80705a60ee..f73a961ad9862 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -34,6 +34,14 @@ #include #endif +#ifndef mp_hal_stdio_mode_raw +#define mp_hal_stdio_mode_raw() +#endif + +#ifndef mp_hal_stdio_mode_orig +#define mp_hal_stdio_mode_orig() +#endif + #ifndef mp_hal_stdio_poll uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags); #endif pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy