📄 tclcmdmz.c
字号:
if (switchObjc == 1) { code = Tcl_ListObjLength(interp, switchObjv[0], &switchObjc); if (code != TCL_OK) { return code; } splitObjs = 1; } for (i = 0; i < switchObjc; i += 2) { if (i == (switchObjc-1)) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "extra switch pattern with no body", -1); code = TCL_ERROR; goto done; } /* * See if the pattern matches the string. */ if (splitObjs) { code = Tcl_ListObjIndex(interp, switchObjv[0], i, &patternObj); if (code != TCL_OK) { return code; } pattern = Tcl_GetStringFromObj(patternObj, &patternLen); } else { pattern = Tcl_GetStringFromObj(switchObjv[i], &patternLen); } matched = 0; if ((*pattern == 'd') && (i == switchObjc-2) && (strcmp(pattern, "default") == 0)) { matched = 1; } else { /* * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL. */ switch (mode) { case EXACT: matched = (strcmp(string, pattern) == 0); break; case GLOB: matched = Tcl_StringMatch(string, pattern); break; case REGEXP: matched = Tcl_RegExpMatch(interp, string, pattern); if (matched < 0) { code = TCL_ERROR; goto done; } break; } } if (!matched) { continue; } /* * We've got a match. Find a body to execute, skipping bodies * that are "-". */ for (bodyIdx = i+1; ; bodyIdx += 2) { if (bodyIdx >= switchObjc) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no body specified for pattern \"", pattern, "\"", (char *) NULL); code = TCL_ERROR; goto done; } if (splitObjs) { code = Tcl_ListObjIndex(interp, switchObjv[0], bodyIdx, &bodyObj); if (code != TCL_OK) { return code; } } else { bodyObj = switchObjv[bodyIdx]; } /* * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL. */ body = Tcl_GetStringFromObj(bodyObj, &length); if ((length != 1) || (body[0] != '-')) { break; } } code = Tcl_EvalObj(interp, bodyObj); if (code == TCL_ERROR) { char msg[100]; sprintf(msg, "\n (\"%.50s\" arm line %d)", pattern, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } goto done; } /* * Nothing matched: return nothing. */ code = TCL_OK; done: return code;#undef EXACT#undef GLOB#undef REGEXP}/* *---------------------------------------------------------------------- * * Tcl_TimeObjCmd -- * * This object-based procedure is invoked to process the "time" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_TimeObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ register Tcl_Obj *objPtr; register int i, result; int count; double totalMicroSec; Tcl_Time start, stop; char buf[100]; if (objc == 2) { count = 1; } else if (objc == 3) { result = Tcl_GetIntFromObj(interp, objv[2], &count); if (result != TCL_OK) { return result; } } else { Tcl_WrongNumArgs(interp, 1, objv, "command ?count?"); return TCL_ERROR; } objPtr = objv[1]; i = count; TclpGetTime(&start); while (i-- > 0) { result = Tcl_EvalObj(interp, objPtr); if (result != TCL_OK) { return result; } } TclpGetTime(&stop); totalMicroSec = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); sprintf(buf, "%.0f microseconds per iteration", ((count <= 0) ? 0 : totalMicroSec/count)); Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_TraceCmd -- * * This procedure is invoked to process the "trace" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_TraceCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ int c; size_t length; if (argc < 2) { Tcl_AppendResult(interp, "too few args: should be \"", argv[0], " option [arg arg ...]\"", (char *) NULL); return TCL_ERROR; } c = argv[1][1]; length = strlen(argv[1]); if ((c == 'a') && (strncmp(argv[1], "variable", length) == 0) && (length >= 2)) { char *p; int flags, length; TraceVarInfo *tvarPtr; if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " variable name ops command\"", (char *) NULL); return TCL_ERROR; } flags = 0; for (p = argv[3] ; *p != 0; p++) { if (*p == 'r') { flags |= TCL_TRACE_READS; } else if (*p == 'w') { flags |= TCL_TRACE_WRITES; } else if (*p == 'u') { flags |= TCL_TRACE_UNSETS; } else { goto badOps; } } if (flags == 0) { goto badOps; } length = strlen(argv[4]); tvarPtr = (TraceVarInfo *) ckalloc((unsigned) (sizeof(TraceVarInfo) - sizeof(tvarPtr->command) + length + 1)); tvarPtr->flags = flags; tvarPtr->errMsg = NULL; tvarPtr->length = length; flags |= TCL_TRACE_UNSETS; strcpy(tvarPtr->command, argv[4]); if (Tcl_TraceVar(interp, argv[2], flags, TraceVarProc, (ClientData) tvarPtr) != TCL_OK) { ckfree((char *) tvarPtr); return TCL_ERROR; } } else if ((c == 'd') && (strncmp(argv[1], "vdelete", length) && (length >= 2)) == 0) { char *p; int flags, length; TraceVarInfo *tvarPtr; ClientData clientData; if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " vdelete name ops command\"", (char *) NULL); return TCL_ERROR; } flags = 0; for (p = argv[3] ; *p != 0; p++) { if (*p == 'r') { flags |= TCL_TRACE_READS; } else if (*p == 'w') { flags |= TCL_TRACE_WRITES; } else if (*p == 'u') { flags |= TCL_TRACE_UNSETS; } else { goto badOps; } } if (flags == 0) { goto badOps; } /* * Search through all of our traces on this variable to * see if there's one with the given command. If so, then * delete the first one that matches. */ length = strlen(argv[4]); clientData = 0; while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0, TraceVarProc, clientData)) != 0) { tvarPtr = (TraceVarInfo *) clientData; if ((tvarPtr->length == length) && (tvarPtr->flags == flags) && (strncmp(argv[4], tvarPtr->command, (size_t) length) == 0)) { Tcl_UntraceVar(interp, argv[2], flags | TCL_TRACE_UNSETS, TraceVarProc, clientData); if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); } ckfree((char *) tvarPtr); break; } } } else if ((c == 'i') && (strncmp(argv[1], "vinfo", length) == 0) && (length >= 2)) { ClientData clientData; char ops[4], *p; char *prefix = "{"; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " vinfo name\"", (char *) NULL); return TCL_ERROR; } clientData = 0; while ((clientData = Tcl_VarTraceInfo(interp, argv[2], 0, TraceVarProc, clientData)) != 0) { TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData; p = ops; if (tvarPtr->flags & TCL_TRACE_READS) { *p = 'r'; p++; } if (tvarPtr->flags & TCL_TRACE_WRITES) { *p = 'w'; p++; } if (tvarPtr->flags & TCL_TRACE_UNSETS) { *p = 'u'; p++; } *p = '\0'; Tcl_AppendResult(interp, prefix, (char *) NULL); Tcl_AppendElement(interp, ops); Tcl_AppendElement(interp, tvarPtr->command); Tcl_AppendResult(interp, "}", (char *) NULL); prefix = " {"; } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": should be variable, vdelete, or vinfo", (char *) NULL); return TCL_ERROR; } return TCL_OK; badOps: Tcl_AppendResult(interp, "bad operations \"", argv[3], "\": should be one or more of rwu", (char *) NULL); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * TraceVarProc -- * * This procedure is called to handle variable accesses that have * been traced using the "trace" command. * * Results: * Normally returns NULL. If the trace command returns an error, * then this procedure returns an error string. * * Side effects: * Depends on the command associated with the trace. * *---------------------------------------------------------------------- */ /* ARGSUSED */static char *TraceVarProc(clientData, interp, name1, name2, flags) ClientData clientData; /* Information about the variable trace. */ Tcl_Interp *interp; /* Interpreter containing variable. */ char *name1; /* Name of variable or array. */ char *name2; /* Name of element within array; NULL means * scalar variable is being referenced. */ int flags; /* OR-ed bits giving operation and other * information. */{ Interp *iPtr = (Interp *) interp; TraceVarInfo *tvarPtr = (TraceVarInfo *) clientData; char *result; int code; Interp dummy; Tcl_DString cmd; Tcl_Obj *saveObjPtr, *oldObjResultPtr; result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); tvarPtr->errMsg = NULL; } if ((tvarPtr->flags & flags) && !(flags & TCL_INTERP_DESTROYED)) { /* * Generate a command to execute by appending list elements * for the two variable names and the operation. The five * extra characters are for three space, the opcode character, * and the terminating null. */ if (name2 == NULL) { name2 = ""; } Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, tvarPtr->command, tvarPtr->length); Tcl_DStringAppendElement(&cmd, name1); Tcl_DStringAppendElement(&cmd, name2); if (flags & TCL_TRACE_READS) { Tcl_DStringAppend(&cmd, " r", 2); } else if (flags & TCL_TRACE_WRITES) { Tcl_DStringAppend(&cmd, " w", 2); } else if (flags & TCL_TRACE_UNSETS) { Tcl_DStringAppend(&cmd, " u", 2); } /* * Execute the command. Be careful to save and restore both the * string and object results from the interpreter used for * the command. We discard any object result the command returns. */ dummy.objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(dummy.objResultPtr); if (interp->freeProc == 0) { dummy.freeProc = (Tcl_FreeProc *) 0; dummy.result = ""; Tcl_SetResult((Tcl_Interp *) &dummy, interp->result, TCL_VOLATILE); } else { dummy.freeProc = interp->freeProc; dummy.result = interp->result; interp->freeProc = (Tcl_FreeProc *) 0; } saveObjPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(saveObjPtr); code = Tcl_Eval(interp, Tcl_DStringValue(&cmd)); if (code != TCL_OK) { /* copy error msg to result */ tvarPtr->errMsg = (char *) ckalloc((unsigned) (strlen(interp->result) + 1)); strcpy(tvarPtr->errMsg, interp->result); result = tvarPtr->errMsg; Tcl_ResetResult(interp); /* must clear error state. */ } /* * Restore the interpreter's string result. */ Tcl_SetResult(interp, dummy.result, (dummy.freeProc == 0) ? TCL_VOLATILE : dummy.freeProc); /* * Restore the interpreter's object result from saveObjPtr. */ oldObjResultPtr = iPtr->objResultPtr; iPtr->objResultPtr = saveObjPtr; /* was incremented above */ Tcl_DecrRefCount(oldObjResultPtr); Tcl_DecrRefCount(dummy.objResultPtr); dummy.objResultPtr = NULL; Tcl_DStringFree(&cmd); } if (flags & TCL_TRACE_DESTROYED) { result = NULL; if (tvarPtr->errMsg != NULL) { ckfree(tvarPtr->errMsg); } ckfree((char *) tvarPtr); } return result;}/* *---------------------------------------------------------------------- * * Tcl_WhileCmd -- * * This procedure is invoked to process the "while" Tcl command. * See the user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when * a command name is computed at runtime, and is "while" or the name * to which "while" was renamed: e.g., "set z while; $z {$i<100} {}" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_WhileCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ int result, value; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " test command\"", (char *) NULL); return TCL_ERROR; } while (1) { result = Tcl_ExprBoolean(interp, argv[1], &value); if (result != TCL_OK) { return result; } if (!value) { break; } result = Tcl_Eval(interp, argv[2]); if ((result != TCL_OK) && (result != TCL_CONTINUE)) { if (result == TCL_ERROR) { char msg[60]; sprintf(msg, "\n (\"while\" body line %d)", interp->errorLine); Tcl_AddErrorInfo(interp, msg); } break; } } if (result == TCL_BREAK) { result = TCL_OK; } if (result == TCL_OK) { Tcl_ResetResult(interp); } return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -