add command_name helper
authorZachary T Welch <zw@superlucidity.net>
Wed, 11 Nov 2009 13:26:17 +0000 (05:26 -0800)
committerZachary T Welch <zw@superlucidity.net>
Wed, 11 Nov 2009 20:15:39 +0000 (12:15 -0800)
The command_name function returns a malloced string for a given
command and its parents.  This can be used to display a message
to the user, but it is used internally to handle registration
and syntax errors.  This helps permit arbitrary command nesting.

src/helper/command.c
src/helper/command.h

index c6327029217ab0506dcd22bba8cc97d2df5f1911..86158d72b23f3f7f992aac04952f8dc7e6b9c192 100644 (file)
@@ -217,32 +217,22 @@ command_t* register_command(command_context_t *context, command_t *parent, char
        if (c->handler == NULL)
                return c;
 
        if (c->handler == NULL)
                return c;
 
-       /* If this is a two level command, e.g. "flash banks", then the
-        * "unknown" proc in startup.tcl must redirect to  this command.
-        *
-        * "flash banks" is translated by "unknown" to "flash_banks"
-        * if such a proc exists
-        */
-       /* Print help for command */
-       const char *t1="";
-       const char *t2="";
-       const char *t3="";
-       /* maximum of two levels :-) */
-       if (c->parent != NULL)
-       {
-               t1 = c->parent->name;
-               t2="_";
-       }
-       t3 = c->name;
-       const char *full_name = alloc_printf("ocd_%s%s%s", t1, t2, t3);
-       Jim_CreateCommand(interp, full_name, script_command, c, NULL);
-       free((void *)full_name);
+       const char *full_name = command_name(c, '_');
+
+       const char *ocd_name = alloc_printf("ocd_%s", full_name);
+       Jim_CreateCommand(interp, ocd_name, script_command, c, NULL);
+       free((void *)ocd_name);
 
        /* we now need to add an overrideable proc */
 
        /* we now need to add an overrideable proc */
-       const char *override_name = alloc_printf("proc %s%s%s {args} {if {[catch {eval ocd_%s%s%s $args}]==0} {return \"\"} else { return -code error }", t1, t2, t3, t1, t2, t3);
+       const char *override_name = alloc_printf("proc %s {args} {"
+                       "if {[catch {eval ocd_%s $args}] == 0} "
+                       "{return \"\"} else {return -code error}}",
+                       full_name, full_name);
        Jim_Eval_Named(interp, override_name, __THIS__FILE__, __LINE__);
        free((void *)override_name);
 
        Jim_Eval_Named(interp, override_name, __THIS__FILE__, __LINE__);
        free((void *)override_name);
 
+       free((void *)full_name);
+
        /* accumulate help text in Tcl helptext list.  */
        Jim_Obj *helptext = Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
        if (Jim_IsShared(helptext))
        /* accumulate help text in Tcl helptext list.  */
        Jim_Obj *helptext = Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
        if (Jim_IsShared(helptext))
@@ -404,6 +394,28 @@ void command_print(command_context_t *context, const char *format, ...)
        va_end(ap);
 }
 
        va_end(ap);
 }
 
+static char *__command_name(struct command_s *c, char delim, unsigned extra)
+{
+       char *name;
+       unsigned len = strlen(c->name);
+       if (NULL == c->parent) {
+               // allocate enough for the name, child names, and '\0'
+               name = malloc(len + extra + 1);
+               strcpy(name, c->name);
+       } else {
+               // parent's extra must include both the space and name
+               name = __command_name(c->parent, delim, 1 + len + extra);
+               char dstr[2] = { delim, 0 };
+               strcat(name, dstr);
+               strcat(name, c->name);
+       }
+       return name;
+}
+char *command_name(struct command_s *c, char delim)
+{
+       return __command_name(c, delim, 0);
+}
+
 static int run_command(command_context_t *context,
                command_t *c, char *words[], unsigned num_words)
 {
 static int run_command(command_context_t *context,
                command_t *c, char *words[], unsigned num_words)
 {
@@ -419,17 +431,12 @@ static int run_command(command_context_t *context,
        if (retval == ERROR_COMMAND_SYNTAX_ERROR)
        {
                /* Print help for command */
        if (retval == ERROR_COMMAND_SYNTAX_ERROR)
        {
                /* Print help for command */
-               const char *t1="";
-               const char *t2="";
-               const char *t3="";
-               /* maximum of two levels :-) */
-               if (c->parent != NULL)
-               {
-                       t1 = c->parent->name;
-                       t2=" ";
-               }
-               t3 = c->name;
-               command_run_linef(context, "help {%s%s%s}", t1, t2, t3);
+               char *full_name = command_name(c, ' ');
+               if (NULL != full_name) {
+                       command_run_linef(context, "help %s", full_name);
+                       free(full_name);
+               } else
+                       retval = -ENOMEM;
        }
        else if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
        {
        }
        else if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
        {
index 0b86b881e4d056f08fc0a69dd7db1f6f6975f469..732fa525ade98678d252c28bd43b98f328f8103f 100644 (file)
@@ -84,6 +84,16 @@ typedef struct command_s
        struct command_s *next;
 } command_t;
 
        struct command_s *next;
 } command_t;
 
+/**
+ * @param c The command to be named.
+ * @param delim The character to place between command names.
+ * @returns A malloc'd string containing the full command name,
+ * which may include one or more ancestor components.  Multiple names
+ * are separated by single spaces.  The caller must free() the string
+ * when done with it.
+ */
+char *command_name(struct command_s *c, char delim);
+
 command_t* register_command(command_context_t *context,
                command_t *parent, char *name,
                int (*handler)(struct command_context_s *context,
 command_t* register_command(command_context_t *context,
                command_t *parent, char *name,
                int (*handler)(struct command_context_s *context,

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)