command output capture: do not use interp global

Adds a log_capture_state structure to pass to the log capture
callback used by the command module.  Ensures that the capture occurs
in the proper context.
This commit is contained in:
Zachary T Welch 2009-11-29 18:39:13 -08:00
parent 7b2906de24
commit cbc894ed7b
1 changed files with 34 additions and 15 deletions

View File

@ -52,30 +52,50 @@ Jim_Interp *interp = NULL;
static int run_command(struct command_context *context,
struct command *c, const char *words[], unsigned num_words);
struct log_capture_state {
Jim_Interp *interp;
Jim_Obj *output;
};
static void tcl_output(void *privData, const char *file, unsigned line,
const char *function, const char *string)
{
Jim_Obj *tclOutput = (Jim_Obj *)privData;
Jim_AppendString(interp, tclOutput, string, strlen(string));
struct log_capture_state *state = (struct log_capture_state *)privData;
Jim_AppendString(state->interp, state->output, string, strlen(string));
}
static Jim_Obj *command_log_capture_start(Jim_Interp *interp)
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);
log_add_callback(tcl_output, tclOutput);
return tclOutput;
state->output = tclOutput;
log_add_callback(tcl_output, state);
return state;
}
static void command_log_capture_finish(Jim_Interp *interp, Jim_Obj *tclOutput)
static void command_log_capture_finish(struct log_capture_state *state)
{
log_remove_callback(tcl_output, tclOutput);
Jim_SetResult(interp, tclOutput);
Jim_DecrRefCount(interp, tclOutput);
if (NULL == state)
return;
log_remove_callback(tcl_output, state);
Jim_SetResult(state->interp, state->output);
Jim_DecrRefCount(state->interp, state->output);
free(state);
}
static int command_retval_set(Jim_Interp *interp, int retval)
@ -164,15 +184,14 @@ static int script_command_run(Jim_Interp *interp,
if (NULL == words)
return JIM_ERR;
Jim_Obj *tclOutput = NULL;
struct log_capture_state *state = NULL;
if (capture)
tclOutput = command_log_capture_start(interp);
state = command_log_capture_start(interp);
struct command_context *cmd_ctx = current_command_context();
int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
if (capture)
command_log_capture_finish(interp, tclOutput);
command_log_capture_finish(state);
script_command_args_free(words, nwords);
return command_retval_set(interp, retval);
@ -804,12 +823,12 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (argc != 2)
return JIM_ERR;
Jim_Obj *tclOutput = command_log_capture_start(interp);
struct log_capture_state *state = command_log_capture_start(interp);
const char *str = Jim_GetString(argv[1], NULL);
int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
command_log_capture_finish(interp, tclOutput);
command_log_capture_finish(state);
return retcode;
}