shell: reimplementation to improve command handling and to support multiple serial interfaces

tags/0.1.0
S.J.R. van Schaik 7 years ago
parent f04041ae96
commit fa16f60b06
  1. 29
      include/shell.h
  2. 58
      source/main.c
  3. 8
      source/shell/args.c
  4. 97
      source/shell/cmd.c

@ -1,16 +1,25 @@
#pragma once #pragma once
size_t count_args(char *line);
char **parse_args(char *line, size_t *argc);
struct cmd { struct cmd {
const char *key; const char *cmd;
void (* exec)(const char *line); const char *desc;
void (* exec)(FILE *out, const char **argv, size_t argc);
};
struct shell {
char line[128];
struct cmd *cmds;
const char *prompt;
struct usart_console *con;
FILE *fp;
}; };
void do_flash_cmd(const char *line); size_t count_args(const char *line);
void do_ftl_cmd(const char *line); char **parse_args(const char *line, size_t *argc);
void do_mufs_cmd(const char *line);
void cmd_exec(struct cmd *cmds, FILE *out, const char **argv, size_t argc);
void cmd_parse(struct cmd *cmds, FILE *out, const char *line);
void cmd_exec(struct cmd *cmds, const char *line); int shell_init(struct shell *shell, struct cmd *cmds,
void cmd_loop(const char *s); struct usart_console *con, const char *prompt);
int shell_parse(struct shell *shell);

@ -10,51 +10,43 @@
#include <libopencm3/stm32/usart.h> #include <libopencm3/stm32/usart.h>
struct usart_console *user_con, *admin_con; struct usart_console *user_con, *admin_con;
FILE *user_io, *admin_io; struct shell user_shell, admin_shell;
char user_line[128];
char admin_line[128]; static void do_echo(FILE *out, const char **argv, size_t argc)
{
if (argc < 1)
return;
fprintf(out, "%s\n", argv[0]);
}
struct cmd cmds[] = {
{ "echo", "", do_echo },
{ NULL, NULL, NULL },
};
int main(void) int main(void)
{ {
char **argv; FILE *fp;
size_t argc, i;
rcc_init(); rcc_init();
gpio_init(); gpio_init();
user_con = console_init(0); user_con = console_init(0);
admin_con = console_init(1); admin_con = console_init(1);
user_io = console_to_fp(user_con);
admin_io = console_to_fp(admin_con);
fprintf(user_io, "TBM-dev (built on " __DATE__ ")\n"); fp = console_to_fp(user_con);
fprintf(admin_io, "TBM-dev (built on " __DATE__ ")\n"); fprintf(fp, "TBM-dev (built on " __DATE__ ")\n");
fprintf(admin_io, "Welcome to the administrative interface.\n");
fprintf(user_io, "tbm # ");
while (1) { fp = console_to_fp(admin_con);
if (console_getline(user_con, user_line, 128) == 0) { fprintf(fp, "TBM-dev (built on " __DATE__ ")\n");
argv = parse_args(user_line, &argc);
for (i = 0; i < argc; ++i) {
fprintf(user_io, "user: %s\n", argv[i]);
fprintf(admin_io, "user: %s\n", argv[i]);
}
free(argv);
*user_line = '\0';
}
if (console_getline(admin_con, admin_line, 128) == 0) { shell_init(&user_shell, cmds, user_con, "tbm $");
argv = parse_args(admin_line, &argc); shell_init(&admin_shell, cmds, admin_con, "tbm #");
for (i = 0; i < argc; ++i) { while (1) {
fprintf(admin_io, "admin: %s\n", argv[i]); shell_parse(&user_shell);
fprintf(user_io, "admin: %s\n", argv[i]); shell_parse(&admin_shell);
}
free(argv);
*admin_line = '\0';
}
} }
return 0; return 0;

@ -4,9 +4,9 @@
#include <shell.h> #include <shell.h>
size_t count_args(char *line) size_t count_args(const char *line)
{ {
char *p = line; const char *p = line;
size_t n = 0; size_t n = 0;
while (*p != '\0') { while (*p != '\0') {
@ -29,11 +29,11 @@ size_t count_args(char *line)
return n; return n;
} }
char **parse_args(char *line, size_t *argc) char **parse_args(const char *line, size_t *argc)
{ {
char **argv; char **argv;
char **arg; char **arg;
char *p = line; const char *p = line;
char *s; char *s;
size_t n; size_t n;

@ -2,78 +2,67 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <console.h>
#include <shell.h> #include <shell.h>
static int should_exit = 0; void cmd_exec(struct cmd *cmds, FILE *out, const char **argv, size_t argc)
static char buf[128];
static void do_exit(const char *s);
struct cmd main_cmds[] = {
{ "exit", do_exit },
{ "quit", do_exit },
{ "flash", do_flash_cmd },
{ "ftl", do_ftl_cmd },
{ "mufs", do_mufs_cmd },
{ NULL, NULL },
};
static void do_exit(const char *s)
{ {
(void)s; struct cmd *cmd;
should_exit = 1; if (argc < 1)
return;
for (cmd = cmds; cmd->cmd; ++cmd) {
if (strcmp(cmd->cmd, argv[0]) == 0) {
cmd->exec(out, argv + 1, argc - 1);
break;
}
}
} }
static char *prompt(const char *prefix) void cmd_parse(struct cmd *cmds, FILE *out, const char *line)
{ {
size_t len; char **argv;
size_t argc;
printf(prefix);
if (!fgets(buf, 128, stdin))
return NULL;
len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n') if (!(argv = parse_args(line, &argc)))
buf[len - 1] = '\0'; return;
putchar('\n'); cmd_exec(cmds, out, (const char **)argv, argc);
free(argv);
return buf;
} }
void cmd_exec(struct cmd *cmds, const char *line) int shell_init(struct shell *shell, struct cmd *cmds,
struct usart_console *con, const char *prompt)
{ {
struct cmd *cmd; if (!shell || !con)
const char *args; return -1;
char *key;
size_t n;
n = strcspn(line, " \n"); memset(shell->line, '\0', sizeof shell->line);
key = strndup(line, n); shell->cmds = cmds;
shell->con = con;
shell->fp = console_to_fp(con);
shell->prompt = prompt;
args = line + n; fprintf(shell->fp, "%s ", prompt ? prompt : "#");
args += strspn(args, " \n");
for (cmd = cmds; cmd->key; ++cmd) { return 0;
if (strcmp(cmd->key, key) == 0) {
cmd->exec(args);
break;
}
}
free(key);
} }
void cmd_loop(const char *show) int shell_parse(struct shell *shell)
{ {
char *line; int ret;
should_exit = 0; if (!shell)
return -1;
while (!should_exit) { if ((ret = console_getline(shell->con, shell->line, sizeof shell->line)) <
line = prompt(show); 0)
cmd_exec(main_cmds, line); return ret;
}
cmd_parse(shell->cmds, shell->fp, shell->line);
fprintf(shell->fp, "%s ", shell->prompt ? shell->prompt : "#");
*shell->line = '\0';
return 0;
} }

Loading…
Cancel
Save