Tcl Source Code

View Ticket
Login
Ticket UUID: 449094
Title: Read trace on arrays (ex "Tcl_TraceVar")
Type: Bug Version: None
Submitter: davidw Created on: 2001-08-08 12:46:16
Subsystem: 07. Variables Assigned To: msofer
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2001-08-11 01:16:30
Resolution: Fixed Closed By: dgp
    Closed on: 2001-08-10 18:16:30
Description:
[ I hate this f**** web interface - go read the
original thread at:


http://groups.google.com/groups?hl=en&safe=off&th=f37901b5fe0e58d3,3&seekm=87zo9u79oa.fsf%40apache.org#p

]





char *traceproc(ClientData clientData,
                Tcl_Interp *interp,
                char *name1,
                char *name2,
                int flags)
{
    Tcl_SetVar2(interp, "rotvar", "foo", "1", 0);
    return NULL;
}

int Rotvar_tcl_Init(Tcl_Interp *interp)
{
    Tcl_TraceVar(interp, "rotvar",
TCL_TRACE_READS|TCL_TRACE_ARRAY, traceproc, NULL);
    return TCL_OK;
}

then...

@ashland [~/workshop] $ gcc -c sicktcl.c ; ld -fPIC
-shared -o libRotVar_tcl.so sicktcl.o -ltcl8.3
@ashland [~/workshop] $ tclsh                         
                         tclsh8.3 [~/workshop]load
./libRotVar_tcl.so
tclsh8.3 [~/workshop]puts [array get rotvar ]

tclsh8.3 [~/workshop]puts [array get rotvar ]
foo 1
tclsh8.3 [~/workshop]

Excusing me for the odd names, why isn't this filling
in the value
*before* the first [array get] ?

The man page says:

       When array tracing has been specified, the trace
procedure
       will be invoked at the  beginning  of  the 
array  command
       implementation,  before  any  of  the operations
like get,
       set, or names have been invoked.  The trace
procedure  can
       modify the array elements with Tcl_SetVar and
Tcl_SetVar2.

Ideas?
-- 
David N. Welton
Free Software: http://people.debian.org/~davidw/
Apache Tcl: http://tcl.apache.org/
Personal: http://www.efn.org/~davidw/

Post a follow-up to this message
Message 2 in thread
From: David N. Welton ([email protected])
Subject: Re: Tcl_TraceVar wierdness
Newsgroups: comp.lang.tcl
Date: 2001-07-24 06:13:05 PST

[email protected] (David N. Welton) writes:

> @ashland [~/workshop] $ gcc -c sicktcl.c ; ld -fPIC
-shared -o libRotVar_tcl.so sicktcl.o -ltcl8.3
> @ashland [~/workshop] $ tclsh                       
                           tclsh8.3 [~/workshop]load
./libRotVar_tcl.so
> tclsh8.3 [~/workshop]puts [array get rotvar ]
> > tclsh8.3 [~/workshop]puts [array get rotvar ]
> foo 1
> tclsh8.3 [~/workshop]
> > Excusing me for the odd names, why isn't this
filling in the value
> *before* the first [array get] ?

Interestingly enough:

tclsh8.3 [~/workshop]load ./libRotVar_tcl.so
tclsh8.3 [~/workshop]array set rotvar {a b}
tclsh8.3 [~/workshop]array get rotvar
foo 1 a b

So, it looks as if it's important that it be defined as
an array...

Hrm...

-- 
David N. Welton
Free Software: http://people.debian.org/~davidw/
Apache Tcl: http://tcl.apache.org/
Personal: http://www.efn.org/~davidw/

Post a follow-up to this message
Message 3 in thread
From: David N. Welton ([email protected])
Subject: Re: Tcl_TraceVar wierdness
Newsgroups: comp.lang.tcl
Date: 2001-07-24 08:15:32 PST

This seems like a logical fix to me.  Basically, we
move the check to
see if it's an array untill after the trace.

In my case, the variable is indeed undefined, but after
the trace it
is an array.

===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclVar.c,v
retrieving revision 1.32
diff -u -r1.32 tclVar.c
--- generic/tclVar.c    2001/05/17 02:13:03     1.32
+++ generic/tclVar.c    2001/07/24 15:12:15
@@ -3002,12 +3002,6 @@
     varPtr = TclLookupVar(interp, varName, (char *)
NULL, /*flags*/ 0,
             /*msg*/ 0, /*createPart1*/ 0,
/*createPart2*/ 0, &arrayPtr);
 
-    notArray = 0;
-    if ((varPtr == NULL) || !TclIsVarArray(varPtr)
-           || TclIsVarUndefined(varPtr)) {
-       notArray = 1;
-    }
-
     /*
      * Special array trace used to keep the env array
in sync for
      * array names, array get, etc.
@@ -3024,6 +3018,12 @@
        }
     }
 
+    notArray = 0;
+    if ((varPtr == NULL) || !TclIsVarArray(varPtr)
+           || TclIsVarUndefined(varPtr)) {
+       notArray = 1;
+    }
+
     /*
      * We have to wait to get the resultPtr until here
because
      * CallTraces can affect the result.


And infact:

% load /home/davidw/workshop/libRotVar_tcl.so
% array get rotvar
foo 1

Works on the first try...

-- 
David N. Welton
Free Software: http://people.debian.org/~davidw/
Apache Tcl: http://tcl.apache.org/
Personal: http://www.efn.org/~davidw/
User Comments: msofer added on 2001-08-10 20:12:36:

File Added - 9434: arrayTrace.txt

Logged In: YES 
user_id=148712

Patch committed.

msofer added on 2001-08-10 20:11:11:

File Deleted - 9426:

msofer added on 2001-08-10 07:43:45:

File Added - 9426: arrayTrace.txt

Logged In: YES 
user_id=148712

The patch originally proposed (and now enclosed) does fix
this bug.

But: shouldn't the call to Tcl_TraceVar with TCL_TRACE_ARRAY 
check that the variable _can_ be an array (ie, it was not
previously defined as a scalar or link, and it is a valid
name for an array)? According to the result, it could either
return an error or else set the variable to an array.

msofer added on 2001-08-10 07:35:19:
Logged In: YES 
user_id=148712

Doh ... At least I understand now why these scripts fail to
do what I thought they would do: Tcl_TraceObjCmd (in
tclCmdMZ.c) does not set the flag TCL_TRACE_ARRAY, the read
trace fires when an element of the array is read and not on
[array]. 

Using the (new in 8.4, still not documented/oficial) [trace]
command, the bug is exposed to scripts: array trace still
does not fire on first access if the variable is undefined:

% trace add variable rotvar array {set rotvar(foo) 1 ;#}
% array names rotvar
% array names rotvar
foo

msofer added on 2001-08-10 05:03:30:
Logged In: YES 
user_id=148712

The following looks wrong too: [array names] does not
trigger read traces; reading Tcl_TraceVar's manpage, I'd
expect a different behaviour:

% set rotvar(bar) 0
0
% trace variable rotvar r {set rotvar(foo) 1 ;#}
% array names rotvar
bar
%  array names rotvar
bar

msofer added on 2001-08-10 00:28:02:
Logged In: YES 
user_id=148712

I think this is a bug report, not a feature request. The bug
is also accessible at the script level:

% set rotvar(bar) 0
0
%  trace variable rotvar r {set rotvar(foo) 1 ;#}
% array get rotvar
bar 0
% array get rotvar
foo 1 bar 0

Attachments: