shell: add getopt library support

This functionality is is enabled by setting CONFIG_SHELL_GETOPT.
It is not active by default.

User can call following functions inside command handlers:
 - shell_getopt - getopt function based on freebsd implementation
 - shell_getopt_status_get - returns getopt status

Beware when getopt functionality is enabled shell will not parse
command handler to look for "-h" or "--help" options and print
help message automatically.

Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@nordicsemi.no>
This commit is contained in:
Jakub Rzeszutko 2021-01-15 14:04:21 +01:00 committed by Anas Nashif
commit 7e46765153
6 changed files with 124 additions and 1 deletions

View file

@ -16,6 +16,10 @@
#include <logging/log.h> #include <logging/log.h>
#include <sys/util.h> #include <sys/util.h>
#if defined CONFIG_SHELL_GETOPT
#include <shell/shell_getopt.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -67,6 +71,7 @@ extern "C" {
* @{ * @{
*/ */
struct getopt_state;
struct shell_static_entry; struct shell_static_entry;
/** /**
@ -649,6 +654,11 @@ struct shell_ctx {
/*!< VT100 color and cursor position, terminal width.*/ /*!< VT100 color and cursor position, terminal width.*/
struct shell_vt100_ctx vt100_ctx; struct shell_vt100_ctx vt100_ctx;
#if defined CONFIG_SHELL_GETOPT
/*!< getopt context for a shell backend. */
struct getopt_state getopt_state;
#endif
uint16_t cmd_buff_len; /*!< Command length.*/ uint16_t cmd_buff_len; /*!< Command length.*/
uint16_t cmd_buff_pos; /*!< Command buffer cursor position.*/ uint16_t cmd_buff_pos; /*!< Command buffer cursor position.*/
@ -958,6 +968,40 @@ void shell_help(const struct shell *shell);
/* @brief Command's help has been printed */ /* @brief Command's help has been printed */
#define SHELL_CMD_HELP_PRINTED (1) #define SHELL_CMD_HELP_PRINTED (1)
#if defined CONFIG_SHELL_GETOPT
/**
* @brief Parses the command-line arguments.
*
* It is based on FreeBSD implementation.
*
* @param[in] shell Pointer to the shell instance.
* @param[in] argc Arguments count.
* @param[in] argv Arguments.
* @param[in] ostr String containing the legitimate option characters.
*
* @return If an option was successfully found, function returns
* the option character.
* @return If options have been detected that is not in @p ostr
* function will return '?'.
* If function encounters an option with a missing
* argument, then the return value depends on the first
* character in optstring: if it is ':', then ':' is
* returned; otherwise '?' is returned.
* @return -1 If all options have been parsed.
*/
int shell_getopt(const struct shell *shell, int argc, char *const argv[],
const char *ostr);
/**
* @brief Returns shell_getopt state.
*
* @param[in] shell Pointer to the shell instance.
*
* @return Pointer to struct getopt_state.
*/
struct getopt_state *shell_getopt_state_get(const struct shell *shell);
#endif /* CONFIG_SHELL_GETOPT */
/** @brief Execute command. /** @brief Execute command.
* *
* Pass command line to shell to execute. * Pass command line to shell to execute.
@ -973,7 +1017,7 @@ void shell_help(const struct shell *shell);
* @option{CONFIG_SHELL_BACKEND_DUMMY} option is enabled. * @option{CONFIG_SHELL_BACKEND_DUMMY} option is enabled.
* @param[in] cmd Command to be executed. * @param[in] cmd Command to be executed.
* *
* @returns Result of the execution * @return Result of the execution
*/ */
int shell_execute_cmd(const struct shell *shell, const char *cmd); int shell_execute_cmd(const struct shell *shell, const char *cmd);

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SHELL_GETOPT_H__
#define SHELL_GETOPT_H__
#include <getopt.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Initializing shell getopt module.
*
* @param[in] shell Pointer to the shell instance.
*/
void z_shell_getopt_init(struct getopt_state *state);
#ifdef __cplusplus
}
#endif
#endif /* SHELL_GETOPT_H__ */

View file

@ -35,6 +35,11 @@ zephyr_sources_ifdef(
shell_help.c shell_help.c
) )
zephyr_sources_ifdef(
CONFIG_SHELL_GETOPT
shell_getopt.c
)
zephyr_sources_ifdef( zephyr_sources_ifdef(
CONFIG_SHELL_CMDS CONFIG_SHELL_CMDS
shell_cmds.c shell_cmds.c

View file

@ -109,6 +109,12 @@ config SHELL_VT100_COLORS
help help
If enabled VT100 colors are used in shell (e.g. print errors in red). If enabled VT100 colors are used in shell (e.g. print errors in red).
config SHELL_GETOPT
bool "Enable getopt support"
select GETOPT
help
Enables getopt support in the shell.
config SHELL_METAKEYS config SHELL_METAKEYS
bool "Enable metakeys" bool "Enable metakeys"
default y if !SHELL_MINIMAL default y if !SHELL_MINIMAL

View file

@ -533,6 +533,10 @@ static int exec_cmd(const struct shell *shell, size_t argc, const char **argv,
} }
if (!ret_val) { if (!ret_val) {
#if CONFIG_SHELL_GETOPT
z_shell_getopt_init(&shell->ctx->getopt_state);
#endif
z_flag_cmd_ctx_set(shell, true); z_flag_cmd_ctx_set(shell, true);
/* Unlock thread mutex in case command would like to borrow /* Unlock thread mutex in case command would like to borrow
* shell context to other thread to avoid mutex deadlock. * shell context to other thread to avoid mutex deadlock.

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <shell/shell.h>
#include <shell/shell_getopt.h>
void z_shell_getopt_init(struct getopt_state *state)
{
getopt_init(state);
}
int shell_getopt(const struct shell *shell, int argc, char *const argv[],
const char *ostr)
{
if (!IS_ENABLED(CONFIG_SHELL_GETOPT)) {
return 0;
}
__ASSERT_NO_MSG(shell);
return getopt(&shell->ctx->getopt_state, argc, argv, ostr);
}
struct getopt_state *shell_getopt_state_get(const struct shell *shell)
{
if (!IS_ENABLED(CONFIG_SHELL_GETOPT)) {
return NULL;
}
__ASSERT_NO_MSG(shell);
return &shell->ctx->getopt_state;
}