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

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

commit 00fd862e268bd281e417ad81bd706c11faec5abb
Author: Jerzy Kasenberg <jerzy.kasenb...@codecoup.pl>
AuthorDate: Sat May 31 00:40:59 2025 +0200

    sys/shell: Add macros for creating link time commands
    
    Shell commands and modules used to be registered at
    run time by packages. This required code and RAM space.
    Both shell modules and commands required RAM of some fixed
    size (specified in syscfg). When more commands or shell
    modules were registered assertion failed at run time.
    
    Now it's possibly to create shell commands that will be
    'registered' at link time and will not require RAM
    nor explicit function call.
    This should eliminate problem of registering to
    many modules or commands.
    
    Signed-off-by: Jerzy Kasenberg <je...@apache.org>
---
 sys/shell/include/shell/shell.h | 187 ++++++++++++++++++++
 sys/shell/pkg.yml               |   6 +
 sys/shell/src/shell.c           | 365 ++++++++++++++++++++++------------------
 3 files changed, 398 insertions(+), 160 deletions(-)

diff --git a/sys/shell/include/shell/shell.h b/sys/shell/include/shell/shell.h
index efb56beb2..691489b16 100644
--- a/sys/shell/include/shell/shell.h
+++ b/sys/shell/include/shell/shell.h
@@ -25,6 +25,7 @@ extern "C" {
 #endif
 
 #include "os/mynewt.h"
+#include "os/link_tables.h"
 #include "streamer/streamer.h"
 
 struct os_eventq;
@@ -85,6 +86,192 @@ struct shell_module {
     const struct shell_cmd *commands;
 };
 
+typedef const struct shell_mod *shell_mod_t;
+typedef const struct shell_cmd *shell_cmd_t;
+
+/*
+ * Shell module enumeration functions
+ */
+typedef struct shell_mod_ops {
+    /** Returns number of module commands */
+    size_t (*count)(shell_mod_t mod);
+    /** Return module command by it's index */
+    shell_cmd_t (*get)(shell_mod_t mod, size_t ix);
+} shell_mod_ops_t;
+
+/*
+ * Shell module
+ */
+struct shell_mod {
+    /* Shell module functions */
+    const shell_mod_ops_t *ops;
+    /* Shell module name visible to end use */
+    const char *name;
+};
+
+/*
+ * Shell module with static array of commands
+ */
+typedef struct shell_mod_std {
+    /* Inherited shell module */
+    struct shell_mod mod;
+    /* Beginning of command array */
+    const struct shell_cmd *commands;
+    /* Pointer to end of command array */
+    const struct shell_cmd *commands_end;
+} shell_mod_std_t;
+extern const struct shell_mod_ops shell_mod_std_ops;
+
+static inline int
+shell_mod_command_count(shell_mod_t mod)
+{
+    return mod->ops->count(mod);
+}
+
+static inline shell_cmd_t
+shell_mod_command(shell_mod_t mod, size_t ix)
+{
+    return mod->ops->get(mod, ix);
+}
+
+LINK_TABLE(shell_mod_t, shell_modules)
+/* Section name for shell modules */
+#define SHELL_MODULES_SECTION LINK_TABLE_SECTION(shell_modules)
+#define SHELL_MODULE_SECTION(mod)                                             \
+    LINK_TABLE_ELEMENT_SECTION(shell_modules, mod)
+
+/**
+ * Create shell module with commands designated by begin and end pointers
+ *
+ * This will create object of type shell_mod_std and pointer to this object.
+ * Pointer will be placed in .shell_modules section so it will be put
+ * together with all other shell modules on one link time table.
+ *
+ * @param _name - name of the module
+ * @param _command_begin - pointer to start of the table with commands
+ * @param _command_end - pointer to end of the table with commands
+ */
+#define SHELL_MODULE_STD(_name, _command_begin, _command_end)                 \
+    const shell_mod_std_t shell_module_##_name = {                            \
+        { &shell_mod_std_ops, #_name },                                       \
+        _command_begin, _command_end                                          \
+    };                                                                        \
+    LINK_TABLE_ELEMENT_REF(shell_modules, _name, shell_module_##_name.mod)
+
+/**
+ * Create shell module with static command table
+ *
+ * @param _name - name of the module
+ * @parma _table - standard table of const struct shell_cmd with know size
+ */
+#define SHELL_MODULE_WITH_TABLE(name_, table_)                                \
+    SHELL_MODULE_STD(name_, table_, table_ + ARRAY_SIZE(table_))
+
+#define SHELL_MODULE_CMD_SECTION(mod_, cmd_)                                  \
+    LINK_TABLE_ELEMENT_SECTION(mod_##_commands, cmd_)
+/* Section name for shell compat (global) commands */
+#define SHELL_COMPAT_CMDS_SECTION LINK_TABLE_SECTION(compat_commands)
+/* Section name for shell compat command */
+#define SHELL_COMPAT_CMD_SECTION(cmd_) SHELL_MODULE_CMD_SECTION(compat, cmd_)
+
+/**
+ * Create shell module with link time table (name derived from _name)
+ *
+ * Link table will have name derived from shell module.
+ * Link table must be declared in some pkg.yml in pkg.link_tables: section
+ *
+ * i.e.
+ * pkg.yml
+ *
+ * pkg.link_tables:
+ *     - mcu_commands
+ *
+ * mcu_cli.c
+ *
+ * SHELL_MODULE_WITH_LINK_TABLE(mcu)
+ *
+ * @param _name - name of the shell module
+ */
+#define SHELL_MODULE_WITH_LINK_TABLE(_name)                                   \
+    LINK_TABLE(struct shell_cmd, _name##_commands)                            \
+    SHELL_MODULE_STD(_name, LINK_TABLE_START(_name##_commands),               \
+                     LINK_TABLE_END(_name##_commands))
+
+/**
+ * Create command for module
+ *
+ * Macro creates object of struct shell_cmd and puts it in link table
+ * for module
+ *
+ * @param mod_ - module name
+ * @param cmd_ - command name
+ * @param name_ - command name as string
+ * @param ext_ - 1 for extended command with streamer
+ * @param func_ - function to execute
+ * @param help_ - help structure for function
+ */
+#define SHELL_MODULE_CMD_WITH_NAME(mod_, cmd_, name_, ext_, func_, help_)      
      \
+    const struct shell_cmd shell_cmd_##cmd_ SHELL_MODULE_CMD_SECTION(mod_, 
cmd_) = { \
+        .sc_ext = ext_,                                                        
      \
+        .sc_cmd_ext_func = (shell_cmd_ext_func_t)(func_),                      
      \
+        .sc_cmd = name_,                                                       
      \
+        .help = SHELL_HELP_(help_),                                            
      \
+    };
+
+/**
+ * Create command for module
+ *
+ * Macro creates object of struct shell_cmd and puts it in link table
+ * for module
+ *
+ * @param mod_ - module name
+ * @param cmd_ - command name
+ * @param func_ - function to execute
+ * @param help_ - help structure for function
+ */
+#define SHELL_MODULE_CMD(mod_, cmd_, func_, help_)                            \
+    SHELL_MODULE_CMD_WITH_NAME(mod_, cmd_, #cmd_, 0, func_, help_)
+
+/**
+ * Create command for module
+ *
+ * Macro creates object of struct shell_cmd and puts it in link table
+ * for module
+ *
+ * @param mod_ - module name
+ * @param cmd_ - command name
+ * @param func_ - function to execute
+ * @param help_ - help structure for function
+ */
+#define SHELL_MODULE_EXT_CMD(mod_, cmd_, func_, help_)                        \
+    SHELL_MODULE_CMD_WITH_NAME(mod_, cmd_, #cmd_, 1, func_, help_)
+
+/**
+ * @brief Register global shell command function
+ *
+ * Macro creates shell command that can be used when shell task is enabled
+ * This is equivalent of calling deprecated function shell_cmd_register.
+ *
+ * @name - cmd_name command name (it will be put in "" to make string
+ * @func - command function function of shell_cmd_ext_func_t
+ * @help pointer to shell_cmd_help
+ */
+#define MAKE_SHELL_CMD(cmd_name, func, help)                                  \
+    SHELL_MODULE_CMD(compat, cmd_name, func, help)
+
+/**
+ * @brief Register global extended shell command function
+ *
+ * Macro creates shell command that can be used when shell task is enabled
+ * This is equivalent of calling deprecated function shell_cmd_register.
+ *
+ * @name - cmd_name command name (it will be put in "" to make string
+ * @func - command function function of shell_cmd_ext_func_t
+ * @help pointer to shell_cmd_help
+ */
+#define MAKE_SHELL_EXT_CMD(cmd_name, func, help)                              \
+    SHELL_MODULE_EXT_CMD(compat, cmd_name, func, help)
+
 #if MYNEWT_VAL(SHELL_CMD_HELP)
 #define SHELL_HELP_(help_) (help_)
 #else
diff --git a/sys/shell/pkg.yml b/sys/shell/pkg.yml
index a0c158d87..9d8e7757d 100644
--- a/sys/shell/pkg.yml
+++ b/sys/shell/pkg.yml
@@ -39,5 +39,11 @@ pkg.deps.SHELL_BRIDGE:
 pkg.req_apis:
     - console
 
+pkg.whole_archive: true
+
+pkg.link_tables:
+    - shell_modules
+    - compat_commands
+
 pkg.init:
     shell_init: 'MYNEWT_VAL(SHELL_SYSINIT_STAGE)'
diff --git a/sys/shell/src/shell.c b/sys/shell/src/shell.c
index f14e423ae..8de736c35 100644
--- a/sys/shell/src/shell.c
+++ b/sys/shell/src/shell.c
@@ -27,14 +27,82 @@
 #include "modlog/modlog.h"
 #include "shell/shell.h"
 #include "shell_priv.h"
+#include "os/link_tables.h"
 
 #define SHELL_PROMPT "shell"
 
-static struct shell_module shell_modules[MYNEWT_VAL(SHELL_MAX_MODULES)];
+static size_t
+shell_mod_std_count(shell_mod_t mod)
+{
+    const struct shell_mod_std *std_mod = (const struct shell_mod_std *)mod;
+    return std_mod->commands_end - std_mod->commands;
+}
+
+static shell_cmd_t
+shell_mod_std_get(shell_mod_t mod, size_t ix)
+{
+    const struct shell_mod_std *std_mod = (const struct shell_mod_std *)mod;
+    size_t limit = std_mod->commands_end - std_mod->commands;
+    return ix < limit ? &std_mod->commands[ix] : NULL;
+}
+
+const struct shell_mod_ops shell_mod_std_ops = {
+    .count = shell_mod_std_count,
+    .get = shell_mod_std_get,
+};
+
+static struct shell_mod_std 
registered_shell_modules[MYNEWT_VAL(SHELL_MAX_MODULES)];
+
 static size_t num_of_shell_entities;
 
+#if MYNEWT_VAL(SHELL_COMPAT)
+#define SHELL_COMPAT_MODULE_NAME "compat"
+static struct shell_cmd 
registered_compat_commands[MYNEWT_VAL(SHELL_MAX_COMPAT_COMMANDS)];
+static size_t num_compat_commands;
+
+static size_t
+shell_mod_compat_count(shell_mod_t mod)
+{
+    return shell_mod_std_count(mod) + num_of_shell_entities;
+}
+
+static shell_cmd_t
+shell_mod_compat_get(shell_mod_t mod, size_t ix)
+{
+    size_t linked_commands = shell_mod_std_count(mod);
+
+    if (ix < linked_commands) {
+        return shell_mod_std_get(mod, ix);
+    } else if (MYNEWT_VAL(SHELL_MAX_MODULES) > 0) {
+        ix -= linked_commands;
+        if (ix < num_compat_commands) {
+            return &registered_compat_commands[ix];
+        }
+    }
+
+    return NULL;
+}
+
+const shell_mod_ops_t shell_mod_compat_ops = {
+    .count = shell_mod_compat_count,
+    .get = shell_mod_compat_get,
+};
+
+LINK_TABLE(struct shell_cmd, compat_commands)
+const struct shell_mod_std shell_mod_compat = {
+    .mod = {
+        .name = "compat",
+        .ops = &shell_mod_compat_ops,
+    },
+    .commands = LINK_TABLE_START(compat_commands),
+    .commands_end = LINK_TABLE_END(compat_commands),
+};
+/* This pointer goes to link table, it's the pointer to actual shell_mod_std */
+LINK_TABLE_ELEMENT_REF(shell_modules, compat, shell_mod_compat.mod)
+
 static const char *prompt;
-static int default_module = -1;
+/* Set default module */
+static const struct shell_mod *default_module = &shell_mod_compat.mod;
 
 static struct shell_cmd app_cmd;
 static shell_prompt_function_t app_prompt_handler;
@@ -65,8 +133,8 @@ get_prompt(void)
         }
     }
 
-    if (default_module != -1) {
-        return shell_modules[default_module].name;
+    if (default_module) {
+        return default_module->name;
     }
 
     return prompt;
@@ -134,35 +202,56 @@ line2argv(char *str, char *argv[], size_t size, struct 
streamer *streamer)
     return argc;
 }
 
-static int
+static shell_mod_t
+shell_module_get(size_t ix)
+{
+    size_t build_time_module_count = shell_modules_size();
+
+    if (ix < build_time_module_count) {
+        return shell_modules[ix];
+    } else if (MYNEWT_VAL_SHELL_MAX_MODULES > 0) {
+        ix -= build_time_module_count;
+        if (ix < num_of_shell_entities) {
+            return (shell_mod_t)&registered_shell_modules[ix];
+        }
+    }
+    return NULL;
+}
+
+static bool
+module_str_matches(shell_mod_t mod, const char *str, int len)
+{
+    if (len < 0) {
+        return strcmp(str, mod->name) == 0;
+    } else {
+        return strncmp(str, mod->name, len) == 0;
+    }
+}
+
+const struct shell_mod *
 get_destination_module(const char *module_str, int len)
 {
-    int i;
+    shell_mod_t mod;
 
-    for (i = 0; i < num_of_shell_entities; i++) {
-        if (len < 0) {
-            if (!strcmp(module_str, shell_modules[i].name)) {
-                return i;
-            }
-        } else {
-            if (!strncmp(module_str, shell_modules[i].name, len)) {
-                return i;
-            }
+    for (size_t i = 0; NULL != (mod = shell_module_get(i)); ++i) {
+        if (module_str_matches(mod, module_str, len)) {
+            return mod;
         }
     }
 
-    return -1;
+    return NULL;
 }
 
 /* For a specific command: argv[0] = module name, argv[1] = command name
  * If a default module was selected: argv[0] = command name
  */
 static const char *
-get_command_and_module(char *argv[], int *module, struct streamer *streamer)
+get_command_and_module(char *argv[], const struct shell_mod **module,
+                       struct streamer *streamer)
 {
-    int def_module = default_module;
+    const struct shell_mod *def_module = default_module;
     const char *first_arg = argv[0];
-    *module = -1;
+    *module = NULL;
 
     if (!argv[0]) {
         streamer_printf(streamer, "Unrecognized command\n");
@@ -171,17 +260,17 @@ get_command_and_module(char *argv[], int *module, struct 
streamer *streamer)
 
     if (first_arg[0] == '/') {
         first_arg++;
-        def_module = -1;
+        def_module = NULL;
     }
 
-    if (def_module == -1) {
+    if (def_module == NULL) {
         if (!argv[1] || argv[1][0] == '\0') {
             streamer_printf(streamer, "Unrecognized command: %s\n", argv[0]);
             return NULL;
         }
 
         *module = get_destination_module(first_arg, -1);
-        if (*module == -1) {
+        if (*module == NULL) {
             streamer_printf(streamer, "Illegal module %s\n", argv[0]);
             return NULL;
         }
@@ -194,11 +283,8 @@ get_command_and_module(char *argv[], int *module, struct 
streamer *streamer)
 }
 
 static void
-print_command_params(const int module, const int command,
-                     struct streamer *streamer)
+print_command_params(const struct shell_cmd *shell_cmd, struct streamer 
*streamer)
 {
-       const struct shell_module *shell_module = &shell_modules[module];
-       const struct shell_cmd *shell_cmd = &shell_module->commands[command];
        int i;
 
        if (!(shell_cmd->help && shell_cmd->help->params)) {
@@ -216,19 +302,16 @@ static int
 show_cmd_help(char *argv[], struct streamer *streamer)
 {
     const char *command = NULL;
-    int module = -1;
-    const struct shell_module *shell_module = NULL;
+    const struct shell_mod *shell_module = NULL;
     const struct shell_cmd *cmd;
     int i;
 
-    command = get_command_and_module(argv, &module, streamer);
-    if ((module == -1) || (command == NULL)) {
+    command = get_command_and_module(argv, &shell_module, streamer);
+    if ((shell_module == NULL) || (command == NULL)) {
         return 0;
     }
 
-    shell_module = &shell_modules[module];
-    for (i = 0; shell_module->commands[i].sc_cmd; i++) {
-        cmd = &shell_module->commands[i];
+    for (i = 0; (cmd = shell_mod_command(shell_module, i)) != NULL; ++i) {
 
         if (!strcmp(command, cmd->sc_cmd)) {
             if (!cmd->help || (!cmd->help->summary &&
@@ -250,7 +333,7 @@ show_cmd_help(char *argv[], struct streamer *streamer)
 
             if (cmd->help->params) {
                 streamer_printf(streamer, "Parameters:\n");
-                print_command_params(module, i, streamer);
+                print_command_params(cmd, streamer);
             }
 
             return 0;
@@ -264,28 +347,21 @@ show_cmd_help(char *argv[], struct streamer *streamer)
 static void
 print_modules(struct streamer *streamer)
 {
-    int module;
-
-    for (module = 0; module < num_of_shell_entities; module++) {
-        streamer_printf(streamer, "%s\n", shell_modules[module].name);
+    LINK_TABLE_FOREACH(mod, shell_modules) {
+        streamer_printf(streamer, "%s\n", (*mod)->name);
     }
 }
 
 static void
-print_module_commands(const int module, struct streamer *streamer)
+print_module_commands(const struct shell_mod *shell_module, struct streamer 
*streamer)
 {
-    const struct shell_module *shell_module = &shell_modules[module];
+    const struct shell_cmd *cmd;
     int i;
 
-    streamer_printf(streamer, "help\n");
-
-    for (i = 0; shell_module->commands[i].sc_cmd; i++) {
-        streamer_printf(streamer, "%-30s", shell_module->commands[i].sc_cmd);
-        if (shell_module->commands[i].help &&
-            shell_module->commands[i].help->summary) {
-        
-            streamer_printf(streamer, "%s",
-                            shell_module->commands[i].help->summary);
+    for (i = 0; NULL != (cmd = shell_mod_command(shell_module, i)); ++i) {
+        streamer_printf(streamer, "%-30s", cmd->sc_cmd);
+        if (cmd->help && cmd->help->summary) {
+            streamer_printf(streamer, "%s", cmd->help->summary);
         }
         streamer_printf(streamer, "\n");
     }
@@ -295,18 +371,18 @@ static int
 show_help(const struct shell_cmd *cmd, int argc, char *argv[],
           struct streamer *streamer)
 {
-    int module;
+    const struct shell_mod *module;
 
     /* help per command */
-    if ((argc > 2) || ((default_module != -1) && (argc == 2))) {
+    if ((argc > 2) || ((default_module != NULL) && (argc == 2))) {
         return show_cmd_help(&argv[1], streamer);
     }
 
     /* help per module */
-    if ((argc == 2) || ((default_module != -1) && (argc == 1))) {
-        if (default_module == -1) {
+    if ((argc == 2) || ((default_module != NULL) && (argc == 1))) {
+        if (default_module == NULL) {
             module = get_destination_module(argv[1], -1);
-            if (module == -1) {
+            if (module == NULL) {
                 streamer_printf(streamer, "Illegal module %s\n", argv[1]);
                 return 0;
             }
@@ -325,17 +401,16 @@ show_help(const struct shell_cmd *cmd, int argc, char 
*argv[],
     return 0;
 }
 
-static const struct shell_cmd shell_cmd_help =
-    SHELL_CMD_EXT("help", show_help, NULL);
+MAKE_SHELL_CMD(help, show_help, NULL)
 
 static int
 set_default_module(const char *name)
 {
-    int module;
+    const struct shell_mod *module;
 
     module = get_destination_module(name, -1);
 
-    if (module == -1) {
+    if (module == NULL) {
         return -1;
     }
 
@@ -349,7 +424,7 @@ select_module(const struct shell_cmd *cmd, int argc, char 
*argv[],
               struct streamer *streamer)
 {
     if (argc == 1) {
-        default_module = -1;
+        default_module = NULL;
     } else {
         set_default_module(argv[1]);
     }
@@ -357,17 +432,16 @@ select_module(const struct shell_cmd *cmd, int argc, char 
*argv[],
     return 0;
 }
 
-static const struct shell_cmd shell_cmd_select_module =
-    SHELL_CMD_EXT("select", select_module, NULL);
+MAKE_SHELL_CMD(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;
-    int def_module = default_module;
-    const struct shell_module *shell_module;
+    const struct shell_mod *def_module = default_module;
+    const struct shell_mod *shell_module;
     const char *command;
+    const struct shell_cmd *cmd;
     int i;
 
     if (!first_string || first_string[0] == '\0') {
@@ -377,7 +451,7 @@ shell_find_cmd(int argc, char *argv[], struct streamer 
*streamer)
 
     if (first_string[0] == '/') {
         first_string++;
-        def_module = -1;
+        def_module = NULL;
     }
 
     if (!strcmp(first_string, "help")) {
@@ -385,23 +459,22 @@ shell_find_cmd(int argc, char *argv[], struct streamer 
*streamer)
     }
 
     if (!strcmp(first_string, "select")) {
-        return &shell_cmd_select_module;
+        return &shell_cmd_select;
     }
 
-    if ((argc == 1) && (def_module == -1)) {
+    if ((argc == 1) && (def_module == NULL)) {
         streamer_printf(streamer, "Missing parameter\n");
         return NULL;
     }
 
-    command = get_command_and_module(argv, &module, streamer);
-    if ((module == -1) || (command == NULL)) {
+    command = get_command_and_module(argv, &shell_module, streamer);
+    if ((shell_module == NULL) || (command == NULL)) {
         return NULL;
     }
 
-    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];
+    for (i = 0; NULL != (cmd = shell_mod_command(shell_module, i)); ++i) {
+        if (!strcmp(command, cmd->sc_cmd)) {
+            return cmd;
         }
     }
 
@@ -414,7 +487,7 @@ shell_exec(int argc, char **argv, struct streamer *streamer)
     const struct shell_cmd *cmd;
     size_t argc_offset = 0;
     int rc;
-    int def_module = default_module;
+    const struct shell_mod *def_module = default_module;
 
     cmd = shell_find_cmd(argc, argv, streamer);
     if (!cmd) {
@@ -430,13 +503,12 @@ shell_exec(int argc, char **argv, struct streamer 
*streamer)
     }
 
     if (argv[0][0] == '/') {
-        def_module = -1;
+        def_module = NULL;
     }
     /* Allow invoking a cmd with module name as a prefix; a command should
      * not know how it was invoked (with or without prefix)
      */
-    if (def_module == -1 && cmd != &shell_cmd_select_module &&
-        cmd != &shell_cmd_help) {
+    if (def_module == NULL && cmd != &shell_cmd_select && cmd != 
&shell_cmd_help) {
         argc_offset = 1;
     }
 
@@ -524,24 +596,23 @@ shell(struct os_event *ev)
 }
 
 #if MYNEWT_VAL(SHELL_COMPLETION)
-static int
-get_command_from_module(const char *command, int len, int module)
+const struct shell_cmd *
+get_command_from_module(const char *command, int len, const struct shell_mod 
*shell_module)
 {
     int i;
-    const struct shell_module *shell_module;
+    const struct shell_cmd *cmd;
 
-    shell_module = &shell_modules[module];
-    for (i = 0; shell_module->commands[i].sc_cmd; i++) {
+    for (i = 0; NULL != (cmd = shell_mod_command(shell_module, i)); ++i) {
 
-        if (strlen(shell_module->commands[i].sc_cmd) != len) {
+        if (strlen(cmd->sc_cmd) != len) {
             continue;
         }
 
-        if (!strncmp(command, shell_module->commands[i].sc_cmd, len)) {
-            return i;
+        if (strncmp(command, cmd->sc_cmd, len) == 0) {
+            return cmd;
         }
     }
-    return -1;
+    return NULL;
 }
 
 static int
@@ -583,15 +654,11 @@ get_last_token(char **cur)
 }
 
 static void
-complete_param(char *line, const char *param_prefix,
-               int param_len, int module_idx, int command_idx,
-               console_append_char_cb append_char)
+complete_param(char *line, const char *param_prefix, int param_len,
+               const struct shell_cmd *command, console_append_char_cb 
append_char)
 {
     const char *first_match = NULL;
     int i, j, common_chars = -1;
-    const struct shell_cmd *command;
-
-    command = &shell_modules[module_idx].commands[command_idx];
 
     if (!(command->help && command->help->params)) {
         return;
@@ -649,26 +716,25 @@ complete_param(char *line, const char *param_prefix,
 }
 
 static void
-complete_command(char *line, char *command_prefix,
-                 int command_len, int module_idx,
-                 console_append_char_cb append_char)
+complete_command(char *line, char *command_prefix, int command_len,
+                 const struct shell_mod *module, console_append_char_cb 
append_char)
 {
     int first_match = -1;
     int match_count = 0;
     int i, j, common_chars = -1;
-    const struct shell_cmd *commands;
-
-    commands = shell_modules[module_idx].commands;
+    const struct shell_cmd *match = NULL;
+    const struct shell_cmd *command;
 
-    for (i = 0; commands[i].sc_cmd; i++) {
-        if (0 != strncmp(command_prefix, commands[i].sc_cmd, command_len)) {
+    for (i = 0; NULL != (command = shell_mod_command(module, i)); ++i) {
+        if (0 != strncmp(command_prefix, command->sc_cmd, command_len)) {
             continue;
         }
         match_count++;
 
         if (match_count == 1) {
             first_match = i;
-            common_chars = strlen(commands[i].sc_cmd);
+            match = command;
+            common_chars = strlen(command->sc_cmd);
             continue;
         }
 
@@ -681,7 +747,7 @@ complete_command(char *line, char *command_prefix,
         }
         /* Check how many additional chars are same as first command's */
         for (j = command_len; j < common_chars; j++) {
-            if (commands[first_match].sc_cmd[j] != commands[i].sc_cmd[j]) {
+            if (match->sc_cmd[j] != command->sc_cmd[j]) {
                 break;
             }
         }
@@ -696,7 +762,7 @@ complete_command(char *line, char *command_prefix,
     if (common_chars > command_len) {
         /* complete common part */
         for (i = command_len; i < common_chars; i++) {
-            if (!append_char(line, (uint8_t)commands[first_match].sc_cmd[i])) {
+            if (!append_char(line, (uint8_t)match->sc_cmd[i])) {
                 return;
             }
         }
@@ -716,10 +782,10 @@ complete_command(char *line, char *command_prefix,
      * list all possible matches.
      */
     console_out('\n');
-    console_printf("%s\n", commands[first_match].sc_cmd);
-    for (i = first_match + 1; commands[i].sc_cmd; i++) {
-        if (0 == strncmp(command_prefix, commands[i].sc_cmd, command_len)) {
-            console_printf("%s\n", commands[i].sc_cmd);
+    console_printf("%s\n", match->sc_cmd);
+    for (i = first_match + 1; NULL != (command = shell_mod_command(module, 
i)); ++i) {
+        if (0 == strncmp(command_prefix, command->sc_cmd, command_len)) {
+            console_printf("%s\n", command->sc_cmd);
         }
     }
     /* restore prompt */
@@ -733,26 +799,25 @@ complete_module(char *line, char *module_prefix,
     int i, j;
     const char *first_match = NULL;
     int common_chars = -1, space = 0;
+    shell_mod_t mod;
 
     if (!module_len) {
         console_out('\n');
-        for (i = 0; i < num_of_shell_entities; i++) {
-            console_printf("%s\n", shell_modules[i].name);
+        for (i = 0; NULL != (mod = shell_module_get(i)); ++i) {
+            console_printf("%s\n", mod->name);
         }
         print_prompt(line);
         return;
     }
 
-    for (i = 0; i < num_of_shell_entities; i++) {
+    for (i = 0; NULL != (mod = shell_module_get(i)); ++i) {
 
-        if (strncmp(module_prefix,
-                     shell_modules[i].name,
-                     module_len)) {
+        if (strncmp(module_prefix, mod->name, module_len)) {
             continue;
         }
 
         if (!first_match) {
-            first_match = shell_modules[i].name;
+            first_match = mod->name;
             continue;
         }
 
@@ -765,14 +830,14 @@ complete_module(char *line, char *module_prefix,
 
         /* cut common part of matching names */
         for (j = 0; j < common_chars; j++) {
-            if (first_match[j] != shell_modules[i].name[j]) {
+            if (first_match[j] != mod->name[j]) {
                 break;
             }
         }
 
         common_chars = j;
 
-        console_printf("%s\n", shell_modules[i].name);
+        console_printf("%s\n", mod->name);
     }
 
     /* no match, do nothing */
@@ -826,9 +891,10 @@ completion(char *line, console_append_char_cb append_char)
 {
     char *cur;
     int tok_len;
-    int module, command;
+    const struct shell_cmd *command;
     int null_terminated = 0;
-    int def_module = default_module;
+    const struct shell_mod *def_module = default_module;
+    const struct shell_mod *module;
 
     /*
      * line to completion is not ended by '\0' as the line that gets from
@@ -841,7 +907,7 @@ completion(char *line, console_append_char_cb append_char)
     cur = line;
     tok_len = get_token(&cur, &null_terminated);
     if (tok_len > 0 && cur[0] == '/') {
-        def_module = -1;
+        def_module = NULL;
         tok_len--;
         cur++;
     }
@@ -849,7 +915,7 @@ completion(char *line, console_append_char_cb append_char)
     /* empty token - print options */
     if (tok_len == 0) {
         console_out('\n');
-        if (def_module == -1) {
+        if (def_module == NULL) {
             print_modules(streamer_console_get());
         } else {
             print_module_commands(def_module, streamer_console_get());
@@ -860,7 +926,7 @@ completion(char *line, console_append_char_cb append_char)
 
     /* token can be completed */
     if (null_terminated) {
-        if (def_module == -1) {
+        if (def_module == NULL) {
             complete_module(line, cur, tok_len, append_char);
             return;
         }
@@ -874,12 +940,12 @@ completion(char *line, console_append_char_cb append_char)
         return;
     }
 
-    if (def_module != -1) {
+    if (def_module != NULL) {
         module = def_module;
     } else {
         module = get_destination_module(cur, tok_len);
 
-        if (module == -1) {
+        if (module == NULL) {
             return;
         }
 
@@ -901,7 +967,7 @@ completion(char *line, console_append_char_cb append_char)
     }
 
     command = get_command_from_module(cur, tok_len, module);
-    if (command == -1) {
+    if (command == NULL) {
         return;
     }
 
@@ -909,12 +975,11 @@ completion(char *line, console_append_char_cb append_char)
     tok_len = get_last_token(&cur);
     if (tok_len == 0) {
         console_out('\n');
-        print_command_params(module, command, streamer_console_get());
+        print_command_params(command, streamer_console_get());
         print_prompt(line);
         return;
     }
-    complete_param(line, cur, tok_len,
-                   module, command, append_char);
+    complete_param(line, cur, tok_len, command, append_char);
     return;
 }
 #endif /* MYNEWT_VAL(SHELL_COMPLETION) */
@@ -960,46 +1025,32 @@ shell_register(const char *module_name, const struct 
shell_cmd *commands)
     if (num_of_shell_entities >= MYNEWT_VAL(SHELL_MAX_MODULES)) {
         DFLT_LOG_ERROR("Max number of modules reached\n");
         assert(0);
+    } else if (MYNEWT_VAL(SHELL_MAX_MODULES) > 0) {
+        registered_shell_modules[num_of_shell_entities].mod.name = module_name;
+        registered_shell_modules[num_of_shell_entities].mod.ops = 
&shell_mod_std_ops;
+        registered_shell_modules[num_of_shell_entities].commands = commands;
+        /* commands_end will point to empty command */
+        while (commands->sc_cmd) {
+            ++commands;
+        }
+        registered_shell_modules[num_of_shell_entities].commands_end = 
commands;
+        ++num_of_shell_entities;
     }
 
-    shell_modules[num_of_shell_entities].name = module_name;
-    shell_modules[num_of_shell_entities].commands = commands;
-    ++num_of_shell_entities;
-
     return 0;
 }
 
-#if MYNEWT_VAL(SHELL_COMPAT)
-#define SHELL_COMPAT_MODULE_NAME "compat"
-static struct shell_cmd compat_commands[MYNEWT_VAL(SHELL_MAX_COMPAT_COMMANDS) 
+ 1];
-static int num_compat_commands;
-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)) {
         DFLT_LOG_ERROR(
                      "Max number of compat commands reached\n");
         assert(0);
+    } else if (MYNEWT_VAL(SHELL_MAX_COMPAT_COMMANDS) > 0) {
+        registered_compat_commands[num_compat_commands] = *sc;
+        ++num_compat_commands;
     }
-
-    if (!module_registered) {
-        shell_register(SHELL_COMPAT_MODULE_NAME, compat_commands);
-        module_registered = 1;
-
-        rc = set_default_module(SHELL_COMPAT_MODULE_NAME);
-        if (rc != 0) {
-            DFLT_LOG_ERROR(
-                         "Illegal module %s, default is not changed\n",
-                         SHELL_COMPAT_MODULE_NAME);
-        }
-    }
-
-    compat_commands[num_compat_commands] = *sc;
-    ++num_compat_commands;
     return 0;
 }
 #endif
@@ -1027,12 +1078,6 @@ shell_init(void)
     console_set_completion_cb(completion);
 #endif
 
-#if MYNEWT_VAL(SHELL_OS_MODULE)
-    shell_os_register();
-#endif
-#if MYNEWT_VAL(SHELL_PROMPT_MODULE)
-    shell_prompt_register();
-#endif
 #if MYNEWT_VAL(SHELL_BRIDGE)
     shell_bridge_init();
 #endif

Reply via email to