/** * Loading a single file into the memory. * * @return size of file - if loading is successful * 0 - otherwise */ static size_t read_file (uint8_t *input_pos_p, /**< next position in the input buffer */ const char *file_name) /**< file name */ { FILE *file = fopen (file_name, "r"); if (file == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name); return 0; } size_t max_size = (size_t) (input_buffer + JERRY_BUFFER_SIZE - input_pos_p); size_t bytes_read = fread (input_pos_p, 1u, max_size, file); fclose (file); if (bytes_read == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name); return 0; } if (bytes_read == max_size) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: file too large: %s\n", file_name); return 0; } printf ("Input file '%s' (%d bytes) loaded.\n", file_name, (int) bytes_read); return bytes_read; } /* read_file */
static const uint8_t * read_file (const char *file_name, size_t *out_size_p) { FILE *file; if (!strcmp ("-", file_name)) { file = stdin; } else { file = fopen (file_name, "r"); if (file == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name); return NULL; } } size_t bytes_read = fread (buffer, 1u, sizeof (buffer), file); if (!bytes_read) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name); fclose (file); return NULL; } fclose (file); *out_size_p = bytes_read; return (const uint8_t *) buffer; } /* read_file */
/** * Print error value */ static void print_unhandled_exception (jerry_value_t error_value) /**< error value */ { assert (!jerry_value_has_error_flag (error_value)); jerry_value_t err_str_val = jerry_value_to_string (error_value); if (jerry_value_has_error_flag (err_str_val)) { /* Avoid recursive error throws. */ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n"); jerry_release_value (err_str_val); return; } jerry_size_t err_str_size = jerry_get_string_size (err_str_val); if (err_str_size >= 256) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n"); jerry_release_value (err_str_val); return; } jerry_char_t err_str_buf[256]; jerry_size_t string_end = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); assert (string_end == err_str_size); err_str_buf[string_end] = 0; jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: %s\n", (char *) err_str_buf); jerry_release_value (err_str_val); } /* print_unhandled_exception */
/** * Read source code into buffer. * * Returned value must be freed with jmem_heap_free_block if it's not NULL. * @return NULL, if read or allocation has failed * pointer to the allocated memory block, otherwise */ static const uint8_t * read_file (const char *file_name, /**< source code */ size_t *out_size_p) /**< [out] number of bytes successfully read from source */ { FILE *file = fopen (get_fullpath(file_name), "r"); if (file == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: %s\n", file_name); return NULL; } int fseek_status = fseek (file, 0, SEEK_END); if (fseek_status != 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to seek (error: %d)\n", fseek_status); fclose (file); return NULL; } long script_len = ftell (file); if (script_len < 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to get the file size(error %ld)\n", script_len); fclose (file); return NULL; } rewind (file); uint8_t *buffer = jmem_heap_alloc_block_null_on_error (script_len); if (buffer == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Out of memory error\n"); fclose (file); return NULL; } size_t bytes_read = fread (buffer, 1u, script_len, file); if (!bytes_read || bytes_read != script_len) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name); jmem_heap_free_block ((void*) buffer, script_len); fclose (file); return NULL; } fclose (file); *out_size_p = bytes_read; return (const uint8_t *) buffer; } /* read_file */
int main (int argc, char **argv) { srand ((unsigned) jerry_port_get_current_time ()); if (argc <= 1 || (argc == 2 && (!strcmp ("-h", argv[1]) || !strcmp ("--help", argv[1])))) { print_help (argv[0]); return JERRY_STANDALONE_EXIT_CODE_OK; } jerry_init (JERRY_INIT_EMPTY); jerry_value_t ret_value = jerry_create_undefined (); for (int i = 1; i < argc; i++) { const char *file_name = argv[i]; size_t source_size; const jerry_char_t *source_p = read_file (file_name, &source_size); if (source_p == NULL) { ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); break; } else { ret_value = jerry_parse (source_p, source_size, false); if (!jerry_value_has_error_flag (ret_value)) { jerry_value_t func_val = ret_value; ret_value = jerry_run (func_val); jerry_release_value (func_val); } } if (jerry_value_has_error_flag (ret_value)) { break; } jerry_release_value (ret_value); ret_value = jerry_create_undefined (); } int ret_code = JERRY_STANDALONE_EXIT_CODE_OK; if (jerry_value_has_error_flag (ret_value)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Unhandled exception: Script Error!\n"); ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_release_value (ret_value); jerry_cleanup (); return ret_code; } /* main */
static void print_unhandled_exception (jerry_value_t error_value) { assert (jerry_value_has_error_flag (error_value)); jerry_value_clear_error_flag (&error_value); jerry_value_t err_str_val = jerry_value_to_string (error_value); jerry_size_t err_str_size = jerry_get_string_size (err_str_val); jerry_char_t err_str_buf[256]; if (err_str_size >= 256) { const char msg[] = "[Error message too long]"; err_str_size = sizeof (msg) / sizeof (char) - 1; memcpy (err_str_buf, msg, err_str_size); } else { jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); assert (sz == err_str_size); } err_str_buf[err_str_size] = 0; jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf); jerry_release_value (err_str_val); } /* print_unhandled_exception */
/** * Utility method to check and print error in the given cli state. * * @return true - if any error is detected * false - if there is no error in the cli state */ static bool check_cli_error (const cli_state_t *const cli_state_p) { if (cli_state_p->error != NULL) { if (cli_state_p->arg != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg); } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error); } return true; } return false; } /* check_cli_error */
/** * Main function. * * @return error code (0 - no error) */ int main (int argc, /**< number of arguments */ char **argv) /**< argument list */ { cli_state_t cli_state = cli_init (main_opts, argc - 1, argv + 1); for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state)) { switch (id) { case OPT_MERGE_HELP: { /* Help is always printed if no command is provided. */ break; } case CLI_OPT_DEFAULT: { const char *command_p = cli_consume_string (&cli_state); if (cli_state.error != NULL) { break; } if (!strcmp ("merge", command_p)) { return process_merge (&cli_state, argc, argv[0]); } else if (!strcmp ("generate", command_p)) { return process_generate (&cli_state, argc, argv[0]); } jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unknown command: %s\n\n", command_p); print_commands (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } default: { cli_state.error = "Internal error"; break; } } } if (check_cli_error (&cli_state)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } print_commands (argv[0]); return JERRY_STANDALONE_EXIT_CODE_OK; } /* main */
/** * Run JerryScript and print its return value. */ static int jerry(int argc, char *argv[]) { int ret_code = jerry_cmd_main(argc, argv); #ifdef CONFIG_DEBUG_VERBOSE jerry_port_log(JERRY_LOG_LEVEL_DEBUG, "JerryScript result: %d\n", ret_code); #endif return ret_code; } /* jerry */
/** * Check whether JerryScript has a requested feature enabled or not. If not, * print a warning message. * * @return the status of the feature. */ static bool check_feature (jerry_feature_t feature, /**< feature to check */ const char *option) /**< command line option that triggered this check */ { if (!jerry_is_feature_enabled (feature)) { jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING); jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option); return false; } return true; } /* check_feature */
/** * Register a JavaScript function in the global object. */ static void register_js_function (const char *name_p, /**< name of the function */ jerry_external_handler_t handler_p) /**< function callback */ { jerry_value_t result_val = jerryx_handler_register_global ((const jerry_char_t *) name_p, handler_p); if (jerry_value_is_error (result_val)) { jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Warning: failed to register '%s' method.", name_p); } jerry_release_value (result_val); } /* register_js_function */
/** * Handle execution of control path that should be unreachable */ void __noreturn jerry_unreachable (const char *file, /**< file name */ const char *function, /**< function name */ const uint32_t line) /**< line */ { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "ICE: Unreachable control path at %s(%s):%lu was executed.\n", file, function, (unsigned long) line); jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION); } /* jerry_unreachable */
/* * Exit with specified status code. * * If !JERRY_NDEBUG and code != 0, print status code with description * and call assertion fail handler. */ void __noreturn jerry_fatal (jerry_fatal_code_t code) /**< status code */ { #ifndef JERRY_NDEBUG switch (code) { case ERR_OUT_OF_MEMORY: { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: ERR_OUT_OF_MEMORY\n"); break; } case ERR_SYSCALL: { /* print nothing as it may invoke syscall recursively */ break; } case ERR_REF_COUNT_LIMIT: { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: ERR_REF_COUNT_LIMIT\n"); break; } case ERR_FAILED_INTERNAL_ASSERTION: { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: ERR_FAILED_INTERNAL_ASSERTION\n"); break; } } #endif /* !JERRY_NDEBUG */ jerry_port_fatal (code); /* to make compiler happy for some RTOS: 'control reaches end of non-void function' */ while (true) { } } /* jerry_fatal */
/** * Handle failed assertion */ void __noreturn jerry_assert_fail (const char *assertion, /**< assertion condition string */ const char *file, /**< file name */ const char *function, /**< function name */ const uint32_t line) /**< line */ { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "ICE: Assertion '%s' failed at %s(%s):%lu.\n", assertion, file, function, (unsigned long) line); jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION); } /* jerry_assert_fail */
/** * Provide the 'assert' implementation for the engine. * * @return true - if only one argument was passed and the argument is a boolean true. */ static jerry_value_t assert_handler (const jerry_value_t func_obj_val __attribute__((unused)), /**< function object */ const jerry_value_t this_p __attribute__((unused)), /**< this arg */ const jerry_value_t args_p[], /**< function arguments */ const jerry_length_t args_cnt) /**< number of function arguments */ { if (args_cnt == 1 && jerry_value_is_boolean (args_p[0]) && jerry_get_boolean_value (args_p[0])) { return jerry_create_boolean (true); } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script error: assertion failed\n"); exit (JERRY_STANDALONE_EXIT_CODE_FAIL); } } /* assert_handler */
/** * Print pools memory usage statistics */ void jmem_pools_stats_print (void) { jmem_pools_stats_t *pools_stats = &JERRY_CONTEXT (jmem_pools_stats); jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Pools stats:\n" " Chunk size: %zu\n" " Pool chunks: %zu\n" " Peak pool chunks: %zu\n" " Free chunks: %zu\n" " Pool reuse ratio: %zu.%04zu\n", JMEM_POOL_CHUNK_SIZE, pools_stats->pools_count, pools_stats->peak_pools_count, pools_stats->free_chunks, pools_stats->reused_count / pools_stats->new_alloc_count, pools_stats->reused_count % pools_stats->new_alloc_count * 10000 / pools_stats->new_alloc_count); } /* jmem_pools_stats_print */
/** * Provide fatal message implementation for the engine. */ void jerry_port_fatal (jerry_fatal_code_t code) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Jerry Fatal Error!\n"); while (true); } /* jerry_port_fatal */
/** * Process 'generate' command. * * @return error code (0 - no error) */ static int process_generate (cli_state_t *cli_state_p, /**< cli state */ int argc, /**< number of arguments */ char *prog_name_p) /**< program name */ { (void) argc; bool is_save_literals_mode_in_c_format = false; uint32_t snapshot_flags = 0; jerry_init_flag_t flags = JERRY_INIT_EMPTY; const char *file_name_p = NULL; uint8_t *source_p = input_buffer; size_t source_length = 0; const char *save_literals_file_name_p = NULL; cli_change_opts (cli_state_p, generate_opts); for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p)) { switch (id) { case OPT_GENERATE_HELP: { cli_help (prog_name_p, "generate", generate_opts); return JERRY_STANDALONE_EXIT_CODE_OK; } case OPT_GENERATE_STATIC: { snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC; break; } case OPT_GENERATE_LITERAL_LIST: case OPT_GENERATE_LITERAL_C: { if (save_literals_file_name_p != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C); save_literals_file_name_p = cli_consume_string (cli_state_p); break; } case OPT_GENERATE_SHOW_OP: { if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg)) { jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); flags |= JERRY_INIT_SHOW_OPCODES; } break; } case OPT_GENERATE_OUT: { output_file_name_p = cli_consume_string (cli_state_p); break; } case CLI_OPT_DEFAULT: { if (file_name_p != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } file_name_p = cli_consume_string (cli_state_p); if (cli_state_p->error == NULL) { source_length = read_file (source_p, file_name_p); if (source_length == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } break; } default: { cli_state_p->error = "Internal error"; break; } } } if (check_cli_error (cli_state_p)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (file_name_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_init (flags); if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_value_t snapshot_result; snapshot_result = jerry_generate_snapshot ((jerry_char_t *) file_name_p, (size_t) strlen (file_name_p), (jerry_char_t *) source_p, source_length, snapshot_flags, output_buffer, sizeof (output_buffer) / sizeof (uint32_t)); if (jerry_value_has_error_flag (snapshot_result)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n"); jerry_value_clear_error_flag (&snapshot_result); print_unhandled_exception (snapshot_result); jerry_release_value (snapshot_result); return JERRY_STANDALONE_EXIT_CODE_FAIL; } size_t snapshot_size = (size_t) jerry_get_number_value (snapshot_result); jerry_release_value (snapshot_result); FILE *snapshot_file_p = fopen (output_file_name_p, "w"); if (snapshot_file_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p); fclose (snapshot_file_p); printf ("Created snapshot file: '%s' (%lu bytes)\n", output_file_name_p, (unsigned long) snapshot_size); if (save_literals_file_name_p != NULL) { const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p, source_length, false, output_buffer, sizeof (output_buffer) / sizeof (uint32_t), is_save_literals_mode_in_c_format); if (literal_buffer_size == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Literal saving failed!\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } FILE *literal_file_p = fopen (save_literals_file_name_p, "w"); if (literal_file_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write literal file: '%s'\n", save_literals_file_name_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } fwrite (output_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p); fclose (literal_file_p); printf ("Created literal file: '%s' (%lu bytes)\n", save_literals_file_name_p, (unsigned long) literal_buffer_size); } return 0; } /* process_generate */
/** * Process 'merge' command. * * @return error code (0 - no error) */ static int process_merge (cli_state_t *cli_state_p, /**< cli state */ int argc, /**< number of arguments */ char *prog_name_p) /**< program name */ { jerry_init (JERRY_INIT_EMPTY); uint8_t *input_pos_p = input_buffer; cli_change_opts (cli_state_p, merge_opts); const uint32_t *merge_buffers[argc]; size_t merge_buffer_sizes[argc]; uint32_t number_of_files = 0; for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p)) { switch (id) { case OPT_MERGE_HELP: { cli_help (prog_name_p, "merge", merge_opts); return JERRY_STANDALONE_EXIT_CODE_OK; } case OPT_MERGE_OUT: { output_file_name_p = cli_consume_string (cli_state_p); break; } case CLI_OPT_DEFAULT: { const char *file_name_p = cli_consume_string (cli_state_p); if (cli_state_p->error == NULL) { size_t size = read_file (input_pos_p, file_name_p); if (size == 0) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } merge_buffers[number_of_files] = (const uint32_t *) input_pos_p; merge_buffer_sizes[number_of_files] = size; number_of_files++; const uintptr_t mask = sizeof (uint32_t) - 1; input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask); } break; } default: { cli_state_p->error = "Internal error"; break; } } } if (check_cli_error (cli_state_p)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (number_of_files < 2) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } const char *error_p; size_t size = jerry_merge_snapshots (merge_buffers, merge_buffer_sizes, number_of_files, output_buffer, JERRY_BUFFER_SIZE, &error_p); if (size == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } FILE *file_p = fopen (output_file_name_p, "w"); if (file_p != NULL) { fwrite (output_buffer, 1u, size, file_p); fclose (file_p); } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p); } return JERRY_STANDALONE_EXIT_CODE_OK; } /* process_merge */
/** * JerryScript command main */ static int jerry_cmd_main (int argc, char *argv[]) { if (argc > JERRY_MAX_COMMAND_LINE_ARGS) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Too many command line arguments. Current maximum is %d\n", JERRY_MAX_COMMAND_LINE_ARGS); return JERRY_STANDALONE_EXIT_CODE_FAIL; } const char *file_names[JERRY_MAX_COMMAND_LINE_ARGS]; int i; int files_counter = 0; bool start_debug_server = false; uint16_t debug_port = 5001; jerry_init_flag_t flags = JERRY_INIT_EMPTY; for (i = 1; i < argc; i++) { if (!strcmp ("-h", argv[i]) || !strcmp ("--help", argv[i])) { print_help (argv[0]); return JERRY_STANDALONE_EXIT_CODE_OK; } else if (!strcmp ("--mem-stats", argv[i])) { jerry_log_level = JERRY_LOG_LEVEL_DEBUG; flags |= JERRY_INIT_MEM_STATS; } else if (!strcmp ("--mem-stats-separate", argv[i])) { jerry_log_level = JERRY_LOG_LEVEL_DEBUG; flags |= JERRY_INIT_MEM_STATS_SEPARATE; } else if (!strcmp ("--show-opcodes", argv[i])) { jerry_log_level = JERRY_LOG_LEVEL_DEBUG; flags |= JERRY_INIT_SHOW_OPCODES | JERRY_INIT_SHOW_REGEXP_OPCODES; } else if (!strcmp ("--log-level", argv[i])) { if (++i < argc && strlen (argv[i]) == 1 && argv[i][0] >='0' && argv[i][0] <= '3') { jerry_log_level = argv[i][0] - '0'; } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format or invalid argument\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } else if (!strcmp ("--start-debug-server", argv[i])) { start_debug_server = true; } else if (!strcmp ("--debug-server-port", argv[i])) { if (++i < argc) { debug_port = str_to_uint (argv[i]); } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format or invalid argument\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } else { file_names[files_counter++] = argv[i]; } } jerry_init (flags); if (start_debug_server) { jerry_debugger_init (debug_port); } register_js_function ("assert", jerryx_handler_assert); register_js_function ("gc", jerryx_handler_gc); register_js_function ("print", jerryx_handler_print); jerry_value_t ret_value = jerry_create_undefined (); if (files_counter == 0) { printf ("No input files, running a hello world demo:\n"); const jerry_char_t script[] = "var str = 'Hello World'; print(str + ' from JerryScript')"; size_t script_size = strlen ((const char *) script); ret_value = jerry_parse (script, script_size, false); if (!jerry_value_has_error_flag (ret_value)) { ret_value = jerry_run (ret_value); } } else { for (i = 0; i < files_counter; i++) { size_t source_size; const jerry_char_t *source_p = read_file (file_names[i], &source_size); if (source_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Source file load error\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } ret_value = jerry_parse_named_resource ((jerry_char_t *) file_names[i], strlen (file_names[i]), source_p, source_size, false); if (!jerry_value_has_error_flag (ret_value)) { jerry_value_t func_val = ret_value; ret_value = jerry_run (func_val); jerry_release_value (func_val); } if (jerry_value_has_error_flag (ret_value)) { print_unhandled_exception (ret_value, source_p); jmem_heap_free_block ((void*) source_p, source_size); break; } jmem_heap_free_block ((void*) source_p, source_size); jerry_release_value (ret_value); ret_value = jerry_create_undefined (); } } int ret_code = JERRY_STANDALONE_EXIT_CODE_OK; if (jerry_value_has_error_flag (ret_value)) { ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_release_value (ret_value); jerry_cleanup (); return ret_code; } /* jerry_cmd_main */
/** * Print error value */ static void print_unhandled_exception (jerry_value_t error_value, /**< error value */ const jerry_char_t *source_p) /**< source_p */ { assert (jerry_value_has_error_flag (error_value)); jerry_value_clear_error_flag (&error_value); jerry_value_t err_str_val = jerry_value_to_string (error_value); jerry_size_t err_str_size = jerry_get_string_size (err_str_val); jerry_char_t err_str_buf[256]; if (err_str_size >= 256) { const char msg[] = "[Error message too long]"; err_str_size = sizeof (msg) / sizeof (char) - 1; memcpy (err_str_buf, msg, err_str_size); } else { jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); assert (sz == err_str_size); err_str_buf[err_str_size] = 0; if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES) && jerry_value_is_syntax_error (error_value)) { unsigned int err_line = 0; unsigned int err_col = 0; /* 1. parse column and line information */ for (jerry_size_t i = 0; i < sz; i++) { if (!strncmp ((char *) (err_str_buf + i), "[line: ", 7)) { i += 7; char num_str[8]; unsigned int j = 0; while (i < sz && err_str_buf[i] != ',') { num_str[j] = (char) err_str_buf[i]; j++; i++; } num_str[j] = '\0'; err_line = (unsigned int) strtol (num_str, NULL, 10); if (strncmp ((char *) (err_str_buf + i), ", column: ", 10)) { break; /* wrong position info format */ } i += 10; j = 0; while (i < sz && err_str_buf[i] != ']') { num_str[j] = (char) err_str_buf[i]; j++; i++; } num_str[j] = '\0'; err_col = (unsigned int) strtol (num_str, NULL, 10); break; } } /* for */ if (err_line != 0 && err_col != 0) { unsigned int curr_line = 1; bool is_printing_context = false; unsigned int pos = 0; /* 2. seek and print */ while (source_p[pos] != '\0') { if (source_p[pos] == '\n') { curr_line++; } if (err_line < SYNTAX_ERROR_CONTEXT_SIZE || (err_line >= curr_line && (err_line - curr_line) <= SYNTAX_ERROR_CONTEXT_SIZE)) { /* context must be printed */ is_printing_context = true; } if (curr_line > err_line) { break; } if (is_printing_context) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%c", source_p[pos]); } pos++; } jerry_port_log (JERRY_LOG_LEVEL_ERROR, "\n"); while (--err_col) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "~"); } jerry_port_log (JERRY_LOG_LEVEL_ERROR, "^\n"); } } } jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf); jerry_release_value (err_str_val); } /* print_unhandled_exception */
int main (int argc, char **argv) { if (argc > JERRY_MAX_COMMAND_LINE_ARGS) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: too many command line arguments: %d (JERRY_MAX_COMMAND_LINE_ARGS=%d)\n", argc, JERRY_MAX_COMMAND_LINE_ARGS); return JERRY_STANDALONE_EXIT_CODE_FAIL; } const char *file_names[JERRY_MAX_COMMAND_LINE_ARGS]; int i; int files_counter = 0; size_t max_data_bss_size, max_stack_size; jerry_get_memory_limits (&max_data_bss_size, &max_stack_size); // FIXME: // jrt_set_mem_limits (max_data_bss_size, max_stack_size); jerry_init_flag_t flags = JERRY_INIT_EMPTY; const char *exec_snapshot_file_names[JERRY_MAX_COMMAND_LINE_ARGS]; int exec_snapshots_count = 0; bool is_parse_only = false; bool is_save_snapshot_mode = false; bool is_save_snapshot_mode_for_global_or_eval = false; const char *save_snapshot_file_name_p = NULL; bool is_repl_mode = false; for (i = 1; i < argc; i++) { if (!strcmp ("-h", argv[i]) || !strcmp ("--help", argv[i])) { print_help (argv[0]); return JERRY_STANDALONE_EXIT_CODE_OK; } else if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) { jerry_port_console ("Version: \t%d.%d\n\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION); return JERRY_STANDALONE_EXIT_CODE_OK; } else if (!strcmp ("--mem-stats", argv[i])) { flags |= JERRY_INIT_MEM_STATS; jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); } else if (!strcmp ("--mem-stats-separate", argv[i])) { flags |= JERRY_INIT_MEM_STATS_SEPARATE; jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); } else if (!strcmp ("--parse-only", argv[i])) { is_parse_only = true; } else if (!strcmp ("--show-opcodes", argv[i])) { flags |= JERRY_INIT_SHOW_OPCODES; jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); } else if (!strcmp ("--show-regexp-opcodes", argv[i])) { flags |= JERRY_INIT_SHOW_REGEXP_OPCODES; jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); } else if (!strcmp ("--save-snapshot-for-global", argv[i]) || !strcmp ("--save-snapshot-for-eval", argv[i])) { is_save_snapshot_mode = true; is_save_snapshot_mode_for_global_or_eval = !strcmp ("--save-snapshot-for-global", argv[i]); if (save_snapshot_file_name_p != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: snapshot file name already specified\n"); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (++i >= argc) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: no file specified for %s\n", argv[i - 1]); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } save_snapshot_file_name_p = argv[i]; } else if (!strcmp ("--exec-snapshot", argv[i])) { if (++i >= argc) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: no file specified for %s\n", argv[i - 1]); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } assert (exec_snapshots_count < JERRY_MAX_COMMAND_LINE_ARGS); exec_snapshot_file_names[exec_snapshots_count++] = argv[i]; } else if (!strcmp ("--log-level", argv[i])) { if (++i >= argc) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: no level specified for %s\n", argv[i - 1]); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (strlen (argv[i]) != 1 || argv[i][0] < '0' || argv[i][0] > '3') { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format for %s\n", argv[i - 1]); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_port_default_set_log_level (argv[i][0] - '0'); } else if (!strcmp ("--abort-on-fail", argv[i])) { jerry_port_default_set_abort_on_fail (true); } else if (!strncmp ("-", argv[i], 1)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unrecognized option: %s\n", argv[i]); print_usage (argv[0]); return JERRY_STANDALONE_EXIT_CODE_FAIL; } else { file_names[files_counter++] = argv[i]; } } if (is_save_snapshot_mode) { if (files_counter != 1) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: --save-snapshot argument works with exactly one script\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (exec_snapshots_count != 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: --save-snapshot and --exec-snapshot options can't be passed simultaneously\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } if (files_counter == 0 && exec_snapshots_count == 0) { is_repl_mode = true; } jerry_init (flags); jerry_value_t global_obj_val = jerry_get_global_object (); jerry_value_t assert_value = jerry_create_external_function (assert_handler); jerry_value_t assert_func_name_val = jerry_create_string ((jerry_char_t *) "assert"); bool is_assert_added = jerry_set_property (global_obj_val, assert_func_name_val, assert_value); jerry_release_value (assert_func_name_val); jerry_release_value (assert_value); jerry_release_value (global_obj_val); if (!is_assert_added) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Warning: failed to register 'assert' method."); } jerry_value_t ret_value = jerry_create_undefined (); for (int i = 0; i < exec_snapshots_count; i++) { size_t snapshot_size; const uint8_t *snapshot_p = read_file (exec_snapshot_file_names[i], &snapshot_size); if (snapshot_p == NULL) { ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } else { ret_value = jerry_exec_snapshot ((void *) snapshot_p, snapshot_size, true); } if (jerry_value_has_error_flag (ret_value)) { break; } } if (!jerry_value_has_error_flag (ret_value)) { for (int i = 0; i < files_counter; i++) { size_t source_size; const jerry_char_t *source_p = read_file (file_names[i], &source_size); if (source_p == NULL) { ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } if (is_save_snapshot_mode) { static uint8_t snapshot_save_buffer[ JERRY_BUFFER_SIZE ]; size_t snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) source_p, source_size, is_save_snapshot_mode_for_global_or_eval, false, snapshot_save_buffer, JERRY_BUFFER_SIZE); if (snapshot_size == 0) { ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ""); } else { FILE *snapshot_file_p = fopen (save_snapshot_file_name_p, "w"); fwrite (snapshot_save_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p); fclose (snapshot_file_p); } } else { ret_value = jerry_parse (source_p, source_size, false); if (!jerry_value_has_error_flag (ret_value) && !is_parse_only) { jerry_value_t func_val = ret_value; ret_value = jerry_run (func_val); jerry_release_value (func_val); } } if (jerry_value_has_error_flag (ret_value)) { break; } } } if (is_repl_mode) { const char *prompt = "jerry> "; bool is_done = false; jerry_value_t global_obj_val = jerry_get_global_object (); jerry_value_t print_func_name_val = jerry_create_string ((jerry_char_t *) "print"); jerry_value_t print_function = jerry_get_property (global_obj_val, print_func_name_val); jerry_release_value (print_func_name_val); if (jerry_value_has_error_flag (print_function)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (!jerry_value_is_function (print_function)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } while (!is_done) { uint8_t *source_buffer_tail = buffer; size_t len = 0; jerry_port_console ("%s", prompt); /* Read a line */ while (true) { if (fread (source_buffer_tail, 1, 1, stdin) != 1 && len == 0) { is_done = true; break; } if (*source_buffer_tail == '\n') { break; } source_buffer_tail ++; len ++; } *source_buffer_tail = 0; if (len > 0) { /* Evaluate the line */ jerry_value_t ret_val_eval = jerry_eval (buffer, len, false); /* Print return value */ const jerry_value_t args[] = { ret_val_eval }; jerry_value_t ret_val_print = jerry_call_function (print_function, jerry_create_undefined (), args, 1); jerry_release_value (ret_val_print); jerry_release_value (ret_val_eval); } } jerry_release_value (global_obj_val); jerry_release_value (print_function); } int ret_code = JERRY_STANDALONE_EXIT_CODE_OK; if (jerry_value_has_error_flag (ret_value)) { jerry_value_clear_error_flag (&ret_value); jerry_value_t err_str_val = jerry_value_to_string (ret_value); jerry_char_t err_str_buf[256]; jerry_size_t err_str_size = jerry_get_string_size (err_str_val); assert (err_str_size < 256); jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); assert (sz == err_str_size); err_str_buf[err_str_size] = 0; jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: unhandled exception: %s\n", err_str_buf); jerry_release_value (err_str_val); ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_release_value (ret_value); jerry_cleanup (); return ret_code; } /* main */
int main (void) { jerry_init (JERRY_INIT_EMPTY); if (!jerry_is_feature_enabled (JERRY_FEATURE_TYPEDARRAY)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "ArrayBuffer is disabled!\n"); jerry_cleanup (); return 0; } jerry_value_t function_val = jerry_create_external_function (assert_handler); register_js_value ("assert", function_val); jerry_release_value (function_val); /* Test array buffer queries */ { const char *eval_arraybuffer_src_p = "new ArrayBuffer (10)"; jerry_value_t eval_arraybuffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (eval_arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (eval_arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (eval_arraybuffer) == 10); jerry_release_value (eval_arraybuffer); } /* Test array buffer creation */ { const uint32_t length = 15; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); jerry_release_value (arraybuffer); } /* Test array buffer read operations */ for (uint8_t i = 0; i < 15; i++) { test_read_with_offset (i); } /* Test zero length ArrayBuffer read */ { const uint32_t length = 0; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); uint8_t data[20]; memset (data, 11, 20); jerry_length_t bytes_read = jerry_arraybuffer_read (arraybuffer, 0, data, 20); TEST_ASSERT (bytes_read == 0); for (int i = 0; i < 20; i++) { TEST_ASSERT (data[i] == 11); } jerry_release_value (arraybuffer); } /* Test array buffer write operations */ for (uint8_t i = 0; i < 15; i++) { test_write_with_offset (i); } /* Test zero length ArrayBuffer write */ { const uint32_t length = 0; jerry_value_t arraybuffer = jerry_create_arraybuffer (length); TEST_ASSERT (!jerry_value_is_error (arraybuffer)); TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length); uint8_t data[20]; memset (data, 11, 20); jerry_length_t bytes_written = jerry_arraybuffer_write (arraybuffer, 0, data, 20); TEST_ASSERT (bytes_written == 0); jerry_release_value (arraybuffer); } /* Test ArrayBuffer with buffer allocated externally */ { const uint32_t buffer_size = 15; const uint8_t base_value = 51; uint8_t buffer_p[buffer_size]; memset (buffer_p, base_value, buffer_size); jerry_value_t arrayb = jerry_create_arraybuffer_external (buffer_size, buffer_p, test_free_cb); uint8_t new_value = 123; jerry_length_t copied = jerry_arraybuffer_write (arrayb, 0, &new_value, 1); TEST_ASSERT (copied == 1); TEST_ASSERT (buffer_p[0] == new_value); TEST_ASSERT (jerry_get_arraybuffer_byte_length (arrayb) == buffer_size); for (uint32_t i = 1; i < buffer_size; i++) { TEST_ASSERT (buffer_p[i] == base_value); } uint8_t test_buffer[buffer_size]; jerry_length_t read = jerry_arraybuffer_read (arrayb, 0, test_buffer, buffer_size); TEST_ASSERT (read == buffer_size); TEST_ASSERT (test_buffer[0] == new_value); for (uint32_t i = 1; i < buffer_size; i++) { TEST_ASSERT (test_buffer[i] == base_value); } TEST_ASSERT (jerry_value_is_arraybuffer (arrayb)); jerry_release_value (arrayb); } /* Test ArrayBuffer external memory map/unmap */ { const uint32_t buffer_size = 20; uint8_t buffer_p[buffer_size]; { jerry_value_t input_buffer = jerry_create_arraybuffer_external (buffer_size, buffer_p, NULL); register_js_value ("input_buffer", input_buffer); jerry_release_value (input_buffer); } const char *eval_arraybuffer_src_p = ( "var array = new Uint8Array(input_buffer);" "for (var i = 0; i < array.length; i++)" "{" " array[i] = i * 2;" "};" "array.buffer"); jerry_value_t buffer = jerry_eval ((jerry_char_t *) eval_arraybuffer_src_p, strlen (eval_arraybuffer_src_p), true); TEST_ASSERT (!jerry_value_is_error (buffer)); TEST_ASSERT (jerry_value_is_arraybuffer (buffer)); TEST_ASSERT (jerry_get_arraybuffer_byte_length (buffer) == 20); uint8_t *const data = jerry_get_arraybuffer_pointer (buffer); /* test memory read */ for (int i = 0; i < 20; i++) { TEST_ASSERT (data[i] == (uint8_t) (i * 2)); } /* "upload" new data */ double sum = 0; for (int i = 0; i < 20; i++) { data[i] = (uint8_t)(i * 3); sum += data[i]; } jerry_release_value (buffer); const char *eval_test_arraybuffer_p = ( "var sum = 0;" "for (var i = 0; i < array.length; i++)" "{" " var expected = i * 3;" " assert(array[i] == expected, 'Array at index ' + i + ' was: ' + array[i] + ' should be: ' + expected);" " sum += array[i]" "};" "sum"); jerry_value_t res = jerry_eval ((jerry_char_t *) eval_test_arraybuffer_p, strlen (eval_test_arraybuffer_p), true); TEST_ASSERT (jerry_value_is_number (res)); TEST_ASSERT (jerry_get_number_value (res) == sum); jerry_release_value (res); jerry_release_value (buffer); } /* Test ArrayBuffer external with invalid arguments */ { jerry_value_t input_buffer = jerry_create_arraybuffer_external (0, NULL, NULL); TEST_ASSERT (jerry_value_is_error (input_buffer)); TEST_ASSERT (jerry_get_error_type (input_buffer) == JERRY_ERROR_RANGE); jerry_release_value (input_buffer); } jerry_cleanup (); TEST_ASSERT (callback_called == true); return 0; } /* main */
static char* read_sources (const char *script_file_names[], int files_count, size_t *out_source_size_p) { int i; char* source_buffer = NULL; char *source_buffer_tail = NULL; size_t total_length = 0; FILE *file = NULL; for (i = 0; i < files_count; i++) { const char *script_file_name = script_file_names[i]; file = fopen (script_file_name, "r"); if (file == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to fopen [%s]\n", script_file_name); return NULL; } int fseek_status = fseek (file, 0, SEEK_END); if (fseek_status != 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to fseek fseek_status(%d)\n", fseek_status); fclose (file); return NULL; } long script_len = ftell (file); if (script_len < 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to ftell script_len(%ld)\n", script_len); fclose (file); break; } total_length += (size_t)script_len; fclose (file); file = NULL; } if (total_length <= 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Theres noting to read\n"); return NULL; } source_buffer = (char*)malloc(total_length); if (source_buffer == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Out of memory error\n"); return NULL; } memset(source_buffer, 0, sizeof(char)*total_length); source_buffer_tail = source_buffer; for (i = 0; i < files_count; i++) { const char *script_file_name = script_file_names[i]; file = fopen (script_file_name, "r"); if (file == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to fopen [%s]\n", script_file_name); break; } int fseek_status = fseek (file, 0, SEEK_END); if (fseek_status != 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to fseek fseek_status(%d)\n", fseek_status); break; } long script_len = ftell (file); if (script_len < 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to ftell script_len(%ld)\n", script_len); break; } rewind (file); const size_t current_source_size = (size_t)script_len; size_t bytes_read = fread (source_buffer_tail, 1, current_source_size, file); if (bytes_read < current_source_size) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to fread bytes_read(%d)\n", bytes_read); break; } fclose (file); file = NULL; source_buffer_tail += current_source_size; } if (file != NULL) { fclose (file); } if (i < files_count) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to read script N%d\n", i + 1); free(source_buffer); return NULL; } *out_source_size_p = (size_t)total_length; return source_buffer; }
int jerryscript_entry (int argc, char *argv[]) { if (argc >= JERRY_MAX_COMMAND_LINE_ARGS) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Too many command line arguments. Current maximum is %d\n", JERRY_MAX_COMMAND_LINE_ARGS); return JERRY_STANDALONE_EXIT_CODE_FAIL; } const char *file_names[JERRY_MAX_COMMAND_LINE_ARGS]; int i; int files_counter = 0; for (i = 1; i < argc; i++) { printf ("PARAM %d : [%s]\n", i, argv[i]); } jerry_flag_t flags = JERRY_FLAG_EMPTY; for (i = 1; i < argc; i++) { if (!strcmp ("-v", argv[i])) { printf ("Build date: \t%s\n", jerry_build_date); printf ("Commit hash:\t%s\n", jerry_commit_hash); printf ("Branch name:\t%s\n", jerry_branch_name); } else if (!strcmp ("--mem-stats", argv[i])) { flags |= JERRY_FLAG_MEM_STATS; } else if (!strcmp ("--mem-stats-separate", argv[i])) { flags |= JERRY_FLAG_MEM_STATS_SEPARATE; } else if (!strcmp ("--parse-only", argv[i])) { flags |= JERRY_FLAG_PARSE_ONLY; } else if (!strcmp ("--show-opcodes", argv[i])) { flags |= JERRY_FLAG_SHOW_OPCODES; } else if (!strcmp ("--abort-on-fail", argv[i])) { jerry_port_default_set_abort_on_fail (true); } else if (!strcmp ("--log-level", argv[i])) { flags |= JERRY_FLAG_ENABLE_LOG; if (++i < argc && strlen (argv[i]) == 1 && argv[i][0] >='0' && argv[i][0] <= '3') { #ifdef JERRY_ENABLE_LOG jerry_debug_level = argv[i][0] - '0'; #endif /* JERRY_ENABLE_LOG */ } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format or invalid argument\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } else { file_names[files_counter++] = argv[i]; } } if (files_counter == 0) { printf ("Jerry: file count 0\n"); return JERRY_STANDALONE_EXIT_CODE_OK; } size_t source_size; char *source_p = read_sources (file_names, files_counter, &source_size); if (source_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "JERRY_STANDALONE_EXIT_CODE_FAIL\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_completion_code_t ret_code; ret_code = jerry_run_simple ((jerry_api_char_t *) source_p, source_size, flags); free(source_p); if (ret_code != JERRY_COMPLETION_CODE_OK) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } return JERRY_STANDALONE_EXIT_CODE_OK; }