Version 14 of info script

Updated 2010-03-19 15:33:03 by Cameron

info script ?filename?

If a Tcl script file is currently being evaluated (i.e. there is a call to Tcl_EvalFile active or there is an active invocation of the source command), then this command returns the name of the innermost file being processed. If filename is specified, then the return value of this command will be modified for the duration of the active invocation to return that name. This is useful in virtual file system applications.

Otherwise, if the file is not in the process of actively being sourced in or processed by Tcl_EvalFile, the command returns an empty string.


MJL I find the above description (from the manual page) rather confusing and poorly worded. So here's my attempt at an explanation:

Every Tcl interpreter has an associated "script file" Tcl object, which is initially empty. This can be set by invoking info script new_value and retrieved by invoking info script. The function Tcl_FSEvalFile(), which is called to implement the source command, modifies the script file object as follows. Its value is saved, then set to the name of the file to be evaluated. The file's contents are evaluated, then the saved value is restored.

P.S. Note that Tcl_EvalFile() is obsolete.

Moreover, as dburns noted in the Chatroom, "I believe 'info script' is what you want, but the command must be executed before the 'source' command finishes reading in the script...hence the 'info script' must be executed at the top-level within the script file...if embedded in a proc within the script, it's 'too late' by the time the proc is run for 'info script' to work correctly"


RS 2005-05-24 - The following idiom allows code to be executed when a script is sourced at top level into an interp, but not if sourced from other scripts - part of a "self-test" mechanism. The test for info exists argv0 is needed for Tclets, iirc - you may not need it:

 proc sum {a b} {expr {$a+$b}} ;# testing dummy

 if {[info exists argv0] && [file tail [info script]] eq [file tail $argv0]} {
    puts "sum 3 4 = [sum 3 4]"
 }

cjl 2010-02-21 - I use a variation on the above to append either some sort of self-test or standalone mode to most of my scripts

   if { ![info exists argv0] || [file tail [info script]] ne [file tail $argv0]} { return }
   # test/standalone code follows

There is a more naive approach which only compares info script with $argv0 and works in many scenarios. The complete version is required for correct behaviour when pkg_mkIndex is being used.


schlenk 2005-04-24 - The man page implies that it is impossible to get the filename a proc comes from after Tcl_FSEvalFile() or the source command has returned. So the only way to do it is to register this info while creating the proc or to use something like grep to look for it inside the filesystem.

 # move the old proc command out of the way
 rename proc ::tcl::proc
 # create a replacement proc that registers all occurrences of proc creation
 # into the global proc_to_filename_map variable
 ::tcl::proc proc {args} {
     global proc_to_filename_map
     set proc_to_filename_map([lindex $args 0]) [info script]
     uplevel 1 [linsert $args 0 ::tcl::proc]
 }

With this one can easily find the file for a proc by looking into the array. For Tcl 8.4 and later one could use execution traces on the proc command to do the same thing without renaming proc, implementation is left as an exercise.


escargo 23 Aug 2005 - There is another idiom where info script is used: where a script needs to source other related scripts so that it can run. For example:

 source [file join [file dirname [info script]] tkcon.tcl]

See also: