📄 tclvar.c
字号:
(TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS);
tracePtr->nextPtr = varPtr->tracePtr;
varPtr->tracePtr = tracePtr;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_UntraceVar --
*
* Remove a previously-created trace for a variable.
*
* Results:
* None.
*
* Side effects:
* If there exists a trace for the variable given by varName
* with the given flags, proc, and clientData, then that trace
* is removed.
*
*----------------------------------------------------------------------
*/
void
Tcl_UntraceVar(interp, varName, flags, proc, clientData)
Tcl_Interp *interp; /* Interpreter containing traced variable. */
char *varName; /* Name of variable; may end with "(index)"
* to signify an array reference. */
int flags; /* OR-ed collection of bits describing
* current trace, including any of
* TCL_TRACE_READS, TCL_TRACE_WRITES,
* TCL_TRACE_UNSETS, and TCL_GLOBAL_ONLY. */
Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
ClientData clientData; /* Arbitrary argument to pass to proc. */
{
register char *p;
/*
* If varName refers to an array (it ends with a parenthesized
* element name), then handle it specially.
*/
for (p = varName; *p != '\0'; p++) {
if (*p == '(') {
char *open = p;
do {
p++;
} while (*p != '\0');
p--;
if (*p != ')') {
goto scalar;
}
*open = '\0';
*p = '\0';
Tcl_UntraceVar2(interp, varName, open+1, flags, proc, clientData);
*open = '(';
*p = ')';
return;
}
}
scalar:
Tcl_UntraceVar2(interp, varName, (char *) NULL, flags, proc, clientData);
}
/*
*----------------------------------------------------------------------
*
* Tcl_UntraceVar2 --
*
* Remove a previously-created trace for a variable.
*
* Results:
* None.
*
* Side effects:
* If there exists a trace for the variable given by part1
* and part2 with the given flags, proc, and clientData, then
* that trace is removed.
*
*----------------------------------------------------------------------
*/
void
Tcl_UntraceVar2(interp, part1, part2, flags, proc, clientData)
Tcl_Interp *interp; /* Interpreter containing traced variable. */
char *part1; /* Name of variable or array. */
char *part2; /* Name of element within array; NULL means
* trace applies to scalar variable or array
* as-a-whole. */
int flags; /* OR-ed collection of bits describing
* current trace, including any of
* TCL_TRACE_READS, TCL_TRACE_WRITES,
* TCL_TRACE_UNSETS, and TCL_GLOBAL_ONLY. */
Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
ClientData clientData; /* Arbitrary argument to pass to proc. */
{
register VarTrace *tracePtr;
VarTrace *prevPtr;
Var *varPtr;
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
ActiveVarTrace *activePtr;
/*
* First, lookup the variable.
*/
if ((flags & TCL_GLOBAL_ONLY) || (iPtr->varFramePtr == NULL)) {
hPtr = Tcl_FindHashEntry(&iPtr->globalTable, part1);
} else {
hPtr = Tcl_FindHashEntry(&iPtr->varFramePtr->varTable, part1);
}
if (hPtr == NULL) {
return;
}
varPtr = (Var *) Tcl_GetHashValue(hPtr);
if (varPtr->flags & VAR_UPVAR) {
hPtr = varPtr->value.upvarPtr;
varPtr = (Var *) Tcl_GetHashValue(hPtr);
}
if (part2 != NULL) {
if (!(varPtr->flags & VAR_ARRAY)) {
return;
}
hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, part2);
if (hPtr == NULL) {
return;
}
varPtr = (Var *) Tcl_GetHashValue(hPtr);
}
flags &= (TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS);
for (tracePtr = varPtr->tracePtr, prevPtr = NULL; ;
prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
if (tracePtr == NULL) {
return;
}
if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags)
&& (tracePtr->clientData == clientData)) {
break;
}
}
/*
* The code below makes it possible to delete traces while traces
* are active: it makes sure that the deleted trace won't be
* processed by CallTraces.
*/
for (activePtr = iPtr->activeTracePtr; activePtr != NULL;
activePtr = activePtr->nextPtr) {
if (activePtr->nextTracePtr == tracePtr) {
activePtr->nextTracePtr = tracePtr->nextPtr;
}
}
if (prevPtr == NULL) {
varPtr->tracePtr = tracePtr->nextPtr;
} else {
prevPtr->nextPtr = tracePtr->nextPtr;
}
ckfree((char *) tracePtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_VarTraceInfo --
*
* Return the clientData value associated with a trace on a
* variable. This procedure can also be used to step through
* all of the traces on a particular variable that have the
* same trace procedure.
*
* Results:
* The return value is the clientData value associated with
* a trace on the given variable. Information will only be
* returned for a trace with proc as trace procedure. If
* the clientData argument is NULL then the first such trace is
* returned; otherwise, the next relevant one after the one
* given by clientData will be returned. If the variable
* doesn't exist, or if there are no (more) traces for it,
* then NULL is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData)
Tcl_Interp *interp; /* Interpreter containing variable. */
char *varName; /* Name of variable; may end with "(index)"
* to signify an array reference. */
int flags; /* 0 or TCL_GLOBAL_ONLY. */
Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
ClientData prevClientData; /* If non-NULL, gives last value returned
* by this procedure, so this call will
* return the next trace after that one.
* If NULL, this call will return the
* first trace. */
{
register char *p;
/*
* If varName refers to an array (it ends with a parenthesized
* element name), then handle it specially.
*/
for (p = varName; *p != '\0'; p++) {
if (*p == '(') {
ClientData result;
char *open = p;
do {
p++;
} while (*p != '\0');
p--;
if (*p != ')') {
goto scalar;
}
*open = '\0';
*p = '\0';
result = Tcl_VarTraceInfo2(interp, varName, open+1, flags, proc,
prevClientData);
*open = '(';
*p = ')';
return result;
}
}
scalar:
return Tcl_VarTraceInfo2(interp, varName, (char *) NULL, flags, proc,
prevClientData);
}
/*
*----------------------------------------------------------------------
*
* Tcl_VarTraceInfo2 --
*
* Same as Tcl_VarTraceInfo, except takes name in two pieces
* instead of one.
*
* Results:
* Same as Tcl_VarTraceInfo.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ClientData
Tcl_VarTraceInfo2(interp, part1, part2, flags, proc, prevClientData)
Tcl_Interp *interp; /* Interpreter containing variable. */
char *part1; /* Name of variable or array. */
char *part2; /* Name of element within array; NULL means
* trace applies to scalar variable or array
* as-a-whole. */
int flags; /* 0 or TCL_GLOBAL_ONLY. */
Tcl_VarTraceProc *proc; /* Procedure assocated with trace. */
ClientData prevClientData; /* If non-NULL, gives last value returned
* by this procedure, so this call will
* return the next trace after that one.
* If NULL, this call will return the
* first trace. */
{
register VarTrace *tracePtr;
Var *varPtr;
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
/*
* First, lookup the variable.
*/
if ((flags & TCL_GLOBAL_ONLY) || (iPtr->varFramePtr == NULL)) {
hPtr = Tcl_FindHashEntry(&iPtr->globalTable, part1);
} else {
hPtr = Tcl_FindHashEntry(&iPtr->varFramePtr->varTable, part1);
}
if (hPtr == NULL) {
return NULL;
}
varPtr = (Var *) Tcl_GetHashValue(hPtr);
if (varPtr->flags & VAR_UPVAR) {
hPtr = varPtr->value.upvarPtr;
varPtr = (Var *) Tcl_GetHashValue(hPtr);
}
if (part2 != NULL) {
if (!(varPtr->flags & VAR_ARRAY)) {
return NULL;
}
hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, part2);
if (hPtr == NULL) {
return NULL;
}
varPtr = (Var *) Tcl_GetHashValue(hPtr);
}
/*
* Find the relevant trace, if any, and return its clientData.
*/
tracePtr = varPtr->tracePtr;
if (prevClientData != NULL) {
for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
if ((tracePtr->clientData == prevClientData)
&& (tracePtr->traceProc == proc)) {
tracePtr = tracePtr->nextPtr;
break;
}
}
}
for ( ; tracePtr != NULL; tracePtr = tracePtr->nextPtr) {
if (tracePtr->traceProc == proc) {
return tracePtr->clientData;
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* Tcl_SetCmd --
*
* This procedure is invoked to process the "set" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result value.
*
* Side effects:
* A variable's value may be changed.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
Tcl_SetCmd(dummy, interp, argc, argv)
ClientData dummy; /* Not used. */
register Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc == 2) {
char *value;
value = Tcl_GetVar(interp, argv[1], TCL_LEAVE_ERR_MSG);
if (value == NULL) {
return TCL_ERROR;
}
interp->result = value;
return TCL_OK;
} else if (argc == 3) {
char *result;
result = Tcl_SetVar(interp, argv[1], argv[2], TCL_LEAVE_ERR_MSG);
if (result == NULL) {
return TCL_ERROR;
}
interp->result = result;
return TCL_OK;
} else {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " varName ?newValue?\"", (char *) NULL);
return TCL_ERROR;
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_UnsetCmd --
*
* This procedure is invoked to process the "unset" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result value.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
Tcl_UnsetCmd(dummy, interp, argc, argv)
ClientData dummy; /* Not used. */
register Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int i;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " varName ?varName ...?\"", (char *) NULL);
return TCL_ERROR;
}
for (i = 1; i < argc; i++) {
if (Tcl_UnsetVar(interp, argv[i], TCL_LEAVE_ERR_MSG) != 0) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppendCmd --
*
* This procedure is invoked to process the "append" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result value.
*
* Side effects:
* A variable's value may be changed.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
Tcl_AppendCmd(dummy, interp, argc, argv)
ClientData dummy; /* Not used. */
register Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int i;
char *result = NULL; /* (Initialization only needed to keep
* the compiler from complaining) */
if (argc < 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " varName value ?value ...?\"", (char *) NULL);
return TCL_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -