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 <stdlib.h>
18425bb815Sopenharmony_ci#include <string.h>
19425bb815Sopenharmony_ci
20425bb815Sopenharmony_ci#include "jerryscript.h"
21425bb815Sopenharmony_ci#include "jerryscript-port.h"
22425bb815Sopenharmony_ci#include "jerryscript-port-default.h"
23425bb815Sopenharmony_ci
24425bb815Sopenharmony_ci#include "cli.h"
25425bb815Sopenharmony_ci
26425bb815Sopenharmony_ci/**
27425bb815Sopenharmony_ci * Maximum size for loaded snapshots
28425bb815Sopenharmony_ci */
29425bb815Sopenharmony_ci#define JERRY_BUFFER_SIZE (1048576)
30425bb815Sopenharmony_ci
31425bb815Sopenharmony_ci/**
32425bb815Sopenharmony_ci * Maximum number of loaded literals
33425bb815Sopenharmony_ci */
34425bb815Sopenharmony_ci#define JERRY_LITERAL_LENGTH (4096)
35425bb815Sopenharmony_ci
36425bb815Sopenharmony_ci/**
37425bb815Sopenharmony_ci * Standalone Jerry exit codes
38425bb815Sopenharmony_ci */
39425bb815Sopenharmony_ci#define JERRY_STANDALONE_EXIT_CODE_OK   (0)
40425bb815Sopenharmony_ci#define JERRY_STANDALONE_EXIT_CODE_FAIL (1)
41425bb815Sopenharmony_ci
42425bb815Sopenharmony_ci#ifdef _WIN32
43425bb815Sopenharmony_ci#  ifdef _WIN64
44425bb815Sopenharmony_ci#    define PRI_SIZET "lu"
45425bb815Sopenharmony_ci#    define SIZE_T_TYPE unsigned long
46425bb815Sopenharmony_ci#  else
47425bb815Sopenharmony_ci#    define PRI_SIZET "zu"
48425bb815Sopenharmony_ci#    define SIZE_T_TYPE size_t
49425bb815Sopenharmony_ci#  endif
50425bb815Sopenharmony_ci#else
51425bb815Sopenharmony_ci#  define PRI_SIZET "zu"
52425bb815Sopenharmony_ci#  define SIZE_T_TYPE size_t
53425bb815Sopenharmony_ci#endif
54425bb815Sopenharmony_ci
55425bb815Sopenharmony_cistatic uint8_t input_buffer[JERRY_BUFFER_SIZE];
56425bb815Sopenharmony_cistatic uint32_t output_buffer[JERRY_BUFFER_SIZE / 4];
57425bb815Sopenharmony_cistatic jerry_char_t literal_buffer[JERRY_BUFFER_SIZE];
58425bb815Sopenharmony_cistatic const char *output_file_name_p = "js.snapshot";
59425bb815Sopenharmony_cistatic jerry_length_t magic_string_lengths[JERRY_LITERAL_LENGTH];
60425bb815Sopenharmony_cistatic const jerry_char_t *magic_string_items[JERRY_LITERAL_LENGTH];
61425bb815Sopenharmony_ci
62425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
63425bb815Sopenharmony_ci/**
64425bb815Sopenharmony_ci * The alloc function passed to jerry_create_context
65425bb815Sopenharmony_ci */
66425bb815Sopenharmony_cistatic void *
67425bb815Sopenharmony_cicontext_alloc (size_t size,
68425bb815Sopenharmony_ci               void *cb_data_p)
69425bb815Sopenharmony_ci{
70425bb815Sopenharmony_ci  (void) cb_data_p; /* unused */
71425bb815Sopenharmony_ci  return malloc (size);
72425bb815Sopenharmony_ci} /* context_alloc */
73425bb815Sopenharmony_ci
74425bb815Sopenharmony_ci/**
75425bb815Sopenharmony_ci * Create and set the default external context.
76425bb815Sopenharmony_ci */
77425bb815Sopenharmony_cistatic void
78425bb815Sopenharmony_cicontext_init (void)
79425bb815Sopenharmony_ci{
80425bb815Sopenharmony_ci  jerry_context_t *context_p = jerry_create_context (JERRY_GLOBAL_HEAP_SIZE * 1024, context_alloc, NULL);
81425bb815Sopenharmony_ci  jerry_port_default_set_current_context (context_p);
82425bb815Sopenharmony_ci} /* context_init */
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
85425bb815Sopenharmony_ci
86425bb815Sopenharmony_ci/**
87425bb815Sopenharmony_ci * Check whether JerryScript has a requested feature enabled or not. If not,
88425bb815Sopenharmony_ci * print a warning message.
89425bb815Sopenharmony_ci *
90425bb815Sopenharmony_ci * @return the status of the feature.
91425bb815Sopenharmony_ci */
92425bb815Sopenharmony_cistatic bool
93425bb815Sopenharmony_cicheck_feature (jerry_feature_t feature, /**< feature to check */
94425bb815Sopenharmony_ci               const char *option) /**< command line option that triggered this check */
95425bb815Sopenharmony_ci{
96425bb815Sopenharmony_ci  if (!jerry_is_feature_enabled (feature))
97425bb815Sopenharmony_ci  {
98425bb815Sopenharmony_ci    jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING);
99425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option);
100425bb815Sopenharmony_ci    return false;
101425bb815Sopenharmony_ci  }
102425bb815Sopenharmony_ci  return true;
103425bb815Sopenharmony_ci} /* check_feature */
104425bb815Sopenharmony_ci
105425bb815Sopenharmony_ci/**
106425bb815Sopenharmony_ci * Utility method to check and print error in the given cli state.
107425bb815Sopenharmony_ci *
108425bb815Sopenharmony_ci * @return true - if any error is detected
109425bb815Sopenharmony_ci *         false - if there is no error in the cli state
110425bb815Sopenharmony_ci */
111425bb815Sopenharmony_cistatic bool
112425bb815Sopenharmony_cicheck_cli_error (const cli_state_t *const cli_state_p)
113425bb815Sopenharmony_ci{
114425bb815Sopenharmony_ci  if (cli_state_p->error != NULL)
115425bb815Sopenharmony_ci  {
116425bb815Sopenharmony_ci    if (cli_state_p->arg != NULL)
117425bb815Sopenharmony_ci    {
118425bb815Sopenharmony_ci      jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg);
119425bb815Sopenharmony_ci    }
120425bb815Sopenharmony_ci    else
121425bb815Sopenharmony_ci    {
122425bb815Sopenharmony_ci      jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error);
123425bb815Sopenharmony_ci    }
124425bb815Sopenharmony_ci
125425bb815Sopenharmony_ci    return true;
126425bb815Sopenharmony_ci  }
127425bb815Sopenharmony_ci
128425bb815Sopenharmony_ci  return false;
129425bb815Sopenharmony_ci} /* check_cli_error */
130425bb815Sopenharmony_ci
131425bb815Sopenharmony_ci/**
132425bb815Sopenharmony_ci * Loading a single file into the memory.
133425bb815Sopenharmony_ci *
134425bb815Sopenharmony_ci * @return size of file - if loading is successful
135425bb815Sopenharmony_ci *         0 - otherwise
136425bb815Sopenharmony_ci */
137425bb815Sopenharmony_cistatic size_t
138425bb815Sopenharmony_ciread_file (uint8_t *input_pos_p, /**< next position in the input buffer */
139425bb815Sopenharmony_ci           const char *file_name) /**< file name */
140425bb815Sopenharmony_ci{
141425bb815Sopenharmony_ci  FILE *file = fopen (file_name, "rb");
142425bb815Sopenharmony_ci
143425bb815Sopenharmony_ci  if (file == NULL)
144425bb815Sopenharmony_ci  {
145425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name);
146425bb815Sopenharmony_ci    return 0;
147425bb815Sopenharmony_ci  }
148425bb815Sopenharmony_ci
149425bb815Sopenharmony_ci  size_t max_size = (size_t) (input_buffer + JERRY_BUFFER_SIZE - input_pos_p);
150425bb815Sopenharmony_ci
151425bb815Sopenharmony_ci  size_t bytes_read = fread (input_pos_p, 1u, max_size, file);
152425bb815Sopenharmony_ci  fclose (file);
153425bb815Sopenharmony_ci
154425bb815Sopenharmony_ci  if (bytes_read == 0)
155425bb815Sopenharmony_ci  {
156425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name);
157425bb815Sopenharmony_ci    return 0;
158425bb815Sopenharmony_ci  }
159425bb815Sopenharmony_ci
160425bb815Sopenharmony_ci  if (bytes_read == max_size)
161425bb815Sopenharmony_ci  {
162425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: file too large: %s\n", file_name);
163425bb815Sopenharmony_ci    return 0;
164425bb815Sopenharmony_ci  }
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci  printf ("Input file '%s' (%"PRI_SIZET" bytes) loaded.\n", file_name, (SIZE_T_TYPE)bytes_read);
167425bb815Sopenharmony_ci  return bytes_read;
168425bb815Sopenharmony_ci} /* read_file */
169425bb815Sopenharmony_ci
170425bb815Sopenharmony_ci/**
171425bb815Sopenharmony_ci * Print error value
172425bb815Sopenharmony_ci */
173425bb815Sopenharmony_cistatic void
174425bb815Sopenharmony_ciprint_unhandled_exception (jerry_value_t error_value) /**< error value */
175425bb815Sopenharmony_ci{
176425bb815Sopenharmony_ci  assert (!jerry_value_is_error (error_value));
177425bb815Sopenharmony_ci
178425bb815Sopenharmony_ci  jerry_value_t err_str_val = jerry_value_to_string (error_value);
179425bb815Sopenharmony_ci
180425bb815Sopenharmony_ci  if (jerry_value_is_error (err_str_val))
181425bb815Sopenharmony_ci  {
182425bb815Sopenharmony_ci    /* Avoid recursive error throws. */
183425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n");
184425bb815Sopenharmony_ci    jerry_release_value (err_str_val);
185425bb815Sopenharmony_ci    return;
186425bb815Sopenharmony_ci  }
187425bb815Sopenharmony_ci
188425bb815Sopenharmony_ci  jerry_size_t err_str_size = jerry_get_utf8_string_size (err_str_val);
189425bb815Sopenharmony_ci
190425bb815Sopenharmony_ci  if (err_str_size >= 256)
191425bb815Sopenharmony_ci  {
192425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n");
193425bb815Sopenharmony_ci    jerry_release_value (err_str_val);
194425bb815Sopenharmony_ci    return;
195425bb815Sopenharmony_ci  }
196425bb815Sopenharmony_ci
197425bb815Sopenharmony_ci  jerry_char_t err_str_buf[256];
198425bb815Sopenharmony_ci  jerry_size_t string_end = jerry_string_to_utf8_char_buffer (err_str_val, err_str_buf, err_str_size);
199425bb815Sopenharmony_ci  assert (string_end == err_str_size);
200425bb815Sopenharmony_ci  err_str_buf[string_end] = 0;
201425bb815Sopenharmony_ci
202425bb815Sopenharmony_ci  jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: %s\n", (char *) err_str_buf);
203425bb815Sopenharmony_ci  jerry_release_value (err_str_val);
204425bb815Sopenharmony_ci} /* print_unhandled_exception */
205425bb815Sopenharmony_ci
206425bb815Sopenharmony_ci/**
207425bb815Sopenharmony_ci * Generate command line option IDs
208425bb815Sopenharmony_ci */
209425bb815Sopenharmony_citypedef enum
210425bb815Sopenharmony_ci{
211425bb815Sopenharmony_ci  OPT_GENERATE_HELP,
212425bb815Sopenharmony_ci  OPT_GENERATE_STATIC,
213425bb815Sopenharmony_ci  OPT_GENERATE_SHOW_OP,
214425bb815Sopenharmony_ci  OPT_GENERATE_FUNCTION,
215425bb815Sopenharmony_ci  OPT_GENERATE_OUT,
216425bb815Sopenharmony_ci  OPT_IMPORT_LITERAL_LIST
217425bb815Sopenharmony_ci} generate_opt_id_t;
218425bb815Sopenharmony_ci
219425bb815Sopenharmony_ci/**
220425bb815Sopenharmony_ci * Generate command line options
221425bb815Sopenharmony_ci */
222425bb815Sopenharmony_cistatic const cli_opt_t generate_opts[] =
223425bb815Sopenharmony_ci{
224425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_GENERATE_HELP, .opt = "h", .longopt = "help",
225425bb815Sopenharmony_ci               .help = "print this help and exit"),
226425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_GENERATE_STATIC, .opt = "s", .longopt = "static",
227425bb815Sopenharmony_ci               .help = "generate static snapshot"),
228425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_GENERATE_FUNCTION, .opt = "f", .longopt = "generate-function-snapshot",
229425bb815Sopenharmony_ci               .meta = "ARGUMENTS",
230425bb815Sopenharmony_ci               .help = "generate function snapshot with given arguments"),
231425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_IMPORT_LITERAL_LIST, .longopt = "load-literals-list-format",
232425bb815Sopenharmony_ci               .meta = "FILE",
233425bb815Sopenharmony_ci               .help = "import literals from list format (for static snapshots)"),
234425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes",
235425bb815Sopenharmony_ci               .help = "print generated opcodes"),
236425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o",  .meta="FILE",
237425bb815Sopenharmony_ci               .help = "specify output file name (default: js.snapshot)"),
238425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
239425bb815Sopenharmony_ci               .help = "input source file")
240425bb815Sopenharmony_ci};
241425bb815Sopenharmony_ci
242425bb815Sopenharmony_ci/**
243425bb815Sopenharmony_ci * Process 'generate' command.
244425bb815Sopenharmony_ci *
245425bb815Sopenharmony_ci * @return error code (0 - no error)
246425bb815Sopenharmony_ci */
247425bb815Sopenharmony_cistatic int
248425bb815Sopenharmony_ciprocess_generate (cli_state_t *cli_state_p, /**< cli state */
249425bb815Sopenharmony_ci                  int argc, /**< number of arguments */
250425bb815Sopenharmony_ci                  char *prog_name_p) /**< program name */
251425bb815Sopenharmony_ci{
252425bb815Sopenharmony_ci  (void) argc;
253425bb815Sopenharmony_ci
254425bb815Sopenharmony_ci  uint32_t snapshot_flags = 0;
255425bb815Sopenharmony_ci  jerry_init_flag_t flags = JERRY_INIT_EMPTY;
256425bb815Sopenharmony_ci
257425bb815Sopenharmony_ci  const char *file_name_p = NULL;
258425bb815Sopenharmony_ci  uint8_t *source_p = input_buffer;
259425bb815Sopenharmony_ci  size_t source_length = 0;
260425bb815Sopenharmony_ci  const char *literals_file_name_p = NULL;
261425bb815Sopenharmony_ci  const char *function_args_p = NULL;
262425bb815Sopenharmony_ci
263425bb815Sopenharmony_ci  cli_change_opts (cli_state_p, generate_opts);
264425bb815Sopenharmony_ci
265425bb815Sopenharmony_ci  for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
266425bb815Sopenharmony_ci  {
267425bb815Sopenharmony_ci    switch (id)
268425bb815Sopenharmony_ci    {
269425bb815Sopenharmony_ci      case OPT_GENERATE_HELP:
270425bb815Sopenharmony_ci      {
271425bb815Sopenharmony_ci        cli_help (prog_name_p, "generate", generate_opts);
272425bb815Sopenharmony_ci        return JERRY_STANDALONE_EXIT_CODE_OK;
273425bb815Sopenharmony_ci      }
274425bb815Sopenharmony_ci      case OPT_GENERATE_STATIC:
275425bb815Sopenharmony_ci      {
276425bb815Sopenharmony_ci        snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC;
277425bb815Sopenharmony_ci        break;
278425bb815Sopenharmony_ci      }
279425bb815Sopenharmony_ci      case OPT_GENERATE_FUNCTION:
280425bb815Sopenharmony_ci      {
281425bb815Sopenharmony_ci        function_args_p = cli_consume_string (cli_state_p);
282425bb815Sopenharmony_ci        break;
283425bb815Sopenharmony_ci      }
284425bb815Sopenharmony_ci      case OPT_IMPORT_LITERAL_LIST:
285425bb815Sopenharmony_ci      {
286425bb815Sopenharmony_ci        literals_file_name_p = cli_consume_string (cli_state_p);
287425bb815Sopenharmony_ci        break;
288425bb815Sopenharmony_ci      }
289425bb815Sopenharmony_ci      case OPT_GENERATE_SHOW_OP:
290425bb815Sopenharmony_ci      {
291425bb815Sopenharmony_ci        if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg))
292425bb815Sopenharmony_ci        {
293425bb815Sopenharmony_ci          jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG);
294425bb815Sopenharmony_ci          flags |= JERRY_INIT_SHOW_OPCODES;
295425bb815Sopenharmony_ci        }
296425bb815Sopenharmony_ci        break;
297425bb815Sopenharmony_ci      }
298425bb815Sopenharmony_ci      case OPT_GENERATE_OUT:
299425bb815Sopenharmony_ci      {
300425bb815Sopenharmony_ci        output_file_name_p = cli_consume_string (cli_state_p);
301425bb815Sopenharmony_ci        break;
302425bb815Sopenharmony_ci      }
303425bb815Sopenharmony_ci      case CLI_OPT_DEFAULT:
304425bb815Sopenharmony_ci      {
305425bb815Sopenharmony_ci        if (file_name_p != NULL)
306425bb815Sopenharmony_ci        {
307425bb815Sopenharmony_ci          jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n");
308425bb815Sopenharmony_ci          return JERRY_STANDALONE_EXIT_CODE_FAIL;
309425bb815Sopenharmony_ci        }
310425bb815Sopenharmony_ci
311425bb815Sopenharmony_ci        file_name_p = cli_consume_string (cli_state_p);
312425bb815Sopenharmony_ci
313425bb815Sopenharmony_ci        if (cli_state_p->error == NULL)
314425bb815Sopenharmony_ci        {
315425bb815Sopenharmony_ci          source_length = read_file (source_p, file_name_p);
316425bb815Sopenharmony_ci
317425bb815Sopenharmony_ci          if (source_length == 0)
318425bb815Sopenharmony_ci          {
319425bb815Sopenharmony_ci            jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n");
320425bb815Sopenharmony_ci            return JERRY_STANDALONE_EXIT_CODE_FAIL;
321425bb815Sopenharmony_ci          }
322425bb815Sopenharmony_ci        }
323425bb815Sopenharmony_ci        break;
324425bb815Sopenharmony_ci      }
325425bb815Sopenharmony_ci      default:
326425bb815Sopenharmony_ci      {
327425bb815Sopenharmony_ci        cli_state_p->error = "Internal error";
328425bb815Sopenharmony_ci        break;
329425bb815Sopenharmony_ci      }
330425bb815Sopenharmony_ci    }
331425bb815Sopenharmony_ci  }
332425bb815Sopenharmony_ci
333425bb815Sopenharmony_ci  if (check_cli_error (cli_state_p))
334425bb815Sopenharmony_ci  {
335425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
336425bb815Sopenharmony_ci  }
337425bb815Sopenharmony_ci
338425bb815Sopenharmony_ci  if (file_name_p == NULL)
339425bb815Sopenharmony_ci  {
340425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n");
341425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
342425bb815Sopenharmony_ci  }
343425bb815Sopenharmony_ci
344425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
345425bb815Sopenharmony_ci  context_init ();
346425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
347425bb815Sopenharmony_ci
348425bb815Sopenharmony_ci  jerry_init (flags);
349425bb815Sopenharmony_ci
350425bb815Sopenharmony_ci  if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length))
351425bb815Sopenharmony_ci  {
352425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n");
353425bb815Sopenharmony_ci    jerry_cleanup ();
354425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
355425bb815Sopenharmony_ci  }
356425bb815Sopenharmony_ci
357425bb815Sopenharmony_ci  if (literals_file_name_p != NULL)
358425bb815Sopenharmony_ci  {
359425bb815Sopenharmony_ci    /* Import literal list */
360425bb815Sopenharmony_ci    uint8_t *sp_buffer_start_p = source_p + source_length + 1;
361425bb815Sopenharmony_ci    size_t sp_buffer_size = read_file (sp_buffer_start_p, literals_file_name_p);
362425bb815Sopenharmony_ci
363425bb815Sopenharmony_ci    if (sp_buffer_size > 0)
364425bb815Sopenharmony_ci    {
365425bb815Sopenharmony_ci      const char *sp_buffer_p = (const char *) sp_buffer_start_p;
366425bb815Sopenharmony_ci      uint32_t num_of_lit = 0;
367425bb815Sopenharmony_ci
368425bb815Sopenharmony_ci      do
369425bb815Sopenharmony_ci      {
370425bb815Sopenharmony_ci        char *sp_buffer_end_p = NULL;
371425bb815Sopenharmony_ci        jerry_length_t mstr_size = (jerry_length_t) strtol (sp_buffer_p, &sp_buffer_end_p, 10);
372425bb815Sopenharmony_ci        if (mstr_size > 0)
373425bb815Sopenharmony_ci        {
374425bb815Sopenharmony_ci          magic_string_items[num_of_lit] = (jerry_char_t *) (sp_buffer_end_p + 1);
375425bb815Sopenharmony_ci          magic_string_lengths[num_of_lit] = mstr_size;
376425bb815Sopenharmony_ci          num_of_lit++;
377425bb815Sopenharmony_ci        }
378425bb815Sopenharmony_ci        sp_buffer_p = sp_buffer_end_p + mstr_size + 1;
379425bb815Sopenharmony_ci      }
380425bb815Sopenharmony_ci      while ((size_t) (sp_buffer_p - (char *) sp_buffer_start_p) < sp_buffer_size);
381425bb815Sopenharmony_ci
382425bb815Sopenharmony_ci      if (num_of_lit > 0)
383425bb815Sopenharmony_ci      {
384425bb815Sopenharmony_ci        jerry_register_magic_strings (magic_string_items, num_of_lit,
385425bb815Sopenharmony_ci                                      magic_string_lengths);
386425bb815Sopenharmony_ci      }
387425bb815Sopenharmony_ci    }
388425bb815Sopenharmony_ci  }
389425bb815Sopenharmony_ci
390425bb815Sopenharmony_ci  jerry_value_t snapshot_result;
391425bb815Sopenharmony_ci
392425bb815Sopenharmony_ci  if (function_args_p != NULL)
393425bb815Sopenharmony_ci  {
394425bb815Sopenharmony_ci    snapshot_result = jerry_generate_function_snapshot ((jerry_char_t *) file_name_p,
395425bb815Sopenharmony_ci                                                        (size_t) strlen (file_name_p),
396425bb815Sopenharmony_ci                                                        (jerry_char_t *) source_p,
397425bb815Sopenharmony_ci                                                        source_length,
398425bb815Sopenharmony_ci                                                        (const jerry_char_t *) function_args_p,
399425bb815Sopenharmony_ci                                                        strlen (function_args_p),
400425bb815Sopenharmony_ci                                                        snapshot_flags,
401425bb815Sopenharmony_ci                                                        output_buffer,
402425bb815Sopenharmony_ci                                                        sizeof (output_buffer) / sizeof (uint32_t));
403425bb815Sopenharmony_ci  }
404425bb815Sopenharmony_ci  else
405425bb815Sopenharmony_ci  {
406425bb815Sopenharmony_ci    snapshot_result = jerry_generate_snapshot ((jerry_char_t *) file_name_p,
407425bb815Sopenharmony_ci                                               (size_t) strlen (file_name_p),
408425bb815Sopenharmony_ci                                               (jerry_char_t *) source_p,
409425bb815Sopenharmony_ci                                               source_length,
410425bb815Sopenharmony_ci                                               snapshot_flags,
411425bb815Sopenharmony_ci                                               output_buffer,
412425bb815Sopenharmony_ci                                               sizeof (output_buffer) / sizeof (uint32_t));
413425bb815Sopenharmony_ci  }
414425bb815Sopenharmony_ci
415425bb815Sopenharmony_ci  if (jerry_value_is_error (snapshot_result))
416425bb815Sopenharmony_ci  {
417425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n");
418425bb815Sopenharmony_ci
419425bb815Sopenharmony_ci    snapshot_result = jerry_get_value_from_error (snapshot_result, true);
420425bb815Sopenharmony_ci
421425bb815Sopenharmony_ci    print_unhandled_exception (snapshot_result);
422425bb815Sopenharmony_ci
423425bb815Sopenharmony_ci    jerry_release_value (snapshot_result);
424425bb815Sopenharmony_ci    jerry_cleanup ();
425425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
426425bb815Sopenharmony_ci  }
427425bb815Sopenharmony_ci
428425bb815Sopenharmony_ci  size_t snapshot_size = (size_t) jerry_get_number_value (snapshot_result);
429425bb815Sopenharmony_ci  jerry_release_value (snapshot_result);
430425bb815Sopenharmony_ci
431425bb815Sopenharmony_ci  FILE *snapshot_file_p = fopen (output_file_name_p, "wb");
432425bb815Sopenharmony_ci  if (snapshot_file_p == NULL)
433425bb815Sopenharmony_ci  {
434425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p);
435425bb815Sopenharmony_ci    jerry_cleanup ();
436425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
437425bb815Sopenharmony_ci  }
438425bb815Sopenharmony_ci
439425bb815Sopenharmony_ci  fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p);
440425bb815Sopenharmony_ci  fclose (snapshot_file_p);
441425bb815Sopenharmony_ci
442425bb815Sopenharmony_ci  printf ("Created snapshot file: '%s' (%zu bytes)\n", output_file_name_p, snapshot_size);
443425bb815Sopenharmony_ci
444425bb815Sopenharmony_ci  jerry_cleanup ();
445425bb815Sopenharmony_ci  return JERRY_STANDALONE_EXIT_CODE_OK;
446425bb815Sopenharmony_ci} /* process_generate */
447425bb815Sopenharmony_ci
448425bb815Sopenharmony_ci/**
449425bb815Sopenharmony_ci * Literal dump command line option IDs
450425bb815Sopenharmony_ci */
451425bb815Sopenharmony_citypedef enum
452425bb815Sopenharmony_ci{
453425bb815Sopenharmony_ci  OPT_LITERAL_DUMP_HELP,
454425bb815Sopenharmony_ci  OPT_LITERAL_DUMP_FORMAT,
455425bb815Sopenharmony_ci  OPT_LITERAL_DUMP_OUT,
456425bb815Sopenharmony_ci} literal_dump_opt_id_t;
457425bb815Sopenharmony_ci
458425bb815Sopenharmony_ci/**
459425bb815Sopenharmony_ci * Literal dump command line options
460425bb815Sopenharmony_ci */
461425bb815Sopenharmony_cistatic const cli_opt_t literal_dump_opts[] =
462425bb815Sopenharmony_ci{
463425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_HELP, .opt = "h", .longopt = "help",
464425bb815Sopenharmony_ci               .help = "print this help and exit"),
465425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_FORMAT, .longopt = "format",
466425bb815Sopenharmony_ci               .meta = "[c|list]",
467425bb815Sopenharmony_ci               .help = "specify output format (default: list)"),
468425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_OUT, .opt = "o",
469425bb815Sopenharmony_ci               .help = "specify output file name (default: literals.[h|list])"),
470425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE(S)",
471425bb815Sopenharmony_ci               .help = "input snapshot files")
472425bb815Sopenharmony_ci};
473425bb815Sopenharmony_ci
474425bb815Sopenharmony_ci/**
475425bb815Sopenharmony_ci * Process 'litdump' command.
476425bb815Sopenharmony_ci *
477425bb815Sopenharmony_ci * @return error code (0 - no error)
478425bb815Sopenharmony_ci */
479425bb815Sopenharmony_cistatic int
480425bb815Sopenharmony_ciprocess_literal_dump (cli_state_t *cli_state_p, /**< cli state */
481425bb815Sopenharmony_ci                      int argc, /**< number of arguments */
482425bb815Sopenharmony_ci                      char *prog_name_p) /**< program name */
483425bb815Sopenharmony_ci{
484425bb815Sopenharmony_ci  uint8_t *input_pos_p = input_buffer;
485425bb815Sopenharmony_ci
486425bb815Sopenharmony_ci  cli_change_opts (cli_state_p, literal_dump_opts);
487425bb815Sopenharmony_ci
488425bb815Sopenharmony_ci  JERRY_VLA (const uint32_t *, snapshot_buffers, argc);
489425bb815Sopenharmony_ci  JERRY_VLA (size_t, snapshot_buffer_sizes, argc);
490425bb815Sopenharmony_ci  uint32_t number_of_files = 0;
491425bb815Sopenharmony_ci  const char *literals_file_name_p = NULL;
492425bb815Sopenharmony_ci  bool is_c_format = false;
493425bb815Sopenharmony_ci
494425bb815Sopenharmony_ci  for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
495425bb815Sopenharmony_ci  {
496425bb815Sopenharmony_ci    switch (id)
497425bb815Sopenharmony_ci    {
498425bb815Sopenharmony_ci      case OPT_LITERAL_DUMP_HELP:
499425bb815Sopenharmony_ci      {
500425bb815Sopenharmony_ci        cli_help (prog_name_p, "litdump", literal_dump_opts);
501425bb815Sopenharmony_ci        return JERRY_STANDALONE_EXIT_CODE_OK;
502425bb815Sopenharmony_ci      }
503425bb815Sopenharmony_ci      case OPT_LITERAL_DUMP_FORMAT:
504425bb815Sopenharmony_ci      {
505425bb815Sopenharmony_ci        const char *fromat_str_p = cli_consume_string (cli_state_p);
506425bb815Sopenharmony_ci        if (!strcmp ("c", fromat_str_p))
507425bb815Sopenharmony_ci        {
508425bb815Sopenharmony_ci          is_c_format = true;
509425bb815Sopenharmony_ci        }
510425bb815Sopenharmony_ci        else if (!strcmp ("list", fromat_str_p))
511425bb815Sopenharmony_ci        {
512425bb815Sopenharmony_ci          is_c_format = false;
513425bb815Sopenharmony_ci        }
514425bb815Sopenharmony_ci        else
515425bb815Sopenharmony_ci        {
516425bb815Sopenharmony_ci          jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unsupported literal dump format.");
517425bb815Sopenharmony_ci          return JERRY_STANDALONE_EXIT_CODE_FAIL;
518425bb815Sopenharmony_ci        }
519425bb815Sopenharmony_ci        break;
520425bb815Sopenharmony_ci      }
521425bb815Sopenharmony_ci      case OPT_LITERAL_DUMP_OUT:
522425bb815Sopenharmony_ci      {
523425bb815Sopenharmony_ci        literals_file_name_p = cli_consume_string (cli_state_p);
524425bb815Sopenharmony_ci        break;
525425bb815Sopenharmony_ci      }
526425bb815Sopenharmony_ci      case CLI_OPT_DEFAULT:
527425bb815Sopenharmony_ci      {
528425bb815Sopenharmony_ci        const char *file_name_p = cli_consume_string (cli_state_p);
529425bb815Sopenharmony_ci
530425bb815Sopenharmony_ci        if (cli_state_p->error == NULL)
531425bb815Sopenharmony_ci        {
532425bb815Sopenharmony_ci          size_t size = read_file (input_pos_p, file_name_p);
533425bb815Sopenharmony_ci
534425bb815Sopenharmony_ci          if (size == 0)
535425bb815Sopenharmony_ci          {
536425bb815Sopenharmony_ci            return JERRY_STANDALONE_EXIT_CODE_FAIL;
537425bb815Sopenharmony_ci          }
538425bb815Sopenharmony_ci
539425bb815Sopenharmony_ci          snapshot_buffers[number_of_files] = (const uint32_t *) input_pos_p;
540425bb815Sopenharmony_ci          snapshot_buffer_sizes[number_of_files] = size;
541425bb815Sopenharmony_ci
542425bb815Sopenharmony_ci          number_of_files++;
543425bb815Sopenharmony_ci          const uintptr_t mask = sizeof (uint32_t) - 1;
544425bb815Sopenharmony_ci          input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
545425bb815Sopenharmony_ci        }
546425bb815Sopenharmony_ci        break;
547425bb815Sopenharmony_ci      }
548425bb815Sopenharmony_ci      default:
549425bb815Sopenharmony_ci      {
550425bb815Sopenharmony_ci        cli_state_p->error = "Internal error";
551425bb815Sopenharmony_ci        break;
552425bb815Sopenharmony_ci      }
553425bb815Sopenharmony_ci    }
554425bb815Sopenharmony_ci  }
555425bb815Sopenharmony_ci
556425bb815Sopenharmony_ci  if (check_cli_error (cli_state_p))
557425bb815Sopenharmony_ci  {
558425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
559425bb815Sopenharmony_ci  }
560425bb815Sopenharmony_ci
561425bb815Sopenharmony_ci  if (number_of_files < 1)
562425bb815Sopenharmony_ci  {
563425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least one input file must be specified.\n");
564425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
565425bb815Sopenharmony_ci  }
566425bb815Sopenharmony_ci
567425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
568425bb815Sopenharmony_ci  context_init ();
569425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
570425bb815Sopenharmony_ci
571425bb815Sopenharmony_ci  jerry_init (JERRY_INIT_EMPTY);
572425bb815Sopenharmony_ci
573425bb815Sopenharmony_ci  size_t lit_buf_sz = 0;
574425bb815Sopenharmony_ci  if (number_of_files == 1)
575425bb815Sopenharmony_ci  {
576425bb815Sopenharmony_ci    lit_buf_sz = jerry_get_literals_from_snapshot (snapshot_buffers[0],
577425bb815Sopenharmony_ci                                                   snapshot_buffer_sizes[0],
578425bb815Sopenharmony_ci                                                   literal_buffer,
579425bb815Sopenharmony_ci                                                   JERRY_BUFFER_SIZE,
580425bb815Sopenharmony_ci                                                   is_c_format);
581425bb815Sopenharmony_ci  }
582425bb815Sopenharmony_ci  else
583425bb815Sopenharmony_ci  {
584425bb815Sopenharmony_ci    /* The input contains more than one input snapshot file, so we must merge them first. */
585425bb815Sopenharmony_ci    const char *error_p = NULL;
586425bb815Sopenharmony_ci    size_t merged_snapshot_size = jerry_merge_snapshots (snapshot_buffers,
587425bb815Sopenharmony_ci                                                         snapshot_buffer_sizes,
588425bb815Sopenharmony_ci                                                         number_of_files,
589425bb815Sopenharmony_ci                                                         output_buffer,
590425bb815Sopenharmony_ci                                                         JERRY_BUFFER_SIZE,
591425bb815Sopenharmony_ci                                                         &error_p);
592425bb815Sopenharmony_ci
593425bb815Sopenharmony_ci    if (merged_snapshot_size == 0)
594425bb815Sopenharmony_ci    {
595425bb815Sopenharmony_ci      jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
596425bb815Sopenharmony_ci      jerry_cleanup ();
597425bb815Sopenharmony_ci      return JERRY_STANDALONE_EXIT_CODE_FAIL;
598425bb815Sopenharmony_ci    }
599425bb815Sopenharmony_ci
600425bb815Sopenharmony_ci    printf ("Successfully merged the input snapshots (%"PRI_SIZET" bytes).\n", (SIZE_T_TYPE)merged_snapshot_size);
601425bb815Sopenharmony_ci
602425bb815Sopenharmony_ci    lit_buf_sz = jerry_get_literals_from_snapshot (output_buffer,
603425bb815Sopenharmony_ci                                                   merged_snapshot_size,
604425bb815Sopenharmony_ci                                                   literal_buffer,
605425bb815Sopenharmony_ci                                                   JERRY_BUFFER_SIZE,
606425bb815Sopenharmony_ci                                                   is_c_format);
607425bb815Sopenharmony_ci  }
608425bb815Sopenharmony_ci
609425bb815Sopenharmony_ci  if (lit_buf_sz == 0)
610425bb815Sopenharmony_ci  {
611425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR,
612425bb815Sopenharmony_ci                    "Error: Literal saving failed! No literals were found in the input snapshot(s).\n");
613425bb815Sopenharmony_ci    jerry_cleanup ();
614425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
615425bb815Sopenharmony_ci  }
616425bb815Sopenharmony_ci
617425bb815Sopenharmony_ci  if (literals_file_name_p == NULL)
618425bb815Sopenharmony_ci  {
619425bb815Sopenharmony_ci    literals_file_name_p = is_c_format ? "literals.h" : "literals.list";
620425bb815Sopenharmony_ci  }
621425bb815Sopenharmony_ci
622425bb815Sopenharmony_ci  FILE *file_p = fopen (literals_file_name_p, "wb");
623425bb815Sopenharmony_ci
624425bb815Sopenharmony_ci  if (file_p == NULL)
625425bb815Sopenharmony_ci  {
626425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", literals_file_name_p);
627425bb815Sopenharmony_ci    jerry_cleanup ();
628425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
629425bb815Sopenharmony_ci  }
630425bb815Sopenharmony_ci
631425bb815Sopenharmony_ci  fwrite (literal_buffer, sizeof (uint8_t), lit_buf_sz, file_p);
632425bb815Sopenharmony_ci  fclose (file_p);
633425bb815Sopenharmony_ci
634425bb815Sopenharmony_ci  printf ("Literals are saved into '%s' (%"PRI_SIZET" bytes).\n", literals_file_name_p, (SIZE_T_TYPE)lit_buf_sz);
635425bb815Sopenharmony_ci
636425bb815Sopenharmony_ci  jerry_cleanup ();
637425bb815Sopenharmony_ci  return JERRY_STANDALONE_EXIT_CODE_OK;
638425bb815Sopenharmony_ci} /* process_literal_dump */
639425bb815Sopenharmony_ci
640425bb815Sopenharmony_ci/**
641425bb815Sopenharmony_ci * Merge command line option IDs
642425bb815Sopenharmony_ci */
643425bb815Sopenharmony_citypedef enum
644425bb815Sopenharmony_ci{
645425bb815Sopenharmony_ci  OPT_MERGE_HELP,
646425bb815Sopenharmony_ci  OPT_MERGE_OUT,
647425bb815Sopenharmony_ci} merge_opt_id_t;
648425bb815Sopenharmony_ci
649425bb815Sopenharmony_ci/**
650425bb815Sopenharmony_ci * Merge command line options
651425bb815Sopenharmony_ci */
652425bb815Sopenharmony_cistatic const cli_opt_t merge_opts[] =
653425bb815Sopenharmony_ci{
654425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_MERGE_HELP, .opt = "h", .longopt = "help",
655425bb815Sopenharmony_ci               .help = "print this help and exit"),
656425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_MERGE_OUT, .opt = "o",
657425bb815Sopenharmony_ci               .help = "specify output file name (default: js.snapshot)"),
658425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
659425bb815Sopenharmony_ci               .help = "input snapshot files, minimum two")
660425bb815Sopenharmony_ci};
661425bb815Sopenharmony_ci
662425bb815Sopenharmony_ci/**
663425bb815Sopenharmony_ci * Process 'merge' command.
664425bb815Sopenharmony_ci *
665425bb815Sopenharmony_ci * @return error code (0 - no error)
666425bb815Sopenharmony_ci */
667425bb815Sopenharmony_cistatic int
668425bb815Sopenharmony_ciprocess_merge (cli_state_t *cli_state_p, /**< cli state */
669425bb815Sopenharmony_ci               int argc, /**< number of arguments */
670425bb815Sopenharmony_ci               char *prog_name_p) /**< program name */
671425bb815Sopenharmony_ci{
672425bb815Sopenharmony_ci  uint8_t *input_pos_p = input_buffer;
673425bb815Sopenharmony_ci
674425bb815Sopenharmony_ci  cli_change_opts (cli_state_p, merge_opts);
675425bb815Sopenharmony_ci
676425bb815Sopenharmony_ci  JERRY_VLA (const uint32_t *, merge_buffers, argc);
677425bb815Sopenharmony_ci  JERRY_VLA (size_t, merge_buffer_sizes, argc);
678425bb815Sopenharmony_ci  uint32_t number_of_files = 0;
679425bb815Sopenharmony_ci
680425bb815Sopenharmony_ci  for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
681425bb815Sopenharmony_ci  {
682425bb815Sopenharmony_ci    switch (id)
683425bb815Sopenharmony_ci    {
684425bb815Sopenharmony_ci      case OPT_MERGE_HELP:
685425bb815Sopenharmony_ci      {
686425bb815Sopenharmony_ci        cli_help (prog_name_p, "merge", merge_opts);
687425bb815Sopenharmony_ci        return JERRY_STANDALONE_EXIT_CODE_OK;
688425bb815Sopenharmony_ci      }
689425bb815Sopenharmony_ci      case OPT_MERGE_OUT:
690425bb815Sopenharmony_ci      {
691425bb815Sopenharmony_ci        output_file_name_p = cli_consume_string (cli_state_p);
692425bb815Sopenharmony_ci        break;
693425bb815Sopenharmony_ci      }
694425bb815Sopenharmony_ci      case CLI_OPT_DEFAULT:
695425bb815Sopenharmony_ci      {
696425bb815Sopenharmony_ci        const char *file_name_p = cli_consume_string (cli_state_p);
697425bb815Sopenharmony_ci
698425bb815Sopenharmony_ci        if (cli_state_p->error == NULL)
699425bb815Sopenharmony_ci        {
700425bb815Sopenharmony_ci          size_t size = read_file (input_pos_p, file_name_p);
701425bb815Sopenharmony_ci
702425bb815Sopenharmony_ci          if (size == 0)
703425bb815Sopenharmony_ci          {
704425bb815Sopenharmony_ci            return JERRY_STANDALONE_EXIT_CODE_FAIL;
705425bb815Sopenharmony_ci          }
706425bb815Sopenharmony_ci
707425bb815Sopenharmony_ci          merge_buffers[number_of_files] = (const uint32_t *) input_pos_p;
708425bb815Sopenharmony_ci          merge_buffer_sizes[number_of_files] = size;
709425bb815Sopenharmony_ci
710425bb815Sopenharmony_ci          number_of_files++;
711425bb815Sopenharmony_ci          const uintptr_t mask = sizeof (uint32_t) - 1;
712425bb815Sopenharmony_ci          input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
713425bb815Sopenharmony_ci        }
714425bb815Sopenharmony_ci        break;
715425bb815Sopenharmony_ci      }
716425bb815Sopenharmony_ci      default:
717425bb815Sopenharmony_ci      {
718425bb815Sopenharmony_ci        cli_state_p->error = "Internal error";
719425bb815Sopenharmony_ci        break;
720425bb815Sopenharmony_ci      }
721425bb815Sopenharmony_ci    }
722425bb815Sopenharmony_ci  }
723425bb815Sopenharmony_ci
724425bb815Sopenharmony_ci  if (check_cli_error (cli_state_p))
725425bb815Sopenharmony_ci  {
726425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
727425bb815Sopenharmony_ci  }
728425bb815Sopenharmony_ci
729425bb815Sopenharmony_ci  if (number_of_files < 2)
730425bb815Sopenharmony_ci  {
731425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n");
732425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
733425bb815Sopenharmony_ci  }
734425bb815Sopenharmony_ci
735425bb815Sopenharmony_ci#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
736425bb815Sopenharmony_ci  context_init ();
737425bb815Sopenharmony_ci#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
738425bb815Sopenharmony_ci
739425bb815Sopenharmony_ci  jerry_init (JERRY_INIT_EMPTY);
740425bb815Sopenharmony_ci
741425bb815Sopenharmony_ci  const char *error_p = NULL;
742425bb815Sopenharmony_ci  size_t merged_snapshot_size = jerry_merge_snapshots (merge_buffers,
743425bb815Sopenharmony_ci                                                       merge_buffer_sizes,
744425bb815Sopenharmony_ci                                                       number_of_files,
745425bb815Sopenharmony_ci                                                       output_buffer,
746425bb815Sopenharmony_ci                                                       JERRY_BUFFER_SIZE,
747425bb815Sopenharmony_ci                                                       &error_p);
748425bb815Sopenharmony_ci
749425bb815Sopenharmony_ci  if (merged_snapshot_size == 0)
750425bb815Sopenharmony_ci  {
751425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
752425bb815Sopenharmony_ci    jerry_cleanup ();
753425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
754425bb815Sopenharmony_ci  }
755425bb815Sopenharmony_ci
756425bb815Sopenharmony_ci  FILE *file_p = fopen (output_file_name_p, "wb");
757425bb815Sopenharmony_ci
758425bb815Sopenharmony_ci  if (file_p == NULL)
759425bb815Sopenharmony_ci  {
760425bb815Sopenharmony_ci    jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p);
761425bb815Sopenharmony_ci    jerry_cleanup ();
762425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
763425bb815Sopenharmony_ci  }
764425bb815Sopenharmony_ci
765425bb815Sopenharmony_ci  fwrite (output_buffer, 1u, merged_snapshot_size, file_p);
766425bb815Sopenharmony_ci  fclose (file_p);
767425bb815Sopenharmony_ci
768425bb815Sopenharmony_ci  printf ("Merge is completed. Merged snapshot is saved into '%s' (%"PRI_SIZET" bytes).\n",
769425bb815Sopenharmony_ci          output_file_name_p,
770425bb815Sopenharmony_ci          (SIZE_T_TYPE)merged_snapshot_size);
771425bb815Sopenharmony_ci
772425bb815Sopenharmony_ci  jerry_cleanup ();
773425bb815Sopenharmony_ci  return JERRY_STANDALONE_EXIT_CODE_OK;
774425bb815Sopenharmony_ci} /* process_merge */
775425bb815Sopenharmony_ci
776425bb815Sopenharmony_ci/**
777425bb815Sopenharmony_ci * Command line option IDs
778425bb815Sopenharmony_ci */
779425bb815Sopenharmony_citypedef enum
780425bb815Sopenharmony_ci{
781425bb815Sopenharmony_ci  OPT_HELP,
782425bb815Sopenharmony_ci} main_opt_id_t;
783425bb815Sopenharmony_ci
784425bb815Sopenharmony_ci/**
785425bb815Sopenharmony_ci * Command line options
786425bb815Sopenharmony_ci */
787425bb815Sopenharmony_cistatic const cli_opt_t main_opts[] =
788425bb815Sopenharmony_ci{
789425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = OPT_HELP, .opt = "h", .longopt = "help",
790425bb815Sopenharmony_ci               .help = "print this help and exit"),
791425bb815Sopenharmony_ci  CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "COMMAND",
792425bb815Sopenharmony_ci               .help = "specify the command")
793425bb815Sopenharmony_ci};
794425bb815Sopenharmony_ci
795425bb815Sopenharmony_ci/**
796425bb815Sopenharmony_ci * Print available commands.
797425bb815Sopenharmony_ci */
798425bb815Sopenharmony_cistatic void
799425bb815Sopenharmony_ciprint_commands (char *prog_name_p) /**< program name */
800425bb815Sopenharmony_ci{
801425bb815Sopenharmony_ci  cli_help (prog_name_p, NULL, main_opts);
802425bb815Sopenharmony_ci
803425bb815Sopenharmony_ci  printf ("\nAvailable commands:\n"
804425bb815Sopenharmony_ci          "  generate\n"
805425bb815Sopenharmony_ci          "  litdump\n"
806425bb815Sopenharmony_ci          "  merge\n"
807425bb815Sopenharmony_ci          "\nPassing -h or --help after a command displays its help.\n");
808425bb815Sopenharmony_ci} /* print_commands */
809425bb815Sopenharmony_ci
810425bb815Sopenharmony_ci/**
811425bb815Sopenharmony_ci * Main function.
812425bb815Sopenharmony_ci *
813425bb815Sopenharmony_ci * @return error code (0 - no error)
814425bb815Sopenharmony_ci */
815425bb815Sopenharmony_ciint
816425bb815Sopenharmony_cimain (int argc, /**< number of arguments */
817425bb815Sopenharmony_ci      char **argv) /**< argument list */
818425bb815Sopenharmony_ci{
819425bb815Sopenharmony_ci  cli_state_t cli_state = cli_init (main_opts, argc - 1, argv + 1);
820425bb815Sopenharmony_ci
821425bb815Sopenharmony_ci  for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state))
822425bb815Sopenharmony_ci  {
823425bb815Sopenharmony_ci    switch (id)
824425bb815Sopenharmony_ci    {
825425bb815Sopenharmony_ci      case OPT_MERGE_HELP:
826425bb815Sopenharmony_ci      {
827425bb815Sopenharmony_ci        /* Help is always printed if no command is provided. */
828425bb815Sopenharmony_ci        break;
829425bb815Sopenharmony_ci      }
830425bb815Sopenharmony_ci      case CLI_OPT_DEFAULT:
831425bb815Sopenharmony_ci      {
832425bb815Sopenharmony_ci        const char *command_p = cli_consume_string (&cli_state);
833425bb815Sopenharmony_ci
834425bb815Sopenharmony_ci        if (cli_state.error != NULL)
835425bb815Sopenharmony_ci        {
836425bb815Sopenharmony_ci          break;
837425bb815Sopenharmony_ci        }
838425bb815Sopenharmony_ci
839425bb815Sopenharmony_ci        if (!strcmp ("merge", command_p))
840425bb815Sopenharmony_ci        {
841425bb815Sopenharmony_ci          return process_merge (&cli_state, argc, argv[0]);
842425bb815Sopenharmony_ci        }
843425bb815Sopenharmony_ci        else if (!strcmp ("litdump", command_p))
844425bb815Sopenharmony_ci        {
845425bb815Sopenharmony_ci          return process_literal_dump (&cli_state, argc, argv[0]);
846425bb815Sopenharmony_ci        }
847425bb815Sopenharmony_ci        else if (!strcmp ("generate", command_p))
848425bb815Sopenharmony_ci        {
849425bb815Sopenharmony_ci          return process_generate (&cli_state, argc, argv[0]);
850425bb815Sopenharmony_ci        }
851425bb815Sopenharmony_ci
852425bb815Sopenharmony_ci        jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unknown command: %s\n\n", command_p);
853425bb815Sopenharmony_ci        print_commands (argv[0]);
854425bb815Sopenharmony_ci
855425bb815Sopenharmony_ci        return JERRY_STANDALONE_EXIT_CODE_FAIL;
856425bb815Sopenharmony_ci      }
857425bb815Sopenharmony_ci      default:
858425bb815Sopenharmony_ci      {
859425bb815Sopenharmony_ci        cli_state.error = "Internal error";
860425bb815Sopenharmony_ci        break;
861425bb815Sopenharmony_ci      }
862425bb815Sopenharmony_ci    }
863425bb815Sopenharmony_ci  }
864425bb815Sopenharmony_ci
865425bb815Sopenharmony_ci  if (check_cli_error (&cli_state))
866425bb815Sopenharmony_ci  {
867425bb815Sopenharmony_ci    return JERRY_STANDALONE_EXIT_CODE_FAIL;
868425bb815Sopenharmony_ci  }
869425bb815Sopenharmony_ci
870425bb815Sopenharmony_ci  print_commands (argv[0]);
871425bb815Sopenharmony_ci  return JERRY_STANDALONE_EXIT_CODE_OK;
872425bb815Sopenharmony_ci} /* main */
873