X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fhelper%2Fcommand.c;h=0afbe2ccf2d6b135cd7d5b65854d706998fdd527;hp=4e0314315cf3fc8ce7fc965c07e07d0485aed2d3;hb=877cec20dca6e78f9f029f0f173879cda101a6c2;hpb=7641fb6ac6bc0736627a26dad9616fcb67cf59ab diff --git a/src/helper/command.c b/src/helper/command.c index 4e0314315c..0afbe2ccf2 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -22,9 +22,7 @@ * 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -57,7 +55,7 @@ struct log_capture_state { static void tcl_output(void *privData, const char *file, unsigned line, const char *function, const char *string) { - struct log_capture_state *state = (struct log_capture_state *)privData; + struct log_capture_state *state = privData; Jim_AppendString(state->interp, state->output, string, strlen(string)); } @@ -121,7 +119,7 @@ static int command_retval_set(Jim_Interp *interp, int retval) if (return_retval != NULL) *return_retval = retval; - return (retval == ERROR_OK) ? JIM_OK : JIM_ERR; + return (retval == ERROR_OK) ? JIM_OK : retval; } extern struct command_context *global_cmd_ctx; @@ -146,17 +144,17 @@ void script_debug(Jim_Interp *interp, const char *name, free(dbg); } -static void script_command_args_free(const char **words, unsigned nwords) +static void script_command_args_free(char **words, unsigned nwords) { for (unsigned i = 0; i < nwords; i++) - free((void *)words[i]); + free(words[i]); free(words); } -static const char **script_command_args_alloc( +static char **script_command_args_alloc( unsigned argc, Jim_Obj * const *argv, unsigned *nwords) { - const char **words = malloc(argc * sizeof(char *)); + char **words = malloc(argc * sizeof(char *)); if (NULL == words) return NULL; @@ -198,7 +196,7 @@ static int script_command_run(Jim_Interp *interp, LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ unsigned nwords; - const char **words = script_command_args_alloc(argc, argv, &nwords); + char **words = script_command_args_alloc(argc, argv, &nwords); if (NULL == words) return JIM_ERR; @@ -299,12 +297,9 @@ static void command_free(struct command *c) command_free(tmp); } - if (c->name) - free((void *)c->name); - if (c->help) - free((void *)c->help); - if (c->usage) - free((void *)c->usage); + free(c->name); + free(c->help); + free(c->usage); free(c); } @@ -362,27 +357,27 @@ 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); + char *ocd_name = alloc_printf("ocd_%s", c->name); if (NULL == ocd_name) return JIM_ERR; LOG_DEBUG("registering '%s'...", ocd_name); - Jim_CmdProc func = c->handler ? &script_command : &command_unknown; + Jim_CmdProc *func = c->handler ? &script_command : &command_unknown; int retval = Jim_CreateCommand(interp, ocd_name, func, c, NULL); - free((void *)ocd_name); + free(ocd_name); if (JIM_OK != retval) return retval; /* we now need to add an overrideable proc */ - const char *override_name = alloc_printf( + char *override_name = alloc_printf( "proc %s {args} {eval ocd_bouncer %s $args}", c->name, c->name); if (NULL == override_name) return JIM_ERR; retval = Jim_Eval_Named(interp, override_name, 0, 0); - free((void *)override_name); + free(override_name); return retval; } @@ -562,6 +557,10 @@ static char *__command_name(struct command *c, char delim, unsigned extra) if (NULL == c->parent) { /* allocate enough for the name, child names, and '\0' */ name = malloc(len + extra + 1); + if (!name) { + LOG_ERROR("Out of memory"); + return NULL; + } strcpy(name, c->name); } else { /* parent's extra must include both the space and name */ @@ -580,31 +579,35 @@ char *command_name(struct command *c, char delim) static bool command_can_run(struct command_context *cmd_ctx, struct command *c) { - return c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode; + if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode) + return true; + + /* 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; + } + 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; } static int run_command(struct command_context *context, struct command *c, const char *words[], unsigned num_words) { - if (!command_can_run(context, c)) { - /* 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); + if (!command_can_run(context, c)) return ERROR_FAIL; - } struct command_invocation cmd = { .ctx = context, @@ -613,22 +616,40 @@ static int run_command(struct command_context *context, .argc = num_words - 1, .argv = words + 1, }; + /* Black magic of overridden current target: + * If the command we are going to handle has a target prefix, + * override the current target temporarily for the time + * of processing the command. + * current_target_override is used also for event handlers + * therefore we prevent touching it if command has no prefix. + * Previous override is saved and restored back to ensure + * correct work when run_command() is re-entered. */ + struct target *saved_target_override = context->current_target_override; + if (c->jim_handler_data) + context->current_target_override = c->jim_handler_data; + int retval = c->handler(&cmd); + + if (c->jim_handler_data) + context->current_target_override = saved_target_override; + 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); - } else - retval = -ENOMEM; + } } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) { /* just fall through for a shutdown request */ } else if (retval != ERROR_OK) { /* we do not print out an error message because the command *should* * have printed out an error */ - LOG_DEBUG("Command failed with error code %d", retval); + char *full_name = command_name(c, ' '); + LOG_DEBUG("Command '%s' failed with error code %d", + full_name ? full_name : c->name, retval); + free(full_name); } return retval; @@ -648,6 +669,8 @@ int command_run_line(struct command_context *context, char *line) * happen when the Jim Tcl interpreter is provided by eCos for * instance. */ + context->current_target_override = NULL; + Jim_Interp *interp = context->interp; Jim_DeleteAssocData(interp, "context"); retcode = Jim_SetAssocData(interp, "context", NULL, context); @@ -662,21 +685,7 @@ int command_run_line(struct command_context *context, char *line) } Jim_DeleteAssocData(interp, "context"); } - if (retcode == JIM_ERR) { - if (retval != ERROR_COMMAND_CLOSE_CONNECTION) { - /* We do not print the connection closed error message */ - Jim_MakeErrorMessage(interp); - LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL)); - } - if (retval == ERROR_OK) { - /* It wasn't a low level OpenOCD command that failed */ - return ERROR_FAIL; - } - return retval; - } else if (retcode == JIM_EXIT) { - /* ignore. - * exit(Jim_GetExitCode(interp)); */ - } else { + if (retcode == JIM_OK) { const char *result; int reslen; @@ -696,7 +705,22 @@ int command_run_line(struct command_context *context, char *line) LOG_USER_N("\n"); } retval = ERROR_OK; + } else if (retcode == JIM_EXIT) { + /* ignore. + * exit(Jim_GetExitCode(interp)); */ + } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) { + return retcode; + } else { + Jim_MakeErrorMessage(interp); + LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL)); + + if (retval == ERROR_OK) { + /* It wasn't a low level OpenOCD command that failed */ + return ERROR_FAIL; + } + return retval; } + return retval; } @@ -814,13 +838,13 @@ static COMMAND_HELPER(command_help_find, struct command *head, } static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, - bool show_help, const char *match); + bool show_help, const char *cmd_match); static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n, - bool show_help, const char *match) + bool show_help, const char *cmd_match) { for (struct command *c = head; NULL != c; c = c->next) - CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, match); + CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, cmd_match); return ERROR_OK; } @@ -852,17 +876,17 @@ static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) } static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, - bool show_help, const char *match) + bool show_help, const char *cmd_match) { char *cmd_name = command_name(c, ' '); if (NULL == cmd_name) - return -ENOMEM; + return ERROR_FAIL; /* If the match string occurs anywhere, we print out * stuff for this command. */ - bool is_match = (strstr(cmd_name, match) != NULL) || - ((c->usage != NULL) && (strstr(c->usage, match) != NULL)) || - ((c->help != NULL) && (strstr(c->help, match) != NULL)); + bool is_match = (strstr(cmd_name, cmd_match) != NULL) || + ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) || + ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL)); if (is_match) { command_help_show_indent(n); @@ -871,7 +895,7 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, free(cmd_name); if (is_match) { - if (c->usage) { + if (c->usage && strlen(c->usage) > 0) { LOG_USER_N(" "); command_help_show_wrap(c->usage, 0, n + 5); } else @@ -913,7 +937,7 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, } return CALL_COMMAND_HANDLER(command_help_show_list, - c->children, n, show_help, match); + c->children, n, show_help, cmd_match); } COMMAND_HANDLER(handle_help_command) @@ -921,26 +945,26 @@ COMMAND_HANDLER(handle_help_command) bool full = strcmp(CMD_NAME, "help") == 0; int retval; struct command *c = CMD_CTX->commands; - char *match = NULL; + char *cmd_match = NULL; if (CMD_ARGC == 0) - match = ""; + cmd_match = ""; else if (CMD_ARGC >= 1) { unsigned i; for (i = 0; i < CMD_ARGC; ++i) { - if (NULL != match) { - char *prev = match; + if (NULL != cmd_match) { + char *prev = cmd_match; - match = alloc_printf("%s %s", match, CMD_ARGV[i]); + cmd_match = alloc_printf("%s %s", cmd_match, CMD_ARGV[i]); free(prev); - if (NULL == match) { + if (NULL == cmd_match) { LOG_ERROR("unable to build search string"); return -ENOMEM; } } else { - match = alloc_printf("%s", CMD_ARGV[i]); - if (NULL == match) { + cmd_match = alloc_printf("%s", CMD_ARGV[i]); + if (NULL == cmd_match) { LOG_ERROR("unable to build search string"); return -ENOMEM; } @@ -950,10 +974,10 @@ COMMAND_HANDLER(handle_help_command) return ERROR_COMMAND_SYNTAX_ERROR; retval = CALL_COMMAND_HANDLER(command_help_show_list, - c, 0, full, match); + c, 0, full, cmd_match); if (CMD_ARGC >= 1) - free(match); + free(cmd_match); return retval; } @@ -1012,6 +1036,9 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } /* pass the command through to the intended handler */ if (c->jim_handler) { + if (!command_can_run(cmd_ctx, c)) + return ERROR_FAIL; + interp->cmdPrivData = c->jim_handler_data; return (*c->jim_handler)(interp, count, start); } @@ -1073,8 +1100,10 @@ static int jim_command_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) Jim_SetResultString(interp, "native", -1); else if (c->handler) Jim_SetResultString(interp, "simple", -1); - else + else if (remaining == 0) Jim_SetResultString(interp, "group", -1); + else + Jim_SetResultString(interp, "unknown", -1); return JIM_OK; } @@ -1103,7 +1132,7 @@ int help_add_command(struct command_context *cmd_ctx, struct command *parent, if (help_text) { bool replaced = false; if (nc->help) { - free((void *)nc->help); + free(nc->help); replaced = true; } nc->help = strdup(help_text); @@ -1115,7 +1144,7 @@ int help_add_command(struct command_context *cmd_ctx, struct command *parent, if (usage) { bool replaced = false; if (nc->usage) { - free((void *)nc->usage); + free(nc->usage); replaced = true; } nc->usage = strdup(usage); @@ -1175,8 +1204,8 @@ COMMAND_HANDLER(handle_sleep_command) return retval; if (!busy) { - long long then = timeval_ms(); - while (timeval_ms() - then < (long long)duration) { + int64_t then = timeval_ms(); + while (timeval_ms() - then < (int64_t)duration) { target_call_timer_callbacks_now(); usleep(1000); } @@ -1271,14 +1300,10 @@ static const struct command_registration command_builtin_handlers[] = { struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp) { - struct command_context *context = malloc(sizeof(struct command_context)); + struct command_context *context = calloc(1, sizeof(struct command_context)); const char *HostOs; context->mode = COMMAND_EXEC; - context->commands = NULL; - context->current_target = 0; - context->output_handler = NULL; - context->output_handler_priv = NULL; /* Create a jim interpreter if we were not handed one */ if (interp == NULL) { @@ -1341,6 +1366,15 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp return context; } +void command_exit(struct command_context *context) +{ + if (!context) + return; + + Jim_FreeInterp(context->interp); + command_done(context); +} + int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode) { if (!cmd_ctx) @@ -1412,6 +1446,8 @@ DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX) +DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX) + #define DEFINE_PARSE_LONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong) DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX) @@ -1456,8 +1492,8 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label) LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in); return ERROR_COMMAND_SYNTAX_ERROR; } - /* fall through */ } + /* fallthrough */ case 0: LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled"); break;