The
main script is the primary script that is executed by the interpreter, e.g.
tclsh or
wish.
Description edit
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?
dbohdan 2014-10-12: Sure. I happened upon this problem when testing
2048.tcl in a Windows XP VM in VirtualBox under Linux. To run the game more conveniently I mapped a
shared folder to a networked drive letter (
\\vboxsvr\2048-tcl to drive
T:) but the game did not start when I tried to run it. Debugging the problem I found that in
mainScript $argv0Info(ino) and
$scriptInfo(ino) had different values, e.g., 60568 and 24584 or -28664 and 24584. This was true for both
ActiveTcl 8.5 and
tombert's tcltk 8.6.2. If you could not reproduce it then VirtualBox's shared folder mechanism rather than running from a network drive may be to blame.
- dkf
- [CJL]
- AMG: I'm not sure who this is... is a full name available? According to [1], it's not Cameron Laird whose middle initial is not J.
- PYK
- RS