static int InterpreterObjCmd( ClientData clientData, /* */ Tcl_Interp *interp, /* Current interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { int index, result = TCL_OK; static const char *const options[] = {"eval", "record", NULL}; enum option {OTHER_EVAL, OTHER_RECORD}; ConsoleInfo *info = clientData; Tcl_Interp *otherInterp = info->interp; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option arg"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "script"); return TCL_ERROR; } if ((otherInterp == NULL) || Tcl_InterpDeleted(otherInterp)) { Tcl_AppendResult(interp, "no active master interp", NULL); return TCL_ERROR; } Tcl_Preserve(otherInterp); switch ((enum option) index) { case OTHER_EVAL: result = Tcl_GlobalEvalObj(otherInterp, objv[2]); /* * TODO: Should exceptions be filtered here? */ Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(otherInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp)); break; case OTHER_RECORD: Tcl_RecordAndEvalObj(otherInterp, objv[2], TCL_EVAL_GLOBAL); /* * By not setting result, we discard any exceptions or errors here and * always return TCL_OK. All the caller wants is the interp result to * display, whether that's result or error message. */ Tcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp)); break; } Tcl_Release(otherInterp); return result; }
int Tk_CreateConsoleWindow( Tcl_Interp *interp) /* Interpreter to use for prompting. */ { Tcl_Channel chan; ConsoleInfo *info; Tk_Window mainWindow; Tcl_Command token; int result = TCL_OK; int haveConsoleChannel = 1; /* Init an interp with Tcl and Tk */ Tcl_Interp *consoleInterp = Tcl_CreateInterp(); if (Tcl_Init(consoleInterp) != TCL_OK) { goto error; } if (Tk_Init(consoleInterp) != TCL_OK) { goto error; } /* * Fetch the instance data from whatever std channel is a * console channel. If none, create fresh instance data. */ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN)) == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT)) == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR)) == &consoleChannelType) { } else { haveConsoleChannel = 0; } if (haveConsoleChannel) { ChannelData *data = (ChannelData *) Tcl_GetChannelInstanceData(chan); info = data->info; if (info->consoleInterp) { /* New ConsoleInfo for a new console window */ info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo)); info->refCount = 0; /* Update any console channels to make use of the new console */ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } } } else { info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo)); info->refCount = 0; } info->consoleInterp = consoleInterp; info->interp = interp; Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, info); info->refCount++; Tcl_CreateThreadExitHandler(DeleteConsoleInterp, consoleInterp); /* * Add console commands to the interp */ token = Tcl_CreateObjCommand(interp, "console", ConsoleObjCmd, info, ConsoleDeleteProc); info->refCount++; /* * We don't have to count the ref held by the [consoleinterp] command * in the consoleInterp. The ref held by the consoleInterp delete * handler takes care of us. */ Tcl_CreateObjCommand(consoleInterp, "consoleinterp", InterpreterObjCmd, info, NULL); mainWindow = Tk_MainWindow(interp); if (mainWindow) { Tk_CreateEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); info->refCount++; } Tcl_Preserve(consoleInterp); result = Tcl_GlobalEval(consoleInterp, "source $tk_library/console.tcl"); if (result == TCL_ERROR) { Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); } Tcl_Release(consoleInterp); if (result == TCL_ERROR) { Tcl_DeleteCommandFromToken(interp, token); mainWindow = Tk_MainWindow(interp); if (mainWindow) { Tk_DeleteEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); if (--info->refCount <= 0) { ckfree((char *) info); } } goto error; } return TCL_OK; error: Tcl_AddErrorInfo(interp, "\n (creating console window)"); if (!Tcl_InterpDeleted(consoleInterp)) { Tcl_DeleteInterp(consoleInterp); } return TCL_ERROR; }
static int ConsoleObjCmd( ClientData clientData, /* Access to the console interp */ Tcl_Interp *interp, /* Current interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { int index, result; static const char *const options[] = {"eval", "hide", "show", "title", NULL}; enum option {CON_EVAL, CON_HIDE, CON_SHOW, CON_TITLE}; Tcl_Obj *cmd = NULL; ConsoleInfo *info = (ConsoleInfo *) clientData; Tcl_Interp *consoleInterp = info->consoleInterp; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum option) index) { case CON_EVAL: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "script"); return TCL_ERROR; } cmd = objv[2]; break; case CON_HIDE: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } cmd = Tcl_NewStringObj("wm withdraw .", -1); break; case CON_SHOW: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } cmd = Tcl_NewStringObj("wm deiconify .", -1); break; case CON_TITLE: if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?title?"); return TCL_ERROR; } cmd = Tcl_NewStringObj("wm title .", -1); if (objc == 3) { Tcl_ListObjAppendElement(NULL, cmd, objv[2]); } break; } Tcl_IncrRefCount(cmd); if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) { Tcl_Preserve(consoleInterp); result = Tcl_GlobalEvalObj(consoleInterp, cmd); Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); Tcl_Release(consoleInterp); } else { Tcl_AppendResult(interp, "no active console interp", NULL); result = TCL_ERROR; } Tcl_DecrRefCount(cmd); return result; }
static int PrefixMatchObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags = 0, result, index; int dummyLength, i, errorLength; Tcl_Obj *errorPtr = NULL; const char *message = "option"; Tcl_Obj *tablePtr, *objPtr, *resultPtr; static const char *const matchOptions[] = { "-error", "-exact", "-message", NULL }; enum matchOptions { PRFMATCH_ERROR, PRFMATCH_EXACT, PRFMATCH_MESSAGE }; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? table string"); return TCL_ERROR; } for (i = 1; i < (objc - 2); i++) { if (Tcl_GetIndexFromObj(interp, objv[i], matchOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum matchOptions) index) { case PRFMATCH_EXACT: flags |= TCL_EXACT; break; case PRFMATCH_MESSAGE: if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value for -message", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL); return TCL_ERROR; } i++; message = Tcl_GetString(objv[i]); break; case PRFMATCH_ERROR: if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value for -error", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL); return TCL_ERROR; } i++; result = Tcl_ListObjLength(interp, objv[i], &errorLength); if (result != TCL_OK) { return TCL_ERROR; } if ((errorLength % 2) != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "error options must have an even number of elements", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); return TCL_ERROR; } errorPtr = objv[i]; break; } } tablePtr = objv[objc - 2]; objPtr = objv[objc - 1]; /* * Check that table is a valid list first, since we want to handle that * error case regardless of level. */ result = Tcl_ListObjLength(interp, tablePtr, &dummyLength); if (result != TCL_OK) { return result; } result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags, &index); if (result != TCL_OK) { if (errorPtr != NULL && errorLength == 0) { Tcl_ResetResult(interp); return TCL_OK; } else if (errorPtr == NULL) { return TCL_ERROR; } if (Tcl_IsShared(errorPtr)) { errorPtr = Tcl_DuplicateObj(errorPtr); } Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewStringObj("-code", 5)); Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewIntObj(result)); return Tcl_SetReturnOptions(interp, errorPtr); } result = Tcl_ListObjIndex(interp, tablePtr, index, &resultPtr); if (result != TCL_OK) { return result; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; }