Attachment "1065378.patch" to
ticket [1065378fff]
added by
dgp
2004-11-16 04:10:12.
Index: generic/tclCmdMZ.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdMZ.c,v
retrieving revision 1.82.2.12
diff -u -r1.82.2.12 tclCmdMZ.c
--- generic/tclCmdMZ.c 30 Aug 2004 18:15:24 -0000 1.82.2.12
+++ generic/tclCmdMZ.c 15 Nov 2004 21:07:40 -0000
@@ -2976,9 +2976,8 @@
int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- int optionIndex, commandLength;
- char *name, *flagOps, *command, *p;
- size_t length;
+ int optionIndex;
+ char *name, *flagOps, *p;
/* Main sub commands to 'trace' */
static CONST char *traceOptions[] = {
"add", "info", "remove",
@@ -3025,105 +3024,52 @@
return (traceSubCmds[typeIndex])(interp, optionIndex, objc, objv);
}
#ifndef TCL_REMOVE_OBSOLETE_TRACES
- case TRACE_OLD_VARIABLE: {
- int flags;
- TraceVarInfo *tvarPtr;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "name ops command");
- return TCL_ERROR;
- }
-
- flags = 0;
- flagOps = Tcl_GetString(objv[3]);
- for (p = flagOps; *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 if (*p == 'a') {
- flags |= TCL_TRACE_ARRAY;
- } else {
- goto badVarOps;
- }
- }
- if (flags == 0) {
- goto badVarOps;
- }
- flags |= TCL_TRACE_OLD_STYLE;
-
- command = Tcl_GetStringFromObj(objv[4], &commandLength);
- length = (size_t) commandLength;
- tvarPtr = (TraceVarInfo *) ckalloc((unsigned)
- (sizeof(TraceVarInfo) - sizeof(tvarPtr->command)
- + length + 1));
- tvarPtr->flags = flags;
- tvarPtr->length = length;
- flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
- strcpy(tvarPtr->command, command);
- name = Tcl_GetString(objv[2]);
- if (Tcl_TraceVar(interp, name, flags, TraceVarProc,
- (ClientData) tvarPtr) != TCL_OK) {
- ckfree((char *) tvarPtr);
- return TCL_ERROR;
- }
- break;
- }
+ case TRACE_OLD_VARIABLE:
case TRACE_OLD_VDELETE: {
- int flags;
- TraceVarInfo *tvarPtr;
- ClientData clientData;
+ Tcl_Obj *copyObjv[6];
+ Tcl_Obj *opsList;
+ int code, numFlags;
if (objc != 5) {
Tcl_WrongNumArgs(interp, 2, objv, "name ops command");
return TCL_ERROR;
}
- flags = 0;
- flagOps = Tcl_GetString(objv[3]);
+ opsList = Tcl_NewObj();
+ Tcl_IncrRefCount(opsList);
+ flagOps = Tcl_GetStringFromObj(objv[3], &numFlags);
+ if (numFlags == 0) {
+ Tcl_DecrRefCount(opsList);
+ goto badVarOps;
+ }
for (p = flagOps; *p != 0; p++) {
if (*p == 'r') {
- flags |= TCL_TRACE_READS;
+ Tcl_ListObjAppendElement(NULL, opsList,
+ Tcl_NewStringObj("read", -1));
} else if (*p == 'w') {
- flags |= TCL_TRACE_WRITES;
+ Tcl_ListObjAppendElement(NULL, opsList,
+ Tcl_NewStringObj("write", -1));
} else if (*p == 'u') {
- flags |= TCL_TRACE_UNSETS;
+ Tcl_ListObjAppendElement(NULL, opsList,
+ Tcl_NewStringObj("unset", -1));
} else if (*p == 'a') {
- flags |= TCL_TRACE_ARRAY;
+ Tcl_ListObjAppendElement(NULL, opsList,
+ Tcl_NewStringObj("array", -1));
} else {
+ Tcl_DecrRefCount(opsList);
goto badVarOps;
}
}
- if (flags == 0) {
- goto badVarOps;
- }
- flags |= TCL_TRACE_OLD_STYLE;
-
- /*
- * 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.
- */
-
- command = Tcl_GetStringFromObj(objv[4], &commandLength);
- length = (size_t) commandLength;
- clientData = 0;
- name = Tcl_GetString(objv[2]);
- while ((clientData = Tcl_VarTraceInfo(interp, name, 0,
- TraceVarProc, clientData)) != 0) {
- tvarPtr = (TraceVarInfo *) clientData;
- if ((tvarPtr->length == length) && (tvarPtr->flags == flags)
- && (strncmp(command, tvarPtr->command,
- (size_t) length) == 0)) {
- Tcl_UntraceVar2(interp, name, NULL,
- flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT,
- TraceVarProc, clientData);
- Tcl_EventuallyFree((ClientData) tvarPtr, TCL_DYNAMIC);
- break;
- }
+ 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);
}
- break;
+ Tcl_DecrRefCount(opsList);
+ return code;
}
case TRACE_OLD_VINFO: {
ClientData clientData;
@@ -3721,6 +3667,9 @@
(sizeof(TraceVarInfo) - sizeof(tvarPtr->command)
+ length + 1));
tvarPtr->flags = flags;
+ if (objv[0] == NULL) {
+ tvarPtr->flags |= TCL_TRACE_OLD_STYLE;
+ }
tvarPtr->length = length;
flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT;
strcpy(tvarPtr->command, command);
@@ -3744,7 +3693,7 @@
TraceVarProc, clientData)) != 0) {
tvarPtr = (TraceVarInfo *) clientData;
if ((tvarPtr->length == length)
- && (tvarPtr->flags == flags)
+ && ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags)
&& (strncmp(command, tvarPtr->command,
(size_t) length) == 0)) {
Tcl_UntraceVar2(interp, name, NULL,
Index: tests/trace.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/trace.test,v
retrieving revision 1.26.2.3
diff -u -r1.26.2.3 trace.test
--- tests/trace.test 29 Sep 2003 22:03:44 -0000 1.26.2.3
+++ tests/trace.test 15 Nov 2004 21:07:41 -0000
@@ -2132,6 +2132,13 @@
set result
} [list [list delete foo]]
+test trace-33.1 {variable match with remove variable} {
+ unset -nocomplain x
+ trace variable x w foo
+ trace remove variable x write foo
+ llength [trace info variable x]
+} 0
+
# Delete procedures when done, so we don't clash with other tests
# (e.g. foobar will clash with 'unknown' tests).
catch {rename foobar {}}