Version 12 of source

Updated 2003-02-12 15:38:25

http://www.purl.org/tcl/home/man/tcl8.4/TclCmd/source.htm

source - Evaluate a file or resource as a Tcl script

 source fileName 
 source -rsrc resourceName ?fileName?
 source -rsrcid resourceId ?fileName?  

This command takes the contents of the specified file or resource and passes it to the Tcl interpreter as a text script. The return value from source is the return value of the last command executed in the script. If an error occurs in evaluating the contents of the script then the source command will return that error. If a return command is invoked from within the script then the remainder of the file will be skipped and the source command will return normally with the result from the return command. The -rsrc and -rsrcid forms of this command are only available on Macintosh computers. These versions of the command allow you to source a script from a TEXT resource. You may specify what TEXT resource to source by either name or id. By default Tcl searches all open resource files, which include the current application and any loaded C extensions. Alternatively, you may specify the fileName where the TEXT resource can be found. (from: Tcl Help)


Note that, with Tcl 8.4, the source command is documented as treating a ^Z (the literal character, not the 2 ascii representation I just used) as an indicator of end of file across all platforms. There is verbage there that reflects what to do if you need to use that character in a data string.


Notice that sourcing is always done in the system encoding. For sources in Unicode or other goodies you'd have to open a file, fconfigure -encoding, read, eval, close - see Unicode file reader or source with encoding. source $file does basically:

 set fp [open $file]
 set data [read $fp]
 close $fp
 eval $data

You can also source (almost) pure data files like this:

 array set data [source datafile]

where datafile contains:

 return {
 1 {some data}
 2 {other data}
 . ...
 foo {note that the element name does not have to be numeric}
 }

results in:

 % parray data
 data(.)   = ...
 data(1)   = some data
 data(2)   = other data
 data(foo) = note that the element name does not have to be numeric

In a general sense, this command feeds commands to Tcl similarly to if you were typing them at the Tcl interpreter prompt.

Can anyone detail some of the Tcl behavioral differences between a user typing in the commands and invoking source?


David Welton's sourcecache [L1 ] acts as source does, but with caching. This is useful, as he notes, "for applications such as web servers running dynamic pages ..."


Arjen Markus Sometimes it is useful to distinguish between the Tcl/Tk shell sourcing the file (as in tclsh aa.tcl) and the script being evaluated to do this (via the command "source aa.tcl"). This can be used to:

  • Provide a library of useful procedures and
  • Provide a self-contained "main" proc in the same file

One example of this, a library of procs that together compare two files. If called directly:

   tclsh numcomp.tcl a.inp b.inp

the main proc gets executed and the comparison is started. If sourced inside another script, however, this is not done and the sourcing script has full control. (In this case: it is a larger script controlling a number of programs whose results must be compared against reference files).

The trick is the code below:

   if { [info script] == "$::argv0" } {
      puts "In main"
   } else {
      puts "Sourcing [info script]" 
   }

Another trick I recently learned: the return command works in source as in any other script - it allows you to return from the source command, so that the rest of the file is not handled. Quite useful for recovering from errors or making the processing depend on external influences.


/bin/sh-like source: When playing Bourne shell, I found out that their source command "." searches the environment PATH, a feature that has occasionally been missed in Tcl's source. Well, here's an emulation (that caters for Unix/Win differences as well):

 proc path'separator {} {
    switch -- $::tcl_platform(platform) {
        unix    {return ":"}
        windows {return ";"}
        default {error "unknown platform"}
    }
 }
 if {[llength [info global tk*]==0} {
    # The name . is taboo in a wish, would exit immediately
    proc . filename {
        foreach path [split $::env(PATH) [path'separator]] {
            set try [file join $path $filename]
            if [file readable $try] {return [source $try]}
        }
        error ".: no such file or directory: $filename"
    }
 } ;# RS

escargo 13 Dec 2002 - I think it is interesting how source takes a filename and not a channel. Certainly as a convenience, having the source command open the file, read the file, and close the file factors out common behaviour, but it hides the low-level operation of reading the file and executing the contents. Is there a particular reason this lower abstraction is not available? (Perhaps it's too trivial, but it seems to me that being able to source a channel could be a powerful thing, maybe too powerful. But then, maybe that's why there are safe interpreters.)


Tcl syntax help - Arts and crafts of Tcl-Tk programming - Category Command