I'm debugging some Tcl code which is using child interpreters, and not being familiar with the code, it would be handy to sprinkle some "puts" showing the path to the current interpreter to get a handle on what the code is doing. Is there a way in Tcl 8.4 to determine which interpreter one is running in?
No, there is no way to just pick the information up (it would violate the isolation principle). But you can pass that information into the sub-interpreters after you create them easily enough:
set i [interp create]
$i eval [list set ::myInterpName $i]
Related
I have this example tcl code that works by itself:
layout peek -celltext "CellA" "CellB"
I would like to have the a list storing CellA and CellB such that I want to execute something like
set list [list "CellA" "CellB"]
set OUTPUT [layout peek -celltext [exec echo $list]]
Unfortuantely, spending 2 hours and various combination isn't getting me anywhere. Any ideas on what I need to do? Forgive me as i'm not strong in Tcl programming.
I need to assign my final variable with the following string UDP6:[2001:172:16:21::36]
set ipAddr1 "UDP6,2001:172:16:21::36"
set ipAddrArr [split $ipAddr1 ","]
set ipAddrArr11 [lindex $ipAddrArr 0]
set ipAddrArr12 [lindex $ipAddrArr 1]
set tmp ":\["
set ipAddr1Part [join "$ipAddrArr11 $ipAddrArr12" $tmp]
set tmp1 "]"
set ipAddrFinal [join "$ipAddr1Part$tmp1"]
When I run the tcl script, it gives invalid command name as 2001:172:16:21::36.
I have printed ipAddrFinal value , it gives the expected one UDP6:[2001:172:16:21::36]
pls help me out? what am I missing
The script as you have written it works fine; it assigns the string UDP6:[2001:172:16:21::36] to the variable ipAddrFinal. However, since it contains characters that are Tcl metacharacters in some contexts, I suspect that you are then using the string in an unsafe way, most likely with eval or possibly with subst or uplevel. If you look at the stack trace of the error (in the errorInfo global variable by default) you should be told pretty exactly where the offending code is; it might give a few places you need to look, but it usually isn't too hard to hunt down where the problem originates from.
If your problem comes from uplevel, you are probably going to need to use list to construct a command; 99.99% of all problems with uplevel are handled that way. If your problems come from eval, the chance's good that you need to switch to using expansion syntax. If your problems come from subst or are otherwise still deeply confusing, check back with us (with your stack trace if you are not sure where the problem is coming from).
Example of a fix for eval:
Change:
set action "puts \"IP\\ address\\ is\\ $ipAddrFinal\""
eval $action
to:
set action [list puts "IP address is $ipAddrFinal"]
{*}$action
NB: The error from doing the eval is a reasonable example too:
invalid command name "2001:172:16:21::36"
while executing
"2001:172:16:21::36"
("eval" body line 1)
invoked from within
"eval $action"
Note that it says that it's in an eval, and that points squarely to unsafe script construction. The list command does safe script construction as one of its bonus superpowers.
So I have been trying to find an answer for this for a bit and could not find the answer on the internet. I need to check to see if an environment variable exists. I thought I had the right code but it keeps returning false.
if { [info exists ::env(USER)] } {
RAT::LogMsg INFO "Found USER"
} else {
RAT::LogMsg INFO "Nope!"
}
Any ideas?
You might want to check what environment variables are actually set; I don't think that USER is one of the guaranteed ones.
RAT::LogMsg INFO "Got these env-vars: [lsort [array names ::env]]"
If puts stdout works in your environment, you can try doing:
parray ::env
(The parray command is a procedure that pretty-prints an array.)
To get the current username reliably, check out the tcl_platform array's user element. That array is generated internally by Tcl (well, with probes to relevant basic OS APIs) instead of by looking at environment variables, and that particular element is always present back at least as far as Tcl 8.4.
RAT::LogMsg INFO "Username is $::tcl_platform(user)"
I've just noticed that the documentation is wrong: it says that the user element comes from USER and/or LOGNAME environment variables. It doesn't, and doesn't in at least 8.5 and 8.6. (And it's definitely my mistake. I forgot to update the code when I fixed this. Ooops!)
You have the right code, test in tclsh:
% if {[info exists ::env(USER)]} {puts "found $::env(USER)"}
found strobel
%
The problem must be in your environment.
I want to find a way to return the name of a library of a certain path in a VHDL Design in Modelsim.
Given a VHDL Design with a path like "/mega_tb/D0". This is compiled in a library that is NOT 'work', say "libnwork".
I can of course take a look in my 'do' file to get the correct lib name. Or I can search in ModelSim's Library tab. But I want to have or create a modelsim command which I can later use in a Tcl script, to get the correct library name.
One of the easiest ways to find something in a Tcl script file – which is all a Modelsim “do” file is — is to evaluate it. Tcl's very good at that. Of course, you don't want to have the commands do all the conventional things. Instead, we'll evaluate in a context where we can make everything do nothing except for the command that produces the information we want:
# Set up our evaluation context, 'worker'
interp create worker -safe
interp eval worker {proc unknown args {}}; # Our do-nothing handler
interp alias worker theInterestingCommand {} ourHandler
proc ourHandler args {
puts "We were called with: $args"
}
# Parse the file!
set f [open /the/file.tcl]
interp eval worker [read $f]
# Clean up
close $f
interp delete worker
Now you just have to make theInterestingCommand have the right name and extract the interesting information from the arguments. Which should be relatively easy…
Te only way I've found is to use the command
write report -tcl
This prints a long list where I have search for the lib names with regexps.
Something like
set data [ write report -tcl]
foreach_regexp { _ type lib entity} $data{
if {$type == "Entity" && $entity == [entity_of_path /mega_tb/D0] } {
....
}
}
Where I of course had to define my "foreach_regexp" procedure and my "entity_of_path" procedure. I then can use something like regsub to extract the library name.
I am still looking for a better and easier way.
So basically in my tcl script I generate a line of tcl code that I have to execute( ie I come up with this instruction during runtime). Once I have the tcl instruction say for example puts "hello world $test_var". How do I execute this using tcl?
Do I use the eval command or what?
The eval command is a reasonable way of doing this, but you might want to consider using catch instead, since that will trap any problems found during the evaluation of the generated code, for example like this:
# Generate the code somehow
set variable {puts "hello word $test_var"}
# Execute and trap problems
if {[catch $variable resultMsg]} {
# An error (or other exception) happened
puts stderr "BOOM, Error! $resultMsg"
}
Instead of using [eval] which works perfectly well, in newer versions of Tcl you can use the {*} syntax.
For example:
set cmd "puts"
lappend cmd "abcd ef"
{*}$cmd
Note that it's a good habit to use list commands to build up your command so you wont run into quoting issues.
I'm afraid you don't have another reasonable choice than to use the eval command, e.g.:
set variable {puts "hello world $test_var"}
eval $variable