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 **) &current_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