/* * 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) { struct mystate *jconf; Jim_Interp *interp; Jim_Obj *errstr; Jim_Obj *n; Jim_Obj *v; int error; errstr = n = v = NULL; error = 0; /* This is the first function embedders should call. */ Jim_InitEmbedded(); /* Create an interpreter */ interp = Jim_CreateInterp(); assert(interp != NULL && "couldn't create interpreter"); /* * Then, we register base commands, so that we actually implement Tcl. */ Jim_RegisterCoreCommands(interp); /* * Create unique state for our sample parser and register all * Jim commands. */ jconf = mystate_new(); Jim_CreateCommand(interp, "interface", InterfaceFunc, jconf, NULL); Jim_CreateCommand(interp, "ip", InterfaceIPFunc, jconf, NULL); /* * Parse a script. */ error = Jim_EvalFile(interp, "./net.tcl"); if (error == JIM_ERR) { fprintf(stderr, "Couldn't execute Jim's script. " "Error occured\n"); Jim_PrintErrorMessage(interp); Jim_FreeInterp(interp); exit(EXIT_FAILURE); } ShowInterfaces(jconf->head); mystate_destroy(jconf); if (n != NULL) Jim_FreeObj(interp, n); Jim_FreeInterp(interp); return (EXIT_SUCCESS); }
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, __THIS__FILE__, __LINE__); Jim_DeleteAssocData(interp, "retval"); } Jim_DeleteAssocData(interp, "context"); } if (retcode == JIM_ERR) { if (retval != ERROR_COMMAND_CLOSE_CONNECTION) { /* We do not print the connection closed error message */ Jim_PrintErrorMessage(interp); } if (retval == ERROR_OK) { /* It wasn't a low level OpenOCD command that failed */ return ERROR_FAIL; } return retval; } else if (retcode == JIM_EXIT) { /* ignore. */ /* exit(Jim_GetExitCode(interp)); */ } else { 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("%s", "\n"); } retval = ERROR_OK; } return retval; }