|  | /* | 
|  | * Copyright (c) 2018 Nordic Semiconductor ASA | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  | #include <zephyr/shell/shell.h> | 
|  | #include <zephyr/sys/iterable_sections.h> | 
|  |  | 
|  | #include "shell_utils.h" | 
|  | #include "shell_help.h" | 
|  | #include "shell_ops.h" | 
|  | #include "shell_vt100.h" | 
|  |  | 
|  | #define SHELL_MSG_CMD_NOT_SUPPORTED	"Command not supported.\n" | 
|  | #define SHELL_HELP_COMMENT		"Ignore lines beginning with 'rem '" | 
|  | #define SHELL_HELP_RETVAL		"Print return value of most recent command" | 
|  | #define SHELL_HELP_CLEAR		"Clear screen." | 
|  | #define SHELL_HELP_BACKENDS		"List active shell backends.\n" | 
|  | #define SHELL_HELP_BACKSPACE_MODE	"Toggle backspace key mode.\n"	      \ | 
|  | "Some terminals are not sending separate escape code for "	      \ | 
|  | "backspace and delete button. This command forces shell to interpret" \ | 
|  | " delete key as backspace." | 
|  | #define SHELL_HELP_BACKSPACE_MODE_BACKSPACE	"Set different escape"	 \ | 
|  | " code for backspace and delete key." | 
|  | #define SHELL_HELP_BACKSPACE_MODE_DELETE	"Set the same escape"	 \ | 
|  | " code for backspace and delete key." | 
|  |  | 
|  | #define SHELL_HELP_COLORS		"Toggle colored syntax." | 
|  | #define SHELL_HELP_COLORS_OFF		"Disable colored syntax." | 
|  | #define SHELL_HELP_COLORS_ON		"Enable colored syntax." | 
|  | #define SHELL_HELP_VT100		"Toggle vt100 commands." | 
|  | #define SHELL_HELP_VT100_OFF		"Disable vt100 commands." | 
|  | #define SHELL_HELP_VT100_ON		"Enable vt100 commands." | 
|  | #define SHELL_HELP_PROMPT		"Toggle prompt." | 
|  | #define SHELL_HELP_PROMPT_OFF		"Disable prompt." | 
|  | #define SHELL_HELP_PROMPT_ON		"Enable prompt." | 
|  | #define SHELL_HELP_STATISTICS		"Shell statistics." | 
|  | #define SHELL_HELP_STATISTICS_SHOW	\ | 
|  | "Get shell statistics for the Logger module." | 
|  | #define SHELL_HELP_STATISTICS_RESET	\ | 
|  | "Reset shell statistics for the Logger module." | 
|  | #define SHELL_HELP_RESIZE						\ | 
|  | "Console gets terminal screen size or assumes default in case"	\ | 
|  | " the readout fails. It must be executed after each terminal"	\ | 
|  | " width change to ensure correct text display." | 
|  | #define SHELL_HELP_RESIZE_DEFAULT				\ | 
|  | "Assume 80 chars screen width and send this setting "	\ | 
|  | "to the terminal." | 
|  | #define SHELL_HELP_HISTORY	"Command history." | 
|  | #define SHELL_HELP_ECHO		"Toggle shell echo." | 
|  | #define SHELL_HELP_ECHO_ON	"Enable shell echo." | 
|  | #define SHELL_HELP_ECHO_OFF	\ | 
|  | "Disable shell echo. Editing keys and meta-keys are not handled" | 
|  |  | 
|  | #define SHELL_HELP_SELECT	"Selects new root command. In order for the " \ | 
|  | "command to be selected, it must meet the criteria:\n"		      \ | 
|  | " - it is a static command\n"					      \ | 
|  | " - it is not preceded by a dynamic command\n"			      \ | 
|  | " - it accepts arguments\n"					      \ | 
|  | "Return to the main command tree is done by pressing alt+r." | 
|  |  | 
|  | #define SHELL_HELP_SHELL		"Useful, not Unix-like shell commands." | 
|  | #define SHELL_HELP_HELP			"Prints help message." | 
|  |  | 
|  | #define SHELL_MSG_UNKNOWN_PARAMETER	" unknown parameter: " | 
|  |  | 
|  | #define SHELL_MAX_TERMINAL_SIZE		(250u) | 
|  |  | 
|  | /* 10 == {esc, [, 2, 5, 0, ;, 2, 5, 0, '\0'} */ | 
|  | #define SHELL_CURSOR_POSITION_BUFFER	(10u) | 
|  |  | 
|  | #define SHELL_DEFAULT_TERMINAL_WIDTH 80 | 
|  | #define SHELL_DEFAULT_TERMINAL_HEIGHT 24 | 
|  |  | 
|  | /* Function reads cursor position from terminal. */ | 
|  | static int cursor_position_get(const struct shell *sh, uint16_t *x, uint16_t *y) | 
|  | { | 
|  | uint16_t buff_idx = 0U; | 
|  | size_t cnt; | 
|  | char c = 0; | 
|  |  | 
|  | *x = 0U; | 
|  | *y = 0U; | 
|  |  | 
|  | memset(sh->ctx->temp_buff, 0, sizeof(sh->ctx->temp_buff)); | 
|  |  | 
|  | /* escape code asking terminal about its size */ | 
|  | static char const cmd_get_terminal_size[] = "\033[6n"; | 
|  |  | 
|  | z_shell_raw_fprintf(sh->fprintf_ctx, cmd_get_terminal_size); | 
|  |  | 
|  | /* fprintf buffer needs to be flushed to start sending prepared | 
|  | * escape code to the terminal. | 
|  | */ | 
|  | z_transport_buffer_flush(sh); | 
|  |  | 
|  | /* timeout for terminal response = ~1s */ | 
|  | for (uint16_t i = 0; i < 1000; i++) { | 
|  | do { | 
|  | (void)sh->iface->api->read(sh->iface, &c, | 
|  | sizeof(c), &cnt); | 
|  | if (cnt == 0) { | 
|  | k_busy_wait(1000); | 
|  | break; | 
|  | } | 
|  | if ((c != SHELL_VT100_ASCII_ESC) && | 
|  | (sh->ctx->temp_buff[0] != | 
|  | SHELL_VT100_ASCII_ESC)) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (c == 'R') { /* End of response from the terminal. */ | 
|  | sh->ctx->temp_buff[buff_idx] = '\0'; | 
|  | if (sh->ctx->temp_buff[1] != '[') { | 
|  | sh->ctx->temp_buff[0] = 0; | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | /* Index start position in the buffer where 'y' | 
|  | * is stored. | 
|  | */ | 
|  | buff_idx = 2U; | 
|  |  | 
|  | while (sh->ctx->temp_buff[buff_idx] != ';') { | 
|  | *y = *y * 10U + | 
|  | (sh->ctx->temp_buff[buff_idx++] - | 
|  | '0'); | 
|  | if (buff_idx >= | 
|  | CONFIG_SHELL_CMD_BUFF_SIZE) { | 
|  | return -EMSGSIZE; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (++buff_idx >= CONFIG_SHELL_CMD_BUFF_SIZE) { | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | while (sh->ctx->temp_buff[buff_idx] | 
|  | != '\0') { | 
|  | *x = *x * 10U + | 
|  | (sh->ctx->temp_buff[buff_idx++] - | 
|  | '0'); | 
|  |  | 
|  | if (buff_idx >= | 
|  | CONFIG_SHELL_CMD_BUFF_SIZE) { | 
|  | return -EMSGSIZE; | 
|  | } | 
|  | } | 
|  | /* horizontal cursor position */ | 
|  | if (*x > SHELL_MAX_TERMINAL_SIZE) { | 
|  | *x = SHELL_MAX_TERMINAL_SIZE; | 
|  | } | 
|  |  | 
|  | /* vertical cursor position */ | 
|  | if (*y > SHELL_MAX_TERMINAL_SIZE) { | 
|  | *y = SHELL_MAX_TERMINAL_SIZE; | 
|  | } | 
|  |  | 
|  | sh->ctx->temp_buff[0] = 0; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sh->ctx->temp_buff[buff_idx] = c; | 
|  |  | 
|  | if (++buff_idx > SHELL_CURSOR_POSITION_BUFFER - 1) { | 
|  | sh->ctx->temp_buff[0] = 0; | 
|  | /* data_buf[SHELL_CURSOR_POSITION_BUFFER - 1] | 
|  | * is reserved for '\0' | 
|  | */ | 
|  | return -ENOMEM; | 
|  | } | 
|  |  | 
|  | } while (cnt > 0); | 
|  | } | 
|  |  | 
|  | return -ETIMEDOUT; | 
|  | } | 
|  |  | 
|  | /* Function gets terminal width and height. */ | 
|  | static int terminal_size_get(const struct shell *sh) | 
|  | { | 
|  | uint16_t x; /* horizontal position */ | 
|  | uint16_t y; /* vertical position */ | 
|  | int ret_val = 0; | 
|  |  | 
|  | z_cursor_save(sh); | 
|  |  | 
|  | /* Assumption: terminal width and height < 999. */ | 
|  | /* Move to last column. */ | 
|  | z_shell_op_cursor_vert_move(sh, -SHELL_MAX_TERMINAL_SIZE); | 
|  | /* Move to last row. */ | 
|  | z_shell_op_cursor_horiz_move(sh, SHELL_MAX_TERMINAL_SIZE); | 
|  |  | 
|  | if (cursor_position_get(sh, &x, &y) == 0) { | 
|  | sh->ctx->vt100_ctx.cons.terminal_wid = x; | 
|  | sh->ctx->vt100_ctx.cons.terminal_hei = y; | 
|  | } else { | 
|  | ret_val = -ENOTSUP; | 
|  | } | 
|  |  | 
|  | z_cursor_restore(sh); | 
|  | return ret_val; | 
|  | } | 
|  |  | 
|  | static int cmd_comment(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(sh); | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_clear(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | Z_SHELL_VT100_CMD(sh, SHELL_VT100_CURSORHOME); | 
|  | Z_SHELL_VT100_CMD(sh, SHELL_VT100_CLEARSCREEN); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_backends(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | uint16_t cnt = 0; | 
|  |  | 
|  | shell_print(sh, "Active shell backends:"); | 
|  | STRUCT_SECTION_FOREACH(shell, obj) { | 
|  | shell_print(sh, "  %2d. :%s (%s)", cnt++, obj->ctx->prompt, obj->name); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_bacskpace_mode_backspace(const struct shell *sh, size_t argc, | 
|  | char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_mode_delete_set(sh, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_bacskpace_mode_delete(const struct shell *sh, size_t argc, | 
|  | char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_mode_delete_set(sh, true); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_colors_off(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_use_colors_set(sh, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_colors_on(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argv); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_use_colors_set(sh, true); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_vt100_off(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_use_vt100_set(sh, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_vt100_on(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argv); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_use_vt100_set(sh, true); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_prompt_off(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | shell_prompt_change(sh, ""); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_prompt_on(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argv); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | shell_prompt_change(sh, sh->default_prompt); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_echo_off(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_echo_set(sh, false); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_echo_on(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | z_flag_echo_set(sh, true); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_echo(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | if (argc == 2) { | 
|  | shell_error(sh, "%s:%s%s", argv[0], | 
|  | SHELL_MSG_UNKNOWN_PARAMETER, argv[1]); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | shell_print(sh, "Echo status: %s", | 
|  | z_flag_echo_get(sh) ? "on" : "off"); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_history(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | size_t i = 0; | 
|  | uint16_t len; | 
|  |  | 
|  | while (1) { | 
|  | z_shell_history_get(sh->history, true, | 
|  | sh->ctx->temp_buff, &len); | 
|  |  | 
|  | if (len) { | 
|  | shell_print(sh, "[%3d] %s", | 
|  | (int)i++, sh->ctx->temp_buff); | 
|  |  | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | sh->ctx->temp_buff[0] = '\0'; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_shell_stats_show(const struct shell *sh, size_t argc, | 
|  | char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | shell_print(sh, "Lost logs: %lu", sh->stats->log_lost_cnt); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_shell_stats_reset(const struct shell *sh, | 
|  | size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | sh->stats->log_lost_cnt = 0; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_resize_default(const struct shell *sh, | 
|  | size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | Z_SHELL_VT100_CMD(sh, SHELL_VT100_SETCOL_80); | 
|  | sh->ctx->vt100_ctx.cons.terminal_wid = SHELL_DEFAULT_TERMINAL_WIDTH; | 
|  | sh->ctx->vt100_ctx.cons.terminal_hei = SHELL_DEFAULT_TERMINAL_HEIGHT; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_resize(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | if (argc != 1) { | 
|  | shell_error(sh, "%s:%s%s", argv[0], | 
|  | SHELL_MSG_UNKNOWN_PARAMETER, argv[1]); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | err = terminal_size_get(sh); | 
|  | if (err != 0) { | 
|  | sh->ctx->vt100_ctx.cons.terminal_wid = | 
|  | CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH; | 
|  | sh->ctx->vt100_ctx.cons.terminal_hei = | 
|  | CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT; | 
|  | shell_warn(sh, "No response from the terminal, assumed 80x24" | 
|  | " screen size"); | 
|  | return -ENOEXEC; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static int cmd_get_retval(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | ARG_UNUSED(argc); | 
|  | ARG_UNUSED(argv); | 
|  |  | 
|  | shell_print(sh, "%d", shell_get_return_value(sh)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static bool no_args(const struct shell_static_entry *entry) | 
|  | { | 
|  | return (entry->args.mandatory == 1) && (entry->args.optional == 0); | 
|  | } | 
|  |  | 
|  | static int cmd_select(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | const struct shell_static_entry *candidate = NULL; | 
|  | struct shell_static_entry entry; | 
|  | size_t matching_argc; | 
|  |  | 
|  | argc--; | 
|  | argv = argv + 1; | 
|  | candidate = z_shell_get_last_command(sh->ctx->selected_cmd, | 
|  | argc, (const char **)argv, | 
|  | &matching_argc, &entry, true); | 
|  |  | 
|  | if ((candidate != NULL) && !no_args(candidate) | 
|  | && (argc == matching_argc)) { | 
|  | sh->ctx->selected_cmd = candidate; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | shell_error(sh, "Cannot select command"); | 
|  |  | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_colors, | 
|  | SHELL_COND_CMD_ARG(CONFIG_SHELL_VT100_COMMANDS, off, NULL, | 
|  | SHELL_HELP_COLORS_OFF, cmd_colors_off, 1, 0), | 
|  | SHELL_COND_CMD_ARG(CONFIG_SHELL_VT100_COMMANDS, on, NULL, | 
|  | SHELL_HELP_COLORS_ON, cmd_colors_on, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_vt100, | 
|  | SHELL_COND_CMD_ARG(CONFIG_SHELL_VT100_COMMANDS, off, NULL, | 
|  | SHELL_HELP_VT100_OFF, cmd_vt100_off, 1, 0), | 
|  | SHELL_COND_CMD_ARG(CONFIG_SHELL_VT100_COMMANDS, on, NULL, | 
|  | SHELL_HELP_VT100_ON, cmd_vt100_on, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_prompt, | 
|  | SHELL_CMD_ARG(off, NULL, SHELL_HELP_PROMPT_OFF, cmd_prompt_off, 1, 0), | 
|  | SHELL_CMD_ARG(on, NULL, SHELL_HELP_PROMPT_ON, cmd_prompt_on, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_echo, | 
|  | SHELL_CMD_ARG(off, NULL, SHELL_HELP_ECHO_OFF, cmd_echo_off, 1, 0), | 
|  | SHELL_CMD_ARG(on, NULL, SHELL_HELP_ECHO_ON, cmd_echo_on, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_shell_stats, | 
|  | SHELL_CMD_ARG(reset, NULL, SHELL_HELP_STATISTICS_RESET, | 
|  | cmd_shell_stats_reset, 1, 0), | 
|  | SHELL_CMD_ARG(show, NULL, SHELL_HELP_STATISTICS_SHOW, | 
|  | cmd_shell_stats_show, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_backspace_mode, | 
|  | SHELL_CMD_ARG(backspace, NULL, SHELL_HELP_BACKSPACE_MODE_BACKSPACE, | 
|  | cmd_bacskpace_mode_backspace, 1, 0), | 
|  | SHELL_CMD_ARG(delete, NULL, SHELL_HELP_BACKSPACE_MODE_DELETE, | 
|  | cmd_bacskpace_mode_delete, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_shell, | 
|  | SHELL_CMD_ARG(backends, NULL, SHELL_HELP_BACKENDS, cmd_backends, 1, 0), | 
|  | SHELL_CMD(backspace_mode, &m_sub_backspace_mode, | 
|  | SHELL_HELP_BACKSPACE_MODE, NULL), | 
|  | SHELL_COND_CMD(CONFIG_SHELL_VT100_COMMANDS, colors, &m_sub_colors, | 
|  | SHELL_HELP_COLORS, NULL), | 
|  | SHELL_COND_CMD(CONFIG_SHELL_VT100_COMMANDS, vt100, &m_sub_vt100, | 
|  | SHELL_HELP_VT100, NULL), | 
|  | SHELL_CMD(prompt, &m_sub_prompt, SHELL_HELP_PROMPT, NULL), | 
|  | SHELL_CMD_ARG(echo, &m_sub_echo, SHELL_HELP_ECHO, cmd_echo, 1, 1), | 
|  | SHELL_COND_CMD(CONFIG_SHELL_STATS, stats, &m_sub_shell_stats, | 
|  | SHELL_HELP_STATISTICS, NULL), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(m_sub_resize, | 
|  | SHELL_CMD_ARG(default, NULL, SHELL_HELP_RESIZE_DEFAULT, | 
|  | cmd_resize_default, 1, 0), | 
|  | SHELL_SUBCMD_SET_END | 
|  | ); | 
|  |  | 
|  | SHELL_COND_CMD_REGISTER(CONFIG_SHELL_VT100_COMMANDS, rem, NULL, | 
|  | SHELL_HELP_COMMENT, cmd_comment); | 
|  | SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_VT100_COMMANDS, clear, NULL, | 
|  | SHELL_HELP_CLEAR, cmd_clear, 1, 0); | 
|  | SHELL_CMD_REGISTER(shell, &m_sub_shell, SHELL_HELP_SHELL, NULL); | 
|  | SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_HISTORY, history, NULL, | 
|  | SHELL_HELP_HISTORY, cmd_history, 1, 0); | 
|  | SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_CMDS_RESIZE, resize, &m_sub_resize, | 
|  | SHELL_HELP_RESIZE, cmd_resize, 1, 1); | 
|  | SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_CMDS_SELECT, select, NULL, | 
|  | SHELL_HELP_SELECT, cmd_select, 2, | 
|  | SHELL_OPT_ARG_CHECK_SKIP); | 
|  | SHELL_COND_CMD_ARG_REGISTER(CONFIG_SHELL_CMDS_RETURN_VALUE, retval, NULL, | 
|  | SHELL_HELP_RETVAL, cmd_get_retval, 1, 0); |