From 7837440cbb2d6ddfb634ca2c277a96935c46f45d Mon Sep 17 00:00:00 2001 From: Akos Kiss Date: Tue, 16 May 2017 10:29:27 +0200 Subject: Add lightweight command line processor to jerry-main (#1809) Eases command line option and sub-command definition, usage summary and detailed help message printing, and argv processing. JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu --- jerry-main/CMakeLists.txt | 6 +- jerry-main/cli.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++ jerry-main/cli.h | 151 ++++++++++++++++ jerry-main/main-unix.c | 306 ++++++++++++++++++--------------- 4 files changed, 755 insertions(+), 137 deletions(-) create mode 100644 jerry-main/cli.c create mode 100644 jerry-main/cli.h (limited to 'jerry-main') diff --git a/jerry-main/CMakeLists.txt b/jerry-main/CMakeLists.txt index 6f6d9d33..b2cc6515 100644 --- a/jerry-main/CMakeLists.txt +++ b/jerry-main/CMakeLists.txt @@ -43,8 +43,8 @@ endif() set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_COMMIT_HASH="${JERRY_COMMIT_HASH}") -macro(jerry_create_executable JERRY_NAME SOURCE_JERRY_STANDALONE_MAIN) - add_executable(${JERRY_NAME} ${SOURCE_JERRY_STANDALONE_MAIN}) +macro(jerry_create_executable JERRY_NAME) + add_executable(${JERRY_NAME} ${ARGN}) set_property(TARGET ${JERRY_NAME} PROPERTY LINK_FLAGS "${LINKER_FLAGS_COMMON}") target_compile_definitions(${JERRY_NAME} PRIVATE ${DEFINES_JERRY}) @@ -57,7 +57,7 @@ endmacro() # Jerry standalones if(JERRY_CMDLINE) - jerry_create_executable("jerry" "main-unix.c") + jerry_create_executable("jerry" "main-unix.c" "cli.c") target_link_libraries("jerry" jerry-ext jerry-port-default) endif() diff --git a/jerry-main/cli.c b/jerry-main/cli.c new file mode 100644 index 00000000..be7f64ef --- /dev/null +++ b/jerry-main/cli.c @@ -0,0 +1,429 @@ +/* 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 +#include + +#include "cli.h" + +/* + * Fixed layout settings + */ + +/** + * Wrap lines at: + */ +#define CLI_LINE_LENGTH 80 + +/** + * Indent various lines with: + */ +#define CLI_LINE_INDENT 2 + +/** + * Tab stop (for multi-column display) at: + */ +#define CLI_LINE_TAB 24 + +/* + * Print helper functions + */ + +/** + * Pad with spaces. + */ +static void +cli_print_pad (int cnt) /**< number of spaces to print */ +{ + for (int i = 0; i < cnt; i++) + { + printf (" "); + } +} /* cli_print_pad */ + +/** + * Print the prefix of a string. + */ +static void +cli_print_prefix (const char *str, /**< string to print */ + int len) /**< length of the prefix to print */ +{ + for (int i = 0; i < len; i++) + { + printf ("%c", *str++); + } +} /* cli_print_prefix */ + +/** + * Print a help message wrapped into the second column. + */ +static void +cli_print_help (const char *help) /**< the help message to print */ +{ + while (help != NULL && *help != 0) + { + int length = -1; + int i = 0; + for (; i < CLI_LINE_LENGTH - CLI_LINE_TAB && help[i] != 0; i++) + { + if (help[i] == ' ') + { + length = i; + } + } + if (length < 0 || i < CLI_LINE_LENGTH - CLI_LINE_TAB) + { + length = i; + } + + cli_print_prefix (help, length); + + help += length; + while (*help == ' ' && *help != 0) + { + help++; + } + + if (*help != 0) + { + printf ("\n"); + cli_print_pad (CLI_LINE_TAB); + } + } +} /* cli_print_help */ + +/* + * Command line option handling + */ + +/** + * Initialize a command line option processor. + * + * @return the state that should be passed iteratively to cli_opt_process. + */ +cli_opt_state_t +cli_opt_init (const cli_opt_t *opts, /**< array of option definitions, terminated by CLI_OPT_END */ + int argc, /**< number of command line arguments */ + char **argv) /**< array of command line arguments */ +{ + return (cli_opt_state_t) + { + .opts = opts, + .argc = argc, + .argv = argv, + .opt = NULL, + .arg = NULL + }; +} /* cli_opt_init */ + +/** + * Perform one step of the command line option processor. + * + * @return the ID of the option that was found. (The definition of the found + * option (if any) is available via state->opt, while the option + * string and its arguments are available via state->arg[0..].) + * CLI_OPT_END signals that all command line arguments are consumed. + */ +int +cli_opt_process (cli_opt_state_t *state) /**< state of the command line option processor */ +{ + if (state->argc <= 0) + { + state->opt = NULL; + state->arg = NULL; + return CLI_OPT_END; + } + + state->arg = state->argv; + + for (const cli_opt_t *o = state->opts; o->id != CLI_OPT_END; o++) + { + state->opt = o; + + if (o->id == CLI_OPT_POSITIONAL && (state->arg[0][0] != '-' || !strcmp (state->arg[0], "-"))) + { + state->argc--; + state->argv++; + return CLI_OPT_POSITIONAL; + } + else if ((o->opt != NULL && !strcmp (o->opt, state->arg[0])) + || (o->longopt != NULL && !strcmp (o->longopt, state->arg[0]))) + { + if (state->argc > o->argc) + { + state->argc -= 1 + o->argc; + state->argv += 1 + o->argc; + return o->id; + } + else + { + state->argv += state->argc; + state->argc = 0; + return CLI_OPT_INCOMPLETE; + } + } + } + + state->opt = NULL; + state->argc--; + state->argv++; + return CLI_OPT_UNKNOWN; +} /* cli_opt_process */ + +/** + * Print usage summary of options. + */ +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_END */ +{ + int length = (int) strlen (progname); + printf ("%s", progname); + + for (const cli_opt_t *o = opts; o->id != CLI_OPT_END; o++) + { + const char *opt = o->opt != NULL ? o->opt : o->longopt; + opt = opt != NULL ? opt : o->meta; + + int opt_length = (int) strlen (opt); + if (o->argc > 0) + { + opt_length += o->meta != NULL ? 1 + (int) strlen (o->meta) : o->argc * 2; + } + opt_length += o->quant == CLI_QUANT_Q || o->quant == CLI_QUANT_A ? 2 : 0; + opt_length += o->quant == CLI_QUANT_P || o->quant == CLI_QUANT_A ? 3 : 0; + + if (length + 1 + opt_length >= CLI_LINE_LENGTH) + { + length = CLI_LINE_INDENT - 1; + printf ("\n"); + cli_print_pad (length); + } + length += opt_length; + + printf (" "); + + if (o->quant == CLI_QUANT_Q || o->quant == CLI_QUANT_A) + { + printf ("["); + } + + printf ("%s", opt); + + if (o->argc > 0) + { + if (o->meta != NULL) + { + printf (" %s", o->meta); + } + else + { + for (int i = 0; i < o->argc; i++) + { + printf (" _"); + } + } + } + + if (o->quant == CLI_QUANT_Q || o->quant == CLI_QUANT_A) + { + printf ("]"); + } + + if (o->quant == CLI_QUANT_P || o->quant == CLI_QUANT_A) + { + printf ("..."); + } + } + + printf ("\n"); +} /* cli_opt_usage */ + +/** + * Print detailed help for options. + */ +void +cli_opt_help (const cli_opt_t *opts) /**< array of command line option definitions, terminated by CLI_OPT_END */ +{ + for (const cli_opt_t *o = opts; o->id != CLI_OPT_END; o++) + { + int length = CLI_LINE_INDENT; + cli_print_pad (length); + + if (o->opt != NULL) + { + printf ("%s", o->opt); + length += (int) strlen (o->opt); + } + + if (o->opt != NULL && o->longopt != NULL) + { + printf (", "); + length += 2; + } + + if (o->longopt != NULL) + { + printf ("%s", o->longopt); + length += (int) strlen (o->longopt); + } + + if (o->opt == NULL && o->longopt == NULL) + { + printf ("%s", o->meta); + length += (int) strlen (o->meta); + } + else if (o->argc > 0) + { + if (o->meta != NULL) + { + printf (" %s", o->meta); + length += 1 + (int) strlen (o->meta); + } + else + { + for (int i = 0; i < o->argc; i++) + { + printf (" _"); + } + length += o->argc * 2; + } + } + + if (o->help != NULL) + { + if (length >= CLI_LINE_TAB) + { + printf ("\n"); + length = 0; + } + cli_print_pad (CLI_LINE_TAB - length); + length = CLI_LINE_TAB; + + cli_print_help (o->help); + } + + printf ("\n"); + } +} /* cli_opt_help */ + +/* + * Sub-command handling + */ + +/** + * Initialize a sub-command processor. + * + * @return the state that should be passed to cli_cmd_process. + */ +cli_cmd_state_t +cli_cmd_init (const cli_cmd_t *cmds, /**< array of sub-command definitions, terminated by CLI_CMD_END */ + int argc, /**< number of command line arguments */ + char **argv) /**< array of command line arguments */ +{ + return (cli_cmd_state_t) + { + .cmds = cmds, + .argc = argc, + .argv = argv, + .cmd = NULL, + .arg = NULL + }; +} /* cli_cmd_init */ + +/** + * Process first element of the command line and determine whether it is a + * defined sub-command or not. + * + * @return the ID of the sub-command that was found. + */ +int +cli_cmd_process (cli_cmd_state_t *state) /**< state of the sub-command processor */ +{ + if (state->argc <= 0 || state->argv[0][0] == '-') + { + state->cmd = NULL; + state->arg = NULL; + return CLI_CMD_NONE; + } + + state->arg = state->argv; + + for (const cli_cmd_t *c = state->cmds; c->id != CLI_CMD_END; c++) + { + state->cmd = c; + + if (!strcmp (c->cmd, state->argv[0])) + { + state->argc--; + state->argv++; + state->cmd = c; + return c->id; + } + } + + state->cmd = NULL; + state->argc--; + state->argv++; + return CLI_CMD_UNKNOWN; +} /* cli_cmd_process */ + +/** + * Print usage summary of all sub-commands. + */ +void +cli_cmd_usage (const char *progname, /**< program name, typically argv[0] */ + const cli_cmd_t *cmds) /**< array of sub-command definitions, terminated by CLI_CMD_END */ +{ + for (const cli_cmd_t *c = cmds; c->id != CLI_CMD_END; c++) + { + if (c->cmd != NULL) + { + CLI_CMD_NAME (cmdname, progname, c->cmd); + cli_opt_usage (cmdname, c->opts); + } + } +} /* cli_cmd_usage */ + +/** + * Print help of all sub-commands. + */ +void +cli_cmd_help (const cli_cmd_t *cmds) /**< array of sub-command definitions, terminated by CLI_CMD_END */ +{ + for (const cli_cmd_t *c = cmds; c->id != CLI_CMD_END; c++) + { + int length = CLI_LINE_INDENT; + cli_print_pad (length); + + printf ("%s", c->cmd); + length += (int) strlen (c->cmd); + + if (c->help != NULL) + { + if (length >= CLI_LINE_TAB) + { + printf ("\n"); + length = 0; + } + cli_print_pad (CLI_LINE_TAB - length); + length = CLI_LINE_TAB; + + cli_print_help (c->help); + } + + printf ("\n"); + } +} /* cli_cmd_help */ diff --git a/jerry-main/cli.h b/jerry-main/cli.h new file mode 100644 index 00000000..a5223de4 --- /dev/null +++ b/jerry-main/cli.h @@ -0,0 +1,151 @@ +/* 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. + */ + +#ifndef CLI_H +#define CLI_H + +#include + +/* + * Types for CLI + */ + +/** + * Command line option definition + */ +typedef struct +{ + int id; /**< unique ID of the option (CLI_OPT_END, CLI_OPT_POSITIONAL, or anything >= 0) */ + const char *opt; /**< short option variant (in the form of "-x") */ + const char *longopt; /**< long option variant (in the form of "--xxx") */ + int argc; /**< number of arguments of the option */ + const char *meta; /**< name(s) of the argument(s) of the option, for display only */ + int quant; /**< quantifier of the option (CLI_QUANT_{Q,A,P,1} for ?,*,+,1), for display only */ + const char *help; /**< descriptive help message of the option */ +} cli_opt_t; + +/** + * Quantifiers of command line options + */ +typedef enum +{ + CLI_QUANT_Q, /**< ? (Question mark: optional, zero or one) */ + CLI_QUANT_A, /**< * (Asterisk, star: zero or one or more) */ + CLI_QUANT_P, /**< + (Plus sign: one or more) */ + CLI_QUANT_1 /**< 1 (One: one) */ +} cli_opt_quant_t; + +/** + * Common command line option IDs + */ +typedef enum +{ + CLI_OPT_POSITIONAL = -1, /**< positional "option" */ + CLI_OPT_END = -2, /**< end of options marker */ + CLI_OPT_INCOMPLETE = -3, /**< incomplete option (too few arguments) */ + CLI_OPT_UNKNOWN = -4 /**< unknown option */ +} cli_opt_id_t; + +/** + * State of the command line option processor. + * No fields should be accessed other than arg and opt. + */ +typedef struct +{ + const cli_opt_t *opts; + int argc; + char **argv; + const cli_opt_t *opt; /**< found option or NULL */ + char **arg; /**< array of strings for the last processed option */ +} cli_opt_state_t; + +/** + * Sub-command definition + */ +typedef struct +{ + int id; /**< unique ID of the sub-command (CLI_CMD_END, or anything >= 0) */ + const char *cmd; /**< sub-command name (in the form of "xxx") */ + const cli_opt_t *opts; /**< array of associated command line option definitions, for display only */ + const char *help; /**< descriptive help message of the sub-command */ +} cli_cmd_t; + +/** + * Common sub-command IDs + */ +typedef enum +{ + CLI_CMD_END = -1, /**< end of sub-commands marker */ + CLI_CMD_NONE = -1, /**< no sub-command */ + CLI_CMD_UNKNOWN = -2 /**< unknown sub-command */ +} cli_cmd_id_t; + +/** + * State of the sub-command processor. + * No fields should be accessed other than arg and cmd. + */ +typedef struct +{ + const cli_cmd_t *cmds; + int argc; + char **argv; + const cli_cmd_t *cmd; /**< found command or NULL */ + char **arg; /**< array of strings for the processed command */ +} cli_cmd_state_t; + +/* + * Functions for CLI + */ + +cli_opt_state_t cli_opt_init (const cli_opt_t *opts, int argc, char **argv); +int cli_opt_process (cli_opt_state_t *state); +void cli_opt_usage (const char *progname, const cli_opt_t *opts); +void cli_opt_help (const cli_opt_t *opts); + +cli_cmd_state_t cli_cmd_init (const cli_cmd_t *cmds, int argc, char **argv); +int cli_cmd_process (cli_cmd_state_t *state); +void cli_cmd_help (const cli_cmd_t *cmds); +void cli_cmd_usage (const char *progname, const cli_cmd_t *cmds); + +/* + * Useful macros for CLI + */ + +/** + * Macro for writing command line option definition struct literals + */ +#define CLI_OPT_DEF(...) /*(cli_opt_t)*/ { __VA_ARGS__ } + +/** + * Macro for writing sub-command definition struct literals + */ +#define CLI_CMD_DEF(...) /*(cli_cmd_t)*/ { __VA_ARGS__ } + +/** + * Declare a char VLA and concatenate a program name and a sub-command name + * (separated by a single space) into the new array. Useful for printing command + * line option usage summary for sub-commands. + * + * @param CMDNAME name of the new array variable. + * @param PROGNAME string containing the name of the program. + * @param CMD string continaing the name of the sub-command. + */ +#define CLI_CMD_NAME(CMDNAME, PROGNAME, CMD) \ + char CMDNAME[strlen ((PROGNAME)) + strlen ((CMD)) + 2]; \ + strncpy (CMDNAME, (PROGNAME), strlen ((PROGNAME))); \ + CMDNAME[strlen ((PROGNAME))] = ' '; \ + strncpy (CMDNAME + strlen ((PROGNAME)) + 1, (CMD), strlen ((CMD)) + 1) + +#endif /* CLI_H */ diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index e391e8ec..de69173c 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -23,6 +23,8 @@ #include "jerryscript-port.h" #include "jerryscript-port-default.h" +#include "cli.h" + /** * Maximum size of source code */ @@ -79,40 +81,6 @@ read_file (const char *file_name, return (const uint32_t *) buffer; } /* read_file */ -static void -print_usage (const char *name) -{ - printf ("Usage: %s [OPTION]... [FILE]...\n" - "Try '%s --help' for more information.\n", - name, - name); -} /* print_usage */ - -static void -print_help (const char *name) -{ - printf ("Usage: %s [OPTION]... [FILE]...\n" - "\n" - "Options:\n" - " -h, --help\n" - " -v, --version\n" - " --mem-stats\n" - " --parse-only\n" - " --show-opcodes\n" - " --show-regexp-opcodes\n" - " --start-debug-server\n" - " --save-snapshot-for-global FILE\n" - " --save-snapshot-for-eval FILE\n" - " --save-literals-list-format FILE\n" - " --save-literals-c-format FILE\n" - " --exec-snapshot FILE\n" - " --log-level [0-3]\n" - " --abort-on-fail\n" - " --no-prompt\n" - "\n", - name); -} /* print_help */ - /** * Check whether an error is a SyntaxError or not * @@ -323,6 +291,68 @@ register_js_function (const char *name_p, /**< name of the function */ jerry_release_value (result_val); } /* register_js_function */ +/** + * Command line option IDs + */ +typedef enum +{ + OPT_HELP, + OPT_VERSION, + OPT_MEM_STATS, + OPT_PARSE_ONLY, + OPT_SHOW_OP, + OPT_SHOW_RE_OP, + OPT_DEBUG_SERVER, + OPT_SAVE_SNAP_GLOBAL, + OPT_SAVE_SNAP_EVAL, + OPT_SAVE_LIT_LIST, + OPT_SAVE_LIT_C, + OPT_EXEC_SNAP, + OPT_LOG_LEVEL, + OPT_ABORT_ON_FAIL, + OPT_NO_PROMPT +} main_opt_id_t; + +/** + * Command line options + */ +static 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 = OPT_VERSION, .opt = "-v", .longopt = "--version", + .help = "print tool and library version and exit"), + CLI_OPT_DEF (.id = OPT_MEM_STATS, .longopt = "--mem-stats", + .help = "dump memory statistics"), + CLI_OPT_DEF (.id = OPT_PARSE_ONLY, .longopt = "--parse-only", + .help = "don't execute JS input"), + CLI_OPT_DEF (.id = OPT_SHOW_OP, .longopt = "--show-opcodes", + .help = "dump parser byte-code"), + CLI_OPT_DEF (.id = OPT_SHOW_RE_OP, .longopt = "--show-regexp-opcodes", + .help = "dump regexp byte-code"), + CLI_OPT_DEF (.id = OPT_DEBUG_SERVER, .longopt = "--start-debug-server", + .help = "start debug server and wait for a connecting client"), + CLI_OPT_DEF (.id = OPT_SAVE_SNAP_GLOBAL, .longopt = "--save-snapshot-for-global", .argc = 1, .meta = "FILE", + .help = "save binary snapshot of parsed JS input (for execution in global context)"), + CLI_OPT_DEF (.id = OPT_SAVE_SNAP_EVAL, .longopt = "--save-snapshot-for-eval", .argc = 1, .meta = "FILE", + .help = "save binary snapshot of parsed JS input (for execution in local context by eval)"), + CLI_OPT_DEF (.id = OPT_SAVE_LIT_LIST, .longopt = "--save-literals-list-format", .argc = 1, .meta = "FILE", + .help = "export literals found in parsed JS input (in list format)"), + CLI_OPT_DEF (.id = OPT_SAVE_LIT_C, .longopt = "--save-literals-c-format", .argc = 1, .meta = "FILE", + .help = "export literals found in parsed JS input (in C source format)"), + CLI_OPT_DEF (.id = OPT_EXEC_SNAP, .longopt = "--exec-snapshot", .argc = 1, .meta = "FILE", .quant = CLI_QUANT_A, + .help = "execute input snapshot file(s)"), + CLI_OPT_DEF (.id = OPT_LOG_LEVEL, .longopt = "--log-level", .argc = 1, .meta = "NUM", + .help = "set log level (0-3)"), + CLI_OPT_DEF (.id = OPT_ABORT_ON_FAIL, .longopt = "--abort-on-fail", + .help = "segfault on internal failure (instead of non-zero exit code)"), + CLI_OPT_DEF (.id = OPT_NO_PROMPT, .longopt = "--no-prompt", + .help = "don't print prompt in REPL mode"), + CLI_OPT_DEF (.id = CLI_OPT_POSITIONAL, .meta = "FILE", .quant = CLI_QUANT_A, + .help = "input JS file(s)"), + CLI_OPT_DEF (.id = CLI_OPT_END) +}; + /** * Check whether JerryScript has a requested feature enabled or not. If not, * print a warning message. @@ -354,14 +384,8 @@ check_usage (bool condition, /**< the condition that must hold */ { if (!condition) { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%s", msg); - if (opt != NULL) - { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%s", opt); - } - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "\n"); - - print_usage (name); + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%s%s\n", msg, opt != NULL ? opt : ""); + cli_opt_usage (name, main_opts); exit (JERRY_STANDALONE_EXIT_CODE_FAIL); } } /* check_usage */ @@ -390,115 +414,129 @@ main (int argc, bool is_repl_mode = false; bool no_prompt = false; - for (int i = 1; i < argc; i++) + cli_opt_state_t cli_state = cli_opt_init (main_opts, argc - 1, argv + 1); + for (int id = cli_opt_process (&cli_state); id != CLI_OPT_END; id = cli_opt_process (&cli_state)) { - if (!strcmp ("-h", argv[i]) || !strcmp ("--help", argv[i])) - { - print_help (argv[0]); - return JERRY_STANDALONE_EXIT_CODE_OK; - } - else if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) - { - printf ("Version: %d.%d%s\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION, JERRY_COMMIT_HASH); - return JERRY_STANDALONE_EXIT_CODE_OK; - } - else if (!strcmp ("--mem-stats", argv[i])) + switch (id) { - if (check_feature (JERRY_FEATURE_MEM_STATS, argv[i])) + case OPT_HELP: { - jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); - flags |= JERRY_INIT_MEM_STATS; + cli_opt_usage (argv[0], main_opts); + printf ("\n"); + cli_opt_help (main_opts); + return JERRY_STANDALONE_EXIT_CODE_OK; } - } - else if (!strcmp ("--parse-only", argv[i])) - { - is_parse_only = true; - } - else if (!strcmp ("--show-opcodes", argv[i])) - { - if (check_feature (JERRY_FEATURE_PARSER_DUMP, argv[i])) + case OPT_VERSION: { - jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); - flags |= JERRY_INIT_SHOW_OPCODES; + printf ("Version: %d.%d%s\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION, JERRY_COMMIT_HASH); + return JERRY_STANDALONE_EXIT_CODE_OK; } - } - else if (!strcmp ("--show-regexp-opcodes", argv[i])) - { - if (check_feature (JERRY_FEATURE_REGEXP_DUMP, argv[i])) + case OPT_MEM_STATS: { - jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); - flags |= JERRY_INIT_SHOW_REGEXP_OPCODES; + if (check_feature (JERRY_FEATURE_MEM_STATS, cli_state.arg[0])) + { + jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); + flags |= JERRY_INIT_MEM_STATS; + } + break; } - } - else if (!strcmp ("--start-debug-server", argv[i])) - { - if (check_feature (JERRY_FEATURE_DEBUGGER, argv[i])) + case OPT_PARSE_ONLY: { - flags |= JERRY_INIT_DEBUGGER; + is_parse_only = true; + break; } - } - else if (!strcmp ("--save-snapshot-for-global", argv[i]) - || !strcmp ("--save-snapshot-for-eval", argv[i])) - { - check_usage (i + 1 < argc, argv[0], "Error: no file specified for ", argv[i]); - check_usage (save_snapshot_file_name_p == NULL, argv[0], "Error: snapshot file name already specified", NULL); - - if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, argv[i++])) + case OPT_SHOW_OP: { - is_save_snapshot_mode = true; - is_save_snapshot_mode_for_global_or_eval = !strcmp ("--save-snapshot-for-global", argv[i - 1]); - save_snapshot_file_name_p = argv[i]; + if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state.arg[0])) + { + jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); + flags |= JERRY_INIT_SHOW_OPCODES; + } + break; } - } - else if (!strcmp ("--exec-snapshot", argv[i])) - { - check_usage (i + 1 < argc, argv[0], "Error: no file specified for ", argv[i]); - - if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, argv[i++])) + case OPT_SHOW_RE_OP: { - exec_snapshot_file_names[exec_snapshots_count++] = argv[i]; + if (check_feature (JERRY_FEATURE_REGEXP_DUMP, cli_state.arg[0])) + { + jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); + flags |= JERRY_INIT_SHOW_REGEXP_OPCODES; + } + break; } - } - else if (!strcmp ("--save-literals-list-format", argv[i]) - || !strcmp ("--save-literals-c-format", argv[i])) - { - check_usage (i + 1 < argc, argv[0], "Error: no file specified for ", argv[i]); - check_usage (save_literals_file_name_p == NULL, argv[0], "Error: literal file name already specified", NULL); - - if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, argv[i++])) + case OPT_DEBUG_SERVER: { - is_save_literals_mode = true; - is_save_literals_mode_in_c_format_or_list = !strcmp ("--save-literals-c-format", argv[i - 1]); - save_literals_file_name_p = argv[i]; + if (check_feature (JERRY_FEATURE_DEBUGGER, cli_state.arg[0])) + { + flags |= JERRY_INIT_DEBUGGER; + } + break; } - } - else if (!strcmp ("--log-level", argv[i])) - { - check_usage (i + 1 < argc, argv[0], "Error: no level specified for ", argv[i]); - check_usage (strlen (argv[i + 1]) == 1 && argv[i + 1][0] >= '0' && argv[i + 1][0] <= '3', - argv[0], "Error: wrong format for ", argv[i]); + case OPT_SAVE_SNAP_GLOBAL: + case OPT_SAVE_SNAP_EVAL: + { + check_usage (save_snapshot_file_name_p == NULL, argv[0], "Error: snapshot file name already specified", NULL); + if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, cli_state.arg[0])) + { + is_save_snapshot_mode = true; + is_save_snapshot_mode_for_global_or_eval = cli_state.opt->id == OPT_SAVE_SNAP_GLOBAL; + save_snapshot_file_name_p = cli_state.arg[1]; + } + break; + } + case OPT_SAVE_LIT_LIST: + case OPT_SAVE_LIT_C: + { + check_usage (save_literals_file_name_p == NULL, argv[0], "Error: literal file name already specified", NULL); + if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, cli_state.arg[0])) + { + is_save_literals_mode = true; + is_save_literals_mode_in_c_format_or_list = cli_state.opt->id == OPT_SAVE_LIT_C; + save_literals_file_name_p = cli_state.arg[1]; + } + break; + } + case OPT_EXEC_SNAP: + { + if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg[0])) + { + exec_snapshot_file_names[exec_snapshots_count++] = cli_state.arg[1]; + } + break; + } + case OPT_LOG_LEVEL: + { + check_usage (strlen (cli_state.arg[1]) == 1 && cli_state.arg[1][0] >= '0' && cli_state.arg[1][0] <= '3', + argv[0], "Error: wrong format for ", cli_state.arg[0]); - jerry_port_default_set_log_level ((jerry_log_level_t) (argv[++i][0] - '0')); - } - else if (!strcmp ("--abort-on-fail", argv[i])) - { - jerry_port_default_set_abort_on_fail (true); - } - else if (!strcmp ("--no-prompt", argv[i])) - { - no_prompt = true; - } - else if (!strcmp ("-", argv[i])) - { - file_names[files_counter++] = argv[i]; - } - else if (!strncmp ("-", argv[i], 1)) - { - check_usage (false, argv[0], "Error: unrecognized option: %s\n", argv[i]); - } - else - { - file_names[files_counter++] = argv[i]; + jerry_port_default_set_log_level ((jerry_log_level_t) (cli_state.arg[1][0] - '0')); + break; + } + case OPT_ABORT_ON_FAIL: + { + jerry_port_default_set_abort_on_fail (true); + break; + } + case OPT_NO_PROMPT: + { + no_prompt = true; + break; + } + case CLI_OPT_POSITIONAL: + { + file_names[files_counter++] = cli_state.arg[0]; + break; + } + case CLI_OPT_INCOMPLETE: + { + check_usage (false, argv[0], "Error: incomplete option: ", cli_state.arg[0]); + break; + } + case CLI_OPT_UNKNOWN: + default: + { + check_usage (false, argv[0], "Error: unrecognized option: ", cli_state.arg[0]); + break; + } } } -- cgit v1.2.3