📄 tcltest.c
字号:
asyncPtr = firstHandler; firstHandler = asyncPtr->nextPtr; Tcl_AsyncDelete(asyncPtr->handler); ckfree(asyncPtr->command); ckfree((char *) asyncPtr); } return TCL_OK; } if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL; prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id != id) { continue; } if (prevPtr == NULL) { firstHandler = asyncPtr->nextPtr; } else { prevPtr->nextPtr = asyncPtr->nextPtr; } Tcl_AsyncDelete(asyncPtr->handler); ckfree(asyncPtr->command); ckfree((char *) asyncPtr); break; } } else if (strcmp(argv[1], "mark") == 0) { if (argc != 5) { goto wrongNumArgs; } if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK) || (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) { return TCL_ERROR; } for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) { Tcl_AsyncMark(asyncPtr->handler); break; } } Tcl_SetResult(interp, (char *)argv[3], TCL_VOLATILE); return code; } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, int, or mark", (char *) NULL); return TCL_ERROR; } return TCL_OK;}static intAsyncHandlerProc(clientData, interp, code) ClientData clientData; /* Pointer to TestAsyncHandler structure. */ Tcl_Interp *interp; /* Interpreter in which command was * executed, or NULL. */ int code; /* Current return code from command. */{ TestAsyncHandler *asyncPtr = (TestAsyncHandler *) clientData; CONST char *listArgv[4], *cmd; char string[TCL_INTEGER_SPACE]; TclFormatInt(string, code); listArgv[0] = asyncPtr->command; listArgv[1] = Tcl_GetString(Tcl_GetObjResult(interp)); listArgv[2] = string; listArgv[3] = NULL; cmd = Tcl_Merge(3, listArgv); if (interp != NULL) { code = Tcl_Eval(interp, cmd); } else { /* * this should not happen, but by definition of how async * handlers are invoked, it's possible. Better error * checking is needed here. */ } ckfree((char *)cmd); return code;}/* *---------------------------------------------------------------------- * * TestcmdinfoCmd -- * * This procedure implements the "testcmdinfo" command. It is used * to test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation * and deletion. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes various commands and modifies their data. * *---------------------------------------------------------------------- */ /* ARGSUSED */static intTestcmdinfoCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */{ Tcl_CmdInfo info; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option cmdName\"", (char *) NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original", CmdDelProc1); } else if (strcmp(argv[1], "delete") == 0) { Tcl_DStringInit(&delString); Tcl_DeleteCommand(interp, argv[2]); Tcl_DStringResult(interp, &delString); } else if (strcmp(argv[1], "get") == 0) { if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) { Tcl_SetResult(interp, "??", TCL_STATIC); return TCL_OK; } if (info.proc == CmdProc1) { Tcl_AppendResult(interp, "CmdProc1", " ", (char *) info.clientData, (char *) NULL); } else if (info.proc == CmdProc2) { Tcl_AppendResult(interp, "CmdProc2", " ", (char *) info.clientData, (char *) NULL); } else { Tcl_AppendResult(interp, "unknown", (char *) NULL); } if (info.deleteProc == CmdDelProc1) { Tcl_AppendResult(interp, " CmdDelProc1", " ", (char *) info.deleteData, (char *) NULL); } else if (info.deleteProc == CmdDelProc2) { Tcl_AppendResult(interp, " CmdDelProc2", " ", (char *) info.deleteData, (char *) NULL); } else { Tcl_AppendResult(interp, " unknown", (char *) NULL); } Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, (char *) NULL); if (info.isNativeObjectProc) { Tcl_AppendResult(interp, " nativeObjectProc", (char *) NULL); } else { Tcl_AppendResult(interp, " stringProc", (char *) NULL); } } else if (strcmp(argv[1], "modify") == 0) { info.proc = CmdProc2; info.clientData = (ClientData) "new_command_data"; info.objProc = NULL; info.objClientData = (ClientData) NULL; info.deleteProc = CmdDelProc2; info.deleteData = (ClientData) "new_delete_data"; if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) { Tcl_SetResult(interp, "0", TCL_STATIC); } else { Tcl_SetResult(interp, "1", TCL_STATIC); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, get, or modify", (char *) NULL); return TCL_ERROR; } return TCL_OK;} /*ARGSUSED*/static intCmdProc1(clientData, interp, argc, argv) ClientData clientData; /* String to return. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */{ Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, (char *) NULL); return TCL_OK;} /*ARGSUSED*/static intCmdProc2(clientData, interp, argc, argv) ClientData clientData; /* String to return. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */{ Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, (char *) NULL); return TCL_OK;}static voidCmdDelProc1(clientData) ClientData clientData; /* String to save. */{ Tcl_DStringInit(&delString); Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1); Tcl_DStringAppend(&delString, (char *) clientData, -1);}static voidCmdDelProc2(clientData) ClientData clientData; /* String to save. */{ Tcl_DStringInit(&delString); Tcl_DStringAppend(&delString, "CmdDelProc2 ", -1); Tcl_DStringAppend(&delString, (char *) clientData, -1);}/* *---------------------------------------------------------------------- * * TestcmdtokenCmd -- * * This procedure implements the "testcmdtoken" command. It is used * to test Tcl_Command tokens and procedures such as * Tcl_GetCommandFullName. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes various commands and modifies their data. * *---------------------------------------------------------------------- */ /* ARGSUSED */static intTestcmdtokenCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */{ Tcl_Command token; int *l; char buf[30]; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option arg\"", (char *) NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { token = Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original", (Tcl_CmdDeleteProc *) NULL); sprintf(buf, "%p", (VOID *)token); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if (strcmp(argv[1], "name") == 0) { Tcl_Obj *objPtr; if (sscanf(argv[2], "%p", &l) != 1) { Tcl_AppendResult(interp, "bad command token \"", argv[2], "\"", (char *) NULL); return TCL_ERROR; } objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr); Tcl_AppendElement(interp, Tcl_GetCommandName(interp, (Tcl_Command) l)); Tcl_AppendElement(interp, Tcl_GetString(objPtr)); Tcl_DecrRefCount(objPtr); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create or name", (char *) NULL); return TCL_ERROR; } return TCL_OK;}/* *---------------------------------------------------------------------- * * TestcmdtraceCmd -- * * This procedure implements the "testcmdtrace" command. It is used * to test Tcl_CreateTrace and Tcl_DeleteTrace. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes a command trace, and tests the invocation of * a procedure by the command trace. * *---------------------------------------------------------------------- */ /* ARGSUSED */static intTestcmdtraceCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ CONST char **argv; /* Argument strings. */{ Tcl_DString buffer; int result; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option script\"", (char *) NULL); return TCL_ERROR; } if (strcmp(argv[1], "tracetest") == 0) { Tcl_DStringInit(&buffer); cmdTrace = Tcl_CreateTrace(interp, 50000, (Tcl_CmdTraceProc *) CmdTraceProc, (ClientData) &buffer); result = Tcl_Eval(interp, argv[2]); if (result == TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); } Tcl_DeleteTrace(interp, cmdTrace); Tcl_DStringFree(&buffer); } else if (strcmp(argv[1], "deletetest") == 0) { /* * Create a command trace then eval a script to check whether it is * called. Note that this trace procedure removes itself as a * further check of the robustness of the trace proc calling code in * TclExecuteByteCode. */ cmdTrace = Tcl_CreateTrace(interp, 50000, (Tcl_CmdTraceProc *) CmdTraceDeleteProc, (ClientData) NULL); Tcl_Eval(interp, argv[2]); } else if ( strcmp(argv[1], "resulttest" ) == 0 ) { /* Create an object-based trace, then eval a script. This is used * to test return codes other than TCL_OK from the trace engine. */ static int deleteCalled; deleteCalled = 0; cmdTrace = Tcl_CreateObjTrace( interp, 50000, TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc, (ClientData) &deleteCalled, ObjTraceDeleteProc ); result = Tcl_Eval( interp, argv[ 2 ] ); Tcl_DeleteTrace( interp, cmdTrace ); if ( !deleteCalled ) { Tcl_SetResult( interp, "Delete wasn't called", TCL_STATIC ); return TCL_ERROR; } else { return result; } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be tracetest, deletetest or resulttest", (char *) NULL); return TCL_ERROR; } return TCL_OK;}static voidCmdTraceProc(clientData, interp, level, command, cmdProc, cmdClientData, argc, argv) ClientData clientData; /* Pointer to buffer in which the * command and arguments are appended. * Accumulates test result. */ Tcl_Interp *interp; /* Current interpreter. */ int level; /* Current trace level. */ char *command; /* The command being traced (after * substitutions). */ Tcl_CmdProc *cmdProc; /* Points to command's command procedure. */ ClientData cmdClientData; /* Client data associated with command * procedure. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ Tcl_DString *bufPtr = (Tcl_DString *) clientData; int i; Tcl_DStringAppendElement(bufPtr, command); Tcl_DStringStartSublist(bufPtr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -