/** * [interp] creates a new interpreter. */ static int JimInterpCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { Jim_Interp *child; char buf[32]; if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, ""); return JIM_ERR; } /* Create the interpreter command */ child = Jim_CreateInterp(); Jim_RegisterCoreCommands(child); Jim_InitStaticExtensions(child); /* Copy some core variables to the new interpreter */ JimInterpCopyVariable(child, interp, "argv", NULL); JimInterpCopyVariable(child, interp, "argc", NULL); JimInterpCopyVariable(child, interp, "argv0", NULL); JimInterpCopyVariable(child, interp, "jim::argv0", NULL); JimInterpCopyVariable(child, interp, "jim::exe", NULL); /* Allow the child interpreter to find the parent */ Jim_SetAssocData(child, "interp.parent", NULL, interp); snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); Jim_CreateCommand(interp, buf, JimInterpSubCmdProc, child, JimInterpDelProc); Jim_SetResultString(interp, buf, -1); return JIM_OK; }
/* This extension is not dynamically loaded, instead it's linked statically, which is why we shouldn't use the unspecific 'Jim_OnLoad' name */ int Jim_EventLoopOnLoad(Jim_Interp *interp) { Jim_EventLoop *eventLoop; Jim_InitExtension(interp); if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG) != JIM_OK) return JIM_ERR; eventLoop = Jim_Alloc(sizeof(*eventLoop)); eventLoop->fileEventHead = NULL; eventLoop->timeEventHead = NULL; eventLoop->timeEventNextId = 1; Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, NULL, NULL); Jim_CreateCommand(interp, "after", JimELAfterCommand, NULL, NULL); /* Export events API */ Jim_RegisterApi(interp, "Jim_CreateFileHandler", Jim_CreateFileHandler); Jim_RegisterApi(interp, "Jim_DeleteFileHandler", Jim_DeleteFileHandler); Jim_RegisterApi(interp, "Jim_CreateTimeHandler", Jim_CreateTimeHandler); Jim_RegisterApi(interp, "Jim_DeleteTimeHandler", Jim_DeleteTimeHandler); Jim_RegisterApi(interp, "Jim_ProcessEvents", Jim_ProcessEvents); return JIM_OK; }
int Jim_eventloopInit(Jim_Interp *interp) { Jim_EventLoop *eventLoop; if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG)) return JIM_ERR; eventLoop = Jim_Alloc(sizeof(*eventLoop)); memset(eventLoop, 0, sizeof(*eventLoop)); Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL); Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL); Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL); return JIM_OK; }
int Jim_eventloopInit(Jim_Interp *interp) { Jim_EventLoop *eventLoop; if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG)) return JIM_ERR; eventLoop = Jim_Alloc(sizeof(*eventLoop)); eventLoop->fileEventHead = NULL; eventLoop->timeEventHead = NULL; eventLoop->timeEventNextId = 1; eventLoop->suppress_bgerror = 0; Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL); Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL); Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL); return JIM_OK; }
static int run_command(struct command_context *context, struct command *c, const char *words[], unsigned num_words) { if (!command_can_run(context, c)) { /* Many commands may be run only before/after 'init' */ const char *when; switch (c->mode) { case COMMAND_CONFIG: when = "before"; break; case COMMAND_EXEC: when = "after"; break; /* handle the impossible with humor; it guarantees a bug report! */ default: when = "if Cthulhu is summoned by"; break; } LOG_ERROR("The '%s' command must be used %s 'init'.", c->name, when); return ERROR_FAIL; } struct command_invocation cmd = { .ctx = context, .current = c, .name = c->name, .argc = num_words - 1, .argv = words + 1, }; int retval = c->handler(&cmd); if (retval == ERROR_COMMAND_SYNTAX_ERROR) { /* Print help for command */ char *full_name = command_name(c, ' '); if (NULL != full_name) { command_run_linef(context, "usage %s", full_name); free(full_name); } else retval = -ENOMEM; } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) { /* just fall through for a shutdown request */ } else if (retval != ERROR_OK) { /* we do not print out an error message because the command *should* * have printed out an error */ LOG_DEBUG("Command failed with error code %d", retval); } return retval; } int command_run_line(struct command_context *context, char *line) { /* all the parent commands have been registered with the interpreter * so, can just evaluate the line as a script and check for * results */ /* run the line thru a script engine */ int retval = ERROR_FAIL; int retcode; /* Beware! This code needs to be reentrant. It is also possible * for OpenOCD commands to be invoked directly from Tcl. This would * happen when the Jim Tcl interpreter is provided by eCos for * instance. */ Jim_Interp *interp = context->interp; Jim_DeleteAssocData(interp, "context"); retcode = Jim_SetAssocData(interp, "context", NULL, context); if (retcode == JIM_OK) { /* associated the return value */ Jim_DeleteAssocData(interp, "retval"); retcode = Jim_SetAssocData(interp, "retval", NULL, &retval); if (retcode == JIM_OK) { retcode = Jim_Eval_Named(interp, line, 0, 0); Jim_DeleteAssocData(interp, "retval"); } Jim_DeleteAssocData(interp, "context"); } if (retcode == JIM_OK) { const char *result; int reslen; result = Jim_GetString(Jim_GetResult(interp), &reslen); if (reslen > 0) { int i; char buff[256 + 1]; for (i = 0; i < reslen; i += 256) { int chunk; chunk = reslen - i; if (chunk > 256) chunk = 256; strncpy(buff, result + i, chunk); buff[chunk] = 0; LOG_USER_N("%s", buff); } LOG_USER_N("\n"); } retval = ERROR_OK; } else if (retcode == JIM_EXIT) { /* ignore. * exit(Jim_GetExitCode(interp)); */ } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) { return retcode; } else { Jim_MakeErrorMessage(interp); LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL)); if (retval == ERROR_OK) { /* It wasn't a low level OpenOCD command that failed */ return ERROR_FAIL; } return retval; } return retval; }