Sumit
Sumit

Reputation: 2023

Getting issues while printing parameters for the proc

I am trying to create a proc trace method. Means when script will use any proc it will print its procedure name and proceed. To do that I am following this method

rename proc _proc

_proc proc {nm params body}  { 
    eval "_proc $nm \{$params\} \{ 
    puts \"Enter proc $nm\";
    puts \"Parameters: $params and body \" ;
    $body;
    puts \"Exit proc $nm\"\}"
}

proc abc { param1 param2 param3 } {
    puts "$param1 and $param2 and $param3"
}

When I am calling proc abc, it is giving output as

Enter proc abc
Parameters:  param1 param2 param3  and body 
a and b and c
Exit proc abc

Question: Why this is printing body also as i definition I want only parameters to print

Upvotes: 0

Views: 52

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

There are many ways to write a replacement for the proc command that allow tracing and introspection features to be injected. However, the best way to go about it is probably to use the trace command to attach tracing hooks to a procedure, and let those hooks invoke info commands to list things like parameter lists, procedure bodies etc.

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137567

That seems over-complicated to me. Let's get rid of the eval and reduce the amount of quoting for starters. (Omitting the rest of your code for simplicity.)

_proc proc {nm params body}  { 
    _proc $nm $params \
        "[list puts "Enter proc $nm"];
        [list puts "Parameters: $params and body "];
        $body
        [list puts "Exit proc $nm"]"
}

But that's not exactly what you want, is it? You want to print the actual parameters and not the formals. That's rather more complex.

_proc proc {nm params body}  { 
    set cmd "[list puts "Enter proc $nm"];puts \"Parameters: "
    foreach p $params {
        append cmd "[lindex $p 0]=\$[lindex $p 0], "
    }
    append cmd " and body \";"
    _proc $nm $params $cmd$body\;[list puts "Exit proc $nm"]
}

But even that will go wrong horribly once you start trying to have a meaningful result returned from the procedure. While you could do something horrific with catch and return to make it work (and it's easier in 8.5, and much easier with 8.6's tryfinally), you want a different approach. You want execution traces.

_proc proc {nm params body} {
    _proc $nm $params $body
    trace add execution $nm enter [list track_entry $nm $params]
    trace add execution $nm leave [list track_leave $nm]
}
_proc track_entry {nm params real args} {
    puts "Enter proc $nm"
    foreach formal $params actual [lrange $real 1 end] {
        append p " [lindex $formal 0]=$actual,"
    }
    puts "Parameters:$p and body"
}
_proc track_leave {nm args} {
    puts "Exit proc $nm"
}

If we try that, we see we get very informative output and yet we don't “disturb” the procedure's working:

% abc p d q
Enter proc abc
Parameters: param1=p, param2=d, param3=q, and body
p and d and q
Exit proc abc
% info body abc

    puts "$param1 and $param2 and $param3"

Upvotes: 2

Related Questions