/* * Now we try to write big enough code to duplication our array in Jim's * list implementation. Later, we try to load a sample script in Tcl that * could print our list. */ int main(int argc, char **argv) { Jim_Interp *interp; int error; /* Create an interpreter. */ interp = Jim_CreateInterp(); assert(interp != NULL && "couldn't create interpreter"); /* We register base commands, so that we actually implement Tcl. */ Jim_RegisterCoreCommands(interp); /* And initialise any static extensions */ Jim_InitStaticExtensions(interp); /* Register our Jim commands. */ Jim_CreateCommand(interp, "MySampleCommand", MySampleCommandFunc, NULL, NULL); /* Run a script. */ error = Jim_Eval(interp, JIM_PROGRAM); if (error == JIM_ERR) { Jim_MakeErrorMessage(interp); fprintf(stderr, "%s\n", Jim_GetString(Jim_GetResult(interp), NULL)); Jim_FreeInterp(interp); exit(EXIT_FAILURE); } Jim_FreeInterp(interp); return (EXIT_SUCCESS); }
es_Status es_eval_tcl(es_Interp *interp, const char *script) { int error = Jim_Eval(interp, script); if (error == JIM_ERR) { Jim_MakeErrorMessage(interp); LOG_ERROR(Tcl,"%s\n", Jim_GetString(Jim_GetResult(interp), NULL)); } return error; }
int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr) { Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); Jim_CallFrame *savedFramePtr; int retval; savedFramePtr = interp->framePtr; interp->framePtr = interp->topFramePtr; retval = Jim_EvalObj(interp, scriptObjPtr); interp->framePtr = savedFramePtr; /* Try to report the error (if any) via the bgerror proc */ if (retval != JIM_OK && retval != JIM_RETURN && !eventLoop->suppress_bgerror) { Jim_Obj *objv[2]; int rc = JIM_ERR; objv[0] = Jim_NewStringObj(interp, "bgerror", -1); objv[1] = Jim_GetResult(interp); Jim_IncrRefCount(objv[0]); Jim_IncrRefCount(objv[1]); if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || (rc = Jim_EvalObjVector(interp, 2, objv)) != JIM_OK) { if (rc == JIM_BREAK) { /* No more bgerror calls */ eventLoop->suppress_bgerror++; } else { /* Report the error to stderr. */ Jim_MakeErrorMessage(interp); fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); /* And reset the result */ Jim_SetResultString(interp, "", -1); } } Jim_DecrRefCount(interp, objv[0]); Jim_DecrRefCount(interp, objv[1]); } return retval; }
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; }
int Jim_InteractivePrompt(Jim_Interp *interp) { int retcode = JIM_OK; char *history_file = NULL; #ifdef USE_LINENOISE const char *home; home = getenv("HOME"); if (home && isatty(STDIN_FILENO)) { int history_len = strlen(home) + sizeof("/.jim_history"); history_file = Jim_Alloc(history_len); snprintf(history_file, history_len, "%s/.jim_history", home); Jim_HistoryLoad(history_file); } #endif printf("Welcome to Jim version %d.%d" JIM_NL, JIM_VERSION / 100, JIM_VERSION % 100); Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); while (1) { Jim_Obj *scriptObjPtr; const char *result; int reslen; char prompt[20]; const char *str; if (retcode != 0) { const char *retcodestr = Jim_ReturnCode(retcode); if (*retcodestr == '?') { snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode); } else { snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr); } } else { prompt[0] = '\0'; } strcat(prompt, ". "); scriptObjPtr = Jim_NewStringObj(interp, "", 0); Jim_IncrRefCount(scriptObjPtr); while (1) { char state; int len; char *line; line = Jim_HistoryGetline(prompt); if (line == NULL) { if (errno == EINTR) { continue; } Jim_DecrRefCount(interp, scriptObjPtr); retcode = JIM_OK; goto out; } if (Jim_Length(scriptObjPtr) != 0) { Jim_AppendString(interp, scriptObjPtr, "\n", 1); } Jim_AppendString(interp, scriptObjPtr, line, -1); free(line); str = Jim_GetString(scriptObjPtr, &len); if (len == 0) { continue; } if (Jim_ScriptIsComplete(str, len, &state)) break; snprintf(prompt, sizeof(prompt), "%c> ", state); } #ifdef USE_LINENOISE if (strcmp(str, "h") == 0) { /* built-in history command */ Jim_HistoryShow(); Jim_DecrRefCount(interp, scriptObjPtr); continue; } Jim_HistoryAdd(Jim_String(scriptObjPtr)); if (history_file) { Jim_HistorySave(history_file); } #endif retcode = Jim_EvalObj(interp, scriptObjPtr); Jim_DecrRefCount(interp, scriptObjPtr); if (retcode == JIM_EXIT) { retcode = JIM_EXIT; break; } if (retcode == JIM_ERR) { Jim_MakeErrorMessage(interp); } result = Jim_GetString(Jim_GetResult(interp), &reslen); if (reslen) { printf("%s\n", result); } } out: Jim_Free(history_file); return retcode; }