STATIC int do_repl(void) { mp_hal_stdout_tx_str("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_PY_SYS_PLATFORM " version\n"); for (;;) { char *line = prompt(">>> "); if (line == NULL) { // EOF return 0; } while (mp_repl_continue_with_input(line)) { char *line2 = prompt("... "); if (line2 == NULL) { break; } char *line3 = strjoin(line, '\n', line2); free(line); free(line2); 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); if (ret & FORCED_EXIT) { return ret; } free(line); } }
STATIC void do_repl(void) { printf("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; UNIX version\n"); for (;;) { char *line = prompt(">>> "); if (line == NULL) { // EOF return; } while (mp_repl_continue_with_input(line)) { char *line2 = prompt("... "); if (line2 == NULL) { break; } char *line3 = strjoin(line, '\n', line2); free(line); free(line2); line = line3; } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, true); free(line); } }
void main_repl(int argc, char **argv) { if (!net_repl_connect()) { } net_repl_packet_t packet; char *line; mp_init(); setup_sys(argc, argv); for (; ;) { // non-blocking net_repl_recv(&packet); switch (packet.type) { case REPL_QUIT: return; case REPL_WAIT: continue; default: break; } if (packet.type == REPL_QUIT) { return; } line = strdup(packet.line); while (mp_repl_continue_with_input(line)) { net_repl_send(REPL_CONTINUE, NULL, false); net_repl_recv(&packet); if (packet.type == REPL_QUIT) { free(line); return; } else if (packet.line_len == 0) { break; } char *joined = strjoin(line, '\n', packet.line); free(line); line = joined; } 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); free(line); if (ret == ERR_SYS_EXIT) { return; } } }
STATIC int do_file(const char *file) { struct stat st; stat(file, &st); if (!S_ISREG(st.st_mode)) { init_console(); printf("Could not locate \"%s\"\n", file); return ERR_FILE_NOT_FOUND; } mp_lexer_t *lex = mp_lexer_new_from_file(file); return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false); }
int main(int argc, char **argv) { mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); pre_process_options(argc, argv); #if MICROPY_ENABLE_GC char *heap = malloc(heap_size); gc_init(heap, heap + heap_size); #endif mp_init(); #ifndef _WIN32 // create keyboard interrupt object MP_STATE_VM(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); #endif char *home = getenv("HOME"); char *path = getenv("MICROPYPATH"); if (path == NULL) { #ifdef MICROPY_PY_SYS_PATH_DEFAULT path = MICROPY_PY_SYS_PATH_DEFAULT; #else path = "~/.micropython/lib:/usr/lib/micropython"; #endif } mp_uint_t path_num = 1; // [0] is for current dir (or base dir of the script) for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { path_num++; if (p != NULL) { p++; } } mp_obj_list_init(mp_sys_path, path_num); mp_obj_t *path_items; mp_obj_list_get(mp_sys_path, &path_num, &path_items); path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); { char *p = path; for (mp_uint_t i = 1; i < path_num; i++) { char *p1 = strchr(p, PATHLIST_SEP_CHAR); if (p1 == NULL) { p1 = p + strlen(p); } if (p[0] == '~' && p[1] == '/' && home != NULL) { // Expand standalone ~ to $HOME CHECKBUF(buf, PATH_MAX); CHECKBUF_APPEND(buf, home, strlen(home)); CHECKBUF_APPEND(buf, p + 1, (size_t)(p1 - p - 1)); path_items[i] = MP_OBJ_NEW_QSTR(qstr_from_strn(buf, CHECKBUF_LEN(buf))); } else { path_items[i] = MP_OBJ_NEW_QSTR(qstr_from_strn(p, p1 - p)); } p = p1 + 1; } } mp_obj_list_init(mp_sys_argv, 0); #if defined(MICROPY_UNIX_COVERAGE) { MP_DECLARE_CONST_FUN_OBJ(extra_coverage_obj); mp_store_global(QSTR_FROM_STR_STATIC("extra_coverage"), (mp_obj_t)&extra_coverage_obj); } #endif // Here is some example code to create a class and instance of that class. // First is the Python, then the C code. // // class TestClass: // pass // test_obj = TestClass() // test_obj.attr = 42 // // mp_obj_t test_class_type, test_class_instance; // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); // mp_store_attr(test_class_instance, QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); /* printf("bytes:\n"); printf(" total %d\n", m_get_total_bytes_allocated()); printf(" cur %d\n", m_get_current_bytes_allocated()); printf(" peak %d\n", m_get_peak_bytes_allocated()); */ const int NOTHING_EXECUTED = -2; int ret = NOTHING_EXECUTED; for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-c") == 0) { if (a + 1 >= argc) { return usage(argv); } ret = do_str(argv[a + 1]); if (ret & FORCED_EXIT) { break; } a += 1; } else if (strcmp(argv[a], "-m") == 0) { if (a + 1 >= argc) { return usage(argv); } mp_obj_t import_args[4]; import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1]), false); import_args[1] = import_args[2] = mp_const_none; // Ask __import__ to handle imported module specially - set its __name__ // to __main__, and also return this leaf module, not top-level package // containing it. import_args[3] = mp_const_false; // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : // "the first element of sys.argv will be the full path to // the module file (while the module file is being located, // the first element will be set to "-m")." set_sys_argv(argv, argc, a + 1); mp_obj_t mod; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); nlr_pop(); } else { // uncaught exception return handle_uncaught_exception((mp_obj_t)nlr.ret_val) & 0xff; } if (mp_obj_is_package(mod)) { // TODO fprintf(stderr, "%s: -m for packages not yet implemented\n", argv[0]); exit(1); } ret = 0; break; } else if (strcmp(argv[a], "-X") == 0) { a += 1; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; } else if (strncmp(argv[a], "-O", 2) == 0) { if (isdigit(argv[a][2])) { MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; } else { MP_STATE_VM(mp_optimise_value) = 0; for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++); } } else { return usage(argv); } } else { char *pathbuf = malloc(PATH_MAX); char *basedir = realpath(argv[a], pathbuf); if (basedir == NULL) { fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[a], errno); perror(""); // CPython exits with 2 in such case ret = 2; break; } // Set base dir of the script as first entry in sys.path char *p = strrchr(basedir, '/'); path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); free(pathbuf); set_sys_argv(argv, argc, a); ret = do_file(argv[a]); break; } } if (ret == NOTHING_EXECUTED) { if (isatty(0)) { prompt_read_history(); 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); } } #if MICROPY_PY_MICROPYTHON_MEM_INFO if (mp_verbose_flag) { mp_micropython_mem_info(0, NULL); } #endif mp_deinit(); #if MICROPY_ENABLE_GC && !defined(NDEBUG) // We don't really need to free memory since we are about to exit the // process, but doing so helps to find memory leaks. free(heap); #endif //printf("total bytes = %d\n", m_get_total_bytes_allocated()); return ret & 0xff; }
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); }
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); }
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(); 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); if (ret & FORCED_EXIT) { return ret; } } #else // use GNU or simple readline for (;;) { char *line = prompt(">>> "); if (line == NULL) { // EOF return 0; } while (mp_repl_continue_with_input(line)) { char *line2 = prompt("... "); if (line2 == NULL) { break; } char *line3 = strjoin(line, '\n', line2); free(line); free(line2); 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); if (ret & FORCED_EXIT) { return ret; } free(line); } #endif }
int do_file(const char *file, uint emit_opt) { mp_lexer_t *lex = mp_lexer_new_from_file(file); return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, emit_opt, false); }
STATIC void do_str(const char *str) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false); execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false); }
STATIC int do_str(const char* line) { 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); }