I want to know in which package all tcl commands will be available .
for example string , list etc .
When we want to use expect , we will use Expect package , similarly we are using these (string , list etc ...) commands without importing any package . i want to know in which package these are all belong ?
basically I came from java ... In java "java.lang" package default.
Formally, all commands that form the core of the Tcl language are provided by the Tcl package. That package is required for you before you run any code (and has to be; the package command itself is one of those commands). By historical convention, the large majority of Tcl commands are placed in the global namespace, which is on the command resolution path of all namespaces. (It's logically last on the path unless explicitly set with namespace path.) Some Tcl commands are defined in the ::tcl namespace, including a fair number of internal commands, direct access to which are not supported (if it isn't documented, it isn't supported; some are explicitly not supported but are relatively well known nonetheless; they're in the ::tcl::unsupported namespace). The namespace ::oo (and its children) are reserved for TclOO.
Commands defined by other packages — especially any newly-created packages — should be placed in a namespace with the same name as the package. This is merely a convention, and is not followed in older packages (particularly those that predate the namespace mechanism, such as Tk and TclX) because it is reckoned to be more important to maintain backward compatibility with existing scripts, but you will definitely find it easiest if you follow it. Also, it's usually the convention that the global namespace belongs principally to the user-defined application, despite the degree of pollution from other packages; it's yours to mangle as you see fit.
The exported commands of a namespace (which should typically be the public commands of the package with the same name) can be made available in another namespace without qualification via namespace import:
namespace eval ::foo {
proc grill {} { puts "grill!" }
namespace export grill
}
namespace eval ::bar {
namespace import ::foo::grill
grill
puts [namespace which grill]; # Prints ::bar::grill
puts [namespace origin grill]; # Prints ::foo::grill
}
Alternatively (from Tcl 8.5) you can update the resolution path of a namespace so it also looks in the other namespace:
namespace eval ::foo {
proc grill {} { puts "grill!" }
}
namespace eval ::bar {
namespace path ::foo
grill
puts [namespace which grill]; # Prints ::foo::grill
puts [namespace origin grill]; # Prints ::foo::grill
}
Note that the two mechanisms are a bit different: with imported commands, there is a local delegate for the command (and as that delegate is actually a command, you can rename it, etc.) whereas with path changes there are no such delegates; the command in the originating namespace is located directly during resolution of what grill means in that context.
List and strings does not come under any special packages. They are the basic commands. All the variables are treated as a string in tcl.
$ tclsh
% set l [list 1 2 3 4 5]
1 2 3 4 5
% lappend l 6
1 2 3 4 5 6
% set str "Hello, World"
Hello, World
Related
This is a simplified case of a problem. I am trying to copy a procedure to a namespace, so that it would be using the namespace own's context. Using import does not work (probably because it just creates aliases) See code below:
proc me_namespace {} {
puts "namespace is:[namespace current]"
puts "called namespace is:[uplevel 1 namespace current ]"
}
namespace eval foo {} {
me_namespace
puts "Now import"
namespace import ::::me_namespace
me_namespace
}
The code output is:
namespace is:::
called namespace is:::foo
Now import
namespace is:::
called namespace is:::foo
namespace is:::foo
Ideally, the proc me_namespace 1st line output, after the copying, should be:
::::me_namespace
Any ideas? The only thing that I can think of is having the procedures definitions be in a file, and then reading the file, and using eval, but I was looking for something more elegant.
The reason that I do not just use uplevel, is that at times (in particular when using variable with uplevel is that the runtime, a times, is far too slow. TCL version is 8.6
Procedures are bound to their containing namespace. Rename the procedure, change its binding. (I hate that!) To recreate a procedure in another namespace, you effectively have to either rename (a move) or to rerun the proc that created the original.
Now, while I'd really recommend looking at using TclOO when you're getting into this sort of thing, you might be able to use a different technique. The namespace upvar command is reasonably fast, and you might be able to use it like this:
proc master_version_of_foo {ns args} {
namespace upvar $ns abc local1 def local2
# ... continue with your code in here
}
# Stamp out some copies
namespace eval ::x {}
interp alias {} ::x::foo {} ::master_version_of_foo ::x
namespace eval ::y {}
interp alias {} ::y::foo {} ::master_version_of_foo ::y
namespace eval ::z {}
interp alias {} ::z::foo {} ::master_version_of_foo ::z
These true command aliases are pretty fast, the variable binding is pretty fast too (similar in speed to the global command; they use virtually the same bytecode operations internally) and you'll be sharing the compilation of the procedure which is itself pretty fast.
The main reason for not doing this is if you need different command resolution in the three cases. At that point, the fastest routes all go through TclOO (which tames quite a few of the advanced capabilities of Tcl to the point of being usable) and probably require some serious redesign on your part to use well.
I have a little problem which I cannot explain at the moment. I created a minimalistic code snippet to show my problem or lack of understanding how tcl namespaces are working.
So I have the file test.tcl:
namespace eval test {
proc print {file_name} {
namespace inscope ::test2 {
printFileName $::test::file_name
}
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
Than I use tclsh and run:
source test.tcl
test::print test.dat
Which returns:
can't read "::test::file_name": no such variable
Why is that should the argument of test::print not be in the ::test namescope?
I have an easy workaround with set ::test::filename $filename before namespace inscope {}.
But I am not satisfied since I miss something here.
I cannot just run ::test2::printFileName $file_name since my real world code is more complex and does not run just one command it sources a list of commands which are all in a different namespace.
Local variables are not namespace variables. In particular, even with variable linking (the mechanism underlying upvar and global and variable etc.) formal parameter variables are never namespace variables in any way. That's just how the variables are mapped, because it's very fast to do; the procedure entry code is one of the hottest parts of Tcl's implementation code, so great efforts are taken to keep it as fast as possible.
But all is not lost!
You can copy the value to a namespace variable easily enough, or even do tricks with traces and upvar to make it appear like the local variable can be written back to from that interior scope. (You'll probably have to use info level to search back up the stack for where to inject the write, which will be horribly messy, but it will work.)
But what I'd instead do is make commands to provide the values (and possibly allow writing back as necessary). I think it's a bit cleaner.
namespace eval test {
proc print {file_name} {
proc ::test2::file_name {} [list return $file_name]
namespace eval ::test2 {
printFileName [file_name]
}
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
You can make this more elegant through the use of namespace path so that you don't have to build a whole new procedure each time you call. interp alias can help too (it's a good way to do argument currying, if you're familiar with that sort of thing from functional programming).
The problem here is that ::test::file_name refers to the file_name variable in the ::test namespace and not the local variable file_name as it seems that you want. That's just the way variable name resolution works. Local variables that are arguments to commands don't reside in the enclosing namespace.
Also, it is unusual to see namespace inscope invoked directly in a script. I would write this instead:
namespace eval test {
proc print {file_name} {
{*}[namespace eval ::test2 namespace code printFileName] $file_name
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
Or some variation if you don't have {*} in your version of Tcl.
But your last comment about not being able to run the command directly makes me suspect that this approach may not yet solve your problem.
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.
Is there a way(a method call) to find out the name of the current package in tcl??
Eg:
package provides abc
proc A {
// I need to print the package name abc.
}
I know the class name here is obviously "abc" but still I want to print it out using a tcl command. I'm working on some debug modules and hence need this. (Similar to what perl provides: __PACKAGE__)
I am not aware of anything like that. However, you can work around:
set __PACKAGE__ foo
package provide $__PACKAGE__ 1.0
# Use can use the variable $__PACKAGE__ from now on
You are missing a few pieces of the puzzle. Even though you declared proc A in a file that is part of a package, A is still created globally.
The package command really just helps tcl figure out which file to source. You usually want to mix package provide with namespace
package provide abc
namespace eval ::abc {
proc A {} {puts stdout "I am in namespace [namespace current]"}
proc B {} {..}
proc C {} {..}
}
In order to call this function you would say
::abc::A
From inside the body of A you can tell what namespace you are in by using namespace current
An alternate way of writing this would be
namespace eval ::abc {}
proc ::abc::A {} {puts stdout "I am in namespace [namespace current]"}
proc ::abc::B {} {..}
proc ::abc::C {} {..}
There is not a one to one mapping between packages and namespaces. So one package could create many namespaces (or like in your example, no namespaces).
Check out this page for how to build libraries:
http://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html
And this page for full instructions on package and namespace
http://www.tcl.tk/man/tcl8.6/TclCmd/contents.htm
I have two tcl scripts. I want to run the second script when the first finished. How can I do it?
Depends on what do you really mean.
One way is to write a third ("master") script which would do
source /the/path/to/the/first.tcl
source /the/path/to/the/second.tcl
Another way is to just add the second call to source from the above example to the bottom of the first script.
Amendment to the first approach: if the scripts to be executed are located in the same directory as the master script, an idiomatic way to source them is
set where [file dirname [info script]]
source [file join $where first.tcl]
source [file join $where second.tcl]
This way sourcing will work no matter what the current process's directory is and where the project directory is located.
While this is generally a correct answer, because the question was not precisely formulated there are tons of ways to achieve the goal of running Tcl code from within Tcl.
I want to get into this in detail because understanding the execution of code is one major point in understanding Tcl itself.
There is source
The source command should not be confound with executing scripts in a classical way, what I think the thread starter has asked.
The source command is like the "include" command in c/perl/php.
Languages like java or python on the other hand only have "import" mechanisms.
The difference is that those languages create a internal database of available packages, who are linked to the corresponding source/binary/bytecode files. By writing a import statement, linked source or bytecode or binary files are loaded. This allows more in-depth dependency management without writing additional code.
In Tcl this can be achieved with namespaces and the package require command.
Example:
Suppose you have this source.tcl:
proc foo {bar} {puts "baz"}
set BAM "BOO"
Now, you have your "master" script like you call it. I call it "main". It has the content:
set BAM {my important data}
source source.tcl
#also the function foo can now be used because the source reads the whole script
foo {wuz}
set BAM
#will output "BOO"
The exec command
If you can live with additional overhead of starting a whole new interpreter instance you could also do:
set BAM {my important data}
exec tclsh source.tcl
#The variable BAM will not be modified. You can not use the function foo.
The eval command
The command eval can evaluate a string or a list (in Tcl everything is a string) like it would be programmed code.
You would have to load the complete source file to a string. And then use eval, to evaluate the code within a separate scope, to not overwrite stuff in your main source file.
set fp [open "somefile" r]
set code_string [read $fp]
close $fp
eval $code_string
You just need to use source to run the 2nd script.
source "/tmp/whatever.tcl"
Simplest possible working example I could find:
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$ tclsh main.tcl
hello world
7
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$ cat main.tcl
lappend auto_path /home/thufir/NetBeansProjects/spawnTelnet/telnet/api
package require weather 1.0
tutstack::hello
set A 3
set B 4
puts [tutstack::sum $A $B]
#puts [tutstack::hello "fred"]
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$ cat api/weather.tcl
package provide weather 1.0
package require Tcl 8.5
namespace eval ::tutstack {
}
proc ::tutstack::hello {} {
puts "hello world"
}
proc ::tutstack::sum {arg1 arg2} {
set x [expr {$arg1 + $arg2}];
return $x
}
proc ::tutstack::helloWorld {arg1} {
return "hello plus arg"
}
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$ cat api/pkgIndex.tcl
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script. It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands. When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.
package ifneeded weather 1.0 [list source [file join $dir weather.tcl]]
thufir#dur:~/NetBeansProjects/spawnTelnet/telnet$