Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69921d9a40 |
@@ -540,7 +540,6 @@ Tcl_Finalize()
|
||||
|
||||
TclFinalizeCompExecEnv();
|
||||
TclFinalizeEnvironment();
|
||||
TclpFinalize();
|
||||
firstExitPtr = NULL;
|
||||
tclInExit = 0;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
@@ -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"}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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__
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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(¬ifier, 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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user