Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba9050dc8c | ||
|
|
3f690409ee | ||
|
|
c32522f739 | ||
|
|
95c04468f9 | ||
|
|
f5fb2ee8f9 |
-21
@@ -354,27 +354,6 @@ containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR
|
||||
associated with the trace. If \fIname\fR does not exist or does not
|
||||
have any traces set, then the result of the command will be an empty
|
||||
string.
|
||||
.RE
|
||||
.PP
|
||||
For backwards compatibility, three other subcommands are available:
|
||||
.RS
|
||||
.TP
|
||||
\fBtrace variable \fIname ops command\fR
|
||||
This is equivalent to \fBtrace add variable \fIname ops command\fR.
|
||||
.TP
|
||||
\fBtrace vdelete \fIname ops command\fR
|
||||
This is equivalent to \fBtrace remove variable \fIname ops command\fR
|
||||
.TP
|
||||
\fBtrace vinfo \fIname\fR
|
||||
This is equivalent to \fBtrace info variable \fIname\fR
|
||||
.RE
|
||||
.PP
|
||||
These subcommands are deprecated and will likely be removed in a
|
||||
future version of Tcl. They use an older syntax in which \fBarray\fR,
|
||||
\fBread\fR, \fBwrite\fR, \fBunset\fR are replaced by \fBa\fR, \fBr\fR,
|
||||
\fBw\fR and \fBu\fR respectively, and the \fIops\fR argument is not a
|
||||
list, but simply a string concatenation of the operations, such as
|
||||
\fBrwua\fR.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Print a message whenever either of the global variables \fBfoo\fR and
|
||||
|
||||
@@ -906,10 +906,6 @@ typedef struct Tcl_DString {
|
||||
#define TCL_INTERP_DESTROYED 0x100
|
||||
#define TCL_LEAVE_ERR_MSG 0x200
|
||||
#define TCL_TRACE_ARRAY 0x800
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
/* Required to support old variable/vdelete/vinfo traces. */
|
||||
#define TCL_TRACE_OLD_STYLE 0x1000
|
||||
#endif
|
||||
/* Indicate the semantics of the result of a trace. */
|
||||
#define TCL_TRACE_RESULT_DYNAMIC 0x8000
|
||||
#define TCL_TRACE_RESULT_OBJECT 0x10000
|
||||
|
||||
+7
-2
@@ -232,7 +232,6 @@ static const CmdInfo builtInCmds[] = {
|
||||
{"switch", Tcl_SwitchObjCmd, TclCompileSwitchCmd, TclNRSwitchObjCmd, CMD_IS_SAFE},
|
||||
{"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE},
|
||||
{"throw", Tcl_ThrowObjCmd, TclCompileThrowCmd, NULL, CMD_IS_SAFE},
|
||||
{"trace", Tcl_TraceObjCmd, NULL, NULL, CMD_IS_SAFE},
|
||||
{"try", Tcl_TryObjCmd, TclCompileTryCmd, TclNRTryObjCmd, CMD_IS_SAFE},
|
||||
{"unset", Tcl_UnsetObjCmd, TclCompileUnsetCmd, NULL, CMD_IS_SAFE},
|
||||
{"uplevel", Tcl_UplevelObjCmd, NULL, TclNRUplevelObjCmd, CMD_IS_SAFE},
|
||||
@@ -768,7 +767,7 @@ Tcl_CreateInterp(void)
|
||||
|
||||
/*
|
||||
* Create the "array", "binary", "chan", "clock", "dict", "encoding",
|
||||
* "file", "info", "namespace" and "string" ensembles. Note that all these
|
||||
* "file", "info", "namespace", "string" and "trace" ensembles. Note that all these
|
||||
* commands (and their subcommands that are not present in the global
|
||||
* namespace) are wholly safe *except* for "clock", "encoding" and "file".
|
||||
*/
|
||||
@@ -793,6 +792,12 @@ Tcl_CreateInterp(void)
|
||||
|
||||
TclClockInit(interp);
|
||||
|
||||
/*
|
||||
* Register "trace" subcommands - modelled after the "clock" ensemble
|
||||
*/
|
||||
|
||||
TclTraceInit(interp);
|
||||
|
||||
/*
|
||||
* Register the built-in functions. This is empty now that they are
|
||||
* implemented as commands in the ::tcl::mathfunc namespace.
|
||||
|
||||
+2
-4
@@ -3430,9 +3430,7 @@ MODULE_SCOPE int Tcl_ThrowObjCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
MODULE_SCOPE int Tcl_TimeObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE int Tcl_TraceObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE void TclTraceInit(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int Tcl_TryObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -4018,7 +4016,7 @@ typedef enum TclProcessWaitStatus {
|
||||
TCL_PROCESS_EXITED = 1, /* Process has exited. */
|
||||
TCL_PROCESS_SIGNALED = 2, /* Child killed because of a signal. */
|
||||
TCL_PROCESS_STOPPED = 3, /* Child suspended because of a signal. */
|
||||
TCL_PROCESS_UNKNOWN_STATUS = 4
|
||||
TCL_PROCESS_UNKNOWN_STATUS = 4
|
||||
/* Child wait status didn't make sense. */
|
||||
} TclProcessWaitStatus;
|
||||
|
||||
|
||||
+225
-175
@@ -100,13 +100,24 @@ static Tcl_TraceTypeObjCmd TraceVariableObjCmd;
|
||||
static Tcl_TraceTypeObjCmd TraceCommandObjCmd;
|
||||
static Tcl_TraceTypeObjCmd TraceExecutionObjCmd;
|
||||
|
||||
static int TraceAddObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
|
||||
static int TraceRemoveObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
|
||||
static int TraceInfoObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
|
||||
|
||||
/*
|
||||
* Each primary subcommand has its own command procedure and its own index.
|
||||
* The index is used to select the correct action.
|
||||
*/
|
||||
enum traceOptions {
|
||||
TRACE_ADD, TRACE_INFO, TRACE_REMOVE
|
||||
};
|
||||
|
||||
/*
|
||||
* Each subcommand has a number of 'types' to which it can apply. Currently
|
||||
* 'execution', 'command' and 'variable' are the only types supported. These
|
||||
* three arrays MUST be kept in sync! In the future we may provide an API to
|
||||
* add to the list of supported trace types.
|
||||
*/
|
||||
|
||||
static const char *const traceTypeOptions[] = {
|
||||
"execution", "command", "variable", NULL
|
||||
};
|
||||
@@ -163,6 +174,191 @@ typedef struct {
|
||||
while ((clientData = Tcl_CommandTraceInfo(interp, name, 0, \
|
||||
TraceCommandProc, clientData)) != NULL)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclTraceInit --
|
||||
*
|
||||
* Registers the 'trace' subcommands with the Tcl interpreter
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Installs the commands (there are no client data)
|
||||
*
|
||||
* Note:
|
||||
* Copied directly from the clock command's initialisation routine
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TclTraceInit(
|
||||
Tcl_Interp *interp) /* Tcl interpreter */
|
||||
{
|
||||
char cmdName[50]; /* Buffer large enough to hold the string
|
||||
*::tcl::trace::remove
|
||||
* plus a terminating NUL. */
|
||||
EnsembleImplMap *traceCmdPtr;
|
||||
|
||||
/* Structure of the 'trace' ensemble */
|
||||
|
||||
static EnsembleImplMap traceImplMap[] = {
|
||||
{"add", TraceAddObjCmd, NULL, NULL, NULL, 0},
|
||||
{"remove", TraceRemoveObjCmd, NULL, NULL, NULL, 0},
|
||||
{"info", TraceInfoObjCmd, NULL, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Install the commands.
|
||||
* TODO - Let Tcl_MakeEnsemble do this?
|
||||
*/
|
||||
|
||||
#define TCL_TRACE_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
|
||||
memcpy(cmdName, "::tcl::trace::", TCL_TRACE_PREFIX_LEN);
|
||||
for (traceCmdPtr=traceImplMap ; traceCmdPtr->name!=NULL ; traceCmdPtr++) {
|
||||
strcpy(cmdName + TCL_TRACE_PREFIX_LEN, traceCmdPtr->name);
|
||||
Tcl_CreateObjCommand(interp, cmdName, traceCmdPtr->proc, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Make the trace ensemble */
|
||||
|
||||
TclMakeEnsemble(interp, "trace", traceImplMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TraceAddObjCmd --
|
||||
*
|
||||
* This function is invoked to process the "trace add" Tcl command. See the
|
||||
* user documentation for details on what it does.
|
||||
*
|
||||
* Standard syntax as of Tcl 8.4 is:
|
||||
* trace add {execution|command|variable} name ops cmd
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
TraceAddObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int typeIndex;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name opList cmdPrefix");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], traceTypeOptions, "option",
|
||||
0, &typeIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return traceSubCmds[typeIndex](interp, TRACE_ADD, objc, objv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TraceRemoveObjCmd --
|
||||
*
|
||||
* This function is invoked to process the "trace remove" Tcl command. See the
|
||||
* user documentation for details on what it does.
|
||||
*
|
||||
* Standard syntax as of Tcl 8.4 is:
|
||||
* trace remove {execution|command|variable} name ops cmd
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
TraceRemoveObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int typeIndex;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name opList cmdPrefix");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], traceTypeOptions, "option",
|
||||
0, &typeIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return traceSubCmds[typeIndex](interp, TRACE_REMOVE, objc, objv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TraceInfoObjCmd --
|
||||
*
|
||||
* This function is invoked to process the "trace info" Tcl command. See the
|
||||
* user documentation for details on what it does.
|
||||
*
|
||||
* Standard syntax as of Tcl 8.4 is:
|
||||
* trace remove {execution|command|variable} name
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
TraceInfoObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int typeIndex;
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], traceTypeOptions, "option",
|
||||
0, &typeIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return traceSubCmds[typeIndex](interp, TRACE_INFO, objc, objv);
|
||||
}
|
||||
|
||||
|
||||
#ifndef TCL_ORIGINAL_TRACE
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -191,24 +387,14 @@ Tcl_TraceObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int optionIndex;
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
const char *name;
|
||||
const char *flagOps, *p;
|
||||
#endif
|
||||
/* Main sub commands to 'trace' */
|
||||
static const char *const traceOptions[] = {
|
||||
"add", "info", "remove",
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
"variable", "vdelete", "vinfo",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
/* 'OLD' options are pre-Tcl-8.4 style */
|
||||
enum traceOptions {
|
||||
TRACE_ADD, TRACE_INFO, TRACE_REMOVE,
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
TRACE_OLD_VARIABLE, TRACE_OLD_VDELETE, TRACE_OLD_VINFO
|
||||
#endif
|
||||
};
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -266,116 +452,10 @@ Tcl_TraceObjCmd(
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
case TRACE_OLD_VARIABLE:
|
||||
case TRACE_OLD_VDELETE: {
|
||||
Tcl_Obj *copyObjv[6];
|
||||
Tcl_Obj *opsList;
|
||||
int code, numFlags;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name ops command");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
opsList = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(opsList);
|
||||
flagOps = TclGetStringFromObj(objv[3], &numFlags);
|
||||
if (numFlags == 0) {
|
||||
Tcl_DecrRefCount(opsList);
|
||||
goto badVarOps;
|
||||
}
|
||||
for (p = flagOps; *p != 0; p++) {
|
||||
Tcl_Obj *opObj;
|
||||
|
||||
if (*p == 'r') {
|
||||
TclNewLiteralStringObj(opObj, "read");
|
||||
} else if (*p == 'w') {
|
||||
TclNewLiteralStringObj(opObj, "write");
|
||||
} else if (*p == 'u') {
|
||||
TclNewLiteralStringObj(opObj, "unset");
|
||||
} else if (*p == 'a') {
|
||||
TclNewLiteralStringObj(opObj, "array");
|
||||
} else {
|
||||
Tcl_DecrRefCount(opsList);
|
||||
goto badVarOps;
|
||||
}
|
||||
Tcl_ListObjAppendElement(NULL, opsList, opObj);
|
||||
}
|
||||
copyObjv[0] = NULL;
|
||||
memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *));
|
||||
copyObjv[4] = opsList;
|
||||
if (optionIndex == TRACE_OLD_VARIABLE) {
|
||||
code = traceSubCmds[2](interp, TRACE_ADD, objc+1, copyObjv);
|
||||
} else {
|
||||
code = traceSubCmds[2](interp, TRACE_REMOVE, objc+1, copyObjv);
|
||||
}
|
||||
Tcl_DecrRefCount(opsList);
|
||||
return code;
|
||||
}
|
||||
case TRACE_OLD_VINFO: {
|
||||
ClientData clientData;
|
||||
char ops[5];
|
||||
Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr;
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
resultListPtr = Tcl_NewObj();
|
||||
name = Tcl_GetString(objv[2]);
|
||||
FOREACH_VAR_TRACE(interp, name, clientData) {
|
||||
TraceVarInfo *tvarPtr = clientData;
|
||||
char *q = ops;
|
||||
|
||||
pairObjPtr = Tcl_NewListObj(0, NULL);
|
||||
if (tvarPtr->flags & TCL_TRACE_READS) {
|
||||
*q = 'r';
|
||||
q++;
|
||||
}
|
||||
if (tvarPtr->flags & TCL_TRACE_WRITES) {
|
||||
*q = 'w';
|
||||
q++;
|
||||
}
|
||||
if (tvarPtr->flags & TCL_TRACE_UNSETS) {
|
||||
*q = 'u';
|
||||
q++;
|
||||
}
|
||||
if (tvarPtr->flags & TCL_TRACE_ARRAY) {
|
||||
*q = 'a';
|
||||
q++;
|
||||
}
|
||||
*q = '\0';
|
||||
|
||||
/*
|
||||
* Build a pair (2-item list) with the ops string as the first obj
|
||||
* element and the tvarPtr->command string as the second obj
|
||||
* element. Append the pair (as an element) to the end of the
|
||||
* result object list.
|
||||
*/
|
||||
|
||||
elemObjPtr = Tcl_NewStringObj(ops, -1);
|
||||
Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
|
||||
elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1);
|
||||
Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr);
|
||||
Tcl_ListObjAppendElement(interp, resultListPtr, pairObjPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultListPtr);
|
||||
break;
|
||||
}
|
||||
#endif /* TCL_REMOVE_OBSOLETE_TRACES */
|
||||
}
|
||||
return TCL_OK;
|
||||
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
badVarOps:
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad operations \"%s\": should be one or more of rwua",
|
||||
flagOps));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "BADOPS", NULL);
|
||||
return TCL_ERROR;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -424,8 +504,8 @@ TraceExecutionObjCmd(
|
||||
int i, listLen, result;
|
||||
Tcl_Obj **elemPtrs;
|
||||
|
||||
if (objc != 6) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name opList command");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -434,7 +514,7 @@ TraceExecutionObjCmd(
|
||||
* pointer to its array of element pointers.
|
||||
*/
|
||||
|
||||
result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
|
||||
result = Tcl_ListObjGetElements(interp, objv[3], &listLen, &elemPtrs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -466,7 +546,7 @@ TraceExecutionObjCmd(
|
||||
break;
|
||||
}
|
||||
}
|
||||
command = TclGetStringFromObj(objv[5], &commandLength);
|
||||
command = TclGetStringFromObj(objv[4], &commandLength);
|
||||
length = (size_t) commandLength;
|
||||
if ((enum traceOptions) optionIndex == TRACE_ADD) {
|
||||
TraceCommandInfo *tcmdPtr = ckalloc(
|
||||
@@ -484,7 +564,7 @@ TraceExecutionObjCmd(
|
||||
flags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC);
|
||||
}
|
||||
memcpy(tcmdPtr->command, command, length+1);
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
|
||||
tcmdPtr) != TCL_OK) {
|
||||
ckfree(tcmdPtr);
|
||||
@@ -503,7 +583,7 @@ TraceExecutionObjCmd(
|
||||
* First ensure the name given is valid.
|
||||
*/
|
||||
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -561,12 +641,12 @@ TraceExecutionObjCmd(
|
||||
ClientData clientData;
|
||||
Tcl_Obj *resultListPtr;
|
||||
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name");
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
|
||||
/*
|
||||
* First ensure the name given is valid.
|
||||
@@ -667,8 +747,8 @@ TraceCommandObjCmd(
|
||||
int i, listLen, result;
|
||||
Tcl_Obj **elemPtrs;
|
||||
|
||||
if (objc != 6) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name opList command");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -677,7 +757,7 @@ TraceCommandObjCmd(
|
||||
* pointer to its array of element pointers.
|
||||
*/
|
||||
|
||||
result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
|
||||
result = Tcl_ListObjGetElements(interp, objv[3], &listLen, &elemPtrs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -705,7 +785,7 @@ TraceCommandObjCmd(
|
||||
}
|
||||
}
|
||||
|
||||
command = TclGetStringFromObj(objv[5], &commandLength);
|
||||
command = TclGetStringFromObj(objv[4], &commandLength);
|
||||
length = (size_t) commandLength;
|
||||
if ((enum traceOptions) optionIndex == TRACE_ADD) {
|
||||
TraceCommandInfo *tcmdPtr = ckalloc(
|
||||
@@ -719,7 +799,7 @@ TraceCommandObjCmd(
|
||||
tcmdPtr->refCount = 1;
|
||||
flags |= TCL_TRACE_DELETE;
|
||||
memcpy(tcmdPtr->command, command, length+1);
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc,
|
||||
tcmdPtr) != TCL_OK) {
|
||||
ckfree(tcmdPtr);
|
||||
@@ -738,7 +818,7 @@ TraceCommandObjCmd(
|
||||
* First ensure the name given is valid.
|
||||
*/
|
||||
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -765,8 +845,8 @@ TraceCommandObjCmd(
|
||||
ClientData clientData;
|
||||
Tcl_Obj *resultListPtr;
|
||||
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name");
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -774,7 +854,7 @@ TraceCommandObjCmd(
|
||||
* First ensure the name given is valid.
|
||||
*/
|
||||
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -866,8 +946,8 @@ TraceVariableObjCmd(
|
||||
int i, listLen, result;
|
||||
Tcl_Obj **elemPtrs;
|
||||
|
||||
if (objc != 6) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name opList command");
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name opList command");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -876,7 +956,7 @@ TraceVariableObjCmd(
|
||||
* pointer to its array of element pointers.
|
||||
*/
|
||||
|
||||
result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs);
|
||||
result = Tcl_ListObjGetElements(interp, objv[3], &listLen, &elemPtrs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -908,7 +988,7 @@ TraceVariableObjCmd(
|
||||
break;
|
||||
}
|
||||
}
|
||||
command = TclGetStringFromObj(objv[5], &commandLength);
|
||||
command = TclGetStringFromObj(objv[4], &commandLength);
|
||||
length = (size_t) commandLength;
|
||||
if ((enum traceOptions) optionIndex == TRACE_ADD) {
|
||||
CombinedTraceVarInfo *ctvarPtr = ckalloc(
|
||||
@@ -916,18 +996,13 @@ TraceVariableObjCmd(
|
||||
+ 1 + length);
|
||||
|
||||
ctvarPtr->traceCmdInfo.flags = flags;
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
if (objv[0] == NULL) {
|
||||
ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE;
|
||||
}
|
||||
#endif
|
||||
ctvarPtr->traceCmdInfo.length = length;
|
||||
flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
|
||||
memcpy(ctvarPtr->traceCmdInfo.command, command, length+1);
|
||||
ctvarPtr->traceInfo.traceProc = TraceVarProc;
|
||||
ctvarPtr->traceInfo.clientData = &ctvarPtr->traceCmdInfo;
|
||||
ctvarPtr->traceInfo.flags = flags;
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
if (TraceVarEx(interp, name, NULL, (VarTrace *) ctvarPtr)
|
||||
!= TCL_OK) {
|
||||
ckfree(ctvarPtr);
|
||||
@@ -940,15 +1015,12 @@ TraceVariableObjCmd(
|
||||
* first one that matches.
|
||||
*/
|
||||
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
FOREACH_VAR_TRACE(interp, name, clientData) {
|
||||
TraceVarInfo *tvarPtr = clientData;
|
||||
|
||||
if ((tvarPtr->length == length)
|
||||
&& ((tvarPtr->flags
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
& ~TCL_TRACE_OLD_STYLE
|
||||
#endif
|
||||
)==flags)
|
||||
&& (strncmp(command, tvarPtr->command,
|
||||
(size_t) length) == 0)) {
|
||||
@@ -964,13 +1036,13 @@ TraceVariableObjCmd(
|
||||
case TRACE_INFO: {
|
||||
Tcl_Obj *resultListPtr;
|
||||
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "name");
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "name");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
resultListPtr = Tcl_NewObj();
|
||||
name = Tcl_GetString(objv[3]);
|
||||
name = Tcl_GetString(objv[2]);
|
||||
FOREACH_VAR_TRACE(interp, name, clientData) {
|
||||
Tcl_Obj *opObjPtr, *eachTraceObjPtr, *elemObjPtr;
|
||||
TraceVarInfo *tvarPtr = clientData;
|
||||
@@ -2009,19 +2081,6 @@ TraceVarProc(
|
||||
Tcl_DStringAppend(&cmd, tvarPtr->command, (int) tvarPtr->length);
|
||||
Tcl_DStringAppendElement(&cmd, name1);
|
||||
Tcl_DStringAppendElement(&cmd, (name2 ? name2 : ""));
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
if (tvarPtr->flags & TCL_TRACE_OLD_STYLE) {
|
||||
if (flags & TCL_TRACE_ARRAY) {
|
||||
TclDStringAppendLiteral(&cmd, " a");
|
||||
} else if (flags & TCL_TRACE_READS) {
|
||||
TclDStringAppendLiteral(&cmd, " r");
|
||||
} else if (flags & TCL_TRACE_WRITES) {
|
||||
TclDStringAppendLiteral(&cmd, " w");
|
||||
} else if (flags & TCL_TRACE_UNSETS) {
|
||||
TclDStringAppendLiteral(&cmd, " u");
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
if (flags & TCL_TRACE_ARRAY) {
|
||||
TclDStringAppendLiteral(&cmd, " array");
|
||||
} else if (flags & TCL_TRACE_READS) {
|
||||
@@ -2031,9 +2090,6 @@ TraceVarProc(
|
||||
} else if (flags & TCL_TRACE_UNSETS) {
|
||||
TclDStringAppendLiteral(&cmd, " unset");
|
||||
}
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Execute the command. We discard any object result the command
|
||||
@@ -2946,9 +3002,6 @@ Tcl_UntraceVar2(
|
||||
|
||||
flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
|
||||
TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
flagMask |= TCL_TRACE_OLD_STYLE;
|
||||
#endif
|
||||
flags &= flagMask;
|
||||
|
||||
hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
|
||||
@@ -3297,9 +3350,6 @@ TraceVarEx(
|
||||
|
||||
flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
|
||||
TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
flagMask |= TCL_TRACE_OLD_STYLE;
|
||||
#endif
|
||||
tracePtr->flags = tracePtr->flags & flagMask;
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&iPtr->varTraces, varPtr, &isNew);
|
||||
|
||||
+8
-8
@@ -188,7 +188,7 @@ test append-7.1 {lappend-created var and error in trace on that var} -setup {
|
||||
catch {rename foo ""}
|
||||
unset -nocomplain x
|
||||
} -body {
|
||||
trace variable x w foo
|
||||
trace add variable x write foo
|
||||
proc foo {} {global x; unset x}
|
||||
catch {lappend x 1}
|
||||
proc foo {args} {global x; unset x}
|
||||
@@ -201,37 +201,37 @@ test append-7.2 {lappend var triggers read trace} -setup {
|
||||
unset -nocomplain myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar a
|
||||
return $::result
|
||||
} -result {myvar {} r}
|
||||
} -result {myvar {} read}
|
||||
test append-7.3 {lappend var triggers read trace, array var} -setup {
|
||||
unset -nocomplain myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
# The behavior of read triggers on lappend changed in 8.0 to not trigger
|
||||
# them, and was changed back in 8.4.
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar(b) a
|
||||
return $::result
|
||||
} -result {myvar b r}
|
||||
} -result {myvar b read}
|
||||
test append-7.4 {lappend var triggers read trace, array var exists} -setup {
|
||||
unset -nocomplain myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
set myvar(0) 1
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar(b) a
|
||||
return $::result
|
||||
} -result {myvar b r}
|
||||
} -result {myvar b read}
|
||||
test append-7.5 {append var does not trigger read trace} -setup {
|
||||
unset -nocomplain myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
append myvar a
|
||||
info exists ::result
|
||||
|
||||
+14
-14
@@ -250,7 +250,7 @@ test appendComp-7.1 {lappendComp-created var and error in trace on that var} -se
|
||||
} -body {
|
||||
proc bar {} {
|
||||
global x
|
||||
trace variable x w foo
|
||||
trace add variable x write foo
|
||||
proc foo {} {global x; unset x}
|
||||
catch {lappend x 1}
|
||||
proc foo {args} {global x; unset x}
|
||||
@@ -265,7 +265,7 @@ test appendComp-7.2 {lappend var triggers read trace, index var} -setup {
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
proc bar {} {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar a
|
||||
return $::result
|
||||
@@ -277,7 +277,7 @@ test appendComp-7.3 {lappend var triggers read trace, stack var} -setup {
|
||||
unset -nocomplain ::myvar
|
||||
} -body {
|
||||
proc bar {} {
|
||||
trace variable ::myvar r foo
|
||||
trace add variable ::myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend ::myvar a
|
||||
return $::result
|
||||
@@ -290,67 +290,67 @@ test appendComp-7.4 {lappend var triggers read trace, array var} -setup {
|
||||
# The behavior of read triggers on lappend changed in 8.0 to not trigger
|
||||
# them. Maybe not correct, but been there a while.
|
||||
proc bar {} {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar(b) a
|
||||
return $::result
|
||||
}
|
||||
bar
|
||||
} -result {myvar b r} -constraints {bug-3057639}
|
||||
} -result {myvar b read} -constraints {bug-3057639}
|
||||
test appendComp-7.5 {lappend var triggers read trace, array var} -setup {
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
# The behavior of read triggers on lappend changed in 8.0 to not trigger
|
||||
# them. Maybe not correct, but been there a while.
|
||||
proc bar {} {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar(b) a b
|
||||
return $::result
|
||||
}
|
||||
bar
|
||||
} -result {myvar b r}
|
||||
} -result {myvar b read}
|
||||
test appendComp-7.6 {lappend var triggers read trace, array var exists} -setup {
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
proc bar {} {
|
||||
set myvar(0) 1
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend myvar(b) a
|
||||
return $::result
|
||||
}
|
||||
bar
|
||||
} -result {myvar b r} -constraints {bug-3057639}
|
||||
} -result {myvar b read} -constraints {bug-3057639}
|
||||
test appendComp-7.7 {lappend var triggers read trace, array stack var} -setup {
|
||||
unset -nocomplain ::myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
proc bar {} {
|
||||
trace variable ::myvar r foo
|
||||
trace add variable ::myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend ::myvar(b) a
|
||||
return $::result
|
||||
}
|
||||
bar
|
||||
} -result {::myvar b r} -constraints {bug-3057639}
|
||||
} -result {::myvar b read} -constraints {bug-3057639}
|
||||
test appendComp-7.8 {lappend var triggers read trace, array stack var} -setup {
|
||||
unset -nocomplain ::myvar
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
proc bar {} {
|
||||
trace variable ::myvar r foo
|
||||
trace add variable ::myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
lappend ::myvar(b) a b
|
||||
return $::result
|
||||
}
|
||||
bar
|
||||
} -result {::myvar b r}
|
||||
} -result {::myvar b read}
|
||||
test appendComp-7.9 {append var does not trigger read trace} -setup {
|
||||
unset -nocomplain ::result
|
||||
} -body {
|
||||
proc bar {} {
|
||||
trace variable myvar r foo
|
||||
trace add variable myvar read foo
|
||||
proc foo {args} {append ::result $args}
|
||||
append myvar a
|
||||
info exists ::result
|
||||
|
||||
+1
-1
@@ -644,7 +644,7 @@ test binary-18.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body {
|
||||
|
||||
test binary-19.1 {Tcl_BinaryObjCmd: errors} -returnCodes error -body {
|
||||
binary s
|
||||
} -result {wrong # args: should be "binary scan value formatString ?varName ...?"}
|
||||
} -result {unknown or ambiguous subcommand "s": must be decode, encode, format, scan, or set}
|
||||
test binary-19.2 {Tcl_BinaryObjCmd: errors} -returnCodes error -body {
|
||||
binary scan foo
|
||||
} -result {wrong # args: should be "binary scan value formatString ?varName ...?"}
|
||||
|
||||
+1
-1
@@ -763,7 +763,7 @@ test expr-20.2 {double invocation of variable traces} -body {
|
||||
set var "$counter + [concat $extraargs]"
|
||||
}
|
||||
}
|
||||
trace variable exprtracevar r [list exprtraceproc 10]
|
||||
trace add variable exprtracevar read [list exprtraceproc 10]
|
||||
list [catch {expr "$exprtracevar + 20"} a] $a \
|
||||
[catch {expr "$exprtracevar + 20"} b] $b \
|
||||
[unset exprtracevar exprtracecounter]
|
||||
|
||||
+1
-1
@@ -1265,7 +1265,7 @@ test if-10.6 {double invocation of variable traces} -body {
|
||||
set var "$counter + [concat $extraargs]"
|
||||
}
|
||||
}
|
||||
trace variable iftracevar r [list iftraceproc 10]
|
||||
trace add variable iftracevar read [list iftraceproc 10]
|
||||
list [catch {if "$iftracevar + 20" {}} a] $a \
|
||||
[catch {if "$iftracevar + 20" {}} b] $b
|
||||
} -cleanup {
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ test incr-old-2.5 {incr errors} {
|
||||
test incr-old-2.6 {incr errors} -body {
|
||||
proc readonly args {error "variable is read-only"}
|
||||
set x 123
|
||||
trace var x w readonly
|
||||
trace add variable x write readonly
|
||||
list [catch {incr x 1} msg] $msg $::errorInfo
|
||||
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
|
||||
while executing
|
||||
|
||||
+1
-1
@@ -157,7 +157,7 @@ foreach arg [subst -nocommands -novariables {
|
||||
auto_reset
|
||||
} -body {
|
||||
namespace eval junk [list array set $arg [list 1 2 3 4]]
|
||||
trace variable ::junk::$arg r \
|
||||
trace add variable ::junk::$arg read \
|
||||
"[list error [subst {Variable \"$arg\" is write-only}]] ;# "
|
||||
catch {parray ::junk::$arg}
|
||||
set first $::errorInfo
|
||||
|
||||
+4
-4
@@ -373,9 +373,9 @@ test link-8.1 {Tcl_UpdateLinkedVar procedure} {testlink} {
|
||||
set x {}
|
||||
testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||
testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
|
||||
trace var int w x
|
||||
trace add variable int write x
|
||||
testlink update 32 4.0 3 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
|
||||
trace vdelete int w x
|
||||
trace remove variable int write x
|
||||
return $x
|
||||
} {{int {} w} 32 -2.0 0 xyzzy 995511}
|
||||
test link-8.2 {Tcl_UpdateLinkedVar procedure} {testlink} {
|
||||
@@ -387,9 +387,9 @@ test link-8.2 {Tcl_UpdateLinkedVar procedure} {testlink} {
|
||||
testlink create 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||
testlink set 14 -2.0 0 xyzzy 995511 64 250 30000 60000 0xbeefbabe 12321 32123 3.25 1231231234
|
||||
testlink delete
|
||||
trace var int w x
|
||||
trace add variable int write x
|
||||
testlink update 32 4.0 6 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
|
||||
trace vdelete int w x
|
||||
trace remove variable int write x
|
||||
return $x
|
||||
} {}
|
||||
test link-8.3 {Tcl_UpdateLinkedVar procedure, read-only variable} {testlink} {
|
||||
|
||||
@@ -635,13 +635,13 @@ test namespace-old-8.1 {traces work across namespace boundaries} {
|
||||
variable status
|
||||
lappend status "$op: $name1"
|
||||
}
|
||||
trace variable foo::x rwu [namespace code monitor]
|
||||
trace add variable foo::x {read write unset} [namespace code monitor]
|
||||
}
|
||||
set test_ns_trace::foo::x "yes!"
|
||||
set test_ns_trace::foo::x
|
||||
unset test_ns_trace::foo::x
|
||||
namespace eval test_ns_trace { set status }
|
||||
} {{w: test_ns_trace::foo::x} {r: test_ns_trace::foo::x} {u: test_ns_trace::foo::x}}
|
||||
} {{write: test_ns_trace::foo::x} {read: test_ns_trace::foo::x} {unset: test_ns_trace::foo::x}}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# TEST: imported commands
|
||||
|
||||
+8
-8
@@ -137,25 +137,25 @@ test proc-old-3.7 {local and global arrays} {
|
||||
proc t1 {args} {global info; set info 1}
|
||||
catch {unset a}
|
||||
set info {}
|
||||
do {global a; trace var a(1) w t1}
|
||||
do {global a; trace add variable a(1) write t1}
|
||||
set a(1) 44
|
||||
set info
|
||||
} 1
|
||||
test proc-old-3.8 {local and global arrays} {
|
||||
proc t1 {args} {global info; set info 1}
|
||||
catch {unset a}
|
||||
trace var a(1) w t1
|
||||
trace add variable a(1) write t1
|
||||
set info {}
|
||||
do {global a; trace vdelete a(1) w t1}
|
||||
do {global a; trace remove variable a(1) write t1}
|
||||
set a(1) 44
|
||||
set info
|
||||
} {}
|
||||
test proc-old-3.9 {local and global arrays} {
|
||||
proc t1 {args} {global info; set info 1}
|
||||
catch {unset a}
|
||||
trace var a(1) w t1
|
||||
do {global a; trace vinfo a(1)}
|
||||
} {{w t1}}
|
||||
trace add variable a(1) write t1
|
||||
do {global a; trace info variable a(1)}
|
||||
} {{write t1}}
|
||||
catch {unset a}
|
||||
|
||||
test proc-old-30.1 {arguments and defaults} {
|
||||
@@ -349,7 +349,7 @@ test proc-old-5.16 {error conditions} {
|
||||
}
|
||||
proc tproc {} {
|
||||
set x 44
|
||||
trace var x u foo
|
||||
trace add variable x unset foo
|
||||
while {$x < 100} {
|
||||
error "Nested error"
|
||||
}
|
||||
@@ -361,7 +361,7 @@ test proc-old-5.16 {error conditions} {
|
||||
"error "Nested error""
|
||||
(procedure "tproc" line 5)
|
||||
invoked from within
|
||||
"tproc"} {foo was called: x {} u}}
|
||||
"tproc"} {foo was called: x {} unset}}
|
||||
|
||||
# The tests below will really only be useful when run under Purify or
|
||||
# some other system that can detect accesses to freed memory...
|
||||
|
||||
+8
-8
@@ -169,7 +169,7 @@ test set-old-5.4 {errors in reading variables} {
|
||||
|
||||
test set-old-6.1 {creating array during write} {
|
||||
catch {unset a}
|
||||
trace var a rwu ignore
|
||||
trace add variable a {read write unset} ignore
|
||||
list [catch {set a(14) 186} msg] $msg [array names a]
|
||||
} {0 186 14}
|
||||
test set-old-6.2 {errors in writing variables} {
|
||||
@@ -407,7 +407,7 @@ test set-old-8.18 {array command, get option} {
|
||||
test set-old-8.19 {array command, get option (unset variable)} {
|
||||
catch {unset a}
|
||||
set a(x) 3
|
||||
trace var a(y) w ignore
|
||||
trace add variable a(y) write ignore
|
||||
array get a
|
||||
} {x 3}
|
||||
test set-old-8.20 {array command, get option, with pattern} {
|
||||
@@ -445,13 +445,13 @@ test set-old-8.24 {array command, names option} {
|
||||
test set-old-8.25 {array command, names option} {
|
||||
catch {unset a}
|
||||
set a(22) 3; set a(33) 44;
|
||||
trace var a(xxx) w ignore
|
||||
trace add variable a(xxx) write ignore
|
||||
list [catch {lsort [array names a]} msg] $msg
|
||||
} {0 {22 33}}
|
||||
test set-old-8.26 {array command, names option} {
|
||||
catch {unset a}
|
||||
set a(22) 3; set a(33) 44;
|
||||
trace var a(xxx) w ignore
|
||||
trace add variable a(xxx) write ignore
|
||||
set a(xxx) value
|
||||
list [catch {lsort [array names a]} msg] $msg
|
||||
} {0 {22 33 xxx}}
|
||||
@@ -579,7 +579,7 @@ test set-old-8.43 {array command, size option} {
|
||||
test set-old-8.44 {array command, size option} {
|
||||
catch {unset a}
|
||||
set a(22) 3;
|
||||
trace var a(33) rwu ignore
|
||||
trace add variable a(33) {read write unset} ignore
|
||||
list [catch {array size a} msg] $msg
|
||||
} {0 1}
|
||||
test set-old-8.45 {array command, size option, array doesn't exist yet but has compiler-allocated procedure slot} {
|
||||
@@ -786,7 +786,7 @@ test set-old-9.10 {array enumeration: searches automatically stopped} {
|
||||
set a(a) 1
|
||||
set x [array startsearch a]
|
||||
set y [array startsearch a]
|
||||
trace var a(b) r {}
|
||||
trace add variable a(b) read {}
|
||||
list [catch {array next a $x} msg] $msg \
|
||||
[catch {array next a $y} msg2] $msg2
|
||||
} {1 {couldn't find search "s-1-a"} 1 {couldn't find search "s-2-a"}}
|
||||
@@ -795,14 +795,14 @@ test set-old-9.11 {array enumeration: searches automatically stopped} {
|
||||
set a(a) 1
|
||||
set x [array startsearch a]
|
||||
set y [array startsearch a]
|
||||
trace var a(a) r {}
|
||||
trace add variable a(a) read {}
|
||||
list [catch {array next a $x} msg] $msg \
|
||||
[catch {array next a $y} msg2] $msg2
|
||||
} {0 a 0 a}
|
||||
test set-old-9.12 {array enumeration with traced undefined elements} {
|
||||
catch {unset a}
|
||||
set a(a) 1
|
||||
trace var a(b) r {}
|
||||
trace add variable a(b) read {}
|
||||
set x [array startsearch a]
|
||||
lsort [list [array next a $x] [array next a $x]]
|
||||
} {{} a}
|
||||
|
||||
+2
-2
@@ -263,7 +263,7 @@ test set-2.4 {set command: runtime error, readonly variable} -setup {
|
||||
} -body {
|
||||
proc readonly args {error "variable is read-only"}
|
||||
set x 123
|
||||
trace var x w readonly
|
||||
trace add variable x write readonly
|
||||
list [catch {set x 1} msg] $msg $::errorInfo
|
||||
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
|
||||
while executing
|
||||
@@ -521,7 +521,7 @@ test set-4.4 {uncompiled set command: runtime error, readonly variable} -body {
|
||||
set z set
|
||||
proc readonly args {error "variable is read-only"}
|
||||
$z x 123
|
||||
trace var x w readonly
|
||||
trace add variable x write readonly
|
||||
list [catch {$z x 1} msg] $msg $::errorInfo
|
||||
} -match glob -result {1 {can't set "x": variable is read-only} {*variable is read-only
|
||||
while executing
|
||||
|
||||
+7
-7
@@ -187,26 +187,26 @@ test upvar-4.2 {nested upvars} {
|
||||
|
||||
proc tproc {args} {global x; set x [list $args [uplevel info vars]]}
|
||||
test upvar-5.1 {traces involving upvars} {
|
||||
proc p1 {a b} {set c 22; set d 33; trace var c rw tproc; p2}
|
||||
proc p1 {a b} {set c 22; set d 33; trace add variable c {read write} tproc; p2}
|
||||
proc p2 {} {upvar c x1; set x1 22}
|
||||
set x ---
|
||||
p1 foo bar
|
||||
set x
|
||||
} {{x1 {} w} x1}
|
||||
} {{x1 {} write} x1}
|
||||
test upvar-5.2 {traces involving upvars} {
|
||||
proc p1 {a b} {set c 22; set d 33; trace var c rw tproc; p2}
|
||||
proc p1 {a b} {set c 22; set d 33; trace add variable c {read write} tproc; p2}
|
||||
proc p2 {} {upvar c x1; set x1}
|
||||
set x ---
|
||||
p1 foo bar
|
||||
set x
|
||||
} {{x1 {} r} x1}
|
||||
} {{x1 {} read} x1}
|
||||
test upvar-5.3 {traces involving upvars} {
|
||||
proc p1 {a b} {set c 22; set d 33; trace var c rwu tproc; p2}
|
||||
proc p1 {a b} {set c 22; set d 33; trace add variable c {read write unset} tproc; p2}
|
||||
proc p2 {} {upvar c x1; unset x1}
|
||||
set x ---
|
||||
p1 foo bar
|
||||
set x
|
||||
} {{x1 {} u} x1}
|
||||
} {{x1 {} unset} x1}
|
||||
|
||||
test upvar-6.1 {retargeting an upvar} {
|
||||
proc p1 {} {
|
||||
@@ -317,7 +317,7 @@ test upvar-8.6 {errors in upvar command} -returnCodes error -body {
|
||||
p1
|
||||
} -result {variable "a" already exists}
|
||||
test upvar-8.7 {errors in upvar command} -returnCodes error -body {
|
||||
proc p1 {} {trace variable a w foo; upvar b a}
|
||||
proc p1 {} {trace add variable a write foo; upvar b a}
|
||||
p1
|
||||
} -result {variable "a" has traces: can't use for upvar}
|
||||
test upvar-8.8 {create nested array with upvar} -body {
|
||||
|
||||
+12
-12
@@ -576,10 +576,10 @@ test var-8.1 {TclDeleteVars, "unset" traces are called with fully-qualified var
|
||||
variable info
|
||||
set info [concat $info [list $name1 $name2 $op]]
|
||||
}
|
||||
trace var v u [namespace code traceUnset]
|
||||
trace add variable v unset [namespace code traceUnset]
|
||||
}
|
||||
list [unset test_ns_var::v] $test_ns_var::info
|
||||
} -result {{} {test_ns_var::v {} u}}
|
||||
} -result {{} {test_ns_var::v {} unset}}
|
||||
test var-8.2 {TclDeleteNamespaceVars, "unset" traces on ns delete are called with fully-qualified var names} -setup {
|
||||
catch {namespace delete test_ns_var}
|
||||
catch {unset a}
|
||||
@@ -587,13 +587,13 @@ test var-8.2 {TclDeleteNamespaceVars, "unset" traces on ns delete are called wit
|
||||
set info ""
|
||||
namespace eval test_ns_var {
|
||||
variable v 123 1
|
||||
trace var v u ::traceUnset
|
||||
trace add variable v unset ::traceUnset
|
||||
}
|
||||
proc traceUnset {name1 name2 op} {
|
||||
set ::info [concat $::info [list $name1 $name2 $op]]
|
||||
}
|
||||
list [namespace delete test_ns_var] $::info
|
||||
} -result {{} {::test_ns_var::v {} u}}
|
||||
} -result {{} {::test_ns_var::v {} unset}}
|
||||
|
||||
test var-8.3 {TclDeleteNamespaceVars, mem leak} -constraints memory -setup {
|
||||
proc ::t {a i o} {
|
||||
@@ -603,7 +603,7 @@ test var-8.3 {TclDeleteNamespaceVars, mem leak} -constraints memory -setup {
|
||||
leaktest {
|
||||
namespace eval n {
|
||||
variable v 123
|
||||
trace variable v u ::t
|
||||
trace add variable v unset ::t
|
||||
}
|
||||
namespace delete n
|
||||
}
|
||||
@@ -682,8 +682,8 @@ test var-9.9 {behaviour of TclGetVar read trace success} -setup {
|
||||
} -constraints testsetnoerr -body {
|
||||
proc resetvar {val name elem op} {upvar 1 $name v; set v $val}
|
||||
set u 10
|
||||
trace var u r [list resetvar 1]
|
||||
trace var v r [list resetvar 2]
|
||||
trace add variable u read [list resetvar 1]
|
||||
trace add variable v read [list resetvar 2]
|
||||
list \
|
||||
[testsetnoerr u] \
|
||||
[testseterr v]
|
||||
@@ -691,7 +691,7 @@ test var-9.9 {behaviour of TclGetVar read trace success} -setup {
|
||||
test var-9.10 {behaviour of TclGetVar read trace error} testsetnoerr {
|
||||
proc writeonly args {error "write-only"}
|
||||
set v 456
|
||||
trace var v r writeonly
|
||||
trace add variable v read writeonly
|
||||
list \
|
||||
[catch {testsetnoerr v} msg] $msg \
|
||||
[catch {testseterr v} msg] $msg
|
||||
@@ -702,8 +702,8 @@ test var-9.11 {behaviour of TclSetVar write trace success} -setup {
|
||||
} -constraints testsetnoerr -body {
|
||||
proc doubleval {name elem op} {upvar 1 $name v; set v [expr {2 * $v}]}
|
||||
set v 1
|
||||
trace var v w doubleval
|
||||
trace var u w doubleval
|
||||
trace add variable v write doubleval
|
||||
trace add variable u write doubleval
|
||||
list \
|
||||
[testsetnoerr u 2] \
|
||||
[testseterr v 3]
|
||||
@@ -711,7 +711,7 @@ test var-9.11 {behaviour of TclSetVar write trace success} -setup {
|
||||
test var-9.12 {behaviour of TclSetVar write trace error} testsetnoerr {
|
||||
proc readonly args {error "read-only"}
|
||||
set v 456
|
||||
trace var v w readonly
|
||||
trace add variable v write readonly
|
||||
list \
|
||||
[catch {testsetnoerr v 2} msg] $msg $v \
|
||||
[catch {testseterr v 3} msg] $msg $v
|
||||
@@ -773,7 +773,7 @@ test var-13.1 {Tcl_UnsetVar2, unset array with trace set on element} -setup {
|
||||
}
|
||||
namespace eval :: {
|
||||
set t(1) 1
|
||||
trace variable t(1) u foo
|
||||
trace add variable t(1) unset foo
|
||||
unset t
|
||||
}
|
||||
set x "If you see this, it worked"
|
||||
|
||||
Reference in New Issue
Block a user