aboutsummaryrefslogtreecommitdiff
path: root/jerry-main
diff options
context:
space:
mode:
authorAkos Kiss <akiss@inf.u-szeged.hu>2017-05-16 10:29:27 +0200
committerGitHub <noreply@github.com>2017-05-16 10:29:27 +0200
commit7837440cbb2d6ddfb634ca2c277a96935c46f45d (patch)
treebbf8511d1a02a1bd9ece7cb1a10953c0e439c2af /jerry-main
parent1501699f48711b47b624a3d1cd1c408032d4acf7 (diff)
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
Diffstat (limited to 'jerry-main')
-rw-r--r--jerry-main/CMakeLists.txt6
-rw-r--r--jerry-main/cli.c429
-rw-r--r--jerry-main/cli.h151
-rw-r--r--jerry-main/main-unix.c306
4 files changed, 755 insertions, 137 deletions
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 <stdio.h>
+#include <string.h>
+
+#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 <string.h>
+
+/*
+ * 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
*
@@ -324,6 +292,68 @@ register_js_function (const char *name_p, /**< name of the function */
} /* 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;
+ }
}
}