openocd: fix for polling during "expr" computation
[fw/openocd] / src / helper / command.c
index 08d14b47fe5f2a803c1703098513035e1724e056..b5c5459a1fa44168bba15233a997fa4cb0663a56 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
  *   part of this file is taken from libcli (libcli.sourceforge.net)       *
  *   Copyright (C) David Parrish (david@dparrish.com)                      *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -62,12 +51,12 @@ static inline bool jimcmd_is_proc(Jim_Cmd *cmd)
        return cmd->isproc;
 }
 
-static inline bool jimcmd_is_ocd_command(Jim_Cmd *cmd)
+bool jimcmd_is_oocd_command(Jim_Cmd *cmd)
 {
        return !cmd->isproc && cmd->u.native.cmdProc == jim_command_dispatch;
 }
 
-static inline void *jimcmd_privdata(Jim_Cmd *cmd)
+void *jimcmd_privdata(Jim_Cmd *cmd)
 {
        return cmd->isproc ? NULL : cmd->u.native.privData;
 }
@@ -118,7 +107,7 @@ static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
  */
 static void command_log_capture_finish(struct log_capture_state *state)
 {
-       if (NULL == state)
+       if (!state)
                return;
 
        log_remove_callback(tcl_output, state);
@@ -137,44 +126,10 @@ static void command_log_capture_finish(struct log_capture_state *state)
        free(state);
 }
 
-/*
- * FIXME: workaround for memory leak in jimtcl 0.80
- * Jim API Jim_CreateCommand() converts the command name in a Jim object and
- * does not free the object. Fixed for jimtcl 0.81 by e4416cf86f0b
- * Use the internal jimtcl API Jim_CreateCommandObj, not exported by jim.h,
- * and override the bugged API through preprocessor's macro.
- * This workaround works only when jimtcl is compiled as OpenOCD submodule.
- * If jimtcl is linked-in from a precompiled library, either static or dynamic,
- * the symbol Jim_CreateCommandObj is not exported and the build will use the
- * bugged API.
- * To be removed when OpenOCD will switch to jimtcl 0.81
- */
-#if JIM_VERSION == 80
-static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
-       Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc);
-int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj,
-       Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
-__attribute__((weak, alias("workaround_createcommand")));
-static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
-       Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
-{
-       if ((void *)Jim_CreateCommandObj == (void *)workaround_createcommand)
-               return Jim_CreateCommand(interp, cmdName, cmdProc, privData, delProc);
-
-       Jim_Obj *cmd_name = Jim_NewStringObj(interp, cmdName, -1);
-       Jim_IncrRefCount(cmd_name);
-       int retval = Jim_CreateCommandObj(interp, cmd_name, cmdProc, privData, delProc);
-       Jim_DecrRefCount(interp, cmd_name);
-       return retval;
-}
-#define Jim_CreateCommand workaround_createcommand
-#endif /* JIM_VERSION == 80 */
-/* FIXME: end of workaround for memory leak in jimtcl 0.80 */
-
 static int command_retval_set(Jim_Interp *interp, int retval)
 {
        int *return_retval = Jim_GetAssocData(interp, "retval");
-       if (return_retval != NULL)
+       if (return_retval)
                *return_retval = retval;
 
        return (retval == ERROR_OK) ? JIM_OK : retval;
@@ -212,7 +167,7 @@ static char **script_command_args_alloc(
        unsigned argc, Jim_Obj * const *argv, unsigned *nwords)
 {
        char **words = malloc(argc * sizeof(char *));
-       if (NULL == words)
+       if (!words)
                return NULL;
 
        unsigned i;
@@ -220,7 +175,7 @@ static char **script_command_args_alloc(
                int len;
                const char *w = Jim_GetString(argv[i], &len);
                words[i] = strdup(w);
-               if (words[i] == NULL) {
+               if (!words[i]) {
                        script_command_args_free(words, i);
                        return NULL;
                }
@@ -233,7 +188,7 @@ 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");
-       if (NULL == cmd_ctx) {
+       if (!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 or if we are running
                 * commands in a startup script.
@@ -260,7 +215,7 @@ static struct command *command_find_from_name(Jim_Interp *interp, const char *na
        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))
+       if (!cmd || jimcmd_is_proc(cmd) || !jimcmd_is_oocd_command(cmd))
                return NULL;
 
        return jimcmd_privdata(cmd);
@@ -284,7 +239,7 @@ static struct command *command_new(struct command_context *cmd_ctx,
                        full_name);
 
        struct command *c = calloc(1, sizeof(struct command));
-       if (NULL == c)
+       if (!c)
                return NULL;
 
        c->name = strdup(cr->name);
@@ -342,7 +297,8 @@ static struct command *register_command(struct command_context *context,
                return NULL;
        }
 
-       LOG_DEBUG("registering '%s'...", full_name);
+       if (false) /* too noisy with debug_level 3 */
+               LOG_DEBUG("registering '%s'...", full_name);
        int retval = Jim_CreateCommand(context->interp, full_name,
                                jim_command_dispatch, c, command_free);
        if (retval != JIM_OK) {
@@ -367,16 +323,16 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
                const struct command_registration *cr = cmds + i;
 
                struct command *c = NULL;
-               if (NULL != cr->name) {
+               if (cr->name) {
                        c = register_command(cmd_ctx, cmd_prefix, cr);
-                       if (NULL == c) {
+                       if (!c) {
                                retval = ERROR_FAIL;
                                break;
                        }
                        c->jim_handler_data = data;
                        c->jim_override_target = override_target;
                }
-               if (NULL != cr->chain) {
+               if (cr->chain) {
                        if (cr->name) {
                                if (cmd_prefix) {
                                        char *new_prefix = alloc_printf("%s %s", cmd_prefix, cr->name);
@@ -392,11 +348,11 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
                        } else {
                                retval = __register_commands(cmd_ctx, cmd_prefix, cr->chain, data, override_target);
                        }
-                       if (ERROR_OK != retval)
+                       if (retval != ERROR_OK)
                                break;
                }
        }
-       if (ERROR_OK != retval) {
+       if (retval != ERROR_OK) {
                for (unsigned j = 0; j < i; j++)
                        unregister_command(cmd_ctx, cmd_prefix, cmds[j].name);
        }
@@ -440,7 +396,8 @@ int unregister_commands_match(struct command_context *cmd_ctx, const char *forma
                        Jim_DecrRefCount(interp, elem);
                        continue;
                }
-               LOG_DEBUG("delete command \"%s\"", name);
+               if (false) /* too noisy with debug_level 3 */
+                       LOG_DEBUG("delete command \"%s\"", name);
 #if JIM_VERSION >= 80
                Jim_DeleteCommand(interp, elem);
 #else
@@ -498,7 +455,7 @@ void command_print_sameline(struct command_invocation *cmd, const char *format,
        va_start(ap, format);
 
        string = alloc_vprintf(format, ap);
-       if (string != NULL && cmd) {
+       if (string && cmd) {
                /* we want this collected in the log + we also want to pick it up as a tcl return
                 * value.
                 *
@@ -521,7 +478,7 @@ void command_print(struct command_invocation *cmd, const char *format, ...)
        va_start(ap, format);
 
        string = alloc_vprintf(format, ap);
-       if (string != NULL && cmd) {
+       if (string && cmd) {
                strcat(string, "\n");   /* alloc_vprintf guaranteed the buffer to be at least one
                                         *char longer */
                /* we want this collected in the log + we also want to pick it up as a tcl return
@@ -667,7 +624,7 @@ int command_run_linef(struct command_context *context, const char *format, ...)
        va_list ap;
        va_start(ap, format);
        string = alloc_vprintf(format, ap);
-       if (string != NULL) {
+       if (string) {
                retval = command_run_line(context, string);
                free(string);
        }
@@ -693,7 +650,7 @@ struct command_context *copy_command_context(struct command_context *context)
 
 void command_done(struct command_context *cmd_ctx)
 {
-       if (NULL == cmd_ctx)
+       if (!cmd_ctx)
                return;
 
        free(cmd_ctx);
@@ -706,7 +663,7 @@ static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return JIM_ERR;
        const char *file = Jim_GetString(argv[1], NULL);
        char *full_path = find_file(file);
-       if (full_path == NULL)
+       if (!full_path)
                return JIM_ERR;
        Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
        free(full_path);
@@ -715,16 +672,18 @@ static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return JIM_OK;
 }
 
-COMMAND_HANDLER(jim_echo)
+COMMAND_HANDLER(handle_echo)
 {
        if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) {
                LOG_USER_N("%s", CMD_ARGV[1]);
-               return JIM_OK;
+               return ERROR_OK;
        }
+
        if (CMD_ARGC != 1)
-               return JIM_ERR;
+               return ERROR_FAIL;
+
        LOG_USER("%s", CMD_ARGV[0]);
-       return JIM_OK;
+       return ERROR_OK;
 }
 
 /* Capture progress output and return as tcl return value. If the
@@ -743,14 +702,12 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
         * This is necessary in order to avoid accidentally getting a non-empty
         * string for tcl fn's.
         */
-       bool save_poll = jtag_poll_get_enabled();
-
-       jtag_poll_set_enabled(false);
+       bool save_poll_mask = jtag_poll_mask();
 
        const char *str = Jim_GetString(argv[1], NULL);
        int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
 
-       jtag_poll_set_enabled(save_poll);
+       jtag_poll_unmask(save_poll_mask);
 
        command_log_capture_finish(state);
 
@@ -812,19 +769,18 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c,
 
        /* If the match string occurs anywhere, we print out
         * stuff for this command. */
-       bool is_match = (strstr(c->cmd_name, cmd_match) != NULL) ||
-               ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) ||
-               ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL));
+       bool is_match = strstr(c->cmd_name, cmd_match) ||
+               (c->usage && strstr(c->usage, cmd_match)) ||
+               (c->help && strstr(c->help, cmd_match));
 
        if (is_match) {
-               command_help_show_indent(n);
-               LOG_USER_N("%s", c->cmd_name);
-
                if (c->usage && strlen(c->usage) > 0) {
-                       LOG_USER_N(" ");
-                       command_help_show_wrap(c->usage, 0, n + 5);
-               } else
-                       LOG_USER_N("\n");
+                       char *msg = alloc_printf("%s %s", c->cmd_name, c->usage);
+                       command_help_show_wrap(msg, n, n + 5);
+                       free(msg);
+               } else {
+                       command_help_show_wrap(c->cmd_name, n, n + 5);
+               }
        }
 
        if (is_match && show_help) {
@@ -864,11 +820,11 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c,
                                        stage_msg = " (?mode error?)";
                                        break;
                        }
-                       msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
+                       msg = alloc_printf("%s%s", c->help ? c->help : "", stage_msg);
                } else
-                       msg = alloc_printf("%s", c->help ? : "");
+                       msg = alloc_printf("%s", c->help ? c->help : "");
 
-               if (NULL != msg) {
+               if (msg) {
                        command_help_show_wrap(msg, n + 3, n + 3);
                        free(msg);
                } else
@@ -897,7 +853,7 @@ COMMAND_HANDLER(handle_help_command)
                }
        }
 
-       if (cmd_match == NULL) {
+       if (!cmd_match) {
                LOG_ERROR("unable to build search string");
                return -ENOMEM;
        }
@@ -952,8 +908,6 @@ static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx,
 
 static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
 {
-       script_debug(interp, argc, argv);
-
        /* check subcommands */
        if (argc > 1) {
                char *s = alloc_printf("%s %s", Jim_GetString(argv[0], NULL), Jim_GetString(argv[1], NULL));
@@ -969,6 +923,8 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a
                Jim_DecrRefCount(interp, js);
        }
 
+       script_debug(interp, argc, argv);
+
        struct command *c = jim_to_command(interp);
        if (!c->jim_handler && !c->handler) {
                Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv);
@@ -980,7 +936,19 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a
        if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
                return JIM_ERR;
 
-       target_call_timer_callbacks_now();
+       /*
+        * TODO: to be removed after v0.12.0
+        * workaround for https://sourceforge.net/p/openocd/tickets/362/
+        * After syntax change of "expr" in jimtcl 0.81
+        * the replacement of jimtcl "expr" with openocd version in
+        * https://review.openocd.org/6510/
+        * introduces too many target polling during math expressions with
+        * "expr" commands.
+        * After v0.12.0 replace the following two lines with
+        * target_call_timer_callbacks();
+        */
+       if (strcmp(c->name, "expr"))
+               target_call_timer_callbacks_now();
 
        /*
         * Black magic of overridden current target:
@@ -1018,7 +986,7 @@ 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) || jimcmd_is_ocd_command(cmd))) {
+               if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_oocd_command(cmd))) {
                        Jim_SetResultString(interp, "unknown", -1);
                        return JIM_OK;
                }
@@ -1169,13 +1137,14 @@ COMMAND_HANDLER(handle_sleep_command)
 
        unsigned long duration = 0;
        int retval = parse_ulong(CMD_ARGV[0], &duration);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        if (!busy) {
                int64_t then = timeval_ms();
                while (timeval_ms() - then < (int64_t)duration) {
                        target_call_timer_callbacks_now();
+                       keep_alive();
                        usleep(1000);
                }
        } else
@@ -1217,10 +1186,9 @@ static const struct command_registration command_builtin_handlers[] = {
        },
        {
                .name = "echo",
-               .handler = jim_echo,
+               .handler = handle_echo,
                .mode = COMMAND_ANY,
                .help = "Logs a message at \"user\" priority. "
-                       "Output message to stdout. "
                        "Option \"-n\" suppresses trailing newline",
                .usage = "[-n] string",
        },
@@ -1277,7 +1245,6 @@ static const struct command_registration command_builtin_handlers[] = {
 struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp)
 {
        struct command_context *context = calloc(1, sizeof(struct command_context));
-       const char *HostOs;
 
        context->mode = COMMAND_EXEC;
 
@@ -1286,7 +1253,7 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp
        INIT_LIST_HEAD(context->help_list);
 
        /* Create a jim interpreter if we were not handed one */
-       if (interp == NULL) {
+       if (!interp) {
                /* Create an interpreter */
                interp = Jim_CreateInterp();
                /* Add all the Jim core commands */
@@ -1296,39 +1263,6 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp
 
        context->interp = interp;
 
-       /* Stick to lowercase for HostOS strings. */
-#if defined(_MSC_VER)
-       /* WinXX - is generic, the forward
-        * looking problem is this:
-        *
-        *   "win32" or "win64"
-        *
-        * "winxx" is generic.
-        */
-       HostOs = "winxx";
-#elif defined(__linux__)
-       HostOs = "linux";
-#elif defined(__APPLE__) || defined(__DARWIN__)
-       HostOs = "darwin";
-#elif defined(__CYGWIN__)
-       HostOs = "cygwin";
-#elif defined(__MINGW32__)
-       HostOs = "mingw32";
-#elif defined(__ECOS)
-       HostOs = "ecos";
-#elif defined(__FreeBSD__)
-       HostOs = "freebsd";
-#elif defined(__NetBSD__)
-       HostOs = "netbsd";
-#elif defined(__OpenBSD__)
-       HostOs = "openbsd";
-#else
-#warning "Unrecognized host OS..."
-       HostOs = "other";
-#endif
-       Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
-               Jim_NewStringObj(interp, HostOs, strlen(HostOs)));
-
        register_commands(context, NULL, command_builtin_handlers);
 
        Jim_SetAssocData(interp, "context", NULL, context);
@@ -1387,11 +1321,11 @@ void process_jim_events(struct command_context *cmd_ctx)
                        LOG_ERROR("Invalid command argument"); \
                        return ERROR_COMMAND_ARGUMENT_INVALID; \
                } \
-               if ((max == *ul) && (ERANGE == errno)) { \
+               if ((max == *ul) && (errno == ERANGE)) { \
                        LOG_ERROR("Argument overflow"); \
                        return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
                } \
-               if (min && (min == *ul) && (ERANGE == errno)) { \
+               if (min && (min == *ul) && (errno == ERANGE)) { \
                        LOG_ERROR("Argument underflow"); \
                        return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
                } \
@@ -1407,7 +1341,7 @@ DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
        { \
                functype n; \
                int retval = parse ## funcname(str, &n); \
-               if (ERROR_OK != retval) \
+               if (retval != ERROR_OK) \
                        return retval; \
                if (n > max) \
                        return ERROR_COMMAND_ARGUMENT_OVERFLOW; \