Search code examples
variablestcltraceproc

using TCL trace on a local variable of a proc



Say I have this TCL code (this is a simplistic example):

proc foo {} {
   set k {0}
   foreach a { 1 2 3 4 } {
      lappend k [ expr { [lindex $k end ] + $a } ]
   }
}

I want to trace the k variable within proc foo, just as I would trace it, had it been a global or a namespace variable. How can I do that, in TCL 8.5?
Thanks.


Solution

  • Yes, even local variables can also be traced. It does not need to be a static/global or namespace variable.

    proc trackMyVar {name element op} {
        # In case of array variable tracing, the 'element' variable will specify the array index
        # For scalar variables, it will be empty
        if {$element != ""} {
            set name ${name}($element)
        }
        upvar $name x
        if {$op eq "r"} {
            puts "Variable $name is read now. It's value : $x"
        } elseif {$op eq "w"} {
            puts "Variable $name is written now. New value : $x"
        } elseif {$op eq "u"} {
            puts "Variable $name is unset"
        } else {
            # Only remaining possible value is "a" which is for array variables 
            # For array variables, tracing will work only if they have accessed/modified with array commands
        }
    }
    
    
    proc foo {} {
        # Adding tracing for variable 'k'
        trace variable k rwu trackMyVar
        set k {0}
        foreach a { 1 2 3 4 } {
            lappend k [ expr { [lindex $k end ] + $a } ]
        }
        unset k; # Just added this to demonstrate 'unset' operation
    }
    

    Output

    % foo
    Variable k is written now. New value : 0
    Variable k is read now. Its's value : 0
    Variable k is written now. New value : 0 1
    Variable k is read now. Its's value : 0 1
    Variable k is written now. New value : 0 1 3
    Variable k is read now. Its's value : 0 1 3
    Variable k is written now. New value : 0 1 3 6
    Variable k is read now. Its's value : 0 1 3 6
    Variable k is written now. New value : 0 1 3 6 10
    Variable k is unset
    %
    

    The command syntax of trace is as follows

    trace variable name ops command

    Here, 'ops' indicates which operations are of interest, and is a list of one or more of the following items

    • array
    • read
    • write
    • unset

    which should be specified as with their first letters as arwu. You can use whichever you are interested to track. I have used rwu. If you want to track only read operation then use r alone in it.

    Reference : trace