This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit e178c3d79cf526fbc146bce25f3a1e15b15a51b8
Author: Christopher Collins <ccoll...@apache.org>
AuthorDate: Fri May 10 18:51:50 2019 -0700

    sys/shell: Use the util/streamer interface
    
    This change allows shell commands to send the output somewhere other
    than the console.  This is in preparation for the ability to invoke
    shell commands via newtmgr.
---
 sys/shell/include/shell/shell.h |  66 +++++++++++-
 sys/shell/pkg.yml               |   1 +
 sys/shell/src/shell.c           | 226 ++++++++++++++++++++++++----------------
 sys/shell/src/shell_priv.h      |  18 ++++
 sys/shell/src/shell_prompt.c    |   2 +-
 5 files changed, 223 insertions(+), 90 deletions(-)

diff --git a/sys/shell/include/shell/shell.h b/sys/shell/include/shell/shell.h
index 859b9fa..8eecbf5 100644
--- a/sys/shell/include/shell/shell.h
+++ b/sys/shell/include/shell/shell.h
@@ -25,8 +25,14 @@ extern "C" {
 #endif
 
 #include "os/mynewt.h"
+#include "streamer/streamer.h"
 
 struct os_eventq;
+struct streamer;
+struct shell_cmd;
+
+/** Command IDs in the "shell" newtmgr group. */
+#define SHELL_NMGR_OP_EXEC      0
 
 /** @brief Callback called when command is entered.
  *
@@ -37,6 +43,21 @@ struct os_eventq;
  */
 typedef int (*shell_cmd_func_t)(int argc, char *argv[]);
 
+/**
+ * @brief Callback for "extended" shell commands.
+ *
+ * @param cmd                   The shell command being executed.
+ * @param argc                  Number of arguments passed.
+ * @param argv                  Array of option strings. First option is always
+ *                                  command name.
+ * @param streamer              The streamer to write shell output to.
+ *
+ * @return                      0 on success; SYS_E[...] on failure.
+ */
+typedef int (*shell_cmd_ext_func_t)(const struct shell_cmd *cmd,
+                                    int argc, char *argv[],
+                                    struct streamer *streamer);
+
 struct shell_param {
     const char *param_name;
     const char *help;
@@ -49,8 +70,13 @@ struct shell_cmd_help {
 };
 
 struct shell_cmd {
+    uint8_t sc_ext : 1; /* 1 if this is an extended shell comand. */
+    union {
+        shell_cmd_func_t sc_cmd_func;
+        shell_cmd_ext_func_t sc_cmd_ext_func;
+    };
+
     const char *sc_cmd;
-    shell_cmd_func_t sc_cmd_func;
     const struct shell_cmd_help *help;
 };
 
@@ -59,6 +85,32 @@ struct shell_module {
     const struct shell_cmd *commands;
 };
 
+#if MYNEWT_VAL(SHELL_CMD_HELP)
+#define SHELL_HELP_(help_) (help_)
+#else
+#define SHELL_HELP_(help_)
+#endif
+
+/**
+ * @brief constructs a legacy shell command.
+ */
+#define SHELL_CMD(cmd_, func_, help_) {         \
+    .sc_ext = 0,                                \
+    .sc_cmd_func = func_,                       \
+    .sc_cmd = cmd_,                             \
+    .help = SHELL_HELP_(help_),                 \
+}
+
+/**
+ * @brief constructs an extended shell command.
+ */
+#define SHELL_CMD_EXT(cmd_, func_, help_) {     \
+    .sc_ext = 1,                                \
+    .sc_cmd_ext_func = func_,                   \
+    .sc_cmd = cmd_,                             \
+    .help = SHELL_HELP_(help_),                 \
+}
+
 /** @brief Register a shell_module object
  *
  *  @param shell_name Module name to be entered in shell console.
@@ -101,6 +153,18 @@ void shell_register_default_module(const char *name);
  */
 void shell_evq_set(struct os_eventq *evq);
 
+/**
+ * @brief Processes a set of arguments and executes their corresponding shell
+ * command.
+ *
+ * @param argc                  The argument count (including command name).
+ * @param argv                  The argument list ([0] is command name).
+ * @param streamer              The streamer to send output to.
+ *
+ * @return                      0 on success; SYS_E[...] on failure.
+ */
+int shell_exec(int argc, char **argv, struct streamer *streamer);
+
 #if MYNEWT_VAL(SHELL_NEWTMGR)
 struct os_mbuf;
 typedef int (*shell_nlip_input_func_t)(struct os_mbuf *, void *arg);
diff --git a/sys/shell/pkg.yml b/sys/shell/pkg.yml
index 6c6f6cf..cf009a8 100644
--- a/sys/shell/pkg.yml
+++ b/sys/shell/pkg.yml
@@ -26,6 +26,7 @@ pkg.keywords:
 pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/time/datetime"
+    - "@apache-mynewt-core/util/streamer"
 
 pkg.deps.SHELL_NEWTMGR:
     - "@apache-mynewt-core/mgmt/mgmt"
diff --git a/sys/shell/src/shell.c b/sys/shell/src/shell.c
index 335564e..b63fe94 100644
--- a/sys/shell/src/shell.c
+++ b/sys/shell/src/shell.c
@@ -23,6 +23,8 @@
 
 #include "os/mynewt.h"
 #include "console/console.h"
+#include "streamer/streamer.h"
+#include "modlog/modlog.h"
 #include "shell/shell.h"
 #include "shell_priv.h"
 
@@ -34,7 +36,7 @@ static size_t num_of_shell_entities;
 static const char *prompt;
 static int default_module = -1;
 
-static shell_cmd_func_t app_cmd_handler;
+static struct shell_cmd app_cmd;
 static shell_prompt_function_t app_prompt_handler;
 
 /* Shared queue for shell events to be processed */
@@ -76,8 +78,16 @@ print_prompt(void)
     console_printf("%s%s", get_prompt(), MYNEWT_VAL(SHELL_PROMPT_SUFFIX));
 }
 
+static void
+print_prompt_if_console(struct streamer *streamer)
+{
+    if (streamer == streamer_console_get()) {
+        print_prompt();
+    }
+}
+
 static size_t
-line2argv(char *str, char *argv[], size_t size)
+line2argv(char *str, char *argv[], size_t size, struct streamer *streamer)
 {
     size_t argc = 0;
 
@@ -109,7 +119,8 @@ line2argv(char *str, char *argv[], size_t size)
         argv[argc++] = str;
 
         if (argc == size) {
-            console_printf("Too many parameters (max %zu)\n", size - 1);
+            streamer_printf(streamer, "Too many parameters (max %zu)\n",
+                            size - 1);
             return 0;
         }
     }
@@ -144,24 +155,24 @@ get_destination_module(const char *module_str, int len)
  * If a default module was selected: argv[0] = command name
  */
 static const char *
-get_command_and_module(char *argv[], int *module)
+get_command_and_module(char *argv[], int *module, struct streamer *streamer)
 {
     *module = -1;
 
     if (!argv[0]) {
-        console_printf("Unrecognized command\n");
+        streamer_printf(streamer, "Unrecognized command\n");
         return NULL;
     }
 
     if (default_module == -1) {
         if (!argv[1] || argv[1][0] == '\0') {
-            console_printf("Unrecognized command: %s\n", argv[0]);
+            streamer_printf(streamer, "Unrecognized command: %s\n", argv[0]);
             return NULL;
         }
 
         *module = get_destination_module(argv[0], -1);
         if (*module == -1) {
-            console_printf("Illegal module %s\n", argv[0]);
+            streamer_printf(streamer, "Illegal module %s\n", argv[0]);
             return NULL;
         }
 
@@ -173,7 +184,8 @@ get_command_and_module(char *argv[], int *module)
 }
 
 static void
-print_command_params(const int module, const int command)
+print_command_params(const int module, const int command,
+                     struct streamer *streamer)
 {
        const struct shell_module *shell_module = &shell_modules[module];
        const struct shell_cmd *shell_cmd = &shell_module->commands[command];
@@ -184,13 +196,14 @@ print_command_params(const int module, const int command)
        }
 
        for (i = 0; shell_cmd->help->params[i].param_name; i++) {
-               console_printf("%-30s%s\n", 
shell_cmd->help->params[i].param_name,
-                              shell_cmd->help->params[i].help);
+               streamer_printf(streamer, "%-30s%s\n",
+                        shell_cmd->help->params[i].param_name,
+                                   shell_cmd->help->params[i].help);
        }
 }
 
 static int
-show_cmd_help(char *argv[])
+show_cmd_help(char *argv[], struct streamer *streamer)
 {
     const char *command = NULL;
     int module = -1;
@@ -198,7 +211,7 @@ show_cmd_help(char *argv[])
     const struct shell_cmd *cmd;
     int i;
 
-    command = get_command_and_module(argv, &module);
+    command = get_command_and_module(argv, &module, streamer);
     if ((module == -1) || (command == NULL)) {
         return 0;
     }
@@ -208,73 +221,75 @@ show_cmd_help(char *argv[])
         cmd = &shell_module->commands[i];
 
         if (!strcmp(command, cmd->sc_cmd)) {
-
             if (!cmd->help || (!cmd->help->summary &&
                                !cmd->help->usage &&
                                !cmd->help->params)) {
-                console_printf("(no help available)\n");
+                streamer_printf(streamer, "(no help available)\n");
                 return 0;
             }
 
             if (cmd->help->summary) {
-                console_printf("Summary:\n");
-                console_printf("%s\n", cmd->help->summary);
+                streamer_printf(streamer, "Summary:\n");
+                streamer_printf(streamer, "%s\n", cmd->help->summary);
             }
 
             if (cmd->help->usage) {
-                console_printf("Usage:\n");
-                console_printf("%s\n", cmd->help->usage);
+                streamer_printf(streamer, "Usage:\n");
+                streamer_printf(streamer, "%s\n", cmd->help->usage);
             }
 
             if (cmd->help->params) {
-                console_printf("Parameters:\n");
-                print_command_params(module, i);
+                streamer_printf(streamer, "Parameters:\n");
+                print_command_params(module, i, streamer);
             }
 
             return 0;
         }
     }
 
-    console_printf("Unrecognized command: %s\n", argv[0]);
+    streamer_printf(streamer, "Unrecognized command: %s\n", argv[0]);
     return 0;
 }
 
 static void
-print_modules(void)
+print_modules(struct streamer *streamer)
 {
     int module;
 
     for (module = 0; module < num_of_shell_entities; module++) {
-        console_printf("%s\n", shell_modules[module].name);
+        streamer_printf(streamer, "%s\n", shell_modules[module].name);
     }
 }
 
 static void
-print_module_commands(const int module)
+print_module_commands(const int module, struct streamer *streamer)
 {
     const struct shell_module *shell_module = &shell_modules[module];
     int i;
 
-    console_printf("help\n");
+    streamer_printf(streamer, "help\n");
 
     for (i = 0; shell_module->commands[i].sc_cmd; i++) {
-        console_printf("%-30s", shell_module->commands[i].sc_cmd);
+        streamer_printf(streamer, "%-30s", shell_module->commands[i].sc_cmd);
         if (shell_module->commands[i].help &&
             shell_module->commands[i].help->summary) {
-        console_printf("%s", shell_module->commands[i].help->summary);
+        
+            streamer_printf(streamer, "%s",
+                            shell_module->commands[i].help->summary);
         }
-        console_printf("\n");
+        streamer_printf(streamer, "\n");
     }
 }
 
 static int
-show_help(int argc, char *argv[])
+show_help(const struct shell_cmd *cmd, int argc, char *argv[],
+          struct streamer *streamer)
 {
     int module;
 
     /* help per command */
     if ((argc > 2) || ((default_module != -1) && (argc == 2))) {
-        return show_cmd_help(&argv[1]);
+        return show_cmd_help(&argv[1], streamer);
     }
 
     /* help per module */
@@ -282,23 +297,27 @@ show_help(int argc, char *argv[])
         if (default_module == -1) {
             module = get_destination_module(argv[1], -1);
             if (module == -1) {
-                console_printf("Illegal module %s\n", argv[1]);
+                streamer_printf(streamer, "Illegal module %s\n", argv[1]);
                 return 0;
             }
         } else {
             module = default_module;
         }
 
-        print_module_commands(module);
+        print_module_commands(module, streamer);
     } else { /* help for all entities */
-        console_printf("Available modules:\n");
-        print_modules();
-        console_printf("To select a module, enter 'select <module name>'.\n");
+        streamer_printf(streamer, "Available modules:\n");
+        print_modules(streamer);
+        streamer_printf(streamer,
+                        "To select a module, enter 'select <module name>'.\n");
     }
 
     return 0;
 }
 
+static const struct shell_cmd shell_cmd_help =
+    SHELL_CMD_EXT("help", show_help, NULL);
+
 static int
 set_default_module(const char *name)
 {
@@ -307,7 +326,6 @@ set_default_module(const char *name)
     module = get_destination_module(name, -1);
 
     if (module == -1) {
-        console_printf("Illegal module %s, default is not changed\n", name);
         return -1;
     }
 
@@ -317,7 +335,8 @@ set_default_module(const char *name)
 }
 
 static int
-select_module(int argc, char *argv[])
+select_module(const struct shell_cmd *cmd, int argc, char *argv[],
+              struct streamer *streamer)
 {
     if (argc == 1) {
         default_module = -1;
@@ -328,8 +347,11 @@ select_module(int argc, char *argv[])
     return 0;
 }
 
-static shell_cmd_func_t
-get_cb(int argc, char *argv[])
+static const struct shell_cmd shell_cmd_select_module =
+    SHELL_CMD_EXT("select", select_module, NULL);
+
+static const struct shell_cmd *
+shell_find_cmd(int argc, char *argv[], struct streamer *streamer)
 {
     const char *first_string = argv[0];
     int module = -1;
@@ -338,24 +360,24 @@ get_cb(int argc, char *argv[])
     int i;
 
     if (!first_string || first_string[0] == '\0') {
-        console_printf("Illegal parameter\n");
+        streamer_printf(streamer, "Illegal parameter\n");
         return NULL;
     }
 
     if (!strcmp(first_string, "help")) {
-        return show_help;
+        return &shell_cmd_help;
     }
 
     if (!strcmp(first_string, "select")) {
-        return select_module;
+        return &shell_cmd_select_module;
     }
 
     if ((argc == 1) && (default_module == -1)) {
-        console_printf("Missing parameter\n");
+        streamer_printf(streamer, "Missing parameter\n");
         return NULL;
     }
 
-    command = get_command_and_module(argv, &module);
+    command = get_command_and_module(argv, &module, streamer);
     if ((module == -1) || (command == NULL)) {
         return NULL;
     }
@@ -363,58 +385,75 @@ get_cb(int argc, char *argv[])
     shell_module = &shell_modules[module];
     for (i = 0; shell_module->commands[i].sc_cmd; i++) {
         if (!strcmp(command, shell_module->commands[i].sc_cmd)) {
-            return shell_module->commands[i].sc_cmd_func;
+            return &shell_module->commands[i];
         }
     }
 
     return NULL;
 }
 
-static void
-shell_process_command(char *line)
+int
+shell_exec(int argc, char **argv, struct streamer *streamer)
 {
-    char *argv[MYNEWT_VAL(SHELL_CMD_ARGC_MAX) + 1];
-    shell_cmd_func_t sc_cmd_func;
+    const struct shell_cmd *cmd;
     size_t argc_offset = 0;
-    size_t argc;
+    int rc;
 
-    argc = line2argv(line, argv, MYNEWT_VAL(SHELL_CMD_ARGC_MAX) + 1);
-    if (!argc) {
-        print_prompt();
-        return;
-    }
-
-    sc_cmd_func = get_cb(argc, argv);
-    if (!sc_cmd_func) {
-        if (app_cmd_handler != NULL) {
-            sc_cmd_func = app_cmd_handler;
+    cmd = shell_find_cmd(argc, argv, streamer);
+    if (!cmd) {
+        if (app_cmd.sc_cmd_func != NULL) {
+            cmd = &app_cmd;
         } else {
-            console_printf("Unrecognized command: %s\n", argv[0]);
-            console_printf("Type 'help' for list of available commands\n");
-            print_prompt();
-            return;
+            streamer_printf(streamer, "Unrecognized command: %s\n", argv[0]);
+            streamer_printf(streamer,
+                            "Type 'help' for list of available commands\n");
+            print_prompt_if_console(streamer);
+            return SYS_ENOENT;
         }
     }
 
     /* Allow invoking a cmd with module name as a prefix; a command should
      * not know how it was invoked (with or without prefix)
      */
-    if (default_module == -1 && sc_cmd_func != select_module &&
-        sc_cmd_func != show_help) {
+    if (default_module == -1 && cmd != &shell_cmd_select_module &&
+        cmd != &shell_cmd_help) {
         argc_offset = 1;
     }
 
     /* Execute callback with arguments */
-    if (sc_cmd_func(argc - argc_offset, &argv[argc_offset]) < 0) {
-        show_cmd_help(argv);
+    if (!cmd->sc_ext) {
+        rc = cmd->sc_cmd_func(argc - argc_offset, &argv[argc_offset]);
+    } else {
+        rc = cmd->sc_cmd_ext_func(cmd, argc - argc_offset, &argv[argc_offset],
+                                  streamer);
+    }
+    if (rc < 0) {
+        show_cmd_help(argv, streamer);
     }
 
-    print_prompt();
+    print_prompt_if_console(streamer);
+
+    return rc;
+}
+
+static void
+shell_process_command(char *line, struct streamer *streamer)
+{
+    char *argv[MYNEWT_VAL(SHELL_CMD_ARGC_MAX) + 1];
+    size_t argc;
+
+    argc = line2argv(line, argv, MYNEWT_VAL(SHELL_CMD_ARGC_MAX) + 1, streamer);
+    if (!argc) {
+        print_prompt_if_console(streamer);
+        return;
+    }
+
+    shell_exec(argc, argv, streamer);
 }
 
 #if MYNEWT_VAL(SHELL_NEWTMGR)
 static void
-shell_process_nlip_line(char *shell_line)
+shell_process_nlip_line(char *shell_line, struct streamer *streamer)
 {
     size_t shell_line_len;
 
@@ -428,10 +467,10 @@ shell_process_nlip_line(char *shell_line)
                 shell_line[1] == SHELL_NLIP_DATA_START2) {
             shell_nlip_process(&shell_line[2], shell_line_len - 2);
         } else {
-            shell_process_command(shell_line);
+            shell_process_command(shell_line, streamer);
         }
     } else {
-        shell_process_command(shell_line);
+        shell_process_command(shell_line, streamer);
     }
 }
 #endif
@@ -440,6 +479,7 @@ static void
 shell(struct os_event *ev)
 {
     struct console_input *cmd;
+    struct streamer *streamer;
 
     if (!ev) {
         print_prompt();
@@ -452,10 +492,12 @@ shell(struct os_event *ev)
         return;
     }
 
+    streamer = streamer_console_get();
+
 #if MYNEWT_VAL(SHELL_NEWTMGR)
-    shell_process_nlip_line(cmd->line);
+    shell_process_nlip_line(cmd->line, streamer);
 #else
-    shell_process_command(cmd->line);
+    shell_process_command(cmd->line, streamer);
 #endif
 
     console_line_event_put(ev);
@@ -752,7 +794,7 @@ complete_select(char *line, char *cur,
             return;
         }
         console_printf("\n");
-        print_modules();
+        print_modules(streamer_console_get());
         print_prompt();
         console_printf("%s", line);
         return;
@@ -788,9 +830,9 @@ completion(char *line, console_append_char_cb append_char)
     if (tok_len == 0) {
         console_printf("\n");
         if (default_module == -1) {
-            print_modules();
+            print_modules(streamer_console_get());
         } else {
-            print_module_commands(default_module);
+            print_module_commands(default_module, streamer_console_get());
         }
         print_prompt();
         console_printf("%s", line);
@@ -827,7 +869,7 @@ completion(char *line, console_append_char_cb append_char)
 
         if (tok_len == 0) {
             console_printf("\n");
-            print_module_commands(module);
+            print_module_commands(module, streamer_console_get());
             print_prompt();
             console_printf("%s", line);
             return;
@@ -849,7 +891,7 @@ completion(char *line, console_append_char_cb append_char)
     tok_len = get_last_token(&cur);
     if (tok_len == 0) {
         console_printf("\n");
-        print_command_params(module, command);
+        print_command_params(module, command, streamer_console_get());
         print_prompt();
         console_printf("%s", line);
         return;
@@ -863,7 +905,7 @@ completion(char *line, console_append_char_cb append_char)
 void
 shell_register_app_cmd_handler(shell_cmd_func_t handler)
 {
-    app_cmd_handler = handler;
+    app_cmd.sc_cmd_func = handler;
 }
 
 void
@@ -899,7 +941,7 @@ int
 shell_register(const char *module_name, const struct shell_cmd *commands)
 {
     if (num_of_shell_entities >= MYNEWT_VAL(SHELL_MAX_MODULES)) {
-        console_printf("Max number of modules reached\n");
+        MODLOG_ERROR(LOG_MODULE_DEFAULT, "Max number of modules reached\n");
         assert(0);
     }
 
@@ -919,22 +961,27 @@ static int module_registered;
 int
 shell_cmd_register(const struct shell_cmd *sc)
 {
+    int rc;
+
     if (num_compat_commands >= MYNEWT_VAL(SHELL_MAX_COMPAT_COMMANDS)) {
-        console_printf("Max number of compat commands reached\n");
+        MODLOG_ERROR(LOG_MODULE_DEFAULT,
+                     "Max number of compat commands reached\n");
         assert(0);
     }
 
     if (!module_registered) {
         shell_register(SHELL_COMPAT_MODULE_NAME, compat_commands);
-        set_default_module(SHELL_COMPAT_MODULE_NAME);
         module_registered = 1;
+
+        rc = set_default_module(SHELL_COMPAT_MODULE_NAME);
+        if (rc != 0) {
+            MODLOG_ERROR(LOG_MODULE_DEFAULT,
+                         "Illegal module %s, default is not changed\n",
+                         SHELL_COMPAT_MODULE_NAME);
+        }
     }
 
-    compat_commands[num_compat_commands].sc_cmd = sc->sc_cmd;
-    compat_commands[num_compat_commands].sc_cmd_func = sc->sc_cmd_func;
-#if MYNEWT_VAL(SHELL_CMD_HELP)
-    compat_commands[num_compat_commands].help = sc->help;
-#endif
+    compat_commands[num_compat_commands] = *sc;
     ++num_compat_commands;
     return 0;
 }
@@ -969,4 +1016,7 @@ shell_init(void)
 #if MYNEWT_VAL(SHELL_PROMPT_MODULE)
     shell_prompt_register();
 #endif
+#if MYNEWT_VAL(SHELL_BRIDGE)
+    shell_bridge_init();
+#endif
 }
diff --git a/sys/shell/src/shell_priv.h b/sys/shell/src/shell_priv.h
index 315ae1c..36a4863 100644
--- a/sys/shell/src/shell_priv.h
+++ b/sys/shell/src/shell_priv.h
@@ -24,7 +24,19 @@
 extern "C" {
 #endif
 
+#include "streamer/streamer.h"
 #include "shell/shell.h"
+struct CborEncoder;
+ 
+#if MYNEWT_VAL(SHELL_BRIDGE)
+/**
+ * Streams CBOR text strings to its encoder.
+ */
+struct shell_bridge_streamer {
+    struct streamer streamer;
+    struct CborEncoder *str_encoder;
+};
+#endif
 
 #if MYNEWT_VAL(SHELL_NEWTMGR)
 #define SHELL_NLIP_PKT_START1 (6)
@@ -40,6 +52,12 @@ void shell_nlip_clear_pkt(void);
 void shell_os_register(void);
 void shell_prompt_register(void);
 
+#if MYNEWT_VAL(SHELL_BRIDGE)
+void shell_bridge_streamer_new(struct shell_bridge_streamer *sbs,
+                               struct CborEncoder *str_encoder);
+int shell_bridge_init(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sys/shell/src/shell_prompt.c b/sys/shell/src/shell_prompt.c
index 0a88500..00a1c18 100644
--- a/sys/shell/src/shell_prompt.c
+++ b/sys/shell/src/shell_prompt.c
@@ -73,7 +73,7 @@ static const struct shell_cmd prompt_commands[] = {
         .help = &ticks_help,
 #endif
     },
-    { NULL, NULL, NULL },
+    { 0 },
 };
 
 

Reply via email to