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, static int run_command(struct command_context *context,
struct command *c, const char *words[], unsigned num_words); 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, static void tcl_output(void *privData, const char *file, unsigned line,
const char *function, const char *string) const char *function, const char *string)
{ {
Jim_Obj *tclOutput = (Jim_Obj *)privData; struct log_capture_state *state = (struct log_capture_state *)privData;
Jim_AppendString(interp, tclOutput, string, strlen(string)); 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 /* capture log output and return it. A garbage collect can
* happen, so we need a reference count to this object */ * happen, so we need a reference count to this object */
Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
if (NULL == tclOutput) if (NULL == tclOutput)
return NULL; return NULL;
struct log_capture_state *state = malloc(sizeof(*state));
if (NULL == state)
return NULL;
state->interp = interp;
Jim_IncrRefCount(tclOutput); Jim_IncrRefCount(tclOutput);
log_add_callback(tcl_output, tclOutput); state->output = tclOutput;
return 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); if (NULL == state)
Jim_SetResult(interp, tclOutput); return;
Jim_DecrRefCount(interp, tclOutput);
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) 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) if (NULL == words)
return JIM_ERR; return JIM_ERR;
Jim_Obj *tclOutput = NULL; struct log_capture_state *state = NULL;
if (capture) if (capture)
tclOutput = command_log_capture_start(interp); state = command_log_capture_start(interp);
struct command_context *cmd_ctx = current_command_context(); struct command_context *cmd_ctx = current_command_context();
int retval = run_command(cmd_ctx, c, (const char **)words, nwords); int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
if (capture) command_log_capture_finish(state);
command_log_capture_finish(interp, tclOutput);
script_command_args_free(words, nwords); script_command_args_free(words, nwords);
return command_retval_set(interp, retval); 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) if (argc != 2)
return JIM_ERR; 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); const char *str = Jim_GetString(argv[1], NULL);
int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
command_log_capture_finish(interp, tclOutput); command_log_capture_finish(state);
return retcode; return retcode;
} }