diff --git a/os/various/shell/shell.c b/os/various/shell/shell.c
index 379b6ddf0..958afcaf1 100644
--- a/os/various/shell/shell.c
+++ b/os/various/shell/shell.c
@@ -55,21 +55,37 @@ event_source_t shell_terminated;
/* Module local functions. */
/*===========================================================================*/
-static char *_strtok(char *str, const char *delim, char **saveptr) {
- char *token;
- if (str)
+static char *parse_arguments(char *str, char **saveptr) {
+ char *p;
+
+ if (str != NULL)
*saveptr = str;
- token = *saveptr;
- if (!token)
+ p = *saveptr;
+ if (!p) {
return NULL;
+ }
- token += strspn(token, delim);
- *saveptr = strpbrk(token, delim);
- if (*saveptr)
+ /* Skipping white space.*/
+ p += strspn(p, " \t");
+
+ if (*p == '"') {
+ /* If an argument starts with a double quote then its delimiter is another
+ quote.*/
+ p++;
+ *saveptr = strpbrk(p, "\"");
+ }
+ else {
+ /* The delimiter is white space.*/
+ *saveptr = strpbrk(p, " \t");
+ }
+
+ /* Replacing the delimiter with a zero.*/
+ if (*saveptr != NULL) {
*(*saveptr)++ = '\0';
+ }
- return *token ? token : NULL;
+ return *p != '\0' ? p : NULL;
}
static void usage(BaseSequentialStream *chp, char *p) {
@@ -122,10 +138,10 @@ THD_FUNCTION(shellThread, p) {
chprintf(chp, "\r\nlogout");
break;
}
- lp = _strtok(line, " \t", &tokp);
+ lp = parse_arguments(line, &tokp);
cmd = lp;
n = 0;
- while ((lp = _strtok(NULL, " \t", &tokp)) != NULL) {
+ while ((lp = parse_arguments(NULL, &tokp)) != NULL) {
if (n >= SHELL_MAX_ARGUMENTS) {
chprintf(chp, "too many arguments\r\n");
cmd = NULL;
diff --git a/os/various/shell/shell_cmd.c b/os/various/shell/shell_cmd.c
index 1a8bba4a4..7d592286b 100644
--- a/os/various/shell/shell_cmd.c
+++ b/os/various/shell/shell_cmd.c
@@ -93,6 +93,18 @@ static void cmd_info(BaseSequentialStream *chp, int argc, char *argv[]) {
}
#endif
+#if (SHELL_CMD_ECHO_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_echo(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc != 1) {
+ usage(chp, "echo \"message\"");
+ return;
+ }
+ chprintf(chp, "%s\r\n", argv[0]);
+}
+#endif
+
#if (SHELL_CMD_SYSTIME_ENABLED == TRUE) || defined(__DOXYGEN__)
static void cmd_systime(BaseSequentialStream *chp, int argc, char *argv[]) {
@@ -175,6 +187,9 @@ ShellCommand shell_local_commands[] = {
#if SHELL_CMD_INFO_ENABLED == TRUE
{"info", cmd_info},
#endif
+#if SHELL_CMD_ECHO_ENABLED == TRUE
+ {"echo", cmd_echo},
+#endif
#if SHELL_CMD_SYSTIME_ENABLED == TRUE
{"systime", cmd_systime},
#endif
diff --git a/os/various/shell/shell_cmd.h b/os/various/shell/shell_cmd.h
index 36e6c0728..9d7c129d0 100644
--- a/os/various/shell/shell_cmd.h
+++ b/os/various/shell/shell_cmd.h
@@ -37,6 +37,10 @@
#define SHELL_CMD_INFO_ENABLED TRUE
#endif
+#if !defined(SHELL_CMD_ECHO_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_ECHO_ENABLED TRUE
+#endif
+
#if !defined(SHELL_CMD_SYSTIME_ENABLED) || defined(__DOXYGEN__)
#define SHELL_CMD_SYSTIME_ENABLED TRUE
#endif
diff --git a/readme.txt b/readme.txt
index 8de727a7a..230488a8a 100644
--- a/readme.txt
+++ b/readme.txt
@@ -76,6 +76,8 @@
*****************************************************************************
*** Next ***
+- VAR: Centralized all usual shell commands into a single shell_cmd.c file.
+- VAR: The shell now accepts quoted arguments.
- ALL: Reorganized source tree, now ports are shared between RT and NIL.
- RT: Merged RT4.
- NIL: Merged NIL2.
diff --git a/testhal/STM32/STM32F7xx/USB_CDC/debug/STM32F7xx-USB_CDC (OpenOCD, Just Run).launch b/testhal/STM32/STM32F7xx/USB_CDC/debug/STM32F7xx-USB_CDC (OpenOCD, Just Run).launch
index bc6f16628..0f4360bab 100644
--- a/testhal/STM32/STM32F7xx/USB_CDC/debug/STM32F7xx-USB_CDC (OpenOCD, Just Run).launch
+++ b/testhal/STM32/STM32F7xx/USB_CDC/debug/STM32F7xx-USB_CDC (OpenOCD, Just Run).launch
@@ -33,7 +33,7 @@
-
+