shell: Redesign internal command handling
Make the internal commands (exit, select & help) as any other commands, so that e.g. "help help" works as expected. Also redesign the way commands are looked up to avoid duplicate lookups. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
329a6628e4
commit
22b5ff9b29
1 changed files with 84 additions and 110 deletions
|
@ -150,60 +150,15 @@ static int get_destination_module(const char *module_str)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For a specific command: argv[0] = module name, argv[1] = command name
|
static int show_cmd_help(const struct shell_cmd *cmd, bool full)
|
||||||
* If a default module was selected: argv[0] = command name
|
|
||||||
*/
|
|
||||||
static const char *get_command_and_module(char *argv[], int *module)
|
|
||||||
{
|
{
|
||||||
*module = -1;
|
printk("Usage: %s %s\n", cmd->cmd_name, cmd->help ? cmd->help : "");
|
||||||
|
|
||||||
if (default_module == -1) {
|
if (full && cmd->desc) {
|
||||||
if (!argv[1] || argv[1][0] == '\0') {
|
printk("%s\n", cmd->desc);
|
||||||
printk("Unrecognized command: %s\n", argv[0]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*module = get_destination_module(argv[0]);
|
|
||||||
if (*module == -1) {
|
|
||||||
printk("Illegal module %s\n", argv[0]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return argv[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*module = default_module;
|
return 0;
|
||||||
return argv[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int show_cmd_help(char *argv[], bool full)
|
|
||||||
{
|
|
||||||
const char *command = NULL;
|
|
||||||
int module = -1;
|
|
||||||
const struct shell_module *shell_module;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
command = get_command_and_module(argv, &module);
|
|
||||||
if ((module == -1) || (command == NULL)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
shell_module = &__shell_cmd_start[module];
|
|
||||||
for (i = 0; shell_module->commands[i].cmd_name; i++) {
|
|
||||||
if (!strcmp(command, shell_module->commands[i].cmd_name)) {
|
|
||||||
printk("Usage: %s %s\n",
|
|
||||||
shell_module->commands[i].cmd_name,
|
|
||||||
shell_module->commands[i].help ?
|
|
||||||
shell_module->commands[i].help : "");
|
|
||||||
if (full && shell_module->commands[i].desc) {
|
|
||||||
printk("%s\n", shell_module->commands[i].desc);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printk("Unrecognized command: %s\n", argv[0]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_module_commands(const int module)
|
static void print_module_commands(const int module)
|
||||||
|
@ -221,27 +176,65 @@ static void print_module_commands(const int module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int show_help(int argc, char *argv[])
|
static const struct shell_cmd *get_cmd(const struct shell_cmd cmds[],
|
||||||
|
const char *cmd_str)
|
||||||
{
|
{
|
||||||
int module;
|
int i;
|
||||||
|
|
||||||
/* help per command */
|
for (i = 0; cmds[i].cmd_name; i++) {
|
||||||
if ((argc > 2) || ((default_module != -1) && (argc == 2))) {
|
if (!strcmp(cmd_str, cmds[i].cmd_name)) {
|
||||||
return show_cmd_help(&argv[1], true);
|
return &cmds[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* help per module */
|
return NULL;
|
||||||
if ((argc == 2) || ((default_module != -1) && (argc == 1))) {
|
}
|
||||||
if (default_module == -1) {
|
|
||||||
module = get_destination_module(argv[1]);
|
static const struct shell_cmd *get_mod_cmd(int module, const char *cmd_str)
|
||||||
if (module == -1) {
|
{
|
||||||
printk("Illegal module %s\n", argv[1]);
|
return get_cmd(__shell_cmd_start[module].commands, cmd_str);
|
||||||
return -EINVAL;
|
}
|
||||||
|
|
||||||
|
static int cmd_help(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int module = default_module;
|
||||||
|
|
||||||
|
/* help per command */
|
||||||
|
if (argc > 1) {
|
||||||
|
const struct shell_cmd *cmd;
|
||||||
|
const char *cmd_str;
|
||||||
|
|
||||||
|
module = get_destination_module(argv[1]);
|
||||||
|
if (module != -1) {
|
||||||
|
if (argc == 2) {
|
||||||
|
goto module_help;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd_str = argv[2];
|
||||||
|
} else if (argc > 2) {
|
||||||
|
cmd_str = argv[1];
|
||||||
} else {
|
} else {
|
||||||
module = default_module;
|
printk("Unknown module or command\n");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (module == -1) {
|
||||||
|
printk("No help found for '%s'\n", cmd_str);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = get_mod_cmd(module, cmd_str);
|
||||||
|
if (cmd) {
|
||||||
|
return show_cmd_help(cmd, true);
|
||||||
|
} else {
|
||||||
|
printk("Unknown command '%s'\n", cmd_str);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module_help:
|
||||||
|
/* help per module */
|
||||||
|
if (module != -1) {
|
||||||
print_module_commands(module);
|
print_module_commands(module);
|
||||||
printk("\nEnter 'exit' to leave current module.\n");
|
printk("\nEnter 'exit' to leave current module.\n");
|
||||||
} else { /* help for all entities */
|
} else { /* help for all entities */
|
||||||
|
@ -280,7 +273,7 @@ static int set_default_module(const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int select_module(int argc, char *argv[])
|
static int cmd_select(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
default_module = -1;
|
default_module = -1;
|
||||||
|
@ -290,7 +283,7 @@ static int select_module(int argc, char *argv[])
|
||||||
return set_default_module(argv[1]);
|
return set_default_module(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exit_module(int argc, char *argv[])
|
static int cmd_exit(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
default_module = -1;
|
default_module = -1;
|
||||||
|
@ -299,42 +292,22 @@ static int exit_module(int argc, char *argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static shell_cmd_function_t get_cb(int module, const char *command)
|
static const struct shell_cmd *get_internal(const char *command)
|
||||||
{
|
{
|
||||||
const struct shell_module *shell_module;
|
static const struct shell_cmd internal_commands[] = {
|
||||||
int i;
|
{ "help", cmd_help, "[command]" },
|
||||||
|
{ "select", cmd_select, "[module]" },
|
||||||
|
{ "exit", cmd_exit, NULL },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
|
||||||
shell_module = &__shell_cmd_start[module];
|
return get_cmd(internal_commands, command);
|
||||||
for (i = 0; shell_module->commands[i].cmd_name; i++) {
|
|
||||||
if (!strcmp(command, shell_module->commands[i].cmd_name)) {
|
|
||||||
return shell_module->commands[i].cb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static shell_cmd_function_t get_internal(const char *command)
|
|
||||||
{
|
|
||||||
if (!strcmp(command, "help")) {
|
|
||||||
return show_help;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(command, "select")) {
|
|
||||||
return select_module;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(command, "exit")) {
|
|
||||||
return exit_module;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int shell_exec(char *line)
|
int shell_exec(char *line)
|
||||||
{
|
{
|
||||||
char *argv[ARGC_MAX + 1], **argv_start = argv;
|
char *argv[ARGC_MAX + 1], **argv_start = argv;
|
||||||
shell_cmd_function_t cb;
|
const struct shell_cmd *cmd;
|
||||||
int argc, err;
|
int argc, err;
|
||||||
|
|
||||||
argc = line2argv(line, argv, ARRAY_SIZE(argv));
|
argc = line2argv(line, argv, ARRAY_SIZE(argv));
|
||||||
|
@ -342,9 +315,9 @@ int shell_exec(char *line)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb = get_internal(argv[0]);
|
cmd = get_internal(argv[0]);
|
||||||
if (cb) {
|
if (cmd) {
|
||||||
return cb(argc, argv_start);
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 1 && default_module == -1) {
|
if (argc == 1 && default_module == -1) {
|
||||||
|
@ -353,35 +326,36 @@ int shell_exec(char *line)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (default_module != -1) {
|
if (default_module != -1) {
|
||||||
cb = get_cb(default_module, argv[0]);
|
cmd = get_mod_cmd(default_module, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cb && argc > 1) {
|
if (!cmd && argc > 1) {
|
||||||
int module;
|
int module;
|
||||||
|
|
||||||
module = get_destination_module(argv[0]);
|
module = get_destination_module(argv[0]);
|
||||||
if (module != -1) {
|
if (module != -1) {
|
||||||
cb = get_cb(module, argv[1]);
|
cmd = get_mod_cmd(module, argv[1]);
|
||||||
if (cb) {
|
if (cmd) {
|
||||||
argc--;
|
argc--;
|
||||||
argv_start++;
|
argv_start++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cb) {
|
if (!cmd) {
|
||||||
if (app_cmd_handler != NULL) {
|
if (app_cmd_handler) {
|
||||||
cb = app_cmd_handler;
|
return app_cmd_handler(argc, argv);
|
||||||
} else {
|
|
||||||
printk("Unrecognized command: %s\n", argv[0]);
|
|
||||||
printk("Type 'help' for list of available commands\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("Unrecognized command: %s\n", argv[0]);
|
||||||
|
printk("Type 'help' for list of available commands\n");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cb(argc, argv_start);
|
done:
|
||||||
|
err = cmd->cb(argc, argv_start);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
show_cmd_help(argv, false);
|
show_cmd_help(cmd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue