void linked_list_free (linked_list list) { ASSERT_LIST (list); linked_list_header *header = (linked_list_header *) list; if (header->next) { linked_list_free ((linked_list) header->next); } jsp_mm_free (list); }
void scopes_tree_free (scopes_tree tree) { assert_tree (tree); if (tree->t.children_num != 0) { for (uint8_t i = 0; i < tree->t.children_num; ++i) { scopes_tree_free (*(scopes_tree *) linked_list_element (tree->t.children, i)); } linked_list_free (tree->t.children); } linked_list_free (tree->instrs); linked_list_free (tree->var_decls); jsp_mm_free (tree); }
/** * Create token of specified type from charset, transforming escape sequences. * * @return token descriptor */ static token lexer_create_token_for_charset_transform_escape_sequences (token_type tt, /**< token type */ const lit_utf8_byte_t *charset_p, /**< charset buffer */ lit_utf8_size_t size) /**< size of the charset */ { lit_utf8_byte_t *converted_str_p = (lit_utf8_byte_t *) jsp_mm_alloc (size); lit_utf8_size_t converted_size = lexer_transform_escape_sequences (charset_p, size, converted_str_p); token ret = lexer_create_token_for_charset (tt, converted_str_p, converted_size); jsp_mm_free (converted_str_p); return ret; } /* lexer_create_token_for_charset_transform_escape_sequences */
/** * Convert specified string to token of specified type, transforming escape sequences * * @return token descriptor */ static token convert_string_to_token_transform_escape_seq (token_type tok_type, /**< type of token to produce */ const jerry_api_char_t *source_str_p, /**< string to convert, * located in source buffer */ size_t source_str_size) /**< size of the string */ { token ret; if (source_str_size == 0) { return convert_string_to_token (tok_type, lit_get_magic_string_utf8 (LIT_MAGIC_STRING__EMPTY), 0); } else { JERRY_ASSERT (source_str_p != NULL); } lit_utf8_byte_t *str_buf_p = (lit_utf8_byte_t*) jsp_mm_alloc (source_str_size); const lit_utf8_byte_t *source_str_iter_p = source_str_p; lit_utf8_byte_t *str_buf_iter_p = str_buf_p; bool is_correct_sequence = true; bool every_char_islower = true; bool every_char_allowed_in_identifier = true; while (source_str_iter_p < source_str_p + source_str_size) { ecma_char_t converted_char; if (*source_str_iter_p != '\\') { converted_char = (lit_utf8_byte_t) *source_str_iter_p++; JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); } else { source_str_iter_p++; const lit_utf8_byte_t escape_character = (lit_utf8_byte_t) *source_str_iter_p++; JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); if (isdigit (escape_character)) { if (escape_character == '0') { JERRY_UNIMPLEMENTED ("<NUL> character is not currently supported.\n"); } else { /* Implementation-defined (ECMA-262 v5, B.1.2): octal escape sequences are not implemented */ is_correct_sequence = false; break; } } else if (escape_character == 'u' || escape_character == 'x') { const uint32_t hex_chars_num = (escape_character == 'u' ? 4u : 2u); if (source_str_iter_p + hex_chars_num > source_str_p + source_str_size) { is_correct_sequence = false; break; } bool chars_are_hex = true; uint16_t char_code = 0; for (uint32_t i = 0; i < hex_chars_num; i++) { const lit_utf8_byte_t byte = (lit_utf8_byte_t) *source_str_iter_p++; if (!isxdigit (byte)) { chars_are_hex = false; break; } else { /* * Check that highest 4 bits are zero, so the value would not overflow. */ JERRY_ASSERT ((char_code & 0xF000u) == 0); char_code = (uint16_t) (char_code << 4u); char_code = (uint16_t) (char_code + ecma_char_hex_to_int (byte)); } } JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); JERRY_ASSERT (source_str_iter_p <= source_str_p + source_str_size); if (!chars_are_hex) { is_correct_sequence = false; break; } /* * In CONFIG_ECMA_CHAR_ASCII mode size of ecma_char_t is 1 byte, so the conversion * would ignore highest part of 2-byte value, and in CONFIG_ECMA_CHAR_UTF16 mode this * would be just an assignment of 2-byte value. */ converted_char = (ecma_char_t) char_code; } else if (ecma_char_is_line_terminator (escape_character)) { if (source_str_iter_p + 1 <= source_str_p + source_str_size) { lit_utf8_byte_t byte = *source_str_iter_p; if (escape_character == '\x0D' && byte == '\x0A') { source_str_iter_p++; } } continue; } else { convert_single_escape_character ((ecma_char_t) escape_character, &converted_char); } } TODO ("Support surrogate paris.") str_buf_iter_p += lit_code_unit_to_utf8 (converted_char, str_buf_iter_p); JERRY_ASSERT (str_buf_iter_p <= str_buf_p + source_str_size); if (!islower (converted_char)) { every_char_islower = false; if (!isalpha (converted_char) && !isdigit (converted_char) && converted_char != '$' && converted_char != '_') { every_char_allowed_in_identifier = false; } } } if (is_correct_sequence) { lit_utf8_size_t length = (lit_utf8_size_t) (str_buf_iter_p - str_buf_p); ret = empty_token; if (tok_type == TOK_NAME) { if (every_char_islower) { ret = decode_keyword (str_buf_p, length); } else if (!every_char_allowed_in_identifier) { PARSE_ERROR ("Malformed identifier name", source_str_p - buffer_start); } } if (is_empty (ret)) { ret = convert_string_to_token (tok_type, str_buf_p, length); } } else { PARSE_ERROR ("Malformed escape sequence", source_str_p - buffer_start); } jsp_mm_free (str_buf_p); return ret; } /* convert_string_to_token_transform_escape_seq */
/** * Create token of specified type from charset * * @return token descriptor */ static token lexer_create_token_for_charset (jsp_token_type_t tt, /**< token type */ const lit_utf8_byte_t *charset_p, /**< charset buffer */ lit_utf8_size_t size) /**< size of the charset */ { JERRY_ASSERT (charset_p != NULL); lit_utf8_iterator_t iter = lit_utf8_iterator_create (charset_p, (lit_utf8_size_t) size); lit_utf8_size_t new_size = 0; lit_utf8_size_t new_length = 0; bool should_convert = false; while (!lit_utf8_iterator_is_eos (&iter)) { if (iter.buf_pos.is_non_bmp_middle) { should_convert = true; } lit_utf8_iterator_incr (&iter); new_size += LIT_CESU8_MAX_BYTES_IN_CODE_UNIT; } lit_utf8_byte_t *converted_str_p; if (unlikely (should_convert)) { lit_utf8_iterator_seek_bos (&iter); converted_str_p = (lit_utf8_byte_t *) jsp_mm_alloc (new_size); while (!lit_utf8_iterator_is_eos (&iter)) { ecma_char_t ch = lit_utf8_iterator_read_next (&iter); new_length += lit_code_unit_to_utf8 (ch, converted_str_p + new_length); } } else { converted_str_p = (lit_utf8_byte_t *) charset_p; new_length = size; JERRY_ASSERT (lit_is_cesu8_string_valid (converted_str_p, new_length)); } lit_literal_t lit = lit_find_literal_by_utf8_string (converted_str_p, new_length); if (lit != NULL) { if (unlikely (should_convert)) { jsp_mm_free (converted_str_p); } return create_token_from_lit (tt, lit); } lit = lit_create_literal_from_utf8_string (converted_str_p, new_length); rcs_record_type_t type = rcs_record_get_type (lit); JERRY_ASSERT (RCS_RECORD_TYPE_IS_CHARSET (type) || RCS_RECORD_TYPE_IS_MAGIC_STR (type) || RCS_RECORD_TYPE_IS_MAGIC_STR_EX (type)); if (unlikely (should_convert)) { jsp_mm_free (converted_str_p); } return create_token_from_lit (tt, lit); } /* lexer_create_token_for_charset */