// 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); }
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); }
mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_byte_t stream_next_byte, mp_lexer_stream_close_t stream_close) { mp_lexer_t *lex = m_new_obj_maybe(mp_lexer_t); // check for memory allocation error if (lex == NULL) { if (stream_close) { stream_close(stream_data); } return NULL; } lex->source_name = src_name; lex->stream_data = stream_data; lex->stream_next_byte = stream_next_byte; lex->stream_close = stream_close; lex->line = 1; lex->column = 1; lex->emit_dent = 0; lex->nested_bracket_level = 0; lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT; lex->num_indent_level = 1; lex->indent_level = m_new_maybe(uint16_t, lex->alloc_indent_level); vstr_init(&lex->vstr, 32); // check for memory allocation error if (lex->indent_level == NULL || vstr_had_error(&lex->vstr)) { mp_lexer_free(lex); return NULL; } // store sentinel for first indentation level lex->indent_level[0] = 0; // preload characters lex->chr0 = stream_next_byte(stream_data); lex->chr1 = stream_next_byte(stream_data); lex->chr2 = stream_next_byte(stream_data); // if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end if (lex->chr0 == MP_LEXER_EOF) { lex->chr0 = '\n'; } else if (lex->chr1 == MP_LEXER_EOF) { if (lex->chr0 == '\r') { lex->chr0 = '\n'; } else if (lex->chr0 != '\n') { lex->chr1 = '\n'; } } else if (lex->chr2 == MP_LEXER_EOF) { if (lex->chr1 == '\r') { lex->chr1 = '\n'; } else if (lex->chr1 != '\n') { lex->chr2 = '\n'; } } // preload first token mp_lexer_next_token_into(lex, true); return lex; }
void usbdbg_init() { irq_enabled=false; vstr_init(&script_buf, 32); mp_const_ide_interrupt = mp_obj_new_exception_msg(&mp_type_Exception, "IDE interrupt"); usbdbg_clear_flags(); }
void usbdbg_init() { script_ready=false; script_running=false; vstr_init(&script_buf, 32); mp_const_ide_interrupt = mp_obj_new_exception_msg(&mp_type_Exception, "IDE interrupt"); }
mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) { mp_lexer_t *lex = m_new_obj(mp_lexer_t); lex->source_name = src_name; lex->reader = reader; lex->line = 1; lex->column = (size_t)-2; // account for 3 dummy bytes lex->emit_dent = 0; lex->nested_bracket_level = 0; lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT; lex->num_indent_level = 1; lex->indent_level = m_new(uint16_t, lex->alloc_indent_level); vstr_init(&lex->vstr, 32); // store sentinel for first indentation level lex->indent_level[0] = 0; // load lexer with start of file, advancing lex->column to 1 // start with dummy bytes and use next_char() for proper EOL/EOF handling lex->chr0 = lex->chr1 = lex->chr2 = 0; next_char(lex); next_char(lex); next_char(lex); // preload first token mp_lexer_to_next(lex); // Check that the first token is in the first column. If it's not then we // convert the token kind to INDENT so that the parser gives a syntax error. if (lex->tok_column != 1) { lex->tok_kind = MP_TOKEN_INDENT; } return 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 pyexec_event_repl_init(void) { vstr_init(&repl.line, 32); repl.cont_line = false; readline_init(&repl.line, ">>> "); if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { pyexec_raw_repl_process_char(CHAR_CTRL_A); } else { pyexec_friendly_repl_process_char(CHAR_CTRL_B); } }
static int vstr_chan_init(struct vstr_chan_t *self_p) { chan_init(&self_p->base, chan_read_null, (chan_write_fn_t)vstr_chan_write, chan_size_null); vstr_init(&self_p->string, 128); return (0); }
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: 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"); } }
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_STR); } vstr_t line; vstr_init(&line, 16); int ret = readline(&line, ""); if (line.len == 0 && ret == CHAR_CTRL_D) { nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); } return mp_obj_new_str_from_vstr(&mp_type_str, &line); }
/// \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; }
int main(void) { unsigned long magic_num = 0xF0F0; unsigned long val = 1; if (!vstr_cntl_opt(666, magic_num, val)) exit (EXIT_FAILED_OK); if (vstr_init()) /* should fail */ exit (EXIT_FAILURE); exit (EXIT_SUCCESS); }
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; }
mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) { mp_lexer_t *lex = m_new_obj(mp_lexer_t); lex->source_name = src_name; lex->reader = reader; lex->line = 1; lex->column = 1; lex->emit_dent = 0; lex->nested_bracket_level = 0; lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT; lex->num_indent_level = 1; lex->indent_level = m_new(uint16_t, lex->alloc_indent_level); vstr_init(&lex->vstr, 32); // store sentinel for first indentation level lex->indent_level[0] = 0; // preload characters lex->chr0 = reader.readbyte(reader.data); lex->chr1 = reader.readbyte(reader.data); lex->chr2 = reader.readbyte(reader.data); // if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end if (lex->chr0 == MP_LEXER_EOF) { lex->chr0 = '\n'; } else if (lex->chr1 == MP_LEXER_EOF) { if (lex->chr0 == '\r') { lex->chr0 = '\n'; } else if (lex->chr0 != '\n') { lex->chr1 = '\n'; } } else if (lex->chr2 == MP_LEXER_EOF) { if (lex->chr1 == '\r') { lex->chr1 = '\n'; } else if (lex->chr1 != '\n') { lex->chr2 = '\n'; } } // preload first token mp_lexer_to_next(lex); // Check that the first token is in the first column. If it's not then we // convert the token kind to INDENT so that the parser gives a syntax error. if (lex->tok_column != 1) { lex->tok_kind = MP_TOKEN_INDENT; } return lex; }
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 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; } }
mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close) { mp_lexer_t *lex = m_new(mp_lexer_t, 1); lex->name = src_name; // TODO do we need to strdup this? lex->stream_data = stream_data; lex->stream_next_char = stream_next_char; lex->stream_close = stream_close; lex->line = 1; lex->column = 1; lex->emit_dent = 0; lex->nested_bracket_level = 0; lex->alloc_indent_level = 16; lex->num_indent_level = 1; lex->indent_level = m_new(uint16_t, lex->alloc_indent_level); lex->indent_level[0] = 0; vstr_init(&lex->vstr); // preload characters lex->chr0 = stream_next_char(stream_data); lex->chr1 = stream_next_char(stream_data); lex->chr2 = stream_next_char(stream_data); // if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end if (lex->chr0 == MP_LEXER_CHAR_EOF) { lex->chr0 = '\n'; } else if (lex->chr1 == MP_LEXER_CHAR_EOF) { if (lex->chr0 != '\n' && lex->chr0 != '\r') { lex->chr1 = '\n'; } } else if (lex->chr2 == MP_LEXER_CHAR_EOF) { if (lex->chr1 != '\n' && lex->chr1 != '\r') { lex->chr2 = '\n'; } } // preload first token mp_lexer_next_token_into(lex, &lex->tok_cur, true); return lex; }
STATIC mp_obj_t stream_readall(mp_obj_t self_in) { const mp_stream_p_t *stream_p = mp_get_stream(self_in); mp_uint_t total_size = 0; vstr_t vstr; vstr_init(&vstr, DEFAULT_BUFFER_SIZE); char *p = vstr.buf; mp_uint_t current_read = DEFAULT_BUFFER_SIZE; while (true) { int error; mp_uint_t out_sz = stream_p->read(self_in, p, current_read, &error); if (out_sz == MP_STREAM_ERROR) { 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. if (total_size == 0) { return mp_const_none; } break; } mp_raise_OSError(error); } if (out_sz == 0) { break; } total_size += out_sz; if (out_sz < current_read) { current_read -= out_sz; p += out_sz; } else { p = vstr_extend(&vstr, DEFAULT_BUFFER_SIZE); current_read = DEFAULT_BUFFER_SIZE; } } vstr.len = total_size; return mp_obj_new_str_from_vstr(STREAM_CONTENT_TYPE(stream_p), &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; } } }
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; } } } }
void pyexec_friendly_repl_init(void) { vstr_init(&repl.line, 32); repl.cont_line = false; readline_init(&repl.line); mp_hal_stdout_tx_str(">>> "); }
// Init the vstr so it allocs exactly enough ram to hold a null-terminated // string of the given length, and set the length. void vstr_init_len(vstr_t *vstr, size_t len) { vstr_init(vstr, len + 1); vstr->len = len; }
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); } }
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { // check that the given type is an exception type assert(exc_type->make_new == mp_obj_exception_make_new); // make exception object mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); if (o == NULL) { // Couldn't allocate heap memory; use local data instead. // Unfortunately, we won't be able to format the string... o = &MP_STATE_VM(mp_emergency_exception_obj); o->base.type = exc_type; o->traceback_data = NULL; o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If the user has provided a buffer, then we try to create a tuple // of length 1, which has a string object and the string data. if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) { mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)MP_STATE_VM(mp_emergency_exception_buf); mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1]; tuple->base.type = &mp_type_tuple; tuple->len = 1; tuple->items[0] = MP_OBJ_FROM_PTR(str); byte *str_data = (byte *)&str[1]; uint max_len = MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - str_data; vstr_t vstr; vstr_init_fixed_buf(&vstr, max_len, (char *)str_data); va_list ap; va_start(ap, fmt); vstr_vprintf(&vstr, fmt, ap); va_end(ap); str->base.type = &mp_type_str; str->hash = qstr_compute_hash(str_data, str->len); str->len = vstr.len; str->data = str_data; o->args = tuple; uint offset = &str_data[str->len] - MP_STATE_VM(mp_emergency_exception_buf); offset += sizeof(void *) - 1; offset &= ~(sizeof(void *) - 1); if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) { // We have room to store some traceback. o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset); o->traceback_alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]); o->traceback_len = 0; } } #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF } else { o->base.type = exc_type; o->traceback_data = NULL; o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL)); assert(fmt != NULL); { if (strchr(fmt, '%') == NULL) { // no formatting substitutions, avoid allocating vstr. o->args->items[0] = mp_obj_new_str(fmt, strlen(fmt), false); } else { // render exception message and store as .args[0] va_list ap; vstr_t vstr; vstr_init(&vstr, 16); va_start(ap, fmt); vstr_vprintf(&vstr, fmt, ap); va_end(ap); o->args->items[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); } } } return MP_OBJ_FROM_PTR(o); }
void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) { vstr_init(vstr, alloc); print->data = vstr; print->print_strn = (mp_print_strn_t)vstr_add_strn; }
void *mod_cout (void *ptr) { int sockfd; /* Socket file descriptor */ int sent_bytes; /* Bytes sent */ struct hostent *hinfo; /* Host information */ struct sockaddr_in remote; /* Remote address information */ vstr_t vstr; /* Data to send */ int soundfd; /* Sound device file descriptor */ struct adpcm_state state; /* ADPCM state, see adpcm.c */ short inbuf[SAMPLES]; /* Input buffer to get sound samples */ char outbuf[SAMPLES/2]; /* Output buffer to receive ADPCM code */ rtp_param_t param; /* RTP parameters */ vstr_t ctrl; char *hostname = (char *) ptr; int i; DEBUG_MSG("hostname:--%s--\n", hostname); fprintf(stderr, "+ Communication output module loaded.\n"); fprintf(stderr, "+ Sound input module loaded.\n"); vstr_init (&vstr, RTP_MTU_SIZE);// init vstr size, data part vstr_init (&ctrl, RTP_MTU_SIZE); /* Initialize ADPCM encoder */ state.valprev = 0; state.index = 0; /* Get target parameters */ if ((hinfo = gethostbyname(hostname)) == (struct hostent *) NULL) { perror("Error resolving host name"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } remote.sin_family = AF_INET; /* Internet protocol */ remote.sin_addr = *((struct in_addr *) hinfo -> h_addr); /* Address */ memset(&(remote.sin_zero), '\0', 8); /* Zero the rest */ /* Open sound device to read */ soundfd = open_soundcard (O_RDONLY); param.flags = 0; param.pt = 3; param.len = SAMPLES / 2; param.payload = outbuf; for (;;) { DEBUG_MSG("%s test\n",__FUNCTION__); vstr_flush (&ctrl); rtcp_send_ctrl (&rtp, &ctrl); rtcp_append_sdes (&rtp, &ctrl, SDES_CNAME | SDES_TOOL); remote.sin_port = htons(RTCP_PORT); /* Port */ sent_bytes = sendto(sockfd, ctrl.head, ctrl.size, 0, (struct sockaddr *) &remote, sizeof(struct sockaddr)); //This will send data to speficy host directly for (i = 0; i < 100; i++) { DEBUG_MSG("%s read data start\n",__FUNCTION__); /* Read from sound device */ read (soundfd, inbuf, sizeof(inbuf)); DEBUG_MSG("%s read data over\n",__FUNCTION__); /* Encodes data */ adpcm_coder (inbuf, outbuf, SAMPLES, &state); /* Create RTP packet */ vstr_flush (&vstr); rtp_send (&rtp, ¶m, &vstr); /* Send to network */ remote.sin_port = htons(RTP_PORT); /* Port */ sent_bytes = sendto(sockfd, vstr.head, vstr.size, 0, (struct sockaddr *) &remote, sizeof(struct sockaddr)); } } }
void *mod_cin (void *ptr) { int rtpfd; /* RTP socket file descriptor */ int rtcpfd; /* RTCP socket file descriptor */ socklen_t addr_len; /* Data size, Bytes received */ struct sockaddr_in rtps; /* RTP socket */ struct sockaddr_in rtcps; /* RTCP socket */ struct sockaddr_in remote; /* Remote address information */ vstr_t recv_data; /* Received data */ rtp_packet_t *packet; /* Parsed RTP packet */ fd_set readset; int fdmax; fprintf(stderr, "+ Communication input module loaded.\n"); vstr_init (&recv_data, RTP_MTU_SIZE); if ((rtpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } if ((rtcpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } rtps.sin_family = AF_INET; /* Internet protocol */ rtps.sin_port = htons(RTP_PORT); /* Port */ rtps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtps address */ memset(&(rtps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtpfd, (struct sockaddr *) &rtps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } rtcps.sin_family = AF_INET; /* Internet protocol */ rtcps.sin_port = htons(RTCP_PORT); /* Port */ rtcps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtcps address */ memset(&(rtcps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtcpfd, (struct sockaddr *) &rtcps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } fprintf(stderr, "+ RTP Listening at %s:%d...\n", inet_ntoa(rtps.sin_addr), ntohs(rtps.sin_port)); fprintf(stderr, "+ RTCP Listening at %s:%d...\n", inet_ntoa(rtcps.sin_addr), ntohs(rtcps.sin_port)); addr_len = sizeof(struct sockaddr); while(1) { FD_ZERO (&readset); FD_SET (rtpfd, &readset); FD_SET (rtcpfd, &readset); fdmax = (rtpfd < rtcpfd) ? rtcpfd : rtpfd; select (fdmax + 1, &readset, NULL, NULL, NULL); if (FD_ISSET(rtpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); printf("receive data, size = %d!!!!!!!!!!!!!!!!!\n", recv_data.size); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } /* Write to buffer */ packet = rtp_recv (&rtp, &recv_data); if (packet != NULL && rtp_enqueue (&rtp, packet) == -1) rtp_packet_free (packet); vstr_flush (&recv_data); } if (FD_ISSET(rtcpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtcpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } rtcp_recv (&rtp, &recv_data); vstr_flush (&recv_data); } } }