os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/library/init.tcl
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
# init.tcl --
sl@0
     2
#
sl@0
     3
# Default system startup file for Tcl-based applications.  Defines
sl@0
     4
# "unknown" procedure and auto-load facilities.
sl@0
     5
#
sl@0
     6
# RCS: @(#) $Id: init.tcl,v 1.55.2.6 2005/07/22 21:59:40 dgp Exp $
sl@0
     7
#
sl@0
     8
# Copyright (c) 1991-1993 The Regents of the University of California.
sl@0
     9
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
sl@0
    10
# Copyright (c) 1998-1999 Scriptics Corporation.
sl@0
    11
# Portions Copyright (c) 2007 Nokia Corporation and/or its subsidiaries. All rights reserved.  
sl@0
    12
#
sl@0
    13
# See the file "license.terms" for information on usage and redistribution
sl@0
    14
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    15
#
sl@0
    16
sl@0
    17
if {[info commands package] == ""} {
sl@0
    18
    error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
sl@0
    19
}
sl@0
    20
package require -exact Tcl 8.4
sl@0
    21
sl@0
    22
# Compute the auto path to use in this interpreter.
sl@0
    23
# The values on the path come from several locations:
sl@0
    24
#
sl@0
    25
# The environment variable TCLLIBPATH
sl@0
    26
#
sl@0
    27
# tcl_library, which is the directory containing this init.tcl script.
sl@0
    28
# tclInitScript.h searches around for the directory containing this
sl@0
    29
# init.tcl and defines tcl_library to that location before sourcing it.
sl@0
    30
#
sl@0
    31
# The parent directory of tcl_library. Adding the parent
sl@0
    32
# means that packages in peer directories will be found automatically.
sl@0
    33
#
sl@0
    34
# Also add the directory ../lib relative to the directory where the
sl@0
    35
# executable is located.  This is meant to find binary packages for the
sl@0
    36
# same architecture as the current executable.
sl@0
    37
#
sl@0
    38
# tcl_pkgPath, which is set by the platform-specific initialization routines
sl@0
    39
#	On UNIX it is compiled in
sl@0
    40
#       On Windows, it is not used
sl@0
    41
#	On Macintosh it is "Tool Command Language" in the Extensions folder
sl@0
    42
sl@0
    43
if {![info exists auto_path]} {
sl@0
    44
    if {[info exists env(TCLLIBPATH)]} {
sl@0
    45
	set auto_path $env(TCLLIBPATH)
sl@0
    46
    } else {
sl@0
    47
	set auto_path ""
sl@0
    48
    }
sl@0
    49
}
sl@0
    50
namespace eval tcl {
sl@0
    51
    variable Dir
sl@0
    52
    if {[info library] ne ""} {
sl@0
    53
	foreach Dir [list [info library] [file dirname [info library]]] {
sl@0
    54
	    if {[lsearch -exact $::auto_path $Dir] < 0} {
sl@0
    55
		lappend ::auto_path $Dir
sl@0
    56
	    }
sl@0
    57
	}
sl@0
    58
    }
sl@0
    59
    if {![string equal $tcl_platform(osSystemName) "Symbian"]} {
sl@0
    60
       set Dir [file join [file dirname [file dirname \
sl@0
    61
	 [info nameofexecutable]]] lib]
sl@0
    62
    }
sl@0
    63
    if {[lsearch -exact $::auto_path $Dir] < 0} {
sl@0
    64
	lappend ::auto_path $Dir
sl@0
    65
    }
sl@0
    66
    if {[info exists ::tcl_pkgPath]} {
sl@0
    67
	foreach Dir $::tcl_pkgPath {
sl@0
    68
	    if {[lsearch -exact $::auto_path $Dir] < 0} {
sl@0
    69
		lappend ::auto_path $Dir
sl@0
    70
	    }
sl@0
    71
	}
sl@0
    72
    }
sl@0
    73
}
sl@0
    74
  
sl@0
    75
# Windows specific end of initialization
sl@0
    76
sl@0
    77
if {(![interp issafe]) && $tcl_platform(platform) eq "windows"} {
sl@0
    78
    namespace eval tcl {
sl@0
    79
	proc EnvTraceProc {lo n1 n2 op} {
sl@0
    80
	    set x $::env($n2)
sl@0
    81
	    set ::env($lo) $x
sl@0
    82
	    set ::env([string toupper $lo]) $x
sl@0
    83
	}
sl@0
    84
	proc InitWinEnv {} {
sl@0
    85
	    global env tcl_platform
sl@0
    86
	    foreach p [array names env] {
sl@0
    87
		set u [string toupper $p]
sl@0
    88
		if {$u ne $p} {
sl@0
    89
		    switch -- $u {
sl@0
    90
			COMSPEC -
sl@0
    91
			PATH {
sl@0
    92
			    if {![info exists env($u)]} {
sl@0
    93
				set env($u) $env($p)
sl@0
    94
			    }
sl@0
    95
			    trace add variable env($p) write \
sl@0
    96
				    [namespace code [list EnvTraceProc $p]]
sl@0
    97
			    trace add variable env($u) write \
sl@0
    98
				    [namespace code [list EnvTraceProc $p]]
sl@0
    99
			}
sl@0
   100
		    }
sl@0
   101
		}
sl@0
   102
	    }
sl@0
   103
	    if {![info exists env(COMSPEC)]} {
sl@0
   104
		if {$tcl_platform(os) eq "Windows NT"} {
sl@0
   105
		    set env(COMSPEC) cmd.exe
sl@0
   106
		} else {
sl@0
   107
		    set env(COMSPEC) command.com
sl@0
   108
		}
sl@0
   109
	    }
sl@0
   110
	}
sl@0
   111
	InitWinEnv
sl@0
   112
    }
sl@0
   113
}
sl@0
   114
sl@0
   115
# Setup the unknown package handler
sl@0
   116
sl@0
   117
package unknown tclPkgUnknown
sl@0
   118
sl@0
   119
if {![interp issafe]} {
sl@0
   120
    # setup platform specific unknown package handlers
sl@0
   121
    if {$::tcl_platform(platform) eq "unix"
sl@0
   122
	    && $::tcl_platform(os) eq "Darwin"} {
sl@0
   123
	package unknown [list tcl::MacOSXPkgUnknown [package unknown]]
sl@0
   124
    }
sl@0
   125
    if {$::tcl_platform(platform) eq "macintosh"} {
sl@0
   126
	package unknown [list tcl::MacPkgUnknown [package unknown]]
sl@0
   127
    }
sl@0
   128
}
sl@0
   129
sl@0
   130
# Conditionalize for presence of exec.
sl@0
   131
sl@0
   132
if {[namespace which -command exec] eq ""} {
sl@0
   133
sl@0
   134
    # Some machines, such as the Macintosh, do not have exec. Also, on all
sl@0
   135
    # platforms, safe interpreters do not have exec.
sl@0
   136
sl@0
   137
    set auto_noexec 1
sl@0
   138
}
sl@0
   139
set errorCode ""
sl@0
   140
set errorInfo ""
sl@0
   141
sl@0
   142
# Define a log command (which can be overwitten to log errors
sl@0
   143
# differently, specially when stderr is not available)
sl@0
   144
sl@0
   145
if {[namespace which -command tclLog] eq ""} {
sl@0
   146
    proc tclLog {string} {
sl@0
   147
	catch {puts stderr $string}
sl@0
   148
    }
sl@0
   149
}
sl@0
   150
sl@0
   151
# unknown --
sl@0
   152
# This procedure is called when a Tcl command is invoked that doesn't
sl@0
   153
# exist in the interpreter.  It takes the following steps to make the
sl@0
   154
# command available:
sl@0
   155
#
sl@0
   156
#	1. See if the command has the form "namespace inscope ns cmd" and
sl@0
   157
#	   if so, concatenate its arguments onto the end and evaluate it.
sl@0
   158
#	2. See if the autoload facility can locate the command in a
sl@0
   159
#	   Tcl script file.  If so, load it and execute it.
sl@0
   160
#	3. If the command was invoked interactively at top-level:
sl@0
   161
#	    (a) see if the command exists as an executable UNIX program.
sl@0
   162
#		If so, "exec" the command.
sl@0
   163
#	    (b) see if the command requests csh-like history substitution
sl@0
   164
#		in one of the common forms !!, !<number>, or ^old^new.  If
sl@0
   165
#		so, emulate csh's history substitution.
sl@0
   166
#	    (c) see if the command is a unique abbreviation for another
sl@0
   167
#		command.  If so, invoke the command.
sl@0
   168
#
sl@0
   169
# Arguments:
sl@0
   170
# args -	A list whose elements are the words of the original
sl@0
   171
#		command, including the command name.
sl@0
   172
sl@0
   173
proc unknown args {
sl@0
   174
    global auto_noexec auto_noload env unknown_pending tcl_interactive
sl@0
   175
    global errorCode errorInfo
sl@0
   176
sl@0
   177
    # If the command word has the form "namespace inscope ns cmd"
sl@0
   178
    # then concatenate its arguments onto the end and evaluate it.
sl@0
   179
sl@0
   180
    set cmd [lindex $args 0]
sl@0
   181
    if {[regexp "^:*namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} {
sl@0
   182
        set arglist [lrange $args 1 end]
sl@0
   183
	set ret [catch {uplevel 1 ::$cmd $arglist} result]
sl@0
   184
        if {$ret == 0} {
sl@0
   185
            return $result
sl@0
   186
        } else {
sl@0
   187
	    return -code $ret -errorcode $errorCode $result
sl@0
   188
        }
sl@0
   189
    }
sl@0
   190
sl@0
   191
    # Save the values of errorCode and errorInfo variables, since they
sl@0
   192
    # may get modified if caught errors occur below.  The variables will
sl@0
   193
    # be restored just before re-executing the missing command.
sl@0
   194
sl@0
   195
    # Safety check in case something unsets the variables 
sl@0
   196
    # ::errorInfo or ::errorCode.  [Bug 1063707]
sl@0
   197
    if {![info exists errorCode]} {
sl@0
   198
	set errorCode ""
sl@0
   199
    }
sl@0
   200
    if {![info exists errorInfo]} {
sl@0
   201
	set errorInfo ""
sl@0
   202
    }
sl@0
   203
    set savedErrorCode $errorCode
sl@0
   204
    set savedErrorInfo $errorInfo
sl@0
   205
    set name $cmd
sl@0
   206
    if {![info exists auto_noload]} {
sl@0
   207
	#
sl@0
   208
	# Make sure we're not trying to load the same proc twice.
sl@0
   209
	#
sl@0
   210
	if {[info exists unknown_pending($name)]} {
sl@0
   211
	    return -code error "self-referential recursion in \"unknown\" for command \"$name\"";
sl@0
   212
	}
sl@0
   213
	set unknown_pending($name) pending;
sl@0
   214
	set ret [catch {auto_load $name [uplevel 1 {::namespace current}]} msg]
sl@0
   215
	unset unknown_pending($name);
sl@0
   216
	if {$ret != 0} {
sl@0
   217
	    append errorInfo "\n    (autoloading \"$name\")"
sl@0
   218
	    return -code $ret -errorcode $errorCode -errorinfo $errorInfo $msg
sl@0
   219
	}
sl@0
   220
	if {![array size unknown_pending]} {
sl@0
   221
	    unset unknown_pending
sl@0
   222
	}
sl@0
   223
	if {$msg} {
sl@0
   224
	    set errorCode $savedErrorCode
sl@0
   225
	    set errorInfo $savedErrorInfo
sl@0
   226
	    set code [catch {uplevel 1 $args} msg]
sl@0
   227
	    if {$code ==  1} {
sl@0
   228
		#
sl@0
   229
		# Compute stack trace contribution from the [uplevel].
sl@0
   230
		# Note the dependence on how Tcl_AddErrorInfo, etc. 
sl@0
   231
		# construct the stack trace.
sl@0
   232
		#
sl@0
   233
		set cinfo $args
sl@0
   234
		set ellipsis ""
sl@0
   235
		while {[string bytelength $cinfo] > 150} {
sl@0
   236
		    set cinfo [string range $cinfo 0 end-1]
sl@0
   237
		    set ellipsis "..."
sl@0
   238
		}
sl@0
   239
		append cinfo $ellipsis "\"\n    (\"uplevel\" body line 1)"
sl@0
   240
		append cinfo "\n    invoked from within"
sl@0
   241
		append cinfo "\n\"uplevel 1 \$args\""
sl@0
   242
		#
sl@0
   243
		# Try each possible form of the stack trace
sl@0
   244
		# and trim the extra contribution from the matching case
sl@0
   245
		#
sl@0
   246
		set expect "$msg\n    while executing\n\"$cinfo"
sl@0
   247
		if {$errorInfo eq $expect} {
sl@0
   248
		    #
sl@0
   249
		    # The stack has only the eval from the expanded command
sl@0
   250
		    # Do not generate any stack trace here.
sl@0
   251
		    #
sl@0
   252
		    return -code error -errorcode $errorCode $msg
sl@0
   253
		}
sl@0
   254
		#
sl@0
   255
		# Stack trace is nested, trim off just the contribution
sl@0
   256
		# from the extra "eval" of $args due to the "catch" above.
sl@0
   257
		#
sl@0
   258
		set expect "\n    invoked from within\n\"$cinfo"
sl@0
   259
		set exlen [string length $expect]
sl@0
   260
		set eilen [string length $errorInfo]
sl@0
   261
		set i [expr {$eilen - $exlen - 1}]
sl@0
   262
		set einfo [string range $errorInfo 0 $i]
sl@0
   263
		#
sl@0
   264
		# For now verify that $errorInfo consists of what we are about
sl@0
   265
		# to return plus what we expected to trim off.
sl@0
   266
		#
sl@0
   267
		if {$errorInfo ne "$einfo$expect"} {
sl@0
   268
		    error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
sl@0
   269
			[list CORE UNKNOWN BADTRACE $expect $errorInfo]
sl@0
   270
		}
sl@0
   271
		return -code error -errorcode $errorCode \
sl@0
   272
			-errorinfo $einfo $msg
sl@0
   273
	    } else {
sl@0
   274
		return -code $code $msg
sl@0
   275
	    }
sl@0
   276
	}
sl@0
   277
    }
sl@0
   278
sl@0
   279
    if {([info level] == 1) && [info script] eq "" \
sl@0
   280
	    && [info exists tcl_interactive] && $tcl_interactive} {
sl@0
   281
	if {![info exists auto_noexec]} {
sl@0
   282
	    set new [auto_execok $name]
sl@0
   283
	    if {$new ne ""} {
sl@0
   284
		set errorCode $savedErrorCode
sl@0
   285
		set errorInfo $savedErrorInfo
sl@0
   286
		set redir ""
sl@0
   287
		if {[namespace which -command console] eq ""} {
sl@0
   288
		    set redir ">&@stdout <@stdin"
sl@0
   289
		}
sl@0
   290
		return [uplevel 1 exec $redir $new [lrange $args 1 end]]
sl@0
   291
	    }
sl@0
   292
	}
sl@0
   293
	set errorCode $savedErrorCode
sl@0
   294
	set errorInfo $savedErrorInfo
sl@0
   295
	if {$name eq "!!"} {
sl@0
   296
	    set newcmd [history event]
sl@0
   297
	} elseif {[regexp {^!(.+)$} $name -> event]} {
sl@0
   298
	    set newcmd [history event $event]
sl@0
   299
	} elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name -> old new]} {
sl@0
   300
	    set newcmd [history event -1]
sl@0
   301
	    catch {regsub -all -- $old $newcmd $new newcmd}
sl@0
   302
	}
sl@0
   303
	if {[info exists newcmd]} {
sl@0
   304
	    tclLog $newcmd
sl@0
   305
	    history change $newcmd 0
sl@0
   306
	    return [uplevel 1 $newcmd]
sl@0
   307
	}
sl@0
   308
sl@0
   309
	set ret [catch {set candidates [info commands $name*]} msg]
sl@0
   310
	if {$name eq "::"} {
sl@0
   311
	    set name ""
sl@0
   312
	}
sl@0
   313
	if {$ret != 0} {
sl@0
   314
	    return -code $ret -errorcode $errorCode \
sl@0
   315
		"error in unknown while checking if \"$name\" is\
sl@0
   316
		a unique command abbreviation:\n$msg"
sl@0
   317
	}
sl@0
   318
	# Handle empty $name separately due to strangeness in [string first]
sl@0
   319
	if {$name eq ""} {
sl@0
   320
	    if {[llength $candidates] != 1} {
sl@0
   321
		return -code error "empty command name \"\""
sl@0
   322
	    }
sl@0
   323
	    return [uplevel 1 [lreplace $args 0 0 [lindex $candidates 0]]]
sl@0
   324
	}
sl@0
   325
	# Filter out bogus matches when $name contained
sl@0
   326
	# a glob-special char [Bug 946952]
sl@0
   327
	set cmds [list]
sl@0
   328
	foreach x $candidates {
sl@0
   329
	    if {[string first $name $x] == 0} {
sl@0
   330
		lappend cmds $x
sl@0
   331
	    }
sl@0
   332
	}
sl@0
   333
	if {[llength $cmds] == 1} {
sl@0
   334
	    return [uplevel 1 [lreplace $args 0 0 [lindex $cmds 0]]]
sl@0
   335
	}
sl@0
   336
	if {[llength $cmds]} {
sl@0
   337
	    return -code error "ambiguous command name \"$name\": [lsort $cmds]"
sl@0
   338
	}
sl@0
   339
    }
sl@0
   340
    return -code error "invalid command name \"$name\""
sl@0
   341
}
sl@0
   342
sl@0
   343
# auto_load --
sl@0
   344
# Checks a collection of library directories to see if a procedure
sl@0
   345
# is defined in one of them.  If so, it sources the appropriate
sl@0
   346
# library file to create the procedure.  Returns 1 if it successfully
sl@0
   347
# loaded the procedure, 0 otherwise.
sl@0
   348
#
sl@0
   349
# Arguments: 
sl@0
   350
# cmd -			Name of the command to find and load.
sl@0
   351
# namespace (optional)  The namespace where the command is being used - must be
sl@0
   352
#                       a canonical namespace as returned [namespace current]
sl@0
   353
#                       for instance. If not given, namespace current is used.
sl@0
   354
sl@0
   355
proc auto_load {cmd {namespace {}}} {
sl@0
   356
    global auto_index auto_oldpath auto_path
sl@0
   357
sl@0
   358
    if {$namespace eq ""} {
sl@0
   359
	set namespace [uplevel 1 [list ::namespace current]]
sl@0
   360
    }
sl@0
   361
    set nameList [auto_qualify $cmd $namespace]
sl@0
   362
    # workaround non canonical auto_index entries that might be around
sl@0
   363
    # from older auto_mkindex versions
sl@0
   364
    lappend nameList $cmd
sl@0
   365
    foreach name $nameList {
sl@0
   366
	if {[info exists auto_index($name)]} {
sl@0
   367
	    namespace eval :: $auto_index($name)
sl@0
   368
	    # There's a couple of ways to look for a command of a given
sl@0
   369
	    # name.  One is to use
sl@0
   370
	    #    info commands $name
sl@0
   371
	    # Unfortunately, if the name has glob-magic chars in it like *
sl@0
   372
	    # or [], it may not match.  For our purposes here, a better
sl@0
   373
	    # route is to use 
sl@0
   374
	    #    namespace which -command $name
sl@0
   375
	    if {[namespace which -command $name] ne ""} {
sl@0
   376
		return 1
sl@0
   377
	    }
sl@0
   378
	}
sl@0
   379
    }
sl@0
   380
    if {![info exists auto_path]} {
sl@0
   381
	return 0
sl@0
   382
    }
sl@0
   383
sl@0
   384
    if {![auto_load_index]} {
sl@0
   385
	return 0
sl@0
   386
    }
sl@0
   387
    foreach name $nameList {
sl@0
   388
	if {[info exists auto_index($name)]} {
sl@0
   389
	    namespace eval :: $auto_index($name)
sl@0
   390
	    if {[namespace which -command $name] ne ""} {
sl@0
   391
		return 1
sl@0
   392
	    }
sl@0
   393
	}
sl@0
   394
    }
sl@0
   395
    return 0
sl@0
   396
}
sl@0
   397
sl@0
   398
# auto_load_index --
sl@0
   399
# Loads the contents of tclIndex files on the auto_path directory
sl@0
   400
# list.  This is usually invoked within auto_load to load the index
sl@0
   401
# of available commands.  Returns 1 if the index is loaded, and 0 if
sl@0
   402
# the index is already loaded and up to date.
sl@0
   403
#
sl@0
   404
# Arguments: 
sl@0
   405
# None.
sl@0
   406
sl@0
   407
proc auto_load_index {} {
sl@0
   408
    global auto_index auto_oldpath auto_path errorInfo errorCode
sl@0
   409
sl@0
   410
    if {[info exists auto_oldpath] && $auto_oldpath eq $auto_path} {
sl@0
   411
	return 0
sl@0
   412
    }
sl@0
   413
    set auto_oldpath $auto_path
sl@0
   414
sl@0
   415
    # Check if we are a safe interpreter. In that case, we support only
sl@0
   416
    # newer format tclIndex files.
sl@0
   417
sl@0
   418
    set issafe [interp issafe]
sl@0
   419
    for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} {
sl@0
   420
	set dir [lindex $auto_path $i]
sl@0
   421
	set f ""
sl@0
   422
	if {$issafe} {
sl@0
   423
	    catch {source [file join $dir tclIndex]}
sl@0
   424
	} elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
sl@0
   425
	    continue
sl@0
   426
	} else {
sl@0
   427
	    set error [catch {
sl@0
   428
		set id [gets $f]
sl@0
   429
		if {$id eq "# Tcl autoload index file, version 2.0"} {
sl@0
   430
		    eval [read $f]
sl@0
   431
		} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
sl@0
   432
		    while {[gets $f line] >= 0} {
sl@0
   433
			if {[string index $line 0] eq "#" 
sl@0
   434
				|| ([llength $line] != 2)} {
sl@0
   435
			    continue
sl@0
   436
			}
sl@0
   437
			set name [lindex $line 0]
sl@0
   438
			set auto_index($name) \
sl@0
   439
				"source [file join $dir [lindex $line 1]]"
sl@0
   440
		    }
sl@0
   441
		} else {
sl@0
   442
		    error "[file join $dir tclIndex] isn't a proper Tcl index file"
sl@0
   443
		}
sl@0
   444
	    } msg]
sl@0
   445
	    if {$f ne ""} {
sl@0
   446
		close $f
sl@0
   447
	    }
sl@0
   448
	    if {$error} {
sl@0
   449
		error $msg $errorInfo $errorCode
sl@0
   450
	    }
sl@0
   451
	}
sl@0
   452
    }
sl@0
   453
    return 1
sl@0
   454
}
sl@0
   455
sl@0
   456
# auto_qualify --
sl@0
   457
#
sl@0
   458
# Compute a fully qualified names list for use in the auto_index array.
sl@0
   459
# For historical reasons, commands in the global namespace do not have leading
sl@0
   460
# :: in the index key. The list has two elements when the command name is
sl@0
   461
# relative (no leading ::) and the namespace is not the global one. Otherwise
sl@0
   462
# only one name is returned (and searched in the auto_index).
sl@0
   463
#
sl@0
   464
# Arguments -
sl@0
   465
# cmd		The command name. Can be any name accepted for command
sl@0
   466
#               invocations (Like "foo::::bar").
sl@0
   467
# namespace	The namespace where the command is being used - must be
sl@0
   468
#               a canonical namespace as returned by [namespace current]
sl@0
   469
#               for instance.
sl@0
   470
sl@0
   471
proc auto_qualify {cmd namespace} {
sl@0
   472
sl@0
   473
    # count separators and clean them up
sl@0
   474
    # (making sure that foo:::::bar will be treated as foo::bar)
sl@0
   475
    set n [regsub -all {::+} $cmd :: cmd]
sl@0
   476
sl@0
   477
    # Ignore namespace if the name starts with ::
sl@0
   478
    # Handle special case of only leading ::
sl@0
   479
sl@0
   480
    # Before each return case we give an example of which category it is
sl@0
   481
    # with the following form :
sl@0
   482
    # ( inputCmd, inputNameSpace) -> output
sl@0
   483
sl@0
   484
    if {[string match ::* $cmd]} {
sl@0
   485
	if {$n > 1} {
sl@0
   486
	    # ( ::foo::bar , * ) -> ::foo::bar
sl@0
   487
	    return [list $cmd]
sl@0
   488
	} else {
sl@0
   489
	    # ( ::global , * ) -> global
sl@0
   490
	    return [list [string range $cmd 2 end]]
sl@0
   491
	}
sl@0
   492
    }
sl@0
   493
    
sl@0
   494
    # Potentially returning 2 elements to try  :
sl@0
   495
    # (if the current namespace is not the global one)
sl@0
   496
sl@0
   497
    if {$n == 0} {
sl@0
   498
	if {$namespace eq "::"} {
sl@0
   499
	    # ( nocolons , :: ) -> nocolons
sl@0
   500
	    return [list $cmd]
sl@0
   501
	} else {
sl@0
   502
	    # ( nocolons , ::sub ) -> ::sub::nocolons nocolons
sl@0
   503
	    return [list ${namespace}::$cmd $cmd]
sl@0
   504
	}
sl@0
   505
    } elseif {$namespace eq "::"} {
sl@0
   506
	#  ( foo::bar , :: ) -> ::foo::bar
sl@0
   507
	return [list ::$cmd]
sl@0
   508
    } else {
sl@0
   509
	# ( foo::bar , ::sub ) -> ::sub::foo::bar ::foo::bar
sl@0
   510
	return [list ${namespace}::$cmd ::$cmd]
sl@0
   511
    }
sl@0
   512
}
sl@0
   513
sl@0
   514
# auto_import --
sl@0
   515
#
sl@0
   516
# Invoked during "namespace import" to make see if the imported commands
sl@0
   517
# reside in an autoloaded library.  If so, the commands are loaded so
sl@0
   518
# that they will be available for the import links.  If not, then this
sl@0
   519
# procedure does nothing.
sl@0
   520
#
sl@0
   521
# Arguments -
sl@0
   522
# pattern	The pattern of commands being imported (like "foo::*")
sl@0
   523
#               a canonical namespace as returned by [namespace current]
sl@0
   524
sl@0
   525
proc auto_import {pattern} {
sl@0
   526
    global auto_index
sl@0
   527
sl@0
   528
    # If no namespace is specified, this will be an error case
sl@0
   529
sl@0
   530
    if {![string match *::* $pattern]} {
sl@0
   531
	return
sl@0
   532
    }
sl@0
   533
sl@0
   534
    set ns [uplevel 1 [list ::namespace current]]
sl@0
   535
    set patternList [auto_qualify $pattern $ns]
sl@0
   536
sl@0
   537
    auto_load_index
sl@0
   538
sl@0
   539
    foreach pattern $patternList {
sl@0
   540
        foreach name [array names auto_index $pattern] {
sl@0
   541
            if {([namespace which -command $name] eq "")
sl@0
   542
		    && ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
sl@0
   543
                namespace eval :: $auto_index($name)
sl@0
   544
            }
sl@0
   545
        }
sl@0
   546
    }
sl@0
   547
}
sl@0
   548
sl@0
   549
# auto_execok --
sl@0
   550
#
sl@0
   551
# Returns string that indicates name of program to execute if 
sl@0
   552
# name corresponds to a shell builtin or an executable in the
sl@0
   553
# Windows search path, or "" otherwise.  Builds an associative 
sl@0
   554
# array auto_execs that caches information about previous checks, 
sl@0
   555
# for speed.
sl@0
   556
#
sl@0
   557
# Arguments: 
sl@0
   558
# name -			Name of a command.
sl@0
   559
sl@0
   560
if {$tcl_platform(platform) eq "windows"} {
sl@0
   561
# Windows version.
sl@0
   562
#
sl@0
   563
# Note that info executable doesn't work under Windows, so we have to
sl@0
   564
# look for files with .exe, .com, or .bat extensions.  Also, the path
sl@0
   565
# may be in the Path or PATH environment variables, and path
sl@0
   566
# components are separated with semicolons, not colons as under Unix.
sl@0
   567
#
sl@0
   568
proc auto_execok name {
sl@0
   569
    global auto_execs env tcl_platform
sl@0
   570
sl@0
   571
    if {[info exists auto_execs($name)]} {
sl@0
   572
	return $auto_execs($name)
sl@0
   573
    }
sl@0
   574
    set auto_execs($name) ""
sl@0
   575
sl@0
   576
    set shellBuiltins [list cls copy date del erase dir echo mkdir \
sl@0
   577
	    md rename ren rmdir rd time type ver vol]
sl@0
   578
    if {$tcl_platform(os) eq "Windows NT"} {
sl@0
   579
	# NT includes the 'start' built-in
sl@0
   580
	lappend shellBuiltins "start"
sl@0
   581
    }
sl@0
   582
    if {[info exists env(PATHEXT)]} {
sl@0
   583
	# Add an initial ; to have the {} extension check first.
sl@0
   584
	set execExtensions [split ";$env(PATHEXT)" ";"]
sl@0
   585
    } else {
sl@0
   586
	set execExtensions [list {} .com .exe .bat]
sl@0
   587
    }
sl@0
   588
sl@0
   589
    if {[lsearch -exact $shellBuiltins $name] != -1} {
sl@0
   590
	# When this is command.com for some reason on Win2K, Tcl won't
sl@0
   591
	# exec it unless the case is right, which this corrects.  COMSPEC
sl@0
   592
	# may not point to a real file, so do the check.
sl@0
   593
	set cmd $env(COMSPEC)
sl@0
   594
	if {[file exists $cmd]} {
sl@0
   595
	    set cmd [file attributes $cmd -shortname]
sl@0
   596
	}
sl@0
   597
	return [set auto_execs($name) [list $cmd /c $name]]
sl@0
   598
    }
sl@0
   599
sl@0
   600
    if {[llength [file split $name]] != 1} {
sl@0
   601
	foreach ext $execExtensions {
sl@0
   602
	    set file ${name}${ext}
sl@0
   603
	    if {[file exists $file] && ![file isdirectory $file]} {
sl@0
   604
		return [set auto_execs($name) [list $file]]
sl@0
   605
	    }
sl@0
   606
	}
sl@0
   607
	return ""
sl@0
   608
    }
sl@0
   609
sl@0
   610
    set path "[file dirname [info nameof]];.;"
sl@0
   611
    if {[info exists env(WINDIR)]} {
sl@0
   612
	set windir $env(WINDIR) 
sl@0
   613
    }
sl@0
   614
    if {[info exists windir]} {
sl@0
   615
	if {$tcl_platform(os) eq "Windows NT"} {
sl@0
   616
	    append path "$windir/system32;"
sl@0
   617
	}
sl@0
   618
	append path "$windir/system;$windir;"
sl@0
   619
    }
sl@0
   620
sl@0
   621
    foreach var {PATH Path path} {
sl@0
   622
	if {[info exists env($var)]} {
sl@0
   623
	    append path ";$env($var)"
sl@0
   624
	}
sl@0
   625
    }
sl@0
   626
sl@0
   627
    foreach dir [split $path {;}] {
sl@0
   628
	# Skip already checked directories
sl@0
   629
	if {[info exists checked($dir)] || $dir eq {}} { continue }
sl@0
   630
	set checked($dir) {}
sl@0
   631
	foreach ext $execExtensions {
sl@0
   632
	    set file [file join $dir ${name}${ext}]
sl@0
   633
	    if {[file exists $file] && ![file isdirectory $file]} {
sl@0
   634
		return [set auto_execs($name) [list $file]]
sl@0
   635
	    }
sl@0
   636
	}
sl@0
   637
    }
sl@0
   638
    return ""
sl@0
   639
}
sl@0
   640
sl@0
   641
} else {
sl@0
   642
# Unix version.
sl@0
   643
#
sl@0
   644
proc auto_execok name {
sl@0
   645
    global auto_execs env
sl@0
   646
sl@0
   647
    if {[info exists auto_execs($name)]} {
sl@0
   648
	return $auto_execs($name)
sl@0
   649
    }
sl@0
   650
    set auto_execs($name) ""
sl@0
   651
    if {[llength [file split $name]] != 1} {
sl@0
   652
	if {[file executable $name] && ![file isdirectory $name]} {
sl@0
   653
	    set auto_execs($name) [list $name]
sl@0
   654
	}
sl@0
   655
	return $auto_execs($name)
sl@0
   656
    }
sl@0
   657
    foreach dir [split $env(PATH) :] {
sl@0
   658
	if {$dir eq ""} {
sl@0
   659
	    set dir .
sl@0
   660
	}
sl@0
   661
	set file [file join $dir $name]
sl@0
   662
	if {[file executable $file] && ![file isdirectory $file]} {
sl@0
   663
	    set auto_execs($name) [list $file]
sl@0
   664
	    return $auto_execs($name)
sl@0
   665
	}
sl@0
   666
    }
sl@0
   667
    return ""
sl@0
   668
}
sl@0
   669
sl@0
   670
}
sl@0
   671
sl@0
   672
# ::tcl::CopyDirectory --
sl@0
   673
#
sl@0
   674
# This procedure is called by Tcl's core when attempts to call the
sl@0
   675
# filesystem's copydirectory function fail.  The semantics of the call
sl@0
   676
# are that 'dest' does not yet exist, i.e. dest should become the exact
sl@0
   677
# image of src.  If dest does exist, we throw an error.  
sl@0
   678
# 
sl@0
   679
# Note that making changes to this procedure can change the results
sl@0
   680
# of running Tcl's tests.
sl@0
   681
#
sl@0
   682
# Arguments: 
sl@0
   683
# action -              "renaming" or "copying" 
sl@0
   684
# src -			source directory
sl@0
   685
# dest -		destination directory
sl@0
   686
proc tcl::CopyDirectory {action src dest} {
sl@0
   687
    set nsrc [file normalize $src]
sl@0
   688
    set ndest [file normalize $dest]
sl@0
   689
    if {$action eq "renaming"} {
sl@0
   690
	# Can't rename volumes.  We could give a more precise
sl@0
   691
	# error message here, but that would break the test suite.
sl@0
   692
	if {[lsearch -exact [file volumes] $nsrc] != -1} {
sl@0
   693
	    return -code error "error $action \"$src\" to\
sl@0
   694
	      \"$dest\": trying to rename a volume or move a directory\
sl@0
   695
	      into itself"
sl@0
   696
	}
sl@0
   697
    }
sl@0
   698
    if {[file exists $dest]} {
sl@0
   699
	if {$nsrc eq $ndest} {
sl@0
   700
	    return -code error "error $action \"$src\" to\
sl@0
   701
	      \"$dest\": trying to rename a volume or move a directory\
sl@0
   702
	      into itself"
sl@0
   703
	}
sl@0
   704
	if {$action eq "copying"} {
sl@0
   705
	    return -code error "error $action \"$src\" to\
sl@0
   706
	      \"$dest\": file already exists"
sl@0
   707
	} else {
sl@0
   708
	    # Depending on the platform, and on the current
sl@0
   709
	    # working directory, the directories '.', '..'
sl@0
   710
	    # can be returned in various combinations.  Anyway,
sl@0
   711
	    # if any other file is returned, we must signal an error.
sl@0
   712
	    set existing [glob -nocomplain -directory $dest * .*]
sl@0
   713
	    eval [linsert \
sl@0
   714
		    [glob -nocomplain -directory $dest -type hidden * .*] 0 \
sl@0
   715
		    lappend existing]
sl@0
   716
	    foreach s $existing {
sl@0
   717
		if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
sl@0
   718
		    return -code error "error $action \"$src\" to\
sl@0
   719
		      \"$dest\": file already exists"
sl@0
   720
		}
sl@0
   721
	    }
sl@0
   722
	}
sl@0
   723
    } else {
sl@0
   724
	if {[string first $nsrc $ndest] != -1} {
sl@0
   725
	    set srclen [expr {[llength [file split $nsrc]] -1}]
sl@0
   726
	    set ndest [lindex [file split $ndest] $srclen]
sl@0
   727
	    if {$ndest eq [file tail $nsrc]} {
sl@0
   728
		return -code error "error $action \"$src\" to\
sl@0
   729
		  \"$dest\": trying to rename a volume or move a directory\
sl@0
   730
		  into itself"
sl@0
   731
	    }
sl@0
   732
	}
sl@0
   733
	file mkdir $dest
sl@0
   734
    }
sl@0
   735
    # Have to be careful to capture both visible and hidden files.
sl@0
   736
    # We will also be more generous to the file system and not
sl@0
   737
    # assume the hidden and non-hidden lists are non-overlapping.
sl@0
   738
    # 
sl@0
   739
    # On Unix 'hidden' files begin with '.'.  On other platforms
sl@0
   740
    # or filesystems hidden files may have other interpretations.
sl@0
   741
    set filelist [concat [glob -nocomplain -directory $src *] \
sl@0
   742
      [glob -nocomplain -directory $src -types hidden *]]
sl@0
   743
    
sl@0
   744
    foreach s [lsort -unique $filelist] {
sl@0
   745
	if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
sl@0
   746
	    file copy $s [file join $dest [file tail $s]]
sl@0
   747
	}
sl@0
   748
    }
sl@0
   749
    return
sl@0
   750
}