shell: Add APIs to set number of arguments
This allows the shell core to perform precheck before calling the handler which then can assume the number of arguments is correct. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
f70f323193
commit
a89690d10f
3 changed files with 120 additions and 26 deletions
|
@ -78,7 +78,10 @@ Use the following macros for adding shell commands:
|
||||||
|
|
||||||
* :c:macro:`SHELL_CMD_REGISTER` - Create root command. All root commands must
|
* :c:macro:`SHELL_CMD_REGISTER` - Create root command. All root commands must
|
||||||
have different name.
|
have different name.
|
||||||
|
* :c:macro:`SHELL_CMD_ARG_REGISTER` - Create root command with arguments.
|
||||||
|
All root commands must have different name.
|
||||||
* :c:macro:`SHELL_CMD` - Initialize a command.
|
* :c:macro:`SHELL_CMD` - Initialize a command.
|
||||||
|
* :c:macro:`SHELL_CMD_ARG` - Initialize a command with arguments.
|
||||||
* :c:macro:`SHELL_CREATE_STATIC_SUBCMD_SET` - Create a static subcommands
|
* :c:macro:`SHELL_CREATE_STATIC_SUBCMD_SET` - Create a static subcommands
|
||||||
array.
|
array.
|
||||||
* :c:macro:`SHELL_SUBCMD_SET_END` - shall be placed as last in
|
* :c:macro:`SHELL_SUBCMD_SET_END` - shall be placed as last in
|
||||||
|
|
|
@ -71,6 +71,22 @@ struct shell_cmd_entry {
|
||||||
|
|
||||||
struct shell;
|
struct shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes a shell command arguments
|
||||||
|
*
|
||||||
|
* @param[in] _mandatory Number of mandatory arguments.
|
||||||
|
* @param[in] _optional Number of optional arguments.
|
||||||
|
*/
|
||||||
|
#define SHELL_ARG(_mandatory, _optional) { \
|
||||||
|
.mandatory = _mandatory, \
|
||||||
|
.optional = _optional, \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct shell_static_args {
|
||||||
|
u8_t mandatory; /*!< Number of mandatory arguments. */
|
||||||
|
u8_t optional; /*!< Number of optional arguments. */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Shell command handler prototype.
|
* @brief Shell command handler prototype.
|
||||||
*/
|
*/
|
||||||
|
@ -85,10 +101,37 @@ struct shell_static_entry {
|
||||||
const char *help; /*!< Command help string. */
|
const char *help; /*!< Command help string. */
|
||||||
const struct shell_cmd_entry *subcmd; /*!< Pointer to subcommand. */
|
const struct shell_cmd_entry *subcmd; /*!< Pointer to subcommand. */
|
||||||
shell_cmd_handler handler; /*!< Command handler. */
|
shell_cmd_handler handler; /*!< Command handler. */
|
||||||
|
const struct shell_static_args *args; /*!< Command arguments. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Macro for defining and adding a root command (level 0).
|
* @brief Macro for defining and adding a root command (level 0) with
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* @note Each root command shall have unique syntax.
|
||||||
|
*
|
||||||
|
* @param[in] syntax Command syntax (for example: history).
|
||||||
|
* @param[in] subcmd Pointer to a subcommands array.
|
||||||
|
* @param[in] help Pointer to a command help string.
|
||||||
|
* @param[in] handler Pointer to a function handler.
|
||||||
|
* @param[in] mandatory Number of mandatory arguments.
|
||||||
|
* @param[in] optional Number of optional arguments.
|
||||||
|
*/
|
||||||
|
#define SHELL_CMD_ARG_REGISTER(syntax, subcmd, help, handler, \
|
||||||
|
mandatory, optional) \
|
||||||
|
static const struct shell_static_entry UTIL_CAT(shell_, syntax) = \
|
||||||
|
SHELL_CMD_ARG(syntax, subcmd, help, handler, mandatory, optional); \
|
||||||
|
static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \
|
||||||
|
__attribute__ ((section("." \
|
||||||
|
STRINGIFY(UTIL_CAT(shell_root_cmd_, syntax))))) \
|
||||||
|
__attribute__((used)) = { \
|
||||||
|
.is_dynamic = false, \
|
||||||
|
.u.entry = &UTIL_CAT(shell_, syntax) \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Macro for defining and adding a root command (level 0) with
|
||||||
|
* arguments.
|
||||||
*
|
*
|
||||||
* @note Each root command shall have unique syntax.
|
* @note Each root command shall have unique syntax.
|
||||||
*
|
*
|
||||||
|
@ -97,7 +140,7 @@ struct shell_static_entry {
|
||||||
* @param[in] help Pointer to a command help string.
|
* @param[in] help Pointer to a command help string.
|
||||||
* @param[in] handler Pointer to a function handler.
|
* @param[in] handler Pointer to a function handler.
|
||||||
*/
|
*/
|
||||||
#define SHELL_CMD_REGISTER(syntax, subcmd, help, handler) \
|
#define SHELL_CMD_REGISTER(syntax, subcmd, help, handler) \
|
||||||
static const struct shell_static_entry UTIL_CAT(shell_, syntax) = \
|
static const struct shell_static_entry UTIL_CAT(shell_, syntax) = \
|
||||||
SHELL_CMD(syntax, subcmd, help, handler); \
|
SHELL_CMD(syntax, subcmd, help, handler); \
|
||||||
static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \
|
static const struct shell_cmd_entry UTIL_CAT(shell_cmd_, syntax) \
|
||||||
|
@ -140,6 +183,26 @@ struct shell_static_entry {
|
||||||
.u.dynamic_get = get \
|
.u.dynamic_get = get \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes a shell command with arguments
|
||||||
|
*
|
||||||
|
* @param[in] _syntax Command syntax (for example: history).
|
||||||
|
* @param[in] _subcmd Pointer to a subcommands array.
|
||||||
|
* @param[in] _help Pointer to a command help string.
|
||||||
|
* @param[in] _handler Pointer to a function handler.
|
||||||
|
* @param[in] _mandatory Number of mandatory arguments.
|
||||||
|
* @param[in] _optional Number of optional arguments.
|
||||||
|
*/
|
||||||
|
#define SHELL_CMD_ARG(_syntax, _subcmd, _help, _handler, \
|
||||||
|
_mandatory, _optional) { \
|
||||||
|
.syntax = (const char *)STRINGIFY(_syntax), \
|
||||||
|
.subcmd = _subcmd, \
|
||||||
|
.help = (const char *)_help, \
|
||||||
|
.handler = _handler, \
|
||||||
|
.args = _mandatory ? \
|
||||||
|
(&(struct shell_static_args) SHELL_ARG(_mandatory, _optional)) : NULL\
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes a shell command.
|
* @brief Initializes a shell command.
|
||||||
*
|
*
|
||||||
|
@ -148,12 +211,9 @@ struct shell_static_entry {
|
||||||
* @param[in] _help Pointer to a command help string.
|
* @param[in] _help Pointer to a command help string.
|
||||||
* @param[in] _handler Pointer to a function handler.
|
* @param[in] _handler Pointer to a function handler.
|
||||||
*/
|
*/
|
||||||
#define SHELL_CMD(_syntax, _subcmd, _help, _handler) { \
|
#define SHELL_CMD(_syntax, _subcmd, _help, _handler) \
|
||||||
.syntax = (const char *)STRINGIFY(_syntax), \
|
SHELL_CMD_ARG(_syntax, _subcmd, _help, _handler, 0, 0)
|
||||||
.subcmd = _subcmd, \
|
|
||||||
.help = (const char *)_help, \
|
|
||||||
.handler = _handler \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal @brief Internal shell state in response to data received from the
|
* @internal @brief Internal shell state in response to data received from the
|
||||||
|
|
|
@ -946,6 +946,53 @@ static const struct shell_cmd_entry *root_cmd_find(const char *syntax)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int exec_cmd(const struct shell *shell, size_t argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret_val = 0;
|
||||||
|
|
||||||
|
if (shell->ctx->active_cmd.handler == NULL) {
|
||||||
|
if (shell->ctx->active_cmd.help) {
|
||||||
|
shell_help_print(shell, NULL, 0);
|
||||||
|
} else {
|
||||||
|
shell_fprintf(shell, SHELL_ERROR,
|
||||||
|
SHELL_MSG_SPECIFY_SUBCOMMAND);
|
||||||
|
ret_val = -ENOEXEC;
|
||||||
|
goto clear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shell->ctx->active_cmd.args) {
|
||||||
|
const struct shell_static_args *args;
|
||||||
|
|
||||||
|
args = shell->ctx->active_cmd.args;
|
||||||
|
|
||||||
|
if (args->optional > 0) {
|
||||||
|
/* Check if argc is within allowed range */
|
||||||
|
ret_val = shell_cmd_precheck(shell,
|
||||||
|
((argc >= args->mandatory)
|
||||||
|
&&
|
||||||
|
(argc <= args->mandatory +
|
||||||
|
args->optional)),
|
||||||
|
NULL, 0);
|
||||||
|
} else {
|
||||||
|
/* Perform exact match if there are no optional args */
|
||||||
|
ret_val = shell_cmd_precheck(shell,
|
||||||
|
(args->mandatory == argc),
|
||||||
|
NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret_val) {
|
||||||
|
ret_val = shell->ctx->active_cmd.handler(shell, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear:
|
||||||
|
help_flag_clear(shell);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Function is analyzing the command buffer to find matching commands. Next, it
|
/* Function is analyzing the command buffer to find matching commands. Next, it
|
||||||
* invokes the last recognized command which has a handler and passes the rest
|
* invokes the last recognized command which has a handler and passes the rest
|
||||||
* of command buffer as arguments.
|
* of command buffer as arguments.
|
||||||
|
@ -959,7 +1006,6 @@ static int shell_execute(const struct shell *shell)
|
||||||
size_t cmd_lvl = SHELL_CMD_ROOT_LVL;
|
size_t cmd_lvl = SHELL_CMD_ROOT_LVL;
|
||||||
size_t cmd_with_handler_lvl = 0;
|
size_t cmd_with_handler_lvl = 0;
|
||||||
bool wildcard_found = false;
|
bool wildcard_found = false;
|
||||||
int ret_val = 0;
|
|
||||||
size_t cmd_idx;
|
size_t cmd_idx;
|
||||||
size_t argc;
|
size_t argc;
|
||||||
char quote;
|
char quote;
|
||||||
|
@ -1102,23 +1148,8 @@ static int shell_execute(const struct shell *shell)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Executing the deepest found handler. */
|
/* Executing the deepest found handler. */
|
||||||
if (shell->ctx->active_cmd.handler == NULL) {
|
return exec_cmd(shell, argc - cmd_with_handler_lvl,
|
||||||
if (shell->ctx->active_cmd.help) {
|
&argv[cmd_with_handler_lvl]);
|
||||||
shell_help_print(shell, NULL, 0);
|
|
||||||
} else {
|
|
||||||
shell_fprintf(shell, SHELL_ERROR,
|
|
||||||
SHELL_MSG_SPECIFY_SUBCOMMAND);
|
|
||||||
ret_val = -ENOEXEC;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret_val = shell->ctx->active_cmd.handler(shell,
|
|
||||||
argc - cmd_with_handler_lvl,
|
|
||||||
&argv[cmd_with_handler_lvl]);
|
|
||||||
}
|
|
||||||
|
|
||||||
help_flag_clear(shell);
|
|
||||||
|
|
||||||
return ret_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shell_transport_evt_handler(enum shell_transport_evt evt_type,
|
static void shell_transport_evt_handler(enum shell_transport_evt evt_type,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue