Compare commits

...
Author SHA1 Message Date
cvs2fossil 69921d9a40 Created branch core-8-0-2-synthetic 1998-04-29 17:09:47 +00:00
14 changed files with 3853 additions and 1 deletions
-1
View File
@@ -540,7 +540,6 @@ Tcl_Finalize()
TclFinalizeCompExecEnv();
TclFinalizeEnvironment();
TclpFinalize();
firstExitPtr = NULL;
tclInExit = 0;
}
+65
View File
@@ -0,0 +1,65 @@
/*
* tclInitScript.h --
*
* This file contains Unix & Windows common init script
* It is not used on the Mac. (the mac init script is in tclMacInit.c)
*
* Copyright (c) 1998 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: %Z% $Id: tclInitScript.h,v 1.1 1998/06/27 22:11:40 welch Exp $
*/
/*
* The following string is the startup script executed in new
* interpreters. It looks on disk in (way too many) different directories
* for a script "init.tcl" that is compatible with this version
* of Tcl. The init.tcl script does all of the real work of
* initialization.
*/
static char initScript[] = "if {[info proc tclInit]==\"\"} {\n\
proc tclInit {} {\n\
global tcl_library tcl_version tcl_patchLevel errorInfo\n\
global tcl_pkgPath\n\
rename tclInit {}\n\
set errors {}\n\
set dirs {}\n\
if {[info exists env(TCL_LIBRARY)]} {\n\
lappend dirs $env(TCL_LIBRARY)\n\
}\n\
lappend dirs $tcl_library\n\
set parentDir [file dirname [file dirname [info nameofexecutable]]]\n\
lappend dirs [file join $parentDir lib/tcl$tcl_version]\n\
if {[string match {*[ab]*} $tcl_patchLevel]} {\n\
set lib tcl$tcl_patchLevel\n\
} else {\n\
set lib tcl$tcl_version\n\
}\n\
lappend dirs [file join [file dirname [file dirname [pwd]]] $lib/library]\n\
lappend dirs [file join [file dirname [pwd]] library]\n\
lappend dirs [file join [file dirname $parentDir] $lib/library]\n\
lappend dirs [file join $parentDir library]\n\
foreach i $dirs {\n\
set tcl_library $i\n\
set tclfile [file join $i init.tcl]\n\
if {[file exists $tclfile]} {\n\
if {![catch {uplevel #0 [list source $tclfile]} msg]} {\n\
lappend tcl_pkgPath [file dirname $i]\n\
return\n\
} else {\n\
append errors \"$tclfile: $msg\n$errorInfo\n\"\n\
}\n\
}\n\
}\n\
set msg \"Can't find a usable init.tcl in the following directories: \n\"\n\
append msg \" $dirs\n\n\"\n\
append msg \"$errors\n\n\"\n\
append msg \"This probably means that Tcl wasn't installed properly.\n\"\n\
error $msg\n\
}\n\
}\n\
tclInit";
+423
View File
@@ -0,0 +1,423 @@
/*
* tclResolve.c --
*
* Contains hooks for customized command/variable name resolution
* schemes. These hooks allow extensions like [incr Tcl] to add
* their own name resolution rules to the Tcl language. Rules can
* be applied to a particular namespace, to the interpreter as a
* whole, or both.
*
* Copyright (c) 1998 Lucent Technologies, Inc.
*
* Originally implemented by
* Michael J. McLennan
* Bell Labs Innovations for Lucent Technologies
* mmclennan@lucent.com
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: %Z% $Id: tclResolve.c,v 1.1 1998/06/28 21:41:31 welch Exp $
*/
#include "tclInt.h"
/*
* Declarations for procedures local to this file:
*/
static void BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr));
/*
*----------------------------------------------------------------------
*
* Tcl_AddInterpResolvers --
*
* Adds a set of command/variable resolution procedures to an
* interpreter. These procedures are consulted when commands
* are resolved in Tcl_FindCommand, and when variables are
* resolved in TclLookupVar and LookupCompiledLocal. Each
* namespace may also have its own set of resolution procedures
* which take precedence over those for the interpreter.
*
* When a name is resolved, it is handled as follows. First,
* the name is passed to the resolution procedures for the
* namespace. If not resolved, the name is passed to each of
* the resolution procedures added to the interpreter. Finally,
* if still not resolved, the name is handled using the default
* Tcl rules for name resolution.
*
* Results:
* Returns pointers to the current name resolution procedures
* in the cmdProcPtr, varProcPtr and compiledVarProcPtr
* arguments.
*
* Side effects:
* If a compiledVarProc is specified, this procedure bumps the
* compileEpoch for the interpreter, forcing all code to be
* recompiled. If a cmdProc is specified, this procedure bumps
* the cmdRefEpoch in all namespaces, forcing commands to be
* resolved again using the new rules.
*
*----------------------------------------------------------------------
*/
void
Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
Tcl_Interp *interp; /* Interpreter whose name resolution
* rules are being modified. */
char *name; /* Name of this resolution scheme. */
Tcl_ResolveCmdProc *cmdProc; /* New procedure for command
* resolution */
Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution
* at runtime */
Tcl_ResolveCompiledVarProc *compiledVarProc;
/* Procedure for variable resolution
* at compile time. */
{
Interp *iPtr = (Interp*)interp;
ResolverScheme *resPtr;
/*
* Since we're adding a new name resolution scheme, we must force
* all code to be recompiled to use the new scheme. If there
* are new compiled variable resolution rules, bump the compiler
* epoch to invalidate compiled code. If there are new command
* resolution rules, bump the cmdRefEpoch in all namespaces.
*/
if (compiledVarProc) {
iPtr->compileEpoch++;
}
if (cmdProc) {
BumpCmdRefEpochs(iPtr->globalNsPtr);
}
/*
* Look for an existing scheme with the given name. If found,
* then replace its rules.
*/
for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
resPtr->cmdResProc = cmdProc;
resPtr->varResProc = varProc;
resPtr->compiledVarResProc = compiledVarProc;
return;
}
}
/*
* Otherwise, this is a new scheme. Add it to the FRONT
* of the linked list, so that it overrides existing schemes.
*/
resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme));
resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1));
strcpy(resPtr->name, name);
resPtr->cmdResProc = cmdProc;
resPtr->varResProc = varProc;
resPtr->compiledVarResProc = compiledVarProc;
resPtr->nextPtr = iPtr->resolverPtr;
iPtr->resolverPtr = resPtr;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetInterpResolvers --
*
* Looks for a set of command/variable resolution procedures with
* the given name in an interpreter. These procedures are
* registered by calling Tcl_AddInterpResolvers.
*
* Results:
* If the name is recognized, this procedure returns non-zero,
* along with pointers to the name resolution procedures in
* the Tcl_ResolverInfo structure. If the name is not recognized,
* this procedure returns zero.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
Tcl_GetInterpResolvers(interp, name, resInfoPtr)
Tcl_Interp *interp; /* Interpreter whose name resolution
* rules are being queried. */
char *name; /* Look for a scheme with this name. */
Tcl_ResolverInfo *resInfoPtr; /* Returns pointers to the procedures,
* if found */
{
Interp *iPtr = (Interp*)interp;
ResolverScheme *resPtr;
/*
* Look for an existing scheme with the given name. If found,
* then return pointers to its procedures.
*/
for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
resInfoPtr->cmdResProc = resPtr->cmdResProc;
resInfoPtr->varResProc = resPtr->varResProc;
resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc;
return 1;
}
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* Tcl_RemoveInterpResolvers --
*
* Removes a set of command/variable resolution procedures
* previously added by Tcl_AddInterpResolvers. The next time
* a command/variable name is resolved, these procedures
* won't be consulted.
*
* Results:
* Returns non-zero if the name was recognized and the
* resolution scheme was deleted. Returns zero otherwise.
*
* Side effects:
* If a scheme with a compiledVarProc was deleted, this procedure
* bumps the compileEpoch for the interpreter, forcing all code
* to be recompiled. If a scheme with a cmdProc was deleted,
* this procedure bumps the cmdRefEpoch in all namespaces,
* forcing commands to be resolved again using the new rules.
*
*----------------------------------------------------------------------
*/
int
Tcl_RemoveInterpResolvers(interp, name)
Tcl_Interp *interp; /* Interpreter whose name resolution
* rules are being modified. */
char *name; /* Name of the scheme to be removed. */
{
Interp *iPtr = (Interp*)interp;
ResolverScheme **prevPtrPtr, *resPtr;
/*
* Look for an existing scheme with the given name.
*/
prevPtrPtr = &iPtr->resolverPtr;
for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
break;
}
prevPtrPtr = &resPtr->nextPtr;
}
/*
* If we found the scheme, delete it.
*/
if (resPtr) {
/*
* If we're deleting a scheme with compiled variable resolution
* rules, bump the compiler epoch to invalidate compiled code.
* If we're deleting a scheme with command resolution rules,
* bump the cmdRefEpoch in all namespaces.
*/
if (resPtr->compiledVarResProc) {
iPtr->compileEpoch++;
}
if (resPtr->cmdResProc) {
BumpCmdRefEpochs(iPtr->globalNsPtr);
}
*prevPtrPtr = resPtr->nextPtr;
ckfree(resPtr->name);
ckfree((char *) resPtr);
return 1;
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* BumpCmdRefEpochs --
*
* This procedure is used to bump the cmdRefEpoch counters in
* the specified namespace and all of its child namespaces.
* It is used whenever name resolution schemes are added/removed
* from an interpreter, to invalidate all command references.
*
* Results:
* None.
*
* Side effects:
* Bumps the cmdRefEpoch in the specified namespace and its
* children, recursively.
*
*----------------------------------------------------------------------
*/
static void
BumpCmdRefEpochs(nsPtr)
Namespace *nsPtr; /* Namespace being modified. */
{
Tcl_HashEntry *entry;
Tcl_HashSearch search;
Namespace *childNsPtr;
nsPtr->cmdRefEpoch++;
for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
entry != NULL;
entry = Tcl_NextHashEntry(&search)) {
childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
BumpCmdRefEpochs(childNsPtr);
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_SetNamespaceResolvers --
*
* Sets the command/variable resolution procedures for a namespace,
* thereby changing the way that command/variable names are
* interpreted. This allows extension writers to support different
* name resolution schemes, such as those for object-oriented
* packages.
*
* Command resolution is handled by a procedure of the following
* type:
*
* typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((
* Tcl_Interp* interp, char* name, Tcl_Namespace *context,
* int flags, Tcl_Command *rPtr));
*
* Whenever a command is executed or Tcl_FindCommand is invoked
* within the namespace, this procedure is called to resolve the
* command name. If this procedure is able to resolve the name,
* it should return the status code TCL_OK, along with the
* corresponding Tcl_Command in the rPtr argument. Otherwise,
* the procedure can return TCL_CONTINUE, and the command will
* be treated under the usual name resolution rules. Or, it can
* return TCL_ERROR, and the command will be considered invalid.
*
* Variable resolution is handled by two procedures. The first
* is called whenever a variable needs to be resolved at compile
* time:
*
* typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
* Tcl_Interp* interp, char* name, Tcl_Namespace *context,
* Tcl_ResolvedVarInfo *rPtr));
*
* If this procedure is able to resolve the name, it should return
* the status code TCL_OK, along with variable resolution info in
* the rPtr argument; this info will be used to set up compiled
* locals in the call frame at runtime. The procedure may also
* return TCL_CONTINUE, and the variable will be treated under
* the usual name resolution rules. Or, it can return TCL_ERROR,
* and the variable will be considered invalid.
*
* Another procedure is used whenever a variable needs to be
* resolved at runtime but it is not recognized as a compiled local.
* (For example, the variable may be requested via
* Tcl_FindNamespaceVar.) This procedure has the following type:
*
* typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
* Tcl_Interp* interp, char* name, Tcl_Namespace *context,
* int flags, Tcl_Var *rPtr));
*
* This procedure is quite similar to the compile-time version.
* It returns the same status codes, but if variable resolution
* succeeds, this procedure returns a Tcl_Var directly via the
* rPtr argument.
*
* Results:
* Nothing.
*
* Side effects:
* Bumps the command epoch counter for the namespace, invalidating
* all command references in that namespace. Also bumps the
* resolver epoch counter for the namespace, forcing all code
* in the namespace to be recompiled.
*
*----------------------------------------------------------------------
*/
void
Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules
* are being modified. */
Tcl_ResolveCmdProc *cmdProc; /* Procedure for command resolution */
Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution
* at runtime */
Tcl_ResolveCompiledVarProc *compiledVarProc;
/* Procedure for variable resolution
* at compile time. */
{
Namespace *nsPtr = (Namespace*)namespacePtr;
/*
* Plug in the new command resolver, and bump the epoch counters
* so that all code will have to be recompiled and all commands
* will have to be resolved again using the new policy.
*/
nsPtr->cmdResProc = cmdProc;
nsPtr->varResProc = varProc;
nsPtr->compiledVarResProc = compiledVarProc;
nsPtr->cmdRefEpoch++;
nsPtr->resolverEpoch++;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetNamespaceResolvers --
*
* Returns the current command/variable resolution procedures
* for a namespace. By default, these procedures are NULL.
* New procedures can be installed by calling
* Tcl_SetNamespaceResolvers, to provide new name resolution
* rules.
*
* Results:
* Returns non-zero if any name resolution procedures have been
* assigned to this namespace; also returns pointers to the
* procedures in the Tcl_ResolverInfo structure. Returns zero
* otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr)
Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules
* are being modified. */
Tcl_ResolverInfo *resInfoPtr; /* Returns: pointers for all
* name resolution procedures
* assigned to this namespace. */
{
Namespace *nsPtr = (Namespace*)namespacePtr;
resInfoPtr->cmdResProc = nsPtr->cmdResProc;
resInfoPtr->varResProc = nsPtr->varResProc;
resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc;
if (nsPtr->cmdResProc != NULL ||
nsPtr->varResProc != NULL ||
nsPtr->compiledVarResProc != NULL) {
return 1;
}
return 0;
}
File diff suppressed because it is too large Load Diff
+52
View File
@@ -0,0 +1,52 @@
# Test file for:
# auto_mkindex
#
# This file provides example cases for testing the Tcl autoloading
# facility. Things are much more complicated with namespaces and classes.
# The "auto_mkindex" facility can no longer be built on top of a simple
# regular expression parser. It must recognize constructs like this:
#
# namespace eval foo {
# proc test {x y} { ... }
# namespace eval bar {
# proc another {args} { ... }
# }
# }
#
# Note that procedures and itcl class definitions can be nested inside
# of namespaces.
#
# Copyright (c) 1993-1998 Lucent Technologies, Inc.
# This shouldn't cause any problems
namespace import -force blt::*
# Should be able to handle "proc" definitions, even if they are
# preceded by white space.
proc normal {x y} {return [expr $x+$y]}
proc indented {x y} {return [expr $x+$y]}
#
# Should be able to handle proc declarations within namespaces,
# even if they have explicit namespace paths.
#
namespace eval buried {
proc inside {args} {return "inside: $args"}
namespace export pub_*
proc pub_one {args} {return "one: $args"}
proc pub_two {args} {return "two: $args"}
}
proc buried::within {args} {return "within: $args"}
namespace eval buried {
namespace eval under {
proc neath {args} {return "neath: $args"}
}
namespace eval ::buried {
proc relative {args} {return "relative: $args"}
proc ::top {args} {return "top: $args"}
proc ::buried::explicit {args} {return "explicit: $args"}
}
}
+55
View File
@@ -0,0 +1,55 @@
# Commands covered: auto_mkindex auto_import
#
# This file contains tests related to autoloading and generating
# the autoloading index.
#
# Copyright (c) 1998 Lucent Technologies, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: $Id: autoMkindex.test,v 1.1 1998/07/24 14:31:08 welch Exp $
if {[string compare test [info procs test]] == 1} then {source defs}
test autoMkindex-1.1 {remove any existing tclIndex file} {
file delete tclIndex
file exists tclIndex
} {0}
test autoMkindex-1.2 {build tclIndex based on a test file} {
auto_mkindex . autoMkindex.tcl
file exists tclIndex
} {1}
set element "{source [file join . autoMkindex.tcl]}"
test autoMkindex-1.3 {examine tclIndex} {
namespace eval tcl_autoMkindex_tmp {
set dir "."
variable auto_index
source tclIndex
set result ""
foreach elem [lsort [array names auto_index]] {
lappend result [list $elem $auto_index($elem)]
}
set result
}
} "{::buried::explicit $element} {::buried::inside $element} {::buried::pub_one $element} {::buried::pub_two $element} {::buried::relative $element} {::buried::under::neath $element} {::buried::within $element} {indented $element} {normal $element} {top $element}"
namespace delete tcl_autoMkindex_tmp
test autoMkindex-2.1 {commands on the autoload path can be imported} {
set interp [interp create]
set final [$interp eval {
namespace eval blt {}
set auto_path [linsert $auto_path 0 .]
set info [list [catch {namespace import buried::*} result] $result]
foreach name [lsort [info commands pub_*]] {
lappend info $name [namespace origin $name]
}
set info
}]
interp delete $interp
set final
} "0 {} pub_one ::buried::pub_one pub_two ::buried::pub_two"
+100
View File
@@ -0,0 +1,100 @@
# This file (iOUtil.test) tests the hookable TclStat(), @@@TclAccess(),
# and @@@Tcl_OpenFileChannel, routines in the file generic/tclIOUtils.c.
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1998 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: %Z% $Id: ioUtil.test,v 1.1 1998/06/04 12:44:44 suresh Exp $
if {[string compare test [info procs test]] == 1} then {source defs}
set unsetScript {
catch {unset testStat1(size)}
catch {unset testStat2(size)}
catch {unset testStat3(size)}
}
test stat-1.1 {TclStat: Check that none of the test procs are there.} {
catch {file stat testTclStat1%.fil testStat1} err1
catch {file stat testTclStat2%.fil testStat2} err2
catch {file stat testTclStat3%.fil testStat3} err3
list $err1 $err2 $err3
} {{couldn't stat "testTclStat1%.fil": no such file or directory} {couldn't stat "testTclStat2%.fil": no such file or directory} {couldn't stat "testTclStat3%.fil": no such file or directory}}
test stat-1.2 {TclStatInsertProc: Insert the 3 test TclStat_ procedures.} {
catch {testTclStat insert TclpStat} err1
testTclStat insert TestTclStatProc1
testTclStat insert TestTclStatProc2
testTclStat insert TestTclStatProc3
set err1
} {bad arg "insert": must be TestTclStatProc1, TestTclStatProc2, or TestTclStatProc3}
test stat-1.3 {TclStat: Use "file stat ?" to invoke each procedure.} {
file stat testTclStat2%.fil testStat2
file stat testTclStat1%.fil testStat1
file stat testTclStat3%.fil testStat3
list $testStat2(size) $testStat1(size) $testStat3(size)
} {2345 1234 3456}
eval $unsetScript
test stat-1.4 {TclStatDeleteProc: "TclpStat" function should not be deletedable.} {
catch {testTclStat delete TclpStat} err2
set err2
} {"TclpStat": could not be deleteed}
test stat-1.5 {TclStatDeleteProc: Delete the 2nd TclStat procedure.} {
# Delete the 2nd procedure and test that it longer exists but that
# the others do actually return a result.
testTclStat delete TestTclStatProc2
file stat testTclStat1%.fil testStat1
catch {file stat testTclStat2%.fil testStat2} err3
file stat testTclStat3%.fil testStat3
list $testStat1(size) $err3 $testStat3(size)
} {1234 {couldn't stat "testTclStat2%.fil": no such file or directory} 3456}
eval $unsetScript
test stat-1.6 {TclStatDeleteProc: Delete the 1st TclStat procedure.} {
# Next delete the 1st procedure and test that only the 3rd procedure
# is the only one that exists.
testTclStat delete TestTclStatProc1
catch {file stat testTclStat1%.fil testStat1} err4
catch {file stat testTclStat2%.fil testStat2} err5
file stat testTclStat3%.fil testStat3
list $err4 $err5 $testStat3(size)
} {{couldn't stat "testTclStat1%.fil": no such file or directory} {couldn't stat "testTclStat2%.fil": no such file or directory} 3456}
eval $unsetScript
test stat-1.7 {TclStatDeleteProc: Delete the 3rd procedure & verify all are gone.} {
# Finally delete the 3rd procedure and check that none of the
# procedures exist.
testTclStat delete TestTclStatProc3
catch {file stat testTclStat1%.fil testStat1} err6
catch {file stat testTclStat2%.fil testStat2} err7
catch {file stat testTclStat3%.fil testStat3} err8
list $err6 $err7 $err8
} {{couldn't stat "testTclStat1%.fil": no such file or directory} {couldn't stat "testTclStat2%.fil": no such file or directory} {couldn't stat "testTclStat3%.fil": no such file or directory}}
eval $unsetScript
test stat-1.8 {TclStatDeleteProc: Verify that all procs have been deleted.} {
# Attempt to delete all the Stat procs. again to ensure they no longer
# exist and an error is returned.
catch {testTclStat delete TestTclStatProc1} err9
catch {testTclStat delete TestTclStatProc2} err10
catch {testTclStat delete TestTclStatProc3} err11
list $err9 $err10 $err11
} {{"TestTclStatProc1": could not be deleteed} {"TestTclStatProc2": could not be deleteed} {"TestTclStatProc3": could not be deleteed}}
eval $unsetScript
+161
View File
@@ -0,0 +1,161 @@
# This file contains Tcl code to implement a remote server that can be
# used during testing of Tcl socket code. This server is used by some
# of the tests in socket.test.
#
# Source this file in the remote server you are using to test Tcl against.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# @(#) remote.tcl 1.5 96/04/17 08:21:19"
# Initialize message delimitor
# Initialize command array
catch {unset command}
set command(0) ""
set callerSocket ""
# Detect whether we should print out connection messages etc.
if {![info exists VERBOSE]} {
set VERBOSE 0
}
proc __doCommands__ {l s} {
global callerSocket VERBOSE
if {$VERBOSE} {
puts "--- Server executing the following for socket $s:"
puts $l
puts "---"
}
set callerSocket $s
if {[catch {uplevel #0 $l} msg]} {
list error $msg
} else {
list success $msg
}
}
proc __readAndExecute__ {s} {
global command VERBOSE
set l [gets $s]
if {[string compare $l "--Marker--Marker--Marker--"] == 0} {
if {[info exists command($s)]} {
puts $s [list error incomplete_command]
}
puts $s "--Marker--Marker--Marker--"
return
}
if {[string compare $l ""] == 0} {
if {[eof $s]} {
if {$VERBOSE} {
puts "Server closing $s, eof from client"
}
close $s
}
return
}
append command($s) $l "\n"
if {[info complete $command($s)]} {
set cmds $command($s)
unset command($s)
puts $s [__doCommands__ $cmds $s]
}
if {[eof $s]} {
if {$VERBOSE} {
puts "Server closing $s, eof from client"
}
close $s
}
}
proc __accept__ {s a p} {
global VERBOSE
if {$VERBOSE} {
puts "Server accepts new connection from $a:$p on $s"
}
fileevent $s readable [list __readAndExecute__ $s]
fconfigure $s -buffering line -translation crlf
}
set serverIsSilent 0
for {set i 0} {$i < $argc} {incr i} {
if {[string compare -serverIsSilent [lindex $argv $i]] == 0} {
set serverIsSilent 1
break
}
}
if {![info exists serverPort]} {
if {[info exists env(serverPort)]} {
set serverPort $env(serverPort)
}
}
if {![info exists serverPort]} {
for {set i 0} {$i < $argc} {incr i} {
if {[string compare -port [lindex $argv $i]] == 0} {
if {$i < [expr $argc - 1]} {
set serverPort [lindex $argv [expr $i + 1]]
}
break
}
}
}
if {![info exists serverPort]} {
set serverPort 2048
}
if {![info exists serverAddress]} {
if {[info exists env(serverAddress)]} {
set serverAddress $env(serverAddress)
}
}
if {![info exists serverAddress]} {
for {set i 0} {$i < $argc} {incr i} {
if {[string compare -address [lindex $argv $i]] == 0} {
if {$i < [expr $argc - 1]} {
set serverAddress [lindex $argv [expr $i + 1]]
}
break
}
}
}
if {![info exists serverAddress]} {
set serverAddress 0.0.0.0
}
if {$serverIsSilent == 0} {
set l "Remote server listening on port $serverPort, IP $serverAddress."
puts ""
puts $l
for {set c [string length $l]} {$c > 0} {incr c -1} {puts -nonewline "-"}
puts ""
puts ""
puts "You have set the Tcl variables serverAddress to $serverAddress and"
puts "serverPort to $serverPort. You can set these with the -address and"
puts "-port command line options, or as environment variables in your"
puts "shell."
puts ""
puts "NOTE: The tests will not work properly if serverAddress is set to"
puts "\"localhost\" or 127.0.0.1."
puts ""
puts "When you invoke tcltest to run the tests, set the variables"
puts "remoteServerPort to $serverPort and remoteServerIP to"
puts "[info hostname]. You can set these as environment variables"
puts "from the shell. The tests will not work properly if you set"
puts "remoteServerIP to \"localhost\" or 127.0.0.1."
puts ""
puts -nonewline "Type Ctrl-C to terminate--> "
flush stdout
}
if {[catch {set serverSocket \
[socket -myaddr $serverAddress -server __accept__ $serverPort]} msg]} {
puts "Server on $serverAddress:$serverPort cannot start: $msg"
} else {
vwait __server_wait_variable__
}
+66
View File
@@ -0,0 +1,66 @@
# This file contains tests for the routines in the file tclUnixFile.c
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1998 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# SCCS: %Z% $Id: unixFile.test,v 1.1 1998/06/17 18:16:41 stanton Exp $
if {[string compare test [info procs test]] == 1} then {source defs}
if {[info commands testobj] == {}} {
puts "This application hasn't been compiled with the \"testfindexecutable\""
puts "command, so I can't test the Tcl_FindExecutable function"
return
}
if {$tcl_platform(platform) != "unix"} {
return
}
set oldPath $env(PATH)
close [open junk w]
file attributes junk -perm 0777
set absPath [file join [pwd] junk]
test unixFile-1.1 {Tcl_FindExecutable} {
set env(PATH) ""
testfindexecutable junk
} $absPath
test unixFile-1.2 {Tcl_FindExecutable} {
set env(PATH) "/dummy"
testfindexecutable junk
} {}
test unixFile-1.3 {Tcl_FindExecutable} {
set env(PATH) "/dummy:[pwd]"
testfindexecutable junk
} $absPath
test unixFile-1.4 {Tcl_FindExecutable} {
set env(PATH) "/dummy:"
testfindexecutable junk
} $absPath
test unixFile-1.5 {Tcl_FindExecutable} {
set env(PATH) "/dummy:/dummy"
testfindexecutable junk
} {}
test unixFile-1.6 {Tcl_FindExecutable} {
set env(PATH) "/dummy::/dummy"
testfindexecutable junk
} $absPath
test unixFile-1.7 {Tcl_FindExecutable} {
set env(PATH) ":/dummy"
testfindexecutable junk
} $absPath
set env(PATH) $oldPath
file delete junk
+71
View File
@@ -0,0 +1,71 @@
#!/bin/sh
# mkLinks.tcl --
# This generates the mkLinks script
# \
exec tclsh "$0" ${1+"$@"}
puts stdout \
{#!/bin/sh
# This script is invoked when installing manual entries. It generates
# additional links to manual entries, corresponding to the procedure
# and command names described by the manual entry. For example, the
# Tcl manual entry Hash.3 describes procedures Tcl_InitHashTable,
# Tcl_CreateHashEntry, and many more. This script will make hard
# links so that Tcl_InitHashTable.3, Tcl_CreateHashEntry.3, and so
# on all refer to Hash.3 in the installed directory.
#
# Because of the length of command and procedure names, this mechanism
# only works on machines that support file names longer than 14 characters.
# This script checks to see if long file names are supported, and it
# doesn't make any links if they are not.
#
# The script takes one argument, which is the name of the directory
# where the manual entries have been installed.
if test $# != 1; then
echo "Usage: mkLinks dir"
exit 1
fi
cd $1
echo foo > xyzzyTestingAVeryLongFileName.foo
x=`echo xyzzyTe*`
rm xyzzyTe*
if test "$x" != "xyzzyTestingAVeryLongFileName.foo"; then
exit
fi
}
foreach file $argv {
set in [open $file]
set tail [file tail $file]
set ext [file extension $file]
set state begin
while {[gets $in line] >= 0} {
switch $state {
begin {
if {[regexp "^.SH NAME" $line]} {
set state name
}
}
name {
regsub {\\-.*} $line {} line
foreach name [split $line ,] {
regsub -all { } $name "" name
if {[string compare $tail $name$ext] != 0} {
puts "if test -r $tail; then"
puts " rm -f $name$ext"
puts " ln $tail $name$ext"
puts "fi"
}
}
set state end
}
end {
break
}
}
}
close $in
}
puts "exit 0"
+656
View File
@@ -0,0 +1,656 @@
/*
* tclXtNotify.c --
*
* This file contains the notifier driver implementation for the
* Xt intrinsics.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tclXtNotify.c 1.10 97/09/15 13:24:21
*/
#include <X11/Intrinsic.h>
#include <tclInt.h>
/*
* This structure is used to keep track of the notifier info for a
* a registered file.
*/
typedef struct FileHandler {
int fd;
int mask; /* Mask of desired events: TCL_READABLE, etc. */
int readyMask; /* Events that have been seen since the
last time FileHandlerEventProc was called
for this file. */
XtInputId read; /* Xt read callback handle. */
XtInputId write; /* Xt write callback handle. */
XtInputId except; /* Xt exception callback handle. */
Tcl_FileProc *proc; /* Procedure to call, in the style of
* Tcl_CreateFileHandler. */
ClientData clientData; /* Argument to pass to proc. */
struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;
/*
* The following structure is what is added to the Tcl event queue when
* file handlers are ready to fire.
*/
typedef struct FileHandlerEvent {
Tcl_Event header; /* Information that is standard for
* all events. */
int fd; /* File descriptor that is ready. Used
* to find the FileHandler structure for
* the file (can't point directly to the
* FileHandler structure because it could
* go away while the event is queued). */
} FileHandlerEvent;
/*
* The following static structure contains the state information for the
* Xt based implementation of the Tcl notifier.
*/
static struct NotifierState {
XtAppContext appContext; /* The context used by the Xt
* notifier. Can be set with
* TclSetAppContext. */
int appContextCreated; /* Was it created by us? */
XtIntervalId currentTimeout; /* Handle of current timer. */
FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler
* list. */
} notifier;
/*
* The following static indicates whether this module has been initialized.
*/
static int initialized = 0;
/*
* Static routines defined in this file.
*/
static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
int flags));
static void FileProc _ANSI_ARGS_((caddr_t clientData,
int *source, XtInputId *id));
static void InitNotifier _ANSI_ARGS_((void));
static void NotifierExitHandler _ANSI_ARGS_((
ClientData clientData));
static void TimerProc _ANSI_ARGS_((caddr_t clientData,
XtIntervalId *id));
/*
* Functions defined in this file for use by users of the Xt Notifier:
*/
EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx));
/*
*----------------------------------------------------------------------
*
* TclSetAppContext --
*
* Set the notifier application context.
*
* Results:
* None.
*
* Side effects:
* Sets the application context used by the notifier. Panics if
* the context is already set when called.
*
*----------------------------------------------------------------------
*/
XtAppContext
TclSetAppContext(appContext)
XtAppContext appContext;
{
if (!initialized) {
InitNotifier();
}
/*
* If we already have a context we check whether we were asked to set a
* new context. If so, we panic because we try to prevent switching
* contexts by mistake. Otherwise, we return the one we have.
*/
if (notifier.appContext != NULL) {
if (appContext != NULL) {
/*
* We already have a context. We do not allow switching contexts
* after initialization, so we panic.
*/
panic("TclSetAppContext: multiple application contexts");
}
} else {
/*
* If we get here we have not yet gotten a context, so either create
* one or use the one supplied by our caller.
*/
if (appContext == NULL) {
/*
* We must create a new context and tell our caller what it is, so
* she can use it too.
*/
notifier.appContext = XtCreateApplicationContext();
notifier.appContextCreated = 1;
} else {
/*
* Otherwise we remember the context that our caller gave us
* and use it.
*/
notifier.appContextCreated = 0;
notifier.appContext = appContext;
}
}
return notifier.appContext;
}
/*
*----------------------------------------------------------------------
*
* InitNotifier --
*
* Initializes the notifier state.
*
* Results:
* None.
*
* Side effects:
* Creates a new exit handler.
*
*----------------------------------------------------------------------
*/
static void
InitNotifier(void)
{
/*
* Only reinitialize if we are not in exit handling. The notifier
* can get reinitialized after its own exit handler has run, because
* of exit handlers for the I/O and timer sub-systems (order dependency).
*/
if (TclInExit()) {
return;
}
/*
* DO NOT create the application context yet; doing so would prevent
* external applications from setting it for us to their own ones.
*/
initialized = 1;
memset(&notifier, 0, sizeof(notifier));
Tcl_CreateExitHandler(NotifierExitHandler, NULL);
}
/*
*----------------------------------------------------------------------
*
* NotifierExitHandler --
*
* This function is called to cleanup the notifier state before
* Tcl is unloaded.
*
* Results:
* None.
*
* Side effects:
* Destroys the notifier window.
*
*----------------------------------------------------------------------
*/
static void
NotifierExitHandler(
ClientData clientData) /* Not used. */
{
if (notifier.currentTimeout != 0) {
XtRemoveTimeOut(notifier.currentTimeout);
}
for (; notifier.firstFileHandlerPtr != NULL; ) {
Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
}
if (notifier.appContextCreated) {
XtDestroyApplicationContext(notifier.appContext);
notifier.appContextCreated = 0;
notifier.appContext = NULL;
}
initialized = 0;
}
/*
*----------------------------------------------------------------------
*
* Tcl_SetTimer --
*
* This procedure sets the current notifier timeout value.
*
* Results:
* None.
*
* Side effects:
* Replaces any previous timer.
*
*----------------------------------------------------------------------
*/
void
Tcl_SetTimer(timePtr)
Tcl_Time *timePtr; /* Timeout value, may be NULL. */
{
long timeout;
if (!initialized) {
InitNotifier();
}
TclSetAppContext(NULL);
if (notifier.currentTimeout != 0) {
XtRemoveTimeOut(notifier.currentTimeout);
}
if (timePtr) {
timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
notifier.currentTimeout =
XtAppAddTimeOut(notifier.appContext, (unsigned long) timeout,
TimerProc, NULL);
} else {
notifier.currentTimeout = 0;
}
}
/*
*----------------------------------------------------------------------
*
* TimerProc --
*
* This procedure is the XtTimerCallbackProc used to handle
* timeouts.
*
* Results:
* None.
*
* Side effects:
* Processes all queued events.
*
*----------------------------------------------------------------------
*/
static void
TimerProc(data, id)
caddr_t data; /* Not used. */
XtIntervalId *id;
{
if (*id != notifier.currentTimeout) {
return;
}
notifier.currentTimeout = 0;
Tcl_ServiceAll();
}
/*
*----------------------------------------------------------------------
*
* Tcl_CreateFileHandler --
*
* This procedure registers a file handler with the Xt notifier.
*
* Results:
* None.
*
* Side effects:
* Creates a new file handler structure and registers one or more
* input procedures with Xt.
*
*----------------------------------------------------------------------
*/
void
Tcl_CreateFileHandler(fd, mask, proc, clientData)
int fd; /* Handle of stream to watch. */
int mask; /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION:
* indicates conditions under which
* proc should be called. */
Tcl_FileProc *proc; /* Procedure to call for each
* selected event. */
ClientData clientData; /* Arbitrary data to pass to proc. */
{
FileHandler *filePtr;
if (!initialized) {
InitNotifier();
}
TclSetAppContext(NULL);
for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->fd == fd) {
break;
}
}
if (filePtr == NULL) {
filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
filePtr->fd = fd;
filePtr->read = 0;
filePtr->write = 0;
filePtr->except = 0;
filePtr->readyMask = 0;
filePtr->mask = 0;
filePtr->nextPtr = notifier.firstFileHandlerPtr;
notifier.firstFileHandlerPtr = filePtr;
}
filePtr->proc = proc;
filePtr->clientData = clientData;
/*
* Register the file with the Xt notifier, if it hasn't been done yet.
*/
if (mask & TCL_READABLE) {
if (!(filePtr->mask & TCL_READABLE)) {
filePtr->read =
XtAppAddInput(notifier.appContext, fd, XtInputReadMask,
FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_READABLE) {
XtRemoveInput(filePtr->read);
}
}
if (mask & TCL_WRITABLE) {
if (!(filePtr->mask & TCL_WRITABLE)) {
filePtr->write =
XtAppAddInput(notifier.appContext, fd, XtInputWriteMask,
FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_WRITABLE) {
XtRemoveInput(filePtr->write);
}
}
if (mask & TCL_EXCEPTION) {
if (!(filePtr->mask & TCL_EXCEPTION)) {
filePtr->except =
XtAppAddInput(notifier.appContext, fd, XtInputExceptMask,
FileProc, filePtr);
}
} else {
if (filePtr->mask & TCL_EXCEPTION) {
XtRemoveInput(filePtr->except);
}
}
filePtr->mask = mask;
}
/*
*----------------------------------------------------------------------
*
* Tcl_DeleteFileHandler --
*
* Cancel a previously-arranged callback arrangement for
* a file.
*
* Results:
* None.
*
* Side effects:
* If a callback was previously registered on file, remove it.
*
*----------------------------------------------------------------------
*/
void
Tcl_DeleteFileHandler(fd)
int fd; /* Stream id for which to remove
* callback procedure. */
{
FileHandler *filePtr, *prevPtr;
if (!initialized) {
InitNotifier();
}
TclSetAppContext(NULL);
/*
* Find the entry for the given file (and return if there
* isn't one).
*/
for (prevPtr = NULL, filePtr = notifier.firstFileHandlerPtr; ;
prevPtr = filePtr, filePtr = filePtr->nextPtr) {
if (filePtr == NULL) {
return;
}
if (filePtr->fd == fd) {
break;
}
}
/*
* Clean up information in the callback record.
*/
if (prevPtr == NULL) {
notifier.firstFileHandlerPtr = filePtr->nextPtr;
} else {
prevPtr->nextPtr = filePtr->nextPtr;
}
if (filePtr->mask & TCL_READABLE) {
XtRemoveInput(filePtr->read);
}
if (filePtr->mask & TCL_WRITABLE) {
XtRemoveInput(filePtr->write);
}
if (filePtr->mask & TCL_EXCEPTION) {
XtRemoveInput(filePtr->except);
}
ckfree((char *) filePtr);
}
/*
*----------------------------------------------------------------------
*
* FileProc --
*
* These procedures are called by Xt when a file becomes readable,
* writable, or has an exception.
*
* Results:
* None.
*
* Side effects:
* Makes an entry on the Tcl event queue if the event is
* interesting.
*
*----------------------------------------------------------------------
*/
static void
FileProc(clientData, fd, id)
caddr_t clientData;
int *fd;
XtInputId *id;
{
FileHandler *filePtr = (FileHandler *)clientData;
FileHandlerEvent *fileEvPtr;
int mask = 0;
/*
* Determine which event happened.
*/
if (*id == filePtr->read) {
mask = TCL_READABLE;
} else if (*id == filePtr->write) {
mask = TCL_WRITABLE;
} else if (*id == filePtr->except) {
mask = TCL_EXCEPTION;
}
/*
* Ignore unwanted or duplicate events.
*/
if (!(filePtr->mask & mask) || (filePtr->readyMask & mask)) {
return;
}
/*
* This is an interesting event, so put it onto the event queue.
*/
filePtr->readyMask |= mask;
fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
/*
* Process events on the Tcl event queue before returning to Xt.
*/
Tcl_ServiceAll();
}
/*
*----------------------------------------------------------------------
*
* FileHandlerEventProc --
*
* This procedure is called by Tcl_ServiceEvent when a file event
* reaches the front of the event queue. This procedure is
* responsible for actually handling the event by invoking the
* callback for the file handler.
*
* Results:
* Returns 1 if the event was handled, meaning it should be removed
* from the queue. Returns 0 if the event was not handled, meaning
* it should stay on the queue. The only time the event isn't
* handled is if the TCL_FILE_EVENTS flag bit isn't set.
*
* Side effects:
* Whatever the file handler's callback procedure does.
*
*----------------------------------------------------------------------
*/
static int
FileHandlerEventProc(evPtr, flags)
Tcl_Event *evPtr; /* Event to service. */
int flags; /* Flags that indicate what events to
* handle, such as TCL_FILE_EVENTS. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
int mask;
if (!(flags & TCL_FILE_EVENTS)) {
return 0;
}
/*
* Search through the file handlers to find the one whose handle matches
* the event. We do this rather than keeping a pointer to the file
* handler directly in the event, so that the handler can be deleted
* while the event is queued without leaving a dangling pointer.
*/
for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->fd != fileEvPtr->fd) {
continue;
}
/*
* The code is tricky for two reasons:
* 1. The file handler's desired events could have changed
* since the time when the event was queued, so AND the
* ready mask with the desired mask.
* 2. The file could have been closed and re-opened since
* the time when the event was queued. This is why the
* ready mask is stored in the file handler rather than
* the queued event: it will be zeroed when a new
* file handler is created for the newly opened file.
*/
mask = filePtr->readyMask & filePtr->mask;
filePtr->readyMask = 0;
if (mask != 0) {
(*filePtr->proc)(filePtr->clientData, mask);
}
break;
}
return 1;
}
/*
*----------------------------------------------------------------------
*
* Tcl_WaitForEvent --
*
* This function is called by Tcl_DoOneEvent to wait for new
* events on the message queue. If the block time is 0, then
* Tcl_WaitForEvent just polls without blocking.
*
* Results:
* Returns 1 if an event was found, else 0. This ensures that
* Tcl_DoOneEvent will return 1, even if the event is handled
* by non-Tcl code.
*
* Side effects:
* Queues file events that are detected by the select.
*
*----------------------------------------------------------------------
*/
int
Tcl_WaitForEvent(
Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
int timeout;
if (!initialized) {
InitNotifier();
}
TclSetAppContext(NULL);
if (timePtr) {
timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
if (timeout == 0) {
if (XtAppPending(notifier.appContext)) {
goto process;
} else {
return 0;
}
} else {
Tcl_SetTimer(timePtr);
}
}
process:
XtAppProcessEvent(notifier.appContext, XtIMAll);
return 1;
}
+518
View File
@@ -0,0 +1,518 @@
Tcl/Tk 8.0.3 for Windows, Binary Distribution
%Z% $Id: README.binary,v 1.1 1998/08/31 16:31:53 stanton Exp $
1. Introduction
---------------
This directory contains the binary distribution of Tcl/Tk 8.0.3 for
Windows. It was compiled with Microsoft Visual C++ 5.0 using Win32
API, so that it will run under Windows NT and Windows 95. The
information here corresponds to release 8.0. This patch provides
compatibility with [incr Tcl] 3.0. Tcl 8.0 is a major new release
that replaces the core of the interpreter with an on-the-fly bytecode
compiler to improve execution speed. It also includes several other
new features such as namespaces and binary I/O, plus many bug fixes.
The compiler introduces a few incompatibilities that may affect
existing Tcl scripts; the incompatibilities are relatively obscure but
may require modifications to some old scripts before they can run with
this version. The compiler introduces many new C-level APIs, but the
old APIs are still supported. See below for more details. This patch
release fixes various bugs in Tcl 8.0, plus it adds a few minor
features to support the TclPro 1.0 tool set and [incr Tcl] 3.0.
Please check the changes file in the source release for details.
This release also corresponds to Tk 8.0.3. This is a major release with
significant new features such as native look and feel on Macintoshes
and PCs, a new font mechanism, application embedding, and proper
support for Safe-Tcl. See below for details. There should be no
backward incompatibilities in Tk 8.0.3 that affect scripts.
Note: with this release the Tk version number skips from 4.2 to 8.0.
The jump was made in order to synchronize the Tcl and Tk version
numbers.
2. Documentation
----------------
The best way to get started with Tcl is to read one of the introductory
books on Tcl:
Practical Programming in Tcl and Tk, 2nd Edition, by Brent Welch,
Prentice-Hall, 1997, ISBN 0-13-616830-2
Tcl and the Tk Toolkit, by John Ousterhout,
Addison-Wesley, 1994, ISBN 0-201-63337-X
Exploring Expect, by Don Libes,
O'Reilly and Associates, 1995, ISBN 1-56592-090-2
Other books are listed at
http://www.scriptics.com/resource/doc/books/
http://www.tclconsortium.org/resources/books.html
There is also an official home for Tcl and Tk on the Web:
http://www.scriptics.com
These Web pages include information about the latest releases, products
related to Tcl and Tk, reports on bug fixes and porting issues, HTML
versions of the manual pages, and pointers to many other Tcl/Tk Web
pages at other sites. Check them out!
3. Installation
---------------
The binary release is distributed as a self-extracting archive called
tcl80.exe. The setup program which will prompt you for an
installation directory. It will create the installation heirarchy
under the specified directory, and install a wish application icon
under the program manager group of your choice.
With the 8.0.3 patch release, we are no longer supporting use of
Tcl with 16-bit versions of Windows. Microsoft has completely dropped
support of the Win32s subsystem. If you still need 16-bit support,
you can get win32s and the 16-bit thunking dll (tcl1680.dll) from the
Scriptics web site at ftp://ftp.scriptics.com/pub/tcl/misc.
4. Summary of changes in Tcl 8.0
--------------------------------
Here are the most significant changes in Tcl 8.0. In addition to these
changes, there are several smaller changes and bug fixes. See the file
"changes" for a complete list of all changes.
1. Bytecode compiler. The core of the Tcl interpreter has been
replaced with an on-the-fly compiler that translates Tcl scripts to
byte codes; a new interpreter then executes the byte codes. In
earlier versions of Tcl, strings were used as a universal
representation; in Tcl 8.0 strings are replaced with Tcl_Obj
structures ("objects") that can hold both a string value and an
internal form such as a binary integer or compiled bytecodes. The
new objects make it possible to store information in efficient
internal forms and avoid the constant translations to and from
strings that occurred with the old interpreter. We have not yet
converted all of Tcl to take full advantage of the compiler and
objects and have not converted any of Tk yet, but even so you
should see speedups of 2-3x on many programs and you may see
speedups as much as 10-20x in some cases (such as code that
manipulates long lists). Future releases should achieve even
greater speedups. The compiler introduces only a few minor changes
at the level of Tcl scripts, but it introduces many new C APIs for
managing objects. See, for example, the manual entries doc/*Obj*.3.
2. Namespaces. There is a new namespace mechanism based on the
namespace implementation by Michael McLennan of Lucent Technologies.
This includes new "namespace" and "variable" commands. There are
many new C APIs associated with namespaces, but they will not be
exported until Tcl 8.1. Note: the syntax of the namespace command
has been changed slightly since the b1 release. See the changes
file for details.
3. Binary I/O. The new object system in Tcl 8.0 supports binary
strings (internally, strings are counted in addition to being null
terminated). There is a new "binary" command for inserting and
extracting data to/from binary strings. Commands such as "puts",
"gets", and "read" commands now operate correctly on binary data.
There is a new variable tcl_platform(byteOrder) to identify the
native byte order for the current host.
4. Random numbers. The "expr" command now contains a random number
generator, which can be accessed via the "rand()" and "srand()" math
functions.
5. Safe-Tcl enhancements. There is a new "hidden command"
mechanism, implemented with the Tcl commands "interp hide", "interp
expose", "interp invokehidden", and "interp hidden" and the C APIs
Tcl_HideCommand and Tcl_ExposeCommand. There is now support for
loadable security policies, including new library procedures such as
tcl_safeCreateInterp.
6. There is a new package "registry" available under Windows for
accessing the Windows registry.
7. There is a new command "file attributes" for getting and setting
things like permissions and owner. There is also a new command
"file nativename" for getting back the platform-specific name for a
particular file.
8. There is a new "fcopy" command to copy data between channels.
This replaces and improves upon the not-so-secret unsupported old
command "unsupported0".
9. There is a new package "http" for doing GET, POST, and HEAD
requests via the HTTP/1.0 protocol. See the manual entry http.n
for details.
10. There are new library procedures for finding word breaks in
strings. See the manual entry library.n for details.
11. There are new C APIs Tcl_Finalize (for cleaning up before
unloading the Tcl DLL) and Tcl_Ungets for pushing bytes back into a
channel's input buffer.
12. Tcl now supports serial I/O devices on Windows and Unix, with a
new fconfigure -mode option. The Windows driver does not yet
support event-driven I/O.
13. The lsort command has new options -dictionary and -index. The
-index option allows for very rapid sorting based on an element
of a list.
14. The event notifier has been completely rewritten (again). It
should now allow Tcl to use an external event loop (like Motif's)
when it is embedded in other applications. No script-level
interfaces have changed, but many of the C APIs have.
Tcl 8.0 introduces the following incompatibilities that may affect Tcl
scripts that worked under Tcl 7.6 and earlier releases:
1. Variable and command names may not include the character sequence
"::" anymore: this sequence is now used as a namespace separator.
2. The semantics of some Tcl commands have been changed slightly to
maximize performance under the compiler. These incompatibilities
are documented on the Web so that we can keep the list up-to-date.
See the URL http://www.sunlabs.com/research/tcl/compiler.html.
3. 2-digit years are now parsed differently by the "clock" command
to handle year 2000 issues better (years 00-38 are treated as
2000-2038 instead of 1900-1938).
4. The old Macintosh commands "cp", "mkdir", "mv", "rm", and "rmdir"
are no longer supported; all of these features are now available on
all platforms via the "file" command.
5. The variable tcl_precision is now shared between interpreters
and defaults to 12 digits instead of 6; safe interpreters cannot
modify tcl_precision. The new object system in Tcl 8.0 causes
floating-to-string conversions (and the associated rounding) to
occur much less often than in Tcl 7.6, which can sometimes cause
behavioral changes.
6. The C APIs associated with the notifier have changed substantially.
7. The procedures Tcl_CreateModalTimeout and Tcl_DeleteModalTimeout
have been removed.
8. Tcl_CreateFileHandler and Tcl_DeleteFileHandler now take Unix
fd's and are only supported on the Unix platform. Please use the
Tcl_CreateChannelHandler interface instead.
9. The C APIs for creating channel drivers have changed as part of
the new notifier implementation. The Tcl_File interfaces have been
removed. Tcl_GetChannelFile has been replaced with
Tcl_GetChannelHandle. Tcl_MakeFileChannel now takes a platform-
specific file handle. Tcl_DriverGetOptionProc procedures now take
an additional interp argument.
5. Summary of changes in Tk 8.0
-------------------------------
Here is a list of the most important new features in Tk 8.0. The
release also includes several smaller feature changes and bug fixes.
See the "changes" file for a complete list of all changes.
1. Native look and feel. The widgets have been rewritten to provide
(nearly?) native look and feel on the Macintosh and PC. Many
widgets, including scrollbars, menus, and the button family, are
implemented with native platform widgets. Others, such as entries
and texts, have been modified to emulate native look and feel.
These changes are backwards compatible except that (a) some
configuration options are now ignored on some platforms and (b) you
must use the new menu mechanism described below to native look and
feel for menus.
2. There is a new interface for creating menus, where a menubar is
implemented as a menu widget instead of a frame containing menubuttons.
The -menu option for a toplevel is used to specify the name of the
menubar; the menu will be displayed *outside* the toplevel using
different mechanisms on each platform (e.g. on the Macintosh the menu
will appear at the top of the screen). See the menu demos in the
widget demo for examples. The old style of menu still works, but
does not provide native look and feel. Menus have several new
features:
- New "-columnbreak" and "-hideMargin" options make it possible
to create multi-column menus.
- It is now possible to manipulate the Apple and Help menus on
the Macintosh, and the system menu on Windows. It is also
possible to have a right justified Help menu on Unix.
- Menus now issue the virtual event <<MenuSelect>> whenever the
current item changes. Applications can use this to generate
help messages.
- There is a new "-direction" option for menubuttons, which
controls where the menu pops up revenues to the button.
3. The font mechanism in Tk has been completely reworked:
- Font names need not be nasty X LFDs: more intuitive names
like {Times 12 Bold} can also be used. See the manual entry
font.n for details.
- Font requests always succeed now. If the requested font is
not available, Tk finds the closest available font and uses
that one.
- Tk now supports named fonts whose precise attributes can be
changed dynamically. If a named font is changed, any widget
using that font updates itself to reflect the change.
- There is a new command "font" for creating named fonts and
querying various information about fonts.
- There are now officially supported C APIs for measuring and
displaying text. If you use these APIs now, your code will
automatically handle international text when internationalization
is added to Tk in a future release. See the manual entries
MeasureChar.3, TextLayout.3, and FontId.3.
- The old C procedures Tk_GetFontStruct, Tk_NameOfFontStruct,
and Tk_FreeFontStruct have been replaced with more portable
procedures Tk_GetFont, Tk_NameOfFont, and Tk_FreeFont.
4. Application embedding. It is now possible to embedded one Tcl/Tk
application inside another, using the -container option on frame
widgets and the -use option for toplevel widgets or on the command
line for wish. Embedding should be fully functional under Unix,
but the implementation is incomplete on the Macintosh and PC.
5. Tk now works correctly with Safe-Tcl: it can be loaded into
safe interpreters.
6. Text widgets now allow images to be embedded directly in the
text without using embedded windows. This is more efficient and
provides smoother scrolling.
7. Buttons have a new -default option for drawing default rings in
a platform-specific manner.
8. There is a new "gray75" bitmap, and the "gray25" bitmap is now
really 25% on (due to an ancient mistake, it had been only 12% on).
The Macintosh now supports native bitmaps, including new builtin
bitmaps "stop", "caution", and "note", plus the ability to use
bitmaps in the application's resource fork.
9. The "destroy" command now ignores windows that don't exist
instead of generating an error.
Tk 8.0 introduces the following incompatibilities that may affect Tcl/Tk
scripts that worked under Tk 4.2 and earlier releases:
1. Font specifications such as "Times 12" now interpret the size
as points, whereas it used to be pixels (this was actually a bug,
since the behavior was documented as points). To get pixels now,
use a negative size such as "Times -12".
2. The -transient option for menus is no longer supported. You can
achieve the same effect with the -type field.
3. In the canvas "coords" command, polygons now return only the
points that were explicitly specified when the polygon was created
(they used to return an extra point if the polygon wasn't originally
closed). Internally, polygons are still closed automatically for
purposes of display and hit detection; the extra point just isn't
returned by the "coords" command.
4. The photo image mechanism now uses Tcl_Channels instead of FILEs,
in order to make it portable. FILEs are no longer used anywhere
in Tk.
5. The procedures Tk_GetFontStruct, Tk_NameOfFontStruct,
and Tk_FreeFontStruct have been removed.
Note: the new compiler in Tcl 8.0 may also affect Tcl/Tk scripts; check
the Tcl documentation for information on incompatibilities introduced by
Tcl 8.0.
6. Known Bugs/Missing Features
------------------------------
- Blocking "after" commands (e.g. "after 3000") don't work on Win32s.
- Clock command fails to handle daylight savings time boundaries for
things like "last week".
- Background processes aren't properly detached on NT.
- File events only work on sockets.
- Pipes/files/console/serial ports don't support nonblocking I/O.
- The library cannot be used by two processes at the same time under
Win32s.
- There is no support for custom cursors/application icons. The core
set of X cursors is supported, although you cannot change their color.
- Stippling of arcs isn't implemented yet.
- Some "wm" functions don't map to Windows and aren't implemented;
others should map, but just aren't implemented. The worst offenders
are the icon manipulation routines.
- Under Win32s, you can only start one instance of Wish at a time.
- Color management on some displays doesn't work properly resulting in
Tk switching to monochrome mode.
- Tk seems to fail to draw anything on some Matrox Millenium cards.
- Send and winfo interps are not currently supported
- Printing does not work for images (e.g. GIF) on a canvas.
- Tk_dialog appears in the upper left corner. This is a symptom of a
larger problem with "wm geometry" when applied to unmapped or
iconified windows.
- Some keys don't work on international keyboards.
- Grabs do not affect native menus or the title bar.
- PPM images are using the wrong translation mode for writing to
files, resulting in CR/LF terminated PPM files.
- Tk crashes if the display depth changes while it is running. Tk
also doesn't consistently track changes in the system colors.
There may be more that we don't know about, so be sure to submit bug
reports when you run into problems. If you have comments or bug
reports for the Windows version of Tcl, please direct them to:
Scott Stanton
scott.stanton@eng.sun.com
or post them to the newsgroup comp.lang.tcl.
7. Tcl newsgroup
-----------------
There is a network news group "comp.lang.tcl" intended for the exchange
of information about Tcl, Tk, and related applications. Feel free to use
the newsgroup both for general information questions and for bug reports.
We read the newsgroup and will attempt to fix bugs and problems reported
to it.
When using comp.lang.tcl, please be sure that your e-mail return address
is correctly set in your postings. This allows people to respond directly
to you, rather than the entire newsgroup, for answers that are not of
general interest. A bad e-mail return address may prevent you from
getting answers to your questions. You may have to reconfigure your news
reading software to ensure that it is supplying valid e-mail addresses.
8. Tcl contributed archive
--------------------------
Many people have created exciting packages and applications based on Tcl
and/or Tk and made them freely available to the Tcl community. An archive
of these contributions is kept on the machine ftp.neosoft.com. You
can access the archive using anonymous FTP; the Tcl contributed archive is
in the directory "/pub/tcl". The archive also contains several FAQ
("frequently asked questions") documents that provide solutions to problems
that are commonly encountered by TCL newcomers.
9. Tcl Resource Center
----------------------
Visit http://www.scritics.com/resource/ to see an annotated index of
many Tcl resources available on the World Wide Web. This includes
papers, books, and FAQs, as well as extensions, applications, binary
releases, and patches. You can contribute patches by sending them
to <patches@scriptics.com>. You can also recommend more URLs for the
resource center using the forms labeled "Add a Resource".
10. Mailing lists
----------------
A couple of Mailing List have been set up to discuss Macintosh or
Windows related Tcl issues. In order to use these Mailing Lists you
must have access to the internet. To subscribe send a message to:
wintcl-request@tclconsortium.org
mactcl-request@tclconsortium.org
In the body of the message (the subject will be ignored) put:
subscribe mactcl Joe Blow
Replacing Joe Blow with your real name, of course. (Use wintcl
instead of mactcl if your interested in the Windows list.) If you
would just like to receive more information about the list without
subscribing put the line:
information mactcl
in the body instead (or wintcl).
10. Support and bug fixes
------------------------
We're very interested in receiving bug reports and suggestions for
improvements. We prefer that you send this information to the
comp.lang.tcl newsgroup rather than to any of us at Sun. We'll see
anything on comp.lang.tcl, and in addition someone else who reads
comp.lang.tcl may be able to offer a solution. The normal turn-around
time for bugs is 2-4 weeks. Enhancements may take longer and may not
happen at all unless there is widespread support for them (we're
trying to slow the rate at which Tcl turns into a kitchen sink). It's
very difficult to make incompatible changes to Tcl at this point, due
to the size of the installed base.
When reporting bugs, please provide a short tclsh script that we can
use to reproduce the bug. Make sure that the script runs with a
bare-bones tclsh and doesn't depend on any extensions or other
programs, particularly those that exist only at your site. Also,
please include three additional pieces of information with the
script:
(a) how do we use the script to make the problem happen (e.g.
what things do we click on, in what order)?
(b) what happens when you do these things (presumably this is
undesirable)?
(c) what did you expect to happen instead?
The Tcl community is too large for us to provide much individual
support for users. If you need help we suggest that you post questions
to comp.lang.tcl. We read the newsgroup and will attempt to answer
esoteric questions for which no-one else is likely to know the answer.
In addition, Tcl support and training are available commercially from
NeoSoft (info@neosoft.com), Computerized Processes Unlimited
(gwl@cpu.com), and Data Kinetics (education@dkl.com).
11. Tcl version numbers
----------------------
Each Tcl release is identified by two numbers separated by a dot, e.g.
6.7 or 7.0. If a new release contains changes that are likely to break
existing C code or Tcl scripts then the major release number increments
and the minor number resets to zero: 6.0, 7.0, etc. If a new release
contains only bug fixes and compatible changes, then the minor number
increments without changing the major number, e.g. 7.1, 7.2, etc. If
you have C code or Tcl scripts that work with release X.Y, then they
should also work with any release X.Z as long as Z > Y.
Alpha and beta releases have an additional suffix of the form b1 or b1.
For example, Tcl 7.0b1 is the first beta release of Tcl version 7.0,
Tcl 7.0b2 is the second beta release, and so on. A beta release is an
initial version of a new release, used to fix bugs and bad features before
declaring the release stable. An alpha release is like a beta release,
except it's likely to need even more work before it's "ready for prime
time". New releases are normally preceded by one or more alpha and beta
releases. We hope that lots of people will try out the alpha and beta
releases and report problems. We'll make new alpha/beta releases to fix
the problems, until eventually there is a beta release that appears to
be stable. Once this occurs we'll make the final release.
We can't promise to maintain compatibility among alpha and beta releases.
For example, release 7.1b2 may not be backward compatible with 7.1b1, even
though the final 7.1 release will be backward compatible with 7.0. This
allows us to change new features as we find problems during beta testing.
We'll try to minimize incompatibilities between beta releases, but if
a major problem turns up then we'll fix it even if it introduces an
incompatibility. Once the official release is made then there won't
be any more incompatibilities until the next release with a new major
version number.
Patch releases have a suffix such as p1 or p2. These releases contain
bug fixes only. A patch release (e.g Tcl 7.6p2) should be completely
compatible with the base release from which it is derived (e.g. Tcl
7.6), and you should normally use the highest available patch release.
As of 8.0.3, the patch releases use a second . instead of 'p'. So, the
8.0 release went to 8.0p1, 8.0p2, and 8.0.3. The alphas and betas will
still use the 'a' and 'b' letters in their tcl_patchLevel.
12. Linking against the binary release
--------------------------------------
In order to link your applications against the .dll files shipped with
this release, you will need to use the appropriate .lib file for your
compiler. In the lib directory of the installation directory, there
are library files for the Microsoft Visual C++ compiler:
tcl80vc.lib
tk80vc.lib
13. Building dynamically loadable extensions
--------------------------------------------
Please refer to the example dynamically loadable extension provided on
our ftp site:
ftp://ftp.scriptics.com/pub/tcl/misc/example.zip
This archive contains a template that you can use for building
extensions that will be loadable on Unix, Windows, and Macintosh
systems.
+19
View File
@@ -0,0 +1,19 @@
@echo off
if exist %1 goto end
if %OS% == Windows_NT goto winnt
echo Add support for Win 95 please
goto end
goto success
:winnt
md %1
if errorlevel 1 goto end
:success
echo created directory %1
:end
+19
View File
@@ -0,0 +1,19 @@
@echo off
if exist %1 goto end
if %OS% == Windows_NT goto winnt
echo Add support for Win 95 please
goto end
goto success
:winnt
rmdir %1 /s /q
if errorlevel 1 goto end
:success
echo deleted directory %1
:end