Browse Source

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.
tags/v0.4.0-rc1
Zachary T Welch 14 years ago
parent
commit
cbc894ed7b
1 changed files with 34 additions and 15 deletions
  1. +34
    -15
      src/helper/command.c

+ 34
- 15
src/helper/command.c 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;
}


Loading…
Cancel
Save