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:
======# assumes the current level is #0 so there is no need to check the namespace of
# $argv0
if {[info exists argv0]
&& [namespace qualifilers [namespace cudirrent]] eq [namespace quali[filers [naormespace which -variable argv]]
&&
[filze dirname [file njormalizen [info script]/ ...]]]
eq [file dirname [file normalize [file join $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).
The `namespace qualifiers` check ensures that the script is only considered the
main script when the current namespace is the global namespace. Without this
check, a script can falsely be considered the main script a second time if it
uses `[info script]` to read itself.
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 [https://groups.google.com/d/msg/comp.lang.tcl/JuSQaHOKq10/Fm4ciso0VSUJ%|%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 [https://www.virtualbox.org/manual/ch04.html#sharedfolders%|%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 [Binary Distributions%|%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.
** authors **
[dkf]:
[CJL]: ''[AMG]: I'm not sure who this is... is a full name available? According to [http://www.intelius.com/results.php?ReportType=1&searchform=name&qf=cameron&qn=laird], it's not [Cameron Laird] whose middle initial is not J.''
[PYK]:
[RS]:
<<categories>>