Support multiple primary functions in a single snapshot. (#1797)
This patch adds an extension to snapshots which allows storing multiple position independent primary functions in a single snapshot data. A new application called jerry-snapshot is added to the project to manage snapshots. Currently the only option is merging snapshots. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -68,3 +68,8 @@ if(JERRY_CMDLINE_MINIMAL)
|
||||
jerry_create_executable("jerry-minimal" "main-unix-minimal.c")
|
||||
target_link_libraries("jerry-minimal" jerry-port-default-minimal)
|
||||
endif()
|
||||
|
||||
if(JERRY_CMDLINE_SNAPSHOT)
|
||||
jerry_create_executable("jerry-snapshot" "main-unix-snapshot.c" "cli.c")
|
||||
target_link_libraries("jerry-snapshot" jerry-port-default)
|
||||
endif()
|
||||
|
||||
+107
-81
@@ -62,7 +62,7 @@
|
||||
* @return the state that should be passed to other cli_ functions.
|
||||
*/
|
||||
cli_state_t
|
||||
cli_init (const cli_opt_t *options, /**< array of option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
cli_init (const cli_opt_t *options_p, /**< array of option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
int argc, /**< number of command line arguments */
|
||||
char **argv) /**< array of command line arguments */
|
||||
{
|
||||
@@ -72,35 +72,45 @@ cli_init (const cli_opt_t *options, /**< array of option definitions, terminated
|
||||
.arg = NULL,
|
||||
.argc = argc,
|
||||
.argv = argv,
|
||||
.opts = options
|
||||
.opts = options_p
|
||||
};
|
||||
} /* cli_init */
|
||||
|
||||
/**
|
||||
* Use another option list.
|
||||
*/
|
||||
void
|
||||
cli_change_opts (cli_state_t *state_p, /**< state of the command line option processor */
|
||||
const cli_opt_t *options_p) /**< array of option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
{
|
||||
state_p->opts = options_p;
|
||||
} /* cli_change_opts */
|
||||
|
||||
/**
|
||||
* Checks whether the current argument is an option.
|
||||
*
|
||||
* Note:
|
||||
* The state->error is not NULL on error and it contains the error message.
|
||||
* The state_p->error is not NULL on error and it contains the error message.
|
||||
*
|
||||
* @return the ID of the option that was found or a CLI_OPT_ constant otherwise.
|
||||
*/
|
||||
int
|
||||
cli_consume_option (cli_state_t *state) /**< state of the command line option processor */
|
||||
cli_consume_option (cli_state_t *state_p) /**< state of the command line option processor */
|
||||
{
|
||||
if (state->error != NULL)
|
||||
if (state_p->error != NULL)
|
||||
{
|
||||
return CLI_OPT_END;
|
||||
}
|
||||
|
||||
if (state->argc <= 0)
|
||||
if (state_p->argc <= 0)
|
||||
{
|
||||
state->arg = NULL;
|
||||
state_p->arg = NULL;
|
||||
return CLI_OPT_END;
|
||||
}
|
||||
|
||||
const char *arg = state->argv[0];
|
||||
const char *arg = state_p->argv[0];
|
||||
|
||||
state->arg = arg;
|
||||
state_p->arg = arg;
|
||||
|
||||
if (arg[0] != '-')
|
||||
{
|
||||
@@ -111,33 +121,33 @@ cli_consume_option (cli_state_t *state) /**< state of the command line option pr
|
||||
{
|
||||
arg += 2;
|
||||
|
||||
for (const cli_opt_t *opt = state->opts; opt->id != CLI_OPT_DEFAULT; opt++)
|
||||
for (const cli_opt_t *opt = state_p->opts; opt->id != CLI_OPT_DEFAULT; opt++)
|
||||
{
|
||||
if (opt->longopt != NULL && strcmp (arg, opt->longopt) == 0)
|
||||
{
|
||||
state->argc--;
|
||||
state->argv++;
|
||||
state_p->argc--;
|
||||
state_p->argv++;
|
||||
return opt->id;
|
||||
}
|
||||
}
|
||||
|
||||
state->error = "Unknown long option";
|
||||
state_p->error = "Unknown long option";
|
||||
return CLI_OPT_END;
|
||||
}
|
||||
|
||||
arg++;
|
||||
|
||||
for (const cli_opt_t *opt = state->opts; opt->id != CLI_OPT_DEFAULT; opt++)
|
||||
for (const cli_opt_t *opt = state_p->opts; opt->id != CLI_OPT_DEFAULT; opt++)
|
||||
{
|
||||
if (opt->opt != NULL && strcmp (arg, opt->opt) == 0)
|
||||
{
|
||||
state->argc--;
|
||||
state->argv++;
|
||||
state_p->argc--;
|
||||
state_p->argv++;
|
||||
return opt->id;
|
||||
}
|
||||
}
|
||||
|
||||
state->error = "Unknown option";
|
||||
state_p->error = "Unknown option";
|
||||
return CLI_OPT_END;
|
||||
} /* cli_consume_option */
|
||||
|
||||
@@ -145,69 +155,69 @@ cli_consume_option (cli_state_t *state) /**< state of the command line option pr
|
||||
* Returns the next argument as string.
|
||||
*
|
||||
* Note:
|
||||
* The state->error is not NULL on error and it contains the error message.
|
||||
* The state_p->error is not NULL on error and it contains the error message.
|
||||
*
|
||||
* @return argument string
|
||||
*/
|
||||
const char *
|
||||
cli_consume_string (cli_state_t *state) /**< state of the command line option processor */
|
||||
cli_consume_string (cli_state_t *state_p) /**< state of the command line option processor */
|
||||
{
|
||||
if (state->error != NULL)
|
||||
if (state_p->error != NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (state->argc <= 0)
|
||||
if (state_p->argc <= 0)
|
||||
{
|
||||
state->error = "Expected string argument";
|
||||
state->arg = NULL;
|
||||
state_p->error = "Expected string argument";
|
||||
state_p->arg = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->arg = state->argv[0];
|
||||
state_p->arg = state_p->argv[0];
|
||||
|
||||
state->argc--;
|
||||
state->argv++;
|
||||
return state->arg;
|
||||
state_p->argc--;
|
||||
state_p->argv++;
|
||||
return state_p->arg;
|
||||
} /* cli_consume_string */
|
||||
|
||||
/**
|
||||
* Returns the next argument as integer.
|
||||
*
|
||||
* Note:
|
||||
* The state->error is not NULL on error and it contains the error message.
|
||||
* The state_p->error is not NULL on error and it contains the error message.
|
||||
*
|
||||
* @return argument integer
|
||||
*/
|
||||
int
|
||||
cli_consume_int (cli_state_t *state) /**< state of the command line option processor */
|
||||
cli_consume_int (cli_state_t *state_p) /**< state of the command line option processor */
|
||||
{
|
||||
if (state->error != NULL)
|
||||
if (state_p->error != NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->error = "Expected integer argument";
|
||||
state_p->error = "Expected integer argument";
|
||||
|
||||
if (state->argc <= 0)
|
||||
if (state_p->argc <= 0)
|
||||
{
|
||||
state->arg = NULL;
|
||||
state_p->arg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->arg = state->argv[0];
|
||||
state_p->arg = state_p->argv[0];
|
||||
|
||||
char *endptr;
|
||||
long int value = strtol (state->arg, &endptr, 10);
|
||||
long int value = strtol (state_p->arg, &endptr, 10);
|
||||
|
||||
if (*endptr != '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->error = NULL;
|
||||
state->argc--;
|
||||
state->argv++;
|
||||
state_p->error = NULL;
|
||||
state_p->argc--;
|
||||
state_p->argv++;
|
||||
return (int) value;
|
||||
} /* cli_consume_int */
|
||||
|
||||
@@ -244,26 +254,41 @@ cli_print_prefix (const char *str, /**< string to print */
|
||||
* Print usage summary of options.
|
||||
*/
|
||||
static void
|
||||
cli_opt_usage (const char *progname, /**< program name, typically argv[0] */
|
||||
const cli_opt_t *opts) /**< array of command line option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
cli_opt_usage (const char *prog_name_p, /**< program name, typically argv[0] */
|
||||
const char *command_name_p, /**< command name if available */
|
||||
const cli_opt_t *opts_p) /**< array of command line option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
{
|
||||
int length = (int) strlen (progname);
|
||||
const cli_opt_t *o = opts;
|
||||
int length = (int) strlen (prog_name_p);
|
||||
const cli_opt_t *current_opt_p = opts_p;
|
||||
|
||||
printf ("%s", progname);
|
||||
printf ("%s", prog_name_p);
|
||||
|
||||
while (o->id != CLI_OPT_DEFAULT)
|
||||
if (command_name_p != NULL)
|
||||
{
|
||||
const char *opt = o->opt;
|
||||
int command_length = (int) strlen (command_name_p);
|
||||
|
||||
if (length + 1 + command_length > CLI_LINE_LENGTH)
|
||||
{
|
||||
length = CLI_LINE_INDENT - 1;
|
||||
printf ("\n");
|
||||
cli_print_pad (length);
|
||||
}
|
||||
|
||||
printf (" %s", command_name_p);
|
||||
}
|
||||
|
||||
while (current_opt_p->id != CLI_OPT_DEFAULT)
|
||||
{
|
||||
const char *opt_p = current_opt_p->opt;
|
||||
int opt_length = 2 + 1;
|
||||
|
||||
if (opt == NULL)
|
||||
if (opt_p == NULL)
|
||||
{
|
||||
opt = o->longopt;
|
||||
opt_p = current_opt_p->longopt;
|
||||
opt_length++;
|
||||
}
|
||||
|
||||
opt_length += (int) strlen (opt);
|
||||
opt_length += (int) strlen (opt_p);
|
||||
|
||||
if (length + 1 + opt_length >= CLI_LINE_LENGTH)
|
||||
{
|
||||
@@ -275,29 +300,29 @@ cli_opt_usage (const char *progname, /**< program name, typically argv[0] */
|
||||
|
||||
printf (" [");
|
||||
|
||||
if (o->opt != NULL)
|
||||
if (current_opt_p->opt != NULL)
|
||||
{
|
||||
printf ("-%s", opt);
|
||||
printf ("-%s", opt_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("--%s", opt);
|
||||
printf ("--%s", opt_p);
|
||||
}
|
||||
|
||||
if (o->meta != NULL)
|
||||
if (current_opt_p->meta != NULL)
|
||||
{
|
||||
printf (" %s", o->meta);
|
||||
printf (" %s", current_opt_p->meta);
|
||||
}
|
||||
|
||||
printf ("]");
|
||||
|
||||
o++;
|
||||
current_opt_p++;
|
||||
}
|
||||
|
||||
if (o->meta != NULL)
|
||||
if (current_opt_p->meta != NULL)
|
||||
{
|
||||
const char *opt = o->meta;
|
||||
int opt_length = (int) (2 + strlen (opt));
|
||||
const char *opt_p = current_opt_p->meta;
|
||||
int opt_length = (int) (2 + strlen (opt_p));
|
||||
|
||||
if (length + 1 + opt_length >= CLI_LINE_LENGTH)
|
||||
{
|
||||
@@ -306,7 +331,7 @@ cli_opt_usage (const char *progname, /**< program name, typically argv[0] */
|
||||
cli_print_pad (length);
|
||||
}
|
||||
|
||||
printf (" [%s]", opt);
|
||||
printf (" [%s]", opt_p);
|
||||
}
|
||||
|
||||
printf ("\n\n");
|
||||
@@ -354,43 +379,44 @@ cli_print_help (const char *help) /**< the help message to print */
|
||||
* Print detailed help for options.
|
||||
*/
|
||||
void
|
||||
cli_help (const char *progname, /**< program name, typically argv[0] */
|
||||
const cli_opt_t *options) /**< array of command line option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
cli_help (const char *prog_name_p, /**< program name, typically argv[0] */
|
||||
const char *command_name_p, /**< command name if available */
|
||||
const cli_opt_t *options_p) /**< array of command line option definitions, terminated by CLI_OPT_DEFAULT */
|
||||
{
|
||||
cli_opt_usage (progname, options);
|
||||
cli_opt_usage (prog_name_p, command_name_p, options_p);
|
||||
|
||||
const cli_opt_t *opt = options;
|
||||
const cli_opt_t *opt_p = options_p;
|
||||
|
||||
while (opt->id != CLI_OPT_DEFAULT)
|
||||
while (opt_p->id != CLI_OPT_DEFAULT)
|
||||
{
|
||||
int length = CLI_LINE_INDENT;
|
||||
cli_print_pad (CLI_LINE_INDENT);
|
||||
|
||||
if (opt->opt != NULL)
|
||||
if (opt_p->opt != NULL)
|
||||
{
|
||||
printf ("-%s", opt->opt);
|
||||
length += (int) (strlen (opt->opt) + 1);
|
||||
printf ("-%s", opt_p->opt);
|
||||
length += (int) (strlen (opt_p->opt) + 1);
|
||||
}
|
||||
|
||||
if (opt->opt != NULL && opt->longopt != NULL)
|
||||
if (opt_p->opt != NULL && opt_p->longopt != NULL)
|
||||
{
|
||||
printf (", ");
|
||||
length += 2;
|
||||
}
|
||||
|
||||
if (opt->longopt != NULL)
|
||||
if (opt_p->longopt != NULL)
|
||||
{
|
||||
printf ("--%s", opt->longopt);
|
||||
length += (int) (strlen (opt->longopt) + 2);
|
||||
printf ("--%s", opt_p->longopt);
|
||||
length += (int) (strlen (opt_p->longopt) + 2);
|
||||
}
|
||||
|
||||
if (opt->meta != NULL)
|
||||
if (opt_p->meta != NULL)
|
||||
{
|
||||
printf (" %s", opt->meta);
|
||||
length += 1 + (int) strlen (opt->meta);
|
||||
printf (" %s", opt_p->meta);
|
||||
length += 1 + (int) strlen (opt_p->meta);
|
||||
}
|
||||
|
||||
if (opt->help != NULL)
|
||||
if (opt_p->help != NULL)
|
||||
{
|
||||
if (length >= CLI_LINE_TAB)
|
||||
{
|
||||
@@ -400,23 +426,23 @@ cli_help (const char *progname, /**< program name, typically argv[0] */
|
||||
cli_print_pad (CLI_LINE_TAB - length);
|
||||
length = CLI_LINE_TAB;
|
||||
|
||||
cli_print_help (opt->help);
|
||||
cli_print_help (opt_p->help);
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
opt++;
|
||||
opt_p++;
|
||||
}
|
||||
|
||||
if (opt->help != NULL)
|
||||
if (opt_p->help != NULL)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
if (opt->meta != NULL)
|
||||
if (opt_p->meta != NULL)
|
||||
{
|
||||
length = (int) (CLI_LINE_INDENT + strlen (opt->meta));
|
||||
length = (int) (CLI_LINE_INDENT + strlen (opt_p->meta));
|
||||
|
||||
cli_print_pad (CLI_LINE_INDENT);
|
||||
printf ("%s", opt->meta);
|
||||
printf ("%s", opt_p->meta);
|
||||
}
|
||||
|
||||
if (length >= CLI_LINE_TAB)
|
||||
@@ -427,7 +453,7 @@ cli_help (const char *progname, /**< program name, typically argv[0] */
|
||||
|
||||
cli_print_pad (CLI_LINE_TAB - length);
|
||||
|
||||
cli_print_help (opt->help);
|
||||
cli_print_help (opt_p->help);
|
||||
printf ("\n");
|
||||
}
|
||||
} /* cli_help */
|
||||
|
||||
+6
-5
@@ -66,10 +66,11 @@ typedef struct
|
||||
* Functions for CLI.
|
||||
*/
|
||||
|
||||
cli_state_t cli_init (const cli_opt_t *options, int argc, char **argv);
|
||||
int cli_consume_option (cli_state_t *state);
|
||||
const char * cli_consume_string (cli_state_t *state);
|
||||
int cli_consume_int (cli_state_t *state);
|
||||
void cli_help (const char *progname, const cli_opt_t *options);
|
||||
cli_state_t cli_init (const cli_opt_t *options_p, int argc, char **argv);
|
||||
void cli_change_opts (cli_state_t *state_p, const cli_opt_t *options_p);
|
||||
int cli_consume_option (cli_state_t *state_p);
|
||||
const char * cli_consume_string (cli_state_t *state_p);
|
||||
int cli_consume_int (cli_state_t *state_p);
|
||||
void cli_help (const char *prog_name_p, const char *command_name_p, const cli_opt_t *options_p);
|
||||
|
||||
#endif /* CLI_H */
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/* 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 <string.h>
|
||||
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
#include "cli.h"
|
||||
|
||||
/**
|
||||
* Maximum size for loaded snapshots
|
||||
*/
|
||||
#define JERRY_BUFFER_SIZE (1048576)
|
||||
|
||||
/**
|
||||
* 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 ];
|
||||
|
||||
/**
|
||||
* Loading a single file into the memory.
|
||||
*
|
||||
* @return size of file - if loading is successful
|
||||
* 0 - otherwise
|
||||
*/
|
||||
static size_t
|
||||
read_file (uint8_t *input_pos_p, /**< next position in the input buffer */
|
||||
const char *file_name) /**< file name */
|
||||
{
|
||||
FILE *file = fopen (file_name, "r");
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = (size_t) (input_buffer + JERRY_BUFFER_SIZE - input_pos_p);
|
||||
|
||||
size_t bytes_read = fread (input_pos_p, 1u, max_size, file);
|
||||
fclose (file);
|
||||
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bytes_read == max_size)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: file too large: %s\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf ("Input file '%s' (%d bytes) loaded.\n", file_name, (int) bytes_read);
|
||||
return bytes_read;
|
||||
} /* read_file */
|
||||
|
||||
/**
|
||||
* 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: merged.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 */
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
uint8_t *input_pos_p = input_buffer;
|
||||
|
||||
cli_change_opts (cli_state_p, merge_opts);
|
||||
|
||||
const char *output_file_name_p = "merged.snapshot";
|
||||
const uint32_t *merge_buffers[argc];
|
||||
size_t merge_buffer_sizes[argc];
|
||||
uint32_t number_of_files = 0;
|
||||
|
||||
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case OPT_MERGE_HELP:
|
||||
{
|
||||
cli_help (prog_name_p, "merge", merge_opts);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
}
|
||||
case OPT_MERGE_OUT:
|
||||
{
|
||||
output_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case CLI_OPT_DEFAULT:
|
||||
{
|
||||
const char *file_name_p = cli_consume_string (cli_state_p);
|
||||
|
||||
if (cli_state_p->error == NULL)
|
||||
{
|
||||
size_t size = read_file (input_pos_p, file_name_p);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
merge_buffers[number_of_files] = (const uint32_t *) input_pos_p;
|
||||
merge_buffer_sizes[number_of_files] = size;
|
||||
|
||||
number_of_files++;
|
||||
const uintptr_t mask = sizeof (uint32_t) - 1;
|
||||
input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cli_state_p->error = "Internal error";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (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 JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
if (number_of_files < 2)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n");
|
||||
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
const char *error_p;
|
||||
size_t size = jerry_merge_snapshots (merge_buffers,
|
||||
merge_buffer_sizes,
|
||||
number_of_files,
|
||||
output_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
&error_p);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
FILE *file_p = fopen (output_file_name_p, "w");
|
||||
|
||||
if (file_p != NULL)
|
||||
{
|
||||
fwrite (output_buffer, 1u, size, file_p);
|
||||
fclose (file_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p);
|
||||
}
|
||||
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
} /* process_merge */
|
||||
|
||||
/**
|
||||
* 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"
|
||||
" 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 - 1, argv + 1);
|
||||
|
||||
for (int id = cli_consume_option (&cli_state); id != CLI_OPT_END; id = cli_consume_option (&cli_state))
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case OPT_MERGE_HELP:
|
||||
{
|
||||
/* Help is always printed if no command is provided. */
|
||||
break;
|
||||
}
|
||||
case CLI_OPT_DEFAULT:
|
||||
{
|
||||
const char *command_p = cli_consume_string (&cli_state);
|
||||
|
||||
if (cli_state.error != NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp ("merge", command_p))
|
||||
{
|
||||
return process_merge (&cli_state, argc, argv[0]);
|
||||
}
|
||||
|
||||
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 (cli_state.error != NULL)
|
||||
{
|
||||
if (cli_state.arg != NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state.error, cli_state.arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state.error);
|
||||
}
|
||||
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
print_commands (argv[0]);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
} /* main */
|
||||
+24
-5
@@ -319,6 +319,7 @@ typedef enum
|
||||
OPT_SAVE_LIT_LIST,
|
||||
OPT_SAVE_LIT_C,
|
||||
OPT_EXEC_SNAP,
|
||||
OPT_EXEC_SNAP_FUNC,
|
||||
OPT_LOG_LEVEL,
|
||||
OPT_ABORT_ON_FAIL,
|
||||
OPT_NO_PROMPT
|
||||
@@ -357,6 +358,8 @@ static const cli_opt_t main_opts[] =
|
||||
.help = "export literals found in parsed JS input (in C source format)"),
|
||||
CLI_OPT_DEF (.id = OPT_EXEC_SNAP, .longopt = "exec-snapshot", .meta = "FILE",
|
||||
.help = "execute input snapshot file(s)"),
|
||||
CLI_OPT_DEF (.id = OPT_EXEC_SNAP_FUNC, .longopt = "exec-snapshot-func", .meta = "FILE NUM",
|
||||
.help = "execute specific function from input snapshot file(s)"),
|
||||
CLI_OPT_DEF (.id = OPT_LOG_LEVEL, .longopt = "log-level", .meta = "NUM",
|
||||
.help = "set log level (0-3)"),
|
||||
CLI_OPT_DEF (.id = OPT_ABORT_ON_FAIL, .longopt = "abort-on-fail",
|
||||
@@ -427,6 +430,7 @@ main (int argc,
|
||||
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
|
||||
|
||||
const char *exec_snapshot_file_names[argc];
|
||||
uint32_t exec_snapshot_file_indices[argc];
|
||||
int exec_snapshots_count = 0;
|
||||
|
||||
bool is_parse_only = false;
|
||||
@@ -452,7 +456,7 @@ main (int argc,
|
||||
{
|
||||
case OPT_HELP:
|
||||
{
|
||||
cli_help (argv[0], main_opts);
|
||||
cli_help (argv[0], NULL, main_opts);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
}
|
||||
case OPT_VERSION:
|
||||
@@ -544,7 +548,21 @@ main (int argc,
|
||||
{
|
||||
if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg))
|
||||
{
|
||||
exec_snapshot_file_names[exec_snapshots_count++] = cli_consume_string (&cli_state);
|
||||
exec_snapshot_file_names[exec_snapshots_count] = cli_consume_string (&cli_state);
|
||||
exec_snapshot_file_indices[exec_snapshots_count++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cli_consume_string (&cli_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_EXEC_SNAP_FUNC:
|
||||
{
|
||||
if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg))
|
||||
{
|
||||
exec_snapshot_file_names[exec_snapshots_count] = cli_consume_string (&cli_state);
|
||||
exec_snapshot_file_indices[exec_snapshots_count++] = (uint32_t) cli_consume_int (&cli_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -650,9 +668,10 @@ main (int argc,
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = jerry_exec_snapshot (snapshot_p,
|
||||
snapshot_size,
|
||||
true);
|
||||
ret_value = jerry_exec_snapshot_at (snapshot_p,
|
||||
snapshot_size,
|
||||
exec_snapshot_file_indices[i],
|
||||
true);
|
||||
}
|
||||
|
||||
if (jerry_value_has_error_flag (ret_value))
|
||||
|
||||
Reference in New Issue
Block a user