X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fhelper%2Fcommand.c;h=cba05f1672ba25e0762c82e70faee44c26e99e44;hb=00b3eb5fed59b87da16590bdfd8e0c682af7c891;hp=8dde2568e88fc7d4ccc05c9b8e4fd491f715bf7d;hpb=d798871a99fe27aa32b8e82f3cf9f87c5ea430d7;p=openocd.git diff --git a/src/helper/command.c b/src/helper/command.c index 8dde2568e8..cba05f1672 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -64,7 +64,6 @@ static void tcl_output(void *privData, const char *file, int line, const char *f extern command_context_t *global_cmd_ctx; - static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { /* the private data is stashed in the interp structure */ @@ -75,10 +74,20 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int nwords; char **words; + /* DANGER!!!! be careful what we invoke here, since interp->cmdPrivData might + * get overwritten by running other Jim commands! Treat it as an + * emphemeral global variable that is used in lieu of an argument + * to the fn and fish it out manually. + */ + c = interp->cmdPrivData; + if (c==NULL) + { + LOG_ERROR("BUG: interp->cmdPrivData==NULL"); + return JIM_ERR; + } target_call_timer_callbacks_now(); LOG_USER_N("%s", ""); /* Keep GDB connection alive*/ - c = interp->cmdPrivData; LOG_DEBUG("script_command - %s", c->name); words = malloc(sizeof(char *) * argc); @@ -138,6 +147,9 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return (retval==ERROR_OK)?JIM_OK:JIM_ERR; } +/* nice short description of source file */ +#define __THIS__FILE__ "command.c" + command_t* register_command(command_context_t *context, command_t *parent, char *name, int (*handler)(struct command_context_s *context, char* name, char** args, int argc), enum command_mode mode, char *help) { command_t *c, *p; @@ -213,7 +225,7 @@ command_t* register_command(command_context_t *context, command_t *parent, char /* 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); - Jim_Eval_Named(interp, override_name, __FILE__, __LINE__ ); + Jim_Eval_Named(interp, override_name, __THIS__FILE__, __LINE__ ); free((void *)override_name); /* accumulate help text in Tcl helptext list. */ @@ -277,8 +289,10 @@ int unregister_command(command_context_t *context, char *name) return ERROR_INVALID_ARGUMENTS; /* find command */ - for (c = context->commands; c; c = c->next) - { + c = context->commands; + + while(NULL != c) + { if (strcmp(name, c->name) == 0) { /* unlink command */ @@ -288,26 +302,32 @@ int unregister_command(command_context_t *context, char *name) } else { + /* first element in command list */ context->commands = c->next; } - + /* unregister children */ - if (c->children) + while(NULL != c->children) { - for (c2 = c->children; c2; c2 = c2->next) - { - free(c2->name); - free(c2); - } + c2 = c->children; + c->children = c->children->next; + free(c2->name); + c2->name = NULL; + free(c2); + c2 = NULL; } - + /* delete command */ free(c->name); + c->name = NULL; free(c); + c = NULL; + return ERROR_OK; } - + /* remember the last command for unlinking */ p = c; + c = c->next; } return ERROR_OK; @@ -433,7 +453,7 @@ int command_run_line(command_context_t *context, char *line) retcode = Jim_SetAssocData(interp, "retval", NULL, &retval); if (retcode == JIM_OK) { - retcode = Jim_Eval_Named(interp, line, __FILE__, __LINE__ ); + retcode = Jim_Eval_Named(interp, line, __THIS__FILE__, __LINE__ ); Jim_DeleteAssocData(interp, "retval"); } @@ -624,10 +644,36 @@ static char* openocd_jim_fgets(char *s, int size, void *cookie) return NULL; } + +static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) + return JIM_ERR; + int retcode; + const char *str = Jim_GetString(argv[1], NULL); + + /* capture log output and return it */ + Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); + /* a garbage collect can happen, so we need a reference count to this object */ + Jim_IncrRefCount(tclOutput); + + log_add_callback(tcl_output, tclOutput); + + retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__ ); + + log_remove_callback(tcl_output, tclOutput); + + /* We dump output into this local variable */ + Jim_SetResult(interp, tclOutput); + Jim_DecrRefCount(interp, tclOutput); + + return retcode; +} + command_context_t* command_init() { command_context_t* context = malloc(sizeof(command_context_t)); - extern unsigned const char startup_tcl[]; + extern const char startup_tcl[]; context->mode = COMMAND_EXEC; context->commands = NULL; @@ -645,6 +691,7 @@ command_context_t* command_init() Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL); Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL); + Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL); /* Set Jim's STDIO */ interp->cookie_stdin = interp; @@ -714,7 +761,12 @@ int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **ar busy_sleep(duration); } else { - alive_sleep(duration); + long long then=timeval_ms(); + while ((timeval_ms()-then)