+static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ /* the private data is stashed in the interp structure */
+ command_t *c;
+ command_context_t *context;
+ int retval;
+ int i;
+ int nwords;
+ char **words;
+
+ 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);
+ for (i = 0; i < argc; i++)
+ {
+ int len;
+ const char *w=Jim_GetString(argv[i], &len);
+ if (*w=='#')
+ {
+ /* hit an end of line comment */
+ break;
+ }
+ words[i] = strdup(w);
+ if (words[i] == NULL)
+ {
+ return JIM_ERR;
+ }
+ LOG_DEBUG("script_command - %s, argv[%u]=%s", c->name, i, words[i]);
+ }
+ nwords = i;
+
+ /* grab the command context from the associated data */
+ context = Jim_GetAssocData(interp, "context");
+ if (context == NULL)
+ {
+ /* Tcl can invoke commands directly instead of via command_run_line(). This would
+ * happen when the Jim Tcl interpreter is provided by eCos.
+ */
+ context = global_cmd_ctx;
+ }
+
+ /* 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);
+
+ retval = run_command(context, c, words, nwords);
+
+ log_remove_callback(tcl_output, tclOutput);
+
+ /* We dump output into this local variable */
+ Jim_SetResult(interp, tclOutput);
+ Jim_DecrRefCount(interp, tclOutput);
+
+ for (i = 0; i < nwords; i++)
+ free(words[i]);
+ free(words);
+
+ int *return_retval = Jim_GetAssocData(interp, "retval");
+ if (return_retval != NULL)
+ {
+ *return_retval = retval;
+ }
+
+ return (retval==ERROR_OK)?JIM_OK:JIM_ERR;
+}