improve command prohibition error report
[openocd.git] / src / helper / command.c
index ac7c8d88b4ef40e6e127a42377305b2d72a41a65..dcad6a198e39ff9de78f6a740263f66af2ece812 100644 (file)
 /* nice short description of source file */
 #define __THIS__FILE__ "command.c"
 
-Jim_Interp *interp = NULL;
 
 static int run_command(struct command_context *context,
                struct command *c, const char *words[], unsigned num_words);
 
+struct log_capture_state {
+       Jim_Interp *interp;
+       Jim_Obj *output;
+};
+
 static void tcl_output(void *privData, const char *file, unsigned line,
                const char *function, const char *string)
 {
-       Jim_Obj *tclOutput = (Jim_Obj *)privData;
-       Jim_AppendString(interp, tclOutput, string, strlen(string));
+       struct log_capture_state *state = (struct log_capture_state *)privData;
+       Jim_AppendString(state->interp, state->output, string, strlen(string));
 }
 
-static Jim_Obj *command_log_capture_start(Jim_Interp *interp)
+static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
 {
        /* capture log output and return it. A garbage collect can
         * happen, so we need a reference count to this object */
        Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
        if (NULL == tclOutput)
                return NULL;
+
+       struct log_capture_state *state = malloc(sizeof(*state));
+       if (NULL == state)
+               return NULL;
+
+       state->interp = interp;
        Jim_IncrRefCount(tclOutput);
-       log_add_callback(tcl_output, tclOutput);
-       return tclOutput;
+       state->output = tclOutput;
+
+       log_add_callback(tcl_output, state);
+
+       return state;
 }
 
-static void command_log_capture_finish(Jim_Interp *interp, Jim_Obj *tclOutput)
+static void command_log_capture_finish(struct log_capture_state *state)
 {
-       log_remove_callback(tcl_output, tclOutput);
-       Jim_SetResult(interp, tclOutput);
-       Jim_DecrRefCount(interp, tclOutput);
+       if (NULL == state)
+               return;
+
+       log_remove_callback(tcl_output, state);
+
+       Jim_SetResult(state->interp, state->output);
+       Jim_DecrRefCount(state->interp, state->output);
+
+       free(state);
 }
 
 static int command_retval_set(Jim_Interp *interp, int retval)
@@ -139,7 +158,7 @@ static const char **script_command_args_alloc(
        return words;
 }
 
-static struct command_context *current_command_context(void)
+static struct command_context *current_command_context(Jim_Interp *interp)
 {
        /* grab the command context from the associated data */
        struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
@@ -164,15 +183,14 @@ static int script_command_run(Jim_Interp *interp,
        if (NULL == words)
                return JIM_ERR;
 
-       Jim_Obj *tclOutput = NULL;
+       struct log_capture_state *state = NULL;
        if (capture)
-               tclOutput = command_log_capture_start(interp);
+               state = command_log_capture_start(interp);
 
-       struct command_context *cmd_ctx = current_command_context();
+       struct command_context *cmd_ctx = current_command_context(interp);
        int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
 
-       if (capture)
-               command_log_capture_finish(interp, tclOutput);
+       command_log_capture_finish(state);
 
        script_command_args_free(words, nwords);
        return command_retval_set(interp, retval);
@@ -308,8 +326,10 @@ command_new_error:
 
 static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 
-static int register_command_handler(struct command *c)
+static int register_command_handler(struct command_context *cmd_ctx,
+               struct command *c)
 {
+       Jim_Interp *interp = cmd_ctx->interp;
        const char *ocd_name = alloc_printf("ocd_%s", c->name);
        if (NULL == ocd_name)
                return JIM_ERR;
@@ -358,11 +378,11 @@ struct command* register_command(struct command_context *context,
        int retval = ERROR_OK;
        if (NULL != cr->jim_handler && NULL == parent)
        {
-               retval = Jim_CreateCommand(interp, cr->name,
+               retval = Jim_CreateCommand(context->interp, cr->name,
                                cr->jim_handler, cr->jim_handler_data, NULL);
        }
        else if (NULL != cr->handler || NULL != parent)
-               retval = register_command_handler(command_root(c));
+               retval = register_command_handler(context, command_root(c));
 
        if (ERROR_OK != retval)
        {
@@ -545,8 +565,16 @@ static int run_command(struct command_context *context,
 {
        if (!command_can_run(context, c))
        {
-               /* Config commands can not run after the config stage */
-               LOG_ERROR("The '%s' command must be used before 'init'.", c->name);
+               /* Many commands may be run only before/after 'init' */
+               const char *when;
+               switch (c->mode) {
+               case COMMAND_CONFIG: when = "before"; break;
+               case COMMAND_EXEC: when = "after"; break;
+               // handle the impossible with humor; it guarantees a bug report!
+               default: when = "if Cthulhu is summoned by"; break;
+               }
+               LOG_ERROR("The '%s' command must be used %s 'init'.",
+                               c->name, when);
                return ERROR_FAIL;
        }
 
@@ -562,7 +590,7 @@ static int run_command(struct command_context *context,
                /* Print help for command */
                char *full_name = command_name(c, ' ');
                if (NULL != full_name) {
-                       command_run_linef(context, "help %s", full_name);
+                       command_run_linef(context, "usage %s", full_name);
                        free(full_name);
                } else
                        retval = -ENOMEM;
@@ -596,6 +624,7 @@ int command_run_line(struct command_context *context, char *line)
         * happen when the Jim Tcl interpreter is provided by eCos for
         * instance.
         */
+       Jim_Interp *interp = context->interp;
        Jim_DeleteAssocData(interp, "context");
        retcode = Jim_SetAssocData(interp, "context", NULL, context);
        if (retcode == JIM_OK)
@@ -683,12 +712,12 @@ struct command_context* copy_command_context(struct command_context* context)
        return copy_context;
 }
 
-int command_done(struct command_context *context)
+void command_done(struct command_context *cmd_ctx)
 {
-       free(context);
-       context = NULL;
+       if (NULL == cmd_ctx)
+               return;
 
-       return ERROR_OK;
+       free(cmd_ctx);
 }
 
 /* find full path to file */
@@ -804,12 +833,12 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        if (argc != 2)
                return JIM_ERR;
 
-       Jim_Obj *tclOutput = command_log_capture_start(interp);
+       struct log_capture_state *state = command_log_capture_start(interp);
 
        const char *str = Jim_GetString(argv[1], NULL);
        int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
 
-       command_log_capture_finish(interp, tclOutput);
+       command_log_capture_finish(state);
 
        return retcode;
 }
@@ -958,7 +987,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
        script_debug(interp, cmd_name, argc, argv);
 
-       struct command_context *cmd_ctx = current_command_context();
+       struct command_context *cmd_ctx = current_command_context(interp);
        struct command *c = cmd_ctx->commands;
        int remaining = command_unknown_find(argc, argv, c, &c, true);
        // if nothing could be consumed, then it's really an unknown command
@@ -980,10 +1009,10 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
        else
        {
-               c = command_find(cmd_ctx->commands, "help");
+               c = command_find(cmd_ctx->commands, "usage");
                if (NULL == c)
                {
-                       LOG_ERROR("unknown command, but help is missing too");
+                       LOG_ERROR("unknown command, but usage is missing too");
                        return JIM_ERR;
                }
                count = argc - remaining;
@@ -1002,7 +1031,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       struct command_context *cmd_ctx = current_command_context();
+       struct command_context *cmd_ctx = current_command_context(interp);
        enum command_mode mode;
        if (argc > 1)
        {
@@ -1035,7 +1064,7 @@ static int jim_command_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        if (1 == argc)
                return JIM_ERR;
 
-       struct command_context *cmd_ctx = current_command_context();
+       struct command_context *cmd_ctx = current_command_context(interp);
        struct command *c = cmd_ctx->commands;
        int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true);
        // if nothing could be consumed, then it's an unknown command
@@ -1257,11 +1286,12 @@ struct command_context* command_init(const char *startup_tcl)
 #if !BUILD_ECOSBOARD
        Jim_InitEmbedded();
        /* Create an interpreter */
-       interp = Jim_CreateInterp();
+       context->interp = Jim_CreateInterp();
        /* Add all the Jim core commands */
-       Jim_RegisterCoreCommands(interp);
+       Jim_RegisterCoreCommands(context->interp);
 #endif
 
+       Jim_Interp *interp = context->interp;
 #if defined(_MSC_VER)
        /* WinXX - is generic, the forward
         * looking problem is this:
@@ -1328,17 +1358,16 @@ int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode
        return ERROR_OK;
 }
 
-void process_jim_events(void)
+void process_jim_events(struct command_context *cmd_ctx)
 {
 #if !BUILD_ECOSBOARD
        static int recursion = 0;
+       if (recursion)
+               return;
 
-       if (!recursion)
-       {
-               recursion++;
-               Jim_ProcessEvents (interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
-               recursion--;
-       }
+       recursion++;
+       Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
+       recursion--;
 #endif
 }
 

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)