Version 21 of main script

Updated 2014-10-12 01:10:24 by pooryorick

The main script is the primary script that is executed by the interpreter, e.g. tclsh or wish.

Description

One common technique is to have a script run a self test if it detects that it is the main script. Naive approaches only compare info script with $argv0. A somewhat more robust approach that usually works with pkg_mkIndex looks only at the file tail of those two values. The most robust approach fully normalizes those two values, including the last component, which a simple file normalize does not resolve.

The most complete approach:

if {[info exists argv0] && [
    file dirname [file normalize [info script]/...]] eq [
    file dirname [file normalize $argv0/...]]} {

    #do stuff
}

The /... on the end of each path ensures that file normalize resolves the path completely. Normally, the last component will not be resolved (see documentation for details).

A common and fairly robust approach:

if {[info exists argv0] && [file tail [info script]] eq [file tail $argv0]} {
    #do stuff
}

The negative approach, also quite common:

if {![info exists argv0] || [file tail [info script]] ne [file tail $argv0]} {
    return
}

# test/standalone code follows

The more simple and naive approach to detection method directly compares info script with $argv0:

if {[info exists argv0] && $argv0 eq [info script]} {
    #do stuff
}

or, as formulated in Methods for Justifying text output in TCL , DKF, comp.lang.tcl, 2001-06-15:

if {[string equal $::argv0 [info script]] || [array exists ::embed_args]} {
    main
} 

AMG: Which posting would that be? What is ::embed_args? It must be something specific to the script DKF was describing.

PYK: I migrated this example and the verbiage from another page (can't remember which one now), and unfortunately it was just as unclear on that other page as well. I just searched comp.lang.tcl though, found the conversation, and included it above.

AMG: Here's a new way to do it, comparing device and inode numbers:

proc mainScript {} {
    global argv0
    if {[info exists argv0]
     && [file exists [info script]] && [file exists $argv0]} {
        file stat $argv0        argv0Info
        file stat [info script] scriptInfo
        expr {$argv0Info(dev) == $scriptInfo(dev)
           && $argv0Info(ino) == $scriptInfo(ino)}
    } else {
        return 0
    }
}

And by request from PYK, here's how to make the above callable as [info main]:

namespace ensemble configure info -map [dict replace\
    [namespace ensemble configure info -map] main mainScript]

PYK: Actually, I was suggesting that since only tclsh itself really knows what is the main script, e.g. wouldn't get confused by source info script, that it should provide [info main] as an alternative to all the scripts on this page.

dbohdan 2014-10-11: It appears that if a script is run from a network drive on Windows $argv0Info(ino) == $scriptInfo(ino) doesn't hold.

PYK 2014-10-11: I just tried with Tcl version 8.6.2 under Windows XP, and didn't detect any problem. Can you provide more details?

authors

dkf
CJL
AMG: I'm not sure who this is... is a full name available? According to [L1 ], it's not Cameron Laird whose middle initial is not J.
PYK
RS