helper/command: unregister commands through their full-name 74/5674/9
authorAntonio Borneo <borneo.antonio@gmail.com>
Wed, 13 May 2020 13:35:19 +0000 (15:35 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sun, 18 Apr 2021 14:34:43 +0000 (15:34 +0100)
While keeping the struct command in place, unregister the jim
commands by scanning the list of jim commands through their
full-name.

Change-Id: I0e903fbc31172858b703d67ccd471809c7949e86
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5674
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
src/helper/command.c
src/helper/command.h

index 5cddf2150e4ba401165157efaf731ef33d21031a..d79d7f464771d483f350c6cdd3ccb4ec2a1aff4e 100644 (file)
@@ -243,6 +243,26 @@ struct command_context *current_command_context(Jim_Interp *interp)
        return cmd_ctx;
 }
 
+/**
+ * Find a openocd command from fullname.
+ * @returns Returns the named command if it is registred in interp.
+ * Returns NULL otherwise.
+ */
+static struct command *command_find_from_name(Jim_Interp *interp, const char *name)
+{
+       if (!name)
+               return NULL;
+
+       Jim_Obj *jim_name = Jim_NewStringObj(interp, name, -1);
+       Jim_IncrRefCount(jim_name);
+       Jim_Cmd *cmd = Jim_GetCommand(interp, jim_name, JIM_NONE);
+       Jim_DecrRefCount(interp, jim_name);
+       if (!cmd || jimcmd_is_proc(cmd) || !jimcmd_is_ocd_command(cmd))
+               return NULL;
+
+       return jimcmd_privdata(cmd);
+}
+
 /**
  * Find a command by name from a list of commands.
  * @returns Returns the named command if it exists in the list.
@@ -429,12 +449,80 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
        return ___register_commands(cmd_ctx, parent, cmds, data, override_target);
 }
 
+static __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)))
+int unregister_commands_match(struct command_context *cmd_ctx, const char *format, ...)
+{
+       Jim_Interp *interp = cmd_ctx->interp;
+       va_list ap;
+
+       va_start(ap, format);
+       char *query = alloc_vprintf(format, ap);
+       va_end(ap);
+       if (!query)
+               return ERROR_FAIL;
+
+       char *query_cmd = alloc_printf("info commands {%s}", query);
+       free(query);
+       if (!query_cmd)
+               return ERROR_FAIL;
+
+       int retval = Jim_EvalSource(interp, __THIS__FILE__, __LINE__, query_cmd);
+       free(query_cmd);
+       if (retval != JIM_OK)
+               return ERROR_FAIL;
+
+       Jim_Obj *list = Jim_GetResult(interp);
+       Jim_IncrRefCount(list);
+
+       int len = Jim_ListLength(interp, list);
+       for (int i = 0; i < len; i++) {
+               Jim_Obj *elem = Jim_ListGetIndex(interp, list, i);
+               Jim_IncrRefCount(elem);
+
+               const char *name = Jim_GetString(elem, NULL);
+               struct command *c = command_find_from_name(interp, name);
+               if (!c) {
+                       /* not openocd command */
+                       Jim_DecrRefCount(interp, elem);
+                       continue;
+               }
+               LOG_DEBUG("delete command \"%s\"", name);
+               Jim_DeleteCommand(interp, elem);
+
+               help_del_command(cmd_ctx, name);
+
+               Jim_DecrRefCount(interp, elem);
+       }
+
+       Jim_DecrRefCount(interp, list);
+       return ERROR_OK;
+}
+
 int unregister_all_commands(struct command_context *context,
-       struct command *parent)
+       const char *cmd_prefix)
 {
-       if (context == NULL)
+       struct command *parent = NULL;
+
+       if (!context)
                return ERROR_OK;
 
+       if (!cmd_prefix || !*cmd_prefix) {
+               int retval = unregister_commands_match(context, "*");
+               if (retval != ERROR_OK)
+                       return retval;
+       } else {
+               Jim_Cmd *cmd = Jim_GetCommand(context->interp, Jim_NewStringObj(context->interp, cmd_prefix, -1), JIM_NONE);
+               if (cmd && jimcmd_is_ocd_command(cmd))
+                       parent = jimcmd_privdata(cmd);
+
+               int retval = unregister_commands_match(context, "%s *", cmd_prefix);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = unregister_commands_match(context, "%s", cmd_prefix);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
        struct command **head = command_list_for_parent(context, parent);
        while (NULL != *head) {
                struct command *tmp = *head;
@@ -458,7 +546,11 @@ static int unregister_command(struct command_context *context,
                        continue;
 
                char *full_name = command_name(c, ' ');
-               help_del_command(context, full_name);
+
+               int retval = unregister_commands_match(context, "%s", full_name);
+               if (retval != ERROR_OK)
+                       return retval;
+
                free(full_name);
 
                if (p)
index db095972af3725fa0921ad90799408cfa4572ce2..4d1928c5a9630ecd03d249e607bebaac7041978e 100644 (file)
@@ -311,11 +311,11 @@ static inline int register_commands_with_data(struct command_context *cmd_ctx,
 /**
  * Unregisters all commands from the specified context.
  * @param cmd_ctx The context that will be cleared of registered commands.
- * @param parent If given, only clear commands from under this one command.
+ * @param cmd_prefix If given, only clear commands from under this one command.
  * @returns ERROR_OK on success, or an error code.
  */
 int unregister_all_commands(struct command_context *cmd_ctx,
-               struct command *parent);
+               const char *cmd_prefix);
 
 /**
  * Unregisters the help for all commands. Used at exit to remove the help

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)