static COMMAND_HELPER(command_help_show, struct command *c, unsigned n, bool show_help, const char *match) { if (!command_can_run(CMD_CTX, c)) return ERROR_OK; char *cmd_name = command_name(c, ' '); if (NULL == cmd_name) return -ENOMEM; /* 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)); if (is_match) { command_help_show_indent(n); LOG_USER_N("%s", cmd_name); } free(cmd_name); if (is_match) { if (c->usage) { LOG_USER_N(" "); command_help_show_wrap(c->usage, 0, n + 5); } else LOG_USER_N("\n"); } if (is_match && show_help) { char *msg; /* Normal commands are runtime-only; highlight exceptions */ if (c->mode != COMMAND_EXEC) { const char *stage_msg = ""; switch (c->mode) { case COMMAND_CONFIG: stage_msg = " (configuration command)"; break; case COMMAND_ANY: stage_msg = " (command valid any time)"; break; default: stage_msg = " (?mode error?)"; break; } msg = alloc_printf("%s%s", c->help ? : "", stage_msg); } else
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); return ERROR_FAIL; } struct command_invocation cmd = { .ctx = context, .current = c, .name = c->name, .argc = num_words - 1, .argv = words + 1, }; int retval = c->handler(&cmd); 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); } return retval; } int command_run_line(struct command_context *context, char *line) { /* all the parent commands have been registered with the interpreter * so, can just evaluate the line as a script and check for * results */ /* run the line thru a script engine */ int retval = ERROR_FAIL; int retcode; /* Beware! This code needs to be reentrant. It is also possible * for OpenOCD commands to be invoked directly from Tcl. This would * 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) { /* associated the return value */ Jim_DeleteAssocData(interp, "retval"); retcode = Jim_SetAssocData(interp, "retval", NULL, &retval); if (retcode == JIM_OK) { retcode = Jim_Eval_Named(interp, line, 0, 0); Jim_DeleteAssocData(interp, "retval"); } Jim_DeleteAssocData(interp, "context"); } if (retcode == JIM_OK) { const char *result; int reslen; result = Jim_GetString(Jim_GetResult(interp), &reslen); if (reslen > 0) { int i; char buff[256 + 1]; for (i = 0; i < reslen; i += 256) { int chunk; chunk = reslen - i; if (chunk > 256) chunk = 256; strncpy(buff, result + i, chunk); buff[chunk] = 0; LOG_USER_N("%s", buff); } 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; }