+ struct log_capture_state *state = (struct log_capture_state *)privData;
+ Jim_AppendString(state->interp, state->output, string, strlen(string));
+}
+
+static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
+{
+ /* capture log output and return it. A garbage collect can
+ * happen, so we need a reference count to this object */
+ Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
+ if (NULL == tclOutput)
+ return NULL;
+
+ struct log_capture_state *state = malloc(sizeof(*state));
+ if (NULL == state)
+ return NULL;
+
+ state->interp = interp;
+ Jim_IncrRefCount(tclOutput);
+ state->output = tclOutput;
+
+ log_add_callback(tcl_output, state);
+
+ return state;
+}
+
+/* Classic openocd commands provide progress output which we
+ * will capture and return as a Tcl return value.
+ *
+ * However, if a non-openocd command has been invoked, then it
+ * makes sense to return the tcl return value from that command.
+ *
+ * The tcl return value is empty for openocd commands that provide
+ * progress output.
+ *
+ * Therefore we set the tcl return value only if we actually
+ * captured output.
+ */
+static void command_log_capture_finish(struct log_capture_state *state)
+{
+ if (NULL == state)
+ return;
+
+ log_remove_callback(tcl_output, state);
+
+ int length;
+ Jim_GetString(state->output, &length);
+
+ if (length > 0)
+ {
+ Jim_SetResult(state->interp, state->output);
+ } else
+ {
+ /* No output captured, use tcl return value (which could
+ * be empty too). */
+ }
+ Jim_DecrRefCount(state->interp, state->output);
+
+ free(state);
+}
+
+static int command_retval_set(Jim_Interp *interp, int retval)
+{
+ int *return_retval = Jim_GetAssocData(interp, "retval");
+ if (return_retval != NULL)
+ *return_retval = retval;
+
+ return (retval == ERROR_OK) ? JIM_OK : JIM_ERR;