helper/command: simplify jim_command_mode()
[openocd.git] / src / helper / command.c
index 3b531807f3dd1aba1d0364aaf6278c84d7982905..5cddf2150e4ba401165157efaf731ef33d21031a 100644 (file)
@@ -52,16 +52,27 @@ struct log_capture_state {
 static int unregister_command(struct command_context *context,
        struct command *parent, const char *name);
 static char *command_name(struct command *c, char delim);
+static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj * const *argv);
 static int help_add_command(struct command_context *cmd_ctx,
        const char *cmd_name, const char *help_text, const char *usage_text);
 static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name);
 
-/* wrap jimtcl internal data */
+/* set of functions to wrap jimtcl internal data */
 static inline bool jimcmd_is_proc(Jim_Cmd *cmd)
 {
        return cmd->isproc;
 }
 
+static inline bool jimcmd_is_ocd_command(Jim_Cmd *cmd)
+{
+       return !cmd->isproc && cmd->u.native.cmdProc == command_unknown;
+}
+
+static inline void *jimcmd_privdata(Jim_Cmd *cmd)
+{
+       return cmd->isproc ? NULL : cmd->u.native.privData;
+}
+
 static void tcl_output(void *privData, const char *file, unsigned line,
        const char *function, const char *string)
 {
@@ -232,13 +243,6 @@ struct command_context *current_command_context(Jim_Interp *interp)
        return cmd_ctx;
 }
 
-static struct command *command_root(struct command *c)
-{
-       while (NULL != c->parent)
-               c = c->parent;
-       return c;
-}
-
 /**
  * Find a command by name from a list of commands.
  * @returns Returns the named command if it exists in the list.
@@ -347,20 +351,6 @@ command_new_error:
        return NULL;
 }
 
-static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
-static int register_command_handler(struct command_context *cmd_ctx,
-       struct command *c)
-{
-       Jim_Interp *interp = cmd_ctx->interp;
-
-#if 0
-       LOG_DEBUG("registering '%s'...", c->name);
-#endif
-
-       return Jim_CreateCommand(interp, c->name, command_unknown, c, NULL);
-}
-
 static struct command *register_command(struct command_context *context,
        struct command *parent, const struct command_registration *cr)
 {
@@ -383,12 +373,13 @@ static struct command *register_command(struct command_context *context,
        if (NULL == c)
                return NULL;
 
-       if (cr->jim_handler || cr->handler) {
-               int retval = register_command_handler(context, command_root(c));
-               if (retval != JIM_OK) {
-                       unregister_command(context, parent, name);
-                       return NULL;
-               }
+       char *full_name = command_name(c, ' ');
+       LOG_DEBUG("registering '%s'...", full_name);
+       int retval = Jim_CreateCommand(context->interp, full_name,
+                               command_unknown, c, NULL);
+       if (retval != JIM_OK) {
+               unregister_command(context, parent, name);
+               return NULL;
        }
        return c;
 }
@@ -563,7 +554,7 @@ static char *command_name(struct command *c, char delim)
        return __command_name(c, delim, 0);
 }
 
-static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
+static bool command_can_run(struct command_context *cmd_ctx, struct command *c, const char *full_name)
 {
        if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode)
                return true;
@@ -582,10 +573,8 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
                        when = "if Cthulhu is summoned by";
                        break;
        }
-       char *full_name = command_name(c, ' ');
        LOG_ERROR("The '%s' command must be used %s 'init'.",
                        full_name ? full_name : c->name, when);
-       free(full_name);
        return false;
 }
 
@@ -606,20 +595,13 @@ static int run_command(struct command_context *context,
        int retval = c->handler(&cmd);
        if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
                /* Print help for command */
-               char *full_name = command_name(c, ' ');
-               if (NULL != full_name) {
-                       command_run_linef(context, "usage %s", full_name);
-                       free(full_name);
-               }
+               command_run_linef(context, "usage %s", words[0]);
        } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
                /* just fall through for a shutdown request */
        } else {
-               if (retval != ERROR_OK) {
-                       char *full_name = command_name(c, ' ');
+               if (retval != ERROR_OK)
                        LOG_DEBUG("Command '%s' failed with error code %d",
-                                               full_name ? full_name : c->name, retval);
-                       free(full_name);
-               }
+                                               words[0], retval);
                /* Use the command output as the Tcl result */
                Jim_SetResult(context->interp, cmd.output);
        }
@@ -941,19 +923,6 @@ COMMAND_HANDLER(handle_help_command)
        return retval;
 }
 
-static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
-       struct command *head, struct command **out)
-{
-       if (0 == argc)
-               return argc;
-       const char *cmd_name = Jim_GetString(argv[0], NULL);
-       struct command *c = command_find(head, cmd_name);
-       if (NULL == c)
-               return argc;
-       *out = c;
-       return command_unknown_find(--argc, ++argv, (*out)->children, out);
-}
-
 static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv)
 {
        char *prev, *all;
@@ -980,41 +949,8 @@ static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv)
        return all;
 }
 
-static int run_usage(Jim_Interp *interp, int argc_valid, int argc, Jim_Obj * const *argv)
-{
-       struct command_context *cmd_ctx = current_command_context(interp);
-       char *command;
-       int retval;
-
-       assert(argc_valid >= 1);
-       assert(argc >= argc_valid);
-
-       command = alloc_concatenate_strings(argc_valid, argv);
-       if (!command)
-               return JIM_ERR;
-
-       retval = command_run_linef(cmd_ctx, "usage %s", command);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("unable to execute command \"usage %s\"", command);
-               return JIM_ERR;
-       }
-
-       if (argc_valid == argc)
-               LOG_ERROR("%s: command requires more arguments", command);
-       else {
-               free(command);
-               command = alloc_concatenate_strings(argc - argc_valid, argv + argc_valid);
-               if (!command)
-                       return JIM_ERR;
-               LOG_ERROR("invalid subcommand \"%s\"", command);
-       }
-
-       free(command);
-       return retval;
-}
-
 static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx,
-               struct command *c, int argc, Jim_Obj *const *argv)
+               struct command *c, int argc, Jim_Obj * const *argv)
 {
        if (c->jim_handler)
                return c->jim_handler(interp, argc, argv);
@@ -1034,30 +970,30 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        script_debug(interp, argc, argv);
 
-       struct command_context *cmd_ctx = current_command_context(interp);
-       struct command *c = cmd_ctx->commands;
-       int remaining = command_unknown_find(argc, argv, c, &c);
-       /* if nothing could be consumed, then it's really an unknown command */
-       if (remaining == argc) {
-               const char *cmd = Jim_GetString(argv[0], NULL);
-               LOG_ERROR("Unknown command:\n  %s", cmd);
-               return JIM_OK;
+       /* check subcommands */
+       if (argc > 1) {
+               char *s = alloc_printf("%s %s", Jim_GetString(argv[0], NULL), Jim_GetString(argv[1], NULL));
+               Jim_Obj *js = Jim_NewStringObj(interp, s, -1);
+               Jim_IncrRefCount(js);
+               free(s);
+               Jim_Cmd *cmd = Jim_GetCommand(interp, js, JIM_NONE);
+               if (cmd) {
+                       int retval = Jim_EvalObjPrefix(interp, js, argc - 2, argv + 2);
+                       Jim_DecrRefCount(interp, js);
+                       return retval;
+               }
+               Jim_DecrRefCount(interp, js);
        }
 
-       Jim_Obj *const *start;
-       unsigned count;
-       if (c->handler || c->jim_handler) {
-               /* include the command name in the list */
-               count = remaining + 1;
-               start = argv + (argc - remaining - 1);
-       } else {
-               count = argc - remaining;
-               start = argv;
-               run_usage(interp, count, argc, start);
+       struct command *c = jim_to_command(interp);
+       if (!c->jim_handler && !c->handler) {
+               Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv);
                return JIM_ERR;
        }
 
-       if (!command_can_run(cmd_ctx, c))
+       struct command_context *cmd_ctx = current_command_context(interp);
+
+       if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
                return JIM_ERR;
 
        target_call_timer_callbacks_now();
@@ -1076,7 +1012,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        if (c->jim_override_target)
                cmd_ctx->current_target_override = c->jim_override_target;
 
-       int retval = exec_command(interp, cmd_ctx, c, count, start);
+       int retval = exec_command(interp, cmd_ctx, c, argc, argv);
 
        if (c->jim_override_target)
                cmd_ctx->current_target_override = saved_target_override;
@@ -1098,18 +1034,19 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE);
                Jim_DecrRefCount(interp, s);
                free(full_name);
-               if (cmd && jimcmd_is_proc(cmd)) {
-                       Jim_SetResultString(interp, "any", -1);
-                       return JIM_OK;
-               }
-               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 an unknown command */
-               if (remaining == argc - 1) {
+               if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_ocd_command(cmd))) {
                        Jim_SetResultString(interp, "unknown", -1);
                        return JIM_OK;
                }
-               mode = c->mode;
+
+               if (jimcmd_is_proc(cmd)) {
+                       /* tcl proc */
+                       mode = COMMAND_ANY;
+               } else {
+                       struct command *c = jimcmd_privdata(cmd);
+
+                       mode = c->mode;
+               }
        } else
                mode = cmd_ctx->mode;
 

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)