1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include <assert.h> 17425bb815Sopenharmony_ci#include <stdio.h> 18425bb815Sopenharmony_ci#include <stdlib.h> 19425bb815Sopenharmony_ci#include <string.h> 20425bb815Sopenharmony_ci 21425bb815Sopenharmony_ci#include "jerryscript.h" 22425bb815Sopenharmony_ci#include "jerryscript-ext/debugger.h" 23425bb815Sopenharmony_ci#include "jerryscript-ext/handler.h" 24425bb815Sopenharmony_ci#include "jerryscript-port.h" 25425bb815Sopenharmony_ci#include "jerryscript-port-default.h" 26425bb815Sopenharmony_ci 27425bb815Sopenharmony_ci#include "cli.h" 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci/** 30425bb815Sopenharmony_ci * Maximum size of source code 31425bb815Sopenharmony_ci */ 32425bb815Sopenharmony_ci#define JERRY_BUFFER_SIZE (1048576) 33425bb815Sopenharmony_ci 34425bb815Sopenharmony_ci/** 35425bb815Sopenharmony_ci * Maximum size of snapshots buffer 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_ci#define JERRY_SNAPSHOT_BUFFER_SIZE (JERRY_BUFFER_SIZE / sizeof (uint32_t)) 38425bb815Sopenharmony_ci 39425bb815Sopenharmony_ci/** 40425bb815Sopenharmony_ci * Standalone Jerry exit codes 41425bb815Sopenharmony_ci */ 42425bb815Sopenharmony_ci#define JERRY_STANDALONE_EXIT_CODE_OK (0) 43425bb815Sopenharmony_ci#define JERRY_STANDALONE_EXIT_CODE_FAIL (1) 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ci/** 46425bb815Sopenharmony_ci * Context size of the SYNTAX_ERROR 47425bb815Sopenharmony_ci */ 48425bb815Sopenharmony_ci#define SYNTAX_ERROR_CONTEXT_SIZE 2 49425bb815Sopenharmony_ci 50425bb815Sopenharmony_cistatic uint8_t buffer[ JERRY_BUFFER_SIZE ]; 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_cistatic const uint32_t * 53425bb815Sopenharmony_ciread_file (const char *file_name, 54425bb815Sopenharmony_ci size_t *out_size_p) 55425bb815Sopenharmony_ci{ 56425bb815Sopenharmony_ci if (file_name == NULL) 57425bb815Sopenharmony_ci { 58425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file, missing filename\n"); 59425bb815Sopenharmony_ci return NULL; 60425bb815Sopenharmony_ci } 61425bb815Sopenharmony_ci 62425bb815Sopenharmony_ci FILE *file; 63425bb815Sopenharmony_ci if (!strcmp ("-", file_name)) 64425bb815Sopenharmony_ci { 65425bb815Sopenharmony_ci file = stdin; 66425bb815Sopenharmony_ci } 67425bb815Sopenharmony_ci else 68425bb815Sopenharmony_ci { 69425bb815Sopenharmony_ci file = fopen (file_name, "rb"); 70425bb815Sopenharmony_ci if (file == NULL) 71425bb815Sopenharmony_ci { 72425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name); 73425bb815Sopenharmony_ci return NULL; 74425bb815Sopenharmony_ci } 75425bb815Sopenharmony_ci } 76425bb815Sopenharmony_ci 77425bb815Sopenharmony_ci size_t bytes_read = fread (buffer, 1u, sizeof (buffer), file); 78425bb815Sopenharmony_ci if (!bytes_read) 79425bb815Sopenharmony_ci { 80425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name); 81425bb815Sopenharmony_ci fclose (file); 82425bb815Sopenharmony_ci return NULL; 83425bb815Sopenharmony_ci } 84425bb815Sopenharmony_ci 85425bb815Sopenharmony_ci fclose (file); 86425bb815Sopenharmony_ci 87425bb815Sopenharmony_ci *out_size_p = bytes_read; 88425bb815Sopenharmony_ci return (const uint32_t *) buffer; 89425bb815Sopenharmony_ci} /* read_file */ 90425bb815Sopenharmony_ci 91425bb815Sopenharmony_ci/** 92425bb815Sopenharmony_ci * Print error value 93425bb815Sopenharmony_ci */ 94425bb815Sopenharmony_cistatic void 95425bb815Sopenharmony_ciprint_unhandled_exception (jerry_value_t error_value) /**< error value */ 96425bb815Sopenharmony_ci{ 97425bb815Sopenharmony_ci assert (!jerry_value_is_error (error_value)); 98425bb815Sopenharmony_ci 99425bb815Sopenharmony_ci jerry_char_t err_str_buf[256]; 100425bb815Sopenharmony_ci 101425bb815Sopenharmony_ci if (jerry_value_is_object (error_value)) 102425bb815Sopenharmony_ci { 103425bb815Sopenharmony_ci jerry_value_t stack_str = jerry_create_string ((const jerry_char_t *) "stack"); 104425bb815Sopenharmony_ci jerry_value_t backtrace_val = jerry_get_property (error_value, stack_str); 105425bb815Sopenharmony_ci jerry_release_value (stack_str); 106425bb815Sopenharmony_ci 107425bb815Sopenharmony_ci if (!jerry_value_is_error (backtrace_val) 108425bb815Sopenharmony_ci && jerry_value_is_array (backtrace_val)) 109425bb815Sopenharmony_ci { 110425bb815Sopenharmony_ci printf ("Exception backtrace:\n"); 111425bb815Sopenharmony_ci 112425bb815Sopenharmony_ci uint32_t length = jerry_get_array_length (backtrace_val); 113425bb815Sopenharmony_ci 114425bb815Sopenharmony_ci /* This length should be enough. */ 115425bb815Sopenharmony_ci if (length > 32) 116425bb815Sopenharmony_ci { 117425bb815Sopenharmony_ci length = 32; 118425bb815Sopenharmony_ci } 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci for (uint32_t i = 0; i < length; i++) 121425bb815Sopenharmony_ci { 122425bb815Sopenharmony_ci jerry_value_t item_val = jerry_get_property_by_index (backtrace_val, i); 123425bb815Sopenharmony_ci 124425bb815Sopenharmony_ci if (!jerry_value_is_error (item_val) 125425bb815Sopenharmony_ci && jerry_value_is_string (item_val)) 126425bb815Sopenharmony_ci { 127425bb815Sopenharmony_ci jerry_size_t str_size = jerry_get_utf8_string_size (item_val); 128425bb815Sopenharmony_ci 129425bb815Sopenharmony_ci if (str_size >= 256) 130425bb815Sopenharmony_ci { 131425bb815Sopenharmony_ci printf ("%3u: [Backtrace string too long]\n", i); 132425bb815Sopenharmony_ci } 133425bb815Sopenharmony_ci else 134425bb815Sopenharmony_ci { 135425bb815Sopenharmony_ci jerry_size_t string_end = jerry_string_to_utf8_char_buffer (item_val, err_str_buf, str_size); 136425bb815Sopenharmony_ci assert (string_end == str_size); 137425bb815Sopenharmony_ci err_str_buf[string_end] = 0; 138425bb815Sopenharmony_ci 139425bb815Sopenharmony_ci printf ("%3u: %s\n", i, err_str_buf); 140425bb815Sopenharmony_ci } 141425bb815Sopenharmony_ci } 142425bb815Sopenharmony_ci 143425bb815Sopenharmony_ci jerry_release_value (item_val); 144425bb815Sopenharmony_ci } 145425bb815Sopenharmony_ci } 146425bb815Sopenharmony_ci jerry_release_value (backtrace_val); 147425bb815Sopenharmony_ci } 148425bb815Sopenharmony_ci 149425bb815Sopenharmony_ci jerry_value_t err_str_val = jerry_value_to_string (error_value); 150425bb815Sopenharmony_ci jerry_size_t err_str_size = jerry_get_utf8_string_size (err_str_val); 151425bb815Sopenharmony_ci 152425bb815Sopenharmony_ci if (err_str_size >= 256) 153425bb815Sopenharmony_ci { 154425bb815Sopenharmony_ci const char msg[] = "[Error message too long]"; 155425bb815Sopenharmony_ci err_str_size = sizeof (msg) / sizeof (char) - 1; 156425bb815Sopenharmony_ci memcpy (err_str_buf, msg, err_str_size + 1); 157425bb815Sopenharmony_ci } 158425bb815Sopenharmony_ci else 159425bb815Sopenharmony_ci { 160425bb815Sopenharmony_ci jerry_size_t string_end = jerry_string_to_utf8_char_buffer (err_str_val, err_str_buf, err_str_size); 161425bb815Sopenharmony_ci assert (string_end == err_str_size); 162425bb815Sopenharmony_ci err_str_buf[string_end] = 0; 163425bb815Sopenharmony_ci 164425bb815Sopenharmony_ci if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES) 165425bb815Sopenharmony_ci && jerry_get_error_type (error_value) == JERRY_ERROR_SYNTAX) 166425bb815Sopenharmony_ci { 167425bb815Sopenharmony_ci jerry_char_t *string_end_p = err_str_buf + string_end; 168425bb815Sopenharmony_ci unsigned int err_line = 0; 169425bb815Sopenharmony_ci unsigned int err_col = 0; 170425bb815Sopenharmony_ci char *path_str_p = NULL; 171425bb815Sopenharmony_ci char *path_str_end_p = NULL; 172425bb815Sopenharmony_ci 173425bb815Sopenharmony_ci /* 1. parse column and line information */ 174425bb815Sopenharmony_ci for (jerry_char_t *current_p = err_str_buf; current_p < string_end_p; current_p++) 175425bb815Sopenharmony_ci { 176425bb815Sopenharmony_ci if (*current_p == '[') 177425bb815Sopenharmony_ci { 178425bb815Sopenharmony_ci current_p++; 179425bb815Sopenharmony_ci 180425bb815Sopenharmony_ci if (*current_p == '<') 181425bb815Sopenharmony_ci { 182425bb815Sopenharmony_ci break; 183425bb815Sopenharmony_ci } 184425bb815Sopenharmony_ci 185425bb815Sopenharmony_ci path_str_p = (char *) current_p; 186425bb815Sopenharmony_ci while (current_p < string_end_p && *current_p != ':') 187425bb815Sopenharmony_ci { 188425bb815Sopenharmony_ci current_p++; 189425bb815Sopenharmony_ci } 190425bb815Sopenharmony_ci 191425bb815Sopenharmony_ci path_str_end_p = (char *) current_p++; 192425bb815Sopenharmony_ci 193425bb815Sopenharmony_ci err_line = (unsigned int) strtol ((char *) current_p, (char **) ¤t_p, 10); 194425bb815Sopenharmony_ci 195425bb815Sopenharmony_ci current_p++; 196425bb815Sopenharmony_ci 197425bb815Sopenharmony_ci err_col = (unsigned int) strtol ((char *) current_p, NULL, 10); 198425bb815Sopenharmony_ci break; 199425bb815Sopenharmony_ci } 200425bb815Sopenharmony_ci } /* for */ 201425bb815Sopenharmony_ci 202425bb815Sopenharmony_ci if (err_line != 0 && err_col != 0) 203425bb815Sopenharmony_ci { 204425bb815Sopenharmony_ci unsigned int curr_line = 1; 205425bb815Sopenharmony_ci 206425bb815Sopenharmony_ci bool is_printing_context = false; 207425bb815Sopenharmony_ci unsigned int pos = 0; 208425bb815Sopenharmony_ci 209425bb815Sopenharmony_ci size_t source_size; 210425bb815Sopenharmony_ci 211425bb815Sopenharmony_ci /* Temporarily modify the error message, so we can use the path. */ 212425bb815Sopenharmony_ci *path_str_end_p = '\0'; 213425bb815Sopenharmony_ci 214425bb815Sopenharmony_ci read_file (path_str_p, &source_size); 215425bb815Sopenharmony_ci 216425bb815Sopenharmony_ci /* Revert the error message. */ 217425bb815Sopenharmony_ci *path_str_end_p = ':'; 218425bb815Sopenharmony_ci 219425bb815Sopenharmony_ci /* 2. seek and print */ 220425bb815Sopenharmony_ci while ((pos < source_size) && (buffer[pos] != '\0')) 221425bb815Sopenharmony_ci { 222425bb815Sopenharmony_ci if (buffer[pos] == '\n') 223425bb815Sopenharmony_ci { 224425bb815Sopenharmony_ci curr_line++; 225425bb815Sopenharmony_ci } 226425bb815Sopenharmony_ci 227425bb815Sopenharmony_ci if (err_line < SYNTAX_ERROR_CONTEXT_SIZE 228425bb815Sopenharmony_ci || (err_line >= curr_line 229425bb815Sopenharmony_ci && (err_line - curr_line) <= SYNTAX_ERROR_CONTEXT_SIZE)) 230425bb815Sopenharmony_ci { 231425bb815Sopenharmony_ci /* context must be printed */ 232425bb815Sopenharmony_ci is_printing_context = true; 233425bb815Sopenharmony_ci } 234425bb815Sopenharmony_ci 235425bb815Sopenharmony_ci if (curr_line > err_line) 236425bb815Sopenharmony_ci { 237425bb815Sopenharmony_ci break; 238425bb815Sopenharmony_ci } 239425bb815Sopenharmony_ci 240425bb815Sopenharmony_ci if (is_printing_context) 241425bb815Sopenharmony_ci { 242425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%c", buffer[pos]); 243425bb815Sopenharmony_ci } 244425bb815Sopenharmony_ci 245425bb815Sopenharmony_ci pos++; 246425bb815Sopenharmony_ci } 247425bb815Sopenharmony_ci 248425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "\n"); 249425bb815Sopenharmony_ci 250425bb815Sopenharmony_ci while (--err_col) 251425bb815Sopenharmony_ci { 252425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "~"); 253425bb815Sopenharmony_ci } 254425bb815Sopenharmony_ci 255425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "^\n"); 256425bb815Sopenharmony_ci } 257425bb815Sopenharmony_ci } 258425bb815Sopenharmony_ci } 259425bb815Sopenharmony_ci 260425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf); 261425bb815Sopenharmony_ci jerry_release_value (err_str_val); 262425bb815Sopenharmony_ci} /* print_unhandled_exception */ 263425bb815Sopenharmony_ci 264425bb815Sopenharmony_ci/** 265425bb815Sopenharmony_ci * Register a JavaScript function in the global object. 266425bb815Sopenharmony_ci */ 267425bb815Sopenharmony_cistatic void 268425bb815Sopenharmony_ciregister_js_function (const char *name_p, /**< name of the function */ 269425bb815Sopenharmony_ci jerry_external_handler_t handler_p) /**< function callback */ 270425bb815Sopenharmony_ci{ 271425bb815Sopenharmony_ci jerry_value_t result_val = jerryx_handler_register_global ((const jerry_char_t *) name_p, handler_p); 272425bb815Sopenharmony_ci 273425bb815Sopenharmony_ci if (jerry_value_is_error (result_val)) 274425bb815Sopenharmony_ci { 275425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Warning: failed to register '%s' method.", name_p); 276425bb815Sopenharmony_ci result_val = jerry_get_value_from_error (result_val, true); 277425bb815Sopenharmony_ci print_unhandled_exception (result_val); 278425bb815Sopenharmony_ci } 279425bb815Sopenharmony_ci 280425bb815Sopenharmony_ci jerry_release_value (result_val); 281425bb815Sopenharmony_ci} /* register_js_function */ 282425bb815Sopenharmony_ci 283425bb815Sopenharmony_ci/** 284425bb815Sopenharmony_ci * Runs the source code received by jerry_debugger_wait_for_client_source. 285425bb815Sopenharmony_ci * 286425bb815Sopenharmony_ci * @return result fo the source code execution 287425bb815Sopenharmony_ci */ 288425bb815Sopenharmony_cistatic jerry_value_t 289425bb815Sopenharmony_ciwait_for_source_callback (const jerry_char_t *resource_name_p, /**< resource name */ 290425bb815Sopenharmony_ci size_t resource_name_size, /**< size of resource name */ 291425bb815Sopenharmony_ci const jerry_char_t *source_p, /**< source code */ 292425bb815Sopenharmony_ci size_t source_size, /**< source code size */ 293425bb815Sopenharmony_ci void *user_p) /**< user pointer */ 294425bb815Sopenharmony_ci{ 295425bb815Sopenharmony_ci (void) user_p; /* unused */ 296425bb815Sopenharmony_ci jerry_value_t ret_val = jerry_parse (resource_name_p, 297425bb815Sopenharmony_ci resource_name_size, 298425bb815Sopenharmony_ci source_p, 299425bb815Sopenharmony_ci source_size, 300425bb815Sopenharmony_ci JERRY_PARSE_NO_OPTS); 301425bb815Sopenharmony_ci 302425bb815Sopenharmony_ci if (!jerry_value_is_error (ret_val)) 303425bb815Sopenharmony_ci { 304425bb815Sopenharmony_ci jerry_value_t func_val = ret_val; 305425bb815Sopenharmony_ci ret_val = jerry_run (func_val); 306425bb815Sopenharmony_ci jerry_release_value (func_val); 307425bb815Sopenharmony_ci } 308425bb815Sopenharmony_ci 309425bb815Sopenharmony_ci return ret_val; 310425bb815Sopenharmony_ci} /* wait_for_source_callback */ 311425bb815Sopenharmony_ci 312425bb815Sopenharmony_ci/** 313425bb815Sopenharmony_ci * Command line option IDs 314425bb815Sopenharmony_ci */ 315425bb815Sopenharmony_citypedef enum 316425bb815Sopenharmony_ci{ 317425bb815Sopenharmony_ci OPT_HELP, 318425bb815Sopenharmony_ci OPT_VERSION, 319425bb815Sopenharmony_ci OPT_MEM_STATS, 320425bb815Sopenharmony_ci OPT_PARSE_ONLY, 321425bb815Sopenharmony_ci OPT_SHOW_OP, 322425bb815Sopenharmony_ci OPT_SHOW_RE_OP, 323425bb815Sopenharmony_ci OPT_DEBUG_SERVER, 324425bb815Sopenharmony_ci OPT_DEBUG_PORT, 325425bb815Sopenharmony_ci OPT_DEBUG_CHANNEL, 326425bb815Sopenharmony_ci OPT_DEBUG_PROTOCOL, 327425bb815Sopenharmony_ci OPT_DEBUG_SERIAL_CONFIG, 328425bb815Sopenharmony_ci OPT_DEBUGGER_WAIT_SOURCE, 329425bb815Sopenharmony_ci OPT_EXEC_SNAP, 330425bb815Sopenharmony_ci OPT_EXEC_SNAP_FUNC, 331425bb815Sopenharmony_ci OPT_LOG_LEVEL, 332425bb815Sopenharmony_ci OPT_NO_PROMPT, 333425bb815Sopenharmony_ci OPT_CALL_ON_EXIT 334425bb815Sopenharmony_ci} main_opt_id_t; 335425bb815Sopenharmony_ci 336425bb815Sopenharmony_ci/** 337425bb815Sopenharmony_ci * Command line options 338425bb815Sopenharmony_ci */ 339425bb815Sopenharmony_cistatic const cli_opt_t main_opts[] = 340425bb815Sopenharmony_ci{ 341425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_HELP, .opt = "h", .longopt = "help", 342425bb815Sopenharmony_ci .help = "print this help and exit"), 343425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_VERSION, .opt = "v", .longopt = "version", 344425bb815Sopenharmony_ci .help = "print tool and library version and exit"), 345425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_MEM_STATS, .longopt = "mem-stats", 346425bb815Sopenharmony_ci .help = "dump memory statistics"), 347425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_PARSE_ONLY, .longopt = "parse-only", 348425bb815Sopenharmony_ci .help = "don't execute JS input"), 349425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_SHOW_OP, .longopt = "show-opcodes", 350425bb815Sopenharmony_ci .help = "dump parser byte-code"), 351425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_SHOW_RE_OP, .longopt = "show-regexp-opcodes", 352425bb815Sopenharmony_ci .help = "dump regexp byte-code"), 353425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUG_SERVER, .longopt = "start-debug-server", 354425bb815Sopenharmony_ci .help = "start debug server and wait for a connecting client"), 355425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUG_PORT, .longopt = "debug-port", .meta = "NUM", 356425bb815Sopenharmony_ci .help = "debug server port (default: 5001)"), 357425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUG_CHANNEL, .longopt = "debug-channel", .meta = "[websocket|rawpacket]", 358425bb815Sopenharmony_ci .help = "Specify the debugger transmission channel (default: websocket)"), 359425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUG_PROTOCOL, .longopt = "debug-protocol", .meta = "PROTOCOL", 360425bb815Sopenharmony_ci .help = "Specify the transmission protocol over the communication channel (tcp|serial, default: tcp)"), 361425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUG_SERIAL_CONFIG, .longopt = "serial-config", .meta = "OPTIONS_STRING", 362425bb815Sopenharmony_ci .help = "Configure parameters for serial port (default: /dev/ttyS0,115200,8,N,1)"), 363425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_DEBUGGER_WAIT_SOURCE, .longopt = "debugger-wait-source", 364425bb815Sopenharmony_ci .help = "wait for an executable source from the client"), 365425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_EXEC_SNAP, .longopt = "exec-snapshot", .meta = "FILE", 366425bb815Sopenharmony_ci .help = "execute input snapshot file(s)"), 367425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_EXEC_SNAP_FUNC, .longopt = "exec-snapshot-func", .meta = "FILE NUM", 368425bb815Sopenharmony_ci .help = "execute specific function from input snapshot file(s)"), 369425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_LOG_LEVEL, .longopt = "log-level", .meta = "NUM", 370425bb815Sopenharmony_ci .help = "set log level (0-3)"), 371425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_NO_PROMPT, .longopt = "no-prompt", 372425bb815Sopenharmony_ci .help = "don't print prompt in REPL mode"), 373425bb815Sopenharmony_ci CLI_OPT_DEF (.id = OPT_CALL_ON_EXIT, .longopt = "call-on-exit", .meta = "STRING", 374425bb815Sopenharmony_ci .help = "invoke the specified function when the process is just about to exit"), 375425bb815Sopenharmony_ci CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE", 376425bb815Sopenharmony_ci .help = "input JS file(s) (If file is -, read standard input.)") 377425bb815Sopenharmony_ci}; 378425bb815Sopenharmony_ci 379425bb815Sopenharmony_ci/** 380425bb815Sopenharmony_ci * Check whether JerryScript has a requested feature enabled or not. If not, 381425bb815Sopenharmony_ci * print a warning message. 382425bb815Sopenharmony_ci * 383425bb815Sopenharmony_ci * @return the status of the feature. 384425bb815Sopenharmony_ci */ 385425bb815Sopenharmony_cistatic bool 386425bb815Sopenharmony_cicheck_feature (jerry_feature_t feature, /**< feature to check */ 387425bb815Sopenharmony_ci const char *option) /**< command line option that triggered this check */ 388425bb815Sopenharmony_ci{ 389425bb815Sopenharmony_ci if (!jerry_is_feature_enabled (feature)) 390425bb815Sopenharmony_ci { 391425bb815Sopenharmony_ci jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING); 392425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option); 393425bb815Sopenharmony_ci return false; 394425bb815Sopenharmony_ci } 395425bb815Sopenharmony_ci return true; 396425bb815Sopenharmony_ci} /* check_feature */ 397425bb815Sopenharmony_ci 398425bb815Sopenharmony_ci/** 399425bb815Sopenharmony_ci * Check whether a usage-related condition holds. If not, print an error 400425bb815Sopenharmony_ci * message, print the usage, and terminate the application. 401425bb815Sopenharmony_ci */ 402425bb815Sopenharmony_cistatic void 403425bb815Sopenharmony_cicheck_usage (bool condition, /**< the condition that must hold */ 404425bb815Sopenharmony_ci const char *name, /**< name of the application (argv[0]) */ 405425bb815Sopenharmony_ci const char *msg, /**< error message to print if condition does not hold */ 406425bb815Sopenharmony_ci const char *opt) /**< optional part of the error message */ 407425bb815Sopenharmony_ci{ 408425bb815Sopenharmony_ci if (!condition) 409425bb815Sopenharmony_ci { 410425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%s: %s%s\n", name, msg, opt != NULL ? opt : ""); 411425bb815Sopenharmony_ci exit (JERRY_STANDALONE_EXIT_CODE_FAIL); 412425bb815Sopenharmony_ci } 413425bb815Sopenharmony_ci} /* check_usage */ 414425bb815Sopenharmony_ci 415425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) 416425bb815Sopenharmony_ci 417425bb815Sopenharmony_ci/** 418425bb815Sopenharmony_ci * The alloc function passed to jerry_create_context 419425bb815Sopenharmony_ci */ 420425bb815Sopenharmony_cistatic void * 421425bb815Sopenharmony_cicontext_alloc (size_t size, 422425bb815Sopenharmony_ci void *cb_data_p) 423425bb815Sopenharmony_ci{ 424425bb815Sopenharmony_ci (void) cb_data_p; /* unused */ 425425bb815Sopenharmony_ci return malloc (size); 426425bb815Sopenharmony_ci} /* context_alloc */ 427425bb815Sopenharmony_ci 428425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */ 429425bb815Sopenharmony_ci 430425bb815Sopenharmony_ci/** 431425bb815Sopenharmony_ci * Inits the engine and the debugger 432425bb815Sopenharmony_ci */ 433425bb815Sopenharmony_cistatic void 434425bb815Sopenharmony_ciinit_engine (jerry_init_flag_t flags, /**< initialized flags for the engine */ 435425bb815Sopenharmony_ci char *debug_channel, /**< enable the debugger init or not */ 436425bb815Sopenharmony_ci char *debug_protocol, /**< enable the debugger init or not */ 437425bb815Sopenharmony_ci uint16_t debug_port, /**< the debugger port for tcp protocol */ 438425bb815Sopenharmony_ci char *debug_serial_config) /**< configuration string for serial protocol */ 439425bb815Sopenharmony_ci{ 440425bb815Sopenharmony_ci jerry_init (flags); 441425bb815Sopenharmony_ci if (strcmp (debug_channel, "")) 442425bb815Sopenharmony_ci { 443425bb815Sopenharmony_ci bool protocol = false; 444425bb815Sopenharmony_ci 445425bb815Sopenharmony_ci if (!strcmp (debug_protocol, "tcp")) 446425bb815Sopenharmony_ci { 447425bb815Sopenharmony_ci protocol = jerryx_debugger_tcp_create (debug_port); 448425bb815Sopenharmony_ci } 449425bb815Sopenharmony_ci else 450425bb815Sopenharmony_ci { 451425bb815Sopenharmony_ci assert (!strcmp (debug_protocol, "serial")); 452425bb815Sopenharmony_ci protocol = jerryx_debugger_serial_create (debug_serial_config); 453425bb815Sopenharmony_ci } 454425bb815Sopenharmony_ci 455425bb815Sopenharmony_ci if (!strcmp (debug_channel, "rawpacket")) 456425bb815Sopenharmony_ci { 457425bb815Sopenharmony_ci jerryx_debugger_after_connect (protocol && jerryx_debugger_rp_create ()); 458425bb815Sopenharmony_ci } 459425bb815Sopenharmony_ci else 460425bb815Sopenharmony_ci { 461425bb815Sopenharmony_ci assert (!strcmp (debug_channel, "websocket")); 462425bb815Sopenharmony_ci jerryx_debugger_after_connect (protocol && jerryx_debugger_ws_create ()); 463425bb815Sopenharmony_ci } 464425bb815Sopenharmony_ci } 465425bb815Sopenharmony_ci 466425bb815Sopenharmony_ci register_js_function ("assert", jerryx_handler_assert); 467425bb815Sopenharmony_ci register_js_function ("gc", jerryx_handler_gc); 468425bb815Sopenharmony_ci register_js_function ("print", jerryx_handler_print); 469425bb815Sopenharmony_ci register_js_function ("resourceName", jerryx_handler_resource_name); 470425bb815Sopenharmony_ci} /* init_engine */ 471425bb815Sopenharmony_ci 472425bb815Sopenharmony_ciint 473425bb815Sopenharmony_cimain (int argc, 474425bb815Sopenharmony_ci char **argv) 475425bb815Sopenharmony_ci{ 476425bb815Sopenharmony_ci union 477425bb815Sopenharmony_ci { 478425bb815Sopenharmony_ci double d; 479425bb815Sopenharmony_ci unsigned u; 480425bb815Sopenharmony_ci } now = { .d = jerry_port_get_current_time () }; 481425bb815Sopenharmony_ci srand (now.u); 482425bb815Sopenharmony_ci JERRY_VLA (const char *, file_names, argc); 483425bb815Sopenharmony_ci int files_counter = 0; 484425bb815Sopenharmony_ci 485425bb815Sopenharmony_ci jerry_init_flag_t flags = JERRY_INIT_EMPTY; 486425bb815Sopenharmony_ci 487425bb815Sopenharmony_ci JERRY_VLA (const char *, exec_snapshot_file_names, argc); 488425bb815Sopenharmony_ci JERRY_VLA (uint32_t, exec_snapshot_file_indices, argc); 489425bb815Sopenharmony_ci int exec_snapshots_count = 0; 490425bb815Sopenharmony_ci 491425bb815Sopenharmony_ci bool is_parse_only = false; 492425bb815Sopenharmony_ci 493425bb815Sopenharmony_ci bool start_debug_server = false; 494425bb815Sopenharmony_ci uint16_t debug_port = 5001; 495425bb815Sopenharmony_ci char *debug_channel = "websocket"; 496425bb815Sopenharmony_ci char *debug_protocol = "tcp"; 497425bb815Sopenharmony_ci char *debug_serial_config = "/dev/ttyS0,115200,8,N,1"; 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci bool is_repl_mode = false; 500425bb815Sopenharmony_ci bool is_wait_mode = false; 501425bb815Sopenharmony_ci bool no_prompt = false; 502425bb815Sopenharmony_ci 503425bb815Sopenharmony_ci const char *exit_cb = NULL; 504425bb815Sopenharmony_ci 505425bb815Sopenharmony_ci cli_state_t cli_state = cli_init (main_opts, argc - 1, argv + 1); 506425bb815Sopenharmony_ci for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state)) 507425bb815Sopenharmony_ci { 508425bb815Sopenharmony_ci switch (id) 509425bb815Sopenharmony_ci { 510425bb815Sopenharmony_ci case OPT_HELP: 511425bb815Sopenharmony_ci { 512425bb815Sopenharmony_ci cli_help (argv[0], NULL, main_opts); 513425bb815Sopenharmony_ci return JERRY_STANDALONE_EXIT_CODE_OK; 514425bb815Sopenharmony_ci } 515425bb815Sopenharmony_ci case OPT_VERSION: 516425bb815Sopenharmony_ci { 517425bb815Sopenharmony_ci printf ("Version: %d.%d.%d%s\n", 518425bb815Sopenharmony_ci JERRY_API_MAJOR_VERSION, 519425bb815Sopenharmony_ci JERRY_API_MINOR_VERSION, 520425bb815Sopenharmony_ci JERRY_API_PATCH_VERSION, 521425bb815Sopenharmony_ci JERRY_COMMIT_HASH); 522425bb815Sopenharmony_ci return JERRY_STANDALONE_EXIT_CODE_OK; 523425bb815Sopenharmony_ci } 524425bb815Sopenharmony_ci case OPT_MEM_STATS: 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_MEM_STATS, cli_state.arg)) 527425bb815Sopenharmony_ci { 528425bb815Sopenharmony_ci jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); 529425bb815Sopenharmony_ci flags |= JERRY_INIT_MEM_STATS; 530425bb815Sopenharmony_ci } 531425bb815Sopenharmony_ci break; 532425bb815Sopenharmony_ci } 533425bb815Sopenharmony_ci case OPT_PARSE_ONLY: 534425bb815Sopenharmony_ci { 535425bb815Sopenharmony_ci is_parse_only = true; 536425bb815Sopenharmony_ci break; 537425bb815Sopenharmony_ci } 538425bb815Sopenharmony_ci case OPT_SHOW_OP: 539425bb815Sopenharmony_ci { 540425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state.arg)) 541425bb815Sopenharmony_ci { 542425bb815Sopenharmony_ci jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); 543425bb815Sopenharmony_ci flags |= JERRY_INIT_SHOW_OPCODES; 544425bb815Sopenharmony_ci } 545425bb815Sopenharmony_ci break; 546425bb815Sopenharmony_ci } 547425bb815Sopenharmony_ci case OPT_CALL_ON_EXIT: 548425bb815Sopenharmony_ci { 549425bb815Sopenharmony_ci exit_cb = cli_consume_string (&cli_state); 550425bb815Sopenharmony_ci break; 551425bb815Sopenharmony_ci } 552425bb815Sopenharmony_ci case OPT_SHOW_RE_OP: 553425bb815Sopenharmony_ci { 554425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_REGEXP_DUMP, cli_state.arg)) 555425bb815Sopenharmony_ci { 556425bb815Sopenharmony_ci jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); 557425bb815Sopenharmony_ci flags |= JERRY_INIT_SHOW_REGEXP_OPCODES; 558425bb815Sopenharmony_ci } 559425bb815Sopenharmony_ci break; 560425bb815Sopenharmony_ci } 561425bb815Sopenharmony_ci case OPT_DEBUG_SERVER: 562425bb815Sopenharmony_ci { 563425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 564425bb815Sopenharmony_ci { 565425bb815Sopenharmony_ci start_debug_server = true; 566425bb815Sopenharmony_ci } 567425bb815Sopenharmony_ci break; 568425bb815Sopenharmony_ci } 569425bb815Sopenharmony_ci case OPT_DEBUG_PORT: 570425bb815Sopenharmony_ci { 571425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 572425bb815Sopenharmony_ci { 573425bb815Sopenharmony_ci debug_port = (uint16_t) cli_consume_int (&cli_state); 574425bb815Sopenharmony_ci } 575425bb815Sopenharmony_ci break; 576425bb815Sopenharmony_ci } 577425bb815Sopenharmony_ci case OPT_DEBUG_CHANNEL: 578425bb815Sopenharmony_ci { 579425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 580425bb815Sopenharmony_ci { 581425bb815Sopenharmony_ci debug_channel = (char *) cli_consume_string (&cli_state); 582425bb815Sopenharmony_ci check_usage (!strcmp (debug_channel, "websocket") || !strcmp (debug_channel, "rawpacket"), 583425bb815Sopenharmony_ci argv[0], "Error: invalid value for --debug-channel: ", cli_state.arg); 584425bb815Sopenharmony_ci } 585425bb815Sopenharmony_ci break; 586425bb815Sopenharmony_ci } 587425bb815Sopenharmony_ci case OPT_DEBUG_PROTOCOL: 588425bb815Sopenharmony_ci { 589425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 590425bb815Sopenharmony_ci { 591425bb815Sopenharmony_ci debug_protocol = (char *) cli_consume_string (&cli_state); 592425bb815Sopenharmony_ci check_usage (!strcmp (debug_protocol, "tcp") || !strcmp (debug_protocol, "serial"), 593425bb815Sopenharmony_ci argv[0], "Error: invalid value for --debug-protocol: ", cli_state.arg); 594425bb815Sopenharmony_ci } 595425bb815Sopenharmony_ci break; 596425bb815Sopenharmony_ci } 597425bb815Sopenharmony_ci case OPT_DEBUG_SERIAL_CONFIG: 598425bb815Sopenharmony_ci { 599425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 600425bb815Sopenharmony_ci { 601425bb815Sopenharmony_ci debug_serial_config = (char *) cli_consume_string (&cli_state); 602425bb815Sopenharmony_ci } 603425bb815Sopenharmony_ci break; 604425bb815Sopenharmony_ci } 605425bb815Sopenharmony_ci case OPT_DEBUGGER_WAIT_SOURCE: 606425bb815Sopenharmony_ci { 607425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg)) 608425bb815Sopenharmony_ci { 609425bb815Sopenharmony_ci is_wait_mode = true; 610425bb815Sopenharmony_ci } 611425bb815Sopenharmony_ci break; 612425bb815Sopenharmony_ci } 613425bb815Sopenharmony_ci case OPT_EXEC_SNAP: 614425bb815Sopenharmony_ci { 615425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg)) 616425bb815Sopenharmony_ci { 617425bb815Sopenharmony_ci exec_snapshot_file_names[exec_snapshots_count] = cli_consume_string (&cli_state); 618425bb815Sopenharmony_ci exec_snapshot_file_indices[exec_snapshots_count++] = 0; 619425bb815Sopenharmony_ci } 620425bb815Sopenharmony_ci else 621425bb815Sopenharmony_ci { 622425bb815Sopenharmony_ci cli_consume_string (&cli_state); 623425bb815Sopenharmony_ci } 624425bb815Sopenharmony_ci break; 625425bb815Sopenharmony_ci } 626425bb815Sopenharmony_ci case OPT_EXEC_SNAP_FUNC: 627425bb815Sopenharmony_ci { 628425bb815Sopenharmony_ci if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg)) 629425bb815Sopenharmony_ci { 630425bb815Sopenharmony_ci exec_snapshot_file_names[exec_snapshots_count] = cli_consume_string (&cli_state); 631425bb815Sopenharmony_ci exec_snapshot_file_indices[exec_snapshots_count++] = (uint32_t) cli_consume_int (&cli_state); 632425bb815Sopenharmony_ci } 633425bb815Sopenharmony_ci else 634425bb815Sopenharmony_ci { 635425bb815Sopenharmony_ci cli_consume_string (&cli_state); 636425bb815Sopenharmony_ci } 637425bb815Sopenharmony_ci break; 638425bb815Sopenharmony_ci } 639425bb815Sopenharmony_ci case OPT_LOG_LEVEL: 640425bb815Sopenharmony_ci { 641425bb815Sopenharmony_ci long int log_level = cli_consume_int (&cli_state); 642425bb815Sopenharmony_ci check_usage (log_level >= 0 && log_level <= 3, 643425bb815Sopenharmony_ci argv[0], "Error: invalid value for --log-level: ", cli_state.arg); 644425bb815Sopenharmony_ci 645425bb815Sopenharmony_ci jerry_port_default_set_log_level ((jerry_log_level_t) log_level); 646425bb815Sopenharmony_ci break; 647425bb815Sopenharmony_ci } 648425bb815Sopenharmony_ci case OPT_NO_PROMPT: 649425bb815Sopenharmony_ci { 650425bb815Sopenharmony_ci no_prompt = true; 651425bb815Sopenharmony_ci break; 652425bb815Sopenharmony_ci } 653425bb815Sopenharmony_ci case CLI_OPT_DEFAULT: 654425bb815Sopenharmony_ci { 655425bb815Sopenharmony_ci file_names[files_counter++] = cli_consume_string (&cli_state); 656425bb815Sopenharmony_ci break; 657425bb815Sopenharmony_ci } 658425bb815Sopenharmony_ci default: 659425bb815Sopenharmony_ci { 660425bb815Sopenharmony_ci cli_state.error = "Internal error"; 661425bb815Sopenharmony_ci break; 662425bb815Sopenharmony_ci } 663425bb815Sopenharmony_ci } 664425bb815Sopenharmony_ci } 665425bb815Sopenharmony_ci 666425bb815Sopenharmony_ci if (cli_state.error != NULL) 667425bb815Sopenharmony_ci { 668425bb815Sopenharmony_ci if (cli_state.arg != NULL) 669425bb815Sopenharmony_ci { 670425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state.error, cli_state.arg); 671425bb815Sopenharmony_ci } 672425bb815Sopenharmony_ci else 673425bb815Sopenharmony_ci { 674425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state.error); 675425bb815Sopenharmony_ci } 676425bb815Sopenharmony_ci 677425bb815Sopenharmony_ci return JERRY_STANDALONE_EXIT_CODE_FAIL; 678425bb815Sopenharmony_ci } 679425bb815Sopenharmony_ci 680425bb815Sopenharmony_ci if (files_counter == 0 681425bb815Sopenharmony_ci && exec_snapshots_count == 0) 682425bb815Sopenharmony_ci { 683425bb815Sopenharmony_ci is_repl_mode = true; 684425bb815Sopenharmony_ci } 685425bb815Sopenharmony_ci 686425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) 687425bb815Sopenharmony_ci 688425bb815Sopenharmony_ci jerry_context_t *context_p = jerry_create_context (JERRY_GLOBAL_HEAP_SIZE * 1024, context_alloc, NULL); 689425bb815Sopenharmony_ci jerry_port_default_set_current_context (context_p); 690425bb815Sopenharmony_ci 691425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */ 692425bb815Sopenharmony_ci 693425bb815Sopenharmony_ci if (!start_debug_server) 694425bb815Sopenharmony_ci { 695425bb815Sopenharmony_ci debug_channel = ""; 696425bb815Sopenharmony_ci } 697425bb815Sopenharmony_ci 698425bb815Sopenharmony_ci init_engine (flags, debug_channel, debug_protocol, debug_port, debug_serial_config); 699425bb815Sopenharmony_ci 700425bb815Sopenharmony_ci jerry_value_t ret_value = jerry_create_undefined (); 701425bb815Sopenharmony_ci 702425bb815Sopenharmony_ci if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC)) 703425bb815Sopenharmony_ci { 704425bb815Sopenharmony_ci for (int i = 0; i < exec_snapshots_count; i++) 705425bb815Sopenharmony_ci { 706425bb815Sopenharmony_ci size_t snapshot_size; 707425bb815Sopenharmony_ci const uint32_t *snapshot_p = read_file (exec_snapshot_file_names[i], &snapshot_size); 708425bb815Sopenharmony_ci 709425bb815Sopenharmony_ci if (snapshot_p == NULL) 710425bb815Sopenharmony_ci { 711425bb815Sopenharmony_ci ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Snapshot file load error"); 712425bb815Sopenharmony_ci } 713425bb815Sopenharmony_ci else 714425bb815Sopenharmony_ci { 715425bb815Sopenharmony_ci ret_value = jerry_exec_snapshot (snapshot_p, 716425bb815Sopenharmony_ci snapshot_size, 717425bb815Sopenharmony_ci exec_snapshot_file_indices[i], 718425bb815Sopenharmony_ci JERRY_SNAPSHOT_EXEC_COPY_DATA); 719425bb815Sopenharmony_ci } 720425bb815Sopenharmony_ci 721425bb815Sopenharmony_ci if (jerry_value_is_error (ret_value)) 722425bb815Sopenharmony_ci { 723425bb815Sopenharmony_ci break; 724425bb815Sopenharmony_ci } 725425bb815Sopenharmony_ci } 726425bb815Sopenharmony_ci } 727425bb815Sopenharmony_ci 728425bb815Sopenharmony_ci while (true) 729425bb815Sopenharmony_ci { 730425bb815Sopenharmony_ci 731425bb815Sopenharmony_ci if (!jerry_value_is_error (ret_value)) 732425bb815Sopenharmony_ci { 733425bb815Sopenharmony_ci for (int i = 0; i < files_counter; i++) 734425bb815Sopenharmony_ci { 735425bb815Sopenharmony_ci size_t source_size; 736425bb815Sopenharmony_ci const jerry_char_t *source_p = (jerry_char_t *) read_file (file_names[i], &source_size); 737425bb815Sopenharmony_ci 738425bb815Sopenharmony_ci if (source_p == NULL) 739425bb815Sopenharmony_ci { 740425bb815Sopenharmony_ci ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Source file load error"); 741425bb815Sopenharmony_ci break; 742425bb815Sopenharmony_ci } 743425bb815Sopenharmony_ci 744425bb815Sopenharmony_ci if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_size)) 745425bb815Sopenharmony_ci { 746425bb815Sopenharmony_ci ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) ("Input must be a valid UTF-8 string.")); 747425bb815Sopenharmony_ci break; 748425bb815Sopenharmony_ci } 749425bb815Sopenharmony_ci 750425bb815Sopenharmony_ci ret_value = jerry_parse ((jerry_char_t *) file_names[i], 751425bb815Sopenharmony_ci strlen (file_names[i]), 752425bb815Sopenharmony_ci source_p, 753425bb815Sopenharmony_ci source_size, 754425bb815Sopenharmony_ci JERRY_PARSE_NO_OPTS); 755425bb815Sopenharmony_ci 756425bb815Sopenharmony_ci if (!jerry_value_is_error (ret_value) && !is_parse_only) 757425bb815Sopenharmony_ci { 758425bb815Sopenharmony_ci jerry_value_t func_val = ret_value; 759425bb815Sopenharmony_ci ret_value = jerry_run (func_val); 760425bb815Sopenharmony_ci jerry_release_value (func_val); 761425bb815Sopenharmony_ci } 762425bb815Sopenharmony_ci 763425bb815Sopenharmony_ci if (jerry_value_is_error (ret_value)) 764425bb815Sopenharmony_ci { 765425bb815Sopenharmony_ci break; 766425bb815Sopenharmony_ci } 767425bb815Sopenharmony_ci 768425bb815Sopenharmony_ci jerry_release_value (ret_value); 769425bb815Sopenharmony_ci ret_value = jerry_create_undefined (); 770425bb815Sopenharmony_ci } 771425bb815Sopenharmony_ci } 772425bb815Sopenharmony_ci 773425bb815Sopenharmony_ci if (is_wait_mode) 774425bb815Sopenharmony_ci { 775425bb815Sopenharmony_ci is_repl_mode = false; 776425bb815Sopenharmony_ci 777425bb815Sopenharmony_ci if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER)) 778425bb815Sopenharmony_ci { 779425bb815Sopenharmony_ci while (true) 780425bb815Sopenharmony_ci { 781425bb815Sopenharmony_ci jerry_debugger_wait_for_source_status_t receive_status; 782425bb815Sopenharmony_ci 783425bb815Sopenharmony_ci do 784425bb815Sopenharmony_ci { 785425bb815Sopenharmony_ci jerry_value_t run_result; 786425bb815Sopenharmony_ci 787425bb815Sopenharmony_ci receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback, 788425bb815Sopenharmony_ci NULL, 789425bb815Sopenharmony_ci &run_result); 790425bb815Sopenharmony_ci 791425bb815Sopenharmony_ci if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED) 792425bb815Sopenharmony_ci { 793425bb815Sopenharmony_ci ret_value = jerry_create_error (JERRY_ERROR_COMMON, 794425bb815Sopenharmony_ci (jerry_char_t *) "Connection aborted before source arrived."); 795425bb815Sopenharmony_ci } 796425bb815Sopenharmony_ci 797425bb815Sopenharmony_ci if (receive_status == JERRY_DEBUGGER_SOURCE_END) 798425bb815Sopenharmony_ci { 799425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n"); 800425bb815Sopenharmony_ci } 801425bb815Sopenharmony_ci 802425bb815Sopenharmony_ci if (jerry_value_is_abort (run_result)) 803425bb815Sopenharmony_ci { 804425bb815Sopenharmony_ci ret_value = jerry_acquire_value (run_result); 805425bb815Sopenharmony_ci } 806425bb815Sopenharmony_ci 807425bb815Sopenharmony_ci jerry_release_value (run_result); 808425bb815Sopenharmony_ci } 809425bb815Sopenharmony_ci while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED); 810425bb815Sopenharmony_ci 811425bb815Sopenharmony_ci if (receive_status != JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED) 812425bb815Sopenharmony_ci { 813425bb815Sopenharmony_ci break; 814425bb815Sopenharmony_ci } 815425bb815Sopenharmony_ci 816425bb815Sopenharmony_ci init_engine (flags, debug_channel, debug_protocol, debug_port, debug_serial_config); 817425bb815Sopenharmony_ci 818425bb815Sopenharmony_ci ret_value = jerry_create_undefined (); 819425bb815Sopenharmony_ci } 820425bb815Sopenharmony_ci } 821425bb815Sopenharmony_ci 822425bb815Sopenharmony_ci } 823425bb815Sopenharmony_ci 824425bb815Sopenharmony_ci bool restart = false; 825425bb815Sopenharmony_ci 826425bb815Sopenharmony_ci if (jerry_is_feature_enabled (JERRY_FEATURE_DEBUGGER) && jerry_value_is_abort (ret_value)) 827425bb815Sopenharmony_ci { 828425bb815Sopenharmony_ci jerry_value_t abort_value = jerry_get_value_from_error (ret_value, false); 829425bb815Sopenharmony_ci if (jerry_value_is_string (abort_value)) 830425bb815Sopenharmony_ci { 831425bb815Sopenharmony_ci static const char restart_str[] = "r353t"; 832425bb815Sopenharmony_ci 833425bb815Sopenharmony_ci jerry_value_t str_val = jerry_value_to_string (abort_value); 834425bb815Sopenharmony_ci jerry_size_t str_size = jerry_get_string_size (str_val); 835425bb815Sopenharmony_ci 836425bb815Sopenharmony_ci if (str_size == sizeof (restart_str) - 1) 837425bb815Sopenharmony_ci { 838425bb815Sopenharmony_ci JERRY_VLA (jerry_char_t, str_buf, str_size); 839425bb815Sopenharmony_ci jerry_string_to_char_buffer (str_val, str_buf, str_size); 840425bb815Sopenharmony_ci if (memcmp (restart_str, (char *) (str_buf), str_size) == 0) 841425bb815Sopenharmony_ci { 842425bb815Sopenharmony_ci jerry_release_value (ret_value); 843425bb815Sopenharmony_ci restart = true; 844425bb815Sopenharmony_ci } 845425bb815Sopenharmony_ci } 846425bb815Sopenharmony_ci 847425bb815Sopenharmony_ci jerry_release_value (str_val); 848425bb815Sopenharmony_ci } 849425bb815Sopenharmony_ci 850425bb815Sopenharmony_ci jerry_release_value (abort_value); 851425bb815Sopenharmony_ci } 852425bb815Sopenharmony_ci 853425bb815Sopenharmony_ci if (!restart) 854425bb815Sopenharmony_ci { 855425bb815Sopenharmony_ci break; 856425bb815Sopenharmony_ci } 857425bb815Sopenharmony_ci 858425bb815Sopenharmony_ci jerry_cleanup (); 859425bb815Sopenharmony_ci 860425bb815Sopenharmony_ci init_engine (flags, debug_channel, debug_protocol, debug_port, debug_serial_config); 861425bb815Sopenharmony_ci 862425bb815Sopenharmony_ci ret_value = jerry_create_undefined (); 863425bb815Sopenharmony_ci } 864425bb815Sopenharmony_ci 865425bb815Sopenharmony_ci if (is_repl_mode) 866425bb815Sopenharmony_ci { 867425bb815Sopenharmony_ci const char *prompt = !no_prompt ? "jerry> " : ""; 868425bb815Sopenharmony_ci bool is_done = false; 869425bb815Sopenharmony_ci 870425bb815Sopenharmony_ci while (!is_done) 871425bb815Sopenharmony_ci { 872425bb815Sopenharmony_ci uint8_t *source_buffer_tail = buffer; 873425bb815Sopenharmony_ci size_t len = 0; 874425bb815Sopenharmony_ci 875425bb815Sopenharmony_ci printf ("%s", prompt); 876425bb815Sopenharmony_ci 877425bb815Sopenharmony_ci /* Read a line */ 878425bb815Sopenharmony_ci while (true) 879425bb815Sopenharmony_ci { 880425bb815Sopenharmony_ci if (fread (source_buffer_tail, 1, 1, stdin) != 1) 881425bb815Sopenharmony_ci { 882425bb815Sopenharmony_ci is_done = true; 883425bb815Sopenharmony_ci break; 884425bb815Sopenharmony_ci } 885425bb815Sopenharmony_ci if (*source_buffer_tail == '\n') 886425bb815Sopenharmony_ci { 887425bb815Sopenharmony_ci break; 888425bb815Sopenharmony_ci } 889425bb815Sopenharmony_ci source_buffer_tail ++; 890425bb815Sopenharmony_ci len ++; 891425bb815Sopenharmony_ci } 892425bb815Sopenharmony_ci *source_buffer_tail = 0; 893425bb815Sopenharmony_ci 894425bb815Sopenharmony_ci if (len > 0) 895425bb815Sopenharmony_ci { 896425bb815Sopenharmony_ci if (!jerry_is_valid_utf8_string (buffer, (jerry_size_t) len)) 897425bb815Sopenharmony_ci { 898425bb815Sopenharmony_ci jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n"); 899425bb815Sopenharmony_ci return JERRY_STANDALONE_EXIT_CODE_FAIL; 900425bb815Sopenharmony_ci } 901425bb815Sopenharmony_ci 902425bb815Sopenharmony_ci /* Evaluate the line */ 903425bb815Sopenharmony_ci jerry_value_t ret_val = jerry_parse (NULL, 904425bb815Sopenharmony_ci 0, 905425bb815Sopenharmony_ci buffer, 906425bb815Sopenharmony_ci len, 907425bb815Sopenharmony_ci JERRY_PARSE_NO_OPTS); 908425bb815Sopenharmony_ci 909425bb815Sopenharmony_ci if (!jerry_value_is_error (ret_val)) 910425bb815Sopenharmony_ci { 911425bb815Sopenharmony_ci jerry_value_t func_val = ret_val; 912425bb815Sopenharmony_ci ret_val = jerry_run (func_val); 913425bb815Sopenharmony_ci jerry_release_value (func_val); 914425bb815Sopenharmony_ci } 915425bb815Sopenharmony_ci 916425bb815Sopenharmony_ci if (!jerry_value_is_error (ret_val)) 917425bb815Sopenharmony_ci { 918425bb815Sopenharmony_ci /* Print return value */ 919425bb815Sopenharmony_ci const jerry_value_t args[] = { ret_val }; 920425bb815Sopenharmony_ci jerry_value_t ret_val_print = jerryx_handler_print (jerry_create_undefined (), 921425bb815Sopenharmony_ci jerry_create_undefined (), 922425bb815Sopenharmony_ci args, 923425bb815Sopenharmony_ci 1); 924425bb815Sopenharmony_ci jerry_release_value (ret_val_print); 925425bb815Sopenharmony_ci jerry_release_value (ret_val); 926425bb815Sopenharmony_ci ret_val = jerry_run_all_enqueued_jobs (); 927425bb815Sopenharmony_ci 928425bb815Sopenharmony_ci if (jerry_value_is_error (ret_val)) 929425bb815Sopenharmony_ci { 930425bb815Sopenharmony_ci ret_val = jerry_get_value_from_error (ret_val, true); 931425bb815Sopenharmony_ci print_unhandled_exception (ret_val); 932425bb815Sopenharmony_ci } 933425bb815Sopenharmony_ci } 934425bb815Sopenharmony_ci else 935425bb815Sopenharmony_ci { 936425bb815Sopenharmony_ci ret_val = jerry_get_value_from_error (ret_val, true); 937425bb815Sopenharmony_ci print_unhandled_exception (ret_val); 938425bb815Sopenharmony_ci } 939425bb815Sopenharmony_ci 940425bb815Sopenharmony_ci jerry_release_value (ret_val); 941425bb815Sopenharmony_ci } 942425bb815Sopenharmony_ci } 943425bb815Sopenharmony_ci } 944425bb815Sopenharmony_ci 945425bb815Sopenharmony_ci int ret_code = JERRY_STANDALONE_EXIT_CODE_OK; 946425bb815Sopenharmony_ci 947425bb815Sopenharmony_ci if (jerry_value_is_error (ret_value)) 948425bb815Sopenharmony_ci { 949425bb815Sopenharmony_ci ret_value = jerry_get_value_from_error (ret_value, true); 950425bb815Sopenharmony_ci print_unhandled_exception (ret_value); 951425bb815Sopenharmony_ci 952425bb815Sopenharmony_ci ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; 953425bb815Sopenharmony_ci } 954425bb815Sopenharmony_ci 955425bb815Sopenharmony_ci jerry_release_value (ret_value); 956425bb815Sopenharmony_ci 957425bb815Sopenharmony_ci ret_value = jerry_run_all_enqueued_jobs (); 958425bb815Sopenharmony_ci 959425bb815Sopenharmony_ci if (jerry_value_is_error (ret_value)) 960425bb815Sopenharmony_ci { 961425bb815Sopenharmony_ci ret_value = jerry_get_value_from_error (ret_value, true); 962425bb815Sopenharmony_ci print_unhandled_exception (ret_value); 963425bb815Sopenharmony_ci ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; 964425bb815Sopenharmony_ci } 965425bb815Sopenharmony_ci 966425bb815Sopenharmony_ci jerry_release_value (ret_value); 967425bb815Sopenharmony_ci 968425bb815Sopenharmony_ci if (exit_cb != NULL) 969425bb815Sopenharmony_ci { 970425bb815Sopenharmony_ci jerry_value_t global = jerry_get_global_object (); 971425bb815Sopenharmony_ci jerry_value_t fn_str = jerry_create_string ((jerry_char_t *) exit_cb); 972425bb815Sopenharmony_ci jerry_value_t callback_fn = jerry_get_property (global, fn_str); 973425bb815Sopenharmony_ci 974425bb815Sopenharmony_ci jerry_release_value (global); 975425bb815Sopenharmony_ci jerry_release_value (fn_str); 976425bb815Sopenharmony_ci 977425bb815Sopenharmony_ci if (jerry_value_is_function (callback_fn)) 978425bb815Sopenharmony_ci { 979425bb815Sopenharmony_ci jerry_value_t ret_val = jerry_call_function (callback_fn, jerry_create_undefined (), NULL, 0); 980425bb815Sopenharmony_ci 981425bb815Sopenharmony_ci if (jerry_value_is_error (ret_val)) 982425bb815Sopenharmony_ci { 983425bb815Sopenharmony_ci ret_val = jerry_get_value_from_error (ret_val, true); 984425bb815Sopenharmony_ci print_unhandled_exception (ret_val); 985425bb815Sopenharmony_ci ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL; 986425bb815Sopenharmony_ci } 987425bb815Sopenharmony_ci 988425bb815Sopenharmony_ci jerry_release_value (ret_val); 989425bb815Sopenharmony_ci } 990425bb815Sopenharmony_ci 991425bb815Sopenharmony_ci jerry_release_value (callback_fn); 992425bb815Sopenharmony_ci } 993425bb815Sopenharmony_ci 994425bb815Sopenharmony_ci jerry_cleanup (); 995425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) 996425bb815Sopenharmony_ci free (context_p); 997425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */ 998425bb815Sopenharmony_ci return ret_code; 999425bb815Sopenharmony_ci} /* main */ 1000