xiuos/APP_Framework/lib/JerryScript/jerryscript/jerry-main/main-unix-snapshot.c

860 lines
25 KiB
C

/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "jerryscript.h"
#include "jerryscript-port.h"
#include "jerryscript-port-default.h"
#include "cli.h"
/**
* Maximum size for loaded snapshots
*/
#define JERRY_BUFFER_SIZE (1048576)
/**
* Maximum number of loaded literals
*/
#define JERRY_LITERAL_LENGTH (4096)
/**
* Standalone Jerry exit codes
*/
#define JERRY_STANDALONE_EXIT_CODE_OK (0)
#define JERRY_STANDALONE_EXIT_CODE_FAIL (1)
static uint8_t input_buffer[JERRY_BUFFER_SIZE];
static uint32_t output_buffer[JERRY_BUFFER_SIZE / 4];
static jerry_char_t literal_buffer[JERRY_BUFFER_SIZE];
static const char *output_file_name_p = "js.snapshot";
static jerry_length_t magic_string_lengths[JERRY_LITERAL_LENGTH];
static const jerry_char_t *magic_string_items[JERRY_LITERAL_LENGTH];
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
/**
* The alloc function passed to jerry_create_context
*/
static void *
context_alloc (size_t size,
void *cb_data_p)
{
(void) cb_data_p; /* unused */
return malloc (size);
} /* context_alloc */
/**
* Create and set the default external context.
*/
static void
context_init (void)
{
jerry_context_t *context_p = jerry_create_context (JERRY_GLOBAL_HEAP_SIZE * 1024, context_alloc, NULL);
jerry_port_default_set_current_context (context_p);
} /* context_init */
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
/**
* Check whether JerryScript has a requested feature enabled or not. If not,
* print a warning message.
*
* @return the status of the feature.
*/
static bool
check_feature (jerry_feature_t feature, /**< feature to check */
const char *option) /**< command line option that triggered this check */
{
if (!jerry_is_feature_enabled (feature))
{
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING);
jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option);
return false;
}
return true;
} /* check_feature */
/**
* Utility method to check and print error in the given cli state.
*
* @return true - if any error is detected
* false - if there is no error in the cli state
*/
static bool
check_cli_error (const cli_state_t *const cli_state_p)
{
if (cli_state_p->error != NULL)
{
if (cli_state_p->arg != NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg);
}
else
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error);
}
return true;
}
return false;
} /* check_cli_error */
/**
* Loading a single file into the memory.
*
* @return size of file - if loading is successful
* 0 - otherwise
*/
static size_t
read_file (uint8_t *input_pos_p, /**< next position in the input buffer */
const char *file_name) /**< file name */
{
FILE *file = fopen (file_name, "rb");
if (file == NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name);
return 0;
}
size_t max_size = (size_t) (input_buffer + JERRY_BUFFER_SIZE - input_pos_p);
size_t bytes_read = fread (input_pos_p, 1u, max_size, file);
fclose (file);
if (bytes_read == 0)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name);
return 0;
}
if (bytes_read == max_size)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: file too large: %s\n", file_name);
return 0;
}
printf ("Input file '%s' (%zu bytes) loaded.\n", file_name, bytes_read);
return bytes_read;
} /* read_file */
/**
* Print error value
*/
static void
print_unhandled_exception (jerry_value_t error_value) /**< error value */
{
assert (!jerry_value_is_error (error_value));
jerry_value_t err_str_val = jerry_value_to_string (error_value);
if (jerry_value_is_error (err_str_val))
{
/* Avoid recursive error throws. */
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n");
jerry_release_value (err_str_val);
return;
}
jerry_size_t err_str_size = jerry_get_utf8_string_size (err_str_val);
if (err_str_size >= 256)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n");
jerry_release_value (err_str_val);
return;
}
jerry_char_t err_str_buf[256];
jerry_size_t string_end = jerry_string_to_utf8_char_buffer (err_str_val, err_str_buf, err_str_size);
assert (string_end == err_str_size);
err_str_buf[string_end] = 0;
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: %s\n", (char *) err_str_buf);
jerry_release_value (err_str_val);
} /* print_unhandled_exception */
/**
* Generate command line option IDs
*/
typedef enum
{
OPT_GENERATE_HELP,
OPT_GENERATE_STATIC,
OPT_GENERATE_SHOW_OP,
OPT_GENERATE_FUNCTION,
OPT_GENERATE_OUT,
OPT_IMPORT_LITERAL_LIST
} generate_opt_id_t;
/**
* Generate command line options
*/
static const cli_opt_t generate_opts[] =
{
CLI_OPT_DEF (.id = OPT_GENERATE_HELP, .opt = "h", .longopt = "help",
.help = "print this help and exit"),
CLI_OPT_DEF (.id = OPT_GENERATE_STATIC, .opt = "s", .longopt = "static",
.help = "generate static snapshot"),
CLI_OPT_DEF (.id = OPT_GENERATE_FUNCTION, .opt = "f", .longopt = "generate-function-snapshot",
.meta = "ARGUMENTS",
.help = "generate function snapshot with given arguments"),
CLI_OPT_DEF (.id = OPT_IMPORT_LITERAL_LIST, .longopt = "load-literals-list-format",
.meta = "FILE",
.help = "import literals from list format (for static snapshots)"),
CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes",
.help = "print generated opcodes"),
CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o", .meta="FILE",
.help = "specify output file name (default: js.snapshot)"),
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
.help = "input source file")
};
/**
* Process 'generate' command.
*
* @return error code (0 - no error)
*/
static int
process_generate (cli_state_t *cli_state_p, /**< cli state */
int argc, /**< number of arguments */
char *prog_name_p) /**< program name */
{
(void) argc;
uint32_t snapshot_flags = 0;
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
const char *file_name_p = NULL;
uint8_t *source_p = input_buffer;
size_t source_length = 0;
const char *literals_file_name_p = NULL;
const char *function_args_p = NULL;
cli_change_opts (cli_state_p, generate_opts);
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
{
switch (id)
{
case OPT_GENERATE_HELP:
{
cli_help (prog_name_p, "generate", generate_opts);
return JERRY_STANDALONE_EXIT_CODE_OK;
}
case OPT_GENERATE_STATIC:
{
snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC;
break;
}
case OPT_GENERATE_FUNCTION:
{
function_args_p = cli_consume_string (cli_state_p);
break;
}
case OPT_IMPORT_LITERAL_LIST:
{
literals_file_name_p = cli_consume_string (cli_state_p);
break;
}
case OPT_GENERATE_SHOW_OP:
{
if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg))
{
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG);
flags |= JERRY_INIT_SHOW_OPCODES;
}
break;
}
case OPT_GENERATE_OUT:
{
output_file_name_p = cli_consume_string (cli_state_p);
break;
}
case CLI_OPT_DEFAULT:
{
if (file_name_p != NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
file_name_p = cli_consume_string (cli_state_p);
if (cli_state_p->error == NULL)
{
source_length = read_file (source_p, file_name_p);
if (source_length == 0)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
}
break;
}
default:
{
cli_state_p->error = "Internal error";
break;
}
}
}
if (check_cli_error (cli_state_p))
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (file_name_p == NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
context_init ();
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
jerry_init (flags);
if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length))
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n");
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (literals_file_name_p != NULL)
{
/* Import literal list */
uint8_t *sp_buffer_start_p = source_p + source_length + 1;
size_t sp_buffer_size = read_file (sp_buffer_start_p, literals_file_name_p);
if (sp_buffer_size > 0)
{
const char *sp_buffer_p = (const char *) sp_buffer_start_p;
uint32_t num_of_lit = 0;
do
{
char *sp_buffer_end_p = NULL;
jerry_length_t mstr_size = (jerry_length_t) strtol (sp_buffer_p, &sp_buffer_end_p, 10);
if (mstr_size > 0)
{
magic_string_items[num_of_lit] = (jerry_char_t *) (sp_buffer_end_p + 1);
magic_string_lengths[num_of_lit] = mstr_size;
num_of_lit++;
}
sp_buffer_p = sp_buffer_end_p + mstr_size + 1;
}
while ((size_t) (sp_buffer_p - (char *) sp_buffer_start_p) < sp_buffer_size);
if (num_of_lit > 0)
{
jerry_register_magic_strings (magic_string_items, num_of_lit,
magic_string_lengths);
}
}
}
jerry_value_t snapshot_result;
if (function_args_p != NULL)
{
snapshot_result = jerry_generate_function_snapshot ((jerry_char_t *) file_name_p,
(size_t) strlen (file_name_p),
(jerry_char_t *) source_p,
source_length,
(const jerry_char_t *) function_args_p,
strlen (function_args_p),
snapshot_flags,
output_buffer,
sizeof (output_buffer) / sizeof (uint32_t));
}
else
{
snapshot_result = jerry_generate_snapshot ((jerry_char_t *) file_name_p,
(size_t) strlen (file_name_p),
(jerry_char_t *) source_p,
source_length,
snapshot_flags,
output_buffer,
sizeof (output_buffer) / sizeof (uint32_t));
}
if (jerry_value_is_error (snapshot_result))
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n");
snapshot_result = jerry_get_value_from_error (snapshot_result, true);
print_unhandled_exception (snapshot_result);
jerry_release_value (snapshot_result);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
size_t snapshot_size = (size_t) jerry_get_number_value (snapshot_result);
jerry_release_value (snapshot_result);
FILE *snapshot_file_p = fopen (output_file_name_p, "wb");
if (snapshot_file_p == NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p);
fclose (snapshot_file_p);
printf ("Created snapshot file: '%s' (%zu bytes)\n", output_file_name_p, snapshot_size);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_OK;
} /* process_generate */
/**
* Literal dump command line option IDs
*/
typedef enum
{
OPT_LITERAL_DUMP_HELP,
OPT_LITERAL_DUMP_FORMAT,
OPT_LITERAL_DUMP_OUT,
} literal_dump_opt_id_t;
/**
* Literal dump command line options
*/
static const cli_opt_t literal_dump_opts[] =
{
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_HELP, .opt = "h", .longopt = "help",
.help = "print this help and exit"),
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_FORMAT, .longopt = "format",
.meta = "[c|list]",
.help = "specify output format (default: list)"),
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_OUT, .opt = "o",
.help = "specify output file name (default: literals.[h|list])"),
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE(S)",
.help = "input snapshot files")
};
/**
* Process 'litdump' command.
*
* @return error code (0 - no error)
*/
static int
process_literal_dump (cli_state_t *cli_state_p, /**< cli state */
int argc, /**< number of arguments */
char *prog_name_p) /**< program name */
{
uint8_t *input_pos_p = input_buffer;
cli_change_opts (cli_state_p, literal_dump_opts);
JERRY_VLA (const uint32_t *, snapshot_buffers, argc);
JERRY_VLA (size_t, snapshot_buffer_sizes, argc);
uint32_t number_of_files = 0;
const char *literals_file_name_p = NULL;
bool is_c_format = false;
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
{
switch (id)
{
case OPT_LITERAL_DUMP_HELP:
{
cli_help (prog_name_p, "litdump", literal_dump_opts);
return JERRY_STANDALONE_EXIT_CODE_OK;
}
case OPT_LITERAL_DUMP_FORMAT:
{
const char *fromat_str_p = cli_consume_string (cli_state_p);
if (!strcmp ("c", fromat_str_p))
{
is_c_format = true;
}
else if (!strcmp ("list", fromat_str_p))
{
is_c_format = false;
}
else
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unsupported literal dump format.");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
break;
}
case OPT_LITERAL_DUMP_OUT:
{
literals_file_name_p = cli_consume_string (cli_state_p);
break;
}
case CLI_OPT_DEFAULT:
{
const char *file_name_p = cli_consume_string (cli_state_p);
if (cli_state_p->error == NULL)
{
size_t size = read_file (input_pos_p, file_name_p);
if (size == 0)
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
snapshot_buffers[number_of_files] = (const uint32_t *) input_pos_p;
snapshot_buffer_sizes[number_of_files] = size;
number_of_files++;
const uintptr_t mask = sizeof (uint32_t) - 1;
input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
}
break;
}
default:
{
cli_state_p->error = "Internal error";
break;
}
}
}
if (check_cli_error (cli_state_p))
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (number_of_files < 1)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least one input file must be specified.\n");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
context_init ();
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
jerry_init (JERRY_INIT_EMPTY);
size_t lit_buf_sz = 0;
if (number_of_files == 1)
{
lit_buf_sz = jerry_get_literals_from_snapshot (snapshot_buffers[0],
snapshot_buffer_sizes[0],
literal_buffer,
JERRY_BUFFER_SIZE,
is_c_format);
}
else
{
/* The input contains more than one input snapshot file, so we must merge them first. */
const char *error_p = NULL;
size_t merged_snapshot_size = jerry_merge_snapshots (snapshot_buffers,
snapshot_buffer_sizes,
number_of_files,
output_buffer,
JERRY_BUFFER_SIZE,
&error_p);
if (merged_snapshot_size == 0)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
printf ("Successfully merged the input snapshots (%zu bytes).\n", merged_snapshot_size);
lit_buf_sz = jerry_get_literals_from_snapshot (output_buffer,
merged_snapshot_size,
literal_buffer,
JERRY_BUFFER_SIZE,
is_c_format);
}
if (lit_buf_sz == 0)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR,
"Error: Literal saving failed! No literals were found in the input snapshot(s).\n");
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (literals_file_name_p == NULL)
{
literals_file_name_p = is_c_format ? "literals.h" : "literals.list";
}
FILE *file_p = fopen (literals_file_name_p, "wb");
if (file_p == NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", literals_file_name_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
fwrite (literal_buffer, sizeof (uint8_t), lit_buf_sz, file_p);
fclose (file_p);
printf ("Literals are saved into '%s' (%zu bytes).\n", literals_file_name_p, lit_buf_sz);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_OK;
} /* process_literal_dump */
/**
* Merge command line option IDs
*/
typedef enum
{
OPT_MERGE_HELP,
OPT_MERGE_OUT,
} merge_opt_id_t;
/**
* Merge command line options
*/
static const cli_opt_t merge_opts[] =
{
CLI_OPT_DEF (.id = OPT_MERGE_HELP, .opt = "h", .longopt = "help",
.help = "print this help and exit"),
CLI_OPT_DEF (.id = OPT_MERGE_OUT, .opt = "o",
.help = "specify output file name (default: js.snapshot)"),
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
.help = "input snapshot files, minimum two")
};
/**
* Process 'merge' command.
*
* @return error code (0 - no error)
*/
static int
process_merge (cli_state_t *cli_state_p, /**< cli state */
int argc, /**< number of arguments */
char *prog_name_p) /**< program name */
{
uint8_t *input_pos_p = input_buffer;
cli_change_opts (cli_state_p, merge_opts);
JERRY_VLA (const uint32_t *, merge_buffers, argc);
JERRY_VLA (size_t, merge_buffer_sizes, argc);
uint32_t number_of_files = 0;
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
{
switch (id)
{
case OPT_MERGE_HELP:
{
cli_help (prog_name_p, "merge", merge_opts);
return JERRY_STANDALONE_EXIT_CODE_OK;
}
case OPT_MERGE_OUT:
{
output_file_name_p = cli_consume_string (cli_state_p);
break;
}
case CLI_OPT_DEFAULT:
{
const char *file_name_p = cli_consume_string (cli_state_p);
if (cli_state_p->error == NULL)
{
size_t size = read_file (input_pos_p, file_name_p);
if (size == 0)
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
merge_buffers[number_of_files] = (const uint32_t *) input_pos_p;
merge_buffer_sizes[number_of_files] = size;
number_of_files++;
const uintptr_t mask = sizeof (uint32_t) - 1;
input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
}
break;
}
default:
{
cli_state_p->error = "Internal error";
break;
}
}
}
if (check_cli_error (cli_state_p))
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (number_of_files < 2)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n");
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
context_init ();
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
jerry_init (JERRY_INIT_EMPTY);
const char *error_p = NULL;
size_t merged_snapshot_size = jerry_merge_snapshots (merge_buffers,
merge_buffer_sizes,
number_of_files,
output_buffer,
JERRY_BUFFER_SIZE,
&error_p);
if (merged_snapshot_size == 0)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
FILE *file_p = fopen (output_file_name_p, "wb");
if (file_p == NULL)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
fwrite (output_buffer, 1u, merged_snapshot_size, file_p);
fclose (file_p);
printf ("Merge is completed. Merged snapshot is saved into '%s' (%zu bytes).\n",
output_file_name_p,
merged_snapshot_size);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_OK;
} /* process_merge */
/**
* Command line option IDs
*/
typedef enum
{
OPT_HELP,
} main_opt_id_t;
/**
* Command line options
*/
static const cli_opt_t main_opts[] =
{
CLI_OPT_DEF (.id = OPT_HELP, .opt = "h", .longopt = "help",
.help = "print this help and exit"),
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "COMMAND",
.help = "specify the command")
};
/**
* Print available commands.
*/
static void
print_commands (char *prog_name_p) /**< program name */
{
cli_help (prog_name_p, NULL, main_opts);
printf ("\nAvailable commands:\n"
" generate\n"
" litdump\n"
" merge\n"
"\nPassing -h or --help after a command displays its help.\n");
} /* print_commands */
/**
* Main function.
*
* @return error code (0 - no error)
*/
int
main (int argc, /**< number of arguments */
char **argv) /**< argument list */
{
cli_state_t cli_state = cli_init (main_opts, argc, argv);
for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state))
{
switch (id)
{
case OPT_MERGE_HELP:
{
/* Help is always printed if no command is provided. */
break;
}
case CLI_OPT_DEFAULT:
{
const char *command_p = cli_consume_string (&cli_state);
if (cli_state.error != NULL)
{
break;
}
if (!strcmp ("merge", command_p))
{
return process_merge (&cli_state, argc, argv[0]);
}
else if (!strcmp ("litdump", command_p))
{
return process_literal_dump (&cli_state, argc, argv[0]);
}
else if (!strcmp ("generate", command_p))
{
return process_generate (&cli_state, argc, argv[0]);
}
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unknown command: %s\n\n", command_p);
print_commands (argv[0]);
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
default:
{
cli_state.error = "Internal error";
break;
}
}
}
if (check_cli_error (&cli_state))
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
print_commands (argv[0]);
return JERRY_STANDALONE_EXIT_CODE_OK;
} /* main */