int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); raw_repl_reset: stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); for (;;) { vstr_reset(&line); stdout_tx_str(">"); for (;;) { char c = stdin_rx_chr(); if (c == VCP_CHAR_CTRL_A) { // reset raw REPL goto raw_repl_reset; } else if (c == VCP_CHAR_CTRL_B) { // change to friendly REPL stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; return 0; } else if (c == VCP_CHAR_CTRL_C) { // clear line vstr_reset(&line); } else if (c == VCP_CHAR_CTRL_D) { // input finished break; } else if (c <= 127) { // let through any other ASCII character vstr_add_char(&line, c); } } // indicate reception of command stdout_tx_str("OK"); if (line.len == 0) { // exit for a soft reset stdout_tx_str("\r\n"); vstr_clear(&line); return 1; } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0); if (lex == NULL) { printf("MemoryError\n"); } else { parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false); } // indicate end of output with EOF character stdout_tx_str("\004"); } }
int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); raw_repl_reset: mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); for (;;) { vstr_reset(&line); mp_hal_stdout_tx_str(">"); for (;;) { int c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_A) { // reset raw REPL goto raw_repl_reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(&line); } else if (c == CHAR_CTRL_D) { // input finished break; } else if (c <= 127) { // let through any other ASCII character vstr_add_char(&line, c); } } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (line.len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0); if (lex == NULL) { printf("\x04MemoryError\n\x04"); } else { int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } } }
int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); raw_repl_reset: mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); for (;;) { vstr_reset(&line); mp_hal_stdout_tx_str(">"); for (;;) { int c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_A) { // reset raw REPL goto raw_repl_reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(&line); } else if (c == CHAR_CTRL_D) { // input finished break; } else { // let through any other raw 8-bit value vstr_add_byte(&line, c); } } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (line.len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } }
STATIC void adv_event_handler(mp_obj_t self_in, uint16_t event_id, ble_drv_adv_data_t * data) { ubluepy_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); ubluepy_scan_entry_obj_t * item = m_new_obj(ubluepy_scan_entry_obj_t); item->base.type = &ubluepy_scan_entry_type; vstr_t vstr; vstr_init(&vstr, 17); vstr_printf(&vstr, ""HEX2_FMT":"HEX2_FMT":"HEX2_FMT":" \ HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", data->p_peer_addr[5], data->p_peer_addr[4], data->p_peer_addr[3], data->p_peer_addr[2], data->p_peer_addr[1], data->p_peer_addr[0]); item->addr = mp_obj_new_str(vstr.buf, vstr.len); vstr_clear(&vstr); item->addr_type = data->addr_type; item->rssi = data->rssi; item->data = mp_obj_new_bytearray(data->data_len, data->p_data); mp_obj_list_append(self->adv_reports, item); // Continue scanning ble_drv_scan_start(true); }
void mp_lexer_free(mp_lexer_t *lex) { if (lex) { lex->reader.close(lex->reader.data); vstr_clear(&lex->vstr); m_del(uint16_t, lex->indent_level, lex->alloc_indent_level); m_del_obj(mp_lexer_t, lex); } }
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { vstr_t vstr; vstr_init(&vstr, 8); mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, obj, PRINT_JSON); mp_obj_t ret = mp_obj_new_str(vstr.buf, vstr.len, false); vstr_clear(&vstr); return ret; }
void mp_lexer_free(mp_lexer_t *lex) { if (lex) { if (lex->stream_close) { lex->stream_close(lex->stream_data); } vstr_clear(&lex->vstr); m_del_obj(mp_lexer_t, lex); } }
// Unbuffered, inefficient implementation of readline() for raw I/O files. STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) { const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_READ); mp_int_t max_size = -1; if (n_args > 1) { max_size = MP_OBJ_SMALL_INT_VALUE(args[1]); } vstr_t vstr; if (max_size != -1) { vstr_init(&vstr, max_size); } else { vstr_init(&vstr, 16); } while (max_size == -1 || max_size-- != 0) { char *p = vstr_add_len(&vstr, 1); if (p == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory")); } int error; mp_uint_t out_sz = stream_p->read(args[0], p, 1, &error); if (out_sz == MP_STREAM_ERROR) { if (mp_is_nonblocking_error(error)) { if (vstr.len == 1) { // We just incremented it, but otherwise we read nothing // and immediately got EAGAIN. This case is not well // specified in // https://docs.python.org/3/library/io.html#io.IOBase.readline // unlike similar case for read(). But we follow the latter's // behavior - return None. vstr_clear(&vstr); return mp_const_none; } else { goto done; } } mp_raise_OSError(error); } if (out_sz == 0) { done: // Back out previously added byte // Consider, what's better - read a char and get OutOfMemory (so read // char is lost), or allocate first as we do. vstr_cut_tail_bytes(&vstr, 1); break; } if (*p == '\n') { break; } } return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); }
/// \method getScanData() /// Return list of the scan data tupples (ad_type, description, value) /// STATIC mp_obj_t scan_entry_get_scan_data(mp_obj_t self_in) { ubluepy_scan_entry_obj_t * self = MP_OBJ_TO_PTR(self_in); mp_obj_t retval_list = mp_obj_new_list(0, NULL); // TODO: check if self->data is set mp_obj_array_t * data = MP_OBJ_TO_PTR(self->data); uint16_t byte_index = 0; while (byte_index < data->len) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); uint8_t adv_item_len = ((uint8_t * )data->items)[byte_index]; uint8_t adv_item_type = ((uint8_t * )data->items)[byte_index + 1]; mp_obj_t description = mp_const_none; mp_map_t *constant_map = mp_obj_dict_get_map(ubluepy_constants_ad_types_type.locals_dict); mp_map_elem_t *ad_types_table = MP_OBJ_TO_PTR(constant_map->table); uint16_t num_of_elements = constant_map->used; for (uint16_t i = 0; i < num_of_elements; i++) { mp_map_elem_t element = (mp_map_elem_t)*ad_types_table; ad_types_table++; uint16_t element_value = mp_obj_get_int(element.value); if (adv_item_type == element_value) { qstr key_qstr = MP_OBJ_QSTR_VALUE(element.key); const char * text = qstr_str(key_qstr); size_t len = qstr_len(key_qstr); vstr_t vstr; vstr_init(&vstr, len); vstr_printf(&vstr, "%s", text); description = mp_obj_new_str(vstr.buf, vstr.len); vstr_clear(&vstr); } } t->items[0] = MP_OBJ_NEW_SMALL_INT(adv_item_type); t->items[1] = description; t->items[2] = mp_obj_new_bytearray(adv_item_len - 1, &((uint8_t * )data->items)[byte_index + 2]); mp_obj_list_append(retval_list, MP_OBJ_FROM_PTR(t)); byte_index += adv_item_len + 1; } return retval_list; }
STATIC mp_obj_t stringio_close(mp_obj_t self_in) { mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_CPYTHON_COMPAT vstr_free(self->vstr); self->vstr = NULL; #else vstr_clear(self->vstr); self->vstr->alloc = 0; self->vstr->len = 0; self->pos = 0; #endif return mp_const_none; }
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mp_int_t max_len = mp_obj_get_int(len_in); vstr_t vstr; // +1 to accommodate for trailing \0 vstr_init_len(&vstr, max_len + 1); int err; mp_uint_t len = sock_read(self_in, vstr.buf, max_len, &err); if (len == MP_STREAM_ERROR) { vstr_clear(&vstr); mp_raise_OSError(err); } if (len == 0) { vstr_clear(&vstr); return mp_const_empty_bytes; } vstr.len = len; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) { if (n_args == 1) { mp_obj_print(args[0], PRINT_REPR); } vstr_t line; vstr_init(&line, 16); int ret = readline(&line, ""); if (line.len == 0 && ret == VCP_CHAR_CTRL_D) { nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); } mp_obj_t o = mp_obj_new_str((const byte*)line.buf, line.len, false); vstr_clear(&line); return o; }
STATIC int pyexec_raw_repl_process_char(int c) { if (c == CHAR_CTRL_A) { // reset raw REPL mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); goto reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; repl.cont_line = false; pyexec_friendly_repl_process_char(CHAR_CTRL_B); return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(&repl.line); return 0; } else if (c == CHAR_CTRL_D) { // input finished } else { // let through any other raw 8-bit value vstr_add_byte(&repl.line, c); return 0; } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (repl.line.len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&repl.line); return PYEXEC_FORCED_EXIT; } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, repl.line.buf, repl.line.len, 0); if (lex == NULL) { mp_hal_stdout_tx_str("\x04MemoryError\r\n\x04"); } else { int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } reset: vstr_reset(&repl.line); mp_hal_stdout_tx_str(">"); return 0; }
STATIC int pyexec_raw_repl_process_char(int c) { if (c == CHAR_CTRL_A) { // reset raw REPL mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); goto reset; } else if (c == CHAR_CTRL_B) { // change to friendly REPL pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; vstr_reset(MP_STATE_VM(repl_line)); repl.cont_line = false; pyexec_friendly_repl_process_char(CHAR_CTRL_B); return 0; } else if (c == CHAR_CTRL_C) { // clear line vstr_reset(MP_STATE_VM(repl_line)); return 0; } else if (c == CHAR_CTRL_D) { // input finished } else { // let through any other raw 8-bit value vstr_add_byte(MP_STATE_VM(repl_line), c); return 0; } // indicate reception of command mp_hal_stdout_tx_str("OK"); if (MP_STATE_VM(repl_line)->len == 0) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(MP_STATE_VM(repl_line)); 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); if (ret & PYEXEC_FORCED_EXIT) { return ret; } reset: vstr_reset(MP_STATE_VM(repl_line)); mp_hal_stdout_tx_str(">"); return 0; }
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) { mp_lexer_t *lex = mp_lexer_new_from_file(file); if (lex == NULL) { printf("could not open file '%s' for reading\n", file); return 1; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name; if (source_file == NULL) { source_name = lex->source_name; } else { source_name = qstr_from_str(source_file); } #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, MP_PARSE_FILE_INPUT); mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, emit_opt, false); vstr_t vstr; vstr_init(&vstr, 16); if (output_file == NULL) { vstr_add_str(&vstr, file); vstr_cut_tail_bytes(&vstr, 2); vstr_add_str(&vstr, "mpy"); } else { vstr_add_str(&vstr, output_file); } mp_raw_code_save_file(rc, vstr_null_terminated_str(&vstr)); vstr_clear(&vstr); nlr_pop(); return 0; } else { // uncaught exception mp_obj_print_exception(&mp_stderr_print, (mp_obj_t)nlr.ret_val); return 1; } }
void microbit_display_exception(mp_obj_t exc_in) { mp_uint_t n, *values; mp_obj_exception_get_traceback(exc_in, &n, &values); if (n >= 3) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 50, &print); #if MICROPY_ENABLE_SOURCE_LINE mp_printf(&print, "line %u ", values[1]); #endif if (mp_obj_is_native_exception_instance(exc_in)) { mp_obj_exception_t *exc = exc_in; mp_printf(&print, "%q ", exc->base.type->name); if (exc->args != NULL && exc->args->len != 0) { mp_obj_print_helper(&print, exc->args->items[0], PRINT_STR); } } mp_hal_display_string(vstr_null_terminated_str(&vstr)); vstr_clear(&vstr); } }
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 pyexec_friendly_repl(void) { vstr_t line; vstr_init(&line, 32); #if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD // in host mode, we enable the LCD for the repl mp_obj_t lcd_o = mp_call_function_0(mp_load_name(qstr_from_str("LCD"))); mp_call_function_1(mp_load_attr(lcd_o, qstr_from_str("light")), mp_const_true); #endif friendly_repl_reset: mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); #endif // to test ctrl-C /* { uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef}; for (;;) { nlr_buf_t nlr; printf("pyexec_repl: %p\n", x); mp_hal_set_interrupt_char(CHAR_CTRL_C); if (nlr_push(&nlr) == 0) { for (;;) { } } else { printf("break\n"); } } } */ for (;;) { input_restart: #if defined(USE_DEVICE_MODE) if (usb_vcp_is_enabled()) { // If the user gets to here and interrupts are disabled then // they'll never see the prompt, traceback etc. The USB REPL needs // interrupts to be enabled or no transfers occur. So we try to // do the user a favor and reenable interrupts. if (query_irq() == IRQ_STATE_DISABLED) { enable_irq(IRQ_STATE_ENABLED); mp_hal_stdout_tx_str("PYB: enabling IRQs\r\n"); } } #endif vstr_reset(&line); int ret = readline(&line, ">>> "); mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; if (ret == CHAR_CTRL_A) { // change to raw REPL mp_hal_stdout_tx_str("\r\n"); 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"); goto friendly_repl_reset; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); continue; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== "); vstr_reset(&line); for (;;) { char c = mp_hal_stdin_rx_chr(); if (c == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (c == CHAR_CTRL_D) { // end of input mp_hal_stdout_tx_str("\r\n"); break; } else { // add char to buffer and echo vstr_add_byte(&line, c); if (c == '\r') { mp_hal_stdout_tx_str("\r\n=== "); } else { mp_hal_stdout_tx_strn(&c, 1); } } } parse_input_kind = MP_PARSE_FILE_INPUT; } else if (vstr_len(&line) == 0) { continue; } 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 mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement break; } } } ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } }
ABC_Char *abc_value_to_string(ABC_Value *value) { VString vstr; char buf[LINE_BUF_SIZE]; ABC_Char wc_buf[LINE_BUF_SIZE]; int i; vstr_clear(&vstr); switch (value->type) { case ABC_BOOLEAN_VALUE: if (value->u.bool_val) { abc_mbstowcs("true", wc_buf); } else { abc_mbstowcs("false", wc_buf); } vstr_append_string(&vstr, wc_buf); break; case ABC_INT_VALUE: sprintf(buf, "%d", value->u.int_val); abc_mbstowcs(buf, wc_buf); vstr_append_string(&vstr, wc_buf); break; case ABC_DOUBLE_VALUE: sprintf(buf, "%f", value->u.double_val); abc_mbstowcs(buf, wc_buf); vstr_append_string(&vstr, wc_buf); break; case ABC_STRING_VALUE: vstr_append_string(&vstr, value->u.object->u.str.str); break; case ABC_POINTER_VALUE: sprintf(buf, "(%s:%p)", value->u.pointer.name, value->u.pointer.pointer); abc_mbstowcs(buf, wc_buf); vstr_append_string(&vstr, wc_buf); break; case ABC_NULL_VALUE: abc_mbstowcs("null", wc_buf); vstr_append_string(&vstr, wc_buf); break; case ABC_ARRAY_VALUE: abc_mbstowcs("(", wc_buf); vstr_append_string(&vstr, wc_buf); for (i = 0; i < value->u.object->u.array.size; i++) { ABC_Char *new_str; if (i > 0) { abc_mbstowcs(", ", wc_buf); vstr_append_string(&vstr, wc_buf); } new_str = abc_value_to_string(&value->u.object->u.array.array[i]); vstr_append_string(&vstr, new_str); free(new_str); } abc_mbstowcs(")", wc_buf); vstr_append_string(&vstr, wc_buf); break; default: abc_internal_error(-1, UNKNOWN_VALUE_TYPE_ERR); } return vstr.string; }
STATIC int pyexec_friendly_repl_process_char(int c) { int ret = readline_process_char(c); if (!repl.cont_line) { if (ret == CHAR_CTRL_A) { // change to raw REPL pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; mp_hal_stdout_tx_str("\r\n"); pyexec_raw_repl_process_char(CHAR_CTRL_A); return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); #endif goto input_restart; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(MP_STATE_VM(repl_line)); return PYEXEC_FORCED_EXIT; } if (ret < 0) { return 0; } if (!mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) { goto exec; } vstr_add_byte(MP_STATE_VM(repl_line), '\n'); repl.cont_line = true; readline_note_newline("... "); return 0; } else { if (ret == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); repl.cont_line = false; goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement goto exec; } if (ret < 0) { return 0; } if (mp_repl_continue_with_input(vstr_null_terminated_str(MP_STATE_VM(repl_line)))) { vstr_add_byte(MP_STATE_VM(repl_line), '\n'); readline_note_newline("... "); return 0; } 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); if (ret & PYEXEC_FORCED_EXIT) { return ret; } input_restart: vstr_reset(MP_STATE_VM(repl_line)); repl.cont_line = false; readline_init(MP_STATE_VM(repl_line), ">>> "); return 0; } }
// This function implements a simple non-recursive JSON parser. // // The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt // The parser here will parse any valid JSON and return the correct // corresponding Python object. It allows through a superset of JSON, since // it treats commas and colons as "whitespace", and doesn't care if // brackets/braces are correctly paired. It will raise a ValueError if the // input is outside it's specs. // // Most of the work is parsing the primitives (null, false, true, numbers, // strings). It does 1 pass over the input string and so is easily extended to // being able to parse from a non-seekable stream. It tries to be fast and // small in code size, while not using more RAM than necessary. STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { mp_uint_t len; const char *s = mp_obj_str_get_data(obj, &len); const char *top = s + len; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; for (;;) { cont: if (s == top) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; switch (*s) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': s += 1; goto cont; case 'n': if (s + 3 < top && s[1] == 'u' && s[2] == 'l' && s[3] == 'l') { s += 4; next = mp_const_none; } else { goto fail; } break; case 'f': if (s + 4 < top && s[1] == 'a' && s[2] == 'l' && s[3] == 's' && s[4] == 'e') { s += 5; next = mp_const_false; } else { goto fail; } break; case 't': if (s + 3 < top && s[1] == 'r' && s[2] == 'u' && s[3] == 'e') { s += 4; next = mp_const_true; } else { goto fail; } break; case '"': vstr_reset(&vstr); for (s++; s < top && *s != '"';) { byte c = *s; if (c == '\\') { s++; c = *s; switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { if (s + 4 >= top) { goto fail; } mp_uint_t num = 0; for (int i = 0; i < 4; i++) { c = (*++s | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } num = (num << 4) | c; } vstr_add_char(&vstr, num); goto str_cont; } } } vstr_add_byte(&vstr, c); str_cont: s++; } if (s == top) { goto fail; } s++; next = mp_obj_new_str(vstr.buf, vstr.len, false); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); for (; s < top; s++) { if (*s == '.' || *s == 'E' || *s == 'e') { flt = true; } else if (*s == '-' || unichar_isdigit(*s)) { // pass } else { break; } vstr_add_byte(&vstr, *s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } break; } case '[': next = mp_obj_new_list(0, NULL); enter = true; s += 1; break; case '{': next = mp_obj_new_dict(0); enter = true; s += 1; break; case '}': case ']': { s += 1; if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; } if (stack.len == 0) { // finished; compound object goto success; } stack.len -= 1; stack_top = stack.items[stack.len]; stack_top_type = mp_obj_get_type(stack_top); goto cont; } default: goto fail; } if (stack_top == MP_OBJ_NULL) { stack_top = next; stack_top_type = mp_obj_get_type(stack_top); if (!enter) { // finished; single primitive only goto success; } } else { // append to list or dict if (stack_top_type == &mp_type_list) { mp_obj_list_append(stack_top, next); } else { if (stack_key == MP_OBJ_NULL) { stack_key = next; if (enter) { goto fail; } } else { mp_obj_dict_store(stack_top, stack_key, next); stack_key = MP_OBJ_NULL; } } if (enter) { if (stack.items == NULL) { mp_obj_list_init(&stack, 1); stack.items[0] = stack_top; } else { mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top); } stack_top = next; stack_top_type = mp_obj_get_type(stack_top); } } } success: // eat trailing whitespace while (s < top && unichar_isspace(*s)) { s++; } if (s < top) { // unexpected chars goto fail; } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object goto fail; } vstr_clear(&vstr); return stack_top; fail: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON")); }
int pyexec_friendly_repl(void) { vstr_t line; vstr_init(&line, 32); #if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD // in host mode, we enable the LCD for the repl mp_obj_t lcd_o = mp_call_function_0(mp_load_name(qstr_from_str("LCD"))); mp_call_function_1(mp_load_attr(lcd_o, qstr_from_str("light")), mp_const_true); #endif friendly_repl_reset: mp_hal_stdout_tx_str("Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); // to test ctrl-C /* { uint32_t x[4] = {0x424242, 0xdeaddead, 0x242424, 0xdeadbeef}; for (;;) { nlr_buf_t nlr; printf("pyexec_repl: %p\n", x); mp_hal_set_interrupt_char(CHAR_CTRL_C); if (nlr_push(&nlr) == 0) { for (;;) { } } else { printf("break\n"); } } } */ for (;;) { input_restart: vstr_reset(&line); int ret = readline(&line, ">>> "); if (ret == CHAR_CTRL_A) { // change to raw REPL mp_hal_stdout_tx_str("\r\n"); 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"); goto friendly_repl_reset; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); continue; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); return PYEXEC_FORCED_EXIT; } else if (vstr_len(&line) == 0) { continue; } 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 mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement break; } } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0); if (lex == NULL) { printf("MemoryError\n"); } else { ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } } }
int pyexec_friendly_repl_process_char(int c) { int ret = readline_process_char(c); if (!repl.cont_line) { if (ret == CHAR_CTRL_A) { // change to raw REPL pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; mp_hal_stdout_tx_str("\r\n"); vstr_clear(&repl.line); return PYEXEC_SWITCH_MODE; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL mp_hal_stdout_tx_str("\r\n"); goto friendly_repl_reset; } else if (ret == CHAR_CTRL_C) { // break mp_hal_stdout_tx_str("\r\n"); goto input_restart; } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&repl.line); return PYEXEC_FORCED_EXIT; } else if (vstr_len(&repl.line) == 0) { //goto input_restart; } if (ret < 0) { return 0; } if (!mp_repl_continue_with_input(vstr_null_terminated_str(&repl.line))) { goto exec; } vstr_add_byte(&repl.line, '\n'); repl.cont_line = true; mp_hal_stdout_tx_str("... "); readline_note_newline(); return 0; } else { if (ret == CHAR_CTRL_C) { // cancel everything mp_hal_stdout_tx_str("\r\n"); repl.cont_line = false; goto input_restart; } else if (ret == CHAR_CTRL_D) { // stop entering compound statement goto exec; } if (ret < 0) { return 0; } if (mp_repl_continue_with_input(vstr_null_terminated_str(&repl.line))) { vstr_add_byte(&repl.line, '\n'); mp_hal_stdout_tx_str("... "); readline_note_newline(); return 0; } exec: ; mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&repl.line), vstr_len(&repl.line), 0); if (lex == NULL) { printf("MemoryError\n"); } else { int ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL); if (ret & PYEXEC_FORCED_EXIT) { return ret; } } friendly_repl_reset: // TODO input_restart: pyexec_friendly_repl_reset(); mp_hal_stdout_tx_str(">>> "); return 0; } }
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ); ujson_stream_t s = {stream_obj, stream_p->read, 0, 0}; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; S_NEXT(s); for (;;) { cont: if (S_END(s)) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; byte cur = S_CUR(s); S_NEXT(s); switch (cur) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': goto cont; case 'n': if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') { S_NEXT(s); next = mp_const_none; } else { goto fail; } break; case 'f': if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_false; } else { goto fail; } break; case 't': if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_true; } else { goto fail; } break; case '"': vstr_reset(&vstr); for (; !S_END(s) && S_CUR(s) != '"';) { byte c = S_CUR(s); if (c == '\\') { c = S_NEXT(s); switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { mp_uint_t num = 0; for (int i = 0; i < 4; i++) { c = (S_NEXT(s) | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } num = (num << 4) | c; } vstr_add_char(&vstr, num); goto str_cont; } } } vstr_add_byte(&vstr, c); str_cont: S_NEXT(s); } if (S_END(s)) { goto fail; } S_NEXT(s); next = mp_obj_new_str(vstr.buf, vstr.len, false); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); for (;;) { vstr_add_byte(&vstr, cur); cur = S_CUR(s); if (cur == '.' || cur == 'E' || cur == 'e') { flt = true; } else if (cur == '-' || unichar_isdigit(cur)) { // pass } else { break; } S_NEXT(s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } break; } case '[': next = mp_obj_new_list(0, NULL); enter = true; break; case '{': next = mp_obj_new_dict(0); enter = true; break; case '}': case ']': { if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; } if (stack.len == 0) { // finished; compound object goto success; } stack.len -= 1; stack_top = stack.items[stack.len]; stack_top_type = mp_obj_get_type(stack_top); goto cont; } default: goto fail; } if (stack_top == MP_OBJ_NULL) { stack_top = next; stack_top_type = mp_obj_get_type(stack_top); if (!enter) { // finished; single primitive only goto success; } } else { // append to list or dict if (stack_top_type == &mp_type_list) { mp_obj_list_append(stack_top, next); } else { if (stack_key == MP_OBJ_NULL) { stack_key = next; if (enter) { goto fail; } } else { mp_obj_dict_store(stack_top, stack_key, next); stack_key = MP_OBJ_NULL; } } if (enter) { if (stack.items == NULL) { mp_obj_list_init(&stack, 1); stack.items[0] = stack_top; } else { mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top); } stack_top = next; stack_top_type = mp_obj_get_type(stack_top); } } } success: // eat trailing whitespace while (unichar_isspace(S_CUR(s))) { S_NEXT(s); } if (!S_END(s)) { // unexpected chars goto fail; } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object goto fail; } vstr_clear(&vstr); return stack_top; fail: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON")); }
STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { // What to do if sz < -1? Python docs don't specify this case. // CPython does a readall, but here we silently let negatives through, // and they will cause a MemoryError. mp_int_t sz; if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) { return stream_readall(args[0]); } const mp_stream_p_t *stream_p = mp_get_stream(args[0]); #if MICROPY_PY_BUILTINS_STR_UNICODE if (stream_p->is_text) { // We need to read sz number of unicode characters. Because we don't have any // buffering, and because the stream API can only read bytes, we must read here // in units of bytes and must never over read. If we want sz chars, then reading // sz bytes will never over-read, so we follow this approach, in a loop to keep // reading until we have exactly enough chars. This will be 1 read for text // with ASCII-only chars, and about 2 reads for text with a couple of non-ASCII // chars. For text with lots of non-ASCII chars, it'll be pretty inefficient // in time and memory. vstr_t vstr; vstr_init(&vstr, sz); mp_uint_t more_bytes = sz; mp_uint_t last_buf_offset = 0; while (more_bytes > 0) { char *p = vstr_add_len(&vstr, more_bytes); int error; mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error); if (error != 0) { vstr_cut_tail_bytes(&vstr, more_bytes); if (mp_is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). // Otherwise, return data read so far. // TODO what if we have read only half a non-ASCII char? if (vstr.len == 0) { vstr_clear(&vstr); return mp_const_none; } break; } mp_raise_OSError(error); } if (out_sz < more_bytes) { // Finish reading. // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); if (out_sz == 0) { break; } } // count chars from bytes just read for (mp_uint_t off = last_buf_offset;;) { byte b = vstr.buf[off]; int n; if (!UTF8_IS_NONASCII(b)) { // 1-byte ASCII char n = 1; } else if ((b & 0xe0) == 0xc0) { // 2-byte char n = 2; } else if ((b & 0xf0) == 0xe0) { // 3-byte char n = 3; } else if ((b & 0xf8) == 0xf0) { // 4-byte char n = 4; } else { // TODO n = 5; } if (off + n <= vstr.len) { // got a whole char in n bytes off += n; sz -= 1; last_buf_offset = off; if (off >= vstr.len) { more_bytes = sz; break; } } else { // didn't get a whole char, so work out how many extra bytes are needed for // this partial char, plus bytes for additional chars that we want more_bytes = (off + n - vstr.len) + (sz - 1); break; } } } return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } #endif vstr_t vstr; vstr_init_len(&vstr, sz); int error; mp_uint_t out_sz = mp_stream_rw(args[0], vstr.buf, sz, &error, flags); if (error != 0) { vstr_clear(&vstr); if (mp_is_nonblocking_error(error)) { // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read // "If the object is in non-blocking mode and no bytes are available, // None is returned." // This is actually very weird, as naive truth check will treat // this as EOF. return mp_const_none; } mp_raise_OSError(error); } else { vstr.len = out_sz; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &vstr); } }