示例#1
0
// 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);
}
示例#2
0
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);
}
示例#3
0
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;
}
示例#4
0
文件: usbdbg.c 项目: RayPhon/openmv
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();
}
示例#5
0
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");
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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);
    }
}
示例#9
0
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);
}
示例#10
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;
            }
        }
    }
}
示例#11
0
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");
    }
}
示例#12
0
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);
}
示例#13
0
/// \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;
}
示例#14
0
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);  
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
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 {
                // 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;
        }
    }
}
示例#18
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;
    }
}
示例#19
0
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;
}
示例#20
0
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);
}
示例#21
0
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
}
示例#22
0
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;
        }
    }
}
示例#23
0
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;
            }
        }
    }
}
示例#24
0
void pyexec_friendly_repl_init(void) {
    vstr_init(&repl.line, 32);
    repl.cont_line = false;
    readline_init(&repl.line);
    mp_hal_stdout_tx_str(">>> ");
}
示例#25
0
// 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;
}
示例#26
0
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);
    }
}
示例#27
0
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);
}
示例#28
0
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;
}
示例#29
0
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, &param, &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));
    }
  }
}
示例#30
0
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);
    }

  }
}