gw16012: use register_commands()
[openocd.git] / src / helper / command.c
index b81d2d19591eba1249ab87413a3e8ee7d7571aa4..dd109657069aa349b5f1e874d5577c90aa9e38e7 100644 (file)
@@ -108,11 +108,24 @@ static const char **script_command_args_alloc(
        return words;
 }
 
+static struct command_context *current_command_context(void)
+{
+       /* grab the command context from the associated data */
+       struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
+       if (NULL == cmd_ctx)
+       {
+               /* Tcl can invoke commands directly instead of via command_run_line(). This would
+                * happen when the Jim Tcl interpreter is provided by eCos.
+                */
+               cmd_ctx = global_cmd_ctx;
+       }
+       return cmd_ctx;
+}
+
 static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        /* the private data is stashed in the interp structure */
        struct command *c;
-       struct command_context *context;
        int retval;
 
        /* DANGER!!!! be careful what we invoke here, since interp->cmdPrivData might
@@ -136,16 +149,6 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        if (NULL == words)
                return JIM_ERR;
 
-       /* grab the command context from the associated data */
-       context = Jim_GetAssocData(interp, "context");
-       if (context == NULL)
-       {
-               /* Tcl can invoke commands directly instead of via command_run_line(). This would
-                * happen when the Jim Tcl interpreter is provided by eCos.
-                */
-               context = global_cmd_ctx;
-       }
-
        /* capture log output and return it */
        Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
        /* a garbage collect can happen, so we need a reference count to this object */
@@ -153,7 +156,8 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
        log_add_callback(tcl_output, tclOutput);
 
-       retval = run_command(context, c, (const char **)words, nwords);
+       struct command_context *cmd_ctx = current_command_context();
+       retval = run_command(cmd_ctx, c, (const char **)words, nwords);
 
        log_remove_callback(tcl_output, tclOutput);
 
@@ -189,6 +193,16 @@ static struct command *command_find(struct command *head, const char *name)
        }
        return NULL;
 }
+struct command *command_find_in_context(struct command_context *cmd_ctx,
+               const char *name)
+{
+       return command_find(cmd_ctx->commands, name);
+}
+struct command *command_find_in_parent(struct command *parent,
+               const char *name)
+{
+       return command_find(parent->children, name);
+}
 
 /**
  * Add the command into the linked list, sorted by name.
@@ -839,6 +853,70 @@ COMMAND_HANDLER(handle_usage_command)
        return CALL_COMMAND_HANDLER(command_help_show, c, 0, false);
 }
 
+static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
+               struct command *head, struct command **out)
+{
+       if (0 == argc)
+               return argc;
+       struct command *c = command_find(head, Jim_GetString(argv[0], NULL));
+       if (NULL == c)
+               return argc;
+       *out = c;
+       return command_unknown_find(--argc, ++argv, (*out)->children, out);
+}
+
+static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+       script_debug(interp, cmd_name, argc - 1, argv + 1);
+
+       struct command_context *cmd_ctx = current_command_context();
+       struct command *c = cmd_ctx->commands;
+       int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
+       // if nothing could be consumed, then it's really an unknown command
+       if (remaining == argc - 1)
+       {
+               const char *cmd = Jim_GetString(argv[1], NULL);
+               LOG_ERROR("Unknown command:\n  %s", cmd);
+               return JIM_OK;
+       }
+
+       bool found = true;
+       Jim_Obj *const *start;
+       unsigned count;
+       if (c->handler)
+       {
+               // include the command name in the list
+               count = remaining + 1;
+               start = argv + (argc - remaining - 1);
+       }
+       else
+       {
+               c = command_find(cmd_ctx->commands, "help");
+               if (NULL == c)
+               {
+                       LOG_ERROR("unknown command, but help is missing too");
+                       return JIM_ERR;
+               }
+               count = argc - remaining;
+               start = argv;
+               found = false;
+       }
+
+       unsigned nwords;
+       const char **words = script_command_args_alloc(count, start, &nwords);
+       if (NULL == words)
+               return JIM_ERR;
+
+       int retval = run_command(cmd_ctx, c, words, nwords);
+
+       script_command_args_free(words, nwords);
+
+       if (!found && ERROR_OK == retval)
+               retval = ERROR_FAIL;
+
+       return retval;
+}
 
 int help_add_command(struct command_context *cmd_ctx, struct command *parent,
                const char *cmd_name, const char *help_text, const char *usage)
@@ -1018,6 +1096,7 @@ struct command_context* command_init(const char *startup_tcl)
        Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
                        Jim_NewStringObj(interp, HostOs , strlen(HostOs)));
 
+       Jim_CreateCommand(interp, "unknown", &command_unknown, NULL, NULL);
        Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
        Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL);
        Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)