diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-04-14 08:47:53 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-04-14 08:47:53 (GMT) |
commit | 7f42387e71a69b938ecd25945d10f01f6e39bcc7 (patch) | |
tree | d6de8446022309740483d0f2db7f089749623f34 | |
parent | 9ffcf83c49f17eca5cd2005902d378ac59aa7adf (diff) | |
parent | ccfe3f47fd0a170a819d29e0b22bba0003546796 (diff) | |
download | tcl-7f42387e71a69b938ecd25945d10f01f6e39bcc7.zip tcl-7f42387e71a69b938ecd25945d10f01f6e39bcc7.tar.gz tcl-7f42387e71a69b938ecd25945d10f01f6e39bcc7.tar.bz2 |
Merge 8.7
141 files changed, 6438 insertions, 4752 deletions
@@ -9018,8 +9018,8 @@ in this changeset (new minor version) rather than bug fixes: 2020-02-25 (bug) release refs when setting class's superclasses fails (dkf) 2020-02-26 (bug) C++ compiler compatibility for registry and dde (nijtmans) -=> registry 1.4.3 -=> dde 1.3.5 +=> registry 1.3.5 +=> dde 1.4.3 2020-03-05 (new) Update to Unicode-13 (nijtmans) diff --git a/doc/FileSystem.3 b/doc/FileSystem.3 index 4583b22..0a3aeef 100644 --- a/doc/FileSystem.3 +++ b/doc/FileSystem.3 @@ -241,9 +241,9 @@ The structure that contains the result of a stat or lstat operation. Name of a procedure to look up in the file's symbol table .AP "const char" *sym2 in Name of a procedure to look up in the file's symbol table -.AP Tcl_PackageInitProc **proc1Ptr out +.AP Tcl_LibraryInitProc **proc1Ptr out Filled with the init function for this code. -.AP Tcl_PackageInitProc **proc2Ptr out +.AP Tcl_LibraryInitProc **proc2Ptr out Filled with the safe-init function for this code. .AP ClientData *clientDataPtr out Filled with the clientData value to pass to this code's unload diff --git a/doc/PkgRequire.3 b/doc/PkgRequire.3 index 71f3acf..f32c936 100644 --- a/doc/PkgRequire.3 +++ b/doc/PkgRequire.3 @@ -94,4 +94,4 @@ compatibility and translate their invocations to this form. .SH KEYWORDS package, present, provide, require, version .SH "SEE ALSO" -package(n), Tcl_StaticPackage(3) +package(n), Tcl_StaticLibrary(3) diff --git a/doc/RegConfig.3 b/doc/RegConfig.3 index d73e3d7..ef46ba5 100644 --- a/doc/RegConfig.3 +++ b/doc/RegConfig.3 @@ -28,7 +28,7 @@ configuration as ASCII string. This means that this information is in UTF-8 too. Must not be NULL. .AP "const Tcl_Config" *configuration in Refers to an array of Tcl_Config entries containing the information -embedded in the binary library. Must not be NULL. The end of the array +embedded in the library. Must not be NULL. The end of the array is signaled by either a key identical to NULL, or a key referring to the empty string. .AP "const char" *valEncoding in @@ -40,10 +40,10 @@ too. Must not be NULL. .PP The function described here has its base in TIP 59 and provides extensions with support for the embedding of configuration -information into their binary library and the generation of a +information into their library and the generation of a Tcl-level interface for querying this information. .PP -To embed configuration information into their binary library an +To embed configuration information into their library an extension has to define a non-volatile array of Tcl_Config entries in one if its source files and then call \fBTcl_RegisterConfig\fR to register that information. @@ -108,4 +108,4 @@ typedef struct Tcl_Config { .\" No cross references yet. .\" .SH "SEE ALSO" .SH KEYWORDS -embedding, configuration, binary library +embedding, configuration, library diff --git a/doc/StaticLibrary.3 b/doc/StaticLibrary.3 new file mode 100644 index 0000000..9a77ab7 --- /dev/null +++ b/doc/StaticLibrary.3 @@ -0,0 +1,78 @@ +'\" +'\" 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. +'\" +.TH Tcl_StaticLibrary 3 7.5 Tcl "Tcl Library Procedures" +.so man.macros +.BS +.SH NAME +Tcl_StaticLibrary, Tcl_StaticPackage \- make a statically linked library available via the 'load' command +.SH SYNOPSIS +.nf +\fB#include <tcl.h>\fR +.sp +\fBTcl_StaticLibrary\fR(\fIinterp, prefix, initProc, safeInitProc\fR) +.sp +\fBTcl_StaticPackage\fR(\fIinterp, prefix, initProc, safeInitProc\fR) +.SH ARGUMENTS +.AS Tcl_LibraryInitProc *safeInitProc +.AP Tcl_Interp *interp in +If not NULL, points to an interpreter into which the library has +already been incorporated (i.e., the caller has already invoked the +appropriate initialization procedure). NULL means the library +has not yet been incorporated into any interpreter. +.AP "const char" *prefix in +Prefix for library initialization function; should be properly +capitalized (first letter upper-case, all others lower-case). +.AP Tcl_LibraryInitProc *initProc in +Procedure to invoke to incorporate this library into a trusted +interpreter. +.AP Tcl_LibraryInitProc *safeInitProc in +Procedure to call to incorporate this library into a safe interpreter +(one that will execute untrusted scripts). NULL means the library +cannot be used in safe interpreters. +.BE +.SH DESCRIPTION +.PP +This procedure may be invoked to announce that a library has been +linked statically with a Tcl application and, optionally, that it +has already been incorporated into an interpreter. +Once \fBTcl_StaticLibrary\fR has been invoked for a library, it +may be incorporated into interpreters using the \fBload\fR command. +\fBTcl_StaticLibrary\fR is normally invoked only by the \fBTcl_AppInit\fR +procedure for the application, not by libraries for themselves +(\fBTcl_StaticLibrary\fR should only be invoked for statically +linked libraries, and code in the library itself should not need +to know whether the library is dynamically loaded or statically linked). +.PP +When the \fBload\fR command is used later to incorporate the library into +an interpreter, one of \fIinitProc\fR and \fIsafeInitProc\fR will +be invoked, depending on whether the target interpreter is safe +or not. +\fIinitProc\fR and \fIsafeInitProc\fR must both match the +following prototype: +.PP +.CS +typedef int \fBTcl_LibraryInitProc\fR( + Tcl_Interp *\fIinterp\fR); +.CE +.PP +The \fIinterp\fR argument identifies the interpreter in which the library +is to be incorporated. The initialization procedure must return \fBTCL_OK\fR or +\fBTCL_ERROR\fR to indicate whether or not it completed successfully; in +the event of an error it should set the interpreter's result to point to an +error message. The result or error from the initialization procedure will +be returned as the result of the \fBload\fR command that caused the +initialization procedure to be invoked. +.PP +\fBTcl_StaticLibrary\fR was named \fBTcl_StaticPackage\fR in Tcl 8.6 and +earlier, but the old name is deprecated now. +.PP +\fBTcl_StaticLibrary\fR can not be used in stub-enabled extensions. Its symbol +entry in the stub table is deprecated and it will be removed in Tcl 9.0. +.SH KEYWORDS +initialization procedure, package, static linking +.SH "SEE ALSO" +load(n), package(n), Tcl_PkgRequire(3) diff --git a/doc/StaticPkg.3 b/doc/StaticPkg.3 deleted file mode 100644 index b22edcc..0000000 --- a/doc/StaticPkg.3 +++ /dev/null @@ -1,73 +0,0 @@ -'\" -'\" 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. -'\" -.TH Tcl_StaticPackage 3 7.5 Tcl "Tcl Library Procedures" -.so man.macros -.BS -.SH NAME -Tcl_StaticPackage \- make a statically linked package available via the 'load' command -.SH SYNOPSIS -.nf -\fB#include <tcl.h>\fR -.sp -\fBTcl_StaticPackage\fR(\fIinterp, pkgName, initProc, safeInitProc\fR) -.SH ARGUMENTS -.AS Tcl_PackageInitProc *safeInitProc -.AP Tcl_Interp *interp in -If not NULL, points to an interpreter into which the package has -already been loaded (i.e., the caller has already invoked the -appropriate initialization procedure). NULL means the package -has not yet been incorporated into any interpreter. -.AP "const char" *pkgName in -Name of the package; should be properly capitalized (first letter -upper-case, all others lower-case). -.AP Tcl_PackageInitProc *initProc in -Procedure to invoke to incorporate this package into a trusted -interpreter. -.AP Tcl_PackageInitProc *safeInitProc in -Procedure to call to incorporate this package into a safe interpreter -(one that will execute untrusted scripts). NULL means the package -cannot be used in safe interpreters. -.BE -.SH DESCRIPTION -.PP -This procedure may be invoked to announce that a package has been -linked statically with a Tcl application and, optionally, that it -has already been loaded into an interpreter. -Once \fBTcl_StaticPackage\fR has been invoked for a package, it -may be loaded into interpreters using the \fBload\fR command. -\fBTcl_StaticPackage\fR is normally invoked only by the \fBTcl_AppInit\fR -procedure for the application, not by packages for themselves -(\fBTcl_StaticPackage\fR should only be invoked for statically -loaded packages, and code in the package itself should not need -to know whether the package is dynamically or statically loaded). -.PP -When the \fBload\fR command is used later to load the package into -an interpreter, one of \fIinitProc\fR and \fIsafeInitProc\fR will -be invoked, depending on whether the target interpreter is safe -or not. -\fIinitProc\fR and \fIsafeInitProc\fR must both match the -following prototype: -.PP -.CS -typedef int \fBTcl_PackageInitProc\fR( - Tcl_Interp *\fIinterp\fR); -.CE -.PP -The \fIinterp\fR argument identifies the interpreter in which the package -is to be loaded. The initialization procedure must return \fBTCL_OK\fR or -\fBTCL_ERROR\fR to indicate whether or not it completed successfully; in -the event of an error it should set the interpreter's result to point to an -error message. The result or error from the initialization procedure will -be returned as the result of the \fBload\fR command that caused the -initialization procedure to be invoked. -.PP -\fBTcl_StaticPackage\fR can not be used in stub-enabled extensions. Its symbol -entry in the stub table is deprecated and it will be removed in Tcl 9.0. -.SH KEYWORDS -initialization procedure, package, static linking -.SH "SEE ALSO" -load(n), package(n), Tcl_PkgRequire(3) @@ -233,10 +233,10 @@ characters. .PP \fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR of \fIlength\fR bytes is long enough to be decoded by -\fBTcl_UtfToUniChar\fR, or 0 otherwise. This function does not guarantee -that the UTF-8 string is properly formed. This routine is used by -procedures that are operating on a byte at a time and need to know if a -full Unicode character has been seen. +\fBTcl_UtfToUniChar\fR/\fBTcl_UtfNext\fR, or 0 otherwise. This function +does not guarantee that the UTF-8 string is properly formed. This routine +is used by procedures that are operating on a byte at a time and need to +know if a full Unicode character has been seen. .PP \fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings. It returns the number of Tcl_UniChars that are represented by the UTF-8 string @@ -257,7 +257,8 @@ Given \fIsrc\fR, a pointer to some location in a UTF-8 string, \fBTcl_UtfNext\fR returns a pointer to the next UTF-8 character in the string. The caller must not ask for the next character after the last character in the string if the string is not terminated by a null -character. +character. \fBTcl_UtfCharComplete\fR can be used in that case to +make sure enough bytes are available before calling \fBTcl_UtfNext\fR. .PP \fBTcl_UtfPrev\fR is used to step backward through but not beyond the UTF-8 string that begins at \fIstart\fR. If the UTF-8 string is made @@ -274,12 +275,12 @@ always a pointer to a location in the string. It always returns a pointer to a byte that begins a character when scanning for characters beginning from \fIstart\fR. When \fIsrc\fR is greater than \fIstart\fR, it always returns a pointer less than \fIsrc\fR and greater than or -equal to (\fIsrc\fR - \fBTCL_UTF_MAX\fR). The character that begins +equal to (\fIsrc\fR - 4). The character that begins at the returned pointer is the first one that either includes the byte \fIsrc[-1]\fR, or might include it if the right trail bytes are present at \fIsrc\fR and greater. \fBTcl_UtfPrev\fR never reads the byte \fIsrc[0]\fR nor the byte \fIstart[-1]\fR nor the byte -\fIsrc[-\fBTCL_UTF_MAX\fI-1]\fR. +\fIsrc[-5]\fR. .PP \fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the Pascal Ord() function. It returns the Unicode character represented at the @@ -22,6 +22,10 @@ of one or more subprocesses to execute. The arguments take the form of a standard shell pipeline where each \fIarg\fR becomes one word of a command, and each distinct command becomes a subprocess. +The result of the command is the standard output of the final subprocess in +the pipeline, interpreted using the system \fBencoding\fR; to use any other +encoding (especially including binary data), the pipeline must be +\fBopen\fRed, configured and read explicitly. .PP If the initial arguments to \fBexec\fR start with \fB\-\fR then they are treated as command-line switches and are not part @@ -411,7 +415,9 @@ With the file \fIcmp.bat\fR looking something like: .CS @gcc %* .CE +.PP or like another variant using single parameters: +.PP .CS @gcc %1 %2 %3 %4 %5 %6 %7 %8 %9 .CE @@ -13,22 +13,21 @@ load \- Load machine code and initialize new commands .SH SYNOPSIS \fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName\fR .br -\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName\fR +\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix\fR .br -\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName interp\fR +\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName prefix interp\fR .BE .SH DESCRIPTION .PP This command loads binary code from a file into the application's address space and calls an initialization procedure -in the package to incorporate it into an interpreter. \fIfileName\fR +in the library to incorporate it into an interpreter. \fIfileName\fR is the name of the file containing the code; its exact form varies from system to system but on most systems it is a shared library, such as a \fB.so\fR file under Solaris or a DLL under Windows. -\fIpackageName\fR is the name of the package, and is used to -compute the name of an initialization procedure. +\fIprefix\fR is used to compute the name of an initialization procedure. \fIinterp\fR is the path name of the interpreter into which to load -the package (see the \fBinterp\fR manual entry for details); +the library (see the \fBinterp\fR manual entry for details); if \fIinterp\fR is omitted, it defaults to the interpreter in which the \fBload\fR command was invoked. .PP @@ -37,32 +36,32 @@ one of two initialization procedures will be invoked in the new code. Typically the initialization procedure will add new commands to a Tcl interpreter. The name of the initialization procedure is determined by -\fIpackageName\fR and whether or not the target interpreter +\fIprefix\fR and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization -procedure will have the form \fIpkg\fB_Init\fR, where \fIpkg\fR -is the same as \fIpackageName\fR except that the first letter is +procedure will have the form \fIpfx\fB_Init\fR, where \fIpfx\fR +is the same as \fIprefix\fR except that the first letter is converted to upper case and all other letters -are converted to lower case. For example, if \fIpackageName\fR is +are converted to lower case. For example, if \fIprefix\fR is \fBfoo\fR or \fBFOo\fR, the initialization procedure's name will be \fBFoo_Init\fR. .PP If the target interpreter is a safe interpreter, then the name -of the initialization procedure will be \fIpkg\fB_SafeInit\fR -instead of \fIpkg\fB_Init\fR. -The \fIpkg\fB_SafeInit\fR function should be written carefully, so that it +of the initialization procedure will be \fIpfx\fB_SafeInit\fR +instead of \fIpfx\fB_Init\fR. +The \fIpfx\fB_SafeInit\fR function should be written carefully, so that it initializes the safe interpreter only with partial functionality provided -by the package that is safe for use by untrusted code. For more information +by the library that is safe for use by untrusted code. For more information on Safe\-Tcl, see the \fBsafe\fR manual entry. .PP The initialization procedure must match the following prototype: .PP .CS -typedef int \fBTcl_PackageInitProc\fR( +typedef int \fBTcl_LibraryInitProc\fR( Tcl_Interp *\fIinterp\fR); .CE .PP The \fIinterp\fR argument identifies the interpreter in which the -package is to be loaded. The initialization procedure must return +library is to be loaded. The initialization procedure must return \fBTCL_OK\fR or \fBTCL_ERROR\fR to indicate whether or not it completed successfully; in the event of an error it should set the interpreter's result to point to an error message. The result of the \fBload\fR command @@ -74,37 +73,37 @@ interpreters, then the first \fBload\fR will load the code and call the initialization procedure; subsequent \fBload\fRs will call the initialization procedure without loading the code again. For Tcl versions lower than 8.5, it is not possible to unload or reload a -package. From version 8.5 however, the \fBunload\fR command allows the unloading +library. From version 8.5 however, the \fBunload\fR command allows the unloading of libraries loaded with \fBload\fR, for libraries that are aware of the Tcl's unloading mechanism. .PP -The \fBload\fR command also supports packages that are statically -linked with the application, if those packages have been registered -by calling the \fBTcl_StaticPackage\fR procedure. -If \fIfileName\fR is an empty string, then \fIpackageName\fR must +The \fBload\fR command also supports libraries that are statically +linked with the application, if those libraries have been registered +by calling the \fBTcl_StaticLibrary\fR procedure. +If \fIfileName\fR is an empty string, then \fIprefix\fR must be specified. .PP -If \fIpackageName\fR is omitted or specified as an empty string, -Tcl tries to guess the name of the package. -This may be done differently on different platforms. -The default guess, which is used on most UNIX platforms, is to -take the last element of \fIfileName\fR, strip off the first -three characters if they are \fBlib\fR, then strip off the next -three characters if they are \fBtcl\fR, and use any following -alphabetic and underline characters as the module name. -For example, the command \fBload libtclxyz4.2.so\fR uses the module -name \fBxyz\fR and the command \fBload bin/last.so {}\fR uses the -module name \fBlast\fR. -.PP -If \fIfileName\fR is an empty string, then \fIpackageName\fR must +If \fIprefix\fR is omitted or specified as an empty string, +Tcl tries to guess the prefix. This may be done differently on +different platforms. The default guess, which is used on most +UNIX platforms, is to take the last element of +\fIfileName\fR, strip off the first three characters if they +are \fBlib\fR, then strip off the next three characters if they +are \fBtcl\fR, and use any following alphabetic and +underline characters, converted to titlecase as the prefix. +For example, the command \fBload libxyz4.2.so\fR uses the prefix +\fBXyz\fR and the command \fBload bin/last.so {}\fR uses the +prefix \fBLast\fR. +.PP +If \fIfileName\fR is an empty string, then \fIprefix\fR must be specified. -The \fBload\fR command first searches for a statically loaded package -(one that has been registered by calling the \fBTcl_StaticPackage\fR +The \fBload\fR command first searches for a statically loaded library +(one that has been registered by calling the \fBTcl_StaticLibrary\fR procedure) by that name; if one is found, it is used. Otherwise, the \fBload\fR command searches for a dynamically loaded -package by that name, and uses it if it is found. If several +library by that name, and uses it if it is found. If several different files have been \fBload\fRed with different versions of -the package, Tcl picks the file that was loaded first. +the library, Tcl picks the file that was loaded first. .PP If \fB\-global\fR is specified preceding the filename, all symbols found in the shared library are exported for global use by other @@ -112,7 +111,7 @@ libraries. The option \fB\-lazy\fR delays the actual loading of symbols until their first actual use. The options may be abbreviated. The option \fB\-\-\fR indicates the end of the options, and should be used if you wish to use a filename which starts with \fB\-\fR -and you provide a packageName to the \fBload\fR command. +and you provide a prefix to the \fBload\fR command. .PP On platforms which do not support the \fB\-global\fR or \fB\-lazy\fR options, the options still exist but have no effect. Note that use @@ -155,7 +154,7 @@ The following is a minimal extension: .CS #include <tcl.h> #include <stdio.h> -static int fooCmd(ClientData clientData, +static int fooCmd(void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { printf("called with %d arguments\en", objc); return TCL_OK; @@ -189,7 +188,7 @@ switch $tcl_platform(platform) { foo .CE .SH "SEE ALSO" -info sharedlibextension, package(n), Tcl_StaticPackage(3), safe(n) +info sharedlibextension, package(n), Tcl_StaticLibrary(3), safe(n) .SH KEYWORDS binary code, dynamic library, load, safe interpreter, shared library '\"Local Variables: @@ -72,7 +72,7 @@ indicate that the opened channel should be configured as if with the reading or writing of binary data. .PP In the second form, \fIaccess\fR consists of a list of any of the -following flags, all of which have the standard POSIX meanings. +following flags, most of which have the standard POSIX meanings. One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR. .TP 15 \fBRDONLY\fR @@ -453,6 +453,12 @@ application are competing for the console at the same time. If the command pipeline is started from a script, so that Tcl is not accessing the console, or if the command pipeline does not use standard input or output, but is redirected from or to a file, then the above problems do not occur. +.PP +Files opened in the +.QW \fBa\fR +mode or with the \fBAPPEND\fR flag set are implemented by seeking immediately +before each write, which is not an atomic operation and does not carry the +guarantee of strict appending that is present on POSIX platforms. .RE .TP \fBUnix\fR\0\0\0\0\0\0\0 @@ -527,6 +533,19 @@ Note that the equivalent options exist on Unix, but are on the serial channel type. .VE "8.7, TIP 160" .SH "EXAMPLES" +Open a file for writing, forcing it to be created and raising an error if it +already exists. +.PP +.CS +set myNewFile [\fBopen\fR filename.txt {WRONLY CREAT EXCL}] +.CE +.PP +Open a file for writing as a log file. +.PP +.CS +set myLogFile [\fBopen\fR filename.log "a"] +fconfigure $myLogFile -buffering line +.CE .PP Open a command pipeline and catch any errors: .PP @@ -538,6 +557,18 @@ if {[catch {close $fl} err]} { } .CE .PP +Open a command pipeline and read binary data from it. Note the unusual form +with +.QW |[list +that handles non-trivial edge cases with arguments that potentially have +spaces in. +.PP +.CS +set fl [\fBopen\fR |[list create_image_data $input] "rb"] +set binData [read $fl] +close $fl +.CE +.PP .VS "8.7, TIP 160" Read a password securely from the user (assuming that the script is being run interactively): diff --git a/doc/packagens.n b/doc/packagens.n index 65535ef..d55151f 100644 --- a/doc/packagens.n +++ b/doc/packagens.n @@ -29,7 +29,7 @@ This parameter specifies the name of the package. It is required. This parameter specifies the version of the package. It is required. .TP \fB\-load \fIfilespec\fR -This parameter specifies a binary library that must be loaded with the +This parameter specifies a library that must be loaded with the \fBload\fR command. \fIfilespec\fR is a list with two elements. The first element is the name of the file to load. The second, optional element is a list of commands supplied by loading that file. If the diff --git a/doc/re_syntax.n b/doc/re_syntax.n index 9a9e2b0..ef8c570 100644 --- a/doc/re_syntax.n +++ b/doc/re_syntax.n @@ -446,7 +446,7 @@ commonly-used character classes: .TP \fB\ew\fR . -\fB[[:alnum:]_]\fR (note underscore) +\fB[[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR (including punctuation connector characters) .TP \fB\eD\fR . @@ -458,7 +458,7 @@ commonly-used character classes: .TP \fB\eW\fR . -\fB[^[:alnum:]_]\fR (note underscore) +\fB[^[:alnum:]_\eu203F\eu2040\eu2054\euFE33\euFE34\euFE4D\euFE4E\euFE4F\euFF3F]\fR (including punctuation connector characters) .RE .PP Within bracket expressions, diff --git a/doc/refchan.n b/doc/refchan.n index 8737556..c17117d 100644 --- a/doc/refchan.n +++ b/doc/refchan.n @@ -322,6 +322,19 @@ invocation (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE +.TP +\fIcmdPrefix \fBtruncate\fR \fIchannelId length\fR +. +This \fIoptional\fR subcommand handles changing the length of the +underlying data stream for the channel \fIchannelId\fR. Its length +gets set to \fIlength\fR. +.RS +.PP +If the subcommand throws an error the command which caused its +invocation (usually \fBchan truncate\fR) will appear to have thrown +this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, +etc.) is treated as and converted to an error. +.RE .SH NOTES Some of the functions supported in channels defined in Tcl's C interface are not available to channels reflected to the Tcl level. diff --git a/doc/string.n b/doc/string.n index 7cd53ca..7413e6b 100644 --- a/doc/string.n +++ b/doc/string.n @@ -404,7 +404,7 @@ Formally, the \fBstring bytelength\fR operation returns the content of the \fIlength\fR field of the \fBTcl_Obj\fR structure, after calling \fBTcl_GetString\fR to ensure that the \fIbytes\fR field is populated. This is highly unlikely to be useful to Tcl scripts, as Tcl's internal -encoding is not strict UTF\-8, but rather a modified CESU\-8 with a +encoding is not strict UTF\-8, but rather a modified WTF\-8 with a denormalized NUL (identical to that used in a number of places by Java's serialization mechanism) to enable basic processing with non-Unicode-aware C functions. As this representation should only diff --git a/doc/unload.n b/doc/unload.n index 0a8e99b..00b709b 100644 --- a/doc/unload.n +++ b/doc/unload.n @@ -13,9 +13,9 @@ unload \- Unload machine code .SH SYNOPSIS \fBunload \fR?\fIswitches\fR? \fIfileName\fR .br -\fBunload \fR?\fIswitches\fR? \fIfileName packageName\fR +\fBunload \fR?\fIswitches\fR? \fIfileName prefix\fR .br -\fBunload \fR?\fIswitches\fR? \fIfileName packageName interp\fR +\fBunload \fR?\fIswitches\fR? \fIfileName prefix interp\fR .BE .SH DESCRIPTION .PP @@ -24,7 +24,7 @@ with \fBload\fR from the application's address space. \fIfileName\fR is the name of the file containing the library file to be unload; it must be the same as the filename provided to \fBload\fR for loading the library. -The \fIpackageName\fR argument is the name of the package (as +The \fIprefix\fR argument is the prefix (as determined by or passed to \fBload\fR), and is used to compute the name of the unload procedure; if not supplied, it is computed from \fIfileName\fR in the same manner as \fBload\fR. @@ -66,12 +66,12 @@ proper reference count. \fBunload\fR works in the opposite direction. As a first step, \fBunload\fR will check whether the library is unloadable: an unloadable library exports a special unload procedure. The name of the unload procedure is determined by -\fIpackageName\fR and whether or not the target interpreter +\fIprefix\fR and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization -procedure will have the form \fIpkg\fB_Unload\fR, where \fIpkg\fR -is the same as \fIpackageName\fR except that the first letter is +procedure will have the form \fIpfx\fB_Unload\fR, where \fIpfx\fR +is the same as \fIprefix\fR except that the first letter is converted to upper case and all other letters -are converted to lower case. For example, if \fIpackageName\fR is +are converted to lower case. For example, if \fIprefix\fR is \fBfoo\fR or \fBFOo\fR, the initialization procedure's name will be \fBFoo_Unload\fR. If the target interpreter is a safe interpreter, then the name @@ -90,7 +90,7 @@ detached from the process. The unload procedure must match the following prototype: .PP .CS -typedef int \fBTcl_PackageUnloadProc\fR( +typedef int \fBTcl_LibraryUnloadProc\fR( Tcl_Interp *\fIinterp\fR, int \fIflags\fR); .CE @@ -114,19 +114,20 @@ the \fIflags\fR argument will be set to \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR. .PP The \fBunload\fR command cannot unload libraries that are statically linked with the application. -If \fIfileName\fR is an empty string, then the \fIpackageName\fR argument must +If \fIfileName\fR is an empty string, then the \fIprefix\fR argument must be specified. .PP -If \fIpackageName\fR is omitted or specified as an empty string, -Tcl tries to guess the name of the package. -This may be done differently on different platforms. -The default guess, which is used on most UNIX platforms, is to -take the last element of \fIfileName\fR, strip off the first -three characters if they are \fBlib\fR, and use any following -alphabetic and underline characters as the module name. -For example, the command \fBunload libxyz4.2.so\fR uses the module -name \fBxyz\fR and the command \fBunload bin/last.so {}\fR uses the -module name \fBlast\fR. +If \fIprefix\fR is omitted or specified as an empty string, +Tcl tries to guess the prefix. This may be done differently on +different platforms. The default guess, which is used on most +UNIX platforms, is to take the last element of +\fIfileName\fR, strip off the first three characters if they +are \fBlib\fR, then strip off the next three characters if they +are \fBtcl\fR, and use any following alphabetic and +underline characters, converted to titlecase as the prefix. +For example, the command \fBunload libxyz4.2.so\fR uses the prefix +\fBXyz\fR and the command \fBunload bin/last.so {}\fR uses the +prefix \fBLast\fR. .SH "PORTABILITY ISSUES" .TP \fBUnix\fR\0\0\0\0\0 diff --git a/doc/zipfs.n b/doc/zipfs.n index da2e026..a75a70b 100644 --- a/doc/zipfs.n +++ b/doc/zipfs.n @@ -84,7 +84,7 @@ Return a list of all files in the mounted zipfs, or just those matching \fIpattern\fR (optionally controlled by the option parameters). The order of the names in the list is arbitrary. .TP -\fBzipfs mount ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR? +\fBzipfs mount\fR ?\fImountpoint\fR? ?\fIzipfile\fR? ?\fIpassword\fR? . The \fBzipfs mount\fR command mounts a ZIP archive file as a Tcl virtual filesystem at \fImountpoint\fR. After this command executes, files contained @@ -146,6 +146,8 @@ the ZIP archive, otherwise the file returned by \fBinfo nameofexecutable\fR (see \fBzipfs mkkey\fR) is placed between the image and ZIP chunks of the output file and the contents of the ZIP chunk are protected with that password. +If the starting image has a ZIP archive already attached to it, it is removed +from the copy in \fIoutfile\fR before the new ZIP archive is added. .PP If there is a file, \fBmain.tcl\fR, in the root directory of the resulting archive and the image file that the archive is attached to is a \fBtclsh\fR diff --git a/generic/tcl.decls b/generic/tcl.decls index 7b53db8..2e3f79d 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -860,8 +860,8 @@ declare 243 { void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr) } declare 244 {nostub {Don't use this function in a stub-enabled extension}} { - void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, - Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) + void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, + Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) } declare 245 {deprecated {No longer in use, changed to macro}} { int Tcl_StringMatch(const char *str, const char *pattern) @@ -1163,7 +1163,7 @@ declare 325 { const char *Tcl_UtfAtIndex(const char *src, int index) } declare 326 { - int Tcl_UtfCharComplete(const char *src, int length) + int TclUtfCharComplete(const char *src, int length) } declare 327 { int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst) @@ -1175,10 +1175,10 @@ declare 329 { const char *Tcl_UtfFindLast(const char *src, int ch) } declare 330 { - const char *Tcl_UtfNext(const char *src) + const char *TclUtfNext(const char *src) } declare 331 { - const char *Tcl_UtfPrev(const char *src, const char *start) + const char *TclUtfPrev(const char *src, const char *start) } declare 332 { int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding, @@ -1581,8 +1581,8 @@ declare 443 { } declare 444 { int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, - const char *sym2, Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, + const char *sym2, Tcl_LibraryInitProc **proc1Ptr, + Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr) } declare 445 { @@ -2413,6 +2413,17 @@ declare 653 { unsigned char *TclGetByteArrayFromObj(Tcl_Obj *objPtr, size_t *lengthPtr) } +# TIP #575 +declare 654 { + int Tcl_UtfCharComplete(const char *src, int length) +} +declare 655 { + const char *Tcl_UtfNext(const char *src) +} +declare 656 { + const char *Tcl_UtfPrev(const char *src, const char *start) +} + # ----- BASELINE -- FOR -- 8.7.0 ----- # ############################################################################## @@ -2437,6 +2448,9 @@ declare 0 win { declare 1 win { char *Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr) } +declare 3 win { + void Tcl_WinConvertError(unsigned errCode) +} ################################ # Mac OS X specific functions @@ -2467,8 +2481,8 @@ export { Tcl_Interp *interp) } export { - void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, - Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) + void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, + Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) } export { void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) @@ -2497,7 +2511,7 @@ export { export { const char *Tcl_InitSubsystems(void) } -export { +export { int TclZipfs_AppHook(int *argc, char ***argv) } diff --git a/generic/tcl.h b/generic/tcl.h index eeb7d19..b027235 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -697,8 +697,8 @@ typedef int (Tcl_MathProc) (ClientData clientData, Tcl_Interp *interp, typedef void (Tcl_NamespaceDeleteProc) (ClientData clientData); typedef int (Tcl_ObjCmdProc) (ClientData clientData, Tcl_Interp *interp, int objc, struct Tcl_Obj *const *objv); -typedef int (Tcl_PackageInitProc) (Tcl_Interp *interp); -typedef int (Tcl_PackageUnloadProc) (Tcl_Interp *interp, int flags); +typedef int (Tcl_LibraryInitProc) (Tcl_Interp *interp); +typedef int (Tcl_LibraryUnloadProc) (Tcl_Interp *interp, int flags); typedef void (Tcl_PanicProc) (const char *format, ...); typedef void (Tcl_TcpAcceptProc) (ClientData callbackData, Tcl_Channel chan, char *address, int port); @@ -717,7 +717,12 @@ typedef void (Tcl_ServiceModeHookProc) (int mode); typedef ClientData (Tcl_InitNotifierProc) (void); typedef void (Tcl_FinalizeNotifierProc) (ClientData clientData); typedef void (Tcl_MainLoopProc) (void); - + +#ifndef TCL_NO_DEPRECATED +# define Tcl_PackageInitProc Tcl_LibraryInitProc +# define Tcl_PackageUnloadProc Tcl_LibraryUnloadProc +#endif + /* *---------------------------------------------------------------------------- * The following structure represents a type of object, which is a particular @@ -2380,6 +2385,9 @@ EXTERN const char *Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact); EXTERN const char *Tcl_InitSubsystems(void); EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); +#ifndef TCL_NO_DEPRECATED +# define Tcl_StaticPackage Tcl_StaticLibrary +#endif #ifdef _WIN32 EXTERN const char *TclZipfs_AppHook(int *argc, wchar_t ***argv); #else diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index 2043248..03655b9 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -748,6 +748,8 @@ TclpRealloc( } #endif /* !USE_TCLALLOC */ +#else +TCL_MAC_EMPTY_FILE(generic_tclAlloc_c) #endif /* !TCL_THREADS */ /* diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 612a6d8..833101c 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -3513,6 +3513,8 @@ Tcl_DeleteCommandFromToken( if (cmdPtr->tracePtr != NULL) { CommandTrace *tracePtr; + /* Note that CallCommandTraces() never frees cmdPtr, that's + * done just before Tcl_DeleteCommandFromToken() returns */ CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE); /* @@ -3682,7 +3684,6 @@ CallCommandTraces( } } cmdPtr->flags |= CMD_TRACE_ACTIVE; - cmdPtr->refCount++; result = NULL; active.nextPtr = iPtr->activeCmdTracePtr; @@ -3740,7 +3741,6 @@ CallCommandTraces( */ cmdPtr->flags &= ~CMD_TRACE_ACTIVE; - cmdPtr->refCount--; iPtr->activeCmdTracePtr = active.nextPtr; Tcl_Release(iPtr); return result; diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index beb55c0..d3588aa 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -1700,7 +1700,7 @@ InfoLoadedCmd( } else { /* Get pkgs just in specified interp. */ packageName = TclGetString(objv[2]); } - return TclGetLoadedPackagesEx(interp, interpName, packageName); + return TclGetLoadedLibraries(interp, interpName, packageName); } /* diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index fa15fba..03aebe3 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -2145,7 +2145,7 @@ ParseLexeme( */ if (!TclIsBareword(*start) || *start == '_') { - if (TclUCS4Complete(start, numBytes)) { + if (Tcl_UtfCharComplete(start, numBytes)) { scanned = TclUtfToUCS4(start, &ch); } else { char utfBytes[8]; diff --git a/generic/tclConfig.c b/generic/tclConfig.c index 540187f..a145bac 100644 --- a/generic/tclConfig.c +++ b/generic/tclConfig.c @@ -178,7 +178,7 @@ Tcl_RegisterConfig( * QueryConfigObjCmd -- * * Implementation of "::<package>::pkgconfig", the command to query - * configuration information embedded into a binary library. + * configuration information embedded into a library. * * Results: * A standard tcl result. diff --git a/generic/tclDecls.h b/generic/tclDecls.h index dc39657..95824bb 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -749,10 +749,10 @@ EXTERN int Tcl_SplitList(Tcl_Interp *interp, EXTERN void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr); /* 244 */ -EXTERN void Tcl_StaticPackage(Tcl_Interp *interp, - const char *pkgName, - Tcl_PackageInitProc *initProc, - Tcl_PackageInitProc *safeInitProc); +EXTERN void Tcl_StaticLibrary(Tcl_Interp *interp, + const char *prefix, + Tcl_LibraryInitProc *initProc, + Tcl_LibraryInitProc *safeInitProc); /* 245 */ TCL_DEPRECATED("No longer in use, changed to macro") int Tcl_StringMatch(const char *str, const char *pattern); @@ -999,7 +999,7 @@ EXTERN int Tcl_UniCharToUtf(int ch, char *buf); /* 325 */ EXTERN const char * Tcl_UtfAtIndex(const char *src, int index); /* 326 */ -EXTERN int Tcl_UtfCharComplete(const char *src, int length); +EXTERN int TclUtfCharComplete(const char *src, int length); /* 327 */ EXTERN int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst); @@ -1008,9 +1008,9 @@ EXTERN const char * Tcl_UtfFindFirst(const char *src, int ch); /* 329 */ EXTERN const char * Tcl_UtfFindLast(const char *src, int ch); /* 330 */ -EXTERN const char * Tcl_UtfNext(const char *src); +EXTERN const char * TclUtfNext(const char *src); /* 331 */ -EXTERN const char * Tcl_UtfPrev(const char *src, const char *start); +EXTERN const char * TclUtfPrev(const char *src, const char *start); /* 332 */ EXTERN int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, @@ -1338,8 +1338,8 @@ EXTERN int Tcl_FSDeleteFile(Tcl_Obj *pathPtr); /* 444 */ EXTERN int Tcl_FSLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, - Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr, + Tcl_LibraryInitProc **proc1Ptr, + Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 445 */ @@ -1931,6 +1931,12 @@ EXTERN Tcl_UniChar * TclGetUnicodeFromObj(Tcl_Obj *objPtr, /* 653 */ EXTERN unsigned char * TclGetByteArrayFromObj(Tcl_Obj *objPtr, size_t *lengthPtr); +/* 654 */ +EXTERN int Tcl_UtfCharComplete(const char *src, int length); +/* 655 */ +EXTERN const char * Tcl_UtfNext(const char *src); +/* 656 */ +EXTERN const char * Tcl_UtfPrev(const char *src, const char *start); typedef struct { const struct TclPlatStubs *tclPlatStubs; @@ -2210,7 +2216,7 @@ typedef struct TclStubs { void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */ int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, const char ***argvPtr); /* 242 */ void (*tcl_SplitPath) (const char *path, int *argcPtr, const char ***argvPtr); /* 243 */ - TCL_DEPRECATED_API("Don't use this function in a stub-enabled extension") void (*tcl_StaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 244 */ + TCL_DEPRECATED_API("Don't use this function in a stub-enabled extension") void (*tcl_StaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 244 */ TCL_DEPRECATED_API("No longer in use, changed to macro") int (*tcl_StringMatch) (const char *str, const char *pattern); /* 245 */ TCL_DEPRECATED_API("") int (*tcl_TellOld) (Tcl_Channel chan); /* 246 */ TCL_DEPRECATED_API("No longer in use, changed to macro") int (*tcl_TraceVar) (Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 247 */ @@ -2292,12 +2298,12 @@ typedef struct TclStubs { int (*tcl_UniCharToUpper) (int ch); /* 323 */ int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ const char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */ - int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */ + int (*tclUtfCharComplete) (const char *src, int length); /* 326 */ int (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */ const char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */ const char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */ - const char * (*tcl_UtfNext) (const char *src); /* 330 */ - const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 331 */ + const char * (*tclUtfNext) (const char *src); /* 330 */ + const char * (*tclUtfPrev) (const char *src, const char *start); /* 331 */ int (*tcl_UtfToExternal) (Tcl_Interp *interp, Tcl_Encoding encoding, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* 332 */ char * (*tcl_UtfToExternalDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 333 */ int (*tcl_UtfToLower) (char *src); /* 334 */ @@ -2410,7 +2416,7 @@ typedef struct TclStubs { int (*tcl_FSCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 441 */ int (*tcl_FSCreateDirectory) (Tcl_Obj *pathPtr); /* 442 */ int (*tcl_FSDeleteFile) (Tcl_Obj *pathPtr); /* 443 */ - int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */ + int (*tcl_FSLoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *sym1, const char *sym2, Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 444 */ int (*tcl_FSMatchInDirectory) (Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); /* 445 */ Tcl_Obj * (*tcl_FSLink) (Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction); /* 446 */ int (*tcl_FSRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 447 */ @@ -2620,6 +2626,9 @@ typedef struct TclStubs { char * (*tclGetStringFromObj) (Tcl_Obj *objPtr, size_t *lengthPtr); /* 651 */ Tcl_UniChar * (*tclGetUnicodeFromObj) (Tcl_Obj *objPtr, size_t *lengthPtr); /* 652 */ unsigned char * (*tclGetByteArrayFromObj) (Tcl_Obj *objPtr, size_t *lengthPtr); /* 653 */ + int (*tcl_UtfCharComplete) (const char *src, int length); /* 654 */ + const char * (*tcl_UtfNext) (const char *src); /* 655 */ + const char * (*tcl_UtfPrev) (const char *src, const char *start); /* 656 */ } TclStubs; extern const TclStubs *tclStubsPtr; @@ -3139,8 +3148,8 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_SplitList) /* 242 */ #define Tcl_SplitPath \ (tclStubsPtr->tcl_SplitPath) /* 243 */ -#define Tcl_StaticPackage \ - (tclStubsPtr->tcl_StaticPackage) /* 244 */ +#define Tcl_StaticLibrary \ + (tclStubsPtr->tcl_StaticLibrary) /* 244 */ #define Tcl_StringMatch \ (tclStubsPtr->tcl_StringMatch) /* 245 */ #define Tcl_TellOld \ @@ -3302,18 +3311,18 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tcl_UniCharToUtf) /* 324 */ #define Tcl_UtfAtIndex \ (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ -#define Tcl_UtfCharComplete \ - (tclStubsPtr->tcl_UtfCharComplete) /* 326 */ +#define TclUtfCharComplete \ + (tclStubsPtr->tclUtfCharComplete) /* 326 */ #define Tcl_UtfBackslash \ (tclStubsPtr->tcl_UtfBackslash) /* 327 */ #define Tcl_UtfFindFirst \ (tclStubsPtr->tcl_UtfFindFirst) /* 328 */ #define Tcl_UtfFindLast \ (tclStubsPtr->tcl_UtfFindLast) /* 329 */ -#define Tcl_UtfNext \ - (tclStubsPtr->tcl_UtfNext) /* 330 */ -#define Tcl_UtfPrev \ - (tclStubsPtr->tcl_UtfPrev) /* 331 */ +#define TclUtfNext \ + (tclStubsPtr->tclUtfNext) /* 330 */ +#define TclUtfPrev \ + (tclStubsPtr->tclUtfPrev) /* 331 */ #define Tcl_UtfToExternal \ (tclStubsPtr->tcl_UtfToExternal) /* 332 */ #define Tcl_UtfToExternalDString \ @@ -3956,11 +3965,18 @@ extern const TclStubs *tclStubsPtr; (tclStubsPtr->tclGetUnicodeFromObj) /* 652 */ #define TclGetByteArrayFromObj \ (tclStubsPtr->tclGetByteArrayFromObj) /* 653 */ +#define Tcl_UtfCharComplete \ + (tclStubsPtr->tcl_UtfCharComplete) /* 654 */ +#define Tcl_UtfNext \ + (tclStubsPtr->tcl_UtfNext) /* 655 */ +#define Tcl_UtfPrev \ + (tclStubsPtr->tcl_UtfPrev) /* 656 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ +#undef TclUnusedStubEntry #if defined(USE_TCL_STUBS) # undef Tcl_CreateInterp # undef Tcl_FindExecutable @@ -3969,7 +3985,7 @@ extern const TclStubs *tclStubsPtr; # undef Tcl_SetPanicProc # undef Tcl_SetExitProc # undef Tcl_ObjSetVar2 -# undef Tcl_StaticPackage +# undef Tcl_StaticLibrary # define Tcl_CreateInterp() (tclStubsPtr->tcl_CreateInterp()) # define Tcl_GetStringResult(interp) (tclStubsPtr->tcl_GetStringResult(interp)) # define Tcl_Init(interp) (tclStubsPtr->tcl_Init(interp)) @@ -4230,10 +4246,16 @@ extern const TclStubs *tclStubsPtr; #define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0) #endif -#if defined(USE_TCL_STUBS) && (TCL_UTF_MAX > 3) +#undef TclUtfCharComplete +#undef TclUtfNext +#undef TclUtfPrev +#if defined(USE_TCL_STUBS) && (TCL_UTF_MAX < 4) && !defined(TCL_NO_DEPRECATED) # undef Tcl_UtfCharComplete -# define Tcl_UtfCharComplete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \ - ? ((length) >= 4) : tclStubsPtr->tcl_UtfCharComplete((src), (length))) +# undef Tcl_UtfNext +# undef Tcl_UtfPrev +# define Tcl_UtfCharComplete (tclStubsPtr->tclUtfCharComplete) +# define Tcl_UtfNext (tclStubsPtr->tclUtfNext) +# define Tcl_UtfPrev (tclStubsPtr->tclUtfPrev) #endif #define Tcl_CreateSlave Tcl_CreateChild #define Tcl_GetSlave Tcl_GetChild diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index c4ef159..72b6ee3 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -220,14 +220,7 @@ static size_t unilen(const char *src); static Tcl_EncodingConvertProc Utf16ToUtfProc; static Tcl_EncodingConvertProc UtfToUtf16Proc; static Tcl_EncodingConvertProc UtfToUcs2Proc; -static int UtfToUtfProc(ClientData clientData, - const char *src, int srcLen, int flags, - Tcl_EncodingState *statePtr, char *dst, - int dstLen, int *srcReadPtr, - int *dstWrotePtr, int *dstCharsPtr, - int pureNullMode); -static Tcl_EncodingConvertProc UtfIntToUtfExtProc; -static Tcl_EncodingConvertProc UtfExtToUtfIntProc; +static Tcl_EncodingConvertProc UtfToUtfProc; static Tcl_EncodingConvertProc Iso88591FromUtfProc; static Tcl_EncodingConvertProc Iso88591ToUtfProc; @@ -517,6 +510,12 @@ FillEncodingFileMap(void) *--------------------------------------------------------------------------- */ +/* This flags must not conflict with other TCL_ENCODING_* flags in tcl.h */ +#define TCL_ENCODING_MODIFIED 0x20 /* Converting NULL bytes to 0xC0 0x80 */ +/* Since TCL_ENCODING_MODIFIED is only used for utf-8 and + * TCL_ENCODING_LE is only used for utf-16/ucs-2, re-use the same value */ +#define TCL_ENCODING_LE TCL_ENCODING_MODIFIED /* Little-endian encoding */ + void TclInitEncodingSubsystem(void) { @@ -533,7 +532,7 @@ TclInitEncodingSubsystem(void) return; } - isLe.s = 1; + isLe.s = TCL_ENCODING_LE; Tcl_MutexLock(&encodingMutex); Tcl_InitHashTable(&encodingTable, TCL_STRING_KEYS); Tcl_MutexUnlock(&encodingMutex); @@ -553,8 +552,8 @@ TclInitEncodingSubsystem(void) tclIdentityEncoding = Tcl_CreateEncoding(&type); type.encodingName = "utf-8"; - type.toUtfProc = UtfExtToUtfIntProc; - type.fromUtfProc = UtfIntToUtfExtProc; + type.toUtfProc = UtfToUtfProc; + type.fromUtfProc = UtfToUtfProc; type.freeProc = NULL; type.nullSize = 1; type.clientData = NULL; @@ -565,7 +564,7 @@ TclInitEncodingSubsystem(void) type.freeProc = NULL; type.nullSize = 2; type.encodingName = "ucs-2le"; - type.clientData = INT2PTR(1); + type.clientData = INT2PTR(TCL_ENCODING_LE); Tcl_CreateEncoding(&type); type.encodingName = "ucs-2be"; type.clientData = INT2PTR(0); @@ -579,7 +578,7 @@ TclInitEncodingSubsystem(void) type.freeProc = NULL; type.nullSize = 2; type.encodingName = "utf-16le"; - type.clientData = INT2PTR(1); + type.clientData = INT2PTR(TCL_ENCODING_LE); Tcl_CreateEncoding(&type); type.encodingName = "utf-16be"; type.clientData = INT2PTR(0); @@ -1141,19 +1140,21 @@ Tcl_ExternalToUtfDString( } flags = TCL_ENCODING_START | TCL_ENCODING_END; + if (encodingPtr->toUtfProc == UtfToUtfProc) { + flags |= TCL_ENCODING_MODIFIED; + } while (1) { result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars); soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); + src += srcRead; if (result != TCL_CONVERT_NOSPACE) { Tcl_DStringSetLength(dstPtr, soFar); return Tcl_DStringValue(dstPtr); } - flags &= ~TCL_ENCODING_START; - src += srcRead; srcLen -= srcRead; if (Tcl_DStringLength(dstPtr) == 0) { Tcl_DStringSetLength(dstPtr, dstLen); @@ -1249,15 +1250,17 @@ Tcl_ExternalToUtf( if (!noTerminate) { /* * If there are any null characters in the middle of the buffer, - * they will converted to the UTF-8 null character (\xC080). To get + * they will converted to the UTF-8 null character (\xC0\x80). To get * the actual \0 at the end of the destination buffer, we need to * append it manually. First make room for it... */ dstLen--; } + if (encodingPtr->toUtfProc == UtfToUtfProc) { + flags |= TCL_ENCODING_MODIFIED; + } do { - int savedFlags = flags; Tcl_EncodingState savedState = *statePtr; result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, @@ -1267,7 +1270,6 @@ Tcl_ExternalToUtf( break; } dstLen = Tcl_UtfAtIndex(dst, maxChars) - dst + (TCL_UTF_MAX - 1); - flags = savedFlags; *statePtr = savedState; } while (1); if (!noTerminate) { @@ -1331,8 +1333,8 @@ Tcl_UtfToExternalDString( flags = TCL_ENCODING_START | TCL_ENCODING_END; while (1) { result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, - srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote, - &dstChars); + srcLen, flags, &state, dst, dstLen, + &srcRead, &dstWrote, &dstChars); soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); if (result != TCL_CONVERT_NOSPACE) { @@ -1433,8 +1435,8 @@ Tcl_UtfToExternal( dstLen -= encodingPtr->nullSize; result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen, - flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, - dstCharsPtr); + flags, statePtr, dst, dstLen, srcReadPtr, + dstWrotePtr, dstCharsPtr); if (encodingPtr->nullSize == 2) { dst[*dstWrotePtr + 1] = '\0'; } @@ -2156,104 +2158,6 @@ BinaryProc( /* *------------------------------------------------------------------------- * - * UtfIntToUtfExtProc -- - * - * Convert from UTF-8 to UTF-8. While converting null-bytes from the - * Tcl's internal representation (0xC0, 0x80) to the official - * representation (0x00). See UtfToUtfProc for details. - * - * Results: - * Returns TCL_OK if conversion was successful. - * - * Side effects: - * None. - * - *------------------------------------------------------------------------- - */ - -static int -UtfIntToUtfExtProc( - ClientData clientData, - const char *src, /* Source string in UTF-8. */ - int srcLen, /* Source string length in bytes. */ - int flags, /* Conversion control flags. */ - Tcl_EncodingState *statePtr,/* Place for conversion routine to store state - * information used during a piecewise - * conversion. Contents of statePtr are - * initialized and/or reset by conversion - * routine under control of flags argument. */ - char *dst, /* Output buffer in which converted string - * is stored. */ - int dstLen, /* The maximum length of output buffer in - * bytes. */ - int *srcReadPtr, /* Filled with the number of bytes from the - * source string that were converted. This may - * be less than the original source length if - * there was a problem converting some source - * characters. */ - int *dstWrotePtr, /* Filled with the number of bytes that were - * stored in the output buffer as a result of - * the conversion. */ - int *dstCharsPtr) /* Filled with the number of characters that - * correspond to the bytes stored in the - * output buffer. */ -{ - return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen, - srcReadPtr, dstWrotePtr, dstCharsPtr, 1); -} - -/* - *------------------------------------------------------------------------- - * - * UtfExtToUtfIntProc -- - * - * Convert from UTF-8 to UTF-8 while converting null-bytes from the - * official representation (0x00) to Tcl's internal representation (0xC0, - * 0x80). See UtfToUtfProc for details. - * - * Results: - * Returns TCL_OK if conversion was successful. - * - * Side effects: - * None. - * - *------------------------------------------------------------------------- - */ - -static int -UtfExtToUtfIntProc( - ClientData clientData, - const char *src, /* Source string in UTF-8. */ - int srcLen, /* Source string length in bytes. */ - int flags, /* Conversion control flags. */ - Tcl_EncodingState *statePtr,/* Place for conversion routine to store state - * information used during a piecewise - * conversion. Contents of statePtr are - * initialized and/or reset by conversion - * routine under control of flags argument. */ - char *dst, /* Output buffer in which converted string is - * stored. */ - int dstLen, /* The maximum length of output buffer in - * bytes. */ - int *srcReadPtr, /* Filled with the number of bytes from the - * source string that were converted. This may - * be less than the original source length if - * there was a problem converting some source - * characters. */ - int *dstWrotePtr, /* Filled with the number of bytes that were - * stored in the output buffer as a result of - * the conversion. */ - int *dstCharsPtr) /* Filled with the number of characters that - * correspond to the bytes stored in the - * output buffer. */ -{ - return UtfToUtfProc(clientData, src, srcLen, flags, statePtr, dst, dstLen, - srcReadPtr, dstWrotePtr, dstCharsPtr, 0); -} - -/* - *------------------------------------------------------------------------- - * * UtfToUtfProc -- * * Convert from UTF-8 to UTF-8. Note that the UTF-8 to UTF-8 translation @@ -2271,15 +2175,11 @@ UtfExtToUtfIntProc( static int UtfToUtfProc( - TCL_UNUSED(ClientData), + ClientData clientData, /* additional flags, e.g. TCL_ENCODING_MODIFIED */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ - Tcl_EncodingState *statePtr,/* Place for conversion routine to store state - * information used during a piecewise - * conversion. Contents of statePtr are - * initialized and/or reset by conversion - * routine under control of flags argument. */ + TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is * stored. */ int dstLen, /* The maximum length of output buffer in @@ -2292,21 +2192,15 @@ UtfToUtfProc( int *dstWrotePtr, /* Filled with the number of bytes that were * stored in the output buffer as a result of * the conversion. */ - int *dstCharsPtr, /* Filled with the number of characters that + int *dstCharsPtr) /* Filled with the number of characters that * correspond to the bytes stored in the * output buffer. */ - int pureNullMode) /* Convert embedded nulls from internal - * representation to real null-bytes or vice - * versa. Also combine or separate surrogate pairs */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars, charLimit = INT_MAX; - int *chPtr = (int *) statePtr; + int ch; - if (flags & TCL_ENCODING_START) { - *statePtr = 0; - } result = TCL_OK; srcStart = src; @@ -2320,10 +2214,11 @@ UtfToUtfProc( } dstStart = dst; + flags |= PTR2INT(clientData); dstEnd = dst + dstLen - TCL_UTF_MAX; for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { - if ((src > srcClose) && (!TclUCS4Complete(src, srcEnd - src))) { + if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) { /* * If there is more string to follow, this will ensure that the * last UTF-8 character in the source buffer hasn't been cut off. @@ -2336,50 +2231,69 @@ UtfToUtfProc( result = TCL_CONVERT_NOSPACE; break; } - if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) { + if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && (flags & TCL_ENCODING_MODIFIED))) { /* * Copy 7bit characters, but skip null-bytes when we are in input * mode, so that they get converted to 0xC080. */ *dst++ = *src++; - *chPtr = 0; /* reset surrogate handling */ - } else if (pureNullMode == 1 && UCHAR(*src) == 0xC0 && - (src + 1 < srcEnd) && UCHAR(*(src+1)) == 0x80) { + } else if (UCHAR(*src) == 0xC0 && (src + 1 < srcEnd) + && UCHAR(src[1]) == 0x80 && !(flags & TCL_ENCODING_MODIFIED)) { /* * Convert 0xC080 to real nulls when we are in output mode. */ *dst++ = 0; - *chPtr = 0; /* reset surrogate handling */ src += 2; - } else if (!TclUCS4Complete(src, srcEnd - src)) { + } else if (!Tcl_UtfCharComplete(src, srcEnd - src)) { /* * Always check before using TclUtfToUCS4. Not doing can so * cause it run beyond the end of the buffer! If we happen such an - * incomplete char its bytes are made to represent themselves. + * incomplete char its bytes are made to represent themselves + * unless the user has explicitly asked to be told. */ - *chPtr = UCHAR(*src); - src += 1; - dst += Tcl_UniCharToUtf(*chPtr, dst); + if (flags & TCL_ENCODING_MODIFIED) { + if (flags & TCL_ENCODING_STOPONERROR) { + result = TCL_CONVERT_MULTIBYTE; + break; + } + ch = UCHAR(*src++); + } else { + char chbuf[2]; + chbuf[0] = UCHAR(*src++); chbuf[1] = 0; + TclUtfToUCS4(chbuf, &ch); + } + dst += Tcl_UniCharToUtf(ch, dst); } else { - src += TclUtfToUCS4(src, chPtr); - if ((*chPtr | 0x7FF) == 0xDFFF) { - /* A surrogate character is detected, handle especially */ - int low = *chPtr; - size_t len = (src <= srcEnd-3) ? TclUtfToUCS4(src, &low) : 0; - if (((low & ~0x3FF) != 0xDC00) || (*chPtr & 0x400)) { - *dst++ = (char) (((*chPtr >> 12) | 0xE0) & 0xEF); - *dst++ = (char) (((*chPtr >> 6) | 0x80) & 0xBF); - *dst++ = (char) ((*chPtr | 0x80) & 0xBF); - continue; + int low; + size_t len = TclUtfToUCS4(src, &ch); + if ((len < 2) && (ch != 0) && (flags & TCL_ENCODING_STOPONERROR) + && (flags & TCL_ENCODING_MODIFIED)) { + result = TCL_CONVERT_SYNTAX; + break; + } + src += len; + if ((ch | 0x7FF) == 0xDFFF) { + /* + * A surrogate character is detected, handle especially. + */ + + low = ch; + len = (src <= srcEnd-3) ? TclUtfToUCS4(src, &low) : 0; + + if (((low & ~0x3FF) != 0xDC00) || (ch & 0x400)) { + *dst++ = (char) (((ch >> 12) | 0xE0) & 0xEF); + *dst++ = (char) (((ch >> 6) | 0x80) & 0xBF); + *dst++ = (char) ((ch | 0x80) & 0xBF); + continue; } src += len; - dst += Tcl_UniCharToUtf(*chPtr, dst); - *chPtr = low; + dst += Tcl_UniCharToUtf(ch, dst); + ch = low; } - dst += Tcl_UniCharToUtf(*chPtr, dst); + dst += Tcl_UniCharToUtf(ch, dst); } } @@ -2407,7 +2321,7 @@ UtfToUtfProc( static int Utf16ToUtfProc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + ClientData clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in Unicode. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ @@ -2433,18 +2347,27 @@ Utf16ToUtfProc( int result, numChars, charLimit = INT_MAX; unsigned short ch; + flags |= PTR2INT(clientData); if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } result = TCL_OK; - /* check alignment with utf-16 (2 == sizeof(UTF-16)) */ + /* + * Check alignment with utf-16 (2 == sizeof(UTF-16)) + */ + if ((srcLen % 2) != 0) { result = TCL_CONVERT_MULTIBYTE; srcLen--; } - /* If last code point is a high surrogate, we cannot handle that yet */ - if ((srcLen >= 2) && ((src[srcLen - (clientData?1:2)] & 0xFC) == 0xD8)) { + + /* + * If last code point is a high surrogate, we cannot handle that yet. + */ + + if ((srcLen >= 2) && + ((src[srcLen - ((flags & TCL_ENCODING_LE)?1:2)] & 0xFC) == 0xD8)) { result = TCL_CONVERT_MULTIBYTE; srcLen-= 2; } @@ -2461,15 +2384,17 @@ Utf16ToUtfProc( break; } - if (clientData) { + if (flags & TCL_ENCODING_LE) { ch = (src[1] & 0xFF) << 8 | (src[0] & 0xFF); } else { ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF); } + /* * Special case for 1-byte utf chars for speed. Make sure we work with * unsigned short-size data. */ + if (ch && ch < 0x80) { *dst++ = (ch & 0xFF); } else { @@ -2502,15 +2427,11 @@ Utf16ToUtfProc( static int UtfToUtf16Proc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + ClientData clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ - Tcl_EncodingState *statePtr,/* Place for conversion routine to store state - * information used during a piecewise - * conversion. Contents of statePtr are - * initialized and/or reset by conversion - * routine under control of flags argument. */ + TCL_UNUSED(Tcl_EncodingState *), char *dst, /* Output buffer in which converted string is * stored. */ int dstLen, /* The maximum length of output buffer in @@ -2529,11 +2450,8 @@ UtfToUtf16Proc( { const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; - Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + int ch; - if (flags & TCL_ENCODING_START) { - *statePtr = 0; - } srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; @@ -2543,6 +2461,7 @@ UtfToUtf16Proc( dstStart = dst; dstEnd = dst + dstLen - sizeof(Tcl_UniChar); + flags |= PTR2INT(clientData); result = TCL_OK; for (numChars = 0; src < srcEnd; numChars++) { @@ -2559,38 +2478,27 @@ UtfToUtf16Proc( result = TCL_CONVERT_NOSPACE; break; } - src += TclUtfToUniChar(src, chPtr); - - if (clientData) { -#if TCL_UTF_MAX > 3 - if (*chPtr <= 0xFFFF) { - *dst++ = (*chPtr & 0xFF); - *dst++ = (*chPtr >> 8); + src += TclUtfToUCS4(src, &ch); + if (flags & TCL_ENCODING_LE) { + if (ch <= 0xFFFF) { + *dst++ = (ch & 0xFF); + *dst++ = (ch >> 8); } else { - *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); - *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; - *dst++ = (*chPtr & 0xFF); - *dst++ = ((*chPtr >> 8) & 0x3) | 0xDC; + *dst++ = (((ch - 0x10000) >> 10) & 0xFF); + *dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8; + *dst++ = (ch & 0xFF); + *dst++ = ((ch >> 8) & 0x3) | 0xDC; } -#else - *dst++ = (*chPtr & 0xFF); - *dst++ = (*chPtr >> 8); -#endif } else { -#if TCL_UTF_MAX > 3 - if (*chPtr <= 0xFFFF) { - *dst++ = (*chPtr >> 8); - *dst++ = (*chPtr & 0xFF); + if (ch <= 0xFFFF) { + *dst++ = (ch >> 8); + *dst++ = (ch & 0xFF); } else { - *dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8; - *dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF); - *dst++ = ((*chPtr >> 8) & 0x3) | 0xDC; - *dst++ = (*chPtr & 0xFF); + *dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8; + *dst++ = (((ch - 0x10000) >> 10) & 0xFF); + *dst++ = ((ch >> 8) & 0x3) | 0xDC; + *dst++ = (ch & 0xFF); } -#else - *dst++ = (*chPtr >> 8); - *dst++ = (*chPtr & 0xFF); -#endif } } *srcReadPtr = src - srcStart; @@ -2617,7 +2525,7 @@ UtfToUtf16Proc( static int UtfToUcs2Proc( - ClientData clientData, /* != NULL means LE, == NUL means BE */ + ClientData clientData, /* additional flags, e.g. TCL_ENCODING_LE */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ @@ -2645,6 +2553,7 @@ UtfToUcs2Proc( #endif Tcl_UniChar ch = 0; + flags |= PTR2INT(clientData); srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; @@ -2688,7 +2597,7 @@ UtfToUcs2Proc( * casting dst to a Tcl_UniChar. [Bug 1122671] */ - if (clientData) { + if (flags & TCL_ENCODING_LE) { *dst++ = (ch & 0xFF); *dst++ = (ch >> 8); } else { @@ -3096,7 +3005,9 @@ Iso88591FromUtfProc( break; } #if TCL_UTF_MAX <= 3 - if ((ch >= 0xD800) && (len < 3)) len = 4; + if ((ch >= 0xD800) && (len < 3)) { + len = 4; + } #endif /* * Plunge on, using '?' as a fallback character. @@ -3141,7 +3052,7 @@ TableFreeProc( ClientData clientData) /* TableEncodingData that specifies * encoding. */ { - TableEncodingData *dataPtr = (TableEncodingData *)clientData; + TableEncodingData *dataPtr = (TableEncodingData *) clientData; /* * Make sure we aren't freeing twice on shutdown. [Bug 219314] @@ -3199,7 +3110,7 @@ EscapeToUtfProc( * correspond to the bytes stored in the * output buffer. */ { - EscapeEncodingData *dataPtr = (EscapeEncodingData *)clientData; + EscapeEncodingData *dataPtr = (EscapeEncodingData *) clientData; const char *prefixBytes, *tablePrefixBytes, *srcStart, *srcEnd; const unsigned short *const *tableToUnicode; const Encoding *encodingPtr; diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 604bb78..f851c8a 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -1581,7 +1581,7 @@ Tcl_UpdateObjCmd( } switch ((enum updateOptionsEnum) optionIndex) { case OPT_IDLETASKS: - flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; + flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT; break; default: Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions"); diff --git a/generic/tclIO.c b/generic/tclIO.c index 9cace8c..3954af2 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3387,7 +3387,8 @@ int Tcl_Close( Tcl_Interp *interp, /* Interpreter for errors. */ Tcl_Channel chan) /* The channel being closed. Must not be - * referenced in any interpreter. */ + * referenced in any interpreter. May be NULL, + * in which case this is a no-op. */ { CloseCallback *cbPtr; /* Iterate over close callbacks for this * channel. */ diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index e6e8e58..88f6de8 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -56,12 +56,13 @@ static int ReflectGetOption(ClientData clientData, static int ReflectSetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, const char *newValue); +static int ReflectTruncate(ClientData clientData, + long long length); static void TimerRunRead(ClientData clientData); static void TimerRunWrite(ClientData clientData); /* - * The C layer channel type/driver definition used by the reflection. This is - * a version 3 structure. + * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRChannelType = { @@ -89,7 +90,7 @@ static const Tcl_ChannelType tclRChannelType = { #else NULL, /* thread action */ #endif - NULL /* truncate */ + ReflectTruncate /* Truncate. NULL'able */ }; /* @@ -187,6 +188,7 @@ static const char *const methodNames[] = { "initialize", /* */ "read", /* OPT */ "seek", /* OPT */ + "truncate", /* OPT */ "watch", /* */ "write", /* OPT */ NULL @@ -200,6 +202,7 @@ typedef enum { METH_INIT, METH_READ, METH_SEEK, + METH_TRUNCATE, METH_WATCH, METH_WRITE } MethodName; @@ -209,7 +212,8 @@ typedef enum { (FLAG(METH_INIT) | FLAG(METH_FINAL) | FLAG(METH_WATCH)) #define NULLABLE_METHODS \ (FLAG(METH_BLOCKING) | FLAG(METH_SEEK) | \ - FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | FLAG(METH_CGETALL)) + FLAG(METH_CONFIGURE) | FLAG(METH_CGET) | \ + FLAG(METH_CGETALL) | FLAG(METH_TRUNCATE)) #define RANDW \ (TCL_READABLE | TCL_WRITABLE) @@ -239,7 +243,8 @@ typedef enum { ForwardedBlock, ForwardedSetOpt, ForwardedGetOpt, - ForwardedGetOptAll + ForwardedGetOptAll, + ForwardedTruncate } ForwardedOperation; /* @@ -302,6 +307,10 @@ struct ForwardParamGetOpt { const char *name; /* Name of option to get, maybe NULL */ Tcl_DString *value; /* Result */ }; +struct ForwardParamTruncate { + ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ + Tcl_WideInt length; /* I: Length of file. */ +}; /* * Now join all these together in a single union for convenience. @@ -316,6 +325,7 @@ typedef union ForwardParam { struct ForwardParamBlock block; struct ForwardParamSetOpt setOpt; struct ForwardParamGetOpt getOpt; + struct ForwardParamTruncate truncate; } ForwardParam; /* @@ -706,6 +716,9 @@ TclChanCreateObjCmd( #endif clonePtr->wideSeekProc = NULL; } + if (!(methods & FLAG(METH_TRUNCATE))) { + clonePtr->truncateProc = NULL; + } chanPtr->typePtr = clonePtr; } @@ -2048,6 +2061,73 @@ ReflectGetOption( } /* + *---------------------------------------------------------------------- + * + * ReflectTruncate -- + * + * This function is invoked to truncate a channel's file size. + * + * Results: + * A standard Tcl result code. + * + * Side effects: + * Arbitrary, as it calls upon a Tcl script. + * + *---------------------------------------------------------------------- + */ + +static int +ReflectTruncate( + ClientData clientData, /* Channel to query */ + long long length) /* Length to truncate to. */ +{ + ReflectedChannel *rcPtr = (ReflectedChannel *)clientData; + Tcl_Obj *lenObj; + int errorNum; /* EINVAL or EOK (success). */ + Tcl_Obj *resObj; /* Result for 'truncate' */ + + /* + * Are we in the correct thread? + */ + +#ifdef TCL_THREADS + if (rcPtr->thread != Tcl_GetCurrentThread()) { + ForwardParam p; + + p.truncate.length = length; + + ForwardOpToHandlerThread(rcPtr, ForwardedTruncate, &p); + + if (p.base.code != TCL_OK) { + PassReceivedError(rcPtr->chan, &p); + return EINVAL; + } + + return EOK; + } +#endif + + /* ASSERT: rcPtr->method & FLAG(METH_TRUNCATE) */ + + Tcl_Preserve(rcPtr); + + lenObj = Tcl_NewIntObj(length); + Tcl_IncrRefCount(lenObj); + + if (InvokeTclMethod(rcPtr,METH_TRUNCATE,lenObj,NULL,&resObj)!=TCL_OK) { + Tcl_SetChannelError(rcPtr->chan, resObj); + errorNum = EINVAL; + } else { + errorNum = EOK; + } + + Tcl_DecrRefCount(lenObj); + Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ + Tcl_Release(rcPtr); + return errorNum; +} + +/* * Helpers. ========================================================= */ @@ -3278,6 +3358,19 @@ ForwardProc( Tcl_Release(rcPtr); break; + case ForwardedTruncate: { + Tcl_Obj *lenObj = Tcl_NewIntObj(paramPtr->truncate.length); + + Tcl_IncrRefCount(lenObj); + Tcl_Preserve(rcPtr); + if (InvokeTclMethod(rcPtr,METH_TRUNCATE,lenObj,NULL,&resObj)!=TCL_OK) { + ForwardSetObjError(paramPtr, resObj); + } + Tcl_Release(rcPtr); + Tcl_DecrRefCount(lenObj); + break; + } + default: /* * Bad operation code. diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index fc9989a..698b614 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -3009,7 +3009,7 @@ Tcl_FSLoadFile( const char *sym1, const char *sym2, /* Names of two functions to find in the * dynamic shared object. */ - Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, + Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, /* Places to store pointers to the functions * named by sym1 and sym2. */ Tcl_LoadHandle *handlePtr, /* A place to store the token for the loaded @@ -3027,8 +3027,8 @@ Tcl_FSLoadFile( res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr); if (res == TCL_OK) { - *proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0]; - *proc2Ptr = (Tcl_PackageInitProc *) procPtrs[1]; + *proc1Ptr = (Tcl_LibraryInitProc *) procPtrs[0]; + *proc2Ptr = (Tcl_LibraryInitProc *) procPtrs[1]; } else { *proc1Ptr = *proc2Ptr = NULL; } diff --git a/generic/tclIndexObj.c b/generic/tclIndexObj.c index f08278b..48ebb69 100644 --- a/generic/tclIndexObj.c +++ b/generic/tclIndexObj.c @@ -785,7 +785,7 @@ PrefixLongestObjCmd( * Adjust in case we stopped in the middle of a UTF char. */ - resultLength = TclUtfPrev(&resultString[i+1], + resultLength = Tcl_UtfPrev(&resultString[i+1], resultString) - resultString; break; } @@ -1332,7 +1332,6 @@ PrintUsage( int width, numSpaces; #define NUM_SPACES 20 static const char spaces[] = " "; - char tmp[TCL_DOUBLE_SPACE]; Tcl_Obj *msg; /* @@ -1382,7 +1381,6 @@ PrintUsage( case TCL_ARGV_FLOAT: Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: %g", *((double *) infoPtr->dstPtr)); - sprintf(tmp, "%g", *((double *) infoPtr->dstPtr)); break; case TCL_ARGV_STRING: { char *string = *((char **) infoPtr->dstPtr); diff --git a/generic/tclInt.decls b/generic/tclInt.decls index a4ed641..c7ead64 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -17,6 +17,7 @@ library tcl # Define the unsupported generic interfaces. interface tclInt +scspec EXTERN # Declare each of the functions in the unsupported internal Tcl # interface. These interfaces are allowed to changed between versions. @@ -239,8 +240,8 @@ declare 55 { # Replaced with TclpLoadFile in 8.1: # declare 56 { # int TclLoadFile(Tcl_Interp *interp, char *fileName, char *sym1, -# char *sym2, Tcl_PackageInitProc **proc1Ptr, -# Tcl_PackageInitProc **proc2Ptr) +# char *sym2, Tcl_LibraryInitProc **proc1Ptr, +# Tcl_LibraryInitProc **proc2Ptr) # } # Signature changed to take a length in 8.1: # declare 57 { @@ -552,8 +553,8 @@ declare 138 { } #declare 139 { # int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1, -# char *sym2, Tcl_PackageInitProc **proc1Ptr, -# Tcl_PackageInitProc **proc2Ptr, void **clientDataPtr) +# char *sym2, Tcl_LibraryInitProc **proc1Ptr, +# Tcl_LibraryInitProc **proc2Ptr, void **clientDataPtr) #} #declare 140 { # int TclLooksLikeInt(const char *bytes, int length) @@ -1025,8 +1026,8 @@ declare 256 { Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags) } declare 257 { - void TclStaticPackage(Tcl_Interp *interp, const char *pkgName, - Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) + void TclStaticLibrary(Tcl_Interp *interp, const char *prefix, + Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc) } # TIP 431: temporary directory creation function diff --git a/generic/tclInt.h b/generic/tclInt.h index cc4f6a9..b8ed3c1 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2739,7 +2739,6 @@ MODULE_SCOPE char *tclNativeExecutableName; MODULE_SCOPE int tclFindExecutableSearchDone; MODULE_SCOPE char *tclMemDumpFileName; MODULE_SCOPE TclPlatformType tclPlatform; -MODULE_SCOPE Tcl_NotifierProcs tclNotifierHooks; MODULE_SCOPE Tcl_Encoding tclIdentityEncoding; @@ -3044,7 +3043,7 @@ MODULE_SCOPE Tcl_Obj * TclGetSourceFromFrame(CmdFrame *cfPtr, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE char * TclGetStringStorage(Tcl_Obj *objPtr, unsigned int *sizePtr); -MODULE_SCOPE int TclGetLoadedPackagesEx(Tcl_Interp *interp, +MODULE_SCOPE int TclGetLoadedLibraries(Tcl_Interp *interp, const char *targetName, const char *packageName); MODULE_SCOPE int TclGetWideBitsFromObj(Tcl_Interp *, Tcl_Obj *, @@ -3133,12 +3132,21 @@ MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp, int code, int level, Tcl_Obj *returnOpts); MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); MODULE_SCOPE Tcl_Obj * TclpTempFileName(void); -MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp, Tcl_Obj* pathPtr); +MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp, + Tcl_Obj* pathPtr); MODULE_SCOPE Tcl_Obj * TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep, int len); +MODULE_SCOPE void TclpAlertNotifier(ClientData clientData); +MODULE_SCOPE void TclpServiceModeHook(int mode); +MODULE_SCOPE void TclpSetTimer(const Tcl_Time *timePtr); +MODULE_SCOPE int TclpWaitForEvent(const Tcl_Time *timePtr); +MODULE_SCOPE void TclpCreateFileHandler(int fd, int mask, + Tcl_FileProc *proc, ClientData clientData); MODULE_SCOPE int TclpDeleteFile(const void *path); +MODULE_SCOPE void TclpDeleteFileHandler(int fd); MODULE_SCOPE void TclpFinalizeCondition(Tcl_Condition *condPtr); MODULE_SCOPE void TclpFinalizeMutex(Tcl_Mutex *mutexPtr); +MODULE_SCOPE void TclpFinalizeNotifier(ClientData clientData); MODULE_SCOPE void TclpFinalizePipes(void); MODULE_SCOPE void TclpFinalizeSockets(void); MODULE_SCOPE int TclCreateSocketAddress(Tcl_Interp *interp, @@ -3152,6 +3160,7 @@ MODULE_SCOPE int TclpFindVariable(const char *name, int *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, unsigned int *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); +MODULE_SCOPE ClientData TclpInitNotifier(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); @@ -3178,8 +3187,9 @@ MODULE_SCOPE int TclpObjChdir(Tcl_Obj *pathPtr); MODULE_SCOPE Tcl_Channel TclpOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); -MODULE_SCOPE void TclPkgFileSeen(Tcl_Interp *interp, const char *fileName); -MODULE_SCOPE void *TclInitPkgFiles(Tcl_Interp *interp); +MODULE_SCOPE void TclPkgFileSeen(Tcl_Interp *interp, + const char *fileName); +MODULE_SCOPE void * TclInitPkgFiles(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_PathPart portion); MODULE_SCOPE char * TclpReadlink(const char *fileName, @@ -3253,16 +3263,10 @@ MODULE_SCOPE int TclUtfCount(int ch); # define TclUtfToUCS4 Tcl_UtfToUniChar # define TclUniCharToUCS4(src, ptr) (*ptr = *(src),1) # define TclUCS4Prev(src, ptr) (((src) > (ptr)) ? ((src) - 1) : (src)) -# define TclUCS4Complete Tcl_UtfCharComplete -# define TclChar16Complete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \ - ? ((length) >= 3) : Tcl_UtfCharComplete((src), (length))) #else MODULE_SCOPE int TclUtfToUCS4(const char *, int *); MODULE_SCOPE int TclUniCharToUCS4(const Tcl_UniChar *, int *); MODULE_SCOPE const Tcl_UniChar *TclUCS4Prev(const Tcl_UniChar *, const Tcl_UniChar *); -# define TclUCS4Complete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \ - ? ((length) >= 4) : Tcl_UtfCharComplete((src), (length))) -# define TclChar16Complete Tcl_UtfCharComplete #endif MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData); MODULE_SCOPE Tcl_Obj * TclpFilesystemPathType(Tcl_Obj *pathPtr); @@ -4218,6 +4222,37 @@ MODULE_SCOPE int TclIndexDecode(int encoded, int endValue); #define TCL_INDEX_START (0) /* + *---------------------------------------------------------------------- + * + * TclScaleTime -- + * + * TIP #233 (Virtualized Time): Wrapper around the time virutalisation + * rescale function to hide the binding of the clientData. + * + * This is static inline code; it's like a macro, but a function. It's + * used because this is a piece of code that ends up in places that are a + * bit performance sensitive. + * + * Results: + * None + * + * Side effects: + * Updates the time structure (given as an argument) with what the time + * should be after virtualisation. + * + *---------------------------------------------------------------------- + */ + +static inline void +TclScaleTime( + Tcl_Time *timePtr) +{ + if (timePtr != NULL) { + tclScaleTimeProcPtr(timePtr, tclTimeClientData); + } +} + +/* *---------------------------------------------------------------- * Macros used by the Tcl core to create and release Tcl objects. * TclNewObj(objPtr) creates a new object denoting an empty string. @@ -4696,11 +4731,6 @@ MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; (numChars) = _count; \ } while (0); -#define TclUtfPrev(src, start) \ - (((src) < (start) + 2) ? (start) : \ - ((unsigned char) *((src) - 1)) < 0x80 ? (src) - 1 : \ - Tcl_UtfPrev(src, start)) - /* *---------------------------------------------------------------- * Macro that encapsulates the logic that determines when it is safe to @@ -4737,7 +4767,7 @@ MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ -#ifdef WORDS_BIGENDIAN +#if defined(WORDS_BIGENDIAN) && (TCL_UTF_MAX > 3) # define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar)) #else /* !WORDS_BIGENDIAN */ # define TclUniCharNcmp Tcl_UniCharNcmp @@ -4768,7 +4798,7 @@ MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); *---------------------------------------------------------------------- */ -MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init; +MODULE_SCOPE Tcl_LibraryInitProc TclTommath_Init; /* *---------------------------------------------------------------------- @@ -4780,11 +4810,11 @@ MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init; *---------------------------------------------------------------------- */ -MODULE_SCOPE Tcl_PackageInitProc TclplatformtestInit; -MODULE_SCOPE Tcl_PackageInitProc TclObjTest_Init; -MODULE_SCOPE Tcl_PackageInitProc TclThread_Init; -MODULE_SCOPE Tcl_PackageInitProc Procbodytest_Init; -MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit; +MODULE_SCOPE Tcl_LibraryInitProc TclplatformtestInit; +MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init; +MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init; +MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init; +MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit; /* *---------------------------------------------------------------- @@ -5156,11 +5186,33 @@ typedef struct NRE_callback { #endif /* + * Special hack for macOS, where the static linker (technically the 'ar' + * command) hates empty object files, and accepts no flags to make it shut up. + * + * These symbols are otherwise completely useless. + * + * They can't be written to or written through. They can't be seen by any + * other code. They use a separate attribute (supported by all macOS + * compilers, which are derivatives of clang or gcc) to stop the compilation + * from moaning. They will be excluded during the final linking stage. + * + * Other platforms get nothing at all. That's good. + */ + +#ifdef MAC_OSX_TCL +#define TCL_MAC_EMPTY_FILE(name) \ + static __attribute__((used)) const void *const TclUnusedFile_ ## name; \ + static const void *const TclUnusedFile_ ## name = NULL; +#else +#define TCL_MAC_EMPTY_FILE(name) +#endif /* MAC_OSX_TCL */ + +/* * Other externals. */ -MODULE_SCOPE size_t TclEnvEpoch; /* Epoch of the tcl environment - * (if changed with tcl-env). */ +MODULE_SCOPE size_t TclEnvEpoch; /* Epoch of the tcl environment + * (if changed with tcl-env). */ #endif /* _TCLINT */ diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h index 1e7e26d..bfd3102 100644 --- a/generic/tclIntDecls.h +++ b/generic/tclIntDecls.h @@ -651,10 +651,10 @@ EXTERN int TclPtrUnsetVar(Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 257 */ -EXTERN void TclStaticPackage(Tcl_Interp *interp, - const char *pkgName, - Tcl_PackageInitProc *initProc, - Tcl_PackageInitProc *safeInitProc); +EXTERN void TclStaticLibrary(Tcl_Interp *interp, + const char *prefix, + Tcl_LibraryInitProc *initProc, + Tcl_LibraryInitProc *safeInitProc); /* 258 */ EXTERN Tcl_Obj * TclpCreateTemporaryDirectory(Tcl_Obj *dirObj, Tcl_Obj *basenameObj); @@ -925,7 +925,7 @@ typedef struct TclIntStubs { Tcl_Obj * (*tclPtrIncrObjVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags); /* 254 */ int (*tclPtrObjMakeUpvar) (Tcl_Interp *interp, Tcl_Var otherPtr, Tcl_Obj *myNamePtr, int myFlags); /* 255 */ int (*tclPtrUnsetVar) (Tcl_Interp *interp, Tcl_Var varPtr, Tcl_Var arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags); /* 256 */ - void (*tclStaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 257 */ + void (*tclStaticLibrary) (Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); /* 257 */ Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 258 */ unsigned char * (*tclGetBytesFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *lengthPtr); /* 259 */ void (*tclUnusedStubEntry) (void); /* 260 */ @@ -1370,8 +1370,8 @@ extern const TclIntStubs *tclIntStubsPtr; (tclIntStubsPtr->tclPtrObjMakeUpvar) /* 255 */ #define TclPtrUnsetVar \ (tclIntStubsPtr->tclPtrUnsetVar) /* 256 */ -#define TclStaticPackage \ - (tclIntStubsPtr->tclStaticPackage) /* 257 */ +#define TclStaticLibrary \ + (tclIntStubsPtr->tclStaticLibrary) /* 257 */ #define TclpCreateTemporaryDirectory \ (tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 258 */ #define TclGetBytesFromObj \ @@ -1409,11 +1409,12 @@ extern const TclIntStubs *tclIntStubsPtr; # undef TclGetCommandFullName # undef TclCopyChannelOld # undef TclSockMinimumBuffersOld -# undef Tcl_StaticPackage -# define Tcl_StaticPackage (tclIntStubsPtr->tclStaticPackage) +# undef Tcl_StaticLibrary +# define Tcl_StaticLibrary (tclIntStubsPtr->tclStaticLibrary) #endif #undef TclGuessPackageName +#undef TclUnusedStubEntry #ifndef TCL_NO_DEPRECATED # define TclGuessPackageName(fileName, pkgName) ((void)fileName,(void)pkgName,0) #endif diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index de308de..bd8d8e5 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -570,6 +570,11 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; #undef TclpGmtime_unix #undef TclWinConvertWSAError #define TclWinConvertWSAError TclWinConvertError +#if !defined(TCL_USE_STUBS) && !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 +# undef TclWinConvertError +# define TclWinConvertError Tcl_WinConvertError +#endif + #undef TclpInetNtoa #define TclpInetNtoa inet_ntoa diff --git a/generic/tclLoad.c b/generic/tclLoad.c index 8b8aa2b..c9d1b31 100644 --- a/generic/tclLoad.c +++ b/generic/tclLoad.c @@ -13,81 +13,81 @@ #include "tclInt.h" /* - * The following structure describes a package that has been loaded either + * The following structure describes a library that has been loaded either * dynamically (with the "load" command) or statically (as indicated by a call - * to TclGetLoadedPackages). All such packages are linked together into a - * single list for the process. Packages are never unloaded, until the + * to Tcl_StaticLibrary). All such libraries are linked together into a + * single list for the process. Library are never unloaded, until the * application exits, when TclFinalizeLoad is called, and these structures are * freed. */ -typedef struct LoadedPackage { - char *fileName; /* Name of the file from which the package was - * loaded. An empty string means the package +typedef struct LoadedLibrary { + char *fileName; /* Name of the file from which the library was + * loaded. An empty string means the library * is loaded statically. Malloc-ed. */ - char *packageName; /* Name of package prefix for the package, + char *prefix; /* Prefix for the library, * properly capitalized (first letter UC, - * others LC), no "_", as in "Net". + * others LC), as in "Net". * Malloc-ed. */ Tcl_LoadHandle loadHandle; /* Token for the loaded file which should be * passed to (*unLoadProcPtr)() when the file * is no longer needed. If fileName is NULL, * then this field is irrelevant. */ - Tcl_PackageInitProc *initProc; + Tcl_LibraryInitProc *initProc; /* Initialization function to call to - * incorporate this package into a trusted + * incorporate this library into a trusted * interpreter. */ - Tcl_PackageInitProc *safeInitProc; + Tcl_LibraryInitProc *safeInitProc; /* Initialization function to call to - * incorporate this package into a safe + * incorporate this library into a safe * interpreter (one that will execute - * untrusted scripts). NULL means the package + * untrusted scripts). NULL means the library * can't be used in unsafe interpreters. */ - Tcl_PackageUnloadProc *unloadProc; - /* Finalisation function to unload a package + Tcl_LibraryUnloadProc *unloadProc; + /* Finalization function to unload a library * from a trusted interpreter. NULL means that - * the package cannot be unloaded. */ - Tcl_PackageUnloadProc *safeUnloadProc; - /* Finalisation function to unload a package + * the library cannot be unloaded. */ + Tcl_LibraryUnloadProc *safeUnloadProc; + /* Finalization function to unload a library * from a safe interpreter. NULL means that - * the package cannot be unloaded. */ - int interpRefCount; /* How many times the package has been loaded + * the library cannot be unloaded. */ + int interpRefCount; /* How many times the library has been loaded * in trusted interpreters. */ - int safeInterpRefCount; /* How many times the package has been loaded + int safeInterpRefCount; /* How many times the library has been loaded * in safe interpreters. */ - struct LoadedPackage *nextPtr; - /* Next in list of all packages loaded into + struct LoadedLibrary *nextPtr; + /* Next in list of all libraries loaded into * this application process. NULL means end of * list. */ -} LoadedPackage; +} LoadedLibrary; /* * TCL_THREADS - * There is a global list of packages that is anchored at firstPackagePtr. + * There is a global list of libraries that is anchored at firstLibraryPtr. * Access to this list is governed by a mutex. */ -static LoadedPackage *firstPackagePtr = NULL; - /* First in list of all packages loaded into +static LoadedLibrary *firstLibraryPtr = NULL; + /* First in list of all libraries loaded into * this process. */ -TCL_DECLARE_MUTEX(packageMutex) +TCL_DECLARE_MUTEX(libraryMutex) /* - * The following structure represents a particular package that has been + * The following structure represents a particular library that has been * incorporated into a particular interpreter (by calling its initialization * function). There is a list of these structures for each interpreter, with * an AssocData value (key "load") for the interpreter that points to the - * first package (if any). + * first library (if any). */ -typedef struct InterpPackage { - LoadedPackage *pkgPtr; /* Points to detailed information about - * package. */ - struct InterpPackage *nextPtr; - /* Next package in this interpreter, or NULL +typedef struct InterpLibrary { + LoadedLibrary *libraryPtr; /* Points to detailed information about + * library. */ + struct InterpLibrary *nextPtr; + /* Next library in this interpreter, or NULL * for end of list. */ -} InterpPackage; +} InterpLibrary; /* * Prototypes for functions that are private to this file: @@ -121,14 +121,14 @@ Tcl_LoadObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; - LoadedPackage *pkgPtr, *defaultPtr; - Tcl_DString pkgName, tmp, initName, safeInitName; + LoadedLibrary *libraryPtr, *defaultPtr; + Tcl_DString pfx, tmp, initName, safeInitName; Tcl_DString unloadName, safeUnloadName; - InterpPackage *ipFirstPtr, *ipPtr; + InterpLibrary *ipFirstPtr, *ipPtr; int code, namesMatch, filesMatch, offset; const char *symbols[2]; - Tcl_PackageInitProc *initProc; - const char *p, *fullFileName, *packageName; + Tcl_LibraryInitProc *initProc; + const char *p, *fullFileName, *prefix; Tcl_LoadHandle loadHandle; Tcl_UniChar ch = 0; unsigned len; @@ -159,7 +159,7 @@ Tcl_LoadObjCmd( } } if ((objc < 2) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?packageName? ?interp?"); + Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { @@ -167,23 +167,23 @@ Tcl_LoadObjCmd( } fullFileName = Tcl_GetString(objv[1]); - Tcl_DStringInit(&pkgName); + Tcl_DStringInit(&pfx); Tcl_DStringInit(&initName); Tcl_DStringInit(&safeInitName); Tcl_DStringInit(&unloadName); Tcl_DStringInit(&safeUnloadName); Tcl_DStringInit(&tmp); - packageName = NULL; + prefix = NULL; if (objc >= 3) { - packageName = Tcl_GetString(objv[2]); - if (packageName[0] == '\0') { - packageName = NULL; + prefix = Tcl_GetString(objv[2]); + if (prefix[0] == '\0') { + prefix = NULL; } } - if ((fullFileName[0] == 0) && (packageName == NULL)) { + if ((fullFileName[0] == 0) && (prefix == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "must specify either file name or package name", -1)); + "must specify either file name or prefix", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY", NULL); code = TCL_ERROR; @@ -191,7 +191,7 @@ Tcl_LoadObjCmd( } /* - * Figure out which interpreter we're going to load the package into. + * Figure out which interpreter we're going to load the library into. */ target = interp; @@ -206,89 +206,89 @@ Tcl_LoadObjCmd( } /* - * Scan through the packages that are currently loaded to see if the - * package we want is already loaded. We'll use a loaded package if it + * Scan through the libraries that are currently loaded to see if the + * library we want is already loaded. We'll use a loaded library if it * meets any of the following conditions: * - Its name and file match the once we're looking for. * - Its file matches, and we weren't given a name. * - Its name matches, the file name was specified as empty, and there is - * only no statically loaded package with the same name. + * only no statically loaded library with the same prefix. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); defaultPtr = NULL; - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { - if (packageName == NULL) { + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { + if (prefix == NULL) { namesMatch = 0; } else { - TclDStringClear(&pkgName); - Tcl_DStringAppend(&pkgName, packageName, -1); + TclDStringClear(&pfx); + Tcl_DStringAppend(&pfx, prefix, -1); TclDStringClear(&tmp); - Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); - Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); + Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1); + Tcl_UtfToLower(Tcl_DStringValue(&pfx)); Tcl_UtfToLower(Tcl_DStringValue(&tmp)); if (strcmp(Tcl_DStringValue(&tmp), - Tcl_DStringValue(&pkgName)) == 0) { + Tcl_DStringValue(&pfx)) == 0) { namesMatch = 1; } else { namesMatch = 0; } } - TclDStringClear(&pkgName); + TclDStringClear(&pfx); - filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); - if (filesMatch && (namesMatch || (packageName == NULL))) { + filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0); + if (filesMatch && (namesMatch || (prefix == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { - defaultPtr = pkgPtr; + defaultPtr = libraryPtr; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { /* - * Can't have two different packages loaded from the same file. + * Can't have two different libraries loaded from the same file. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "file \"%s\" is already loaded for package \"%s\"", - fullFileName, pkgPtr->packageName)); + "file \"%s\" is already loaded for prefix \"%s\"", + fullFileName, libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "SPLITPERSONALITY", NULL); code = TCL_ERROR; - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); goto done; } } - Tcl_MutexUnlock(&packageMutex); - if (pkgPtr == NULL) { - pkgPtr = defaultPtr; + Tcl_MutexUnlock(&libraryMutex); + if (libraryPtr == NULL) { + libraryPtr = defaultPtr; } /* - * Scan through the list of packages already loaded in the target - * interpreter. If the package we want is already loaded there, then + * Scan through the list of libraries already loaded in the target + * interpreter. If the library we want is already loaded there, then * there's nothing for us to do. */ - if (pkgPtr != NULL) { - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + if (libraryPtr != NULL) { + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { code = TCL_OK; goto done; } } } - if (pkgPtr == NULL) { + if (libraryPtr == NULL) { /* * The desired file isn't currently loaded, so load it. It's an error - * if the desired package is a static one. + * if the desired library is a static one. */ if (fullFileName[0] == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "package \"%s\" isn't loaded statically", packageName)); + "no library with prefix \"%s\" is loaded statically", prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC", NULL); code = TCL_ERROR; @@ -296,11 +296,11 @@ Tcl_LoadObjCmd( } /* - * Figure out the module name if it wasn't provided explicitly. + * Figure out the prefix if it wasn't provided explicitly. */ - if (packageName != NULL) { - Tcl_DStringAppend(&pkgName, packageName, -1); + if (prefix != NULL) { + Tcl_DStringAppend(&pfx, prefix, -1); } else { Tcl_Obj *splitPtr, *pkgGuessPtr; int pElements; @@ -311,11 +311,11 @@ Tcl_LoadObjCmd( */ /* - * The platform-specific code couldn't figure out the module - * name. Make a guess by taking the last element of the file - * name, stripping off any leading "lib", and then using all - * of the alphabetic and underline characters that follow - * that. + * The platform-specific code couldn't figure out the prefix. + * Make a guess by taking the last element of the file + * name, stripping off any leading "lib" and/or "tcl", and + * then using all of the alphabetic and underline characters + * that follow that. */ splitPtr = Tcl_FSSplitPath(objv[1], &pElements); @@ -346,85 +346,85 @@ Tcl_LoadObjCmd( if (p == pkgGuess) { Tcl_DecrRefCount(splitPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't figure out package name for %s", + "couldn't figure out prefix for %s", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", - "WHATPACKAGE", NULL); + "WHATLIBRARY", NULL); code = TCL_ERROR; goto done; } - Tcl_DStringAppend(&pkgName, pkgGuess, p - pkgGuess); + Tcl_DStringAppend(&pfx, pkgGuess, p - pkgGuess); Tcl_DecrRefCount(splitPtr); } /* - * Fix the capitalization in the package name so that the first + * Fix the capitalization in the prefix so that the first * character is in caps (or title case) but the others are all * lower-case. */ - Tcl_DStringSetLength(&pkgName, - Tcl_UtfToTitle(Tcl_DStringValue(&pkgName))); + Tcl_DStringSetLength(&pfx, + Tcl_UtfToTitle(Tcl_DStringValue(&pfx))); /* * Compute the names of the two initialization functions, based on the - * package name. + * prefix. */ - TclDStringAppendDString(&initName, &pkgName); + TclDStringAppendDString(&initName, &pfx); TclDStringAppendLiteral(&initName, "_Init"); - TclDStringAppendDString(&safeInitName, &pkgName); + TclDStringAppendDString(&safeInitName, &pfx); TclDStringAppendLiteral(&safeInitName, "_SafeInit"); - TclDStringAppendDString(&unloadName, &pkgName); + TclDStringAppendDString(&unloadName, &pfx); TclDStringAppendLiteral(&unloadName, "_Unload"); - TclDStringAppendDString(&safeUnloadName, &pkgName); + TclDStringAppendDString(&safeUnloadName, &pfx); TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload"); /* - * Call platform-specific code to load the package and find the two + * Call platform-specific code to load the library and find the two * initialization functions. */ symbols[0] = Tcl_DStringValue(&initName); symbols[1] = NULL; - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc, &loadHandle); - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); if (code != TCL_OK) { goto done; } /* - * Create a new record to describe this package. + * Create a new record to describe this library. */ - pkgPtr = (LoadedPackage *)ckalloc(sizeof(LoadedPackage)); + libraryPtr = (LoadedLibrary *)ckalloc(sizeof(LoadedLibrary)); len = strlen(fullFileName) + 1; - pkgPtr->fileName = (char *)ckalloc(len); - memcpy(pkgPtr->fileName, fullFileName, len); - len = Tcl_DStringLength(&pkgName) + 1; - pkgPtr->packageName = (char *)ckalloc(len); - memcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName), len); - pkgPtr->loadHandle = loadHandle; - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = (Tcl_PackageInitProc *) + libraryPtr->fileName = (char *)ckalloc(len); + memcpy(libraryPtr->fileName, fullFileName, len); + len = Tcl_DStringLength(&pfx) + 1; + libraryPtr->prefix = (char *)ckalloc(len); + memcpy(libraryPtr->prefix, Tcl_DStringValue(&pfx), len); + libraryPtr->loadHandle = loadHandle; + libraryPtr->initProc = initProc; + libraryPtr->safeInitProc = (Tcl_LibraryInitProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeInitName)); - pkgPtr->unloadProc = (Tcl_PackageUnloadProc *) + libraryPtr->unloadProc = (Tcl_LibraryUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&unloadName)); - pkgPtr->safeUnloadProc = (Tcl_PackageUnloadProc *) + libraryPtr->safeUnloadProc = (Tcl_LibraryUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeUnloadName)); - pkgPtr->interpRefCount = 0; - pkgPtr->safeInterpRefCount = 0; + libraryPtr->interpRefCount = 0; + libraryPtr->safeInterpRefCount = 0; - Tcl_MutexLock(&packageMutex); - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexLock(&libraryMutex); + libraryPtr->nextPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr; + Tcl_MutexUnlock(&libraryMutex); /* * The Tcl_FindSymbol calls may have left a spurious error message in @@ -435,32 +435,32 @@ Tcl_LoadObjCmd( } /* - * Invoke the package's initialization function (either the normal one or + * Invoke the library's initialization function (either the normal one or * the safe one, depending on whether or not the interpreter is safe). */ if (Tcl_IsSafe(target)) { - if (pkgPtr->safeInitProc == NULL) { + if (libraryPtr->safeInitProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't use package in a safe interpreter: no" - " %s_SafeInit procedure", pkgPtr->packageName)); + "can't use library in a safe interpreter: no" + " %s_SafeInit procedure", libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE", NULL); code = TCL_ERROR; goto done; } - code = pkgPtr->safeInitProc(target); + code = libraryPtr->safeInitProc(target); } else { - if (pkgPtr->initProc == NULL) { + if (libraryPtr->initProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't attach package to interpreter: no %s_Init procedure", - pkgPtr->packageName)); + "can't attach library to interpreter: no %s_Init procedure", + libraryPtr->prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT", NULL); code = TCL_ERROR; goto done; } - code = pkgPtr->initProc(target); + code = libraryPtr->initProc(target); } /* @@ -487,33 +487,33 @@ Tcl_LoadObjCmd( } /* - * Record the fact that the package has been loaded in the target + * Record the fact that the library has been loaded in the target * interpreter. * * Update the proper reference count. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); if (Tcl_IsSafe(target)) { - pkgPtr->safeInterpRefCount++; + libraryPtr->safeInterpRefCount++; } else { - pkgPtr->interpRefCount++; + libraryPtr->interpRefCount++; } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); /* - * Refetch ipFirstPtr: loading the package may have introduced additional - * static packages at the head of the linked list! + * Refetch ipFirstPtr: loading the library may have introduced additional + * static libraries at the head of the linked list! */ - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); - ipPtr = (InterpPackage *)ckalloc(sizeof(InterpPackage)); - ipPtr->pkgPtr = pkgPtr; + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); + ipPtr = (InterpLibrary *)ckalloc(sizeof(InterpLibrary)); + ipPtr->libraryPtr = libraryPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr); done: - Tcl_DStringFree(&pkgName); + Tcl_DStringFree(&pfx); Tcl_DStringFree(&initName); Tcl_DStringFree(&safeInitName); Tcl_DStringFree(&unloadName); @@ -547,14 +547,14 @@ Tcl_UnloadObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; /* Which interpreter to unload from. */ - LoadedPackage *pkgPtr, *defaultPtr; - Tcl_DString pkgName, tmp; - Tcl_PackageUnloadProc *unloadProc; - InterpPackage *ipFirstPtr, *ipPtr; + LoadedLibrary *libraryPtr, *defaultPtr; + Tcl_DString pfx, tmp; + Tcl_LibraryUnloadProc *unloadProc; + InterpLibrary *ipFirstPtr, *ipPtr; int i, index, code, complain = 1, keepLibrary = 0; int trustedRefCount = -1, safeRefCount = -1; const char *fullFileName = ""; - const char *packageName; + const char *prefix; static const char *const options[] = { "-nocomplain", "-keeplibrary", "--", NULL }; @@ -598,7 +598,7 @@ Tcl_UnloadObjCmd( endOfForLoop: if ((objc-i < 1) || (objc-i > 3)) { Tcl_WrongNumArgs(interp, 1, objv, - "?-switch ...? fileName ?packageName? ?interp?"); + "?-switch ...? fileName ?prefix? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) { @@ -606,19 +606,19 @@ Tcl_UnloadObjCmd( } fullFileName = Tcl_GetString(objv[i]); - Tcl_DStringInit(&pkgName); + Tcl_DStringInit(&pfx); Tcl_DStringInit(&tmp); - packageName = NULL; + prefix = NULL; if (objc - i >= 2) { - packageName = Tcl_GetString(objv[i+1]); - if (packageName[0] == '\0') { - packageName = NULL; + prefix = Tcl_GetString(objv[i+1]); + if (prefix[0] == '\0') { + prefix = NULL; } } - if ((fullFileName[0] == 0) && (packageName == NULL)) { + if ((fullFileName[0] == 0) && (prefix == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "must specify either file name or package name", -1)); + "must specify either file name or prefix", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY", NULL); code = TCL_ERROR; @@ -626,7 +626,7 @@ Tcl_UnloadObjCmd( } /* - * Figure out which interpreter we're going to load the package into. + * Figure out which interpreter we're going to load the library into. */ target = interp; @@ -640,65 +640,65 @@ Tcl_UnloadObjCmd( } /* - * Scan through the packages that are currently loaded to see if the - * package we want is already loaded. We'll use a loaded package if it + * Scan through the libraries that are currently loaded to see if the + * library we want is already loaded. We'll use a loaded library if it * meets any of the following conditions: - * - Its name and file match the once we're looking for. - * - Its file matches, and we weren't given a name. - * - Its name matches, the file name was specified as empty, and there is - * only no statically loaded package with the same name. + * - Its prefix and file match the once we're looking for. + * - Its file matches, and we weren't given a prefix. + * - Its prefix matches, the file name was specified as empty, and there is + * only no statically loaded library with the same prefix. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); defaultPtr = NULL; - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { int namesMatch, filesMatch; - if (packageName == NULL) { + if (prefix == NULL) { namesMatch = 0; } else { - TclDStringClear(&pkgName); - Tcl_DStringAppend(&pkgName, packageName, -1); + TclDStringClear(&pfx); + Tcl_DStringAppend(&pfx, prefix, -1); TclDStringClear(&tmp); - Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); - Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); + Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1); + Tcl_UtfToLower(Tcl_DStringValue(&pfx)); Tcl_UtfToLower(Tcl_DStringValue(&tmp)); if (strcmp(Tcl_DStringValue(&tmp), - Tcl_DStringValue(&pkgName)) == 0) { + Tcl_DStringValue(&pfx)) == 0) { namesMatch = 1; } else { namesMatch = 0; } } - TclDStringClear(&pkgName); + TclDStringClear(&pfx); - filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); - if (filesMatch && (namesMatch || (packageName == NULL))) { + filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0); + if (filesMatch && (namesMatch || (prefix == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { - defaultPtr = pkgPtr; + defaultPtr = libraryPtr; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { break; } } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); if (fullFileName[0] == 0) { /* - * It's an error to try unload a static package. + * It's an error to try unload a static library. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "package \"%s\" is loaded statically and cannot be unloaded", - packageName)); + "library with prefix \"%s\" is loaded statically and cannot be unloaded", + prefix)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC", NULL); code = TCL_ERROR; goto done; } - if (pkgPtr == NULL) { + if (libraryPtr == NULL) { /* * The DLL pointed by the provided filename has never been loaded. */ @@ -712,16 +712,16 @@ Tcl_UnloadObjCmd( } /* - * Scan through the list of packages already loaded in the target - * interpreter. If the package we want is already loaded there, then we + * Scan through the list of libraries already loaded in the target + * interpreter. If the library we want is already loaded there, then we * should proceed with unloading. */ code = TCL_ERROR; - if (pkgPtr != NULL) { - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + if (libraryPtr != NULL) { + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { code = TCL_OK; break; } @@ -729,7 +729,7 @@ Tcl_UnloadObjCmd( } if (code != TCL_OK) { /* - * The package has not been loaded in this interpreter. + * The library has not been loaded in this interpreter. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -743,12 +743,12 @@ Tcl_UnloadObjCmd( /* * Ensure that the DLL can be unloaded. If it is a trusted interpreter, - * pkgPtr->unloadProc must not be NULL for the DLL to be unloadable. If - * the interpreter is a safe one, pkgPtr->safeUnloadProc must be non-NULL. + * libraryPtr->unloadProc must not be NULL for the DLL to be unloadable. If + * the interpreter is a safe one, libraryPtr->safeUnloadProc must be non-NULL. */ if (Tcl_IsSafe(target)) { - if (pkgPtr->safeUnloadProc == NULL) { + if (libraryPtr->safeUnloadProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" cannot be unloaded under a safe interpreter", fullFileName)); @@ -757,9 +757,9 @@ Tcl_UnloadObjCmd( code = TCL_ERROR; goto done; } - unloadProc = pkgPtr->safeUnloadProc; + unloadProc = libraryPtr->safeUnloadProc; } else { - if (pkgPtr->unloadProc == NULL) { + if (libraryPtr->unloadProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" cannot be unloaded under a trusted interpreter", fullFileName)); @@ -768,11 +768,11 @@ Tcl_UnloadObjCmd( code = TCL_ERROR; goto done; } - unloadProc = pkgPtr->unloadProc; + unloadProc = libraryPtr->unloadProc; } /* - * We are ready to unload the package. First, evaluate the unload + * We are ready to unload the library. First, evaluate the unload * function. If this fails, we cannot proceed with unload. Also, we must * specify the proper flag to pass to the unload callback. * TCL_UNLOAD_DETACH_FROM_INTERPRETER is defined when the callback should @@ -783,10 +783,10 @@ Tcl_UnloadObjCmd( code = TCL_UNLOAD_DETACH_FROM_INTERPRETER; if (!keepLibrary) { - Tcl_MutexLock(&packageMutex); - trustedRefCount = pkgPtr->interpRefCount; - safeRefCount = pkgPtr->safeInterpRefCount; - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexLock(&libraryMutex); + trustedRefCount = libraryPtr->interpRefCount; + safeRefCount = libraryPtr->safeInterpRefCount; + Tcl_MutexUnlock(&libraryMutex); if (Tcl_IsSafe(target)) { safeRefCount--; @@ -809,34 +809,34 @@ Tcl_UnloadObjCmd( * if we unload the DLL. */ - Tcl_MutexLock(&packageMutex); + Tcl_MutexLock(&libraryMutex); if (Tcl_IsSafe(target)) { - pkgPtr->safeInterpRefCount--; + libraryPtr->safeInterpRefCount--; /* * Do not let counter get negative. */ - if (pkgPtr->safeInterpRefCount < 0) { - pkgPtr->safeInterpRefCount = 0; + if (libraryPtr->safeInterpRefCount < 0) { + libraryPtr->safeInterpRefCount = 0; } } else { - pkgPtr->interpRefCount--; + libraryPtr->interpRefCount--; /* * Do not let counter get negative. */ - if (pkgPtr->interpRefCount < 0) { - pkgPtr->interpRefCount = 0; + if (libraryPtr->interpRefCount < 0) { + libraryPtr->interpRefCount = 0; } } - trustedRefCount = pkgPtr->interpRefCount; - safeRefCount = pkgPtr->safeInterpRefCount; - Tcl_MutexUnlock(&packageMutex); + trustedRefCount = libraryPtr->interpRefCount; + safeRefCount = libraryPtr->safeInterpRefCount; + Tcl_MutexUnlock(&libraryMutex); code = TCL_OK; - if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0 + if (libraryPtr->safeInterpRefCount <= 0 && libraryPtr->interpRefCount <= 0 && !keepLibrary) { /* * Unload the shared library from the application memory... @@ -850,21 +850,21 @@ Tcl_UnloadObjCmd( * it's been unloaded. */ - if (pkgPtr->fileName[0] != '\0') { - Tcl_MutexLock(&packageMutex); - if (Tcl_FSUnloadFile(interp, pkgPtr->loadHandle) == TCL_OK) { + if (libraryPtr->fileName[0] != '\0') { + Tcl_MutexLock(&libraryMutex); + if (Tcl_FSUnloadFile(interp, libraryPtr->loadHandle) == TCL_OK) { /* * Remove this library from the loaded library cache. */ - defaultPtr = pkgPtr; - if (defaultPtr == firstPackagePtr) { - firstPackagePtr = pkgPtr->nextPtr; + defaultPtr = libraryPtr; + if (defaultPtr == firstLibraryPtr) { + firstLibraryPtr = libraryPtr->nextPtr; } else { - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; - pkgPtr = pkgPtr->nextPtr) { - if (pkgPtr->nextPtr == defaultPtr) { - pkgPtr->nextPtr = defaultPtr->nextPtr; + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; + libraryPtr = libraryPtr->nextPtr) { + if (libraryPtr->nextPtr == defaultPtr) { + libraryPtr->nextPtr = defaultPtr->nextPtr; break; } } @@ -874,16 +874,16 @@ Tcl_UnloadObjCmd( * Remove this library from the interpreter's library cache. */ - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); ipPtr = ipFirstPtr; - if (ipPtr->pkgPtr == defaultPtr) { + if (ipPtr->libraryPtr == defaultPtr) { ipFirstPtr = ipFirstPtr->nextPtr; } else { - InterpPackage *ipPrevPtr; + InterpLibrary *ipPrevPtr; for (ipPrevPtr = ipPtr; ipPtr != NULL; ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == defaultPtr) { + if (ipPtr->libraryPtr == defaultPtr) { ipPrevPtr->nextPtr = ipPtr->nextPtr; break; } @@ -892,10 +892,10 @@ Tcl_UnloadObjCmd( Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); ckfree(defaultPtr->fileName); - ckfree(defaultPtr->packageName); + ckfree(defaultPtr->prefix); ckfree(defaultPtr); ckfree(ipPtr); - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); } else { code = TCL_ERROR; } @@ -911,7 +911,7 @@ Tcl_UnloadObjCmd( } done: - Tcl_DStringFree(&pkgName); + Tcl_DStringFree(&pfx); Tcl_DStringFree(&tmp); if (!complain && (code != TCL_OK)) { code = TCL_OK; @@ -923,99 +923,99 @@ Tcl_UnloadObjCmd( /* *---------------------------------------------------------------------- * - * Tcl_StaticPackage -- + * Tcl_StaticLibrary -- * - * This function is invoked to indicate that a particular package has + * This function is invoked to indicate that a particular library has * been linked statically with an application. * * Results: * None. * * Side effects: - * Once this function completes, the package becomes loadable via the + * Once this function completes, the library becomes loadable via the * "load" command with an empty file name. * *---------------------------------------------------------------------- */ void -Tcl_StaticPackage( - Tcl_Interp *interp, /* If not NULL, it means that the package has +Tcl_StaticLibrary( + Tcl_Interp *interp, /* If not NULL, it means that the library has * already been loaded into the given * interpreter by calling the appropriate init * proc. */ - const char *pkgName, /* Name of package (must be properly + const char *prefix, /* Prefix (must be properly * capitalized: first letter upper case, * others lower case). */ - Tcl_PackageInitProc *initProc, + Tcl_LibraryInitProc *initProc, /* Function to call to incorporate this - * package into a trusted interpreter. */ - Tcl_PackageInitProc *safeInitProc) + * library into a trusted interpreter. */ + Tcl_LibraryInitProc *safeInitProc) /* Function to call to incorporate this - * package into a safe interpreter (one that + * library into a safe interpreter (one that * will execute untrusted scripts). NULL means - * the package can't be used in safe + * the library can't be used in safe * interpreters. */ { - LoadedPackage *pkgPtr; - InterpPackage *ipPtr, *ipFirstPtr; + LoadedLibrary *libraryPtr; + InterpLibrary *ipPtr, *ipFirstPtr; /* - * Check to see if someone else has already reported this package as + * Check to see if someone else has already reported this library as * statically loaded in the process. */ - Tcl_MutexLock(&packageMutex); - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { - if ((pkgPtr->initProc == initProc) - && (pkgPtr->safeInitProc == safeInitProc) - && (strcmp(pkgPtr->packageName, pkgName) == 0)) { + Tcl_MutexLock(&libraryMutex); + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) { + if ((libraryPtr->initProc == initProc) + && (libraryPtr->safeInitProc == safeInitProc) + && (strcmp(libraryPtr->prefix, prefix) == 0)) { break; } } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); /* - * If the package is not yet recorded as being loaded statically, add it + * If the library is not yet recorded as being loaded statically, add it * to the list now. */ - if (pkgPtr == NULL) { - pkgPtr = (LoadedPackage *)ckalloc(sizeof(LoadedPackage)); - pkgPtr->fileName = (char *)ckalloc(1); - pkgPtr->fileName[0] = 0; - pkgPtr->packageName = (char *)ckalloc(strlen(pkgName) + 1); - strcpy(pkgPtr->packageName, pkgName); - pkgPtr->loadHandle = NULL; - pkgPtr->initProc = initProc; - pkgPtr->safeInitProc = safeInitProc; - Tcl_MutexLock(&packageMutex); - pkgPtr->nextPtr = firstPackagePtr; - firstPackagePtr = pkgPtr; - Tcl_MutexUnlock(&packageMutex); + if (libraryPtr == NULL) { + libraryPtr = (LoadedLibrary *)ckalloc(sizeof(LoadedLibrary)); + libraryPtr->fileName = (char *)ckalloc(1); + libraryPtr->fileName[0] = 0; + libraryPtr->prefix = (char *)ckalloc(strlen(prefix) + 1); + strcpy(libraryPtr->prefix, prefix); + libraryPtr->loadHandle = NULL; + libraryPtr->initProc = initProc; + libraryPtr->safeInitProc = safeInitProc; + Tcl_MutexLock(&libraryMutex); + libraryPtr->nextPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr; + Tcl_MutexUnlock(&libraryMutex); } if (interp != NULL) { /* - * If we're loading the package into an interpreter, determine whether + * If we're loading the library into an interpreter, determine whether * it's already loaded. */ - ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(interp, "tclLoad", NULL); + ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - if (ipPtr->pkgPtr == pkgPtr) { + if (ipPtr->libraryPtr == libraryPtr) { return; } } /* - * Package isn't loaded in the current interp yet. Mark it as now being + * Library isn't loaded in the current interp yet. Mark it as now being * loaded. */ - ipPtr = (InterpPackage *)ckalloc(sizeof(InterpPackage)); - ipPtr->pkgPtr = pkgPtr; + ipPtr = (InterpLibrary *)ckalloc(sizeof(InterpLibrary)); + ipPtr->libraryPtr = libraryPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr); } @@ -1024,7 +1024,7 @@ Tcl_StaticPackage( /* *---------------------------------------------------------------------- * - * TclGetLoadedPackagesEx -- + * TclGetLoadedLibraries -- * * This function returns information about all of the files that are * loaded (either in a particular interpreter, or for all interpreters). @@ -1034,7 +1034,7 @@ Tcl_StaticPackage( * list of lists is placed in the interp's result. Each sublist * corresponds to one loaded file; its first element is the name of the * file (or an empty string for something that's statically loaded) and - * the second element is the name of the package in that file. + * the second element is the prefix of the library in that file. * * Side effects: * None. @@ -1043,33 +1043,33 @@ Tcl_StaticPackage( */ int -TclGetLoadedPackagesEx( +TclGetLoadedLibraries( Tcl_Interp *interp, /* Interpreter in which to return information * or error message. */ const char *targetName, /* Name of target interpreter or NULL. If * NULL, return info about all interps; * otherwise, just return info about this * interpreter. */ - const char *packageName) /* Package name or NULL. If NULL, return info - * for all packages. + const char *prefix) /* Prefix or NULL. If NULL, return info + * for all prefixes. */ { Tcl_Interp *target; - LoadedPackage *pkgPtr; - InterpPackage *ipPtr; + LoadedLibrary *libraryPtr; + InterpLibrary *ipPtr; Tcl_Obj *resultObj, *pkgDesc[2]; if (targetName == NULL) { TclNewObj(resultObj); - Tcl_MutexLock(&packageMutex); - for (pkgPtr = firstPackagePtr; pkgPtr != NULL; - pkgPtr = pkgPtr->nextPtr) { - pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1); - pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1); + Tcl_MutexLock(&libraryMutex); + for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; + libraryPtr = libraryPtr->nextPtr) { + pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1); + pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } - Tcl_MutexUnlock(&packageMutex); + Tcl_MutexUnlock(&libraryMutex); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } @@ -1078,19 +1078,19 @@ TclGetLoadedPackagesEx( if (target == NULL) { return TCL_ERROR; } - ipPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL); + ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); /* - * Return information about all of the available packages. + * Return information about all of the available libraries. */ - if (packageName) { + if (prefix) { resultObj = NULL; for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - pkgPtr = ipPtr->pkgPtr; + libraryPtr = ipPtr->libraryPtr; - if (!strcmp(packageName, pkgPtr->packageName)) { - resultObj = Tcl_NewStringObj(pkgPtr->fileName, -1); + if (!strcmp(prefix, libraryPtr->prefix)) { + resultObj = Tcl_NewStringObj(libraryPtr->fileName, -1); break; } } @@ -1102,15 +1102,15 @@ TclGetLoadedPackagesEx( } /* - * Return information about only the packages that are loaded in a given + * Return information about only the libraries that are loaded in a given * interpreter. */ TclNewObj(resultObj); for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { - pkgPtr = ipPtr->pkgPtr; - pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1); - pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1); + libraryPtr = ipPtr->libraryPtr; + pkgDesc[0] = Tcl_NewStringObj(libraryPtr->fileName, -1); + pkgDesc[1] = Tcl_NewStringObj(libraryPtr->prefix, -1); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } Tcl_SetObjResult(interp, resultObj); @@ -1122,7 +1122,7 @@ TclGetLoadedPackagesEx( * * LoadCleanupProc -- * - * This function is called to delete all of the InterpPackage structures + * This function is called to delete all of the InterpLibrary structures * for an interpreter when the interpreter is deleted. It gets invoked * via the Tcl AssocData mechanism. * @@ -1130,20 +1130,20 @@ TclGetLoadedPackagesEx( * None. * * Side effects: - * Storage for all of the InterpPackage functions for interp get deleted. + * Storage for all of the InterpLibrary functions for interp get deleted. * *---------------------------------------------------------------------- */ static void LoadCleanupProc( - ClientData clientData, /* Pointer to first InterpPackage structure + ClientData clientData, /* Pointer to first InterpLibrary structure * for interp. */ TCL_UNUSED(Tcl_Interp *)) { - InterpPackage *ipPtr, *nextPtr; + InterpLibrary *ipPtr, *nextPtr; - ipPtr = (InterpPackage *)clientData; + ipPtr = (InterpLibrary *)clientData; while (ipPtr != NULL) { nextPtr = ipPtr->nextPtr; ckfree(ipPtr); @@ -1157,7 +1157,7 @@ LoadCleanupProc( * TclFinalizeLoad -- * * This function is invoked just before the application exits. It frees - * all of the LoadedPackage structures. + * all of the LoadedLibrary structures. * * Results: * None. @@ -1171,18 +1171,18 @@ LoadCleanupProc( void TclFinalizeLoad(void) { - LoadedPackage *pkgPtr; + LoadedLibrary *libraryPtr; /* * No synchronization here because there should just be one thread alive - * at this point. Logically, packageMutex should be grabbed at this point, + * at this point. Logically, libraryMutex should be grabbed at this point, * but the Mutexes get finalized before the call to this routine. The only * subsystem left alive at this point is the memory allocator. */ - while (firstPackagePtr != NULL) { - pkgPtr = firstPackagePtr; - firstPackagePtr = pkgPtr->nextPtr; + while (firstLibraryPtr != NULL) { + libraryPtr = firstLibraryPtr; + firstLibraryPtr = libraryPtr->nextPtr; #if defined(TCL_UNLOAD_DLLS) || defined(_WIN32) /* @@ -1192,14 +1192,14 @@ TclFinalizeLoad(void) * it has been unloaded. */ - if (pkgPtr->fileName[0] != '\0') { - Tcl_FSUnloadFile(NULL, pkgPtr->loadHandle); + if (libraryPtr->fileName[0] != '\0') { + Tcl_FSUnloadFile(NULL, libraryPtr->loadHandle); } #endif - ckfree(pkgPtr->fileName); - ckfree(pkgPtr->packageName); - ckfree(pkgPtr); + ckfree(libraryPtr->fileName); + ckfree(libraryPtr->prefix); + ckfree(libraryPtr); } } diff --git a/generic/tclNotify.c b/generic/tclNotify.c index b43413d..12b40b1 100644 --- a/generic/tclNotify.c +++ b/generic/tclNotify.c @@ -10,6 +10,7 @@ * Copyright © 1995-1997 Sun Microsystems, Inc. * Copyright © 1998 Scriptics Corporation. * Copyright © 2003 Kevin B. Kenny. All rights reserved. + * Copyright © 2021 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -18,11 +19,11 @@ #include "tclInt.h" /* - * Module-scope struct of notifier hooks that are checked in the default + * Notifier hooks that are checked in the public wrappers for the default * notifier functions (for overriding via Tcl_SetNotifier). */ -Tcl_NotifierProcs tclNotifierHooks = { +static Tcl_NotifierProcs tclNotifierHooks = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; @@ -174,7 +175,8 @@ TclFinalizeNotifier(void) Tcl_Event *evPtr, *hold; if (!tsdPtr->initialized) { - return; /* Notifier not initialized for the current thread */ + return; /* Notifier not initialized for the current + * thread. */ } Tcl_MutexLock(&(tsdPtr->queueMutex)); @@ -227,6 +229,38 @@ Tcl_SetNotifier( Tcl_NotifierProcs *notifierProcPtr) { tclNotifierHooks = *notifierProcPtr; + + /* + * Don't allow hooks to refer to the hook point functions; avoids infinite + * loop. + */ + + if (tclNotifierHooks.setTimerProc == Tcl_SetTimer) { + tclNotifierHooks.setTimerProc = NULL; + } + if (tclNotifierHooks.waitForEventProc == Tcl_WaitForEvent) { + tclNotifierHooks.waitForEventProc = NULL; + } + if (tclNotifierHooks.initNotifierProc == Tcl_InitNotifier) { + tclNotifierHooks.initNotifierProc = NULL; + } + if (tclNotifierHooks.finalizeNotifierProc == Tcl_FinalizeNotifier) { + tclNotifierHooks.finalizeNotifierProc = NULL; + } + if (tclNotifierHooks.alertNotifierProc == Tcl_AlertNotifier) { + tclNotifierHooks.alertNotifierProc = NULL; + } + if (tclNotifierHooks.serviceModeHookProc == Tcl_ServiceModeHook) { + tclNotifierHooks.serviceModeHookProc = NULL; + } +#ifndef _WIN32 + if (tclNotifierHooks.createFileHandlerProc == Tcl_CreateFileHandler) { + tclNotifierHooks.createFileHandlerProc = NULL; + } + if (tclNotifierHooks.deleteFileHandlerProc == Tcl_DeleteFileHandler) { + tclNotifierHooks.deleteFileHandlerProc = NULL; + } +#endif /* !_WIN32 */ } /* @@ -276,7 +310,7 @@ Tcl_CreateEventSource( * checkProc. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - EventSource *sourcePtr = (EventSource *)ckalloc(sizeof(EventSource)); + EventSource *sourcePtr = (EventSource *) ckalloc(sizeof(EventSource)); sourcePtr->setupProc = setupProc; sourcePtr->checkProc = checkProc; @@ -794,7 +828,7 @@ Tcl_SetServiceMode( void Tcl_SetMaxBlockTime( - const Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the + const Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the * next blocking operation in the event * tsdPtr-> */ { @@ -1133,6 +1167,260 @@ Tcl_ThreadAlert( } /* + *---------------------------------------------------------------------- + * + * Tcl_InitNotifier -- + * + * Initializes the platform specific notifier state. Forwards to the + * platform implementation when the hook is not enabled. + * + * Results: + * Returns a handle to the notifier state for this thread.. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ClientData +Tcl_InitNotifier(void) +{ + if (tclNotifierHooks.initNotifierProc) { + return tclNotifierHooks.initNotifierProc(); + } else { + return TclpInitNotifier(); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_FinalizeNotifier -- + * + * This function is called to cleanup the notifier state before a thread + * is terminated. Forwards to the platform implementation when the hook + * is not enabled. + * + * Results: + * None. + * + * Side effects: + * If no finalizeNotifierProc notifier hook exists, TclpFinalizeNotifier + * is called. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_FinalizeNotifier( + ClientData clientData) +{ + if (tclNotifierHooks.finalizeNotifierProc) { + tclNotifierHooks.finalizeNotifierProc(clientData); + } else { + TclpFinalizeNotifier(clientData); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AlertNotifier -- + * + * Wake up the specified notifier from any thread. This routine is called + * by the platform independent notifier code whenever the Tcl_ThreadAlert + * routine is called. This routine is guaranteed not to be called by Tcl + * on a given notifier after Tcl_FinalizeNotifier is called for that + * notifier. This routine is typically called from a thread other than + * the notifier's thread. Forwards to the platform implementation when + * the hook is not enabled. + * + * Results: + * None. + * + * Side effects: + * See the platform-specific implementations. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_AlertNotifier( + ClientData clientData) /* Pointer to thread data. */ +{ + if (tclNotifierHooks.alertNotifierProc) { + tclNotifierHooks.alertNotifierProc(clientData); + } else { + TclpAlertNotifier(clientData); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ServiceModeHook -- + * + * This function is invoked whenever the service mode changes. Forwards + * to the platform implementation when the hook is not enabled. + * + * Results: + * None. + * + * Side effects: + * See the platform-specific implementations. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_ServiceModeHook( + int mode) /* Either TCL_SERVICE_ALL, or + * TCL_SERVICE_NONE. */ +{ + if (tclNotifierHooks.serviceModeHookProc) { + tclNotifierHooks.serviceModeHookProc(mode); + } else { + TclpServiceModeHook(mode); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetTimer -- + * + * This function sets the current notifier timer value. Forwards to the + * platform implementation when the hook is not enabled. + * + * Results: + * None. + * + * Side effects: + * See the platform-specific implementations. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_SetTimer( + const Tcl_Time *timePtr) /* Timeout value, may be NULL. */ +{ + if (tclNotifierHooks.setTimerProc) { + tclNotifierHooks.setTimerProc(timePtr); + } else { + TclpSetTimer(timePtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_WaitForEvent -- + * + * This function is called by Tcl_DoOneEvent to wait for new events on + * the notifier's message queue. If the block time is 0, then + * Tcl_WaitForEvent just polls without blocking. Forwards to the + * platform implementation when the hook is not enabled. + * + * Results: + * Returns -1 if the wait would block forever, 1 if an out-of-loop source + * was processed (see platform-specific notes) and otherwise returns 0. + * + * Side effects: + * Queues file events that are detected by the notifier. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_WaitForEvent( + const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ +{ + if (tclNotifierHooks.waitForEventProc) { + return tclNotifierHooks.waitForEventProc(timePtr); + } else { + return TclpWaitForEvent(timePtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_CreateFileHandler -- + * + * This function registers a file descriptor handler with the notifier. + * Forwards to the platform implementation when the hook is not enabled. + * + * This function is not defined on Windows. The OS API there is too + * different. + * + * Results: + * None. + * + * Side effects: + * Creates a new file handler structure. + * + *---------------------------------------------------------------------- + */ + +#ifndef _WIN32 +void +Tcl_CreateFileHandler( + 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, /* Function to call for each selected + * event. */ + ClientData clientData) /* Arbitrary data to pass to proc. */ +{ + if (tclNotifierHooks.createFileHandlerProc) { + tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); + } else { + TclpCreateFileHandler(fd, mask, proc, clientData); + } +} +#endif /* !_WIN32 */ + +/* + *---------------------------------------------------------------------- + * + * Tcl_DeleteFileHandler -- + * + * Cancel a previously-arranged callback arrangement for a file + * descriptor. Forwards to the platform implementation when the hook is + * not enabled. + * + * This function is not defined on Windows. The OS API there is too + * different. + * + * Results: + * None. + * + * Side effects: + * If a callback was previously registered on the file descriptor, remove + * it. + * + *---------------------------------------------------------------------- + */ + +#ifndef _WIN32 +void +Tcl_DeleteFileHandler( + int fd) /* Stream id for which to remove callback + * function. */ +{ + if (tclNotifierHooks.deleteFileHandlerProc) { + tclNotifierHooks.deleteFileHandlerProc(fd); + } else { + TclpDeleteFileHandler(fd); + } +} +#endif /* !_WIN32 */ + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tclParse.c b/generic/tclParse.c index df6c9bf..4de0356 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -935,7 +935,7 @@ TclParseBackslash( * #217987] test subst-3.2 */ - if (TclUCS4Complete(p, numBytes - 1)) { + if (Tcl_UtfCharComplete(p, numBytes - 1)) { count = TclUtfToUCS4(p, &unichar) + 1; /* +1 for '\' */ } else { char utfBytes[8]; diff --git a/generic/tclPkgConfig.c b/generic/tclPkgConfig.c index eea7a07..a0dae51 100644 --- a/generic/tclPkgConfig.c +++ b/generic/tclPkgConfig.c @@ -2,7 +2,7 @@ * tclPkgConfig.c -- * * This file contains the configuration information to embed into the tcl - * binary library. + * library. * * Copyright © 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net> * diff --git a/generic/tclPlatDecls.h b/generic/tclPlatDecls.h index ee5ca50..f2bc0da 100644 --- a/generic/tclPlatDecls.h +++ b/generic/tclPlatDecls.h @@ -65,6 +65,9 @@ EXTERN TCHAR * Tcl_WinUtfToTChar(const char *str, int len, /* 1 */ EXTERN char * Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr); +/* Slot 2 is reserved */ +/* 3 */ +EXTERN void Tcl_WinConvertError(unsigned errCode); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 0 */ @@ -89,6 +92,8 @@ typedef struct TclPlatStubs { #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */ char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */ + void (*reserved2)(void); + void (*tcl_WinConvertError) (unsigned errCode); /* 3 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */ @@ -114,6 +119,9 @@ extern const TclPlatStubs *tclPlatStubsPtr; (tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */ #define Tcl_WinTCharToUtf \ (tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */ +/* Slot 2 is reserved */ +#define Tcl_WinConvertError \ + (tclPlatStubsPtr->tcl_WinConvertError) /* 3 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ #define Tcl_MacOSXOpenBundleResources \ diff --git a/generic/tclResult.c b/generic/tclResult.c index ba42e46..5b7a8e5 100644 --- a/generic/tclResult.c +++ b/generic/tclResult.c @@ -464,6 +464,7 @@ Tcl_SetResult( ResetObjResult(iPtr); } +#endif /* !TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------- @@ -482,10 +483,12 @@ Tcl_SetResult( *---------------------------------------------------------------------- */ +#undef Tcl_GetStringResult const char * Tcl_GetStringResult( Tcl_Interp *interp)/* Interpreter whose result to return. */ { +#ifndef TCL_NO_DEPRECATED Interp *iPtr = (Interp *) interp; /* * If the string result is empty, move the object result to the string @@ -497,8 +500,10 @@ Tcl_GetStringResult( TCL_VOLATILE); } return iPtr->result; +#else + return TclGetString(Tcl_GetObjResult(interp)); +#endif } -#endif /* !TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------- diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 0777018..af72e13 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -70,6 +70,11 @@ static void SetUnicodeObj(Tcl_Obj *objPtr, static int UnicodeLength(const Tcl_UniChar *unicode); static void UpdateStringOfString(Tcl_Obj *objPtr); +#define ISCONTINUATION(bytes) (\ + ((((bytes)[0] & 0xC0) == 0x80) || (((bytes)[0] == '\xED') \ + && (((bytes)[1] & 0xF0) == 0xB0) && (((bytes)[2] & 0xC0) == 0x80)))) + + /* * The structure below defines the string Tcl object type by means of * functions that can be invoked by generic object code. @@ -1199,10 +1204,10 @@ Tcl_AppendLimitedToObj( } eLen = strlen(ellipsis); while (eLen > limit) { - eLen = TclUtfPrev(ellipsis+eLen, ellipsis) - ellipsis; + eLen = Tcl_UtfPrev(ellipsis+eLen, ellipsis) - ellipsis; } - toCopy = TclUtfPrev(bytes+limit+1-eLen, bytes) - bytes; + toCopy = Tcl_UtfPrev(bytes+limit+1-eLen, bytes) - bytes; } /* @@ -1218,6 +1223,11 @@ Tcl_AppendLimitedToObj( SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); + /* If appended string starts with a continuation byte or a lower surrogate, + * force objPtr to unicode representation. See [7f1162a867] */ + if (bytes && ISCONTINUATION(bytes)) { + Tcl_GetUnicode(objPtr); + } if (stringPtr->hasUnicode && stringPtr->numChars > 0) { AppendUtfToUnicodeRep(objPtr, bytes, toCopy); } else { @@ -1415,6 +1425,12 @@ Tcl_AppendObjToObj( SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); + /* If appended string starts with a continuation byte or a lower surrogate, + * force objPtr to unicode representation. See [7f1162a867] + * This fixes append-3.4, append-3.7 and utf-1.18 testcases. */ + if (ISCONTINUATION(TclGetString(appendObjPtr))) { + Tcl_GetUnicode(objPtr); + } /* * If objPtr has a valid Unicode rep, then get a Unicode string from * appendObjPtr and append it. @@ -2644,7 +2660,7 @@ AppendPrintfToObjVA( * multi-byte characters. */ - q = TclUtfPrev(end, bytes); + q = Tcl_UtfPrev(end, bytes); if (!Tcl_UtfCharComplete(q, (int)(end - q))) { end = q; } @@ -3032,7 +3048,7 @@ TclStringCat( { Tcl_Obj *objResultPtr, * const *ov; int oc, length = 0, binary = 1; - int allowUniChar = 1, requestUniChar = 0; + int allowUniChar = 1, requestUniChar = 0, forceUniChar = 0; int first = objc - 1; /* Index of first value possibly not empty */ int last = 0; /* Index of last value possibly not empty */ int inPlace = flags & TCL_STRING_IN_PLACE; @@ -3068,7 +3084,9 @@ TclStringCat( */ binary = 0; - if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) { + if (ov > objv+1 && ISCONTINUATION(TclGetString(objPtr))) { + forceUniChar = 1; + } else if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) { /* Prevent shimmer of non-string types. */ allowUniChar = 0; } @@ -3117,7 +3135,7 @@ TclStringCat( } } } while (--oc); - } else if (allowUniChar && requestUniChar) { + } else if ((allowUniChar && requestUniChar) || forceUniChar) { /* * Result will be pure Tcl_UniChar array. Pre-size it. */ @@ -3270,7 +3288,7 @@ TclStringCat( dst += more; } } - } else if (allowUniChar && requestUniChar) { + } else if ((allowUniChar && requestUniChar) || forceUniChar) { /* Efficiently produce a pure Tcl_UniChar array result */ Tcl_UniChar *dst; @@ -3456,7 +3474,7 @@ TclStringCmp( s1 = (char *) Tcl_GetUnicode(value1Ptr); s2 = (char *) Tcl_GetUnicode(value2Ptr); if ( -#ifdef WORDS_BIGENDIAN +#if defined(WORDS_BIGENDIAN) && (TCL_UTF_MAX > 3) 1 #else checkEq @@ -4145,9 +4163,22 @@ ExtendUnicodeRepWithString( } else { numAppendChars = 0; } - for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) { + dst = stringPtr->unicode + numOrigChars; + if (numAppendChars-- > 0) { bytes += TclUtfToUniChar(bytes, &unichar); - *dst = unichar; +#if TCL_UTF_MAX > 3 + /* join upper/lower surrogate */ + if (bytes && (stringPtr->unicode[numOrigChars - 1] | 0x3FF) == 0xDBFF && (unichar | 0x3FF) == 0xDFFF) { + stringPtr->numChars--; + unichar = ((stringPtr->unicode[numOrigChars - 1] & 0x3FF) << 10) + (unichar & 0x3FF) + 0x10000; + dst--; + } +#endif + *dst++ = unichar; + while (numAppendChars-- > 0) { + bytes += TclUtfToUniChar(bytes, &unichar); + *dst++ = unichar; + } } *dst = 0; } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 50c99ad..41ece01 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -65,15 +65,22 @@ #undef TclWinGetSockOpt #undef TclWinSetSockOpt #undef TclWinNToHS -#undef TclStaticPackage +#undef TclStaticLibrary #undef Tcl_BackgroundError #undef TclGuessPackageName #undef TclGetLoadedPackages -#define TclStaticPackage Tcl_StaticPackage +#define TclStaticLibrary Tcl_StaticLibrary #undef Tcl_UniCharToUtfDString #undef Tcl_UtfToUniCharDString #undef Tcl_UtfToUniChar #undef Tcl_MacOSXOpenBundleResources +#undef TclWinConvertWSAError +#undef TclWinConvertError +#if defined(_WIN32) || defined(__CYGWIN__) +#define TclWinConvertWSAError (void (*)(DWORD))(void *)Tcl_WinConvertError +#define TclWinConvertError (void (*)(DWORD))(void *)Tcl_WinConvertError +#endif + #if TCL_UTF_MAX > 3 static void uniCodePanic(void) { @@ -90,6 +97,32 @@ static void uniCodePanic(void) { # define Tcl_UniCharNcmp (int(*)(const Tcl_UniChar *, const Tcl_UniChar *, unsigned long))(void *)uniCodePanic #endif +#define TclUtfCharComplete UtfCharComplete +#define TclUtfNext UtfNext +#define TclUtfPrev UtfPrev + +static int TclUtfCharComplete(const char *src, int length) { + if ((unsigned)((unsigned char)*(src) - 0xF0) < 5) { + return length < 3; + } + return Tcl_UtfCharComplete(src, length); +} + +static const char *TclUtfNext(const char *src) { + if ((unsigned)((unsigned char)*(src) - 0xF0) < 5) { + return src + 1; + } + return Tcl_UtfNext(src); +} + +static const char *TclUtfPrev(const char *src, const char *start) { + if ((src >= start + 3) && ((src[-1] & 0xC0) == 0x80) + && ((src[-2] & 0xC0) == 0x80) && ((src[-3] & 0xC0) == 0x80)) { + return src - 3; + } + return Tcl_UtfPrev(src, start); +} + #define TclBN_mp_add mp_add #define TclBN_mp_and mp_and #define TclBN_mp_clamp mp_clamp @@ -283,7 +316,7 @@ static int TclGetLoadedPackages( * otherwise, just return info about this * interpreter. */ { - return TclGetLoadedPackagesEx(interp, targetName, NULL); + return TclGetLoadedLibraries(interp, targetName, NULL); } mp_err TclBN_mp_div_3(const mp_int *a, mp_int *c, unsigned int *d) { @@ -602,8 +635,6 @@ static int utfNcasecmp(const char *s1, const char *s2, unsigned int n){ # define Tcl_Eval 0 # undef Tcl_GlobalEval # define Tcl_GlobalEval 0 -# undef Tcl_GetStringResult -# define Tcl_GetStringResult 0 # undef Tcl_SaveResult # define Tcl_SaveResult 0 # undef Tcl_RestoreResult @@ -1006,7 +1037,7 @@ static const TclIntStubs tclIntStubs = { TclPtrIncrObjVar, /* 254 */ TclPtrObjMakeUpvar, /* 255 */ TclPtrUnsetVar, /* 256 */ - TclStaticPackage, /* 257 */ + TclStaticLibrary, /* 257 */ TclpCreateTemporaryDirectory, /* 258 */ TclGetBytesFromObj, /* 259 */ TclUnusedStubEntry, /* 260 */ @@ -1122,6 +1153,8 @@ static const TclPlatStubs tclPlatStubs = { #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ Tcl_WinUtfToTChar, /* 0 */ Tcl_WinTCharToUtf, /* 1 */ + 0, /* 2 */ + Tcl_WinConvertError, /* 3 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ Tcl_MacOSXOpenBundleResources, /* 0 */ @@ -1493,7 +1526,7 @@ const TclStubs tclStubs = { Tcl_SourceRCFile, /* 241 */ Tcl_SplitList, /* 242 */ Tcl_SplitPath, /* 243 */ - Tcl_StaticPackage, /* 244 */ + Tcl_StaticLibrary, /* 244 */ Tcl_StringMatch, /* 245 */ Tcl_TellOld, /* 246 */ Tcl_TraceVar, /* 247 */ @@ -1575,12 +1608,12 @@ const TclStubs tclStubs = { Tcl_UniCharToUpper, /* 323 */ Tcl_UniCharToUtf, /* 324 */ Tcl_UtfAtIndex, /* 325 */ - Tcl_UtfCharComplete, /* 326 */ + TclUtfCharComplete, /* 326 */ Tcl_UtfBackslash, /* 327 */ Tcl_UtfFindFirst, /* 328 */ Tcl_UtfFindLast, /* 329 */ - Tcl_UtfNext, /* 330 */ - Tcl_UtfPrev, /* 331 */ + TclUtfNext, /* 330 */ + TclUtfPrev, /* 331 */ Tcl_UtfToExternal, /* 332 */ Tcl_UtfToExternalDString, /* 333 */ Tcl_UtfToLower, /* 334 */ @@ -1903,6 +1936,9 @@ const TclStubs tclStubs = { TclGetStringFromObj, /* 651 */ TclGetUnicodeFromObj, /* 652 */ TclGetByteArrayFromObj, /* 653 */ + Tcl_UtfCharComplete, /* 654 */ + Tcl_UtfNext, /* 655 */ + Tcl_UtfPrev, /* 656 */ }; /* !END!: Do not edit above this line. */ diff --git a/generic/tclTest.c b/generic/tclTest.c index bf55e82..d32057b 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -19,6 +19,9 @@ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif +#ifndef TCL_NO_DEPRECATED +# define TCL_NO_DEPRECATED +#endif #include "tclInt.h" #ifdef TCL_WITH_EXTERNAL_TOMMATH # include "tommath.h" @@ -275,7 +278,7 @@ static Tcl_CmdProc Testset2Cmd; static Tcl_CmdProc TestseterrorcodeCmd; static Tcl_ObjCmdProc TestsetobjerrorcodeCmd; static Tcl_CmdProc TestsetplatformCmd; -static Tcl_CmdProc TeststaticpkgCmd; +static Tcl_CmdProc TeststaticlibraryCmd; static Tcl_CmdProc TesttranslatefilenameCmd; static Tcl_CmdProc TestupvarCmd; static Tcl_ObjCmdProc TestWrongNumArgsObjCmd; @@ -661,7 +664,7 @@ Tcltest_Init( NULL, NULL); Tcl_CreateCommand(interp, "testsocket", TestSocketCmd, NULL, NULL); - Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd, + Tcl_CreateCommand(interp, "teststaticlibrary", TeststaticlibraryCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); @@ -4274,10 +4277,10 @@ TestsetplatformCmd( /* *---------------------------------------------------------------------- * - * TeststaticpkgCmd -- + * TeststaticlibraryCmd -- * - * This procedure implements the "teststaticpkg" command. - * It is used to test the procedure Tcl_StaticPackage. + * This procedure implements the "teststaticlibrary" command. + * It is used to test the procedure Tcl_StaticLibrary. * * Results: * A standard Tcl result. @@ -4290,7 +4293,7 @@ TestsetplatformCmd( */ static int -TeststaticpkgCmd( +TeststaticlibraryCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ @@ -4300,7 +4303,7 @@ TeststaticpkgCmd( if (argc != 4) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", - argv[0], " pkgName safe loaded\"", NULL); + argv[0], " prefix safe loaded\"", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) { @@ -4309,7 +4312,7 @@ TeststaticpkgCmd( if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) { return TCL_ERROR; } - Tcl_StaticPackage((loaded) ? interp : NULL, argv[1], + Tcl_StaticLibrary((loaded) ? interp : NULL, argv[1], StaticInitProc, (safe) ? StaticInitProc : NULL); return TCL_OK; } @@ -7022,7 +7025,7 @@ TestUtfPrevCmd( } else { offset = numBytes; } - result = TclUtfPrev(bytes + offset, bytes); + result = Tcl_UtfPrev(bytes + offset, bytes); Tcl_SetObjResult(interp, Tcl_NewIntObj(result - bytes)); return TCL_OK; } diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 28475f9..727f061 100644 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -564,7 +564,7 @@ TclThreadAllocObj(void) cachePtr->numObjects = numMove = NOBJALLOC; newObjsPtr = (Tcl_Obj *)TclpSysAlloc(sizeof(Tcl_Obj) * numMove, 0); if (newObjsPtr == NULL) { - Tcl_Panic("alloc: could not allocate %ld new objects", numMove); + Tcl_Panic("alloc: could not allocate %" TCL_Z_MODIFIER "u new objects", numMove); } cachePtr->lastPtr = newObjsPtr + numMove - 1; objPtr = cachePtr->firstObjPtr; /* NULL */ diff --git a/generic/tclThreadJoin.c b/generic/tclThreadJoin.c index ba789d3..4d2aca5 100644 --- a/generic/tclThreadJoin.c +++ b/generic/tclThreadJoin.c @@ -305,6 +305,8 @@ TclSignalExitThread( Tcl_MutexUnlock(&threadPtr->threadMutex); } +#else +TCL_MAC_EMPTY_FILE(generic_tclThreadJoin_c) #endif /* _WIN32 */ /* diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 847717a..3a3b9a8 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -17,7 +17,6 @@ library tcl # Define the unsupported generic interfaces. interface tclTomMath -# hooks {tclTomMathInt} scspec EXTERN # Declare each of the functions in the Tcl tommath interface diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 5db7343..28f725a 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -64,20 +64,12 @@ static const unsigned char totalBytes[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -/* Tcl_UtfCharComplete() might point to 2nd byte of valid 4-byte sequence */ - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -/* End of "continuation byte section" */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -#if TCL_UTF_MAX > 3 - 4,4,4,4,4, -#else - 1,1,1,1,1, -#endif - 1,1,1,1,1,1,1,1,1,1,1 + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 }; - + static const unsigned char complete[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -88,15 +80,9 @@ static const unsigned char complete[256] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, /* End of "continuation byte section" */ 2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -#if TCL_UTF_MAX > 3 - 4,4,4,4,4, -#else - 3,3,3,3,3, -#endif - 1,1,1,1,1,1,1,1,1,1,1 + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 }; - + /* * Functions used only in this module. */ @@ -694,7 +680,7 @@ Tcl_UtfToUniCharDString( p += TclUtfToUCS4(p, &ch); *w++ = ch; } - while ((p < endPtr) && TclUCS4Complete(p, endPtr-p)) { + while ((p < endPtr) && Tcl_UtfCharComplete(p, endPtr-p)) { p += TclUtfToUCS4(p, &ch); *w++ = ch; } @@ -752,7 +738,7 @@ Tcl_UtfToChar16DString( *w++ = ch; } while (p < endPtr) { - if (TclChar16Complete(p, endPtr-p)) { + if (Tcl_UtfCharComplete(p, endPtr-p)) { p += Tcl_UtfToChar16(p, &ch); *w++ = ch; } else { @@ -833,7 +819,7 @@ Tcl_NumUtfChars( /* Pointer to the end of string. Never read endPtr[0] */ const char *endPtr = src + length; /* Pointer to last byte where optimization still can be used */ - const char *optPtr = endPtr - TCL_UTF_MAX; + const char *optPtr = endPtr - 4; /* * Optimize away the call in this loop. Justified because... @@ -970,6 +956,10 @@ Tcl_UtfNext( const char *next; if (((*src) & 0xC0) == 0x80) { + /* Continuation byte, so we start 'inside' a (possible valid) UTF-8 + * sequence. Since we are not allowed to access src[-1], we cannot + * check if the sequence is actually valid, the best we can do is + * just assume it is valid and locate the end. */ if ((((*++src) & 0xC0) == 0x80) && (((*++src) & 0xC0) == 0x80)) { ++src; } @@ -1064,7 +1054,7 @@ Tcl_UtfPrev( * it (the fallback) is correct. */ - || (trailBytesSeen >= complete[byte])) { + || (trailBytesSeen >= totalBytes[byte])) { /* * That is, (1 + trailBytesSeen > needed). * We've examined more bytes than needed to complete @@ -1105,19 +1095,14 @@ Tcl_UtfPrev( /* Continue the search backwards... */ look--; - } while (trailBytesSeen < TCL_UTF_MAX); + } while (trailBytesSeen < 4); /* - * We've seen TCL_UTF_MAX trail bytes, so we know there will not be a + * We've seen 4 trail bytes, so we know there will not be a * properly formed byte sequence to find, and we can stop looking, - * accepting the fallback (for TCL_UTF_MAX > 3) or just go back as - * far as we can. + * accepting the fallback. */ -#if TCL_UTF_MAX > 3 return fallback; -#else - return src - TCL_UTF_MAX; -#endif } /* @@ -1744,7 +1729,7 @@ Tcl_UniCharToLower( /* Clear away extension bits, if any */ return ch & 0x1FFFFF; } - + /* *---------------------------------------------------------------------- * @@ -1838,7 +1823,7 @@ Tcl_UniCharNcmp( const Tcl_UniChar *uct, /* Unicode string ucs is compared to. */ unsigned long numChars) /* Number of unichars to compare. */ { -#ifdef WORDS_BIGENDIAN +#if defined(WORDS_BIGENDIAN) && (TCL_UTF_MAX > 3) /* * We are definitely on a big-endian machine; memcmp() is safe */ @@ -1852,6 +1837,14 @@ Tcl_UniCharNcmp( for ( ; numChars != 0; ucs++, uct++, numChars--) { if (*ucs != *uct) { +#if TCL_UTF_MAX < 4 + /* special case for handling upper surrogates */ + if (((*ucs & 0xFC00) == 0xD800) && ((*uct & 0xFC00) != 0xD800)) { + return 1; + } else if (((*uct & 0xFC00) == 0xD800)) { + return -1; + } +#endif return (*ucs - *uct); } } @@ -1889,6 +1882,14 @@ Tcl_UniCharNcasecmp( Tcl_UniChar lct = Tcl_UniCharToLower(*uct); if (lcs != lct) { +#if TCL_UTF_MAX < 4 + /* special case for handling upper surrogates */ + if (((lcs & 0xFC00) == 0xD800) && ((lct & 0xFC00) != 0xD800)) { + return 1; + } else if (((lct & 0xFC00) == 0xD800)) { + return -1; + } +#endif return (lcs - lct); } } diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 1904e2f..d5ec040 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -1707,11 +1707,7 @@ TclTrimRight( const char *q = trim; int pInc = 0, bytesLeft = numTrim; - pp = TclUtfPrev(p, bytes); -#if TCL_UTF_MAX < 4 /* Needed because TclUtfPrev() cannot always jump back */ - /* sufficiently. See [d43f96c1a8] */ - pp = TclUtfPrev(pp, bytes); -#endif + pp = Tcl_UtfPrev(p, bytes); do { pp += pInc; pInc = TclUtfToUCS4(pp, &ch1); diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index cdb7bf3..a79681b 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -47,6 +47,7 @@ #define ZIPFS_VOLUME_LEN 9 #define ZIPFS_APP_MOUNT "//zipfs:/app" #define ZIPFS_ZIP_MOUNT "//zipfs:/lib/tcl" +#define ZIPFS_FALLBACK_ENCODING "cp437" /* * Various constants and offsets found in ZIP archive files @@ -129,6 +130,14 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj(errstr, -1)); \ } \ } while (0) +#define ZIPFS_MEM_ERROR(interp) \ + do { \ + if (interp) { \ + Tcl_SetObjResult(interp, Tcl_NewStringObj( \ + "out of memory", -1)); \ + Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); \ + } \ + } while (0) #define ZIPFS_POSIX_ERROR(interp,errstr) \ do { \ if (interp) { \ @@ -136,27 +145,11 @@ "%s: %s", errstr, Tcl_PosixError(interp))); \ } \ } while (0) - -/* - * Macros to read and write 16 and 32 bit integers from/to ZIP archives. - */ - -#define ZipReadInt(p) \ - ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)) -#define ZipReadShort(p) \ - ((p)[0] | ((p)[1] << 8)) - -#define ZipWriteInt(p, v) \ - do { \ - (p)[0] = (v) & 0xff; \ - (p)[1] = ((v) >> 8) & 0xff; \ - (p)[2] = ((v) >> 16) & 0xff; \ - (p)[3] = ((v) >> 24) & 0xff; \ - } while (0) -#define ZipWriteShort(p, v) \ - do { \ - (p)[0] = (v) & 0xff; \ - (p)[1] = ((v) >> 8) & 0xff; \ +#define ZIPFS_ERROR_CODE(interp,errcode) \ + do { \ + if (interp) { \ + Tcl_SetErrorCode(interp, "TCL", "ZIPFS", errcode, NULL); \ + } \ } while (0) /* @@ -177,6 +170,12 @@ TCL_DECLARE_MUTEX(localtimeMutex) #endif /* !_WIN32 && !HAVE_LOCALTIME_R && TCL_THREADS */ /* + * Forward declaration. + */ + +struct ZipEntry; + +/* * In-core description of mounted ZIP archive file. */ @@ -205,6 +204,7 @@ typedef struct ZipFile { /* * In-core description of file contained in mounted ZIP archive. + * ZIP_ATTR_ */ typedef struct ZipEntry { @@ -260,12 +260,22 @@ static struct { int initialized; /* True when initialized */ int lock; /* RW lock, see below */ int waiters; /* RW lock, see below */ - int wrmax; /* Maximum write size of a file */ + int wrmax; /* Maximum write size of a file; only written + * to from Tcl code in a trusted interpreter, + * so NOT protected by mutex. */ + char *fallbackEntryEncoding;/* The fallback encoding for ZIP entries when + * they are believed to not be UTF-8; only + * written to from Tcl code in a trusted + * interpreter, so not protected by mutex. */ + Tcl_Encoding utf8; /* The UTF-8 encoding that we prefer to use + * for the strings (especially filenames) + * embedded in a ZIP. Other encodings are used + * dynamically. */ int idCount; /* Counter for channel names */ Tcl_HashTable fileHash; /* File name to ZipEntry mapping */ Tcl_HashTable zipHash; /* Mount to ZipFile mapping */ } ZipFS = { - 0, 0, 0, DEFAULT_WRITE_MAX_SIZE, 0, + 0, 0, 0, DEFAULT_WRITE_MAX_SIZE, NULL, NULL, 0, {0,{0,0,0,0},0,0,0,0,0,0,0,0,0}, {0,{0,0,0,0},0,0,0,0,0,0,0,0,0} }; @@ -282,9 +292,30 @@ static const char *zipfs_literal_tcl_library = NULL; /* Function prototypes */ +static int CopyImageFile(Tcl_Interp *interp, const char *imgName, + Tcl_Channel out); static inline int DescribeMounted(Tcl_Interp *interp, const char *mountPoint); +static int InitReadableChannel(Tcl_Interp *interp, + ZipChannel *info, ZipEntry *z); +static int InitWritableChannel(Tcl_Interp *interp, + ZipChannel *info, ZipEntry *z, int trunc); static inline int ListMountPoints(Tcl_Interp *interp); +static void SerializeCentralDirectoryEntry( + const unsigned char *start, + const unsigned char *end, unsigned char *buf, + ZipEntry *z, size_t nameLength, + long long dataStartOffset); +static void SerializeCentralDirectorySuffix( + const unsigned char *start, + const unsigned char *end, unsigned char *buf, + int entryCount, long long dataStartOffset, + long long directoryStartOffset, + long long suffixStartOffset); +static void SerializeLocalEntryHeader( + const unsigned char *start, + const unsigned char *end, unsigned char *buf, + ZipEntry *z, int nameLength, int align); #if !defined(STATIC_BUILD) static int ZipfsAppHookFindTclInit(const char *archive); #endif @@ -299,6 +330,9 @@ static Tcl_Channel ZipFSOpenFileChannelProc(Tcl_Interp *interp, static int ZipFSMatchInDirectoryProc(Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); +static void ZipFSMatchMountPoints(Tcl_Obj *result, + Tcl_Obj *normPathPtr, const char *pattern, + Tcl_DString *prefix); static Tcl_Obj * ZipFSListVolumesProc(void); static const char *const *ZipFSFileAttrStringsProc(Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); @@ -309,6 +343,8 @@ static int ZipFSFileAttrsSetProc(Tcl_Interp *interp, int index, static int ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); +static int ZipMapArchive(Tcl_Interp *interp, ZipFile *zf, + void *handle); static void ZipfsExitHandler(ClientData clientData); static void ZipfsSetup(void); static int ZipChannelClose(void *instanceData, @@ -316,12 +352,12 @@ static int ZipChannelClose(void *instanceData, static Tcl_DriverGetHandleProc ZipChannelGetFile; static int ZipChannelRead(void *instanceData, char *buf, int toRead, int *errloc); -#ifndef TCL_NO_DEPRECATED +#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) static int ZipChannelSeek(void *instanceData, long offset, int mode, int *errloc); #endif -static long long ZipChannelWideSeek(void *instanceData, long long offset, - int mode, int *errloc); +static long long ZipChannelWideSeek(void *instanceData, + long long offset, int mode, int *errloc); static void ZipChannelWatchChannel(void *instanceData, int mask); static int ZipChannelWrite(void *instanceData, @@ -360,7 +396,7 @@ static const Tcl_Filesystem zipfsFilesystem = { NULL, /* renameFileProc */ NULL, /* copyDirectoryProc */ NULL, /* lstatProc */ - (Tcl_FSLoadFileProc *)(void *)ZipFSLoadFile, + (Tcl_FSLoadFileProc *) (void *) ZipFSLoadFile, NULL, /* getCwdProc */ NULL, /* chdirProc */ }; @@ -370,27 +406,28 @@ static const Tcl_Filesystem zipfsFilesystem = { */ static Tcl_ChannelType ZipChannelType = { - "zip", /* Type name. */ + "zip", /* Type name. */ TCL_CHANNEL_VERSION_5, - TCL_CLOSE2PROC, /* Close channel, clean instance data */ - ZipChannelRead, /* Handle read request */ - ZipChannelWrite, /* Handle write request */ -#ifndef TCL_NO_DEPRECATED - ZipChannelSeek, /* Move location of access point, NULL'able */ + TCL_CLOSE2PROC, /* Close channel, clean instance data */ + ZipChannelRead, /* Handle read request */ + ZipChannelWrite, /* Handle write request */ +#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) + ZipChannelSeek, /* Move location of access point, NULL'able */ #else - NULL, /* Move location of access point, NULL'able */ + NULL, /* Move location of access point, NULL'able */ #endif - NULL, /* Set options, NULL'able */ - NULL, /* Get options, NULL'able */ - ZipChannelWatchChannel, /* Initialize notifier */ - ZipChannelGetFile, /* Get OS handle from the channel */ - ZipChannelClose, /* 2nd version of close channel, NULL'able */ - NULL, /* Set blocking mode for raw channel, NULL'able */ - NULL, /* Function to flush channel, NULL'able */ - NULL, /* Function to handle event, NULL'able */ - ZipChannelWideSeek, /* Wide seek function, NULL'able */ - NULL, /* Thread action function, NULL'able */ - NULL, /* Truncate function, NULL'able */ + NULL, /* Set options, NULL'able */ + NULL, /* Get options, NULL'able */ + ZipChannelWatchChannel, /* Initialize notifier */ + ZipChannelGetFile, /* Get OS handle from the channel */ + ZipChannelClose, /* 2nd version of close channel, NULL'able */ + NULL, /* Set blocking mode for raw channel, + * NULL'able */ + NULL, /* Function to flush channel, NULL'able */ + NULL, /* Function to handle event, NULL'able */ + ZipChannelWideSeek, /* Wide seek function, NULL'able */ + NULL, /* Thread action function, NULL'able */ + NULL, /* Truncate function, NULL'able */ }; /* @@ -402,6 +439,79 @@ static Tcl_ChannelType ZipChannelType = { /* *------------------------------------------------------------------------- * + * ZipReadInt, ZipReadShort, ZipWriteInt, ZipWriteShort -- + * + * Inline functions to read and write little-endian 16 and 32 bit + * integers from/to buffers representing parts of ZIP archives. + * + * These take bufferStart and bufferEnd pointers, which are used to + * maintain a guarantee that out-of-bounds accesses don't happen when + * reading or writing critical directory structures. + * + *------------------------------------------------------------------------- + */ + +static inline unsigned int +ZipReadInt( + const unsigned char *bufferStart, + const unsigned char *bufferEnd, + const unsigned char *ptr) +{ + if (ptr < bufferStart || ptr + 4 > bufferEnd) { + Tcl_Panic("out of bounds read(4): start=%p, end=%p, ptr=%p", + bufferStart, bufferEnd, ptr); + } + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static inline unsigned short +ZipReadShort( + const unsigned char *bufferStart, + const unsigned char *bufferEnd, + const unsigned char *ptr) +{ + if (ptr < bufferStart || ptr + 2 > bufferEnd) { + Tcl_Panic("out of bounds read(2): start=%p, end=%p, ptr=%p", + bufferStart, bufferEnd, ptr); + } + return ptr[0] | (ptr[1] << 8); +} + +static inline void +ZipWriteInt( + const unsigned char *bufferStart, + const unsigned char *bufferEnd, + unsigned char *ptr, + unsigned int value) +{ + if (ptr < bufferStart || ptr + 4 > bufferEnd) { + Tcl_Panic("out of bounds write(4): start=%p, end=%p, ptr=%p", + bufferStart, bufferEnd, ptr); + } + ptr[0] = value & 0xff; + ptr[1] = (value >> 8) & 0xff; + ptr[2] = (value >> 16) & 0xff; + ptr[3] = (value >> 24) & 0xff; +} + +static inline void +ZipWriteShort( + const unsigned char *bufferStart, + const unsigned char *bufferEnd, + unsigned char *ptr, + unsigned short value) +{ + if (ptr < bufferStart || ptr + 2 > bufferEnd) { + Tcl_Panic("out of bounds write(2): start=%p, end=%p, ptr=%p", + bufferStart, bufferEnd, ptr); + } + ptr[0] = value & 0xff; + ptr[1] = (value >> 8) & 0xff; +} + +/* + *------------------------------------------------------------------------- + * * ReadLock, WriteLock, Unlock -- * * POSIX like rwlock functions to support multiple readers and single @@ -420,7 +530,7 @@ TCL_DECLARE_MUTEX(ZipFSMutex) static Tcl_Condition ZipFSCond; -static void +static inline void ReadLock(void) { Tcl_MutexLock(&ZipFSMutex); @@ -433,7 +543,7 @@ ReadLock(void) Tcl_MutexUnlock(&ZipFSMutex); } -static void +static inline void WriteLock(void) { Tcl_MutexLock(&ZipFSMutex); @@ -446,7 +556,7 @@ WriteLock(void) Tcl_MutexUnlock(&ZipFSMutex); } -static void +static inline void Unlock(void) { Tcl_MutexLock(&ZipFSMutex); @@ -566,7 +676,7 @@ ToDosDate( *------------------------------------------------------------------------- */ -static int +static inline int CountSlashes( const char *string) { @@ -585,6 +695,115 @@ CountSlashes( /* *------------------------------------------------------------------------- * + * DecodeZipEntryText -- + * + * Given a sequence of bytes from an entry in a ZIP central directory, + * convert that into a Tcl string. This is complicated because we don't + * actually know what encoding is in use! So we try to use UTF-8, and if + * that goes wrong, we fall back to a user-specified encoding, or to an + * encoding we specify (Windows code page 437), or to ISO 8859-1 if + * absolutely nothing else works. + * + * During Tcl startup, we skip the user-specified encoding and cp437, as + * we may well not have any loadable encodings yet. Tcl's own library + * files ought to be using ASCII filenames. + * + * Results: + * The decoded filename; the filename is owned by the argument DString. + * + * Side effects: + * Updates dstPtr. + * + *------------------------------------------------------------------------- + */ + +static char * +DecodeZipEntryText( + const unsigned char *inputBytes, + unsigned int inputLength, + Tcl_DString *dstPtr) +{ + Tcl_Encoding encoding; + const char *src; + char *dst; + int dstLen, srcLen = inputLength, flags; + Tcl_EncodingState state; + + Tcl_DStringInit(dstPtr); + if (inputLength < 1) { + return Tcl_DStringValue(dstPtr); + } + + /* + * We can't use Tcl_ExternalToUtfDString at this point; it has no way to + * fail. So we use this modified version of it that can report encoding + * errors to us (so we can fall back to something else). + * + * The utf-8 encoding is implemented internally, and so is guaranteed to + * be present. + */ + + src = (const char *) inputBytes; + dst = Tcl_DStringValue(dstPtr); + dstLen = dstPtr->spaceAvl - 1; + flags = TCL_ENCODING_START | TCL_ENCODING_END | + TCL_ENCODING_STOPONERROR; /* Special flag! */ + + while (1) { + int srcRead, dstWrote; + int result = Tcl_ExternalToUtf(NULL, ZipFS.utf8, src, srcLen, flags, + &state, dst, dstLen, &srcRead, &dstWrote, NULL); + int soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); + + if (result == TCL_OK) { + Tcl_DStringSetLength(dstPtr, soFar); + return Tcl_DStringValue(dstPtr); + } else if (result != TCL_CONVERT_NOSPACE) { + break; + } + + flags &= ~TCL_ENCODING_START; + src += srcRead; + srcLen -= srcRead; + if (Tcl_DStringLength(dstPtr) == 0) { + Tcl_DStringSetLength(dstPtr, dstLen); + } + Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); + dst = Tcl_DStringValue(dstPtr) + soFar; + dstLen = Tcl_DStringLength(dstPtr) - soFar - 1; + } + + /* + * Something went wrong. Fall back to another encoding. Those *can* use + * Tcl_ExternalToUtfDString(). + */ + + encoding = NULL; + if (ZipFS.fallbackEntryEncoding) { + encoding = Tcl_GetEncoding(NULL, ZipFS.fallbackEntryEncoding); + } + if (!encoding) { + encoding = Tcl_GetEncoding(NULL, ZIPFS_FALLBACK_ENCODING); + } + if (!encoding) { + /* + * Fallback to internal encoding that always converts all bytes. + * Should only happen when a filename isn't UTF-8 and we've not got + * our encodings initialised for some reason. + */ + + encoding = Tcl_GetEncoding(NULL, "iso8859-1"); + } + + char *converted = Tcl_ExternalToUtfDString(encoding, + (const char *) inputBytes, inputLength, dstPtr); + Tcl_FreeEncoding(encoding); + return converted; +} + +/* + *------------------------------------------------------------------------- + * * CanonicalPath -- * * This function computes the canonical path from a directory and file @@ -770,16 +989,16 @@ CanonicalPath( *------------------------------------------------------------------------- */ -static ZipEntry * +static inline ZipEntry * ZipFSLookup( - char *filename) + const char *filename) { Tcl_HashEntry *hPtr; ZipEntry *z = NULL; hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename); if (hPtr) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); } return z; } @@ -787,13 +1006,13 @@ ZipFSLookup( /* *------------------------------------------------------------------------- * - * ZipFSLookupMount -- + * ZipFSLookupZip -- * - * This function returns an indication if the given file name corresponds - * to a mounted ZIP archive file. + * This function gets the structure for a mounted ZIP archive. * * Results: - * Returns true, if the given file name is a mounted ZIP archive file. + * Returns a pointer to the structure, or NULL if the file is ZIP file is + * unknown/not mounted. * * Side effects: * None. @@ -801,25 +1020,76 @@ ZipFSLookup( *------------------------------------------------------------------------- */ -#ifdef NEVER_USED -static int -ZipFSLookupMount( - char *filename) +static inline ZipFile * +ZipFSLookupZip( + const char *mountPoint) { Tcl_HashEntry *hPtr; - Tcl_HashSearch search; + ZipFile *zf = NULL; - for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; - hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = Tcl_GetHashValue(hPtr); + hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint); + if (hPtr) { + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + } + return zf; +} + +/* + *------------------------------------------------------------------------- + * + * AllocateZipFile, AllocateZipEntry, AllocateZipChannel -- + * + * Allocates the memory for a datastructure. Always ensures that it is + * zeroed out for safety. + * + * Returns: + * The allocated structure, or NULL if allocate fails. + * + * Side effects: + * The interpreter result may be written to on error. Which might fail + * (for ZipFile) in a low-memory situation. Always panics if ZipEntry + * allocation fails. + * + *------------------------------------------------------------------------- + */ - if (strcmp(zf->mountPoint, filename) == 0) { - return 1; - } +static inline ZipFile * +AllocateZipFile( + Tcl_Interp *interp, + size_t mountPointNameLength) +{ + size_t size = sizeof(ZipFile) + mountPointNameLength + 1; + ZipFile *zf = (ZipFile *) attemptckalloc(size); + + if (!zf) { + ZIPFS_MEM_ERROR(interp); + } else { + memset(zf, 0, size); } - return 0; + return zf; +} + +static inline ZipEntry * +AllocateZipEntry(void) +{ + ZipEntry *z = (ZipEntry *) ckalloc(sizeof(ZipEntry)); + memset(z, 0, sizeof(ZipEntry)); + return z; +} + +static inline ZipChannel * +AllocateZipChannel( + Tcl_Interp *interp) +{ + ZipChannel *zc = (ZipChannel *) attemptckalloc(sizeof(ZipChannel)); + + if (!zc) { + ZIPFS_MEM_ERROR(interp); + } else { + memset(zc, 0, sizeof(ZipChannel)); + } + return zc; } -#endif /* NEVER_USED */ /* *------------------------------------------------------------------------- @@ -856,6 +1126,10 @@ ZipFSCloseArchive( return; } + /* + * Remove the memory mapping, if we have one. + */ + #ifdef _WIN32 if (zf->data && !zf->ptrToFree) { UnmapViewOfFile(zf->data); @@ -867,7 +1141,7 @@ ZipFSCloseArchive( #else /* !_WIN32 */ if ((zf->data != MAP_FAILED) && !zf->ptrToFree) { munmap(zf->data, zf->length); - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; } #endif /* _WIN32 */ @@ -888,7 +1162,7 @@ ZipFSCloseArchive( * * This function takes a memory mapped zip file and indexes the contents. * When "needZip" is zero an embedded ZIP archive in an executable file - * is accepted. + * is accepted. Note that we do not support ZIP64. * * Results: * TCL_OK on success, TCL_ERROR otherwise with an error message placed @@ -908,12 +1182,20 @@ ZipFSFindTOC( ZipFile *zf) { size_t i; - unsigned char *p, *q; + const unsigned char *p, *q; + const unsigned char *start = zf->data; + const unsigned char *end = zf->data + zf->length; + + /* + * Scan backwards from the end of the file for the signature. This is + * necessary because ZIP archives aren't the only things that get tagged + * on the end of executables; digital signatures can also go there. + */ p = zf->data + zf->length - ZIP_CENTRAL_END_LEN; - while (p >= zf->data) { + while (p >= start) { if (*p == (ZIP_CENTRAL_END_SIG & 0xFF)) { - if (ZipReadInt(p) == ZIP_CENTRAL_END_SIG) { + if (ZipReadInt(start, end, p) == ZIP_CENTRAL_END_SIG) { break; } p -= ZIP_SIG_LEN; @@ -922,73 +1204,93 @@ ZipFSFindTOC( } } if (p < zf->data) { + /* + * Didn't find it (or not enough space for a central directory!); not + * a ZIP archive. This might be OK or a problem. + */ + if (!needZip) { zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } ZIPFS_ERROR(interp, "wrong end signature"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "END_SIG", NULL); - } + ZIPFS_ERROR_CODE(interp, "END_SIG"); goto error; } - zf->numFiles = ZipReadShort(p + ZIP_CENTRAL_ENTS_OFFS); + + /* + * How many files in the archive? If that's bogus, we're done here. + */ + + zf->numFiles = ZipReadShort(start, end, p + ZIP_CENTRAL_ENTS_OFFS); if (zf->numFiles == 0) { if (!needZip) { zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } ZIPFS_ERROR(interp, "empty archive"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL); - } + ZIPFS_ERROR_CODE(interp, "EMPTY"); goto error; } - q = zf->data + ZipReadInt(p + ZIP_CENTRAL_DIRSTART_OFFS); - p -= ZipReadInt(p + ZIP_CENTRAL_DIRSIZE_OFFS); - if ((p < zf->data) || (p > zf->data + zf->length) + + /* + * Where does the central directory start? + */ + + q = zf->data + ZipReadInt(start, end, p + ZIP_CENTRAL_DIRSTART_OFFS); + p -= ZipReadInt(start, end, p + ZIP_CENTRAL_DIRSIZE_OFFS); + if ((p < q) || (p < zf->data) || (p > zf->data + zf->length) || (q < zf->data) || (q > zf->data + zf->length)) { if (!needZip) { zf->baseOffset = zf->passOffset = zf->length; return TCL_OK; } ZIPFS_ERROR(interp, "archive directory not found"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_DIR", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_DIR"); goto error; } + + /* + * Read the central directory. + */ + zf->baseOffset = zf->passOffset = p - q; zf->directoryOffset = p - zf->data; q = p; for (i = 0; i < zf->numFiles; i++) { int pathlen, comlen, extra; - if (q + ZIP_CENTRAL_HEADER_LEN > zf->data + zf->length) { + if (q + ZIP_CENTRAL_HEADER_LEN > end) { ZIPFS_ERROR(interp, "wrong header length"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_LEN", NULL); - } + ZIPFS_ERROR_CODE(interp, "HDR_LEN"); goto error; } - if (ZipReadInt(q) != ZIP_CENTRAL_HEADER_SIG) { + if (ZipReadInt(start, end, q) != ZIP_CENTRAL_HEADER_SIG) { ZIPFS_ERROR(interp, "wrong header signature"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_SIG", NULL); - } + ZIPFS_ERROR_CODE(interp, "HDR_SIG"); goto error; } - pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS); - comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); - extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS); + pathlen = ZipReadShort(start, end, q + ZIP_CENTRAL_PATHLEN_OFFS); + comlen = ZipReadShort(start, end, q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + extra = ZipReadShort(start, end, q + ZIP_CENTRAL_EXTRALEN_OFFS); q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; } + + /* + * If there's also an encoded password, extract that too (but don't decode + * yet). + */ + q = zf->data + zf->baseOffset; - if ((zf->baseOffset >= 6) && (ZipReadInt(q - 4) == ZIP_PASSWORD_END_SIG)) { + if ((zf->baseOffset >= 6) && + (ZipReadInt(start, end, q - 4) == ZIP_PASSWORD_END_SIG)) { + const unsigned char *passPtr; + i = q[-5]; - if (q - 5 - i > zf->data) { + passPtr = q - 5 - i; + if (passPtr >= start && passPtr + i < end) { zf->passBuf[0] = i; - memcpy(zf->passBuf + 1, q - 5 - i, i); + memcpy(zf->passBuf + 1, passPtr, i); zf->passOffset -= i ? (5 + i) : 0; } } @@ -1037,18 +1339,42 @@ ZipFSOpenArchive( zf->data = NULL; zf->mountHandle = INVALID_HANDLE_VALUE; #else /* !_WIN32 */ - zf->data = (unsigned char *)MAP_FAILED; + zf->data = (unsigned char *) MAP_FAILED; #endif /* _WIN32 */ zf->length = 0; zf->numFiles = 0; zf->baseOffset = zf->passOffset = 0; zf->ptrToFree = NULL; zf->passBuf[0] = 0; + + /* + * Actually open the file. + */ + zf->chan = Tcl_OpenFileChannel(interp, zipname, "rb", 0); if (!zf->chan) { return TCL_ERROR; } - if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) { + + /* + * See if we can get the OS handle. If we can, we can use that to memory + * map the file, which is nice and efficient. However, it totally depends + * on the filename pointing to a real regular OS file. + * + * Opening real filesystem entities that are not files will lead to an + * error. + */ + + if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) == TCL_OK) { + if (ZipMapArchive(interp, zf, handle) != TCL_OK) { + goto error; + } + } else { + /* + * Not an OS file, but rather something in a Tcl VFS. Must copy into + * memory. + */ + zf->length = Tcl_Seek(zf->chan, 0, SEEK_END); if (zf->length == ERROR_LENGTH) { ZIPFS_POSIX_ERROR(interp, "seek error"); @@ -1057,21 +1383,16 @@ ZipFSOpenArchive( if ((zf->length - ZIP_CENTRAL_END_LEN) > (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) { ZIPFS_ERROR(interp, "illegal file size"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL); - } + ZIPFS_ERROR_CODE(interp, "FILE_SIZE"); goto error; } if (Tcl_Seek(zf->chan, 0, SEEK_SET) == -1) { ZIPFS_POSIX_ERROR(interp, "seek error"); goto error; } - zf->ptrToFree = zf->data = (unsigned char *)attemptckalloc(zf->length); + zf->ptrToFree = zf->data = (unsigned char *) attemptckalloc(zf->length); if (!zf->ptrToFree) { - ZIPFS_ERROR(interp, "out of memory"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } + ZIPFS_MEM_ERROR(interp); goto error; } i = Tcl_Read(zf->chan, (char *) zf->data, zf->length); @@ -1081,67 +1402,137 @@ ZipFSOpenArchive( } Tcl_Close(interp, zf->chan); zf->chan = NULL; - } else { + } + return ZipFSFindTOC(interp, needZip, zf); + + /* + * Handle errors by closing the archive. This includes closing the channel + * handle for the archive file. + */ + + error: + ZipFSCloseArchive(interp, zf); + return TCL_ERROR; +} + +/* + *------------------------------------------------------------------------- + * + * ZipMapArchive -- + * + * Wrapper around the platform-specific parts of mmap() (and Windows's + * equivalent) because it's not part of the standard channel API. + * + *------------------------------------------------------------------------- + */ + +static int +ZipMapArchive( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + ZipFile *zf, /* The archive descriptor structure. */ + void *handle) /* The OS handle to the open archive. */ +{ #ifdef _WIN32 - int readSuccessful; + HANDLE hFile = (HANDLE) handle; + int readSuccessful; + + /* + * Determine the file size. + */ + # ifdef _WIN64 - i = GetFileSizeEx((HANDLE) handle, (PLARGE_INTEGER) &zf->length); - readSuccessful = (i != 0); + readSuccessful = GetFileSizeEx(hFile, (PLARGE_INTEGER) &zf->length) != 0; # else /* !_WIN64 */ - zf->length = GetFileSize((HANDLE) handle, 0); - readSuccessful = (zf->length != (size_t) INVALID_FILE_SIZE); + zf->length = GetFileSize(hFile, 0); + readSuccessful = (zf->length != (size_t) INVALID_FILE_SIZE); # endif /* _WIN64 */ - if (!readSuccessful || (zf->length < ZIP_CENTRAL_END_LEN)) { - ZIPFS_POSIX_ERROR(interp, "invalid file size"); - goto error; - } - zf->mountHandle = CreateFileMappingW((HANDLE) handle, 0, PAGE_READONLY, - 0, zf->length, 0); - if (zf->mountHandle == INVALID_HANDLE_VALUE) { - ZIPFS_POSIX_ERROR(interp, "file mapping failed"); - goto error; - } - zf->data = (unsigned char *)MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0, - zf->length); - if (!zf->data) { - ZIPFS_POSIX_ERROR(interp, "file mapping failed"); - goto error; - } + if (!readSuccessful || (zf->length < ZIP_CENTRAL_END_LEN)) { + ZIPFS_POSIX_ERROR(interp, "invalid file size"); + return TCL_ERROR; + } + + /* + * Map the file. + */ + + zf->mountHandle = CreateFileMappingW(hFile, 0, PAGE_READONLY, 0, + zf->length, 0); + if (zf->mountHandle == INVALID_HANDLE_VALUE) { + ZIPFS_POSIX_ERROR(interp, "file mapping failed"); + return TCL_ERROR; + } + zf->data = (unsigned char *) + MapViewOfFile(zf->mountHandle, FILE_MAP_READ, 0, 0, zf->length); + if (!zf->data) { + ZIPFS_POSIX_ERROR(interp, "file mapping failed"); + return TCL_ERROR; + } #else /* !_WIN32 */ - zf->length = lseek(PTR2INT(handle), 0, SEEK_END); - if (zf->length == ERROR_LENGTH || zf->length < ZIP_CENTRAL_END_LEN) { - ZIPFS_POSIX_ERROR(interp, "invalid file size"); - goto error; - } - lseek(PTR2INT(handle), 0, SEEK_SET); - zf->data = (unsigned char *) mmap(0, zf->length, PROT_READ, - MAP_FILE | MAP_PRIVATE, PTR2INT(handle), 0); - if (zf->data == MAP_FAILED) { - ZIPFS_POSIX_ERROR(interp, "file mapping failed"); - goto error; - } -#endif /* _WIN32 */ + int fd = PTR2INT(handle); + + /* + * Determine the file size. + */ + + zf->length = lseek(fd, 0, SEEK_END); + if (zf->length == ERROR_LENGTH || zf->length < ZIP_CENTRAL_END_LEN) { + ZIPFS_POSIX_ERROR(interp, "invalid file size"); + return TCL_ERROR; } - return ZipFSFindTOC(interp, needZip, zf); + lseek(fd, 0, SEEK_SET); - error: - ZipFSCloseArchive(interp, zf); - return TCL_ERROR; + zf->data = (unsigned char *) + mmap(0, zf->length, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + if (zf->data == MAP_FAILED) { + ZIPFS_POSIX_ERROR(interp, "file mapping failed"); + return TCL_ERROR; + } +#endif /* _WIN32 */ + return TCL_OK; } /* *------------------------------------------------------------------------- * - * ZipFSRootNode -- + * IsPasswordValid -- * - * This function generates the root node for a ZIPFS filesystem. + * Basic test for whether a passowrd is valid. If the test fails, sets an + * error message in the interpreter. + * + * Returns: + * TCL_OK if the test passes, TCL_ERROR if it fails. + * + *------------------------------------------------------------------------- + */ + +static inline int +IsPasswordValid( + Tcl_Interp *interp, + const char *passwd, + int pwlen) +{ + if ((pwlen > 255) || strchr(passwd, 0xff)) { + ZIPFS_ERROR(interp, "illegal password"); + ZIPFS_ERROR_CODE(interp, "BAD_PASS"); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * + * ZipFSCatalogFilesystem -- + * + * This function generates the root node for a ZIPFS filesystem by + * reading the ZIP's central directory. * * Results: * TCL_OK on success, TCL_ERROR otherwise with an error message placed * into the given "interp" if it is not NULL. * * Side effects: - * ... + * Will acquire and release the write lock. * *------------------------------------------------------------------------- */ @@ -1149,7 +1540,7 @@ ZipFSOpenArchive( static int ZipFSCatalogFilesystem( Tcl_Interp *interp, /* Current interpreter. NULLable. */ - ZipFile *zf0, + ZipFile *zf0, /* Temporary buffer hold archive descriptors */ const char *mountPoint, /* Mount point path. */ const char *passwd, /* Password for opening the ZIP, or NULL if * the ZIP is unprotected. */ @@ -1170,16 +1561,22 @@ ZipFSCatalogFilesystem( pwlen = 0; if (passwd) { pwlen = strlen(passwd); - if ((pwlen > 255) || strchr(passwd, 0xff)) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL); - } + if (IsPasswordValid(interp, passwd, pwlen) != TCL_OK) { return TCL_ERROR; } } + /* + * Validate the TOC data. If that's bad, things fall apart. + */ + + if (zf0->baseOffset >= zf0->length || zf0->passOffset >= zf0->length || + zf0->directoryOffset >= zf0->length) { + ZIPFS_ERROR(interp, "bad zip data"); + ZIPFS_ERROR_CODE(interp, "BAD_ZIP"); + return TCL_ERROR; + } + WriteLock(); /* @@ -1197,37 +1594,36 @@ ZipFSCatalogFilesystem( hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew); if (!isNew) { if (interp) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s is already mounted on %s", zf->name, mountPoint)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "MOUNTED", NULL); + ZIPFS_ERROR_CODE(interp, "MOUNTED"); } Unlock(); ZipFSCloseArchive(interp, zf0); return TCL_ERROR; } - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = AllocateZipFile(interp, strlen(mountPoint)); if (!zf) { - if (interp) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } Unlock(); ZipFSCloseArchive(interp, zf0); return TCL_ERROR; } Unlock(); + /* + * Convert to a real archive descriptor. + */ + *zf = *zf0; - zf->mountPoint = (char *)Tcl_GetHashKey(&ZipFS.zipHash, hPtr); + zf->mountPoint = (char *) Tcl_GetHashKey(&ZipFS.zipHash, hPtr); Tcl_CreateExitHandler(ZipfsExitHandler, zf); zf->mountPointLen = strlen(zf->mountPoint); + zf->nameLength = strlen(zipname); - zf->name = (char *)ckalloc(zf->nameLength + 1); + zf->name = (char *) ckalloc(zf->nameLength + 1); memcpy(zf->name, zipname, zf->nameLength + 1); - zf->entries = NULL; - zf->topEnts = NULL; - zf->numOpen = 0; + Tcl_SetHashValue(hPtr, zf); if ((zf->passBuf[0] == 0) && pwlen) { int k = 0; @@ -1242,21 +1638,15 @@ ZipFSCatalogFilesystem( if (mountPoint[0] != '\0') { hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew); if (isNew) { - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + z = AllocateZipEntry(); Tcl_SetHashValue(hPtr, z); - z->tnext = NULL; z->depth = CountSlashes(mountPoint); z->zipFilePtr = zf; z->isDirectory = (zf->baseOffset == 0) ? 1 : -1; /* root marker */ - z->isEncrypted = 0; z->offset = zf->baseOffset; - z->crc32 = 0; - z->timestamp = 0; - z->numBytes = z->numCompressedBytes = 0; z->compressMethod = ZIP_COMPMETH_STORED; - z->data = NULL; - z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); z->next = zf->entries; zf->entries = z; } @@ -1264,17 +1654,17 @@ ZipFSCatalogFilesystem( q = zf->data + zf->directoryOffset; Tcl_DStringInit(&fpBuf); for (i = 0; i < zf->numFiles; i++) { + const unsigned char *start = zf->data; + const unsigned char *end = zf->data + zf->length; int extra, isdir = 0, dosTime, dosDate, nbcompr; size_t offs, pathlen, comlen; unsigned char *lq, *gq = NULL; char *fullpath, *path; - pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS); - comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); - extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS); - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen); - path = Tcl_DStringValue(&ds); + pathlen = ZipReadShort(start, end, q + ZIP_CENTRAL_PATHLEN_OFFS); + comlen = ZipReadShort(start, end, q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); + extra = ZipReadShort(start, end, q + ZIP_CENTRAL_EXTRALEN_OFFS); + path = DecodeZipEntryText(q + ZIP_CENTRAL_HEADER_LEN, pathlen, &ds); if ((pathlen > 0) && (path[pathlen - 1] == '/')) { Tcl_DStringSetLength(&ds, pathlen - 1); path = Tcl_DStringValue(&ds); @@ -1284,24 +1674,25 @@ ZipFSCatalogFilesystem( goto nextent; } lq = zf->data + zf->baseOffset - + ZipReadInt(q + ZIP_CENTRAL_LOCALHDR_OFFS); - if ((lq < zf->data) || (lq > zf->data + zf->length)) { + + ZipReadInt(start, end, q + ZIP_CENTRAL_LOCALHDR_OFFS); + if ((lq < start) || (lq + ZIP_LOCAL_HEADER_LEN > end)) { goto nextent; } - nbcompr = ZipReadInt(lq + ZIP_LOCAL_COMPLEN_OFFS); + nbcompr = ZipReadInt(start, end, lq + ZIP_LOCAL_COMPLEN_OFFS); if (!isdir && (nbcompr == 0) - && (ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) - && (ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { + && (ZipReadInt(start, end, lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0) + && (ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS) == 0)) { gq = q; - nbcompr = ZipReadInt(gq + ZIP_CENTRAL_COMPLEN_OFFS); + nbcompr = ZipReadInt(start, end, gq + ZIP_CENTRAL_COMPLEN_OFFS); } offs = (lq - zf->data) + ZIP_LOCAL_HEADER_LEN - + ZipReadShort(lq + ZIP_LOCAL_PATHLEN_OFFS) - + ZipReadShort(lq + ZIP_LOCAL_EXTRALEN_OFFS); + + ZipReadShort(start, end, lq + ZIP_LOCAL_PATHLEN_OFFS) + + ZipReadShort(start, end, lq + ZIP_LOCAL_EXTRALEN_OFFS); if (offs + nbcompr > zf->length) { goto nextent; } + if (!isdir && (mountPoint[0] == '\0') && !CountSlashes(path)) { #ifdef ANDROID /* @@ -1317,8 +1708,7 @@ ZipFSCatalogFilesystem( Tcl_DStringInit(&ds2); Tcl_DStringAppend(&ds2, "assets/.root/", -1); Tcl_DStringAppend(&ds2, path, -1); - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, Tcl_DStringValue(&ds2)); - if (hPtr) { + if (ZipFSLookup(Tcl_DStringValue(&ds2))) { /* should not happen but skip it anyway */ Tcl_DStringFree(&ds2); goto nextent; @@ -1335,83 +1725,91 @@ ZipFSCatalogFilesystem( goto nextent; #endif /* ANDROID */ } + Tcl_DStringSetLength(&fpBuf, 0); fullpath = CanonicalPath(mountPoint, path, &fpBuf, 1); - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); - z->name = NULL; - z->tnext = NULL; + z = AllocateZipEntry(); z->depth = CountSlashes(fullpath); z->zipFilePtr = zf; z->isDirectory = isdir; - z->isEncrypted = (ZipReadShort(lq + ZIP_LOCAL_FLAGS_OFFS) & 1) + z->isEncrypted = + (ZipReadShort(start, end, lq + ZIP_LOCAL_FLAGS_OFFS) & 1) && (nbcompr > 12); z->offset = offs; if (gq) { - z->crc32 = ZipReadInt(gq + ZIP_CENTRAL_CRC32_OFFS); - dosDate = ZipReadShort(gq + ZIP_CENTRAL_MDATE_OFFS); - dosTime = ZipReadShort(gq + ZIP_CENTRAL_MTIME_OFFS); + z->crc32 = ZipReadInt(start, end, gq + ZIP_CENTRAL_CRC32_OFFS); + dosDate = ZipReadShort(start, end, gq + ZIP_CENTRAL_MDATE_OFFS); + dosTime = ZipReadShort(start, end, gq + ZIP_CENTRAL_MTIME_OFFS); z->timestamp = DosTimeDate(dosDate, dosTime); - z->numBytes = ZipReadInt(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS); - z->compressMethod = ZipReadShort(gq + ZIP_CENTRAL_COMPMETH_OFFS); + z->numBytes = ZipReadInt(start, end, + gq + ZIP_CENTRAL_UNCOMPLEN_OFFS); + z->compressMethod = ZipReadShort(start, end, + gq + ZIP_CENTRAL_COMPMETH_OFFS); } else { - z->crc32 = ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS); - dosDate = ZipReadShort(lq + ZIP_LOCAL_MDATE_OFFS); - dosTime = ZipReadShort(lq + ZIP_LOCAL_MTIME_OFFS); + z->crc32 = ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS); + dosDate = ZipReadShort(start, end, lq + ZIP_LOCAL_MDATE_OFFS); + dosTime = ZipReadShort(start, end, lq + ZIP_LOCAL_MTIME_OFFS); z->timestamp = DosTimeDate(dosDate, dosTime); - z->numBytes = ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS); - z->compressMethod = ZipReadShort(lq + ZIP_LOCAL_COMPMETH_OFFS); + z->numBytes = ZipReadInt(start, end, + lq + ZIP_LOCAL_UNCOMPLEN_OFFS); + z->compressMethod = ZipReadShort(start, end, + lq + ZIP_LOCAL_COMPMETH_OFFS); } z->numCompressedBytes = nbcompr; - z->data = NULL; hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew); if (!isNew) { /* should not happen but skip it anyway */ ckfree(z); - } else { - Tcl_SetHashValue(hPtr, z); - z->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); - z->next = zf->entries; - zf->entries = z; - if (isdir && (mountPoint[0] == '\0') && (z->depth == 1)) { - z->tnext = zf->topEnts; - zf->topEnts = z; - } - if (!z->isDirectory && (z->depth > 1)) { - char *dir, *end; - ZipEntry *zd; - - Tcl_DStringSetLength(&ds, strlen(z->name) + 8); - Tcl_DStringSetLength(&ds, 0); - Tcl_DStringAppend(&ds, z->name, -1); - dir = Tcl_DStringValue(&ds); - for (end = strrchr(dir, '/'); end && (end != dir); - end = strrchr(dir, '/')) { - Tcl_DStringSetLength(&ds, end - dir); - hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew); - if (!isNew) { - break; - } - zd = (ZipEntry *)ckalloc(sizeof(ZipEntry)); - zd->name = NULL; - zd->tnext = NULL; - zd->depth = CountSlashes(dir); - zd->zipFilePtr = zf; - zd->isDirectory = 1; - zd->isEncrypted = 0; - zd->offset = z->offset; - zd->crc32 = 0; - zd->timestamp = z->timestamp; - zd->numBytes = zd->numCompressedBytes = 0; - zd->compressMethod = ZIP_COMPMETH_STORED; - zd->data = NULL; - Tcl_SetHashValue(hPtr, zd); - zd->name = (char *)Tcl_GetHashKey(&ZipFS.fileHash, hPtr); - zd->next = zf->entries; - zf->entries = zd; - if ((mountPoint[0] == '\0') && (zd->depth == 1)) { - zd->tnext = zf->topEnts; - zf->topEnts = zd; - } + goto nextent; + } + + Tcl_SetHashValue(hPtr, z); + z->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + z->next = zf->entries; + zf->entries = z; + if (isdir && (mountPoint[0] == '\0') && (z->depth == 1)) { + z->tnext = zf->topEnts; + zf->topEnts = z; + } + + /* + * Make any directory nodes we need. ZIPs are not consistent about + * containing directory nodes. + */ + + if (!z->isDirectory && (z->depth > 1)) { + char *dir, *endPtr; + ZipEntry *zd; + + Tcl_DStringSetLength(&ds, strlen(z->name) + 8); + Tcl_DStringSetLength(&ds, 0); + Tcl_DStringAppend(&ds, z->name, -1); + dir = Tcl_DStringValue(&ds); + for (endPtr = strrchr(dir, '/'); endPtr && (endPtr != dir); + endPtr = strrchr(dir, '/')) { + Tcl_DStringSetLength(&ds, endPtr - dir); + hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, dir, &isNew); + if (!isNew) { + /* + * Already made. That's fine. + */ + break; + } + + zd = AllocateZipEntry(); + zd->depth = CountSlashes(dir); + zd->zipFilePtr = zf; + zd->isDirectory = 1; + zd->offset = z->offset; + zd->timestamp = z->timestamp; + zd->compressMethod = ZIP_COMPMETH_STORED; + Tcl_SetHashValue(hPtr, zd); + zd->name = (char *) Tcl_GetHashKey(&ZipFS.fileHash, hPtr); + zd->next = zf->entries; + zf->entries = zd; + if ((mountPoint[0] == '\0') && (zd->depth == 1)) { + zd->tnext = zf->topEnts; + zf->topEnts = zd; } } } @@ -1456,6 +1854,10 @@ ZipfsSetup(void) Tcl_InitHashTable(&ZipFS.zipHash, TCL_STRING_KEYS); ZipFS.idCount = 1; ZipFS.wrmax = DEFAULT_WRITE_MAX_SIZE; + ZipFS.fallbackEntryEncoding = (char *) + ckalloc(strlen(ZIPFS_FALLBACK_ENCODING) + 1); + strcpy(ZipFS.fallbackEntryEncoding, ZIPFS_FALLBACK_ENCODING); + ZipFS.utf8 = Tcl_GetEncoding(NULL, "utf-8"); ZipFS.initialized = 1; } @@ -1485,17 +1887,28 @@ ListMountPoints( Tcl_HashEntry *hPtr; Tcl_HashSearch search; ZipFile *zf; + Tcl_Obj *resultList; + + if (!interp) { + /* + * Are there any entries in the zipHash? Don't need to enumerate them + * all to know. + */ + + return (ZipFS.zipHash.numEntries ? TCL_OK : TCL_BREAK); + } + resultList = Tcl_NewObj(); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - if (!interp) { - return TCL_OK; - } - zf = (ZipFile *)Tcl_GetHashValue(hPtr); - Tcl_AppendElement(interp, zf->mountPoint); - Tcl_AppendElement(interp, zf->name); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); + Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj( + zf->mountPoint, -1)); + Tcl_ListObjAppendElement(NULL, resultList, Tcl_NewStringObj( + zf->name, -1)); } - return (interp ? TCL_OK : TCL_BREAK); + Tcl_SetObjResult(interp, resultList); + return TCL_OK; } /* @@ -1522,13 +1935,10 @@ DescribeMounted( Tcl_Interp *interp, const char *mountPoint) { - Tcl_HashEntry *hPtr; - ZipFile *zf; - if (interp) { - hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint); - if (hPtr) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + ZipFile *zf = ZipFSLookupZip(mountPoint); + + if (zf) { Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1)); return TCL_OK; } @@ -1558,7 +1968,8 @@ int TclZipfs_Mount( Tcl_Interp *interp, /* Current interpreter. NULLable. */ const char *mountPoint, /* Mount point path. */ - const char *zipname, /* Path to ZIP file to mount. */ + const char *zipname, /* Path to ZIP file to mount; should be + * normalized. */ const char *passwd) /* Password for opening the ZIP, or NULL if * the ZIP is unprotected. */ { @@ -1595,22 +2006,11 @@ TclZipfs_Mount( * Have both a mount point and a file (name) to mount there. */ - if (passwd) { - if ((strlen(passwd) > 255) || strchr(passwd, 0xff)) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL); - } - return TCL_ERROR; - } + if (passwd && IsPasswordValid(interp, passwd, strlen(passwd)) != TCL_OK) { + return TCL_ERROR; } - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = AllocateZipFile(interp, strlen(mountPoint)); if (!zf) { - if (interp) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } return TCL_ERROR; } if (ZipFSOpenArchive(interp, zipname, 1, zf) != TCL_OK) { @@ -1686,23 +2086,16 @@ TclZipfs_MountBuffer( * Have both a mount point and data to mount there. */ - zf = (ZipFile *)attemptckalloc(sizeof(ZipFile) + strlen(mountPoint) + 1); + zf = AllocateZipFile(interp, strlen(mountPoint)); if (!zf) { - if (interp) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } return TCL_ERROR; } zf->isMemBuffer = 1; zf->length = datalen; if (copy) { - zf->data = (unsigned char *)attemptckalloc(datalen); + zf->data = (unsigned char *) attemptckalloc(datalen); if (!zf->data) { - if (interp) { - Tcl_AppendResult(interp, "out of memory", (char *) NULL); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } + ZIPFS_MEM_ERROR(interp); return TCL_ERROR; } memcpy(zf->data, data, datalen); @@ -1711,7 +2104,6 @@ TclZipfs_MountBuffer( zf->data = data; zf->ptrToFree = NULL; } - zf->passBuf[0] = 0; /* stop valgrind cries */ if (ZipFSFindTOC(interp, 0, zf) != TCL_OK) { return TCL_ERROR; } @@ -1767,13 +2159,20 @@ TclZipfs_Unmount( goto done; } - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->numOpen > 0) { ZIPFS_ERROR(interp, "filesystem is busy"); + ZIPFS_ERROR_CODE(interp, "BUSY"); ret = TCL_ERROR; goto done; } Tcl_DeleteHashEntry(hPtr); + + /* + * Now no longer mounted - the rest of the code won't find it - but we're + * still cleaning things up. + */ + for (z = zf->entries; z; z = znext) { znext = z->next; hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name); @@ -1789,6 +2188,7 @@ TclZipfs_Unmount( Tcl_DeleteExitHandler(ZipfsExitHandler, zf); ckfree(zf); unmounted = 1; + done: Unlock(); if (unmounted) { @@ -1820,16 +2220,38 @@ ZipFSMountObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + const char *mountPoint = NULL, *zipFile = NULL, *password = NULL; + Tcl_Obj *zipFileObj = NULL; + int result; if (objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?zipfile? ?password?"); return TCL_ERROR; } + if (objc > 1) { + mountPoint = Tcl_GetString(objv[1]); + } + if (objc > 2) { + zipFileObj = Tcl_FSGetNormalizedPath(interp, objv[2]); + if (!zipFileObj) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "could not normalize zip filename", -1)); + Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NORMALIZE", NULL); + return TCL_ERROR; + } + Tcl_IncrRefCount(zipFileObj); + zipFile = Tcl_GetString(zipFileObj); + } + if (objc > 3) { + password = Tcl_GetString(objv[3]); + } - return TclZipfs_Mount(interp, (objc > 1) ? Tcl_GetString(objv[1]) : NULL, - (objc > 2) ? Tcl_GetString(objv[2]) : NULL, - (objc > 3) ? Tcl_GetString(objv[3]) : NULL); + result = TclZipfs_Mount(interp, mountPoint, zipFile, password); + if (zipFileObj != NULL) { + Tcl_DecrRefCount(zipFileObj); + } + return result; } /* @@ -1937,7 +2359,6 @@ ZipFSUnmountObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "zipfile"); return TCL_ERROR; @@ -1970,49 +2391,95 @@ ZipFSMkKeyObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int len, i = 0; - char *pw, passBuf[264]; + const char *pw; + Tcl_Obj *passObj; + unsigned char *passBuf; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "password"); return TCL_ERROR; } - pw = Tcl_GetString(objv[1]); - len = strlen(pw); + pw = Tcl_GetStringFromObj(objv[1], &len); if (len == 0) { return TCL_OK; } - if ((len > 255) || strchr(pw, 0xff)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1)); + if (IsPasswordValid(interp, pw, len) != TCL_OK) { return TCL_ERROR; } + + passObj = Tcl_NewByteArrayObj(NULL, 264); + passBuf = Tcl_GetByteArrayFromObj(passObj, (int *)NULL); while (len > 0) { int ch = pw[len - 1]; - passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; - i++; + passBuf[i++] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; len--; } passBuf[i] = i; - ++i; - passBuf[i++] = (char) ZIP_PASSWORD_END_SIG; - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 8); - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 16); - passBuf[i++] = (char) (ZIP_PASSWORD_END_SIG >> 24); - passBuf[i] = '\0'; - Tcl_AppendResult(interp, passBuf, (char *) NULL); + i++; + ZipWriteInt(passBuf, passBuf + 264, passBuf + i, ZIP_PASSWORD_END_SIG); + Tcl_SetByteArrayLength(passObj, i + 4); + Tcl_SetObjResult(interp, passObj); return TCL_OK; } /* *------------------------------------------------------------------------- * + * RandomChar -- + * + * Worker for ZipAddFile(). Picks a random character (range: 0..255) + * using Tcl's standard PRNG. + * + * Returns: + * Tcl result code. Updates chPtr with random character on success. + * + * Side effects: + * Advances the PRNG state. May reenter the Tcl interpreter if the user + * has replaced the PRNG. + * + *------------------------------------------------------------------------- + */ + +static int +RandomChar( + Tcl_Interp *interp, + int step, + int *chPtr) +{ + double r; + Tcl_Obj *ret; + + if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", -1, 0) != TCL_OK) { + goto failed; + } + ret = Tcl_GetObjResult(interp); + if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) { + goto failed; + } + *chPtr = (int) (r * 256); + return TCL_OK; + + failed: + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (evaluating PRNG step %d for password encoding)", + step)); + return TCL_ERROR; +} + +/* + *------------------------------------------------------------------------- + * * ZipAddFile -- * - * This procedure is used by ZipFSMkZipOrImgCmd() to add a single file to + * This procedure is used by ZipFSMkZipOrImg() to add a single file to * the output ZIP archive file being written. A ZipEntry struct about the * input file is added to the given fileHash table for later creation of * the central ZIP directory. * + * Tcl *always* encodes filenames in the ZIP as UTF-8. Similarly, it + * would always encode comments as UTF-8, if it supported comments. + * * Results: * A standard Tcl result. * @@ -2026,23 +2493,30 @@ ZipFSMkKeyObjCmd( static int ZipAddFile( Tcl_Interp *interp, /* Current interpreter. */ - const char *path, - const char *name, - Tcl_Channel out, + Tcl_Obj *pathObj, /* Actual name of the file to add. */ + const char *name, /* Name to use in the ZIP archive, in Tcl's + * internal encoding. */ + Tcl_Channel out, /* The open ZIP archive being built. */ const char *passwd, /* Password for encoding the file, or NULL if * the file is to be unprotected. */ - char *buf, - int bufsize, - Tcl_HashTable *fileHash) + char *buf, /* Working buffer. */ + int bufsize, /* Size of buf */ + Tcl_HashTable *fileHash) /* Where to record ZIP entry metdata so we can + * built the central directory. */ { + const unsigned char *start = (unsigned char *) buf; + const unsigned char *end = (unsigned char *) buf + bufsize; Tcl_Channel in; Tcl_HashEntry *hPtr; ZipEntry *z; z_stream stream; - const char *zpath; + Tcl_DString zpathDs; /* Buffer for the encoded filename. */ + const char *zpathExt; /* Filename in external encoding (true + * UTF-8). */ + const char *zpathTcl; /* Filename in Tcl's internal encoding. */ int crc, flush, zpathlen; size_t nbyte, nbytecompr, len, olen, align = 0; - long long pos[3]; + long long headerStartOffset, dataStartOffset, dataEndOffset; int mtime = 0, isNew, compMeth; unsigned long keys[3], keys0[3]; char obuf[4096]; @@ -2052,23 +2526,31 @@ ZipAddFile( * nothing to do. */ - zpath = name; - while (zpath && zpath[0] == '/') { - zpath++; + zpathTcl = name; + while (zpathTcl && zpathTcl[0] == '/') { + zpathTcl++; } - if (!zpath || (zpath[0] == '\0')) { + if (!zpathTcl || (zpathTcl[0] == '\0')) { return TCL_OK; } - zpathlen = strlen(zpath); + /* + * Convert to encoded form. Note that we use strlen() here; if someone's + * crazy enough to embed NULs in filenames, they deserve what they get! + */ + + zpathExt = Tcl_UtfToExternalDString(ZipFS.utf8, zpathTcl, -1, &zpathDs); + zpathlen = strlen(zpathExt); if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "path too long for \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "PATH_LEN", NULL); + "path too long for \"%s\"", Tcl_GetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "PATH_LEN"); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - in = Tcl_OpenFileChannel(interp, path, "rb", 0); + in = Tcl_FSOpenFileChannel(interp, pathObj, "rb", 0); if (!in) { + Tcl_DStringFree(&zpathDs); #ifdef _WIN32 /* hopefully a directory */ if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) { @@ -2079,27 +2561,31 @@ ZipAddFile( Tcl_Close(interp, in); return TCL_ERROR; } else { - Tcl_Obj *pathObj = Tcl_NewStringObj(path, -1); Tcl_StatBuf statBuf; - Tcl_IncrRefCount(pathObj); if (Tcl_FSStat(pathObj, &statBuf) != -1) { mtime = statBuf.st_mtime; } - Tcl_DecrRefCount(pathObj); } Tcl_ResetResult(interp); + + /* + * Compute the CRC. + */ + crc = 0; nbyte = nbytecompr = 0; while (1) { len = Tcl_Read(in, buf, bufsize); if (len == ERROR_LENGTH) { + Tcl_DStringFree(&zpathDs); if (nbyte == 0 && errno == EISDIR) { Tcl_Close(interp, in); return TCL_OK; } + readErrorWithChannelOpen: Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s", - path, Tcl_PosixError(interp))); + Tcl_GetString(pathObj), Tcl_PosixError(interp))); Tcl_Close(interp, in); return TCL_ERROR; } @@ -2111,66 +2597,70 @@ ZipAddFile( } if (Tcl_Seek(in, 0, SEEK_SET) == -1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("seek error on \"%s\": %s", - path, Tcl_PosixError(interp))); + Tcl_GetString(pathObj), Tcl_PosixError(interp))); Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - pos[0] = Tcl_Tell(out); + + /* + * Remember where we've got to so far so we can write the header (after + * writing the file). + */ + + headerStartOffset = Tcl_Tell(out); + + /* + * Reserve space for the per-file header. Includes writing the file name + * as we already know that. + */ + memset(buf, '\0', ZIP_LOCAL_HEADER_LEN); - memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen); + memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpathExt, zpathlen); len = zpathlen + ZIP_LOCAL_HEADER_LEN; if ((size_t) Tcl_Write(out, buf, len) != len) { - wrerr: + writeErrorWithChannelOpen: Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error on %s: %s", path, Tcl_PosixError(interp))); + "write error on \"%s\": %s", + Tcl_GetString(pathObj), Tcl_PosixError(interp))); Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } - if ((len + pos[0]) & 3) { - unsigned char abuf[8]; - /* - * Align payload to next 4-byte boundary using a dummy extra entry - * similar to the zipalign tool from Android's SDK. - */ + /* + * Align payload to next 4-byte boundary (if necessary) using a dummy + * extra entry similar to the zipalign tool from Android's SDK. + */ - align = 4 + ((len + pos[0]) & 3); - ZipWriteShort(abuf, 0xffff); - ZipWriteShort(abuf + 2, align - 4); - ZipWriteInt(abuf + 4, 0x03020100); + if ((len + headerStartOffset) & 3) { + unsigned char abuf[8]; + const unsigned char *astart = abuf; + const unsigned char *aend = abuf + 8; + + align = 4 + ((len + headerStartOffset) & 3); + ZipWriteShort(astart, aend, abuf, 0xffff); + ZipWriteShort(astart, aend, abuf + 2, align - 4); + ZipWriteInt(astart, aend, abuf + 4, 0x03020100); if ((size_t) Tcl_Write(out, (const char *) abuf, align) != align) { - goto wrerr; + goto writeErrorWithChannelOpen; } } + + /* + * Set up encryption if we were asked to. + */ + if (passwd) { int i, ch, tmp; unsigned char kvbuf[24]; - Tcl_Obj *ret; init_keys(passwd, keys, crc32tab); for (i = 0; i < 12 - 2; i++) { - double r; - - if (Tcl_EvalEx(interp, "::tcl::mathfunc::rand", -1, 0) != TCL_OK) { - Tcl_Obj *eiPtr = Tcl_ObjPrintf( - "\n (evaluating PRNG step %d for password encoding)", - i); - - Tcl_AppendObjToErrorInfo(interp, eiPtr); - Tcl_Close(interp, in); - return TCL_ERROR; - } - ret = Tcl_GetObjResult(interp); - if (Tcl_GetDoubleFromObj(interp, ret, &r) != TCL_OK) { - Tcl_Obj *eiPtr = Tcl_ObjPrintf( - "\n (evaluating PRNG step %d for password encoding)", - i); - - Tcl_AppendObjToErrorInfo(interp, eiPtr); + if (RandomChar(interp, i, &ch) != TCL_OK) { Tcl_Close(interp, in); return TCL_ERROR; } - ch = (int) (r * 256); kvbuf[i + 12] = UCHAR(zencode(keys, crc32tab, ch, tmp)); } Tcl_ResetResult(interp); @@ -2183,16 +2673,23 @@ ZipAddFile( len = Tcl_Write(out, (char *) kvbuf, 12); memset(kvbuf, 0, 24); if (len != 12) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error on %s: %s", path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); - return TCL_ERROR; + goto writeErrorWithChannelOpen; } memcpy(keys0, keys, sizeof(keys0)); nbytecompr += 12; } + + /* + * Save where we've got to in case we need to just store this file. + */ + Tcl_Flush(out); - pos[2] = Tcl_Tell(out); + dataStartOffset = Tcl_Tell(out); + + /* + * Compress the stream. + */ + compMeth = ZIP_COMPMETH_DEFLATED; memset(&stream, 0, sizeof(z_stream)); stream.zalloc = Z_NULL; @@ -2201,19 +2698,18 @@ ZipAddFile( if (deflateInit2(&stream, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "compression init error on \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE_INIT", NULL); + "compression init error on \"%s\"", Tcl_GetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DEFLATE_INIT"); Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } + do { len = Tcl_Read(in, buf, bufsize); if (len == ERROR_LENGTH) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "read error on %s: %s", path, Tcl_PosixError(interp))); deflateEnd(&stream); - Tcl_Close(interp, in); - return TCL_ERROR; + goto readErrorWithChannelOpen; } stream.avail_in = len; stream.next_in = (unsigned char *) buf; @@ -2224,10 +2720,11 @@ ZipAddFile( len = deflate(&stream, flush); if (len == (size_t) Z_STREAM_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "deflate error on %s", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE", NULL); + "deflate error on \"%s\"", Tcl_GetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DEFLATE"); deflateEnd(&stream); Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } olen = sizeof(obuf) - stream.avail_out; @@ -2240,41 +2737,42 @@ ZipAddFile( } } if (olen && ((size_t) Tcl_Write(out, obuf, olen) != olen)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error: %s", Tcl_PosixError(interp))); deflateEnd(&stream); - Tcl_Close(interp, in); - return TCL_ERROR; + goto writeErrorWithChannelOpen; } nbytecompr += olen; } while (stream.avail_out == 0); } while (flush != Z_FINISH); deflateEnd(&stream); + + /* + * Work out where we've got to. + */ + Tcl_Flush(out); - pos[1] = Tcl_Tell(out); + dataEndOffset = Tcl_Tell(out); + if (nbyte - nbytecompr <= 0) { /* * Compressed file larger than input, write it again uncompressed. */ + if (Tcl_Seek(in, 0, SEEK_SET) != 0) { goto seekErr; } - if (Tcl_Seek(out, pos[2], SEEK_SET) != pos[2]) { + if (Tcl_Seek(out, dataStartOffset, SEEK_SET) != dataStartOffset) { seekErr: - Tcl_Close(interp, in); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "seek error: %s", Tcl_PosixError(interp))); + Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); return TCL_ERROR; } nbytecompr = (passwd ? 12 : 0); while (1) { len = Tcl_Read(in, buf, bufsize); if (len == ERROR_LENGTH) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "read error on \"%s\": %s", - path, Tcl_PosixError(interp))); - Tcl_Close(interp, in); - return TCL_ERROR; + goto readErrorWithChannelOpen; } else if (len == 0) { break; } @@ -2287,61 +2785,57 @@ ZipAddFile( } } if ((size_t) Tcl_Write(out, buf, len) != len) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "write error: %s", Tcl_PosixError(interp))); - Tcl_Close(interp, in); - return TCL_ERROR; + goto writeErrorWithChannelOpen; } nbytecompr += len; } compMeth = ZIP_COMPMETH_STORED; + + /* + * Chop off everything after this; it's the over-large compressed data + * and we don't know if it is going to get overwritten otherwise. + */ + Tcl_Flush(out); - pos[1] = Tcl_Tell(out); - Tcl_TruncateChannel(out, pos[1]); + dataEndOffset = Tcl_Tell(out); + Tcl_TruncateChannel(out, dataEndOffset); } Tcl_Close(interp, in); + Tcl_DStringFree(&zpathDs); + zpathExt = NULL; - hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew); + hPtr = Tcl_CreateHashEntry(fileHash, zpathTcl, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "non-unique path name \"%s\"", path)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DUPLICATE_PATH", NULL); + "non-unique path name \"%s\"", Tcl_GetString(pathObj))); + ZIPFS_ERROR_CODE(interp, "DUPLICATE_PATH"); return TCL_ERROR; } - z = (ZipEntry *)ckalloc(sizeof(ZipEntry)); + /* + * Remember that we've written the file (for central directory generation) + * and generate the local (per-file) header in the space that we reserved + * earlier. + */ + + z = AllocateZipEntry(); Tcl_SetHashValue(hPtr, z); - z->name = NULL; - z->tnext = NULL; - z->depth = 0; - z->zipFilePtr = NULL; - z->isDirectory = 0; z->isEncrypted = (passwd ? 1 : 0); - z->offset = pos[0]; + z->offset = headerStartOffset; z->crc32 = crc; z->timestamp = mtime; z->numBytes = nbyte; z->numCompressedBytes = nbytecompr; z->compressMethod = compMeth; - z->data = NULL; - z->name = (char *)Tcl_GetHashKey(fileHash, hPtr); - z->next = NULL; + z->name = (char *) Tcl_GetHashKey(fileHash, hPtr); /* * Write final local header information. */ - ZipWriteInt(buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG); - ZipWriteShort(buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION); - ZipWriteShort(buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted); - ZipWriteShort(buf + ZIP_LOCAL_COMPMETH_OFFS, z->compressMethod); - ZipWriteShort(buf + ZIP_LOCAL_MTIME_OFFS, ToDosTime(z->timestamp)); - ZipWriteShort(buf + ZIP_LOCAL_MDATE_OFFS, ToDosDate(z->timestamp)); - ZipWriteInt(buf + ZIP_LOCAL_CRC32_OFFS, z->crc32); - ZipWriteInt(buf + ZIP_LOCAL_COMPLEN_OFFS, z->numCompressedBytes); - ZipWriteInt(buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->numBytes); - ZipWriteShort(buf + ZIP_LOCAL_PATHLEN_OFFS, zpathlen); - ZipWriteShort(buf + ZIP_LOCAL_EXTRALEN_OFFS, align); - if (Tcl_Seek(out, pos[0], SEEK_SET) != pos[0]) { + + SerializeLocalEntryHeader(start, end, (unsigned char *) buf, z, + zpathlen, align); + if (Tcl_Seek(out, headerStartOffset, SEEK_SET) != headerStartOffset) { Tcl_DeleteHashEntry(hPtr); ckfree(z); Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2356,7 +2850,7 @@ ZipAddFile( return TCL_ERROR; } Tcl_Flush(out); - if (Tcl_Seek(out, pos[1], SEEK_SET) != pos[1]) { + if (Tcl_Seek(out, dataEndOffset, SEEK_SET) != dataEndOffset) { Tcl_DeleteHashEntry(hPtr); ckfree(z); Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2369,12 +2863,101 @@ ZipAddFile( /* *------------------------------------------------------------------------- * - * ZipFSMkZipOrImgObjCmd -- + * ZipFSFind -- + * + * Worker for ZipFSMkZipOrImg() that discovers the list of files to add. + * Simple wrapper around [zipfs find]. + * + *------------------------------------------------------------------------- + */ + +static Tcl_Obj * +ZipFSFind( + Tcl_Interp *interp, + Tcl_Obj *dirRoot) +{ + Tcl_Obj *cmd[2]; + int result; + + cmd[0] = Tcl_NewStringObj("::tcl::zipfs::find", -1); + cmd[1] = dirRoot; + Tcl_IncrRefCount(cmd[0]); + result = Tcl_EvalObjv(interp, 2, cmd, 0); + Tcl_DecrRefCount(cmd[0]); + if (result != TCL_OK) { + return NULL; + } + return Tcl_GetObjResult(interp); +} + +/* + *------------------------------------------------------------------------- + * + * ComputeNameInArchive -- + * + * Helper for ZipFSMkZipOrImg() that computes what the actual name of a + * file in the ZIP archive should be, stripping a prefix (if appropriate) + * and any leading slashes. If the result is an empty string, the entry + * should be skipped. + * + * Returns: + * Pointer to the name (in Tcl's internal encoding), which will be in + * memory owned by one of the argument objects. + * + * Side effects: + * None (if Tcl_Objs have string representations) + * + *------------------------------------------------------------------------- + */ + +static inline const char * +ComputeNameInArchive( + Tcl_Obj *pathObj, /* The path to the origin file */ + Tcl_Obj *directNameObj, /* User-specified name for use in the ZIP + * archive */ + const char *strip, /* A prefix to strip; may be NULL if no + * stripping need be done. */ + int slen) /* The length of the prefix; must be 0 if no + * stripping need be done. */ +{ + const char *name; + int len; + + if (directNameObj) { + name = Tcl_GetString(directNameObj); + } else { + name = Tcl_GetStringFromObj(pathObj, &len); + if (slen > 0) { + if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { + /* + * Guaranteed to be a NUL at the end, which will make this + * entry be skipped. + */ + + return name + len; + } + name += slen; + } + } + while (name[0] == '/') { + ++name; + } + return name; +} + +/* + *------------------------------------------------------------------------- + * + * ZipFSMkZipOrImg -- * * This procedure is creates a new ZIP archive file or image file given * output filename, input directory of files to be archived, optional * password, and optional image to be prepended to the output ZIP archive - * file. + * file. It's the core of the implementation of [zipfs mkzip], [zipfs + * mkimg], [zipfs lmkzip] and [zipfs lmkimg]. + * + * Tcl *always* encodes filenames in the ZIP as UTF-8. Similarly, it + * would always encode comments as UTF-8, if it supported comments. * * Results: * A standard Tcl result. @@ -2386,95 +2969,103 @@ ZipAddFile( */ static int -ZipFSMkZipOrImgObjCmd( +ZipFSMkZipOrImg( Tcl_Interp *interp, /* Current interpreter. */ - int isImg, - int isList, - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ + int isImg, /* Are we making an image? */ + Tcl_Obj *targetFile, /* What file are we making? */ + Tcl_Obj *dirRoot, /* What directory do we take files from? Do + * not specify at the same time as + * mappingList (one must be NULL). */ + Tcl_Obj *mappingList, /* What files are we putting in, and with what + * names? Do not specify at the same time as + * dirRoot (one must be NULL). */ + Tcl_Obj *originFile, /* If we're making an image, what file does + * the non-ZIP part of the image come from? */ + Tcl_Obj *stripPrefix, /* Are we going to strip a prefix from + * filenames found beneath dirRoot? If NULL, + * do not strip anything (except for dirRoot + * itself). */ + Tcl_Obj *passwordObj) /* The password for encoding things. NULL if + * there's no password protection. */ { Tcl_Channel out; - int pwlen = 0, count, ret = TCL_ERROR, lobjc; - size_t len, slen = 0, i = 0; - long long pos[3]; - Tcl_Obj **lobjv, *list = NULL; + int pwlen = 0, slen = 0, count, ret = TCL_ERROR, lobjc; + size_t len, i = 0; + long long dataStartOffset; /* The overall file offset of the start of the + * data section of the file. */ + long long directoryStartOffset; + /* The overall file offset of the start of the + * central directory. */ + long long suffixStartOffset;/* The overall file offset of the start of the + * suffix of the central directory (i.e., + * where this data will be written). */ + Tcl_Obj **lobjv, *list = mappingList; ZipEntry *z; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable fileHash; char *strip = NULL, *pw = NULL, passBuf[264], buf[4096]; + unsigned char *start = (unsigned char *) buf; + unsigned char *end = start + sizeof(buf); /* * Caller has verified that the number of arguments is correct. */ passBuf[0] = 0; - if (objc > (isList ? 3 : 4)) { - pw = Tcl_GetString(objv[isList ? 3 : 4]); - pwlen = strlen(pw); - if ((pwlen > 255) || strchr(pw, 0xff)) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("illegal password", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL); + if (passwordObj != NULL) { + pw = Tcl_GetStringFromObj(passwordObj, &pwlen); + if (IsPasswordValid(interp, pw, pwlen) != TCL_OK) { return TCL_ERROR; } + if (pwlen <= 0) { + pw = NULL; + pwlen = 0; + } } - if (isList) { - list = objv[2]; - Tcl_IncrRefCount(list); - } else { - Tcl_Obj *cmd[3]; - - cmd[1] = Tcl_NewStringObj("::tcl::zipfs::find", -1); - cmd[2] = objv[2]; - cmd[0] = Tcl_NewListObj(2, cmd + 1); - Tcl_IncrRefCount(cmd[0]); - if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) { - Tcl_DecrRefCount(cmd[0]); + if (dirRoot != NULL) { + list = ZipFSFind(interp, dirRoot); + if (!list) { return TCL_ERROR; } - Tcl_DecrRefCount(cmd[0]); - list = Tcl_GetObjResult(interp); - Tcl_IncrRefCount(list); } + Tcl_IncrRefCount(list); if (Tcl_ListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) { Tcl_DecrRefCount(list); return TCL_ERROR; } - if (isList && (lobjc % 2)) { + if (mappingList && (lobjc % 2)) { Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, - Tcl_NewStringObj("need even number of elements", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "LIST_LENGTH", NULL); + ZIPFS_ERROR(interp, "need even number of elements"); + ZIPFS_ERROR_CODE(interp, "LIST_LENGTH"); return TCL_ERROR; } if (lobjc == 0) { Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL); + ZIPFS_ERROR(interp, "empty archive"); + ZIPFS_ERROR_CODE(interp, "EMPTY"); return TCL_ERROR; } - out = Tcl_OpenFileChannel(interp, Tcl_GetString(objv[1]), "wb", 0755); + out = Tcl_FSOpenFileChannel(interp, targetFile, "wb", 0755); if (out == NULL) { Tcl_DecrRefCount(list); return TCL_ERROR; } - if (pwlen <= 0) { - pw = NULL; - pwlen = 0; - } + + /* + * Copy the existing contents from the image if it is an executable image. + * Care must be taken because this might include an existing ZIP, which + * needs to be stripped. + */ + if (isImg) { ZipFile *zf, zf0; int isMounted = 0; const char *imgName; - if (isList) { - imgName = (objc > 4) ? Tcl_GetString(objv[4]) : - Tcl_GetNameOfExecutable(); - } else { - imgName = (objc > 5) ? Tcl_GetString(objv[5]) : - Tcl_GetNameOfExecutable(); - } + // TODO: normalize the origin file name + imgName = (originFile != NULL) ? Tcl_GetString(originFile) : + Tcl_GetNameOfExecutable(); if (pwlen) { i = 0; for (len = pwlen; len-- > 0;) { @@ -2499,7 +3090,7 @@ ZipFSMkZipOrImgObjCmd( WriteLock(); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - zf = (ZipFile *)Tcl_GetHashValue(hPtr); + zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (strcmp(zf->name, imgName) == 0) { isMounted = 1; zf->numOpen++; @@ -2507,10 +3098,16 @@ ZipFSMkZipOrImgObjCmd( } } Unlock(); + if (!isMounted) { zf = &zf0; + memset(&zf0, 0, sizeof(ZipFile)); } if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) { + /* + * Copy everything up to the ZIP-related suffix. + */ + if ((size_t) Tcl_Write(out, (char *) zf->data, zf->passOffset) != zf->passOffset) { memset(passBuf, 0, sizeof(passBuf)); @@ -2535,56 +3132,23 @@ ZipFSMkZipOrImgObjCmd( Unlock(); } } else { - size_t k; - int m, n; - Tcl_Channel in; - const char *errMsg = "seek error"; - /* * Fall back to read it as plain file which hopefully is a static * tclsh or wish binary with proper zipfs infrastructure built in. */ - Tcl_ResetResult(interp); - in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644); - if (!in) { + if (CopyImageFile(interp, imgName, out) != TCL_OK) { memset(passBuf, 0, sizeof(passBuf)); Tcl_DecrRefCount(list); Tcl_Close(interp, out); return TCL_ERROR; } - i = Tcl_Seek(in, 0, SEEK_END); - if (i == ERROR_LENGTH) { - cperr: - memset(passBuf, 0, sizeof(passBuf)); - Tcl_DecrRefCount(list); - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "%s: %s", errMsg, Tcl_PosixError(interp))); - Tcl_Close(interp, out); - Tcl_Close(interp, in); - return TCL_ERROR; - } - Tcl_Seek(in, 0, SEEK_SET); - for (k = 0; k < i; k += m) { - m = i - k; - if (m > (int) sizeof(buf)) { - m = (int) sizeof(buf); - } - n = Tcl_Read(in, buf, m); - if (n == -1) { - errMsg = "read error"; - goto cperr; - } else if (n == 0) { - break; - } - m = Tcl_Write(out, buf, n); - if (m != n) { - errMsg = "write error"; - goto cperr; - } - } - Tcl_Close(interp, in); } + + /* + * Store the password so that the automounter can find it. + */ + len = strlen(passBuf); if (len > 0) { i = Tcl_Write(out, passBuf, len); @@ -2599,105 +3163,74 @@ ZipFSMkZipOrImgObjCmd( memset(passBuf, 0, sizeof(passBuf)); Tcl_Flush(out); } + + /* + * Prepare the contents of the ZIP archive. + */ + Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS); - pos[0] = Tcl_Tell(out); - if (!isList && (objc > 3)) { - strip = Tcl_GetString(objv[3]); - slen = strlen(strip); + dataStartOffset = Tcl_Tell(out); + if (mappingList == NULL && stripPrefix != NULL) { + strip = Tcl_GetStringFromObj(stripPrefix, &slen); + if (!slen) { + strip = NULL; + } } - for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) { - const char *path, *name; + for (i = 0; i < (size_t) lobjc; i += (mappingList ? 2 : 1)) { + Tcl_Obj *pathObj = lobjv[i]; + const char *name = ComputeNameInArchive(pathObj, + (mappingList ? lobjv[i + 1] : NULL), strip, slen); - path = Tcl_GetString(lobjv[i]); - if (isList) { - name = Tcl_GetString(lobjv[i + 1]); - } else { - name = path; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { - continue; - } - name += slen; - } - } - while (name[0] == '/') { - ++name; - } if (name[0] == '\0') { continue; } - if (ZipAddFile(interp, path, name, out, pw, buf, sizeof(buf), + if (ZipAddFile(interp, pathObj, name, out, pw, buf, sizeof(buf), &fileHash) != TCL_OK) { goto done; } } - pos[1] = Tcl_Tell(out); + + /* + * Construct the contents of the ZIP central directory. + */ + + directoryStartOffset = Tcl_Tell(out); count = 0; - for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) { - const char *path, *name; + for (i = 0; i < (size_t) lobjc; i += (mappingList ? 2 : 1)) { + const char *name = ComputeNameInArchive(lobjv[i], + (mappingList ? lobjv[i + 1] : NULL), strip, slen); + Tcl_DString ds; - path = Tcl_GetString(lobjv[i]); - if (isList) { - name = Tcl_GetString(lobjv[i + 1]); - } else { - name = path; - if (slen > 0) { - len = strlen(name); - if ((len <= slen) || (strncmp(strip, name, slen) != 0)) { - continue; - } - name += slen; - } - } - while (name[0] == '/') { - ++name; - } - if (name[0] == '\0') { - continue; - } hPtr = Tcl_FindHashEntry(&fileHash, name); if (!hPtr) { continue; } - z = (ZipEntry *)Tcl_GetHashValue(hPtr); - len = strlen(z->name); - ZipWriteInt(buf + ZIP_CENTRAL_SIG_OFFS, ZIP_CENTRAL_HEADER_SIG); - ZipWriteShort(buf + ZIP_CENTRAL_VERSIONMADE_OFFS, ZIP_MIN_VERSION); - ZipWriteShort(buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION); - ZipWriteShort(buf + ZIP_CENTRAL_FLAGS_OFFS, z->isEncrypted); - ZipWriteShort(buf + ZIP_CENTRAL_COMPMETH_OFFS, z->compressMethod); - ZipWriteShort(buf + ZIP_CENTRAL_MTIME_OFFS, ToDosTime(z->timestamp)); - ZipWriteShort(buf + ZIP_CENTRAL_MDATE_OFFS, ToDosDate(z->timestamp)); - ZipWriteInt(buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32); - ZipWriteInt(buf + ZIP_CENTRAL_COMPLEN_OFFS, z->numCompressedBytes); - ZipWriteInt(buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->numBytes); - ZipWriteShort(buf + ZIP_CENTRAL_PATHLEN_OFFS, len); - ZipWriteShort(buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0); - ZipWriteShort(buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0); - ZipWriteShort(buf + ZIP_CENTRAL_DISKFILE_OFFS, 0); - ZipWriteShort(buf + ZIP_CENTRAL_IATTR_OFFS, 0); - ZipWriteInt(buf + ZIP_CENTRAL_EATTR_OFFS, 0); - ZipWriteInt(buf + ZIP_CENTRAL_LOCALHDR_OFFS, z->offset - pos[0]); - if ((Tcl_Write(out, buf, - ZIP_CENTRAL_HEADER_LEN) != ZIP_CENTRAL_HEADER_LEN) - || ((size_t) Tcl_Write(out, z->name, len) != len)) { + z = (ZipEntry *) Tcl_GetHashValue(hPtr); + + name = Tcl_UtfToExternalDString(ZipFS.utf8, z->name, -1, &ds); + len = Tcl_DStringLength(&ds); + SerializeCentralDirectoryEntry(start, end, (unsigned char *) buf, + z, len, dataStartOffset); + if ((Tcl_Write(out, buf, ZIP_CENTRAL_HEADER_LEN) + != ZIP_CENTRAL_HEADER_LEN) + || ((size_t) Tcl_Write(out, name, len) != len)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); + Tcl_DStringFree(&ds); goto done; } + Tcl_DStringFree(&ds); count++; } + + /* + * Finalize the central directory. + */ + Tcl_Flush(out); - pos[2] = Tcl_Tell(out); - ZipWriteInt(buf + ZIP_CENTRAL_END_SIG_OFFS, ZIP_CENTRAL_END_SIG); - ZipWriteShort(buf + ZIP_CENTRAL_DISKNO_OFFS, 0); - ZipWriteShort(buf + ZIP_CENTRAL_DISKDIR_OFFS, 0); - ZipWriteShort(buf + ZIP_CENTRAL_ENTS_OFFS, count); - ZipWriteShort(buf + ZIP_CENTRAL_TOTALENTS_OFFS, count); - ZipWriteInt(buf + ZIP_CENTRAL_DIRSIZE_OFFS, pos[2] - pos[1]); - ZipWriteInt(buf + ZIP_CENTRAL_DIRSTART_OFFS, pos[1] - pos[0]); - ZipWriteShort(buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0); + suffixStartOffset = Tcl_Tell(out); + SerializeCentralDirectorySuffix(start, end, (unsigned char *) buf, + count, dataStartOffset, directoryStartOffset, suffixStartOffset); if (Tcl_Write(out, buf, ZIP_CENTRAL_END_LEN) != ZIP_CENTRAL_END_LEN) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "write error: %s", Tcl_PosixError(interp))); @@ -2715,7 +3248,7 @@ ZipFSMkZipOrImgObjCmd( Tcl_DecrRefCount(list); for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - z = (ZipEntry *)Tcl_GetHashValue(hPtr); + z = (ZipEntry *) Tcl_GetHashValue(hPtr); ckfree(z); Tcl_DeleteHashEntry(hPtr); } @@ -2724,18 +3257,207 @@ ZipFSMkZipOrImgObjCmd( } /* + * --------------------------------------------------------------------- + * + * CopyImageFile -- + * + * A simple file copy function that is used (by ZipFSMkZipOrImg) for + * anything that is not an image with a ZIP appended. + * + * Returns: + * A Tcl result code. + * + * Side effects: + * Writes to an output channel. + * + * --------------------------------------------------------------------- + */ + +static int +CopyImageFile( + Tcl_Interp *interp, /* For error reporting. */ + const char *imgName, /* Where to copy from. */ + Tcl_Channel out) /* Where to copy to; already open for writing + * binary data. */ +{ + size_t i, k; + int m, n; + Tcl_Channel in; + char buf[4096]; + const char *errMsg; + + Tcl_ResetResult(interp); + in = Tcl_OpenFileChannel(interp, imgName, "rb", 0644); + if (!in) { + return TCL_ERROR; + } + + /* + * Get the length of the file (and exclude non-files). + */ + + i = Tcl_Seek(in, 0, SEEK_END); + if (i == ERROR_LENGTH) { + errMsg = "seek error"; + goto copyError; + } + Tcl_Seek(in, 0, SEEK_SET); + + /* + * Copy the whole file, 8 blocks at a time (reasonably efficient). Note + * that this totally ignores things like Windows's Alternate File Streams. + */ + + for (k = 0; k < i; k += m) { + m = i - k; + if (m > (int) sizeof(buf)) { + m = (int) sizeof(buf); + } + n = Tcl_Read(in, buf, m); + if (n == -1) { + errMsg = "read error"; + goto copyError; + } else if (n == 0) { + break; + } + m = Tcl_Write(out, buf, n); + if (m != n) { + errMsg = "write error"; + goto copyError; + } + } + Tcl_Close(interp, in); + return TCL_OK; + + copyError: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "%s: %s", errMsg, Tcl_PosixError(interp))); + Tcl_Close(interp, in); + return TCL_ERROR; +} + +/* + * --------------------------------------------------------------------- + * + * SerializeLocalEntryHeader, SerializeCentralDirectoryEntry, + * SerializeCentralDirectorySuffix -- + * + * Create serialized forms of the structures that make up the ZIP + * metadata. Note that the both the local entry and the central directory + * entry need to have the name of the entry written directly afterwards. + * + * We could write these as structs except we need to guarantee that we + * are writing these out as little-endian values. + * + * Side effects: + * Both update their buffer arguments, but otherwise change nothing. + * + * --------------------------------------------------------------------- + */ + +static void +SerializeLocalEntryHeader( + const unsigned char *start, /* The start of writable memory. */ + const unsigned char *end, /* The end of writable memory. */ + unsigned char *buf, /* Where to serialize to */ + ZipEntry *z, /* The description of what to serialize. */ + int nameLength, /* The length of the name. */ + int align) /* The number of alignment bytes. */ +{ + ZipWriteInt(start, end, buf + ZIP_LOCAL_SIG_OFFS, ZIP_LOCAL_HEADER_SIG); + ZipWriteShort(start, end, buf + ZIP_LOCAL_VERSION_OFFS, ZIP_MIN_VERSION); + ZipWriteShort(start, end, buf + ZIP_LOCAL_FLAGS_OFFS, z->isEncrypted); + ZipWriteShort(start, end, buf + ZIP_LOCAL_COMPMETH_OFFS, + z->compressMethod); + ZipWriteShort(start, end, buf + ZIP_LOCAL_MTIME_OFFS, + ToDosTime(z->timestamp)); + ZipWriteShort(start, end, buf + ZIP_LOCAL_MDATE_OFFS, + ToDosDate(z->timestamp)); + ZipWriteInt(start, end, buf + ZIP_LOCAL_CRC32_OFFS, z->crc32); + ZipWriteInt(start, end, buf + ZIP_LOCAL_COMPLEN_OFFS, + z->numCompressedBytes); + ZipWriteInt(start, end, buf + ZIP_LOCAL_UNCOMPLEN_OFFS, z->numBytes); + ZipWriteShort(start, end, buf + ZIP_LOCAL_PATHLEN_OFFS, nameLength); + ZipWriteShort(start, end, buf + ZIP_LOCAL_EXTRALEN_OFFS, align); +} + +static void +SerializeCentralDirectoryEntry( + const unsigned char *start, /* The start of writable memory. */ + const unsigned char *end, /* The end of writable memory. */ + unsigned char *buf, /* Where to serialize to */ + ZipEntry *z, /* The description of what to serialize. */ + size_t nameLength, /* The length of the name. */ + long long dataStartOffset) /* The overall file offset of the start of the + * data section of the file. */ +{ + ZipWriteInt(start, end, buf + ZIP_CENTRAL_SIG_OFFS, + ZIP_CENTRAL_HEADER_SIG); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_VERSIONMADE_OFFS, + ZIP_MIN_VERSION); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_VERSION_OFFS, ZIP_MIN_VERSION); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_FLAGS_OFFS, z->isEncrypted); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_COMPMETH_OFFS, + z->compressMethod); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_MTIME_OFFS, + ToDosTime(z->timestamp)); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_MDATE_OFFS, + ToDosDate(z->timestamp)); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_CRC32_OFFS, z->crc32); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_COMPLEN_OFFS, + z->numCompressedBytes); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_UNCOMPLEN_OFFS, z->numBytes); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_PATHLEN_OFFS, nameLength); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_EXTRALEN_OFFS, 0); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_FCOMMENTLEN_OFFS, 0); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKFILE_OFFS, 0); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_IATTR_OFFS, 0); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_EATTR_OFFS, 0); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_LOCALHDR_OFFS, + z->offset - dataStartOffset); +} + +static void +SerializeCentralDirectorySuffix( + const unsigned char *start, /* The start of writable memory. */ + const unsigned char *end, /* The end of writable memory. */ + unsigned char *buf, /* Where to serialize to */ + int entryCount, /* The number of entries in the directory */ + long long dataStartOffset, /* The overall file offset of the start of the + * data section of the file. */ + long long directoryStartOffset, + /* The overall file offset of the start of the + * central directory. */ + long long suffixStartOffset)/* The overall file offset of the start of the + * suffix of the central directory (i.e., + * where this data will be written). */ +{ + ZipWriteInt(start, end, buf + ZIP_CENTRAL_END_SIG_OFFS, + ZIP_CENTRAL_END_SIG); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKNO_OFFS, 0); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_DISKDIR_OFFS, 0); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_ENTS_OFFS, entryCount); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_TOTALENTS_OFFS, entryCount); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSIZE_OFFS, + suffixStartOffset - directoryStartOffset); + ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSTART_OFFS, + directoryStartOffset - dataStartOffset); + ZipWriteShort(start, end, buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0); +} + +/* *------------------------------------------------------------------------- * * ZipFSMkZipObjCmd, ZipFSLMkZipObjCmd -- * * These procedures are invoked to process the [zipfs mkzip] and [zipfs - * lmkzip] commands. See description of ZipFSMkZipOrImgCmd(). + * lmkzip] commands. See description of ZipFSMkZipOrImg(). * * Results: * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImg(). * *------------------------------------------------------------------------- */ @@ -2747,17 +3469,22 @@ ZipFSMkZipObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *stripPrefix, *password; + if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 0, 0, objc, objv); + + stripPrefix = (objc > 3 ? objv[3] : NULL); + password = (objc > 4 ? objv[4] : NULL); + return ZipFSMkZipOrImg(interp, 0, objv[1], objv[2], NULL, NULL, + stripPrefix, password); } static int @@ -2767,17 +3494,21 @@ ZipFSLMkZipObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *password; + if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 0, 1, objc, objv); + + password = (objc > 3 ? objv[3] : NULL); + return ZipFSMkZipOrImg(interp, 0, objv[1], NULL, objv[2], NULL, + NULL, password); } /* @@ -2786,13 +3517,13 @@ ZipFSLMkZipObjCmd( * ZipFSMkImgObjCmd, ZipFSLMkImgObjCmd -- * * These procedures are invoked to process the [zipfs mkimg] and [zipfs - * lmkimg] commands. See description of ZipFSMkZipOrImgCmd(). + * lmkimg] commands. See description of ZipFSMkZipOrImg(). * * Results: * A standard Tcl result. * * Side effects: - * See description of ZipFSMkZipOrImgCmd(). + * See description of ZipFSMkZipOrImg(). * *------------------------------------------------------------------------- */ @@ -2804,18 +3535,24 @@ ZipFSMkImgObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *originFile, *stripPrefix, *password; + if (objc < 3 || objc > 6) { Tcl_WrongNumArgs(interp, 1, objv, "outfile indir ?strip? ?password? ?infile?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 1, 0, objc, objv); + + originFile = (objc > 5 ? objv[5] : NULL); + stripPrefix = (objc > 3 ? objv[3] : NULL); + password = (objc > 4 ? objv[4] : NULL); + return ZipFSMkZipOrImg(interp, 1, objv[1], objv[2], NULL, + originFile, stripPrefix, password); } static int @@ -2825,17 +3562,22 @@ ZipFSLMkImgObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { + Tcl_Obj *originFile, *password; + if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "outfile inlist ?password infile?"); return TCL_ERROR; } if (Tcl_IsSafe(interp)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "operation not permitted in a safe interpreter", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "SAFE_INTERP", NULL); + ZIPFS_ERROR(interp, "operation not permitted in a safe interpreter"); + ZIPFS_ERROR_CODE(interp, "SAFE_INTERP"); return TCL_ERROR; } - return ZipFSMkZipOrImgObjCmd(interp, 1, 1, objc, objv); + + originFile = (objc > 4 ? objv[4] : NULL); + password = (objc > 3 ? objv[3] : NULL); + return ZipFSMkZipOrImg(interp, 1, objv[1], NULL, objv[2], + originFile, NULL, password); } /* @@ -2950,7 +3692,7 @@ ZipFSExistsObjCmd( * * ZipFSInfoObjCmd -- * - * This procedure is invoked to process the [zipfs info] command. On + * This procedure is invoked to process the [zipfs info] command. On * success, it returns a Tcl list made up of name of ZIP archive file, * size uncompressed, size compressed, and archive offset of a file in * the ZIP filesystem. @@ -3026,36 +3768,48 @@ ZipFSListObjCmd( Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj *result = Tcl_GetObjResult(interp); + const char *options[] = {"-glob", "-regexp", NULL}; + enum list_options { OPT_GLOB, OPT_REGEXP }; + + /* + * Parse arguments. + */ if (objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?(-glob|-regexp)? ?pattern?"); return TCL_ERROR; } if (objc == 3) { - int n; - char *what = Tcl_GetStringFromObj(objv[1], &n); + int idx; - if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) { + if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", + 0, &idx) != TCL_OK) { + return TCL_ERROR; + } + switch (idx) { + case OPT_GLOB: pattern = Tcl_GetString(objv[2]); - } else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) { + break; + case OPT_REGEXP: regexp = Tcl_RegExpCompile(interp, Tcl_GetString(objv[2])); if (!regexp) { return TCL_ERROR; } - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "unknown option \"%s\"", what)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_OPT", NULL); - return TCL_ERROR; + break; } } else if (objc == 2) { pattern = Tcl_GetString(objv[1]); } + + /* + * Scan for matching entries. + */ + ReadLock(); if (pattern) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_StringMatch(z->name, pattern)) { Tcl_ListObjAppendElement(interp, result, @@ -3065,7 +3819,7 @@ ZipFSListObjCmd( } else if (regexp) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if (Tcl_RegExpExec(interp, regexp, z->name, z->name)) { Tcl_ListObjAppendElement(interp, result, @@ -3075,7 +3829,7 @@ ZipFSListObjCmd( } else { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(z->name, -1)); @@ -3146,7 +3900,7 @@ TclZipfs_TclLibrary(void) #if !defined(STATIC_BUILD) #if defined(_WIN32) || defined(__CYGWIN__) - hModule = TclWinGetTclInstance(); + hModule = (HMODULE)TclWinGetTclInstance(); GetModuleFileNameW(hModule, wName, MAX_PATH); #ifdef __CYGWIN__ cygwin_conv_path(3, wName, dllName, sizeof(dllName)); @@ -3235,7 +3989,7 @@ ZipChannelClose( TCL_UNUSED(Tcl_Interp *), int flags) { - ZipChannel *info = (ZipChannel *)instanceData; + ZipChannel *info = (ZipChannel *) instanceData; if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; @@ -3251,7 +4005,8 @@ ZipChannelClose( } if (info->isWriting) { ZipEntry *z = info->zipEntryPtr; - unsigned char *newdata = (unsigned char *)attemptckrealloc(info->ubuf, info->numRead); + unsigned char *newdata = (unsigned char *) + attemptckrealloc(info->ubuf, info->numRead); if (newdata) { if (z->data) { @@ -3467,7 +4222,7 @@ ZipChannelWideSeek( return info->numRead; } -#ifndef TCL_NO_DEPRECATED +#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) static int ZipChannelSeek( void *instanceData, @@ -3536,7 +4291,7 @@ ZipChannelGetFile( * ZipChannelOpen -- * * This function opens a Tcl_Channel on a file from a mounted ZIP archive - * according to given open mode. + * according to given open mode (already parsed by caller). * * Results: * Tcl_Channel on success, or NULL on error. @@ -3550,24 +4305,19 @@ ZipChannelGetFile( static Tcl_Channel ZipChannelOpen( Tcl_Interp *interp, /* Current interpreter. */ - char *filename, - int mode, - TCL_UNUSED(int) /*permissions*/) + char *filename, /* What are we opening. */ + int wr, /* True if we're opening in write mode. */ + int trunc) /* True if we're opening in truncate mode. */ { ZipEntry *z; ZipChannel *info; - int i, ch, trunc, wr, flags = 0; + int flags = 0; char cname[128]; - if ((mode & O_APPEND) - || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) { - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("unsupported open mode", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_MODE", NULL); - } - return NULL; - } + /* + * Is the file there? + */ + WriteLock(); z = ZipFSLookup(filename); if (!z) { @@ -3579,188 +4329,161 @@ ZipChannelOpen( } goto error; } - trunc = (mode & O_TRUNC) != 0; - wr = (mode & (O_WRONLY | O_RDWR)) != 0; - if ((z->compressMethod != ZIP_COMPMETH_STORED) - && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) { - ZIPFS_ERROR(interp, "unsupported compression method"); + + /* + * Do we support opening the file that way? + */ + + if (wr && z->isDirectory) { + Tcl_SetErrno(EISDIR); if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "COMP_METHOD", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unsupported file type: %s", + Tcl_PosixError(interp))); } goto error; } - if (wr && z->isDirectory) { - ZIPFS_ERROR(interp, "unsupported file type"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_TYPE", NULL); - } + if ((z->compressMethod != ZIP_COMPMETH_STORED) + && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) { + ZIPFS_ERROR(interp, "unsupported compression method"); + ZIPFS_ERROR_CODE(interp, "COMP_METHOD"); goto error; } if (!trunc) { flags |= TCL_READABLE; if (z->isEncrypted && (z->zipFilePtr->passBuf[0] == 0)) { ZIPFS_ERROR(interp, "decryption failed"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DECRYPT", NULL); - } + ZIPFS_ERROR_CODE(interp, "DECRYPT"); goto error; } else if (wr && !z->data && (z->numBytes > ZipFS.wrmax)) { ZIPFS_ERROR(interp, "file too large"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL); - } + ZIPFS_ERROR_CODE(interp, "FILE_SIZE"); goto error; } } else { flags = TCL_WRITABLE; } - info = (ZipChannel *)attemptckalloc(sizeof(ZipChannel)); + + info = AllocateZipChannel(interp); if (!info) { - ZIPFS_ERROR(interp, "out of memory"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } goto error; } info->zipFilePtr = z->zipFilePtr; info->zipEntryPtr = z; - info->numRead = 0; if (wr) { + /* + * Set up a writable channel. + */ + flags |= TCL_WRITABLE; - info->isWriting = 1; - info->isDirectory = 0; - info->maxWrite = ZipFS.wrmax; - info->iscompr = 0; - info->isEncrypted = 0; - info->ubuf = (unsigned char *)attemptckalloc(info->maxWrite); - if (!info->ubuf) { - merror0: - if (info->ubuf) { - ckfree(info->ubuf); - } + if (InitWritableChannel(interp, info, z, trunc) == TCL_ERROR) { ckfree(info); - ZIPFS_ERROR(interp, "out of memory"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } goto error; } - memset(info->ubuf, 0, info->maxWrite); - if (trunc) { - info->numBytes = 0; - } else if (z->data) { - unsigned int j = z->numBytes; - - if (j > info->maxWrite) { - j = info->maxWrite; - } - memcpy(info->ubuf, z->data, j); - info->numBytes = j; - } else { - unsigned char *zbuf = z->zipFilePtr->data + z->offset; - - if (z->isEncrypted) { - int len = z->zipFilePtr->passBuf[0] & 0xFF; - char passBuf[260]; - - for (i = 0; i < len; i++) { - ch = z->zipFilePtr->passBuf[len - i]; - passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; - } - passBuf[i] = '\0'; - init_keys(passBuf, info->keys, crc32tab); - memset(passBuf, 0, sizeof(passBuf)); - for (i = 0; i < 12; i++) { - ch = info->ubuf[i]; - zdecode(info->keys, crc32tab, ch); - } - zbuf += i; - } - if (z->compressMethod == ZIP_COMPMETH_DEFLATED) { - z_stream stream; - int err; - unsigned char *cbuf = NULL; - - memset(&stream, 0, sizeof(z_stream)); - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - stream.avail_in = z->numCompressedBytes; - if (z->isEncrypted) { - unsigned int j; - - stream.avail_in -= 12; - cbuf = (unsigned char *)attemptckalloc(stream.avail_in); - if (!cbuf) { - goto merror0; - } - for (j = 0; j < stream.avail_in; j++) { - ch = info->ubuf[j]; - cbuf[j] = zdecode(info->keys, crc32tab, ch); - } - stream.next_in = cbuf; - } else { - stream.next_in = zbuf; - } - stream.next_out = info->ubuf; - stream.avail_out = info->maxWrite; - if (inflateInit2(&stream, -15) != Z_OK) { - goto cerror0; - } - err = inflate(&stream, Z_SYNC_FLUSH); - inflateEnd(&stream); - if ((err == Z_STREAM_END) - || ((err == Z_OK) && (stream.avail_in == 0))) { - if (cbuf) { - memset(info->keys, 0, sizeof(info->keys)); - ckfree(cbuf); - } - goto wrapchan; - } - cerror0: - if (cbuf) { - memset(info->keys, 0, sizeof(info->keys)); - ckfree(cbuf); - } - if (info->ubuf) { - ckfree(info->ubuf); - } - ckfree(info); - ZIPFS_ERROR(interp, "decompression error"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "CORRUPT", NULL); - } - goto error; - } else if (z->isEncrypted) { - for (i = 0; i < z->numBytes - 12; i++) { - ch = zbuf[i]; - info->ubuf[i] = zdecode(info->keys, crc32tab, ch); - } - } else { - memcpy(info->ubuf, zbuf, z->numBytes); - } - memset(info->keys, 0, sizeof(info->keys)); - goto wrapchan; - } } else if (z->data) { + /* + * Set up a readable channel for direct data. + */ + flags |= TCL_READABLE; - info->isWriting = 0; - info->iscompr = 0; - info->isDirectory = 0; - info->isEncrypted = 0; info->numBytes = z->numBytes; - info->maxWrite = 0; info->ubuf = z->data; } else { + /* + * Set up a readable channel. + */ + flags |= TCL_READABLE; - info->isWriting = 0; - info->iscompr = (z->compressMethod == ZIP_COMPMETH_DEFLATED); - info->ubuf = z->zipFilePtr->data + z->offset; - info->isDirectory = z->isDirectory; - info->isEncrypted = z->isEncrypted; - info->numBytes = z->numBytes; - info->maxWrite = 0; - if (info->isEncrypted) { + if (InitReadableChannel(interp, info, z) == TCL_ERROR) { + ckfree(info); + goto error; + } + } + + /* + * Wrap the ZipChannel into a Tcl_Channel. + */ + + sprintf(cname, "zipfs_%" TCL_Z_MODIFIER "x_%d", z->offset, + ZipFS.idCount++); + z->zipFilePtr->numOpen++; + Unlock(); + return Tcl_CreateChannel(&ZipChannelType, cname, info, flags); + + error: + Unlock(); + return NULL; +} + +/* + *------------------------------------------------------------------------- + * + * InitWritableChannel -- + * + * Assistant for ZipChannelOpen() that sets up a writable channel. It's + * up to the caller to actually register the channel. + * + * Returns: + * Tcl result code. + * + * Side effects: + * Allocates memory for the implementation of the channel. Writes to the + * interpreter's result on error. + * + *------------------------------------------------------------------------- + */ + +static int +InitWritableChannel( + Tcl_Interp *interp, /* Current interpreter, or NULL (when errors + * will be silent). */ + ZipChannel *info, /* The channel to set up. */ + ZipEntry *z, /* The zipped file that the channel will write + * to. */ + int trunc) /* Whether to truncate the data. */ +{ + int i, ch; + unsigned char *cbuf = NULL; + + /* + * Set up a writable channel. + */ + + info->isWriting = 1; + info->maxWrite = ZipFS.wrmax; + + info->ubuf = (unsigned char *) attemptckalloc(info->maxWrite); + if (!info->ubuf) { + goto memoryError; + } + memset(info->ubuf, 0, info->maxWrite); + + if (trunc) { + /* + * Truncate; nothing there. + */ + + info->numBytes = 0; + } else if (z->data) { + /* + * Already got uncompressed data. + */ + + unsigned int j = z->numBytes; + + if (j > info->maxWrite) { + j = info->maxWrite; + } + memcpy(info->ubuf, z->data, j); + info->numBytes = j; + } else { + /* + * Need to uncompress the existing data. + */ + + unsigned char *zbuf = z->zipFilePtr->data + z->offset; + + if (z->isEncrypted) { int len = z->zipFilePtr->passBuf[0] & 0xFF; char passBuf[260]; @@ -3775,118 +4498,244 @@ ZipChannelOpen( ch = info->ubuf[i]; zdecode(info->keys, crc32tab, ch); } - info->ubuf += i; + zbuf += i; } - if (info->iscompr) { + + if (z->compressMethod == ZIP_COMPMETH_DEFLATED) { z_stream stream; int err; - unsigned char *ubuf = NULL; - unsigned int j; memset(&stream, 0, sizeof(z_stream)); stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; stream.avail_in = z->numCompressedBytes; - if (info->isEncrypted) { + if (z->isEncrypted) { + unsigned int j; + stream.avail_in -= 12; - ubuf = (unsigned char *)attemptckalloc(stream.avail_in); - if (!ubuf) { - info->ubuf = NULL; - goto merror; + cbuf = (unsigned char *) attemptckalloc(stream.avail_in); + if (!cbuf) { + goto memoryError; } for (j = 0; j < stream.avail_in; j++) { ch = info->ubuf[j]; - ubuf[j] = zdecode(info->keys, crc32tab, ch); + cbuf[j] = zdecode(info->keys, crc32tab, ch); } - stream.next_in = ubuf; + stream.next_in = cbuf; } else { - stream.next_in = info->ubuf; - } - stream.next_out = info->ubuf = (unsigned char *)attemptckalloc(info->numBytes); - if (!info->ubuf) { - merror: - if (ubuf) { - info->isEncrypted = 0; - memset(info->keys, 0, sizeof(info->keys)); - ckfree(ubuf); - } - ckfree(info); - if (interp) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("out of memory", -1)); - Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL); - } - goto error; + stream.next_in = zbuf; } - stream.avail_out = info->numBytes; + stream.next_out = info->ubuf; + stream.avail_out = info->maxWrite; if (inflateInit2(&stream, -15) != Z_OK) { - goto cerror; + goto corruptionError; } err = inflate(&stream, Z_SYNC_FLUSH); inflateEnd(&stream); if ((err == Z_STREAM_END) || ((err == Z_OK) && (stream.avail_in == 0))) { - if (ubuf) { - info->isEncrypted = 0; + if (cbuf) { memset(info->keys, 0, sizeof(info->keys)); - ckfree(ubuf); + ckfree(cbuf); } - goto wrapchan; - } - cerror: - if (ubuf) { - info->isEncrypted = 0; - memset(info->keys, 0, sizeof(info->keys)); - ckfree(ubuf); - } - if (info->ubuf) { - ckfree(info->ubuf); - } - ckfree(info); - ZIPFS_ERROR(interp, "decompression error"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "CORRUPT", NULL); + return TCL_OK; } - goto error; - } else if (info->isEncrypted) { - unsigned char *ubuf = NULL; - unsigned int j, len; + goto corruptionError; + } else if (z->isEncrypted) { + /* + * Need to decrypt some otherwise-simple stored data. + */ + for (i = 0; i < z->numBytes - 12; i++) { + ch = zbuf[i]; + info->ubuf[i] = zdecode(info->keys, crc32tab, ch); + } + } else { /* - * Decode encrypted but uncompressed file, since we support - * Tcl_Seek() on it, and it can be randomly accessed later. + * Simple stored data. Copy into our working buffer. */ - len = z->numCompressedBytes - 12; - ubuf = (unsigned char *) attemptckalloc(len); - if (ubuf == NULL) { - ckfree((char *) info); - if (interp != NULL) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("out of memory", -1)); - } - goto error; + memcpy(info->ubuf, zbuf, z->numBytes); + } + memset(info->keys, 0, sizeof(info->keys)); + } + return TCL_OK; + + memoryError: + if (info->ubuf) { + ckfree(info->ubuf); + } + ZIPFS_MEM_ERROR(interp); + return TCL_ERROR; + + corruptionError: + if (cbuf) { + memset(info->keys, 0, sizeof(info->keys)); + ckfree(cbuf); + } + if (info->ubuf) { + ckfree(info->ubuf); + } + ZIPFS_ERROR(interp, "decompression error"); + ZIPFS_ERROR_CODE(interp, "CORRUPT"); + return TCL_ERROR; +} + +/* + *------------------------------------------------------------------------- + * + * InitReadableChannel -- + * + * Assistant for ZipChannelOpen() that sets up a readable channel. It's + * up to the caller to actually register the channel. + * + * Returns: + * Tcl result code. + * + * Side effects: + * Allocates memory for the implementation of the channel. Writes to the + * interpreter's result on error. + * + *------------------------------------------------------------------------- + */ + +static int +InitReadableChannel( + Tcl_Interp *interp, /* Current interpreter, or NULL (when errors + * will be silent). */ + ZipChannel *info, /* The channel to set up. */ + ZipEntry *z) /* The zipped file that the channel will read + * from. */ +{ + unsigned char *ubuf = NULL; + int i, ch; + + info->iscompr = (z->compressMethod == ZIP_COMPMETH_DEFLATED); + info->ubuf = z->zipFilePtr->data + z->offset; + info->isDirectory = z->isDirectory; + info->isEncrypted = z->isEncrypted; + info->numBytes = z->numBytes; + + if (info->isEncrypted) { + int len = z->zipFilePtr->passBuf[0] & 0xFF; + char passBuf[260]; + + for (i = 0; i < len; i++) { + ch = z->zipFilePtr->passBuf[len - i]; + passBuf[i] = (ch & 0x0f) | pwrot[(ch >> 4) & 0x0f]; + } + passBuf[i] = '\0'; + init_keys(passBuf, info->keys, crc32tab); + memset(passBuf, 0, sizeof(passBuf)); + for (i = 0; i < 12; i++) { + ch = info->ubuf[i]; + zdecode(info->keys, crc32tab, ch); + } + info->ubuf += i; + } + + if (info->iscompr) { + z_stream stream; + int err; + unsigned int j; + + /* + * Data to decode is compressed, and possibly encrpyted too. + */ + + memset(&stream, 0, sizeof(z_stream)); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.avail_in = z->numCompressedBytes; + if (info->isEncrypted) { + stream.avail_in -= 12; + ubuf = (unsigned char *) attemptckalloc(stream.avail_in); + if (!ubuf) { + info->ubuf = NULL; + goto memoryError; } - for (j = 0; j < len; j++) { + + for (j = 0; j < stream.avail_in; j++) { ch = info->ubuf[j]; ubuf[j] = zdecode(info->keys, crc32tab, ch); } - info->ubuf = ubuf; + stream.next_in = ubuf; + } else { + stream.next_in = info->ubuf; + } + stream.next_out = info->ubuf = (unsigned char *) + attemptckalloc(info->numBytes); + if (!info->ubuf) { + goto memoryError; + } + stream.avail_out = info->numBytes; + if (inflateInit2(&stream, -15) != Z_OK) { + goto corruptionError; + } + err = inflate(&stream, Z_SYNC_FLUSH); + inflateEnd(&stream); + + /* + * Decompression was successful if we're either in the END state, or + * in the OK state with no buffered bytes. + */ + + if ((err != Z_STREAM_END) + && ((err != Z_OK) || (stream.avail_in != 0))) { + goto corruptionError; + } + + if (ubuf) { info->isEncrypted = 0; + memset(info->keys, 0, sizeof(info->keys)); + ckfree(ubuf); } + return TCL_OK; + } else if (info->isEncrypted) { + unsigned int j, len; + + /* + * Decode encrypted but uncompressed file, since we support Tcl_Seek() + * on it, and it can be randomly accessed later. + */ + + len = z->numCompressedBytes - 12; + ubuf = (unsigned char *) attemptckalloc(len); + if (ubuf == NULL) { + goto memoryError; + } + for (j = 0; j < len; j++) { + ch = info->ubuf[j]; + ubuf[j] = zdecode(info->keys, crc32tab, ch); + } + info->ubuf = ubuf; + info->isEncrypted = 0; } + return TCL_OK; - wrapchan: - sprintf(cname, "zipfs_%" TCL_Z_MODIFIER "x_%d", z->offset, - ZipFS.idCount++); - z->zipFilePtr->numOpen++; - Unlock(); - return Tcl_CreateChannel(&ZipChannelType, cname, info, flags); + corruptionError: + if (ubuf) { + info->isEncrypted = 0; + memset(info->keys, 0, sizeof(info->keys)); + ckfree(ubuf); + } + if (info->ubuf) { + ckfree(info->ubuf); + } + ZIPFS_ERROR(interp, "decompression error"); + ZIPFS_ERROR_CODE(interp, "CORRUPT"); + return TCL_ERROR; - error: - Unlock(); - return NULL; + memoryError: + if (ubuf) { + info->isEncrypted = 0; + memset(info->keys, 0, sizeof(info->keys)); + ckfree(ubuf); + } + ZIPFS_MEM_ERROR(interp); + return TCL_ERROR; } /* @@ -3971,9 +4820,14 @@ ZipEntryAccess( * * ZipFSOpenFileChannelProc -- * + * Open a channel to a file in a mounted ZIP archive. Delegates to + * ZipChannelOpen(). + * * Results: + * Tcl_Channel on success, or NULL on error. * * Side effects: + * Allocates memory. * *------------------------------------------------------------------------- */ @@ -3983,16 +4837,31 @@ ZipFSOpenFileChannelProc( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *pathPtr, int mode, - int permissions) + TCL_UNUSED(int) /* permissions */) { - int len; + int trunc = (mode & O_TRUNC) != 0; + int wr = (mode & (O_WRONLY | O_RDWR)) != 0; pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return NULL; } - return ZipChannelOpen(interp, Tcl_GetStringFromObj(pathPtr, &len), mode, - permissions); + + /* + * Check for unsupported modes. + */ + + if ((mode & O_APPEND) || ((ZipFS.wrmax <= 0) && wr)) { + Tcl_SetErrno(EACCES); + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "write access not supported: %s", + Tcl_PosixError(interp))); + } + return NULL; + } + + return ZipChannelOpen(interp, Tcl_GetString(pathPtr), wr, trunc); } /* @@ -4017,13 +4886,11 @@ ZipFSStatProc( Tcl_Obj *pathPtr, Tcl_StatBuf *buf) { - int len; - pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return -1; } - return ZipEntryStat(Tcl_GetStringFromObj(pathPtr, &len), buf); + return ZipEntryStat(Tcl_GetString(pathPtr), buf); } /* @@ -4048,13 +4915,11 @@ ZipFSAccessProc( Tcl_Obj *pathPtr, int mode) { - int len; - pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return -1; } - return ZipEntryAccess(Tcl_GetStringFromObj(pathPtr, &len), mode); + return ZipEntryAccess(Tcl_GetString(pathPtr), mode); } /* @@ -4086,6 +4951,38 @@ ZipFSFilesystemSeparatorProc( /* *------------------------------------------------------------------------- * + * AppendWithPrefix -- + * + * Worker for ZipFSMatchInDirectoryProc() that is a wrapper around + * Tcl_ListObjAppendElement() which knows about handling prefixes. + * + *------------------------------------------------------------------------- + */ + +static inline void +AppendWithPrefix( + Tcl_Obj *result, /* Where to append a list element to. */ + Tcl_DString *prefix, /* The prefix to add to the element, or NULL + * for don't do that. */ + const char *name, /* The name to append. */ + int nameLen) /* The length of the name. May be -1 for + * append-up-to-NUL-byte. */ +{ + if (prefix) { + int prefixLength = Tcl_DStringLength(prefix); + + Tcl_DStringAppend(prefix, name, nameLen); + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj( + Tcl_DStringValue(prefix), Tcl_DStringLength(prefix))); + Tcl_DStringSetLength(prefix, prefixLength); + } else { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(name, nameLen)); + } +} + +/* + *------------------------------------------------------------------------- + * * ZipFSMatchInDirectoryProc -- * * This routine is used by the globbing code to search a directory for @@ -4105,24 +5002,24 @@ ZipFSFilesystemSeparatorProc( static int ZipFSMatchInDirectoryProc( TCL_UNUSED(Tcl_Interp *), - Tcl_Obj *result, - Tcl_Obj *pathPtr, - const char *pattern, - Tcl_GlobTypeData *types) + Tcl_Obj *result, /* Where to append matched items to. */ + Tcl_Obj *pathPtr, /* Where we are looking. */ + const char *pattern, /* What names we are looking for. */ + Tcl_GlobTypeData *types) /* What types we are looking for. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); - int scnt, l, dirOnly = -1, prefixLen, strip = 0; - size_t len; + int scnt, l, dirOnly = -1, prefixLen, strip = 0, mounts = 0, len; char *pat, *prefix, *path; - Tcl_DString dsPref; + Tcl_DString dsPref, *prefixBuf = NULL; if (!normPathPtr) { return -1; } if (types) { dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR; + mounts = (types->type == TCL_GLOB_TYPE_MOUNT); } /* @@ -4135,107 +5032,58 @@ ZipFSMatchInDirectoryProc( * The (normalized) path we're searching. */ - path = Tcl_GetString(normPathPtr); - len = normPathPtr->length; + path = Tcl_GetStringFromObj(normPathPtr, &len); Tcl_DStringInit(&dsPref); - Tcl_DStringAppend(&dsPref, prefix, prefixLen); - if (strcmp(prefix, path) == 0) { - prefix = NULL; + prefixBuf = NULL; } else { + /* + * We need to strip the normalized prefix of the filenames and replace + * it with the official prefix that we were expecting to get. + */ + strip = len + 1; - } - if (prefix) { + Tcl_DStringAppend(&dsPref, prefix, prefixLen); Tcl_DStringAppend(&dsPref, "/", 1); - prefixLen++; prefix = Tcl_DStringValue(&dsPref); + prefixBuf = &dsPref; } + ReadLock(); - if (types && (types->type == TCL_GLOB_TYPE_MOUNT)) { - l = CountSlashes(path); - if (path[len - 1] == '/') { - len--; - } else { - l++; - } - if (!pattern || (pattern[0] == '\0')) { - pattern = "*"; - } - for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; - hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr); - - if (zf->mountPointLen == 0) { - ZipEntry *z; - - for (z = zf->topEnts; z; z = z->tnext) { - size_t lenz = strlen(z->name); - - if ((lenz > len + 1) && (strncmp(z->name, path, len) == 0) - && (z->name[len] == '/') - && (CountSlashes(z->name) == l) - && Tcl_StringCaseMatch(z->name + len + 1, pattern, - 0)) { - if (prefix) { - Tcl_DStringAppend(&dsPref, z->name, lenz); - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref))); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(z->name, lenz)); - } - } - } - } else if ((zf->mountPointLen > len + 1) - && (strncmp(zf->mountPoint, path, len) == 0) - && (zf->mountPoint[len] == '/') - && (CountSlashes(zf->mountPoint) == l) - && Tcl_StringCaseMatch(zf->mountPoint + len + 1, - pattern, 0)) { - if (prefix) { - Tcl_DStringAppend(&dsPref, zf->mountPoint, - zf->mountPointLen); - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref))); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(zf->mountPoint, - zf->mountPointLen)); - } - } - } + + /* + * Are we globbing the mount points? + */ + + if (mounts) { + ZipFSMatchMountPoints(result, normPathPtr, pattern, prefixBuf); goto end; } + /* + * Can we skip the complexity of actual globbing? Without a pattern, yes; + * it's a directory existence test. + */ + if (!pattern || (pattern[0] == '\0')) { - hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); - if (hPtr) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); - - if ((dirOnly < 0) || (!dirOnly && !z->isDirectory) - || (dirOnly && z->isDirectory)) { - if (prefix) { - Tcl_DStringAppend(&dsPref, z->name, -1); - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref))); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(z->name, -1)); - } - } + ZipEntry *z = ZipFSLookup(path); + + if (z && ((dirOnly < 0) || (!dirOnly && !z->isDirectory) + || (dirOnly && z->isDirectory))) { + AppendWithPrefix(result, prefixBuf, z->name, -1); } goto end; } + /* + * We've got to work for our supper and do the actual globbing. And all + * we've got really is an undifferentiated pile of all the filenames we've + * got from all our ZIP mounts. + */ + l = strlen(pattern); - pat = (char *)ckalloc(len + l + 2); + pat = (char *) ckalloc(len + l + 2); memcpy(pat, path, len); while ((len > 1) && (pat[len - 1] == '/')) { --len; @@ -4246,25 +5094,17 @@ ZipFSMatchInDirectoryProc( } memcpy(pat + len, pattern, l + 1); scnt = CountSlashes(pat); + for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr); + ZipEntry *z = (ZipEntry *) Tcl_GetHashValue(hPtr); if ((dirOnly >= 0) && ((dirOnly && !z->isDirectory) || (!dirOnly && z->isDirectory))) { continue; } if ((z->depth == scnt) && Tcl_StringCaseMatch(z->name, pat, 0)) { - if (prefix) { - Tcl_DStringAppend(&dsPref, z->name + strip, -1); - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(Tcl_DStringValue(&dsPref), - Tcl_DStringLength(&dsPref))); - Tcl_DStringSetLength(&dsPref, prefixLen); - } else { - Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(z->name + strip, -1)); - } + AppendWithPrefix(result, prefixBuf, z->name + strip, -1); } } ckfree(pat); @@ -4278,6 +5118,94 @@ ZipFSMatchInDirectoryProc( /* *------------------------------------------------------------------------- * + * ZipFSMatchMountPoints -- + * + * This routine is a worker for ZipFSMatchInDirectoryProc, used by the + * globbing code to search for all mount points files which match a given + * pattern. + * + * Results: + * None. + * + * Side effects: + * Adds the matching mounts to the list in result, uses prefix as working + * space if it is non-NULL. + * + *------------------------------------------------------------------------- + */ + +static void +ZipFSMatchMountPoints( + Tcl_Obj *result, /* The list of matches being built. */ + Tcl_Obj *normPathPtr, /* Where we're looking from. */ + const char *pattern, /* What we're looking for. NULL for a full + * list. */ + Tcl_DString *prefix) /* Workspace filled with a prefix for all the + * filenames, or NULL if no prefix is to be + * used. */ +{ + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + int l, normLength; + const char *path = Tcl_GetStringFromObj(normPathPtr, &normLength); + size_t len = (size_t) normLength; + + if (len < 1) { + /* + * Shouldn't happen. But "shouldn't"... + */ + + return; + } + l = CountSlashes(path); + if (path[len - 1] == '/') { + len--; + } else { + l++; + } + if (!pattern || (pattern[0] == '\0')) { + pattern = "*"; + } + + for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; + hPtr = Tcl_NextHashEntry(&search)) { + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); + + if (zf->mountPointLen == 0) { + ZipEntry *z; + + /* + * Enumerate the contents of the ZIP; it's mounted on the root. + */ + + for (z = zf->topEnts; z; z = z->tnext) { + size_t lenz = strlen(z->name); + + if ((lenz > len + 1) && (strncmp(z->name, path, len) == 0) + && (z->name[len] == '/') + && (CountSlashes(z->name) == l) + && Tcl_StringCaseMatch(z->name + len + 1, pattern, 0)) { + AppendWithPrefix(result, prefix, z->name, lenz); + } + } + } else if ((zf->mountPointLen > len + 1) + && (strncmp(zf->mountPoint, path, len) == 0) + && (zf->mountPoint[len] == '/') + && (CountSlashes(zf->mountPoint) == l) + && Tcl_StringCaseMatch(zf->mountPoint + len + 1, + pattern, 0)) { + /* + * Standard mount; append if it matches. + */ + + AppendWithPrefix(result, prefix, zf->mountPoint, zf->mountPointLen); + } + } +} + +/* + *------------------------------------------------------------------------- + * * ZipFSPathInFilesystemProc -- * * This function determines if the given path object is in the ZIP @@ -4299,22 +5227,18 @@ ZipFSPathInFilesystemProc( { Tcl_HashEntry *hPtr; Tcl_HashSearch search; - int ret = -1; - size_t len; + int ret = -1, len; char *path; pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (!pathPtr) { return -1; } - - path = Tcl_GetString(pathPtr); + path = Tcl_GetStringFromObj(pathPtr, &len); if (strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) != 0) { return -1; } - len = pathPtr->length; - ReadLock(); hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path); if (hPtr) { @@ -4324,7 +5248,7 @@ ZipFSPathInFilesystemProc( for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { - ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr); + ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr); if (zf->mountPointLen == 0) { ZipEntry *z; @@ -4332,12 +5256,13 @@ ZipFSPathInFilesystemProc( for (z = zf->topEnts; z != NULL; z = z->tnext) { size_t lenz = strlen(z->name); - if ((len >= lenz) && (strncmp(path, z->name, lenz) == 0)) { + if (((size_t) len >= lenz) && + (strncmp(path, z->name, lenz) == 0)) { ret = TCL_OK; goto endloop; } } - } else if ((len >= zf->mountPointLen) && + } else if (((size_t) len >= zf->mountPointLen) && (strncmp(path, zf->mountPoint, zf->mountPointLen) == 0)) { ret = TCL_OK; break; @@ -4389,11 +5314,25 @@ ZipFSListVolumesProc(void) *------------------------------------------------------------------------- */ +enum ZipFileAttrs { + ZIP_ATTR_UNCOMPSIZE, + ZIP_ATTR_COMPSIZE, + ZIP_ATTR_OFFSET, + ZIP_ATTR_MOUNT, + ZIP_ATTR_ARCHIVE, + ZIP_ATTR_PERMISSIONS, + ZIP_ATTR_CRC +}; + static const char *const * ZipFSFileAttrStringsProc( TCL_UNUSED(Tcl_Obj *) /*pathPtr*/, TCL_UNUSED(Tcl_Obj **) /*objPtrRef*/) { + /* + * Must match up with ZipFileAttrs enum above. + */ + static const char *const attrs[] = { "-uncompsize", "-compsize", @@ -4401,6 +5340,7 @@ ZipFSFileAttrStringsProc( "-mount", "-archive", "-permissions", + "-crc", NULL, }; @@ -4452,27 +5392,31 @@ ZipFSFileAttrsGetProc( goto done; } switch (index) { - case 0: + case ZIP_ATTR_UNCOMPSIZE: TclNewIntObj(*objPtrRef, z->numBytes); break; - case 1: + case ZIP_ATTR_COMPSIZE: TclNewIntObj(*objPtrRef, z->numCompressedBytes); break; - case 2: + case ZIP_ATTR_OFFSET: TclNewIntObj(*objPtrRef, z->offset); break; - case 3: + case ZIP_ATTR_MOUNT: *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint, z->zipFilePtr->mountPointLen); break; - case 4: + case ZIP_ATTR_ARCHIVE: *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->name, -1); break; - case 5: + case ZIP_ATTR_PERMISSIONS: *objPtrRef = Tcl_NewStringObj("0o555", -1); break; + case ZIP_ATTR_CRC: + TclNewIntObj(*objPtrRef, z->crc32); + break; default: ZIPFS_ERROR(interp, "unknown attribute"); + ZIPFS_ERROR_CODE(interp, "FILE_ATTR"); ret = TCL_ERROR; } @@ -4505,10 +5449,8 @@ ZipFSFileAttrsSetProc( TCL_UNUSED(Tcl_Obj *) /*pathPtr*/, TCL_UNUSED(Tcl_Obj *) /*objPtr*/) { - if (interp) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("unsupported operation", -1)); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "UNSUPPORTED_OP", NULL); - } + ZIPFS_ERROR(interp, "unsupported operation"); + ZIPFS_ERROR_CODE(interp, "UNSUPPORTED_OP"); return TCL_ERROR; } @@ -4610,7 +5552,7 @@ ZipFSLoadFile( if (execName) { const char *p = strrchr(execName, '/'); - if (p > execName + 1) { + if (p && p > execName + 1) { --p; objs[0] = Tcl_NewStringObj(execName, p - execName); } @@ -4636,7 +5578,8 @@ ZipFSLoadFile( Tcl_DecrRefCount(objs[1]); } - loadFileProc = (Tcl_FSLoadFileProc2 *)(void *)tclNativeFilesystem.loadFileProc; + loadFileProc = (Tcl_FSLoadFileProc2 *) (void *) + tclNativeFilesystem.loadFileProc; if (loadFileProc) { ret = loadFileProc(interp, path, loadHandle, unloadProcPtr, flags); } else { @@ -4725,8 +5668,12 @@ TclZipfs_Init( Tcl_Obj *mapObj; Tcl_EvalEx(interp, findproc, -1, TCL_EVAL_GLOBAL); - Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax, - TCL_LINK_INT); + if (!Tcl_IsSafe(interp)) { + Tcl_LinkVar(interp, "::tcl::zipfs::wrmax", (char *) &ZipFS.wrmax, + TCL_LINK_INT); + Tcl_LinkVar(interp, "::tcl::zipfs::fallbackEntryEncoding", + (char *) &ZipFS.fallbackEntryEncoding, TCL_LINK_STRING); + } ensemble = TclMakeEnsemble(interp, "zipfs", Tcl_IsSafe(interp) ? (initMap + 4) : initMap); @@ -4744,7 +5691,7 @@ TclZipfs_Init( return TCL_OK; #else /* !HAVE_ZLIB */ ZIPFS_ERROR(interp, "no zlib available"); - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); return TCL_ERROR; #endif /* HAVE_ZLIB */ } @@ -4792,7 +5739,7 @@ static void ZipfsExitHandler( ClientData clientData) { - ZipFile *zf = (ZipFile *)clientData; + ZipFile *zf = (ZipFile *) clientData; if (TCL_OK != TclZipfs_Unmount(NULL, zf->mountPoint)) { Tcl_Panic("tried to unmount busy filesystem"); @@ -4955,9 +5902,7 @@ TclZipfs_Mount( * the ZIP is unprotected. */ { ZIPFS_ERROR(interp, "no zlib available"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); return TCL_ERROR; } @@ -4970,9 +5915,7 @@ TclZipfs_MountBuffer( int copy) { ZIPFS_ERROR(interp, "no zlib available"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); return TCL_ERROR; } @@ -4982,9 +5925,7 @@ TclZipfs_Unmount( const char *mountPoint) /* Mount point path. */ { ZIPFS_ERROR(interp, "no zlib available"); - if (interp) { - Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "NO_ZLIB", NULL); - } + ZIPFS_ERROR_CODE(interp, "NO_ZLIB"); return TCL_ERROR; } #endif /* !HAVE_ZLIB */ diff --git a/generic/tclZlib.c b/generic/tclZlib.c index 9fc84da..440bb9a 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -3957,7 +3957,7 @@ TclZlibInit( * Formally provide the package as a Tcl built-in. */ -#ifndef TCL_NO_DEPRECATED +#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) Tcl_PkgProvide(interp, "zlib", TCL_ZLIB_VERSION); #endif return Tcl_PkgProvide(interp, "tcl::zlib", TCL_ZLIB_VERSION); diff --git a/library/dde/pkgIndex.tcl b/library/dde/pkgIndex.tcl index 5d1727d..18ac517 100644 --- a/library/dde/pkgIndex.tcl +++ b/library/dde/pkgIndex.tcl @@ -1,3 +1,12 @@ -if {![package vsatisfies [package provide Tcl] 8.5-]} return if {[info sharedlibextension] != ".dll"} return -package ifneeded dde 1.4.4 [list load [file join $dir tcldde14.dll] Dde] +if {[package vsatisfies [package provide Tcl] 9.0-]} { + package ifneeded dde 1.4.4 \ + [list load [file join $dir tcl9dde14.dll] Dde] +} elseif {![package vsatisfies [package provide Tcl] 8.7] + && [::tcl::pkgconfig get debug]} { + package ifneeded dde 1.4.4 \ + [list load [file join $dir tcldde14g.dll] Dde] +} else { + package ifneeded dde 1.4.4 \ + [list load [file join $dir tcldde14.dll] Dde] +} diff --git a/library/registry/pkgIndex.tcl b/library/registry/pkgIndex.tcl index 5c73f30..765f02a 100644 --- a/library/registry/pkgIndex.tcl +++ b/library/registry/pkgIndex.tcl @@ -1,4 +1,9 @@ if {![package vsatisfies [package provide Tcl] 8.5-]} return if {[info sharedlibextension] != ".dll"} return -package ifneeded registry 1.3.6 \ - [list load [file join $dir tclregistry13.dll] Registry] +if {[package vsatisfies [package provide Tcl] 9.0-]} { + package ifneeded registry 1.3.6 \ + [list load [file join $dir tcl9registry13.dll] Registry] +} else { + package ifneeded registry 1.3.6 \ + [list load [file join $dir tclregistry13.dll] Registry] +} diff --git a/library/safe.tcl b/library/safe.tcl index 2ee4531..3c01f75 100644 --- a/library/safe.tcl +++ b/library/safe.tcl @@ -1009,8 +1009,8 @@ proc ::safe::AliasLoad {child file args} { return -code error $msg } - # package name (can be empty if file is not). - set package [lindex $args 0] + # prefix (can be empty if file is not). + set prefix [lindex $args 0] namespace upvar ::safe [VarName $child] state @@ -1022,23 +1022,23 @@ proc ::safe::AliasLoad {child file args} { # authorize that. if {!$state(nestedok)} { Log $child "loading to a sub interp (nestedok)\ - disabled (trying to load $package to $target)" + disabled (trying to load $prefix to $target)" return -code error "permission denied (nested load)" } } # Determine what kind of load is requested if {$file eq ""} { - # static package loading - if {$package eq ""} { - set msg "load error: empty filename and no package name" + # static loading + if {$prefix eq ""} { + set msg "load error: empty filename and no prefix" Log $child $msg return -code error $msg } if {!$state(staticsok)} { - Log $child "static packages loading disabled\ - (trying to load $package to $target)" - return -code error "permission denied (static package)" + Log $child "static loading disabled\ + (trying to load $prefix to $target)" + return -code error "permission denied (static library)" } } else { # file loading @@ -1061,10 +1061,10 @@ proc ::safe::AliasLoad {child file args} { } try { - return [::interp invokehidden $child load $file $package $target] + return [::interp invokehidden $child load $file $prefix $target] } on error msg { - # Some packages return no error message. - set msg0 "load of binary library for package $package failed" + # Some libraries return no error message. + set msg0 "load of library for prefix $prefix failed" if {$msg eq {}} { set msg $msg0 } else { diff --git a/macosx/Tcl.xcode/project.pbxproj b/macosx/Tcl.xcode/project.pbxproj index eba62f2..0746261 100644 --- a/macosx/Tcl.xcode/project.pbxproj +++ b/macosx/Tcl.xcode/project.pbxproj @@ -394,7 +394,7 @@ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; }; F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; }; F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; }; - F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; }; + F96D3EA508F272A7004A47F5 /* StaticLibrary.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticLibrary.3; sourceTree = "<group>"; }; F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; }; F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; }; F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; }; @@ -1141,7 +1141,7 @@ F96D3EA208F272A7004A47F5 /* split.n */, F96D3EA308F272A7004A47F5 /* SplitList.3 */, F96D3EA408F272A7004A47F5 /* SplitPath.3 */, - F96D3EA508F272A7004A47F5 /* StaticPkg.3 */, + F96D3EA508F272A7004A47F5 /* StaticLibrary.3 */, F96D3EA608F272A7004A47F5 /* StdChannels.3 */, F96D3EA708F272A7004A47F5 /* string.n */, F96D3EA808F272A7004A47F5 /* StringObj.3 */, diff --git a/macosx/Tcl.xcodeproj/project.pbxproj b/macosx/Tcl.xcodeproj/project.pbxproj index c20e83a..6bb3417 100644 --- a/macosx/Tcl.xcodeproj/project.pbxproj +++ b/macosx/Tcl.xcodeproj/project.pbxproj @@ -393,7 +393,7 @@ F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = "<group>"; }; F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = "<group>"; }; F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = "<group>"; }; - F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = "<group>"; }; + F96D3EA508F272A7004A47F5 /* StaticLibrary.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticLibrary.3; sourceTree = "<group>"; }; F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = "<group>"; }; F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = "<group>"; }; F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = "<group>"; }; @@ -1141,7 +1141,7 @@ F96D3EA208F272A7004A47F5 /* split.n */, F96D3EA308F272A7004A47F5 /* SplitList.3 */, F96D3EA408F272A7004A47F5 /* SplitPath.3 */, - F96D3EA508F272A7004A47F5 /* StaticPkg.3 */, + F96D3EA508F272A7004A47F5 /* StaticLibrary.3 */, F96D3EA608F272A7004A47F5 /* StdChannels.3 */, F96D3EA708F272A7004A47F5 /* string.n */, F96D3EA808F272A7004A47F5 /* StringObj.3 */, diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c index 5bdc5a3..c870a36 100644 --- a/macosx/tclMacOSXNotify.c +++ b/macosx/tclMacOSXNotify.c @@ -534,7 +534,58 @@ MODULE_SCOPE long tclMacOSXDarwinRelease; /* *---------------------------------------------------------------------- * - * Tcl_InitNotifier -- + * LookUpFileHandler -- + * + * Look up the file handler structure (and optionally the previous one in + * the chain) associated with a file descriptor. + * + * Returns: + * A pointer to the file handler, or NULL if it can't be found. + * + * Side effects: + * If prevPtrPtr is non-NULL, it will be written to if the file handler + * is found. + * + *---------------------------------------------------------------------- + */ + +static inline FileHandler * +LookUpFileHandler( + ThreadSpecificData *tsdPtr, /* Where to look things up. */ + int fd, /* What we are looking for. */ + FileHandler **prevPtrPtr) /* If non-NULL, where to report the previous + * pointer. */ +{ + FileHandler *filePtr, *prevPtr; + + /* + * Find the entry for the given file (and return if there isn't one). + */ + + for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; + prevPtr = filePtr, filePtr = filePtr->nextPtr) { + if (filePtr == NULL) { + return NULL; + } + if (filePtr->fd == fd) { + break; + } + } + + /* + * Report what we've found to our caller. + */ + + if (prevPtrPtr) { + *prevPtrPtr = prevPtr; + } + return filePtr; +} + +/* + *---------------------------------------------------------------------- + * + * TclpInitNotifier -- * * Initializes the platform specific notifier state. * @@ -548,22 +599,16 @@ MODULE_SCOPE long tclMacOSXDarwinRelease; */ ClientData -Tcl_InitNotifier(void) +TclpInitNotifier(void) { - ThreadSpecificData *tsdPtr; - - if (tclNotifierHooks.initNotifierProc) { - return tclNotifierHooks.initNotifierProc(); - } - - tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); #ifdef WEAK_IMPORT_SPINLOCKLOCK /* * Initialize support for weakly imported spinlock API. */ if (pthread_once(&spinLockLockInitControl, SpinLockLockInit)) { - Tcl_Panic("Tcl_InitNotifier: pthread_once failed"); + Tcl_Panic("Tcl_InitNotifier: %s", "pthread_once failed"); } #endif @@ -590,7 +635,8 @@ Tcl_InitNotifier(void) runLoopSource = CFRunLoopSourceCreate(NULL, LONG_MIN, &runLoopSourceContext); if (!runLoopSource) { - Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource"); + Tcl_Panic("Tcl_InitNotifier: %s", + "could not create CFRunLoopSource"); } CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes); CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode); @@ -602,8 +648,8 @@ Tcl_InitNotifier(void) LONG_MIN, UpdateWaitingListAndServiceEvents, &runLoopObserverContext); if (!runLoopObserver) { - Tcl_Panic("Tcl_InitNotifier: could not create " - "CFRunLoopObserver"); + Tcl_Panic("Tcl_InitNotifier: %s", + "could not create CFRunLoopObserver"); } CFRunLoopAddObserver(runLoop, runLoopObserver, kCFRunLoopCommonModes); @@ -620,8 +666,8 @@ Tcl_InitNotifier(void) LONG_MIN, UpdateWaitingListAndServiceEvents, &runLoopObserverContext); if (!runLoopObserverTcl) { - Tcl_Panic("Tcl_InitNotifier: could not create " - "CFRunLoopObserver"); + Tcl_Panic("Tcl_InitNotifier: %s", + "could not create CFRunLoopObserver"); } CFRunLoopAddObserver(runLoop, runLoopObserverTcl, tclEventsOnlyRunLoopMode); @@ -650,7 +696,7 @@ Tcl_InitNotifier(void) int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild); if (result) { - Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed"); + Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed"); } atForkInit = 1; } @@ -663,20 +709,20 @@ Tcl_InitNotifier(void) */ if (pipe(fds) != 0) { - Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe"); + Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe"); } status = fcntl(fds[0], F_GETFL); status |= O_NONBLOCK; if (fcntl(fds[0], F_SETFL, status) < 0) { - Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non " - "blocking"); + Tcl_Panic("Tcl_InitNotifier: %s", + "could not make receive pipe non-blocking"); } status = fcntl(fds[1], F_GETFL); status |= O_NONBLOCK; if (fcntl(fds[1], F_SETFL, status) < 0) { - Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non " - "blocking"); + Tcl_Panic("Tcl_InitNotifier: %s", + "could not make trigger pipe non-blocking"); } receivePipe = fds[0]; @@ -762,7 +808,7 @@ StartNotifierThread(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setstacksize(&attr, 60 * 1024); result = pthread_create(¬ifierThread, &attr, - (void * (*)(void *))NotifierThreadProc, NULL); + (void * (*)(void *)) NotifierThreadProc, NULL); pthread_attr_destroy(&attr); if (result) { Tcl_Panic("StartNotifierThread: unable to start notifier thread"); @@ -776,7 +822,7 @@ StartNotifierThread(void) /* *---------------------------------------------------------------------- * - * Tcl_FinalizeNotifier -- + * TclpFinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread * is terminated. @@ -792,17 +838,10 @@ StartNotifierThread(void) */ void -Tcl_FinalizeNotifier( - ClientData clientData) +TclpFinalizeNotifier( + TCL_UNUSED(ClientData)) { - ThreadSpecificData *tsdPtr; - - if (tclNotifierHooks.finalizeNotifierProc) { - tclNotifierHooks.finalizeNotifierProc(clientData); - return; - } - - tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); LOCK_NOTIFIER_INIT; notifierCount--; @@ -876,7 +915,7 @@ Tcl_FinalizeNotifier( /* *---------------------------------------------------------------------- * - * Tcl_AlertNotifier -- + * TclpAlertNotifier -- * * Wake up the specified notifier from any thread. This routine is called * by the platform independent notifier code whenever the Tcl_ThreadAlert @@ -893,15 +932,10 @@ Tcl_FinalizeNotifier( */ void -Tcl_AlertNotifier( +TclpAlertNotifier( ClientData clientData) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData; - - if (tclNotifierHooks.alertNotifierProc) { - tclNotifierHooks.alertNotifierProc(clientData); - return; - } + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; LOCK_NOTIFIER_TSD; if (tsdPtr->runLoop) { @@ -914,7 +948,7 @@ Tcl_AlertNotifier( /* *---------------------------------------------------------------------- * - * Tcl_SetTimer -- + * TclpSetTimer -- * * This function sets the current notifier timer value. * @@ -928,18 +962,13 @@ Tcl_AlertNotifier( */ void -Tcl_SetTimer( +TclpSetTimer( const Tcl_Time *timePtr) /* Timeout value, may be NULL. */ { ThreadSpecificData *tsdPtr; CFRunLoopTimerRef runLoopTimer; CFTimeInterval waitTime; - if (tclNotifierHooks.setTimerProc) { - tclNotifierHooks.setTimerProc(timePtr); - return; - } - tsdPtr = TCL_TSD_INIT(&dataKey); runLoopTimer = tsdPtr->runLoopTimer; if (!runLoopTimer) { @@ -949,7 +978,7 @@ Tcl_SetTimer( Tcl_Time vTime = *timePtr; if (vTime.sec != 0 || vTime.usec != 0) { - tclScaleTimeProcPtr(&vTime, tclTimeClientData); + TclScaleTime(&vTime); waitTime = vTime.sec + 1.0e-6 * vTime.usec; } else { waitTime = 0; @@ -988,7 +1017,7 @@ TimerWakeUp( /* *---------------------------------------------------------------------- * - * Tcl_ServiceModeHook -- + * TclpServiceModeHook -- * * This function is invoked whenever the service mode changes. * @@ -1002,18 +1031,11 @@ TimerWakeUp( */ void -Tcl_ServiceModeHook( +TclpServiceModeHook( int mode) /* Either TCL_SERVICE_ALL, or * TCL_SERVICE_NONE. */ { - ThreadSpecificData *tsdPtr; - - if (tclNotifierHooks.serviceModeHookProc) { - tclNotifierHooks.serviceModeHookProc(mode); - return; - } - - tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (mode == TCL_SERVICE_ALL && !tsdPtr->runLoopTimer) { if (!tsdPtr->runLoop) { @@ -1033,9 +1055,9 @@ Tcl_ServiceModeHook( /* *---------------------------------------------------------------------- * - * Tcl_CreateFileHandler -- + * TclpCreateFileHandler -- * - * This function registers a file handler with the select notifier. + * This function registers a file handler with the notifier. * * Results: * None. @@ -1047,7 +1069,7 @@ Tcl_ServiceModeHook( */ void -Tcl_CreateFileHandler( +TclpCreateFileHandler( int fd, /* Handle of stream to watch. */ int mask, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION: indicates @@ -1057,24 +1079,11 @@ Tcl_CreateFileHandler( * event. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { - ThreadSpecificData *tsdPtr; - FileHandler *filePtr; - - if (tclNotifierHooks.createFileHandlerProc) { - tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); - return; - } - - tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL); - for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { - if (filePtr->fd == fd) { - break; - } - } if (filePtr == NULL) { - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); filePtr->fd = fd; filePtr->readyMask = 0; filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; @@ -1113,7 +1122,7 @@ Tcl_CreateFileHandler( /* *---------------------------------------------------------------------- * - * Tcl_DeleteFileHandler -- + * TclpDeleteFileHandler -- * * Cancel a previously-arranged callback arrangement for a file. * @@ -1127,47 +1136,34 @@ Tcl_CreateFileHandler( */ void -Tcl_DeleteFileHandler( +TclpDeleteFileHandler( int fd) /* Stream id for which to remove callback * function. */ { FileHandler *filePtr, *prevPtr; - int i, numFdBits; - ThreadSpecificData *tsdPtr; - - if (tclNotifierHooks.deleteFileHandlerProc) { - tclNotifierHooks.deleteFileHandlerProc(fd); - return; - } - - tsdPtr = TCL_TSD_INIT(&dataKey); - numFdBits = -1; + int i, numFdBits = -1; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Find the entry for the given file (and return if there isn't one). */ - for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; - prevPtr = filePtr, filePtr = filePtr->nextPtr) { - if (filePtr == NULL) { - return; - } - if (filePtr->fd == fd) { - break; - } + filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr); + if (filePtr == NULL) { + return; } /* * Find current max fd. */ - if (fd+1 == tsdPtr->numFdBits) { + if (fd + 1 == tsdPtr->numFdBits) { numFdBits = 0; - for (i = fd-1; i >= 0; i--) { + for (i = fd - 1; i >= 0; i--) { if (FD_ISSET(i, &tsdPtr->checkMasks.readable) || FD_ISSET(i, &tsdPtr->checkMasks.writable) || FD_ISSET(i, &tsdPtr->checkMasks.exceptional)) { - numFdBits = i+1; + numFdBits = i + 1; break; } } @@ -1250,12 +1246,8 @@ FileHandlerEventProc( */ tsdPtr = TCL_TSD_INIT(&dataKey); - for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { - if (filePtr->fd != fileEvPtr->fd) { - continue; - } - + filePtr = LookUpFileHandler(tsdPtr, fileEvPtr->fd, NULL); + if (filePtr != NULL) { /* * The code is tricky for two reasons: * 1. The file handler's desired events could have changed since the @@ -1284,7 +1276,6 @@ FileHandlerEventProc( UNLOCK_NOTIFIER_TSD; filePtr->proc(filePtr->clientData, mask); } - break; } return 1; } @@ -1292,7 +1283,7 @@ FileHandlerEventProc( /* *---------------------------------------------------------------------- * - * Tcl_WaitForEvent -- + * TclpWaitForEvent -- * * 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 @@ -1309,7 +1300,7 @@ FileHandlerEventProc( */ int -Tcl_WaitForEvent( +TclpWaitForEvent( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { int result, polling, runLoopRunning; @@ -1317,9 +1308,6 @@ Tcl_WaitForEvent( SInt32 runLoopStatus; ThreadSpecificData *tsdPtr; - if (tclNotifierHooks.waitForEventProc) { - return tclNotifierHooks.waitForEventProc(timePtr); - } result = -1; polling = 0; waitTime = CF_TIMEINTERVAL_FOREVER; @@ -1343,10 +1331,9 @@ Tcl_WaitForEvent( */ if (vTime.sec != 0 || vTime.usec != 0) { - tclScaleTimeProcPtr(&vTime, tclTimeClientData); + TclScaleTime(&vTime); waitTime = vTime.sec + 1.0e-6 * vTime.usec; } else { - /* * The max block time was set to 0. * @@ -1357,8 +1344,8 @@ Tcl_WaitForEvent( * or timers are ready to fire immediately, only one (possibly two * if one is a version 0 source) will be fired, regardless of the * value of returnAfterSourceHandled." This can cause some chanio - * tests to fail. So we use a small positive waitTime unless there - * is another RunLoop running. + * tests to fail. So we use a small positive waitTime unless + * there is another RunLoop running. */ polling = 1; @@ -1431,7 +1418,7 @@ QueueFileEvents( { SelectMasks readyMasks; FileHandler *filePtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info; /* * Queue all detected file events. @@ -1470,7 +1457,8 @@ QueueFileEvents( */ if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)ckalloc(sizeof(FileHandlerEvent)); + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) + ckalloc(sizeof(FileHandlerEvent)); fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; @@ -1485,8 +1473,8 @@ QueueFileEvents( * * UpdateWaitingListAndServiceEvents -- * - * CFRunLoopObserver callback for updating waitingList and - * servicing Tcl events. + * CFRunLoopObserver callback for updating waitingList and servicing Tcl + * events. * * Results: * None. @@ -1503,7 +1491,8 @@ UpdateWaitingListAndServiceEvents( CFRunLoopActivity activity, void *info) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) info; + if (tsdPtr->sleeping) { return; } @@ -1626,8 +1615,7 @@ Tcl_Sleep( vdelay.sec = ms / 1000; vdelay.usec = (ms % 1000) * 1000; - tclScaleTimeProcPtr(&vdelay, tclTimeClientData); - + TclScaleTime(&vdelay); if (tsdPtr->runLoop) { CFTimeInterval waitTime; @@ -1853,7 +1841,7 @@ TclUnixWaitForFile( * * Result: * None. Once started, this routine never exits. It dies with the overall - * process. + * process or terminates its own thread (on notifier termination). * * Side effects: * The trigger pipe used to signal the notifier thread is created when @@ -2090,9 +2078,9 @@ AtForkChild(void) ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* - * If a child process unlocks an os_unfair_lock that was created in its parent - * the child will exit with an illegal instruction error. So we reinitialize - * the lock in the child rather than attempt to unlock it. + * If a child process unlocks an os_unfair_lock that was created in its + * parent the child will exit with an illegal instruction error. So we + * reinitialize the lock in the child rather than attempt to unlock it. */ #if defined(USE_OS_UNFAIR_LOCK) diff --git a/tests/append.test b/tests/append.test index a174615..c0c0cce 100644 --- a/tests/append.test +++ b/tests/append.test @@ -15,8 +15,12 @@ if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } +::tcltest::loadTestedCommands unset -nocomplain x +catch [list package require -exact tcl::test [info patchlevel]] +testConstraint testbytestring [llength [info commands testbytestring]] + test append-1.1 {append command} { unset -nocomplain x list [append x 1 2 abc "long string"] $x @@ -53,6 +57,35 @@ test append-3.3 {append errors} -returnCodes error -body { unset -nocomplain x append x } -result {can't read "x": no such variable} +test append-3.4 {append surrogates} -body { + set x \uD83D + append x \uDE02 +} -result \uD83D\uDE02 +test append-3.5 {append surrogates} -body { + set x \uD83D + set x $x\uDE02 +} -result \uD83D\uDE02 +test append-3.6 {append surrogates} -body { + set x \uDE02 + set x \uD83D$x +} -result \uD83D\uDE02 +test append-3.7 {append \xC0 \x80} -constraints testbytestring -body { + set x [testbytestring \xC0] + string length [append x [testbytestring \x80]] +} -result 2 +test append-3.8 {append \xC0 \x80} -constraints testbytestring -body { + set x [testbytestring \xC0] + string length $x[testbytestring \x80] +} -result 2 +test append-3.9 {append \xC0 \x80} -constraints testbytestring -body { + set x [testbytestring \x80] + string length [testbytestring \xC0]$x +} -result 2 +test append-3.10 {append surrogates} -body { + set x \uD83D + string range $x 0 end + append x \uDE02 +} -result [string range \uD83D\uDE02 0 end] test append-4.1 {lappend command} { unset -nocomplain x diff --git a/tests/binary.test b/tests/binary.test index 8b326d4..a43fb49 100644 --- a/tests/binary.test +++ b/tests/binary.test @@ -14,6 +14,9 @@ if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } +::tcltest::loadTestedCommands +catch [list package require -exact tcl::test [info patchlevel]] + testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}] testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}] testConstraint testbytestring [llength [info commands testbytestring]] @@ -25,9 +28,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -37,19 +40,19 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -59,11 +62,11 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) set ieeeValues(littleEndian) 0 return 1 @@ -160,16 +163,16 @@ test binary-4.3 {Tcl_BinaryObjCmd: format} { } \x80 test binary-4.4 {Tcl_BinaryObjCmd: format} { binary format B* 010011 -} \x4c +} \x4C test binary-4.5 {Tcl_BinaryObjCmd: format} { binary format B8 01001101 -} \x4d +} \x4D test binary-4.6 {Tcl_BinaryObjCmd: format} { binary format A2X2B9 oo 01001101 -} \x4d\x00 +} \x4D\x00 test binary-4.7 {Tcl_BinaryObjCmd: format} { binary format B9 010011011010 -} \x4d\x80 +} \x4D\x80 test binary-4.8 {Tcl_BinaryObjCmd: format} { binary format B2B3 10 010 } \x80\x40 @@ -191,16 +194,16 @@ test binary-5.4 {Tcl_BinaryObjCmd: format} { } 2 test binary-5.5 {Tcl_BinaryObjCmd: format} { binary format b8 01001101 -} \xb2 +} \xB2 test binary-5.6 {Tcl_BinaryObjCmd: format} { binary format A2X2b9 oo 01001101 -} \xb2\x00 +} \xB2\x00 test binary-5.7 {Tcl_BinaryObjCmd: format} { binary format b9 010011011010 -} \xb2\x01 +} \xB2\x01 test binary-5.8 {Tcl_BinaryObjCmd: format} { binary format b17 1 -} \x01\00\00 +} \x01\x00\x00 test binary-5.9 {Tcl_BinaryObjCmd: format} { binary format b2b3 10 010 } \x01\x02 @@ -219,19 +222,19 @@ test binary-6.3 {Tcl_BinaryObjCmd: format} { } \x01 test binary-6.4 {Tcl_BinaryObjCmd: format} { binary format h c -} \x0c +} \x0C test binary-6.5 {Tcl_BinaryObjCmd: format} { binary format h* baadf00d -} \xab\xda\x0f\xd0 +} \xAB\xDA\x0F\xD0 test binary-6.6 {Tcl_BinaryObjCmd: format} { binary format h4 c410 -} \x4c\x01 +} \x4C\x01 test binary-6.7 {Tcl_BinaryObjCmd: format} { binary format h6 c4102 -} \x4c\x01\x02 +} \x4C\x01\x02 test binary-6.8 {Tcl_BinaryObjCmd: format} { binary format h5 c41020304 -} \x4c\x01\x02 +} \x4C\x01\x02 test binary-6.9 {Tcl_BinaryObjCmd: format} { binary format a3X3h5 foo 2 } \x02\x00\x00 @@ -253,19 +256,19 @@ test binary-7.3 {Tcl_BinaryObjCmd: format} { } \x10 test binary-7.4 {Tcl_BinaryObjCmd: format} { binary format H c -} \xc0 +} \xC0 test binary-7.5 {Tcl_BinaryObjCmd: format} { binary format H* baadf00d -} \xba\xad\xf0\x0d +} \xBA\xAD\xF0\x0D test binary-7.6 {Tcl_BinaryObjCmd: format} { binary format H4 c410 -} \xc4\x10 +} \xC4\x10 test binary-7.7 {Tcl_BinaryObjCmd: format} { binary format H6 c4102 -} \xc4\x10\x20 +} \xC4\x10\x20 test binary-7.8 {Tcl_BinaryObjCmd: format} { binary format H5 c41023304 -} \xc4\x10\x20 +} \xC4\x10\x20 test binary-7.9 {Tcl_BinaryObjCmd: format} { binary format a3X3H5 foo 2 } \x20\x00\x00 @@ -485,34 +488,34 @@ test binary-13.3 {Tcl_BinaryObjCmd: format} { } {} test binary-13.4 {Tcl_BinaryObjCmd: format} bigEndian { binary format f 1.6 -} \x3f\xcc\xcc\xcd +} \x3F\xCC\xCC\xCD test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian { binary format f 1.6 -} \xcd\xcc\xcc\x3f +} \xCD\xCC\xCC\x3F test binary-13.6 {Tcl_BinaryObjCmd: format} bigEndian { binary format f* {1.6 3.4} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian { binary format f* {1.6 3.4} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-13.8 {Tcl_BinaryObjCmd: format} bigEndian { binary format f2 {1.6 3.4} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian { binary format f2 {1.6 3.4} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-13.10 {Tcl_BinaryObjCmd: format} bigEndian { binary format f2 {1.6 3.4 5.6} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-13.11 {Tcl_BinaryObjCmd: format} littleEndian { binary format f2 {1.6 3.4 5.6} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian { binary format f -3.402825e+38 -} \xff\x7f\xff\xff +} \xFF\x7F\xFF\xFF test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian { binary format f -3.402825e+38 -} \xff\xff\x7f\xff +} \xFF\xFF\x7F\xFF test binary-13.14 {Tcl_BinaryObjCmd: float underflow} bigEndian { binary format f -3.402825e-100 } \x80\x00\x00\x00 @@ -529,11 +532,11 @@ test binary-13.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body { test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian { set a {1.6 3.4} binary format f1 $a -} \x3f\xcc\xcc\xcd +} \x3F\xCC\xCC\xCD test binary-13.19 {Tcl_BinaryObjCmd: format} littleEndian { set a {1.6 3.4} binary format f1 $a -} \xcd\xcc\xcc\x3f +} \xCD\xCC\xCC\x3F test binary-14.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body { binary format d @@ -546,28 +549,28 @@ test binary-14.3 {Tcl_BinaryObjCmd: format} { } {} test binary-14.4 {Tcl_BinaryObjCmd: format} bigEndian { binary format d 1.6 -} \x3f\xf9\x99\x99\x99\x99\x99\x9a +} \x3F\xF9\x99\x99\x99\x99\x99\x9A test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian { binary format d 1.6 -} \x9a\x99\x99\x99\x99\x99\xf9\x3f +} \x9A\x99\x99\x99\x99\x99\xF9\x3F test binary-14.6 {Tcl_BinaryObjCmd: format} bigEndian { binary format d* {1.6 3.4} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-14.7 {Tcl_BinaryObjCmd: format} littleEndian { binary format d* {1.6 3.4} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-14.8 {Tcl_BinaryObjCmd: format} bigEndian { binary format d2 {1.6 3.4} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-14.9 {Tcl_BinaryObjCmd: format} littleEndian { binary format d2 {1.6 3.4} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-14.10 {Tcl_BinaryObjCmd: format} bigEndian { binary format d2 {1.6 3.4 5.6} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-14.11 {Tcl_BinaryObjCmd: format} littleEndian { binary format d2 {1.6 3.4 5.6} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-14.14 {Tcl_BinaryObjCmd: format} -returnCodes error -body { binary format d2 {1.6} } -result {number of elements in list does not match count} @@ -578,11 +581,11 @@ test binary-14.15 {Tcl_BinaryObjCmd: format} -returnCodes error -body { test binary-14.16 {Tcl_BinaryObjCmd: format} bigEndian { set a {1.6 3.4} binary format d1 $a -} \x3f\xf9\x99\x99\x99\x99\x99\x9a +} \x3F\xF9\x99\x99\x99\x99\x99\x9A test binary-14.17 {Tcl_BinaryObjCmd: format} littleEndian { set a {1.6 3.4} binary format d1 $a -} \x9a\x99\x99\x99\x99\x99\xf9\x3f +} \x9A\x99\x99\x99\x99\x99\xF9\x3F test binary-14.18 {FormatNumber: Bug 1116542} { binary scan [binary format d 1.25] d w set w @@ -874,11 +877,11 @@ test binary-24.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-24.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 h* arg1] $arg1 + list [binary scan \x52\xA3 h* arg1] $arg1 } {1 253a} test binary-24.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xc2\xa3 h arg1] $arg1 + list [binary scan \xC2\xA3 h arg1] $arg1 } {1 2} test binary-24.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -890,7 +893,7 @@ test binary-24.5 {Tcl_BinaryObjCmd: scan} { } {1 {}} test binary-24.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xf2\x53 h2 arg1] $arg1 + list [binary scan \xF2\x53 h2 arg1] $arg1 } {1 2f} test binary-24.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -920,11 +923,11 @@ test binary-25.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-25.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 H* arg1] $arg1 + list [binary scan \x52\xA3 H* arg1] $arg1 } {1 52a3} test binary-25.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xc2\xa3 H arg1] $arg1 + list [binary scan \xC2\xA3 H arg1] $arg1 } {1 c} test binary-25.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -936,7 +939,7 @@ test binary-25.5 {Tcl_BinaryObjCmd: scan} { } {1 {}} test binary-25.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xf2\x53 H2 arg1] $arg1 + list [binary scan \xF2\x53 H2 arg1] $arg1 } {1 f2} test binary-25.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -965,27 +968,27 @@ test binary-26.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-26.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c* arg1] $arg1 + list [binary scan \x52\xA3 c* arg1] $arg1 } {1 {82 -93}} test binary-26.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c arg1] $arg1 + list [binary scan \x52\xA3 c arg1] $arg1 } {1 82} test binary-26.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c1 arg1] $arg1 + list [binary scan \x52\xA3 c1 arg1] $arg1 } {1 82} test binary-26.5 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c0 arg1] $arg1 + list [binary scan \x52\xA3 c0 arg1] $arg1 } {1 {}} test binary-26.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c2 arg1] $arg1 + list [binary scan \x52\xA3 c2 arg1] $arg1 } {1 {82 -93}} test binary-26.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xff c arg1] $arg1 + list [binary scan \xFF c arg1] $arg1 } {1 -1} test binary-26.8 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1006,15 +1009,15 @@ test binary-26.10 {Tcl_BinaryObjCmd: scan} { } {2 {112 -121} 5} test binary-26.11 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 cu* arg1] $arg1 + list [binary scan \x52\xA3 cu* arg1] $arg1 } {1 {82 163}} test binary-26.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 cu arg1] $arg1 + list [binary scan \x52\xA3 cu arg1] $arg1 } {1 82} test binary-26.13 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xff cu arg1] $arg1 + list [binary scan \xFF cu arg1] $arg1 } {1 255} test binary-26.14 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 @@ -1034,23 +1037,23 @@ test binary-27.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-27.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 s* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 s* arg1] $arg1 } {1 {-23726 21587}} test binary-27.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 s arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 s arg1] $arg1 } {1 -23726} test binary-27.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 s1 arg1] $arg1 + list [binary scan \x52\xA3 s1 arg1] $arg1 } {1 -23726} test binary-27.5 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 s0 arg1] $arg1 + list [binary scan \x52\xA3 s0 arg1] $arg1 } {1 {}} test binary-27.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 s2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 s2 arg1] $arg1 } {1 {-23726 21587}} test binary-27.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1067,23 +1070,23 @@ test binary-27.9 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x05 s2c* arg1 arg2] $arg1 $arg2 } {2 {-23726 21587} 5} test binary-27.10 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 su* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 su* arg1] $arg1 } {1 {41810 21587}} test binary-27.11 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \xff\xff\xff\xff sus arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF sus arg1 arg2] $arg1 $arg2 } {2 65535 -1} test binary-27.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \xff\xff\xff\xff ssu arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF ssu arg1 arg2] $arg1 $arg2 } {2 -1 65535} test binary-28.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { @@ -1091,23 +1094,23 @@ test binary-28.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-28.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 S* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 S* arg1] $arg1 } {1 {21155 21332}} test binary-28.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 S arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 S arg1] $arg1 } {1 21155} test binary-28.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 S1 arg1] $arg1 + list [binary scan \x52\xA3 S1 arg1] $arg1 } {1 21155} test binary-28.5 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3 S0 arg1] $arg1 + list [binary scan \x52\xA3 S0 arg1] $arg1 } {1 {}} test binary-28.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 S2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 S2 arg1] $arg1 } {1 {21155 21332}} test binary-28.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1124,15 +1127,15 @@ test binary-28.9 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x05 S2c* arg1 arg2] $arg1 $arg2 } {2 {21155 21332} 5} test binary-28.10 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 Su* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 Su* arg1] $arg1 } {1 {21155 21332}} test binary-28.11 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \xa3\x52\x54\x53 Su* arg1] $arg1 + list [binary scan \xA3\x52\x54\x53 Su* arg1] $arg1 } {1 {41810 21587}} test binary-29.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { @@ -1140,23 +1143,23 @@ test binary-29.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-29.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i* arg1] $arg1 } {1 {1414767442 67305985}} test binary-29.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i arg1] $arg1 } {1 1414767442} test binary-29.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 i1 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 i1 arg1] $arg1 } {1 1414767442} test binary-29.5 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53 i0 arg1] $arg1 + list [binary scan \x52\xA3\x53 i0 arg1] $arg1 } {1 {}} test binary-29.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 i2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 i2 arg1] $arg1 } {1 {1414767442 67305985}} test binary-29.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1173,15 +1176,15 @@ test binary-29.9 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 i2c* arg1 arg2] $arg1 $arg2 } {2 {1414767442 67305985} 5} test binary-29.10 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 - list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iui arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF iui arg1 arg2] $arg1 $arg2 } {2 4294967295 -1} test binary-29.11 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 - list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff iiu arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF iiu arg1 arg2] $arg1 $arg2 } {2 -1 4294967295} test binary-29.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 @@ -1193,23 +1196,23 @@ test binary-30.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-30.2 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I* arg1] $arg1 } {1 {1386435412 16909060}} test binary-30.3 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I arg1] $arg1 } {1 1386435412} test binary-30.4 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 I1 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 I1 arg1] $arg1 } {1 1386435412} test binary-30.5 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53 I0 arg1] $arg1 + list [binary scan \x52\xA3\x53 I0 arg1] $arg1 } {1 {}} test binary-30.6 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 I2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 I2 arg1] $arg1 } {1 {1386435412 16909060}} test binary-30.7 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1226,15 +1229,15 @@ test binary-30.9 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 I2c* arg1 arg2] $arg1 $arg2 } {2 {1386435412 16909060} 5} test binary-30.10 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 - list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IuI arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF IuI arg1 arg2] $arg1 $arg2 } {2 4294967295 -1} test binary-30.11 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 - list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff IIu arg1 arg2] $arg1 $arg2 + list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF IIu arg1 arg2] $arg1 $arg2 } {2 -1 4294967295} test binary-30.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 arg2 @@ -1246,43 +1249,43 @@ test binary-31.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-31.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f* arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f* arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-31.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f* arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f* arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-31.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f arg1] $arg1 } {1 1.600000023841858} test binary-31.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f arg1] $arg1 } {1 1.600000023841858} test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd f1 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD f1 arg1] $arg1 } {1 1.600000023841858} test binary-31.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f f1 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F f1 arg1] $arg1 } {1 1.600000023841858} test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd f0 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD f0 arg1] $arg1 } {1 {}} test binary-31.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f f0 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F f0 arg1] $arg1 } {1 {}} test binary-31.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f2 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A f2 arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-31.11 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f2 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 f2 arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-31.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1293,19 +1296,19 @@ test binary-31.13 {Tcl_BinaryObjCmd: scan} -setup { unset -nocomplain arg1 } -returnCodes error -body { set arg1 1 - binary scan \x3f\xcc\xcc\xcd f1 arg1(a) + binary scan \x3F\xCC\xCC\xCD f1 arg1(a) } -result {can't set "arg1(a)": variable isn't array} test binary-31.14 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 f2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A\x05 f2c* arg1 arg2] $arg1 $arg2 } {2 {1.600000023841858 3.4000000953674316} 5} test binary-31.15 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2 } {2 {1.600000023841858 3.4000000953674316} 5} test binary-32.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { @@ -1313,43 +1316,43 @@ test binary-32.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-32.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d* arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d* arg1] $arg1 } {1 {1.6 3.4}} test binary-32.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d* arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d* arg1] $arg1 } {1 {1.6 3.4}} test binary-32.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d arg1] $arg1 } {1 1.6} test binary-32.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d arg1] $arg1 } {1 1.6} test binary-32.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d1 arg1] $arg1 } {1 1.6} test binary-32.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d1 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F d1 arg1] $arg1 } {1 1.6} test binary-32.8 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d0 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d0 arg1] $arg1 } {1 {}} test binary-32.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f d0 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F d0 arg1] $arg1 } {1 {}} test binary-32.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 d2 arg1] $arg1 } {1 {1.6 3.4}} test binary-32.11 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 d2 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 d2 arg1] $arg1 } {1 {1.6 3.4}} test binary-32.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -1360,19 +1363,19 @@ test binary-32.13 {Tcl_BinaryObjCmd: scan} -setup { unset -nocomplain arg1 } -returnCodes error -body { set arg1 1 - binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a d1 arg1(a) + binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A d1 arg1(a) } -result {can't set "arg1(a)": variable isn't array} test binary-32.14 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33\x05 d2c* arg1 arg2] $arg1 $arg2 } {2 {1.6 3.4} 5} test binary-32.15 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 d2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40\x05 d2c* arg1 arg2] $arg1 $arg2 } {2 {1.6 3.4} 5} test binary-33.1 {Tcl_BinaryObjCmd: scan} { @@ -1543,20 +1546,20 @@ test binary-38.4 {FormatNumber: word alignment} { } \x01\x00\x00\x00\x01 test binary-38.5 {FormatNumber: word alignment} bigEndian { set x [binary format c1d1 1 1.6] -} \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a +} \x01\x3F\xF9\x99\x99\x99\x99\x99\x9A test binary-38.6 {FormatNumber: word alignment} littleEndian { set x [binary format c1d1 1 1.6] -} \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f +} \x01\x9A\x99\x99\x99\x99\x99\xF9\x3F test binary-38.7 {FormatNumber: word alignment} bigEndian { set x [binary format c1f1 1 1.6] -} \x01\x3f\xcc\xcc\xcd +} \x01\x3F\xCC\xCC\xCD test binary-38.8 {FormatNumber: word alignment} littleEndian { set x [binary format c1f1 1 1.6] -} \x01\xcd\xcc\xcc\x3f +} \x01\xCD\xCC\xCC\x3F test binary-39.1 {ScanNumber: sign extension} { unset -nocomplain arg1 - list [binary scan \x52\xa3 c2 arg1] $arg1 + list [binary scan \x52\xA3 c2 arg1] $arg1 } {1 {82 -93}} test binary-39.2 {ScanNumber: sign extension} { unset -nocomplain arg1 @@ -1576,7 +1579,7 @@ test binary-39.5 {ScanNumber: sign extension} { } {1 {16843010 -2130640639 25297153 16876033 16843137}} test binary-39.6 {ScanNumber: no sign extension} { unset -nocomplain arg1 - list [binary scan \x52\xa3 cu2 arg1] $arg1 + list [binary scan \x52\xA3 cu2 arg1] $arg1 } {1 {82 163}} test binary-39.7 {ScanNumber: no sign extension} { unset -nocomplain arg1 @@ -1597,11 +1600,11 @@ test binary-39.10 {ScanNumber: no sign extension} { test binary-40.3 {ScanNumber: NaN} -body { unset -nocomplain arg1 - list [binary scan \xff\xff\xff\xff f1 arg1] $arg1 + list [binary scan \xFF\xFF\xFF\xFF f1 arg1] $arg1 } -match glob -result {1 -NaN*} test binary-40.4 {ScanNumber: NaN} -body { unset -nocomplain arg1 - list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d arg1] $arg1 + list [binary scan \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF d arg1] $arg1 } -match glob -result {1 -NaN*} test binary-41.1 {ScanNumber: word alignment} -setup { @@ -1627,22 +1630,22 @@ test binary-41.4 {ScanNumber: word alignment} -setup { test binary-41.5 {ScanNumber: word alignment} -setup { unset -nocomplain arg1 arg2 } -constraints bigEndian -body { - list [binary scan \x01\x3f\xcc\xcc\xcd c1f1 arg1 arg2] $arg1 $arg2 + list [binary scan \x01\x3F\xCC\xCC\xCD c1f1 arg1 arg2] $arg1 $arg2 } -result {2 1 1.600000023841858} test binary-41.6 {ScanNumber: word alignment} -setup { unset -nocomplain arg1 arg2 } -constraints littleEndian -body { - list [binary scan \x01\xcd\xcc\xcc\x3f c1f1 arg1 arg2] $arg1 $arg2 + list [binary scan \x01\xCD\xCC\xCC\x3F c1f1 arg1 arg2] $arg1 $arg2 } -result {2 1 1.600000023841858} test binary-41.7 {ScanNumber: word alignment} -setup { unset -nocomplain arg1 arg2 } -constraints bigEndian -body { - list [binary scan \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a c1d1 arg1 arg2] $arg1 $arg2 + list [binary scan \x01\x3F\xF9\x99\x99\x99\x99\x99\x9A c1d1 arg1 arg2] $arg1 $arg2 } -result {2 1 1.6} test binary-41.8 {ScanNumber: word alignment} -setup { unset -nocomplain arg1 arg2 } -constraints littleEndian -body { - list [binary scan \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f c1d1 arg1 arg2] $arg1 $arg2 + list [binary scan \x01\x9A\x99\x99\x99\x99\x99\xF9\x3F c1d1 arg1 arg2] $arg1 $arg2 } -result {2 1 1.6} test binary-42.1 {Tcl_BinaryObjCmd: bad arguments} -constraints {} -body { @@ -1713,26 +1716,26 @@ test binary-45.2 {Tcl_BinaryObjCmd: combined wide int handling} { } {66 64 0 0 0 0 127 -1 -1 -1 65 76} test binary-46.1 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} { - binary format a* \u20ac -} \u00ac + binary format a* € +} \xAC test binary-46.2 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} { - list [binary scan [binary format a* \u20ac\u20bd] s x] $x + list [binary scan [binary format a* €₽] s x] $x } {1 -16980} test binary-46.3 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} { set x {} set y {} set z {} - list [binary scan [binary format a* \u20ac\u20bd] aaa x y z] $x $y $z -} "2 \u00ac \u00bd {}" + list [binary scan [binary format a* €₽] aaa x y z] $x $y $z +} "2 \xAC \xBD {}" test binary-46.4 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} { - set x [encoding convertto iso8859-15 \u20ac] + set x [encoding convertto iso8859-15 €] set y [binary format a* $x] list $x $y -} "\u00a4 \u00a4" +} "\xA4 \xA4" test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} { - set x [binary scan \u00a4 a* y] + set x [binary scan \xA4 a* y] list $x $y [encoding convertfrom iso8859-15 $y] -} "1 \u00a4 \u20ac" +} "1 \xA4 €" test binary-47.1 {Tcl_BinaryObjCmd: number cache reference count handling} { # This test is only reliable when memory debugging is turned on, but @@ -1898,28 +1901,28 @@ test binary-51.3 {Tcl_BinaryObjCmd: format} { } {} test binary-51.4 {Tcl_BinaryObjCmd: format} {} { binary format Q 1.6 -} \x3f\xf9\x99\x99\x99\x99\x99\x9a +} \x3F\xF9\x99\x99\x99\x99\x99\x9A test binary-51.5 {Tcl_BinaryObjCmd: format} {} { binary format q 1.6 -} \x9a\x99\x99\x99\x99\x99\xf9\x3f +} \x9A\x99\x99\x99\x99\x99\xF9\x3F test binary-51.6 {Tcl_BinaryObjCmd: format} {} { binary format Q* {1.6 3.4} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-51.7 {Tcl_BinaryObjCmd: format} {} { binary format q* {1.6 3.4} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-51.8 {Tcl_BinaryObjCmd: format} {} { binary format Q2 {1.6 3.4} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-51.9 {Tcl_BinaryObjCmd: format} {} { binary format q2 {1.6 3.4} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-51.10 {Tcl_BinaryObjCmd: format} {} { binary format Q2 {1.6 3.4 5.6} -} \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 +} \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 test binary-51.11 {Tcl_BinaryObjCmd: format} {} { binary format q2 {1.6 3.4 5.6} -} \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 +} \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 test binary-51.14 {Tcl_BinaryObjCmd: format} -returnCodes error -body { binary format q2 {1.6} } -result {number of elements in list does not match count} @@ -1930,11 +1933,11 @@ test binary-51.15 {Tcl_BinaryObjCmd: format} -returnCodes error -body { test binary-51.16 {Tcl_BinaryObjCmd: format} {} { set a {1.6 3.4} binary format Q1 $a -} \x3f\xf9\x99\x99\x99\x99\x99\x9a +} \x3F\xF9\x99\x99\x99\x99\x99\x9A test binary-51.17 {Tcl_BinaryObjCmd: format} {} { set a {1.6 3.4} binary format q1 $a -} \x9a\x99\x99\x99\x99\x99\xf9\x3f +} \x9A\x99\x99\x99\x99\x99\xF9\x3F # format R/r test binary-53.1 {Tcl_BinaryObjCmd: format} -returnCodes error -body { @@ -1948,34 +1951,34 @@ test binary-53.3 {Tcl_BinaryObjCmd: format} { } {} test binary-53.4 {Tcl_BinaryObjCmd: format} {} { binary format R 1.6 -} \x3f\xcc\xcc\xcd +} \x3F\xCC\xCC\xCD test binary-53.5 {Tcl_BinaryObjCmd: format} {} { binary format r 1.6 -} \xcd\xcc\xcc\x3f +} \xCD\xCC\xCC\x3F test binary-53.6 {Tcl_BinaryObjCmd: format} {} { binary format R* {1.6 3.4} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-53.7 {Tcl_BinaryObjCmd: format} {} { binary format r* {1.6 3.4} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-53.8 {Tcl_BinaryObjCmd: format} {} { binary format R2 {1.6 3.4} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-53.9 {Tcl_BinaryObjCmd: format} {} { binary format r2 {1.6 3.4} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-53.10 {Tcl_BinaryObjCmd: format} {} { binary format R2 {1.6 3.4 5.6} -} \x3f\xcc\xcc\xcd\x40\x59\x99\x9a +} \x3F\xCC\xCC\xCD\x40\x59\x99\x9A test binary-53.11 {Tcl_BinaryObjCmd: format} {} { binary format r2 {1.6 3.4 5.6} -} \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 +} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {} { binary format R -3.402825e+38 -} \xff\x7f\xff\xff +} \xFF\x7F\xFF\xFF test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} { binary format r -3.402825e+38 -} \xff\xff\x7f\xff +} \xFF\xFF\x7F\xFF test binary-53.14 {Tcl_BinaryObjCmd: float underflow} {} { binary format R -3.402825e-100 } \x80\x00\x00\x00 @@ -1992,11 +1995,11 @@ test binary-53.17 {Tcl_BinaryObjCmd: format} -returnCodes error -body { test binary-53.18 {Tcl_BinaryObjCmd: format} {} { set a {1.6 3.4} binary format R1 $a -} \x3f\xcc\xcc\xcd +} \x3F\xCC\xCC\xCD test binary-53.19 {Tcl_BinaryObjCmd: format} {} { set a {1.6 3.4} binary format r1 $a -} \xcd\xcc\xcc\x3f +} \xCD\xCC\xCC\x3F # scan t (s) test binary-54.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { @@ -2004,23 +2007,23 @@ test binary-54.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-54.2 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t* arg1] $arg1 } {1 {-23726 21587}} test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t arg1] $arg1 } {1 -23726} test binary-54.4 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3 t1 arg1] $arg1 + list [binary scan \x52\xA3 t1 arg1] $arg1 } {1 -23726} test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3 t0 arg1] $arg1 + list [binary scan \x52\xA3 t0 arg1] $arg1 } {1 {}} test binary-54.6 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t2 arg1] $arg1 } {1 {-23726 21587}} test binary-54.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 @@ -2037,7 +2040,7 @@ test binary-54.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2 } {2 {-23726 21587} 5} test binary-54.10 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 @@ -2058,23 +2061,23 @@ test binary-55.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-55.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t* arg1] $arg1 } {1 {21155 21332}} test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t arg1] $arg1 } {1 21155} test binary-55.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3 t1 arg1] $arg1 + list [binary scan \x52\xA3 t1 arg1] $arg1 } {1 21155} test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3 t0 arg1] $arg1 + list [binary scan \x52\xA3 t0 arg1] $arg1 } {1 {}} test binary-55.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 t2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 t2 arg1] $arg1 } {1 {21155 21332}} test binary-55.7 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 @@ -2091,7 +2094,7 @@ test binary-55.9 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x05 t2c* arg1 arg2] $arg1 $arg2 } {2 {21155 21332} 5} test binary-55.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 @@ -2112,23 +2115,23 @@ test binary-56.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-56.2 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1 } {1 {1414767442 67305985}} test binary-56.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n arg1] $arg1 } {1 1414767442} test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 n1 arg1] $arg1 } {1 1414767442} test binary-56.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53 n0 arg1] $arg1 + list [binary scan \x52\xA3\x53 n0 arg1] $arg1 } {1 {}} test binary-56.6 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1 } {1 {1414767442 67305985}} test binary-56.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 @@ -2145,7 +2148,7 @@ test binary-56.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2 } {2 {1414767442 67305985} 5} test binary-56.10 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 @@ -2166,23 +2169,23 @@ test binary-57.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-57.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n* arg1] $arg1 } {1 {1386435412 16909060}} test binary-57.3 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n arg1] $arg1 } {1 1386435412} test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54 n1 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54 n1 arg1] $arg1 } {1 1386435412} test binary-57.5 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53 n0 arg1] $arg1 + list [binary scan \x52\xA3\x53 n0 arg1] $arg1 } {1 {}} test binary-57.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04 n2 arg1] $arg1 } {1 {1386435412 16909060}} test binary-57.7 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 @@ -2199,7 +2202,7 @@ test binary-57.9 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x52\xA3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2 } {2 {1386435412 16909060} 5} test binary-57.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 @@ -2220,43 +2223,43 @@ test binary-58.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-58.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q* arg1] $arg1 } {1 {1.6 3.4}} test binary-58.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q* arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q* arg1] $arg1 } {1 {1.6 3.4}} test binary-58.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q arg1] $arg1 } {1 1.6} test binary-58.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q arg1] $arg1 } {1 1.6} test binary-58.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q1 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A Q1 arg1] $arg1 } {1 1.6} test binary-58.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q1 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F q1 arg1] $arg1 } {1 1.6} test binary-58.8 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a Q0 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A Q0 arg1] $arg1 } {1 {}} test binary-58.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f q0 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F q0 arg1] $arg1 } {1 {}} test binary-58.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33 Q2 arg1] $arg1 } {1 {1.6 3.4}} test binary-58.11 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40 q2 arg1] $arg1 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40 q2 arg1] $arg1 } {1 {1.6 3.4}} test binary-58.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -2267,19 +2270,19 @@ test binary-58.13 {Tcl_BinaryObjCmd: scan} -setup { unset -nocomplain arg1 } -returnCodes error -body { set arg1 1 - binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a q1 arg1(a) + binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A q1 arg1(a) } -result {can't set "arg1(a)": variable isn't array} test binary-58.14 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x3F\xF9\x99\x99\x99\x99\x99\x9A\x40\x0B\x33\x33\x33\x33\x33\x33\x05 Q2c* arg1 arg2] $arg1 $arg2 } {2 {1.6 3.4} 5} test binary-58.15 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x9a\x99\x99\x99\x99\x99\xf9\x3f\x33\x33\x33\x33\x33\x33\x0b\x40\x05 q2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x9A\x99\x99\x99\x99\x99\xF9\x3F\x33\x33\x33\x33\x33\x33\x0B\x40\x05 q2c* arg1 arg2] $arg1 $arg2 } {2 {1.6 3.4} 5} # scan R/r @@ -2288,43 +2291,43 @@ test binary-59.1 {Tcl_BinaryObjCmd: scan} -returnCodes error -body { } -result {not enough arguments for all format specifiers} test binary-59.2 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R* arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R* arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-59.3 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r* arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r* arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-59.4 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R arg1] $arg1 } {1 1.600000023841858} test binary-59.5 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r arg1] $arg1 } {1 1.600000023841858} test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd R1 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD R1 arg1] $arg1 } {1 1.600000023841858} test binary-59.7 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f r1 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F r1 arg1] $arg1 } {1 1.600000023841858} test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd R0 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD R0 arg1] $arg1 } {1 {}} test binary-59.9 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f r0 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F r0 arg1] $arg1 } {1 {}} test binary-59.10 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R2 arg1] $arg1 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A R2 arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-59.11 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r2 arg1] $arg1 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40 r2 arg1] $arg1 } {1 {1.600000023841858 3.4000000953674316}} test binary-59.12 {Tcl_BinaryObjCmd: scan} { unset -nocomplain arg1 @@ -2335,19 +2338,19 @@ test binary-59.13 {Tcl_BinaryObjCmd: scan} -setup { unset -nocomplain arg1 } -returnCodes error -body { set arg1 1 - binary scan \x3f\xcc\xcc\xcd r1 arg1(a) + binary scan \x3F\xCC\xCC\xCD r1 arg1(a) } -result {can't set "arg1(a)": variable isn't array} test binary-59.14 {Tcl_BinaryObjCmd: scan} bigEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 R2c* arg1 arg2] $arg1 $arg2 + list [binary scan \x3F\xCC\xCC\xCD\x40\x59\x99\x9A\x05 R2c* arg1 arg2] $arg1 $arg2 } {2 {1.600000023841858 3.4000000953674316} 5} test binary-59.15 {Tcl_BinaryObjCmd: scan} littleEndian { unset -nocomplain arg1 arg2 set arg1 foo set arg2 bar - list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2 + list [binary scan \xCD\xCC\xCC\x3F\x9A\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2 } {2 {1.600000023841858 3.4000000953674316} 5} test binary-60.1 {[binary format] with NaN} -body { @@ -2496,7 +2499,7 @@ test binary-70.4 {binary encode hex} -body { binary encode hex [string repeat a 20] } -result [string repeat 61 20] test binary-70.5 {binary encode hex} -body { - binary encode hex \0\1\2\3\4\0\1\2\3\4 + binary encode hex \x00\x01\x02\x03\x04\x00\x01\x02\x03\x04 } -result {00010203040001020304} test binary-71.1 {binary decode hex} -body { @@ -2513,7 +2516,7 @@ test binary-71.4 {binary decode hex} -body { } -result [string repeat a 20] test binary-71.5 {binary decode hex} -body { binary decode hex 00010203040001020304 -} -result "\0\1\2\3\4\0\1\2\3\4" +} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04" test binary-71.6 {binary decode hex} -body { binary decode hex "61 61" } -result {aa} @@ -2572,19 +2575,19 @@ test binary-72.4 {binary encode base64} -body { binary encode base64 [string repeat abc 20] } -result [string repeat YWJj 20] test binary-72.5 {binary encode base64} -body { - binary encode base64 \0\1\2\3\4\0\1\2\3 + binary encode base64 \x00\x01\x02\x03\x04\x00\x01\x02\x03 } -result {AAECAwQAAQID} test binary-72.6 {binary encode base64} -body { - binary encode base64 \0 + binary encode base64 \x00 } -result {AA==} test binary-72.7 {binary encode base64} -body { - binary encode base64 \0\0 + binary encode base64 \x00\x00 } -result {AAA=} test binary-72.8 {binary encode base64} -body { - binary encode base64 \0\0\0 + binary encode base64 \x00\x00\x00 } -result {AAAA} test binary-72.9 {binary encode base64} -body { - binary encode base64 \0\0\0\0 + binary encode base64 \x00\x00\x00\x00 } -result {AAAAAA==} test binary-72.10 {binary encode base64} -body { binary encode base64 -maxlen 0 -wrapchar : abcabcabc @@ -2644,7 +2647,7 @@ test binary-72.28 {binary encode base64} -body { binary encode base64 -maxlen 6 -wrapchar 0123456789 abcabcabc } -result {YWJjYW0123456789JjYWJj} test binary-72.29 {binary encode base64} { - string length [binary encode base64 -maxlen 3 -wrapchar \xca abc] + string length [binary encode base64 -maxlen 3 -wrapchar \xCA abc] } 5 test binary-73.1 {binary decode base64} -body { @@ -2661,19 +2664,19 @@ test binary-73.4 {binary decode base64} -body { } -result [string repeat abc 20] test binary-73.5 {binary decode base64} -body { binary decode base64 AAECAwQAAQID -} -result "\0\1\2\3\4\0\1\2\3" +} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03" test binary-73.6 {binary decode base64} -body { binary decode base64 AA== -} -result "\0" +} -result "\x00" test binary-73.7 {binary decode base64} -body { binary decode base64 AAA= -} -result "\0\0" +} -result "\x00\x00" test binary-73.8 {binary decode base64} -body { binary decode base64 AAAA -} -result "\0\0\0" +} -result "\x00\x00\x00" test binary-73.9 {binary decode base64} -body { binary decode base64 AAAAAA== -} -result "\0\0\0\0" +} -result "\x00\x00\x00\x00" test binary-73.10 {binary decode base64} -body { set s "[string repeat YWJj 10]\n[string repeat YWJj 10]" binary decode base64 $s @@ -2791,22 +2794,22 @@ test binary-74.4 {binary encode uuencode} -body { binary encode uuencode [string repeat abc 20] } -result "M[string repeat 86)C 15]\n/[string repeat 86)C 5]\n" test binary-74.5 {binary encode uuencode} -body { - binary encode uuencode \0\1\2\3\4\0\1\2\3 + binary encode uuencode \x00\x01\x02\x03\x04\x00\x01\x02\x03 } -result ")``\$\"`P0``0(#\n" test binary-74.6 {binary encode uuencode} -body { binary encode uuencode \0 } -result {!`` } test binary-74.7 {binary encode uuencode} -body { - binary encode uuencode \0\0 + binary encode uuencode \x00\x00 } -result "\"``` " test binary-74.8 {binary encode uuencode} -body { - binary encode uuencode \0\0\0 + binary encode uuencode \x00\x00\x00 } -result {#```` } test binary-74.9 {binary encode uuencode} -body { - binary encode uuencode \0\0\0\0 + binary encode uuencode \x00\x00\x00\x00 } -result {$`````` } test binary-74.10 {binary encode uuencode} -returnCodes error -body { @@ -2842,7 +2845,7 @@ test binary-75.4 {binary decode uuencode} -body { } -result [string repeat abc 20] test binary-75.5 {binary decode uuencode} -body { binary decode uuencode ")``\$\"`P0``0(#" -} -result "\0\1\2\3\4\0\1\2\3" +} -result "\x00\x01\x02\x03\x04\x00\x01\x02\x03" test binary-75.6 {binary decode uuencode} -body { string length [binary decode uuencode "`\n"] } -result 0 @@ -2948,18 +2951,18 @@ test binary-79.1 {Tcl_SetByteArrayLength} testsetbytearraylength { testsetbytearraylength [string cat A B C] 1 } A test binary-79.2 {Tcl_SetByteArrayLength} testsetbytearraylength { - testsetbytearraylength [string cat \u0141 B C] 1 + testsetbytearraylength [string cat Ł B C] 1 } A test binary-80.1 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body { - testbytestring "\u4E4E" -} -result "expected byte sequence but character 0 was '\u4E4E' (U+004E4E)" + testbytestring "乎" +} -result "expected byte sequence but character 0 was '乎' (U+004E4E)" test binary-80.2 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body { testbytestring [testbytestring "\x00\xA0\xA0\xA0\xE4\xB9\x8E"] -} -result "expected byte sequence but character 4 was '\u4E4E' (U+004E4E)" +} -result "expected byte sequence but character 4 was '乎' (U+004E4E)" test binary-80.3 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body { testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xE4\xB9\x8E"] -} -result "expected byte sequence but character 4 was '\u4E4E' (U+004E4E)" +} -result "expected byte sequence but character 4 was '乎' (U+004E4E)" test binary-80.4 {TclGetBytesFromObj} -constraints testbytestring -returnCodes 1 -body { testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"] } -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)" diff --git a/tests/chan.test b/tests/chan.test index 3e65433..92846d5 100644 --- a/tests/chan.test +++ b/tests/chan.test @@ -48,10 +48,10 @@ test chan-4.1 {chan command: configure subcommand} -body { chan configure } -returnCodes error -result "wrong # args: should be \"chan configure channelId ?-option value ...?\"" test chan-4.2 {chan command: [Bug 800753]} -body { - chan configure stdout -eofchar \u0100 + chan configure stdout -eofchar Ā } -returnCodes error -match glob -result {bad value*} test chan-4.3 {chan command: [Bug 800753]} -body { - chan configure stdout -eofchar \u0000 + chan configure stdout -eofchar \x00 } -returnCodes error -match glob -result {bad value*} test chan-4.4 {chan command: check valid inValue, no outValue} -body { chan configure stdout -eofchar [list \x27 {}] diff --git a/tests/chanio.test b/tests/chanio.test index 04f0e3f..8dfefb7 100644 --- a/tests/chanio.test +++ b/tests/chanio.test @@ -79,7 +79,7 @@ namespace eval ::tcl::test::io { if {$argv != ""} { set f [open [lindex $argv 0]] } - chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1a + chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1A chan configure stdout -encoding binary -translation lf -buffering none chan event $f readable "foo $f" proc foo {f} { @@ -115,17 +115,17 @@ set path(test1) [makeFile {} test1] test chan-io-1.6 {Tcl_WriteChars: WriteBytes} { set f [open $path(test1) w] chan configure $f -encoding binary - chan puts -nonewline $f "a\u4e4d\0" + chan puts -nonewline $f "a乍\x00" chan close $f contents $path(test1) -} "a\x4d\x00" +} "aM\x00" test chan-io-1.7 {Tcl_WriteChars: WriteChars} { set f [open $path(test1) w] chan configure $f -encoding shiftjis - chan puts -nonewline $f "a\u4e4d\0" + chan puts -nonewline $f "a乍\x00" chan close $f contents $path(test1) -} "a\x93\xe1\x00" +} "a\x93\xE1\x00" set path(test2) [makeFile {} test2] test chan-io-1.8 {Tcl_WriteChars: WriteChars} { # This test written for SF bug #506297. @@ -138,7 +138,7 @@ test chan-io-1.8 {Tcl_WriteChars: WriteChars} { chan puts -nonewline $f [format %s%c [string repeat " " 4] 12399] chan close $f contents $path(test2) -} " \x1b\$B\$O\x1b(B" +} " \x1B\$B\$O\x1B(B" test chan-io-1.9 {Tcl_WriteChars: WriteChars} { # When closing a channel with an encoding that appends escape bytes, check # for the case where the escape bytes overflow the current IO buffer. The @@ -273,13 +273,13 @@ test chan-io-3.6 {WriteChars: (stageRead + dstWrote == 0)} { # to the beginning of that UTF-8 character and try again. # # Translate the first 16 bytes, produce 14 bytes of output, 2 left over - # (first two bytes of \uff21 in UTF-8). Given those two bytes try + # (first two bytes of A in UTF-8). Given those two bytes try # translating them again, find that no bytes are read produced, and break # to outer loop where those two bytes will have the remaining 4 bytes (the - # last byte of \uff21 plus the all of \uff22) appended. + # last byte of A plus the all of B) appended. set f [open $path(test1) w] chan configure $f -encoding shiftjis -buffersize 16 - chan puts -nonewline $f "12345678901234\uff21\uff22" + chan puts -nonewline $f "12345678901234AB" set x [list [contents $path(test1)]] chan close $f lappend x [contents $path(test1)] @@ -421,7 +421,7 @@ test chan-io-6.3 {Tcl_GetsObj: how many have we used?} -body { test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} -body { set f [open $path(test1) w] chan configure $f -translation binary - chan puts $f "\x81\u1234\0" + chan puts $f "\x81\u1234\x00" chan close $f set f [open $path(test1)] chan configure $f -translation binary @@ -432,14 +432,14 @@ test chan-io-6.4 {Tcl_GetsObj: encoding == NULL} -body { test chan-io-6.5 {Tcl_GetsObj: encoding != NULL} -body { set f [open $path(test1) w] chan configure $f -translation binary - chan puts $f "\x88\xea\x92\x9a" + chan puts $f "\x88\xEA\x92\x9A" chan close $f set f [open $path(test1)] chan configure $f -encoding shiftjis list [chan gets $f line] $line } -cleanup { chan close $f -} -result [list 2 "\u4e00\u4e01"] +} -result [list 2 "一丁"] set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" append a $a append a $a @@ -467,20 +467,20 @@ test chan-io-6.7 {Tcl_GetsObj: error in input} -constraints stdio -body { } -result {-1} test chan-io-6.8 {Tcl_GetsObj: remember if EOF is seen} -body { set f [open $path(test1) w] - chan puts $f "abcdef\x1aghijk\nwombat" + chan puts $f "abcdef\x1Aghijk\nwombat" chan close $f set f [open $path(test1)] - chan configure $f -eofchar \x1a + chan configure $f -eofchar \x1A list [chan gets $f line] $line [chan gets $f line] $line } -cleanup { chan close $f } -result {6 abcdef -1 {}} test chan-io-6.9 {Tcl_GetsObj: remember if EOF is seen} -body { set f [open $path(test1) w] - chan puts $f "abcdefghijk\nwom\u001abat" + chan puts $f "abcdefghijk\nwom\x1Abat" chan close $f set f [open $path(test1)] - chan configure $f -eofchar \x1a + chan configure $f -eofchar \x1A list [chan gets $f line] $line [chan gets $f line] $line } -cleanup { chan close $f @@ -865,7 +865,7 @@ test chan-io-6.43 {Tcl_GetsObj: input saw cr} -setup { chan configure $f -blocking 0 lappend x [chan gets $f line] $line [testchannel queuedcr $f] chan configure $f -blocking 1 - chan puts -nonewline $f "\nabcd\refg\x1a" + chan puts -nonewline $f "\nabcd\refg\x1A" lappend x [chan gets $f line] $line [testchannel queuedcr $f] lappend x [chan gets $f line] $line } -cleanup { @@ -883,7 +883,7 @@ test chan-io-6.44 {Tcl_GetsObj: input saw cr, not followed by cr} -setup { chan configure $f -blocking 0 lappend x [chan gets $f line] $line [testchannel queuedcr $f] chan configure $f -blocking 1 - chan puts -nonewline $f "abcd\refg\x1a" + chan puts -nonewline $f "abcd\refg\x1A" lappend x [chan gets $f line] $line [testchannel queuedcr $f] lappend x [chan gets $f line] $line } -cleanup { @@ -919,7 +919,7 @@ test chan-io-6.46 {Tcl_GetsObj: input saw cr, followed by just \n should give eo chan configure $f -blocking 0 lappend x [chan gets $f line] $line [testchannel queuedcr $f] chan configure $f -blocking 1 - chan puts -nonewline $f "\n\x1a" + chan puts -nonewline $f "\n\x1A" lappend x [chan gets $f line] $line [testchannel queuedcr $f] } -cleanup { chan close $f @@ -985,10 +985,10 @@ test chan-io-6.52 {Tcl_GetsObj: saw EOF character} -constraints {testchannel} -b # if (eof != NULL) set f [open $path(test1) w] chan configure $f -translation lf - chan puts -nonewline $f "123456\x1ak9012345\r" + chan puts -nonewline $f "123456\x1Ak9012345\r" chan close $f set f [open $path(test1)] - chan configure $f -eofchar \x1a + chan configure $f -eofchar \x1A list [chan gets $f] [testchannel queuedcr $f] [chan tell $f] [chan gets $f] } -cleanup { chan close $f @@ -1016,14 +1016,14 @@ test chan-io-6.55 {Tcl_GetsObj: overconverted} -body { # Tcl_ExternalToUtf(), make sure state updated set f [open $path(test1) w] chan configure $f -encoding iso2022-jp - chan puts $f "there\u4e00ok\n\u4e01more bytes\nhere" + chan puts $f "there一ok\n丁more bytes\nhere" chan close $f set f [open $path(test1)] chan configure $f -encoding iso2022-jp list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line } -cleanup { chan close $f -} -result [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"] +} -result [list 8 "there一ok" 11 "丁more bytes" 4 "here"] test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup { update variable x {} @@ -1057,19 +1057,19 @@ test chan-io-7.1 {FilterInputBytes: split up character at end of buffer} -body { # (result == TCL_CONVERT_MULTIBYTE) set f [open $path(test1) w] chan configure $f -encoding shiftjis - chan puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend" + chan puts $f "123456789012301234\nend" chan close $f set f [open $path(test1)] chan configure $f -encoding shiftjis -buffersize 16 chan gets $f } -cleanup { chan close $f -} -result "1234567890123\uff10\uff11\uff12\uff13\uff14" +} -result "123456789012301234" test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} -body { # (bufPtr->nextAdded < bufPtr->bufLength) set f [open $path(test1) w] chan configure $f -encoding binary - chan puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82" + chan puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82" chan close $f set f [open $path(test1)] chan configure $f -encoding shiftjis @@ -1082,7 +1082,7 @@ test chan-io-7.3 {FilterInputBytes: split up character at EOF} -setup { } -constraints {testchannel} -body { set f [open $path(test1) w] chan configure $f -encoding binary - chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82" + chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" chan close $f set f [open $path(test1)] chan configure $f -encoding shiftjis @@ -1091,13 +1091,13 @@ test chan-io-7.3 {FilterInputBytes: split up character at EOF} -setup { lappend x [chan gets $f line] $line } -cleanup { chan close $f -} -result [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""] +} -result [list 15 "123456789012301" 18 0 1 -1 ""] test chan-io-7.4 {FilterInputBytes: recover from split up character} -setup { variable x "" } -constraints {stdio fileevent} -body { set f [openpipe w+ $path(cat)] chan configure $f -encoding binary -buffering none - chan puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82" + chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" chan configure $f -encoding shiftjis -blocking 0 chan event $f read [namespace code { lappend x [chan gets $f line] $line [chan blocked $f] @@ -1110,7 +1110,7 @@ test chan-io-7.4 {FilterInputBytes: recover from split up character} -setup { return $x } -cleanup { chan close $f -} -result [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0] +} -result [list -1 "" 1 17 "12345678901230123" 0] test chan-io-8.1 {PeekAhead: only go to device if no more cached data} -constraints {testchannel} -body { # (bufPtr->nextPtr == NULL) @@ -1205,7 +1205,7 @@ test chan-io-8.7 {PeekAhead: cleanup} -setup { chan puts -nonewline $f "abcdefghijklmno\r" # here lappend x [chan gets $f line] $line [testchannel queuedcr $f] - chan puts -nonewline $f "\x1a" + chan puts -nonewline $f "\x1A" lappend x [chan gets $f line] $line } -cleanup { chan close $f @@ -1361,22 +1361,22 @@ test chan-io-12.4 {ReadChars: split-up char} -setup { chan configure $f -encoding shiftjis vwait [namespace which -variable x] chan configure $f -encoding binary -blocking 1 - chan puts -nonewline $f "\x7b" + chan puts -nonewline $f "\x7B" after 500 ;# Give the cat process time to catch up chan configure $f -encoding shiftjis -blocking 0 vwait [namespace which -variable x] return $x } -cleanup { chan close $f -} -result [list "123456789012345" 1 "\u672c" 0] +} -result [list "123456789012345" 1 "本" 0] test chan-io-12.5 {ReadChars: chan events on partial characters} -setup { variable x {} } -constraints {stdio fileevent} -body { set path(test1) [makeFile { chan configure stdout -encoding binary -buffering none - chan gets stdin; chan puts -nonewline "\xe7" + chan gets stdin; chan puts -nonewline "\xE7" chan gets stdin; chan puts -nonewline "\x89" - chan gets stdin; chan puts -nonewline "\xa6" + chan gets stdin; chan puts -nonewline "\xA6" } test1] set f [openpipe r+ $path(test1)] chan event $f readable [namespace code { @@ -1401,7 +1401,7 @@ test chan-io-12.5 {ReadChars: chan events on partial characters} -setup { vwait [namespace which -variable x] vwait [namespace which -variable x] lappend x [catch {chan close $f} msg] $msg -} -result "{} timeout {} timeout \u7266 {} eof 0 {}" +} -result "{} timeout {} timeout 牦 {} eof 0 {}" test chan-io-13.1 {TranslateInputEOL: cr mode} -body { set f [open $path(test1) w] @@ -1530,7 +1530,7 @@ test chan-io-13.10 {TranslateInputEOL: auto mode: \n} -body { chan close $f } -result "abcd\ndef" test chan-io-13.11 {TranslateInputEOL: EOF char} -body { - # (*chanPtr->inEofChar != '\0') + # (*chanPtr->inEofChar != '\x00') set f [open $path(test1) w] chan configure $f -translation lf chan puts -nonewline $f "abcd\ndefgh" @@ -1542,7 +1542,7 @@ test chan-io-13.11 {TranslateInputEOL: EOF char} -body { chan close $f } -result "abcd\nd" test chan-io-13.12 {TranslateInputEOL: find EOF char in src} -body { - # (*chanPtr->inEofChar != '\0') + # (*chanPtr->inEofChar != '\x00') set f [open $path(test1) w] chan configure $f -translation lf chan puts -nonewline $f "\r\n\r\n\r\nab\r\n\r\ndef\r\n\r\n\r\n" @@ -1878,7 +1878,7 @@ test chan-io-20.2 {Tcl_CreateChannel: initial settings} -constraints {win} -body list [chan configure $f -eofchar] [chan configure $f -translation] } -cleanup { chan close $f -} -result [list [list \x1a ""] {auto crlf}] +} -result [list [list \x1A ""] {auto crlf}] test chan-io-20.3 {Tcl_CreateChannel: initial settings} -constraints {unix} -body { set f [open $path(test1) w+] list [chan configure $f -eofchar] [chan configure $f -translation] @@ -3091,10 +3091,10 @@ test chan-io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} -setup { } -body { set f [open $path(test1) w] chan configure $f -translation lf - chan puts -nonewline $f hello\nthere\nand\rhere\n\x1a + chan puts -nonewline $f hello\nthere\nand\rhere\n\x1A chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A chan read $f } -cleanup { chan close $f @@ -3107,11 +3107,11 @@ test chan-io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} -setup { file delete $path(test1) } -constraints {win} -body { set f [open $path(test1) w] - chan configure $f -eofchar \x1a -translation lf + chan configure $f -translation lf -eofchar \x1A chan puts $f hello\nthere\nand\rhere chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A chan read $f } -cleanup { chan close $f @@ -3129,7 +3129,7 @@ test chan-io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} -setup { chan puts $f $s chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A set l "" lappend l [chan gets $f] lappend l [chan gets $f] @@ -3150,7 +3150,7 @@ test chan-io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} -setup { chan puts $f $s chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A set l "" lappend l [chan gets $f] lappend l [chan gets $f] @@ -3183,7 +3183,7 @@ test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} -setup { lappend l [chan eof $f] } -cleanup { chan close $f -} -result "abc def 0 \x1aghi 0 qrs 0 {} 1" +} -result "abc def 0 \x1Aghi 0 qrs 0 {} 1" test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} -setup { file delete $path(test1) set l "" @@ -3195,7 +3195,7 @@ test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} -setup { set f [open $path(test1) r] chan configure $f -translation cr -eofchar {} set x [chan gets $f] - lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"] + lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"] lappend l [chan eof $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3213,7 +3213,7 @@ test chan-io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} -setup { set f [open $path(test1) r] chan configure $f -translation crlf -eofchar {} set x [chan gets $f] - lappend l [string equal $x "abc\ndef\n\x1aghi\nqrs\n"] + lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"] lappend l [chan eof $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3228,7 +3228,7 @@ test chan-io-30.23 {Tcl_Write lf, ^Z in middle, Tcl_Read auto} -setup { chan puts $f [format abc\ndef\n%cqrs\ntuv 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3242,7 +3242,7 @@ test chan-io-30.24 {Tcl_Write lf, ^Z in middle, Tcl_Read lf} -setup { chan puts $f $c chan close $f set f [open $path(test1) r] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3256,7 +3256,7 @@ test chan-io-30.25 {Tcl_Write cr, ^Z in middle, Tcl_Read auto} -setup { chan puts $f $c chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3270,7 +3270,7 @@ test chan-io-30.26 {Tcl_Write cr, ^Z in middle, Tcl_Read cr} -setup { chan puts $f $c chan close $f set f [open $path(test1) r] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3284,7 +3284,7 @@ test chan-io-30.27 {Tcl_Write crlf, ^Z in middle, Tcl_Read auto} -setup { chan puts $f $c chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3298,7 +3298,7 @@ test chan-io-30.28 {Tcl_Write crlf, ^Z in middle, Tcl_Read crlf} -setup { chan puts $f $c chan close $f set f [open $path(test1) r] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A list [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -3649,7 +3649,7 @@ test chan-io-31.18 {Tcl_Write ^Z at end, Tcl_Gets auto} -setup { chan puts $f [format "hello\nthere\nand\rhere\n\%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan gets $f] @@ -3665,11 +3665,11 @@ test chan-io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} -setup { set l "" } -body { set f [open $path(test1) w] - chan configure $f -eofchar \x1a -translation lf + chan configure $f -translation lf -eofchar \x1A chan puts $f hello\nthere\nand\rhere chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan gets $f] @@ -3689,8 +3689,7 @@ test chan-io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a - chan configure $f -translation auto + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3708,7 +3707,7 @@ test chan-io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3738,7 +3737,7 @@ test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} -setup { lappend l [chan eof $f] } -cleanup { chan close $f -} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1" +} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1" test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} -setup { file delete $path(test1) set l "" @@ -3760,7 +3759,7 @@ test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} -setup { lappend l [chan eof $f] } -cleanup { chan close $f -} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1" +} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1" test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} -setup { file delete $path(test1) set l "" @@ -3782,7 +3781,7 @@ test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} -setup { lappend l [chan eof $f] } -cleanup { chan close $f -} -result "abc def 0 \x1aqrs 0 tuv 0 {} 1" +} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1" test chan-io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} -setup { file delete $path(test1) set l "" @@ -3792,7 +3791,7 @@ test chan-io-31.25 {Tcl_Write lf, ^Z in middle, Tcl_Gets auto} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3810,7 +3809,7 @@ test chan-io-31.26 {Tcl_Write lf, ^Z in middle, Tcl_Gets lf} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3828,7 +3827,7 @@ test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3846,7 +3845,7 @@ test chan-io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3864,7 +3863,7 @@ test chan-io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -3882,7 +3881,7 @@ test chan-io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} -setup { chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A lappend l [chan gets $f] lappend l [chan gets $f] lappend l [chan eof $f] @@ -4638,12 +4637,12 @@ test chan-io-35.6 {Tcl_Eof, eof char, lf write, auto read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4652,12 +4651,12 @@ test chan-io-35.7 {Tcl_Eof, eof char, lf write, lf read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4666,12 +4665,12 @@ test chan-io-35.8 {Tcl_Eof, eof char, cr write, auto read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4680,12 +4679,12 @@ test chan-io-35.9 {Tcl_Eof, eof char, cr write, cr read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4694,12 +4693,12 @@ test chan-io-35.10 {Tcl_Eof, eof char, crlf write, auto read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4708,12 +4707,12 @@ test chan-io-35.11 {Tcl_Eof, eof char, crlf write, crlf read} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A chan puts $f abc\ndef chan close $f set s [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A list $s [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4727,7 +4726,7 @@ test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4741,7 +4740,7 @@ test chan-io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4755,7 +4754,7 @@ test chan-io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4769,7 +4768,7 @@ test chan-io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4783,7 +4782,7 @@ test chan-io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -4797,7 +4796,7 @@ test chan-io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} -setup { chan close $f set c [file size $path(test1)] set f [open $path(test1) r] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A list $c [string length [chan read $f]] [chan eof $f] } -cleanup { chan close $f @@ -5167,27 +5166,27 @@ test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup { } -body { set f [open $path(test1) w] chan configure $f -encoding {} - chan puts -nonewline $f \xe7\x89\xa6 + chan puts -nonewline $f \xE7\x89\xA6 chan close $f set f [open $path(test1) r] chan configure $f -encoding utf-8 chan read $f } -cleanup { chan close $f -} -result \u7266 +} -result 牦 test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] chan configure $f -encoding binary - chan puts -nonewline $f \xe7\x89\xa6 + chan puts -nonewline $f \xE7\x89\xA6 chan close $f set f [open $path(test1) r] chan configure $f -encoding utf-8 chan read $f } -cleanup { chan close $f -} -result \u7266 +} -result 牦 test chan-io-39.16 {Tcl_SetChannelOption: -encoding, errors} -setup { file delete $path(test1) set f [open $path(test1) w] @@ -5201,7 +5200,7 @@ test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_ } -constraints {stdio fileevent} -body { set f [openpipe r+ $path(cat)] chan configure $f -encoding binary - chan puts -nonewline $f "\xe7" + chan puts -nonewline $f "\xE7" chan flush $f chan configure $f -encoding utf-8 -blocking 0 chan event $f readable [namespace code { lappend x [chan read $f] }] @@ -5219,7 +5218,7 @@ test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_ return $x } -cleanup { chan close $f -} -result "{} timeout {} timeout \xe7 timeout" +} -result "{} timeout {} timeout \xE7 timeout" test chan-io-39.18 {Tcl_SetChannelOption, setting read mode independently} \ -constraints {socket} -body { proc accept {s a p} {chan close $s} @@ -5533,11 +5532,11 @@ test chan-io-42.2 {Tcl_FileeventCmd: replacing} {fileevent} { } {{first script} {new script} {yet another} {}} test chan-io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} { set result {} - chan event $f r "first scr\0ipt" + chan event $f r "first scr\x00ipt" lappend result [string length [chan event $f readable]] - chan event $f r "new scr\0ipt" + chan event $f r "new scr\x00ipt" lappend result [string length [chan event $f readable]] - chan event $f r "yet ano\0ther" + chan event $f r "yet ano\x00ther" lappend result [string length [chan event $f readable]] chan event $f r "" lappend result [chan event $f readable] @@ -5983,7 +5982,7 @@ test chan-io-48.4 {lf write, testing readability, ^Z termination, auto read mode chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6007,7 +6006,7 @@ test chan-io-48.5 {lf write, testing readability, ^Z in middle, auto read mode} chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6031,7 +6030,7 @@ test chan-io-48.6 {cr write, testing readability, ^Z termination, auto read mode chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6055,7 +6054,7 @@ test chan-io-48.7 {cr write, testing readability, ^Z in middle, auto read mode} chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6079,7 +6078,7 @@ test chan-io-48.8 {crlf write, testing readability, ^Z termination, auto read mo chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation auto -eofchar \x1a + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6103,7 +6102,7 @@ test chan-io-48.9 {crlf write, testing readability, ^Z in middle, auto read mode chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation auto + chan configure $f -translation auto -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6127,7 +6126,7 @@ test chan-io-48.10 {lf write, testing readability, ^Z in middle, lf read mode} - chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation lf + chan configure $f -translation lf -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6151,7 +6150,7 @@ test chan-io-48.11 {lf write, testing readability, ^Z termination, lf read mode} chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation lf -eofchar \x1a + chan configure $f -translation lf -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6175,7 +6174,7 @@ test chan-io-48.12 {cr write, testing readability, ^Z in middle, cr read mode} - chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation cr + chan configure $f -translation cr -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6199,7 +6198,7 @@ test chan-io-48.13 {cr write, testing readability, ^Z termination, cr read mode} chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation cr -eofchar \x1a + chan configure $f -translation cr -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6223,7 +6222,7 @@ test chan-io-48.14 {crlf write, testing readability, ^Z in middle, crlf read mod chan puts -nonewline $f [format "abc\ndef\n%cfoo\nbar\n" 26] chan close $f set f [open $path(test1) r] - chan configure $f -eofchar \x1a -translation crlf + chan configure $f -translation crlf -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6247,7 +6246,7 @@ test chan-io-48.15 {crlf write, testing readability, ^Z termi, crlf read mode} - chan puts -nonewline $f [format "abc\ndef\n%c" 26] chan close $f set f [open $path(test1) r] - chan configure $f -translation crlf -eofchar \x1a + chan configure $f -translation crlf -eofchar \x1A chan event $f readable [namespace code { if {[chan eof $f]} { set x done @@ -6784,7 +6783,7 @@ set path(utf8-rp.txt) [makeFile {} utf8-rp.txt] # Create kyrillic file, use lf translation to avoid os eol issues set out [open $path(kyrillic.txt) w] chan configure $out -encoding koi8-r -translation lf -chan puts $out "\u0410\u0410" +chan puts $out "АА" chan close $out test chan-io-52.9 {TclCopyChannel & encodings} {fcopy} { # Copy kyrillic to UTF-8, using chan copy. @@ -6822,7 +6821,7 @@ test chan-io-52.10 {TclCopyChannel & encodings} {fcopy} { test chan-io-52.11 {TclCopyChannel & encodings} -setup { set f [open $path(utf8-fcopy.txt) w] fconfigure $f -encoding utf-8 -translation lf - puts $f "\u0410\u0410" + puts $f "АА" close $f } -constraints {fcopy} -body { # binary to encoding => the input has to be in utf-8 to make sense to the @@ -7496,7 +7495,7 @@ test chan-io-60.1 {writing illegal utf sequences} {fileevent testbytestring} { set out [open $path(script) w] chan puts $out "catch {load $::tcltestlib Tcltest}" chan puts $out { - chan puts [testbytestring \xe2] + chan puts [testbytestring \xE2] exit 1 } proc readit {pipe} { diff --git a/tests/clock.test b/tests/clock.test index 37c8066..2a53259 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -234,7 +234,7 @@ namespace eval ::testClock { Bias 300 \ StandardBias 0 \ DaylightBias -60 \ - StandardStart \x00\x00\x0b\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \ + StandardStart \x00\x00\x0B\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \ DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]] } @@ -36789,16 +36789,16 @@ test clock-58.1 {clock l10n - Japanese localisation} {*}{ -body { set trouble {} foreach {date jdate} { - 1872-12-31 \u897f\u66a61872\u5e7412\u670831\u65e5 - 1873-01-01 \u660e\u6cbb06\u5e7401\u670801\u65e5 - 1912-07-29 \u660e\u6cbb45\u5e7407\u670829\u65e5 - 1912-07-30 \u5927\u6b6301\u5e7407\u670830\u65e5 - 1926-12-24 \u5927\u6b6315\u5e7412\u670824\u65e5 - 1926-12-25 \u662d\u548c01\u5e7412\u670825\u65e5 - 1989-01-07 \u662d\u548c64\u5e7401\u670807\u65e5 - 1989-01-08 \u5e73\u621001\u5e7401\u670808\u65e5 - 2019-04-30 \u5e73\u621031\u5e7404\u670830\u65e5 - 2019-05-01 \u4ee4\u548c01\u5e7405\u670801\u65e5 + 1872-12-31 西暦1872年12月31日 + 1873-01-01 明治06年01月01日 + 1912-07-29 明治45年07月29日 + 1912-07-30 大正01年07月30日 + 1926-12-24 大正15年12月24日 + 1926-12-25 昭和01年12月25日 + 1989-01-07 昭和64年01月07日 + 1989-01-08 平成01年01月08日 + 2019-04-30 平成31年04月30日 + 2019-05-01 令和01年05月01日 } { set status [catch { set secs [clock scan $date \ diff --git a/tests/cmdAH.test b/tests/cmdAH.test index baa148e..5fefbeb 100644 --- a/tests/cmdAH.test +++ b/tests/cmdAH.test @@ -149,10 +149,10 @@ test cmdAH-2.6.2 {cd} -constraints {unix nonPortable} -setup { test cmdAH-2.6.3 {Tcl_CdObjCmd, bug #3118489} -setup { set dir [pwd] } -returnCodes error -body { - cd .\0 + cd .\x00 } -cleanup { cd $dir -} -match glob -result "couldn't change working directory to \".\0\": *" +} -match glob -result "couldn't change working directory to \".\x00\": *" test cmdAH-2.7 {Tcl_ConcatObjCmd} { concat } {} @@ -186,7 +186,7 @@ test cmdAH-4.5 {Tcl_EncodingObjCmd} -setup { set system [encoding system] } -body { encoding system jis0208 - encoding convertto \u4e4e + encoding convertto 乎 } -cleanup { encoding system $system } -result 8C @@ -194,7 +194,7 @@ test cmdAH-4.6 {Tcl_EncodingObjCmd} -setup { set system [encoding system] } -body { encoding system iso8859-1 - encoding convertto jis0208 \u4e4e + encoding convertto jis0208 乎 } -cleanup { encoding system $system } -result 8C @@ -211,7 +211,7 @@ test cmdAH-4.9 {Tcl_EncodingObjCmd} -setup { encoding convertfrom 8C } -cleanup { encoding system $system -} -result \u4e4e +} -result 乎 test cmdAH-4.10 {Tcl_EncodingObjCmd} -setup { set system [encoding system] } -body { @@ -219,7 +219,7 @@ test cmdAH-4.10 {Tcl_EncodingObjCmd} -setup { encoding convertfrom jis0208 8C } -cleanup { encoding system $system -} -result \u4e4e +} -result 乎 test cmdAH-4.11 {Tcl_EncodingObjCmd} -returnCodes error -body { encoding names foo } -result {wrong # args: should be "encoding names"} @@ -1221,7 +1221,7 @@ test cmdAH-24.9 {Tcl_FileObjCmd: mtime touch with non-ascii chars} -setup { set oldfile $file } -constraints unix -body { # introduce some non-ascii characters. - append file \u2022 + append file • file delete -force $file file rename $oldfile $file set mtime [file mtime $file] @@ -1246,7 +1246,7 @@ test cmdAH-24.11 {Tcl_FileObjCmd: mtime touch with non-ascii chars} -setup { set oldfile $file } -constraints win -body { # introduce some non-ascii characters. - append file \u2022 + append file • file delete -force $file file rename $oldfile $file set mtime [file mtime $file] diff --git a/tests/cmdIL.test b/tests/cmdIL.test index 83fe80e..063750c 100644 --- a/tests/cmdIL.test +++ b/tests/cmdIL.test @@ -151,17 +151,17 @@ test cmdIL-1.36 {lsort -stride and -index: Bug 2918962} { } } {{{b i g} 12345} {{d e m o} 34512} {{c o d e} 54321} {{b l a h} 94729}} test cmdIL-1.37 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { - lsort -ascii [list \0 \x7f \x80 \uffff] -} [list \0 \x7f \x80 \uffff] + lsort -ascii [list \x00 \x7F \x80 \uFFFF] +} [list \x00 \x7F \x80 \uFFFF] test cmdIL-1.38 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { - lsort -ascii -nocase [list \0 \x7f \x80 \uffff] -} [list \0 \x7f \x80 \uffff] + lsort -ascii -nocase [list \x00 \x7F \x80 \uFFFF] +} [list \x00 \x7F \x80 \uFFFF] test cmdIL-1.39 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { - lsort -ascii [list \0 \x7f \x80 \U01ffff \uffff] -} [list \0 \x7f \x80 \uffff \U01ffff] + lsort -ascii [list \x00 \x7F \x80 \U01ffff \uFFFF] +} [list \x00 \x7F \x80 \uFFFF \U01ffff] test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { - lsort -ascii -nocase [list \0 \x7f \x80 \U01ffff \uffff] -} [list \0 \x7f \x80 \uffff \U01ffff] + lsort -ascii -nocase [list \x00 \x7F \x80 \U01ffff \uFFFF] +} [list \x00 \x7F \x80 \uFFFF \U01FFFF] test cmdIL-1.41 {lsort -stride and -index} -body { lsort -stride 2 -index -2 {a 2 b 1} } -returnCodes error -result {index "-2" out of range} @@ -177,7 +177,7 @@ test cmdIL-2.1 {MergeSort and MergeLists procedures} -setup { set r 1435753299 proc rand {} { global r - set r [expr {(16807 * $r) % (0x7fffffff)}] + set r [expr {(16807 * $r) % (0x7FFFFFFF)}] } } -body { for {set i 0} {$i < 150} {incr i} { @@ -396,16 +396,16 @@ test cmdIL-4.23 {DictionaryCompare procedure, case} { } {ABcd AbCd} test cmdIL-4.24 {DictionaryCompare procedure, international characters} {hasIsoLocale} { ::tcltest::set_iso8859_1_locale - set result [lsort -dictionary "a b c A B C \xe3 \xc4"] + set result [lsort -dictionary "a b c A B C ã Ä"] ::tcltest::restore_locale set result -} "A a B b C c \xe3 \xc4" +} "A a B b C c ã Ä" test cmdIL-4.25 {DictionaryCompare procedure, international characters} {hasIsoLocale} { ::tcltest::set_iso8859_1_locale - set result [lsort -dictionary "a23\xe3 a23\xc5 a23\xe4"] + set result [lsort -dictionary "a23ã a23Å a23ä"] ::tcltest::restore_locale set result -} "a23\xe3 a23\xe4 a23\xc5" +} "a23ã a23ä a23Å" test cmdIL-4.26 {DefaultCompare procedure, signed characters} { set l [lsort [list "abc\200" "abc"]] set viewlist {} @@ -472,10 +472,10 @@ test cmdIL-4.36 {SortCompare procedure, UTF-8 with -nocase option} { scan [lsort -ascii -nocase [list \u101 \u100]] %c%c%c } {257 32 256} test cmdIL-4.37 {SortCompare procedure, UTF-8 with -nocase option} { - scan [lsort -ascii -nocase [list a\u0000a a]] %c%c%c%c%c + scan [lsort -ascii -nocase [list a\x00a a]] %c%c%c%c%c } {97 32 97 0 97} test cmdIL-4.38 {SortCompare procedure, UTF-8 with -nocase option} { - scan [lsort -ascii -nocase [list a a\u0000a]] %c%c%c%c%c + scan [lsort -ascii -nocase [list a a\x00a]] %c%c%c%c%c } {97 32 97 0 97} test cmdIL-5.1 {lsort with list style index} { diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test index ef9790f..a1cb6c2 100644 --- a/tests/cmdMZ.test +++ b/tests/cmdMZ.test @@ -299,19 +299,19 @@ test cmdMZ-4.10 {Tcl_SplitObjCmd: basic split commands} { } {]\n} test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} { apply {{} { - set x ab\000c + set x ab\x00c set y [split $x {}] binary scan $y c* z return $z }} } {97 32 98 32 0 32 99} test cmdMZ-4.12 {Tcl_SplitObjCmd: basic split commands} { - split "a0ab1b2bbb3\000c4" ab\000c + split "a0ab1b2bbb3\x00c4" ab\x00c } {{} 0 {} 1 2 {} {} 3 {} 4} test cmdMZ-4.13 {Tcl_SplitObjCmd: basic split commands} { - # if not UTF-8 aware, result is "a {} {} b qw\xe5 {} N wq" - split "a\u4e4eb qw\u5e4e\x4e wq" " \u4e4e" -} "a b qw\u5e4eN wq" + # if not UTF-8 aware, result is "a {} {} b qwå {} N wq" + split "a乎b qw幎N wq" " 乎" +} "a b qw幎N wq" # The tests for Tcl_StringObjCmd are in string.test # The tests for Tcl_SubstObjCmd are in subst.test diff --git a/tests/compExpr-old.test b/tests/compExpr-old.test index 03c5dc9..b70e65c 100644 --- a/tests/compExpr-old.test +++ b/tests/compExpr-old.test @@ -29,9 +29,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -41,19 +41,19 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -63,11 +63,11 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) set ieeeValues(littleEndian) 0 return 1 diff --git a/tests/compile.test b/tests/compile.test index 5987bfe..be68b5b 100644 --- a/tests/compile.test +++ b/tests/compile.test @@ -286,10 +286,10 @@ test compile-7.1 {TclCompileWhileCmd: command substituted test expression} { } {4} test compile-8.1 {CollectArgInfo: binary data} { - list [catch "string length \000foo" msg] $msg + list [catch "string length \x00foo" msg] $msg } {0 4} test compile-8.2 {CollectArgInfo: binary data} { - list [catch "string length foo\000" msg] $msg + list [catch "string length foo\x00" msg] $msg } {0 4} test compile-8.3 {CollectArgInfo: handle "]" at end of command properly} { set x ] diff --git a/tests/encoding.test b/tests/encoding.test index b1150c6..c8daed6 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -183,7 +183,7 @@ test encoding-7.2 {Tcl_UtfToExternalDString: big buffer} { test encoding-8.1 {Tcl_ExternalToUtf} { set f [open [file join [temporaryDirectory] dummy] w] fconfigure $f -translation binary -encoding iso8859-1 - puts -nonewline $f "ab\x8c\xc1g" + puts -nonewline $f "ab\x8C\xC1g" close $f set f [open [file join [temporaryDirectory] dummy] r] fconfigure $f -translation binary -encoding shiftjis @@ -219,7 +219,7 @@ test encoding-10.1 {Tcl_UtfToExternal} { close $f file delete [file join [temporaryDirectory] dummy] return $x -} "ab\x8c\xc1g" +} "ab\x8C\xC1g" proc viewable {str} { set res "" @@ -227,7 +227,7 @@ proc viewable {str} { if {[string is print $c] && [string is ascii $c]} { append res $c } else { - append res "\\u[format %4.4x [scan $c %c]]" + append res "\\u[format %4.4X [scan $c %c]]" } } return "$str ($res)" @@ -258,7 +258,7 @@ test encoding-11.5 {LoadEncodingFile: escape file} { } [viewable "\x1B\$B8C\x1B(B"] test encoding-11.5.1 {LoadEncodingFile: escape file} { viewable [encoding convertto iso2022-jp 乎] -} [viewable "\x1b\$B8C\x1b(B"] +} [viewable "\x1B\$B8C\x1B(B"] test encoding-11.6 {LoadEncodingFile: invalid file} -constraints {testencoding} -setup { set system [encoding system] set path [encoding dirs] @@ -283,24 +283,24 @@ test encoding-11.6 {LoadEncodingFile: invalid file} -constraints {testencoding} } -result {invalid encoding file "splat"} test encoding-11.8 {encoding: extended Unicode UTF-16} { viewable [encoding convertto utf-16le 😹] -} {=Ø9Þ (=\u00d89\u00de)} +} {=Ø9Þ (=\u00D89\u00DE)} test encoding-11.9 {encoding: extended Unicode UTF-16} { viewable [encoding convertto utf-16be 😹] -} {Ø=Þ9 (\u00d8=\u00de9)} +} {Ø=Þ9 (\u00D8=\u00DE9)} # OpenEncodingFile is fully tested by the rest of the tests in this file. test encoding-12.1 {LoadTableEncoding: normal encoding} { - set x [encoding convertto iso8859-3 \u0120] - append x [encoding convertto iso8859-3 \xD5] - append x [encoding convertfrom iso8859-3 \xD5] -} "\xD5?\u120" + set x [encoding convertto iso8859-3 Ġ] + append x [encoding convertto iso8859-3 Õ] + append x [encoding convertfrom iso8859-3 Õ] +} "Õ?Ġ" test encoding-12.2 {LoadTableEncoding: single-byte encoding} { - set x [encoding convertto iso8859-3 ab\u0120g] - append x [encoding convertfrom iso8859-3 ab\xD5g] -} "ab\xD5gab\u120g" + set x [encoding convertto iso8859-3 abĠg] + append x [encoding convertfrom iso8859-3 abÕg] +} "abÕgabĠg" test encoding-12.3 {LoadTableEncoding: multi-byte encoding} { set x [encoding convertto shiftjis ab乎g] - append x [encoding convertfrom shiftjis ab\x8c\xc1g] + append x [encoding convertfrom shiftjis ab\x8C\xC1g] } "ab\x8C\xC1gab乎g" test encoding-12.4 {LoadTableEncoding: double-byte encoding} { set x [encoding convertto jis0208 乎α] @@ -317,7 +317,7 @@ test encoding-13.1 {LoadEscapeTable} { } [viewable "ab\x1B\$B8C\x1B\$\(DD%\x1B(Bg"] test encoding-15.1 {UtfToUtfProc} { - encoding convertto utf-8 \xA3 + encoding convertto utf-8 £ } "\xC2\xA3" test encoding-15.2 {UtfToUtfProc null character output} testbytestring { binary scan [testbytestring [encoding convertto utf-8 \x00]] H* z @@ -351,8 +351,8 @@ test encoding-15.7 {UtfToUtfProc emoji character output} { list [string length $x] [string length $y] $z } {3 9 edb882eda0bdeda0bd} test encoding-15.8 {UtfToUtfProc emoji character output} { - set x \uDE02\uD83D\xE9 - set y [encoding convertto utf-8 \uDE02\uD83D\xE9] + set x \uDE02\uD83Dé + set y [encoding convertto utf-8 \uDE02\uD83Dé] binary scan $y H* z list [string length $x] [string length $y] $z } {3 8 edb882eda0bdc3a9} @@ -363,14 +363,14 @@ test encoding-15.9 {UtfToUtfProc emoji character output} { list [string length $x] [string length $y] $z } {3 7 edb882eda0bd58} test encoding-15.10 {UtfToUtfProc high surrogate character output} { - set x \uDE02\xE9 - set y [encoding convertto utf-8 \uDE02\xE9] + set x \uDE02é + set y [encoding convertto utf-8 \uDE02é] binary scan $y H* z list [string length $x] [string length $y] $z } {2 5 edb882c3a9} test encoding-15.11 {UtfToUtfProc low surrogate character output} { - set x \uDA02\xE9 - set y [encoding convertto utf-8 \uDA02\xE9] + set x \uDA02é + set y [encoding convertto utf-8 \uDA02é] binary scan $y H* z list [string length $x] [string length $y] $z } {2 5 eda882c3a9} @@ -425,7 +425,7 @@ test encoding-16.3 {Utf16ToUtfProc} -body { test encoding-16.4 {Ucs2ToUtfProc} -body { set val [encoding convertfrom ucs-2 NN] list $val [format %x [scan $val %c]] -} -result "\u4E4E 4e4e" +} -result "乎 4e4e" test encoding-16.4 {Ucs2ToUtfProc} -body { set val [encoding convertfrom ucs-2 "\xD8\xD8\xDC\xDC"] list $val [format %x [scan $val %c]] @@ -459,18 +459,18 @@ test encoding-21.1 {EscapeToUtfProc} { test encoding-22.1 {EscapeFromUtfProc} { } {} -set iso2022encData "\u001b\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\u001b(B -\u001b\$B>.@Z<jAwIU@h\$H\$7\$F;HMQ\$7\$F\$*\$j\$^\$9!#62\$lF~\$j\$^\$9\$,!\"@5\$7\$\$=;=j\$r\$4EPO?\$7\$J\$*\u001b(B -\u001b\$B\$*4j\$\$\$\$\$?\$7\$^\$9!#\$^\$?!\"BgJQ62=L\$G\$9\$,!\"=;=jJQ99\$N\$\"\$H!\"F|K\\8l%5!<%S%9It!J\u001b(B -casino_japanese@___.com \u001b\$B!K\$^\$G\$4=;=jJQ99:Q\$NO\"Mm\$r\$\$\$?\$@\$1\$J\$\$\$G\u001b(B -\u001b\$B\$7\$g\$&\$+!)\u001b(B" +set iso2022encData "\x1B\$B;d\$I\$b\$G\$O!\"%A%C%W\$49XF~;~\$K\$4EPO?\$\$\$?\$@\$\$\$?\$4=;=j\$r%-%c%C%7%e%\"%&%H\$N:]\$N\x1B(B +\x1B\$B>.@Z<jAwIU@h\$H\$7\$F;HMQ\$7\$F\$*\$j\$^\$9!#62\$lF~\$j\$^\$9\$,!\"@5\$7\$\$=;=j\$r\$4EPO?\$7\$J\$*\x1B(B +\x1B\$B\$*4j\$\$\$\$\$?\$7\$^\$9!#\$^\$?!\"BgJQ62=L\$G\$9\$,!\"=;=jJQ99\$N\$\"\$H!\"F|K\\8l%5!<%S%9It!J\x1B(B +casino_japanese@___.com \x1B\$B!K\$^\$G\$4=;=jJQ99:Q\$NO\"Mm\$r\$\$\$?\$@\$1\$J\$\$\$G\x1B(B +\x1B\$B\$7\$g\$&\$+!)\x1B(B" set iso2022uniData [encoding convertfrom iso2022-jp $iso2022encData] -set iso2022uniData2 "\u79c1\u3069\u3082\u3067\u306f\u3001\u30c1\u30c3\u30d7\u3054\u8cfc\u5165\u6642\u306b\u3054\u767b\u9332\u3044\u305f\u3060\u3044\u305f\u3054\u4f4f\u6240\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\u30a2\u30a6\u30c8\u306e\u969b\u306e -\u5c0f\u5207\u624b\u9001\u4ed8\u5148\u3068\u3057\u3066\u4f7f\u7528\u3057\u3066\u304a\u308a\u307e\u3059\u3002\u6050\u308c\u5165\u308a\u307e\u3059\u304c\u3001\u6b63\u3057\u3044\u4f4f\u6240\u3092\u3054\u767b\u9332\u3057\u306a\u304a -\u304a\u9858\u3044\u3044\u305f\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u5927\u5909\u6050\u7e2e\u3067\u3059\u304c\u3001\u4f4f\u6240\u5909\u66f4\u306e\u3042\u3068\u3001\u65e5\u672c\u8a9e\u30b5\u30fc\u30d3\u30b9\u90e8\uff08 -\u0063\u0061\u0073\u0069\u006e\u006f\u005f\u006a\u0061\u0070\u0061\u006e\u0065\u0073\u0065\u0040\u005f\u005f\u005f\u002e\u0063\u006f\u006d\u0020\uff09\u307e\u3067\u3054\u4f4f\u6240\u5909\u66f4\u6e08\u306e\u9023\u7d61\u3092\u3044\u305f\u3060\u3051\u306a\u3044\u3067 -\u3057\u3087\u3046\u304b\uff1f" +set iso2022uniData2 "私どもでは、チップご購入時にご登録いただいたご住所をキャッシュアウトの際の +小切手送付先として使用しております。恐れ入りますが、正しい住所をご登録しなお +お願いいたします。また、大変恐縮ですが、住所変更のあと、日本語サービス部( +casino_japanese@___.com )までご住所変更済の連絡をいただけないで +しょうか?" cd [temporaryDirectory] set fid [open iso2022.txt w] @@ -539,7 +539,7 @@ test encoding-24.2 {EscapeFreeProc on open channels} {exec} { set env(TCL_FINALIZE_ON_EXIT) 1 exit }] -} "ab\x1B\$B8C\x1B\$(DD%\x1B(Bg (ab\\u001b\$B8C\\u001b\$(DD%\\u001b(Bg)" +} "ab\x1B\$B8C\x1B\$(DD%\x1B(Bg (ab\\u001B\$B8C\\u001B\$(DD%\\u001B(Bg)" test encoding-24.3 {EscapeFreeProc on open channels} {stdio} { # Bug #219314 - if we don't free escape encodings correctly on channel # closure, we go boom @@ -554,7 +554,7 @@ test encoding-24.3 {EscapeFreeProc on open channels} {stdio} { close $f removeFile iso2022.tcl list $count [viewable $line] -} [list 3 "乎乞也 (\\u4e4e\\u4e5e\\u4e5f)"] +} [list 3 "乎乞也 (\\u4E4E\\u4E5E\\u4E5F)"] test encoding-24.4 {Parse valid or invalid utf-8} { string length [encoding convertfrom utf-8 "\xC0\x80"] @@ -632,20 +632,20 @@ proc foreach-jisx0208 {varName command} { } proc gen-jisx0208-euc-jp {code} { binary format cc \ - [expr {($code >> 8) | 0x80}] [expr {($code & 0xff) | 0x80}] + [expr {($code >> 8) | 0x80}] [expr {($code & 0xFF) | 0x80}] } proc gen-jisx0208-iso2022-jp {code} { binary format a3cca3 \ - "\x1b\$B" [expr {$code >> 8}] [expr {$code & 0xff}] "\x1b(B" + "\x1B\$B" [expr {$code >> 8}] [expr {$code & 0xFF}] "\x1B(B" } proc gen-jisx0208-cp932 {code} { set c1 [expr {($code >> 8) | 0x80}] set c2 [expr {($code & 0xff)| 0x80}] if {$c1 % 2} { - set c1 [expr {($c1 >> 1) + ($c1 < 0xdf ? 0x31 : 0x71)}] - incr c2 [expr {- (0x60 + ($c2 < 0xe0))}] + set c1 [expr {($c1 >> 1) + ($c1 < 0xDF ? 0x31 : 0x71)}] + incr c2 [expr {- (0x60 + ($c2 < 0xE0))}] } else { - set c1 [expr {($c1 >> 1) + ($c1 < 0xdf ? 0x30 : 0x70)}] + set c1 [expr {($c1 >> 1) + ($c1 < 0xDF ? 0x30 : 0x70)}] incr c2 -2 } binary format cc $c1 $c2 diff --git a/tests/exec.test b/tests/exec.test index 412cd4c..6e4718a 100644 --- a/tests/exec.test +++ b/tests/exec.test @@ -169,19 +169,19 @@ test exec-2.6 {redirecting input from immediate source, with UTF} -setup { encoding system iso8859-1 proc quotenonascii s { regsub -all {\[|\\|\]} $s {\\&} s - regsub -all "\[\u007f-\uffff\]" $s \ - {[apply {c {format {\u%04x} [scan $c %c]}} &]} s + regsub -all "\[\x7F-\xFF\]" $s \ + {[apply {c {format {\x%02X} [scan $c %c]}} &]} s return [subst -novariables $s] } } -constraints {exec} -body { - # If this fails, it may give back: "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1" + # If this fails, it may give back: "\xC3\xA9\xC3\xA0\xC3\xBC\xC3\xB1" # If it does, this means that the UTF -> external conversion did not occur # before writing out the temp file. - quotenonascii [exec [interpreter] $path(cat) << "\uE9\uE0\uFC\uF1"] + quotenonascii [exec [interpreter] $path(cat) << "\xE9\xE0\xFC\xF1"] } -cleanup { encoding system $sysenc rename quotenonascii {} -} -result {\u00e9\u00e0\u00fc\u00f1} +} -result {\xE9\xE0\xFC\xF1} # I/O redirection: output to file. diff --git a/tests/execute.test b/tests/execute.test index f22747c..d86ad0e 100644 --- a/tests/execute.test +++ b/tests/execute.test @@ -1066,7 +1066,7 @@ test execute-9.1 {Interp result resetting [Bug 1522803]} { } SUCCESS test execute-10.1 {TclExecuteByteCode, INST_CONCAT1, bytearrays} { - apply {s {binary scan $s c x; list $x [scan $s$s %c%c]}} \u0130 + apply {s {binary scan $s c x; list $x [scan $s$s %c%c]}} İ } {48 {304 304}} test execute-10.2 {Bug 2802881} -setup { interp create child diff --git a/tests/expr-old.test b/tests/expr-old.test index 50fbba7..676443a 100644 --- a/tests/expr-old.test +++ b/tests/expr-old.test @@ -35,9 +35,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -47,19 +47,19 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -69,11 +69,11 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) set ieeeValues(littleEndian) 0 return 1 diff --git a/tests/expr.test b/tests/expr.test index 8d2f668..32706d9 100644 --- a/tests/expr.test +++ b/tests/expr.test @@ -33,9 +33,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -45,21 +45,21 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) - binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\xFF d \ ieeeValues(-NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -69,13 +69,13 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) - binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-NaN) set ieeeValues(littleEndian) 0 return 1 @@ -351,7 +351,7 @@ test expr-8.11 {CompileEqualityExpr: error compiling equality arm} -body { expr 2!=x } -returnCodes error -match glob -result * test expr-8.12 {CompileBitAndExpr: equality expr} {expr {"a"eq"a"}} 1 -test expr-8.13 {CompileBitAndExpr: equality expr} {expr {"\374" eq [set s \u00fc]}} 1 +test expr-8.13 {CompileBitAndExpr: equality expr} {expr {"\374" eq [set s \xFC]}} 1 test expr-8.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0 test expr-8.15 {CompileBitAndExpr: equality expr} {expr 2.0eq2} 0 test expr-8.16 {CompileBitAndExpr: equality expr} {expr 3.2ne2.2} 1 diff --git a/tests/fCmd.test b/tests/fCmd.test index 6a909f8..d1d1930 100644 --- a/tests/fCmd.test +++ b/tests/fCmd.test @@ -271,7 +271,7 @@ test fCmd-3.14 {FileCopyRename: FileBasename fails} -setup { file mkdir td1 file rename ~_totally_bogus_user td1 } -result {user "_totally_bogus_user" doesn't exist} -test fCmd-3.15 {FileCopyRename: source[0] == '\0'} -setup { +test fCmd-3.15 {FileCopyRename: source[0] == '\x00'} -setup { cleanup } -constraints {notRoot unixOrWin} -returnCodes error -body { file mkdir td1 @@ -313,7 +313,7 @@ test fCmd-4.4 {TclFileMakeDirsCmd: Tcl_TranslateFileName fails} -setup { } -constraints {notRoot} -returnCodes error -body { file mkdir ~_totally_bogus_user } -result {user "_totally_bogus_user" doesn't exist} -test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -setup { +test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\x00'} -setup { cleanup } -constraints {notRoot} -returnCodes error -body { file mkdir "" diff --git a/tests/fileSystemEncoding.test b/tests/fileSystemEncoding.test index 848b570..c9d36d2 100644 --- a/tests/fileSystemEncoding.test +++ b/tests/fileSystemEncoding.test @@ -13,7 +13,7 @@ namespace eval ::tcl::test::fileSystemEncoding { namespace import -force ::tcltest::* } - variable fname1 \u767b\u9e1b\u9d72\u6a13 + variable fname1 登鸛鵲樓 proc autopath {} { global auto_path diff --git a/tests/format.test b/tests/format.test index 9a62193..41918b2 100644 --- a/tests/format.test +++ b/tests/format.test @@ -105,17 +105,17 @@ test format-2.4 {string formatting} { format "%s %s %% %c %s" abcd {This is a very long test string.} 120 x } {abcd This is a very long test string. % x x} test format-2.5 {string formatting, embedded nulls} { - format "%10s" abc\0def -} " abc\0def" + format "%10s" abc\x00def +} " abc\x00def" test format-2.6 {string formatting, international chars} { - format "%10s" abc\ufeffdef -} " abc\ufeffdef" + format "%10s" abc\uFEFFdef +} " abc\uFEFFdef" test format-2.7 {string formatting, international chars} { - format "%.5s" abc\ufeffdef -} "abc\ufeffd" + format "%.5s" abc\uFEFFdef +} "abc\uFEFFd" test format-2.8 {string formatting, international chars} { - format "foo\ufeffbar%s" baz -} "foo\ufeffbarbaz" + format "foo\uFEFFbar%s" baz +} "foo\uFEFFbarbaz" test format-2.9 {string formatting, width} { format "a%5sa" f } "a fa" @@ -143,13 +143,19 @@ test format-2.16 {string formatting, width and precision} { test format-2.17 {string formatting, width and precision} { format "a%5.7sa" foobarbaz } "afoobarba" +test format-2.18 {string formatting, surrogates} { + format "\uD83D%s" \uDE02 +} \uD83D\uDE02 +test format-2.19 {string formatting, surrogates} { + format "%s\uDE02" \uD83D +} \uD83D\uDE02 test format-3.1 {Tcl_FormatObjCmd: character formatting} { format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 65 65 65 65 65 65 3 65 -4 65 } "|A|A|A|A|A | A| A|A |" test format-3.2 {Tcl_FormatObjCmd: international character formatting} { - format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xa2 0x4e4e 0x25a 0xc3 0xff08 0 3 0x6575 -4 0x4e4f -} "|\ua2|\u4e4e|\u25a|\uc3|\uff08 | \0| \u6575|\u4e4f |" + format "|%c|%0c|%-1c|%1c|%-6c|%6c|%*c|%*c|" 0xA2 0x4E4E 0x25A 0xC3 0xFF08 0 3 0x6575 -4 0x4E4F +} "|¢|乎|ɚ|Ã|( | \x00| 敵|乏 |" test format-4.1 {e and f formats} {eformat} { format "%e %e %e %e" 34.2e12 68.514 -.125 -16000. .000053 diff --git a/tests/http.test b/tests/http.test index ff9fb78..2fd5af4 100644 --- a/tests/http.test +++ b/tests/http.test @@ -42,7 +42,7 @@ proc bgerror {args} { # Name resolution is often a problem on OSX; not focus of HTTP package anyway. # Also a problem on other platforms for http-4.14 (test with bad port number). set HOST localhost -set bindata "This is binary data\x0d\x0amore\x0dmore\x0amore\x00null" +set bindata "This is binary data\x0D\x0Amore\x0Dmore\x0Amore\x00null" catch {unset data} # Ensure httpd file exists @@ -620,12 +620,12 @@ test http-5.3 {http::formatQuery} { http::formatQuery lines "line1\nline2\nline3" } {lines=line1%0D%0Aline2%0D%0Aline3} test http-5.4 {http::formatQuery} { - http::formatQuery name1 ~bwelch name2 \xa1\xa2\xa2 + http::formatQuery name1 ~bwelch name2 ¡¢¢ } {name1=~bwelch&name2=%C2%A1%C2%A2%C2%A2} test http-5.5 {http::formatQuery} { set enc [http::config -urlencoding] http::config -urlencoding iso8859-1 - set res [http::formatQuery name1 ~bwelch name2 \xa1\xa2\xa2] + set res [http::formatQuery name1 ~bwelch name2 ¡¢¢] http::config -urlencoding $enc set res } {name1=~bwelch&name2=%A1%A2%A2} @@ -650,24 +650,24 @@ test http-7.1 {http::mapReply} { test http-7.2 {http::mapReply} { # RFC 2718 specifies that we pass urlencoding on utf-8 chars by default, # so make sure this gets converted to utf-8 then urlencoded. - http::mapReply "\u2208" + http::mapReply "∈" } {%E2%88%88} test http-7.3 {http::formatQuery} -setup { set enc [http::config -urlencoding] } -returnCodes error -body { # this would be reverting to http <=2.4 behavior http::config -urlencoding "" - http::mapReply "\u2208" + http::mapReply "∈" } -cleanup { http::config -urlencoding $enc -} -result "can't read \"formMap(\u2208)\": no such element in array" +} -result "can't read \"formMap(∈)\": no such element in array" test http-7.4 {http::formatQuery} -setup { set enc [http::config -urlencoding] } -body { # this would be reverting to http <=2.4 behavior w/o errors # (unknown chars become '?') http::config -urlencoding "iso8859-1" - http::mapReply "\u2208" + http::mapReply "∈" } -cleanup { http::config -urlencoding $enc } -result {%3F} @@ -715,37 +715,37 @@ test http-idna-2.1 {puny encode: functional test} { ::tcl::idna puny encode abc } abc- test http-idna-2.2 {puny encode: functional test} { - ::tcl::idna puny encode a\u20acb\u20acc + ::tcl::idna puny encode a€b€c } abc-k50ab test http-idna-2.3 {puny encode: functional test} { ::tcl::idna puny encode ABC } ABC- test http-idna-2.4 {puny encode: functional test} { - ::tcl::idna puny encode A\u20ACB\u20ACC + ::tcl::idna puny encode A€B€C } ABC-k50ab test http-idna-2.5 {puny encode: functional test} { ::tcl::idna puny encode ABC 0 } abc- test http-idna-2.6 {puny encode: functional test} { - ::tcl::idna puny encode A\u20ACB\u20ACC 0 + ::tcl::idna puny encode A€B€C 0 } abc-k50ab test http-idna-2.7 {puny encode: functional test} { ::tcl::idna puny encode ABC 1 } ABC- test http-idna-2.8 {puny encode: functional test} { - ::tcl::idna puny encode A\u20ACB\u20ACC 1 + ::tcl::idna puny encode A€B€C 1 } ABC-k50ab test http-idna-2.9 {puny encode: functional test} { ::tcl::idna puny encode abc 0 } abc- test http-idna-2.10 {puny encode: functional test} { - ::tcl::idna puny encode a\u20ACb\u20ACc 0 + ::tcl::idna puny encode a€b€c 0 } abc-k50ab test http-idna-2.11 {puny encode: functional test} { ::tcl::idna puny encode abc 1 } ABC- test http-idna-2.12 {puny encode: functional test} { - ::tcl::idna puny encode a\u20ACb\u20ACc 1 + ::tcl::idna puny encode a€b€c 1 } ABC-k50ab test http-idna-2.13 {puny encode: edge cases} { ::tcl::idna puny encode "" @@ -875,43 +875,43 @@ test http-idna-3.1 {puny decode: functional test} { } abc test http-idna-3.2 {puny decode: functional test} { ::tcl::idna puny decode abc-k50ab -} a\u20acb\u20acc +} a€b€c test http-idna-3.3 {puny decode: functional test} { ::tcl::idna puny decode ABC- } ABC test http-idna-3.4 {puny decode: functional test} { ::tcl::idna puny decode ABC-k50ab -} A\u20ACB\u20ACC +} A€B€C test http-idna-3.5 {puny decode: functional test} { ::tcl::idna puny decode ABC-K50AB -} A\u20ACB\u20ACC +} A€B€C test http-idna-3.6 {puny decode: functional test} { ::tcl::idna puny decode abc-K50AB -} a\u20ACb\u20ACc +} a€b€c test http-idna-3.7 {puny decode: functional test} { ::tcl::idna puny decode ABC- 0 } abc test http-idna-3.8 {puny decode: functional test} { ::tcl::idna puny decode ABC-K50AB 0 -} a\u20ACb\u20ACc +} a€b€c test http-idna-3.9 {puny decode: functional test} { ::tcl::idna puny decode ABC- 1 } ABC test http-idna-3.10 {puny decode: functional test} { ::tcl::idna puny decode ABC-K50AB 1 -} A\u20ACB\u20ACC +} A€B€C test http-idna-3.11 {puny decode: functional test} { ::tcl::idna puny decode abc- 0 } abc test http-idna-3.12 {puny decode: functional test} { ::tcl::idna puny decode abc-k50ab 0 -} a\u20ACb\u20ACc +} a€b€c test http-idna-3.13 {puny decode: functional test} { ::tcl::idna puny decode abc- 1 } ABC test http-idna-3.14 {puny decode: functional test} { ::tcl::idna puny decode abc-k50ab 1 -} A\u20ACB\u20ACC +} A€B€C test http-idna-3.15 {puny decode: edge cases and errors} { # Is this case actually correct? binary encode hex [encoding convertto utf-8 [::tcl::idna puny decode abc]] @@ -1045,16 +1045,16 @@ test http-idna-4.1 {IDNA encoding} { ::tcl::idna encode abc.def } abc.def test http-idna-4.2 {IDNA encoding} { - ::tcl::idna encode a\u20acb\u20acc.def + ::tcl::idna encode a€b€c.def } xn--abc-k50ab.def test http-idna-4.3 {IDNA encoding} { - ::tcl::idna encode def.a\u20acb\u20acc + ::tcl::idna encode def.a€b€c } def.xn--abc-k50ab test http-idna-4.4 {IDNA encoding} { ::tcl::idna encode ABC.DEF } ABC.DEF test http-idna-4.5 {IDNA encoding} { - ::tcl::idna encode A\u20acB\u20acC.def + ::tcl::idna encode A€B€C.def } xn--ABC-k50ab.def test http-idna-4.6 {IDNA encoding: invalid edge case} { # Should this be an error? @@ -1084,7 +1084,7 @@ test http-idna-4.9.1 {IDNA encoding: max lengths from RFC 5890} { } {IDNA OVERLONG_PART xn--989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c} unset overlong test http-idna-4.10 {IDNA encoding: edge cases} { - ::tcl::idna encode pass\u00e9.example.com + ::tcl::idna encode passé.example.com } xn--pass-epa.example.com test http-idna-5.1 {IDNA decoding} { diff --git a/tests/init.test b/tests/init.test index 0074625..4acad3d 100644 --- a/tests/init.test +++ b/tests/init.test @@ -155,7 +155,7 @@ foreach arg [subst -nocommands -novariables { error stack cannot be uniquely determined. foo bar "} - {argument that contains non-ASCII character, \u20ac, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library} + {argument that contains non-ASCII character, €, and which is of such great length that it will be longer than 150 bytes so it will be truncated by the Tcl C library} }] { ;# emacs needs -> " test init-4.$count.0 {::errorInfo produced by [unknown]} -setup { diff --git a/tests/io.test b/tests/io.test index 0d75116..e0a2389 100644 --- a/tests/io.test +++ b/tests/io.test @@ -108,17 +108,17 @@ set path(test1) [makeFile {} test1] test io-1.6 {Tcl_WriteChars: WriteBytes} { set f [open $path(test1) w] fconfigure $f -encoding binary - puts -nonewline $f "a\u4e4d\0" + puts -nonewline $f "a乍\x00" close $f contents $path(test1) -} "a\x4d\x00" +} "a\x4D\x00" test io-1.7 {Tcl_WriteChars: WriteChars} { set f [open $path(test1) w] fconfigure $f -encoding shiftjis - puts -nonewline $f "a\u4e4d\0" + puts -nonewline $f "a乍\x00" close $f contents $path(test1) -} "a\x93\xe1\x00" +} "a\x93\xE1\x00" set path(test2) [makeFile {} test2] test io-1.8 {Tcl_WriteChars: WriteChars} { # This test written for SF bug #506297. @@ -132,7 +132,7 @@ test io-1.8 {Tcl_WriteChars: WriteChars} { puts -nonewline $f [format %s%c [string repeat " " 4] 12399] close $f contents $path(test2) -} " \x1b\$B\$O\x1b(B" +} " \x1B\$B\$O\x1B(B" test io-1.9 {Tcl_WriteChars: WriteChars} { # When closing a channel with an encoding that appends @@ -295,14 +295,14 @@ test io-3.6 {WriteChars: (stageRead + dstWrote == 0)} { # in src to the beginning of that UTF-8 character and try again. # # Translate the first 16 bytes, produce 14 bytes of output, 2 left over - # (first two bytes of \uff21 in UTF-8). Given those two bytes try + # (first two bytes of A in UTF-8). Given those two bytes try # translating them again, find that no bytes are read produced, and break # to outer loop where those two bytes will have the remaining 4 bytes - # (the last byte of \uff21 plus the all of \uff22) appended. + # (the last byte of A plus the all of B) appended. set f [open $path(test1) w] fconfigure $f -encoding shiftjis -buffersize 16 - puts -nonewline $f "12345678901234\uff21\uff22" + puts -nonewline $f "12345678901234AB" set x [list [contents $path(test1)]] close $f lappend x [contents $path(test1)] @@ -451,7 +451,7 @@ test io-6.3 {Tcl_GetsObj: how many have we used?} { test io-6.4 {Tcl_GetsObj: encoding == NULL} { set f [open $path(test1) w] fconfigure $f -translation binary - puts $f "\x81\u1234\0" + puts $f "\x81\u1234\x00" close $f set f [open $path(test1)] fconfigure $f -translation binary @@ -462,14 +462,14 @@ test io-6.4 {Tcl_GetsObj: encoding == NULL} { test io-6.5 {Tcl_GetsObj: encoding != NULL} { set f [open $path(test1) w] fconfigure $f -translation binary - puts $f "\x88\xea\x92\x9a" + puts $f "\x88\xEA\x92\x9A" close $f set f [open $path(test1)] fconfigure $f -encoding shiftjis set x [list [gets $f line] $line] close $f set x -} [list 2 "\u4e00\u4e01"] +} [list 2 "一丁"] set a "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" append a $a append a $a @@ -509,7 +509,7 @@ test io-6.8 {Tcl_GetsObj: remember if EOF is seen} { } {6 abcdef -1 {}} test io-6.9 {Tcl_GetsObj: remember if EOF is seen} { set f [open $path(test1) w] - puts $f "abcdefghijk\nwom\u001abat" + puts $f "abcdefghijk\nwom\x1Abat" close $f set f [open $path(test1)] fconfigure $f -eofchar \x1A @@ -1052,14 +1052,14 @@ test io-6.55 {Tcl_GetsObj: overconverted} { set f [open $path(test1) w] fconfigure $f -encoding iso2022-jp - puts $f "there\u4e00ok\n\u4e01more bytes\nhere" + puts $f "there一ok\n丁more bytes\nhere" close $f set f [open $path(test1)] fconfigure $f -encoding iso2022-jp set x [list [gets $f line] $line [gets $f line] $line [gets $f line] $line] close $f set x -} [list 8 "there\u4e00ok" 11 "\u4e01more bytes" 4 "here"] +} [list 8 "there一ok" 11 "丁more bytes" 4 "here"] test io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} {stdio fileevent} { update set f [open "|[list [interpreter] $path(cat)]" w+] @@ -1086,20 +1086,20 @@ test io-7.1 {FilterInputBytes: split up character at end of buffer} { set f [open $path(test1) w] fconfigure $f -encoding shiftjis - puts $f "1234567890123\uff10\uff11\uff12\uff13\uff14\nend" + puts $f "123456789012301234\nend" close $f set f [open $path(test1)] fconfigure $f -encoding shiftjis -buffersize 16 set x [gets $f] close $f set x -} "1234567890123\uff10\uff11\uff12\uff13\uff14" +} "123456789012301234" test io-7.2 {FilterInputBytes: split up character in middle of buffer} { # (bufPtr->nextAdded < bufPtr->bufLength) set f [open $path(test1) w] fconfigure $f -encoding binary - puts -nonewline $f "1234567890\n123\x82\x4f\x82\x50\x82" + puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82" close $f set f [open $path(test1)] fconfigure $f -encoding shiftjis @@ -1110,7 +1110,7 @@ test io-7.2 {FilterInputBytes: split up character in middle of buffer} { test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} { set f [open $path(test1) w] fconfigure $f -encoding binary - puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82" + puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" close $f set f [open $path(test1)] fconfigure $f -encoding shiftjis @@ -1119,11 +1119,11 @@ test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} { lappend x [gets $f line] $line close $f set x -} [list 15 "1234567890123\uff10\uff11" 18 0 1 -1 ""] +} [list 15 "123456789012301" 18 0 1 -1 ""] test io-7.4 {FilterInputBytes: recover from split up character} {stdio fileevent} { set f [open "|[list [interpreter] $path(cat)]" w+] fconfigure $f -encoding binary -buffering none - puts -nonewline $f "1234567890123\x82\x4f\x82\x50\x82" + puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" fconfigure $f -encoding shiftjis -blocking 0 fileevent $f read [namespace code "ready $f"] variable x {} @@ -1138,7 +1138,7 @@ test io-7.4 {FilterInputBytes: recover from split up character} {stdio fileevent vwait [namespace which -variable x] close $f set x -} [list -1 "" 1 17 "1234567890123\uff10\uff11\uff12\uff13" 0] +} [list -1 "" 1 17 "12345678901230123" 0] test io-8.1 {PeekAhead: only go to device if no more cached data} {testchannel} { # (bufPtr->nextPtr == NULL) @@ -1415,19 +1415,19 @@ test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} { fconfigure $f -encoding shiftjis vwait [namespace which -variable x] fconfigure $f -encoding binary -blocking 1 - puts -nonewline $f "\x7b" + puts -nonewline $f "\x7B" after 500 ;# Give the cat process time to catch up fconfigure $f -encoding shiftjis -blocking 0 vwait [namespace which -variable x] close $f set x -} [list "123456789012345" 1 "\u672c" 0] +} [list "123456789012345" 1 "本" 0] test io-12.5 {ReadChars: fileevents on partial characters} {stdio fileevent} { set path(test1) [makeFile { fconfigure stdout -encoding binary -buffering none - gets stdin; puts -nonewline "\xe7" + gets stdin; puts -nonewline "\xE7" gets stdin; puts -nonewline "\x89" - gets stdin; puts -nonewline "\xa6" + gets stdin; puts -nonewline "\xA6" } test1] set f [open "|[list [interpreter] $path(test1)]" r+] fileevent $f readable [namespace code { @@ -1454,7 +1454,7 @@ test io-12.5 {ReadChars: fileevents on partial characters} {stdio fileevent} { vwait [namespace which -variable x] lappend x [catch {close $f} msg] $msg set x -} "{} timeout {} timeout \u7266 {} eof 0 {}" +} "{} timeout {} timeout 牦 {} eof 0 {}" test io-12.6 {ReadChars: too many chars read} { proc driver {cmd args} { variable buffer @@ -1464,7 +1464,7 @@ test io-12.6 {ReadChars: too many chars read} { initialize { set index($chan) 0 set buffer($chan) [encoding convertto utf-8 \ - [string repeat \uBEEF 20][string repeat . 20]] + [string repeat 뻯 20][string repeat . 20]] return {initialize finalize watch read} } finalize { @@ -1497,7 +1497,7 @@ test io-12.7 {ReadChars: too many chars read [bc5b790099]} { initialize { set index($chan) 0 set buffer($chan) [encoding convertto utf-8 \ - [string repeat \uBEEF 10]....\uBEEF] + [string repeat 뻯 10]....뻯] return {initialize finalize watch read} } finalize { @@ -1524,7 +1524,7 @@ test io-12.7 {ReadChars: too many chars read [bc5b790099]} { test io-12.8 {ReadChars: multibyte chars split} { set f [open $path(test1) w] fconfigure $f -translation binary - puts -nonewline $f [string repeat a 9]\xc2\xa0 + puts -nonewline $f [string repeat a 9]\xC2\xA0 close $f set f [open $path(test1)] fconfigure $f -encoding utf-8 -buffersize 10 @@ -1535,7 +1535,7 @@ test io-12.8 {ReadChars: multibyte chars split} { test io-12.9 {ReadChars: multibyte chars split} { set f [open $path(test1) w] fconfigure $f -translation binary - puts -nonewline $f [string repeat a 9]\xc2 + puts -nonewline $f [string repeat a 9]\xC2 close $f set f [open $path(test1)] fconfigure $f -encoding utf-8 -buffersize 10 @@ -1546,7 +1546,7 @@ test io-12.9 {ReadChars: multibyte chars split} { test io-12.10 {ReadChars: multibyte chars split} { set f [open $path(test1) w] fconfigure $f -translation binary - puts -nonewline $f [string repeat a 9]\xc2 + puts -nonewline $f [string repeat a 9]\xC2 close $f set f [open $path(test1)] fconfigure $f -encoding utf-8 -buffersize 11 @@ -1732,7 +1732,7 @@ test io-13.10 {TranslateInputEOL: auto mode: \n} { set x } "abcd\ndef" test io-13.11 {TranslateInputEOL: EOF char} { - # (*chanPtr->inEofChar != '\0') + # (*chanPtr->inEofChar != '\x00') set f [open $path(test1) w] fconfigure $f -translation lf @@ -1745,7 +1745,7 @@ test io-13.11 {TranslateInputEOL: EOF char} { set x } "abcd\nd" test io-13.12 {TranslateInputEOL: find EOF char in src} { - # (*chanPtr->inEofChar != '\0') + # (*chanPtr->inEofChar != '\x00') set f [open $path(test1) w] fconfigure $f -translation lf @@ -3202,7 +3202,7 @@ test io-30.16 {Tcl_Write ^Z at end, Tcl_Read auto} { puts -nonewline $f hello\nthere\nand\rhere\n\x1A close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set c [read $f] close $f set c @@ -3214,11 +3214,11 @@ here test io-30.17 {Tcl_Write, implicit ^Z at end, Tcl_Read auto} {win} { file delete $path(test1) set f [open $path(test1) w] - fconfigure $f -eofchar \x1A -translation lf + fconfigure $f -translation lf -eofchar \x1A puts $f hello\nthere\nand\rhere close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set c [read $f] close $f set c @@ -3235,7 +3235,7 @@ test io-30.18 {Tcl_Write, ^Z in middle, Tcl_Read auto} { puts $f $s close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -3255,7 +3255,7 @@ test io-30.19 {Tcl_Write, ^Z no newline in middle, Tcl_Read auto} { puts $f $s close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -3736,7 +3736,7 @@ test io-31.18 {Tcl_Write ^Z at end, Tcl_Gets auto} { puts $f $s close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -3751,11 +3751,11 @@ test io-31.18 {Tcl_Write ^Z at end, Tcl_Gets auto} { test io-31.19 {Tcl_Write, implicit ^Z at end, Tcl_Gets auto} { file delete $path(test1) set f [open $path(test1) w] - fconfigure $f -eofchar \x1A -translation lf + fconfigure $f -translation lf -eofchar \x1A puts $f hello\nthere\nand\rhere close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -3775,8 +3775,7 @@ test io-31.20 {Tcl_Write, ^Z in middle, Tcl_Gets auto, eofChar} { puts $f $s close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A - fconfigure $f -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -3794,7 +3793,7 @@ test io-31.21 {Tcl_Write, no newline ^Z in middle, Tcl_Gets auto, eofChar} { puts $f $s close $f set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A set l "" lappend l [gets $f] lappend l [gets $f] @@ -5479,26 +5478,26 @@ test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} { file delete $path(test1) set f [open $path(test1) w] fconfigure $f -encoding {} - puts -nonewline $f \xe7\x89\xa6 + puts -nonewline $f \xE7\x89\xA6 close $f set f [open $path(test1) r] fconfigure $f -encoding utf-8 set x [read $f] close $f set x -} \u7266 +} 牦 test io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} { file delete $path(test1) set f [open $path(test1) w] fconfigure $f -encoding binary - puts -nonewline $f \xe7\x89\xa6 + puts -nonewline $f \xE7\x89\xA6 close $f set f [open $path(test1) r] fconfigure $f -encoding utf-8 set x [read $f] close $f set x -} \u7266 +} 牦 test io-39.16 {Tcl_SetChannelOption: -encoding, errors} { file delete $path(test1) set f [open $path(test1) w] @@ -5509,7 +5508,7 @@ test io-39.16 {Tcl_SetChannelOption: -encoding, errors} { test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio fileevent} { set f [open "|[list [interpreter] $path(cat)]" r+] fconfigure $f -encoding binary - puts -nonewline $f "\xe7" + puts -nonewline $f "\xE7" flush $f fconfigure $f -encoding utf-8 -blocking 0 variable x {} @@ -5527,7 +5526,7 @@ test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} vwait [namespace which -variable x] close $f set x -} "{} timeout {} timeout \xe7 timeout" +} "{} timeout {} timeout \xE7 timeout" test io-39.18 {Tcl_SetChannelOption, setting read mode independently} \ {socket} { proc accept {s a p} {close $s} @@ -5830,11 +5829,11 @@ test io-42.2 {Tcl_FileeventCmd: replacing} {fileevent} { } {{first script} {new script} {yet another} {}} test io-42.3 {Tcl_FileeventCmd: replacing, with NULL chars in script} {fileevent} { set result {} - fileevent $f r "first scr\0ipt" + fileevent $f r "first scr\x00ipt" lappend result [string length [fileevent $f readable]] - fileevent $f r "new scr\0ipt" + fileevent $f r "new scr\x00ipt" lappend result [string length [fileevent $f readable]] - fileevent $f r "yet ano\0ther" + fileevent $f r "yet ano\x00ther" lappend result [string length [fileevent $f readable]] fileevent $f r "" lappend result [fileevent $f readable] @@ -6391,7 +6390,7 @@ test io-48.5 {lf write, testing readability, ^Z in middle, auto read mode} {file set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -6447,7 +6446,7 @@ test io-48.7 {cr write, testing readability, ^Z in middle, auto read mode} {file set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -6503,7 +6502,7 @@ test io-48.9 {crlf write, testing readability, ^Z in middle, auto read mode} {fi set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation auto + fconfigure $f -translation auto -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -6531,7 +6530,7 @@ test io-48.10 {lf write, testing readability, ^Z in middle, lf read mode} {filee set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation lf + fconfigure $f -translation lf -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -6587,7 +6586,7 @@ test io-48.12 {cr write, testing readability, ^Z in middle, cr read mode} {filee set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation cr + fconfigure $f -translation cr -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -6643,7 +6642,7 @@ test io-48.14 {crlf write, testing readability, ^Z in middle, crlf read mode} {f set c 0 set l "" set f [open $path(test1) r] - fconfigure $f -eofchar \x1A -translation crlf + fconfigure $f -translation crlf -eofchar \x1A fileevent $f readable [namespace code [list consume $f]] variable x vwait [namespace which -variable x] @@ -7218,7 +7217,7 @@ set path(utf8-rp.txt) [makeFile {} utf8-rp.txt] # Create kyrillic file, use lf translation to avoid os eol issues set out [open $path(kyrillic.txt) w] fconfigure $out -encoding koi8-r -translation lf -puts $out "\u0410\u0410" +puts $out "АА" close $out test io-52.9 {TclCopyChannel & encodings} {fcopy} { # Copy kyrillic to UTF-8, using fcopy. @@ -7270,7 +7269,7 @@ test io-52.10 {TclCopyChannel & encodings} {fcopy} { test io-52.11 {TclCopyChannel & encodings} -setup { set out [open $path(utf8-fcopy.txt) w] fconfigure $out -encoding utf-8 -translation lf - puts $out "\u0410\u0410" + puts $out "АА" close $out } -constraints {fcopy} -body { # binary to encoding => the input has to be @@ -8390,7 +8389,7 @@ test io-60.1 {writing illegal utf sequences} {fileevent testbytestring} { set out [open $path(script) w] puts $out "catch {load $::tcltestlib Tcltest}" puts $out { - puts [testbytestring \xe2] + puts [testbytestring \xE2] exit 1 } proc readit {pipe} { @@ -8748,7 +8747,7 @@ test io-73.5 {effect of eof on encoding end flags} -setup { read $rfd } -body { set result [eof $rfd] - puts -nonewline $wfd "more\u00c2\u00a0data" + puts -nonewline $wfd "more\xC2\xA0data" lappend result [eof $rfd] lappend result [read $rfd] lappend result [eof $rfd] @@ -8756,7 +8755,7 @@ test io-73.5 {effect of eof on encoding end flags} -setup { close $wfd close $rfd removeFile io-73.5 -} -result [list 1 1 more\u00a0data 1] +} -result [list 1 1 more\xA0data 1] test io-74.1 {[104f2885bb] improper cache validity check} -setup { set fn [makeFile {} io-74.1] diff --git a/tests/ioCmd.test b/tests/ioCmd.test index bdf162d..dbca866 100644 --- a/tests/ioCmd.test +++ b/tests/ioCmd.test @@ -494,14 +494,14 @@ test iocmd-12.10 {POSIX open access modes: BINARY} { } 5 test iocmd-12.11 {POSIX open access modes: BINARY} { set f [open $path(test1) {WRONLY BINARY TRUNC}] - puts $f \u0248 ;# gets truncated to \u0048 + puts $f Ɉ ;# gets truncated to H close $f set f [open $path(test1) r] fconfigure $f -translation binary set result [read -nonewline $f] close $f set result -} \u0048 +} H test iocmd-13.1 {errors in open command} { list [catch {open} msg] $msg diff --git a/tests/list.test b/tests/list.test index 4cd3a75..905a3d3 100644 --- a/tests/list.test +++ b/tests/list.test @@ -45,23 +45,23 @@ test list-1.24 {basic tests} {list} {} test list-1.25 {basic tests} {list # #} {{#} #} test list-1.26 {basic tests} {list #\{ #\{} {\#\{ #\{} test list-1.27 {basic null treatment} { - set l [list "" "\0" "\0\0"] - set e "{} \0 \0\0" + set l [list "" "\x00" "\x00\x00"] + set e "{} \x00 \x00\x00" string equal $l $e } 1 test list-1.28 {basic null treatment} { - set result "\0a\0b" + set result "\x00a\x00b" list $result [string length $result] -} "\0a\0b 4" +} "\x00a\x00b 4" test list-1.29 {basic null treatment} { - set result "\0a\0b" + set result "\x00a\x00b" set srep "$result 4" set lrep [list $result [string length $result]] string equal $srep $lrep } 1 test list-1.30 {basic null treatment} { - set l [list "\0abc" "xyz"] - set e "\0abc xyz" + set l [list "\x00abc" "xyz"] + set e "\x00abc xyz" string equal $l $e } 1 diff --git a/tests/load.test b/tests/load.test index 7978f64..40901e5 100644 --- a/tests/load.test +++ b/tests/load.test @@ -36,9 +36,9 @@ testConstraint $loaded [expr {![string match *pkga* $alreadyLoaded]}] set alreadyTotalLoaded [info loaded] -# Certain tests require the 'teststaticpkg' command from tcltest +# Certain tests require the 'teststaticlibrary' command from tcltest -testConstraint teststaticpkg [llength [info commands teststaticpkg]] +testConstraint teststaticlibrary [llength [info commands teststaticlibrary]] # Test load-10.1 requires the 'testsimplefilesystem' command from tcltest @@ -47,28 +47,28 @@ testConstraint testsimplefilesystem \ test load-1.1 {basic errors} -returnCodes error -body { load -} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?packageName? ?interp?"} +} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"} test load-1.2 {basic errors} -returnCodes error -body { load a b c d -} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?packageName? ?interp?"} +} -result {wrong # args: should be "load ?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"} test load-1.3 {basic errors} -returnCodes error -body { load a b foobar } -result {could not find interpreter "foobar"} test load-1.4 {basic errors} -returnCodes error -body { load -global {} -} -result {must specify either file name or package name} +} -result {must specify either file name or prefix} test load-1.5 {basic errors} -returnCodes error -body { load -lazy {} {} -} -result {must specify either file name or package name} +} -result {must specify either file name or prefix} test load-1.6 {basic errors} -returnCodes error -body { load {} Unknown -} -result {package "Unknown" isn't loaded statically} +} -result {no library with prefix "Unknown" is loaded statically} test load-1.7 {basic errors} -returnCodes error -body { load -abc foo } -result {bad option "-abc": must be -global, -lazy, or --} test load-1.8 {basic errors} -returnCodes error -body { load -global -} -result {couldn't figure out package name for -global} +} -result {couldn't figure out prefix for -global} test load-2.1 {basic loading, with guess for package name} \ [list $dll $loaded] { @@ -90,7 +90,7 @@ test load-2.3 {loading with no _Init procedure} -constraints [list $dll $loaded] {TCL LOOKUP LOAD_SYMBOL *Foo_Init}] test load-2.4 {loading with no _SafeInit procedure} [list $dll $loaded] { list [catch {load [file join $testDir pkga$ext] {} child} msg] $msg -} {1 {can't use package in a safe interpreter: no Pkga_SafeInit procedure}} +} {1 {can't use library in a safe interpreter: no Pkga_SafeInit procedure}} test load-3.1 {error in _Init procedure, same interpreter} \ [list $dll $loaded] { @@ -128,7 +128,7 @@ test load-4.2 {reloading package into same interpreter} -setup { catch {load [file join $testDir pkga$ext] Pkga} } -constraints [list $dll $loaded] -returnCodes error -body { load [file join $testDir pkga$ext] Pkgb -} -result "file \"[file join $testDir pkga$ext]\" is already loaded for package \"Pkga\"" +} -result "file \"[file join $testDir pkga$ext]\" is already loaded for prefix \"Pkga\"" test load-5.1 {file name not specified and no static package: pick default} -setup { catch {interp delete x} @@ -150,78 +150,78 @@ test load-6.1 {errors loading file} [list $dll $loaded] { catch {load foo foo} } {1} -test load-7.1 {Tcl_StaticPackage procedure} [list teststaticpkg] { +test load-7.1 {Tcl_StaticLibrary procedure} [list teststaticlibrary] { set x "not loaded" - teststaticpkg Test 1 0 + teststaticlibrary Test 1 0 load {} test load {} test child list [set x] [child eval set x] } {loaded loaded} -test load-7.2 {Tcl_StaticPackage procedure} [list teststaticpkg] { +test load-7.2 {Tcl_StaticLibrary procedure} [list teststaticlibrary] { set x "not loaded" - teststaticpkg Another 0 0 + teststaticlibrary Another 0 0 load {} Another child eval {set x "not loaded"} list [catch {load {} Another child} msg] $msg \ [child eval set x] [set x] -} {1 {can't use package in a safe interpreter: no Another_SafeInit procedure} {not loaded} loaded} -test load-7.3 {Tcl_StaticPackage procedure} [list teststaticpkg] { +} {1 {can't use library in a safe interpreter: no Another_SafeInit procedure} {not loaded} loaded} +test load-7.3 {Tcl_StaticLibrary procedure} [list teststaticlibrary] { set x "not loaded" - teststaticpkg More 0 1 + teststaticlibrary More 0 1 load {} more set x } {not loaded} catch {load [file join $testDir pkga$ext] Pkga} catch {load [file join $testDir pkgb$ext] Pkgb} catch {load [file join $testDir pkge$ext] Pkge} -set currentRealPackages [list [list [file join $testDir pkge$ext] Pkge] [list [file join $testDir pkgb$ext] Pkgb] [list [file join $testDir pkga$ext] Pkga]] -test load-7.4 {Tcl_StaticPackage procedure, redundant calls} -setup { - teststaticpkg Test 1 0 - teststaticpkg Another 0 0 - teststaticpkg More 0 1 -} -constraints [list teststaticpkg $dll $loaded] -body { - teststaticpkg Double 0 1 - teststaticpkg Double 0 1 +set currentRealLibraries [list [list [file join $testDir pkge$ext] Pkge] [list [file join $testDir pkgb$ext] Pkgb] [list [file join $testDir pkga$ext] Pkga]] +test load-7.4 {Tcl_StaticLibrary procedure, redundant calls} -setup { + teststaticlibrary Test 1 0 + teststaticlibrary Another 0 0 + teststaticlibrary More 0 1 +} -constraints [list teststaticlibrary $dll $loaded] -body { + teststaticlibrary Double 0 1 + teststaticlibrary Double 0 1 info loaded -} -result [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealPackages {*}$alreadyTotalLoaded] +} -result [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealLibraries {*}$alreadyTotalLoaded] -testConstraint teststaticpkg_8.x 0 -if {[testConstraint teststaticpkg]} { +testConstraint teststaticlibrary_8.x 0 +if {[testConstraint teststaticlibrary]} { catch { - teststaticpkg Test 1 1 - teststaticpkg Another 0 1 - teststaticpkg More 0 1 - teststaticpkg Double 0 1 - testConstraint teststaticpkg_8.x 1 + teststaticlibrary Test 1 1 + teststaticlibrary Another 0 1 + teststaticlibrary More 0 1 + teststaticlibrary Double 0 1 + testConstraint teststaticlibrary_8.x 1 } } -test load-8.1 {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] { +test load-8.1 {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] { lsort -index 1 [info loaded] -} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealPackages {*}$alreadyTotalLoaded]] -test load-8.2 {TclGetLoadedPackages procedure} -constraints {teststaticpkg_8.x} -body { +} [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealLibraries {*}$alreadyTotalLoaded]] +test load-8.2 {TclGetLoadedLibraries procedure} -constraints {teststaticlibrary_8.x} -body { info loaded gorp } -returnCodes error -result {could not find interpreter "gorp"} -test load-8.3a {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] { +test load-8.3a {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] { lsort -index 1 [info loaded {}] } [lsort -index 1 [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga] [list [file join $testDir pkgb$ext] Pkgb] {*}$alreadyLoaded]] -test load-8.3b {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] { +test load-8.3b {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] { lsort -index 1 [info loaded child] } [lsort -index 1 [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]] -test load-8.4 {TclGetLoadedPackages procedure} [list teststaticpkg_8.x $dll $loaded] { +test load-8.4 {TclGetLoadedLibraries procedure} [list teststaticlibrary_8.x $dll $loaded] { load [file join $testDir pkgb$ext] Pkgb list [lsort -index 1 [info loaded {}]] [lsort [info commands pkgb_*]] } [list [lsort -index 1 [concat [list [list [file join $testDir pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded]] {pkgb_demo pkgb_sub pkgb_unsafe}] interp delete child -test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} -setup { +test load-9.1 {Tcl_StaticLibrary, load already-loaded package into another interp} -setup { interp create child1 interp create child2 load {} Tcltest child1 load {} Tcltest child2 -} -constraints {teststaticpkg} -body { - child1 eval { teststaticpkg Loadninepointone 0 1 } - child2 eval { teststaticpkg Loadninepointone 0 1 } +} -constraints {teststaticlibrary} -body { + child1 eval { teststaticlibrary Loadninepointone 0 1 } + child2 eval { teststaticlibrary Loadninepointone 0 1 } list [child1 eval { info loaded {} }] \ [child2 eval { info loaded {} }] } -match glob -cleanup { @@ -234,7 +234,7 @@ test load-10.1 {load from vfs} -setup { cd $testDir testsimplefilesystem 1 } -constraints [list $dll $loaded testsimplefilesystem] -body { - list [catch {load simplefs:/pkgd$ext PKGD} msg] $msg + list [catch {load simplefs:/pkgd$ext Pkgd} msg] $msg } -result {0 {}} -cleanup { testsimplefilesystem 0 cd $dir diff --git a/tests/lsearch.test b/tests/lsearch.test index 06f3ae4..7c1402d 100644 --- a/tests/lsearch.test +++ b/tests/lsearch.test @@ -102,13 +102,13 @@ test lsearch-3.7 {lsearch errors} -returnCodes error -body { } -result {-subindices cannot be used without -index option} test lsearch-4.1 {binary data} { - lsearch -exact [list foo one\000two bar] bar + lsearch -exact [list foo one\x00two bar] bar } 2 test lsearch-4.2 {binary data} { set x one append x \x00 append x two - lsearch -exact [list foo one\000two bar] $x + lsearch -exact [list foo one\x00two bar] $x } 1 # Make a sorted list diff --git a/tests/main.test b/tests/main.test index 37f87b4..2d3f63c 100644 --- a/tests/main.test +++ b/tests/main.test @@ -68,56 +68,56 @@ namespace eval ::tcl::test::main { stdio } -setup { makeFile {puts [list $argv0 $argv $tcl_interactive]} script - catch {set f [open "|[list [interpreter] script \u00c0]" r]} + catch {set f [open "|[list [interpreter] script À]" r]} } -body { read $f } -cleanup { close $f removeFile script } -result [list script [list [encoding convertfrom [encoding system] \ - [encoding convertto [encoding system] \u00c0]]] 0]\n + [encoding convertto [encoding system] À]]] 0]\n test Tcl_Main-1.4 { } -constraints { stdio } -setup { makeFile {puts [list $argv0 $argv $tcl_interactive]} script - catch {set f [open "|[list [interpreter] script \u20ac]" r]} + catch {set f [open "|[list [interpreter] script €]" r]} } -body { read $f } -cleanup { close $f removeFile script } -result [list script [list [encoding convertfrom [encoding system] \ - [encoding convertto [encoding system] \u20ac]]] 0]\n + [encoding convertto [encoding system] €]]] 0]\n test Tcl_Main-1.5 { } -constraints { stdio } -setup { - makeFile {puts [list $argv0 $argv $tcl_interactive]} \u00c0 - catch {set f [open "|[list [interpreter] \u00c0]" r]} + makeFile {puts [list $argv0 $argv $tcl_interactive]} À + catch {set f [open "|[list [interpreter] À]" r]} } -body { read $f } -cleanup { close $f - removeFile \u00c0 + removeFile À } -result [list [list [encoding convertfrom [encoding system] \ - [encoding convertto [encoding system] \u00c0]]] {} 0]\n + [encoding convertto [encoding system] À]]] {} 0]\n test Tcl_Main-1.6 { } -constraints { stdio } -setup { - makeFile {puts [list $argv0 $argv $tcl_interactive]} \u20ac - catch {set f [open "|[list [interpreter] \u20ac]" r]} + makeFile {puts [list $argv0 $argv $tcl_interactive]} € + catch {set f [open "|[list [interpreter] €]" r]} } -body { read $f } -cleanup { close $f - removeFile \u20ac + removeFile € } -result [list [list [encoding convertfrom [encoding system] \ - [encoding convertto [encoding system] \u20ac]]] {} 0]\n + [encoding convertto [encoding system] €]]] {} 0]\n test Tcl_Main-1.7 { Tcl_Main: startup script - -encoding option @@ -129,8 +129,8 @@ namespace eval ::tcl::test::main { set f [open $script w] chan configure $f -encoding utf-8 puts $f {puts [list $argv0 $argv $tcl_interactive]} - puts -nonewline $f {puts [string equal \u20ac } - puts $f "\u20ac]" + puts -nonewline $f {puts [string equal € } + puts $f "€]" close $f catch {set f [open "|[list [interpreter] -encoding utf-8 script]" r]} } -body { @@ -151,7 +151,7 @@ namespace eval ::tcl::test::main { chan configure $f -encoding utf-8 puts $f {puts [list $argv0 $argv $tcl_interactive]} puts -nonewline $f {puts [string equal \u20ac } - puts $f "\u20ac]" + puts $f "€]" close $f catch {set f [open "|[list [interpreter] -encoding ascii script]" r]} } -body { @@ -172,7 +172,7 @@ namespace eval ::tcl::test::main { chan configure $f -encoding utf-8 puts $f {puts [list $argv0 $argv $tcl_interactive]} puts -nonewline $f {puts [string equal \u20ac } - puts $f "\u20ac]" + puts $f "€]" close $f catch {set f [open "|[list [interpreter] -enc utf-8 script]" r+]} } -body { @@ -606,8 +606,8 @@ namespace eval ::tcl::test::main { catch {set f [open "|[list [interpreter]]" w+]} catch {chan configure $f -blocking 0} } -body { - type $f "chan configure stdin -eofchar \"\\032 {}\" - if 1 \{\n\032" + type $f "chan configure stdin -eofchar \"\\x1A {}\" + if 1 \{\n\x1A" variable wait chan event $f readable \ [list set [namespace which -variable wait] "child exit"] diff --git a/tests/obj.test b/tests/obj.test index a2976de..4fa8d3a 100644 --- a/tests/obj.test +++ b/tests/obj.test @@ -251,10 +251,10 @@ test obj-13.7 {SetBooleanFromAny, error converting from "empty string"} testobj } {{} 1 {expected boolean value but got ""}} test obj-13.8 {SetBooleanFromAny, unicode strings} testobj { set result "" - lappend result [teststringobj set 1 1\u7777] + lappend result [teststringobj set 1 1睷] lappend result [catch {testbooleanobj not 1} msg] lappend result $msg -} "1\u7777 1 {expected boolean value but got \"1\u7777\"}" +} "1睷 1 {expected boolean value but got \"1睷\"}" test obj-14.1 {UpdateStringOfBoolean} testobj { set result "" diff --git a/tests/parse.test b/tests/parse.test index 3bf0de9..b0c051b 100644 --- a/tests/parse.test +++ b/tests/parse.test @@ -31,7 +31,7 @@ testConstraint testevent [llength [info commands testevent]] testConstraint memory [llength [info commands memory]] test parse-1.1 {Tcl_ParseCommand procedure, computing string length} {testparser testbytestring} { - testparser [testbytestring "foo\0 bar"] -1 + testparser [testbytestring "foo\x00 bar"] -1 } {- foo 1 simple foo 1 text foo 0 {}} test parse-1.2 {Tcl_ParseCommand procedure, computing string length} testparser { testparser "foo bar" -1 @@ -300,8 +300,8 @@ test parse-6.15 {ParseTokens procedure, backslash-newline} testparser { testparser "\"b\\\nc\"" 0 } {- \"b\\\nc\" 1 word \"b\\\nc\" 3 text b 0 backslash \\\n 0 text c 0 {}} test parse-6.16 {ParseTokens procedure, backslash substitution} testparser { - testparser {\n\a\x7f} 0 -} {- {\n\a\x7f} 1 word {\n\a\x7f} 3 backslash {\n} 0 backslash {\a} 0 backslash {\x7f} 0 {}} + testparser {\n\a\x7F} 0 +} {- {\n\a\x7F} 1 word {\n\a\x7F} 3 backslash {\n} 0 backslash {\a} 0 backslash {\x7F} 0 {}} test parse-6.17 {ParseTokens procedure, null characters} {testparser testbytestring} { expr {[testparser [testbytestring "foo\0zz"] 0] eq "- [testbytestring foo\0zz] 1 word [testbytestring foo\0zz] 3 text foo 0 text [testbytestring \0] 0 text zz 0 {}" @@ -707,7 +707,7 @@ test parse-13.6 {Tcl_ParseVar memory leak} -constraints {testparsevar memory} -s } -result 0 test parse-14.1 {Tcl_ParseBraces procedure, computing string length} {testparser testbytestring} { - testparser [testbytestring "foo\0 bar"] -1 + testparser [testbytestring "foo\x00 bar"] -1 } {- foo 1 simple foo 1 text foo 0 {}} test parse-14.2 {Tcl_ParseBraces procedure, computing string length} testparser { testparser "foo bar" -1 @@ -744,7 +744,7 @@ test parse-14.12 {Tcl_ParseBraces procedure, missing close brace} testparser { } {1 {missing close-brace} missing\ close-brace\n\ \ \ \ (remainder\ of\ script:\ \"\{xy\\\nz\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"foo\ \\\{xy\\\\\\nz\"\ 0\"} test parse-15.1 {Tcl_ParseQuotedString procedure, computing string length} {testparser testbytestring} { - testparser [testbytestring "foo\0 bar"] -1 + testparser [testbytestring "foo\x00 bar"] -1 } {- foo 1 simple foo 1 text foo 0 {}} test parse-15.2 {Tcl_ParseQuotedString procedure, computing string length} testparser { testparser "foo bar" -1 @@ -910,10 +910,10 @@ test parse-15.54 {CommandComplete procedure} " info complete \"foo bar;# \{\" " 1 test parse-15.55 {CommandComplete procedure} testbytestring { - info complete "set x [testbytestring \0]; puts hi" + info complete "set x [testbytestring \x00]; puts hi" } 1 test parse-15.56 {CommandComplete procedure} testbytestring { - info complete "set x [testbytestring \0]; \{" + info complete "set x [testbytestring \x00]; \{" } 0 test parse-15.57 {CommandComplete procedure} { info complete "# Comment should be complete command" diff --git a/tests/parseExpr.test b/tests/parseExpr.test index 99ada39..c70c5e3 100644 --- a/tests/parseExpr.test +++ b/tests/parseExpr.test @@ -32,9 +32,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -44,19 +44,19 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -66,11 +66,11 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) set ieeeValues(littleEndian) 0 return 1 @@ -85,7 +85,7 @@ testConstraint ieeeFloatingPoint [testIEEE] ###################################################################### test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} {testexprparser testbytestring} { - testexprparser [testbytestring "1+2\0 +3"] -1 + testexprparser [testbytestring "1+2\x00 +3"] -1 } {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}} test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} testexprparser { testexprparser "1 + 2" -1 @@ -882,17 +882,17 @@ test parseExpr-21.36 {error messages} -body { } -returnCodes error -result {invalid character "@" in expression "...fghijklmnopqrstuvwxyz"@"abcdefghijklmnopqrstu..."} test parseExpr-21.37 {error messages} -body { - expr [format {"%s" @ 0} [string repeat \u00a7 25]] + expr [format {"%s" @ 0} [string repeat \xA7 25]] } -returnCodes error -result [format {invalid character "@" -in expression "...%s" @ 0"} [string repeat \u00a7 10]] +in expression "...%s" @ 0"} [string repeat \xA7 10]] test parseExpr-21.38 {error messages} -body { - expr [format {0 @ "%s"} [string repeat \u00a7 25]] + expr [format {0 @ "%s"} [string repeat \xA7 25]] } -returnCodes error -result [format {invalid character "@" -in expression "0 @ "%s..."} [string repeat \u00a7 10]] +in expression "0 @ "%s..."} [string repeat \xA7 10]] test parseExpr-21.39 {error messages} -body { - expr [format {"%s" @ "%s"} [string repeat \u00a7 25] [string repeat \u00a7 25]] + expr [format {"%s" @ "%s"} [string repeat \xA7 25] [string repeat \xA7 25]] } -returnCodes error -result [format {invalid character "@" -in expression "...%s" @ "%s..."} [string repeat \u00a7 10] [string repeat \u00a7 10]] +in expression "...%s" @ "%s..."} [string repeat \xA7 10] [string repeat \xA7 10]] test parseExpr-21.40 {error messages} -body { catch {expr {"abcdefghijklmnopqrstuvwxyz"@0}} m o dict get $o -errorinfo @@ -902,13 +902,13 @@ in expression "...fghijklmnopqrstuvwxyz"@0" invoked from within "expr {"abcdefghijklmnopqrstuvwxyz"@0}"} test parseExpr-21.41 {error messages} -body { - catch {expr [format {"%s" @ 0} [string repeat \u00a7 25]]} m o + catch {expr [format {"%s" @ 0} [string repeat \xA7 25]]} m o dict get $o -errorinfo } -result [format {invalid character "@" in expression "...%s" @ 0" (parsing expression ""%s...") invoked from within -"expr [format {"%%s" @ 0} [string repeat \u00a7 25]]"} [string repeat \u00a7 10] [string repeat \u00a7 10]] +"expr [format {"%%s" @ 0} [string repeat \xA7 25]]"} [string repeat \xA7 10] [string repeat \xA7 10]] test parseExpr-21.42 {error message} -body { expr {123456789012345678901234567890*"abcdefghijklmnopqrstuvwxyz} } -returnCodes error -result {missing " @@ -1066,13 +1066,13 @@ test parseExpr-22.18 {Bug 3401704} -constraints testexprparser -body { } -result {TCL PARSE EXPR BADNUMBER BINARY} test parseExpr-22.19 {Bug d2ffcca163} -constraints testexprparser -body { - testexprparser \u0433 -1 + testexprparser г -1 } -returnCodes error -match glob -result {*invalid character*} test parseExpr-22.20 {Bug d2ffcca163} -constraints testexprparser -body { - testexprparser \u043f -1 + testexprparser п -1 } -returnCodes error -match glob -result {*invalid character*} test parseExpr-22.21 {Bug d2ffcca163} -constraints testexprparser -body { - testexprparser in\u0433(0) -1 + testexprparser inг(0) -1 } -returnCodes error -match glob -result {missing operand*} test parseExpr-23.1 {TIP 582: comments} -constraints testexprparser -body { diff --git a/tests/parseOld.test b/tests/parseOld.test index f8caf24..44aa5d1 100644 --- a/tests/parseOld.test +++ b/tests/parseOld.test @@ -22,7 +22,6 @@ if {"::tcltest" ni [namespace children]} { catch [list package require -exact tcl::test [info patchlevel]] testConstraint testwordend [llength [info commands testwordend]] -testConstraint testbytestring [llength [info commands testbytestring]] # Save the argv value for restoration later set savedArgv $argv @@ -264,14 +263,14 @@ test parseOld-7.10 {backslash substitution} { test parseOld-7.11 {backslash substitution} { eval "list a \"b c\"\\\nd e" } {a {b c} d e} -test parseOld-7.12 {backslash substitution} testbytestring { - expr {[list \ua2] eq [testbytestring "\xc2\xa2"]} +test parseOld-7.12 {backslash substitution} { + expr {[list \uA2] eq "¢"} } 1 -test parseOld-7.13 {backslash substitution} testbytestring { - expr {[list \u4e21] eq [testbytestring "\xe4\xb8\xa1"]} +test parseOld-7.13 {backslash substitution} { + expr {[list \u4E21] eq "両"} } 1 -test parseOld-7.14 {backslash substitution} testbytestring { - expr {[list \u4e2k] eq [testbytestring "\xd3\xa2k"]} +test parseOld-7.14 {backslash substitution} { + expr {[list \u4E2k] eq "Ӣk"} } 1 # Semi-colon. diff --git a/tests/proc.test b/tests/proc.test index 23aea28..ab32567 100644 --- a/tests/proc.test +++ b/tests/proc.test @@ -17,6 +17,7 @@ if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } +::tcltest::loadTestedCommands testConstraint tcl::test [expr {![catch {package require tcl::test}]}] testConstraint memory [llength [info commands memory]] diff --git a/tests/reg.test b/tests/reg.test index 5ebc2f9..b6198d8 100644 --- a/tests/reg.test +++ b/tests/reg.test @@ -514,8 +514,8 @@ expectMatch 9.40 eE {a[\\]b} "a\\b" "a\\b" expectMatch 9.41 bE {a[\\]b} "a\\b" "a\\b" expectError 9.42 - {a[\Z]b} EESCAPE expectMatch 9.43 & {a[[b]c} "a\[c" "a\[c" -expectMatch 9.44 EMP* {a[\u00fe-\u0507][\u00ff-\u0300]b} \ - "a\u0102\u02ffb" "a\u0102\u02ffb" +expectMatch 9.44 EMP* {a[\xFE-\u0507][\xFF-\u0300]b} \ + "a\u0102\u02FFb" "a\u0102\u02FFb" doing 10 "anchors and newlines" @@ -643,8 +643,8 @@ expectMatch 13.29 P "a\\U0001234x" "a\u1234x" "a\u1234x" expectMatch 13.30 P {a\U0001234x} "a\u1234x" "a\u1234x" expectMatch 13.31 P "a\\U000012345x" "a\u12345x" "a\u12345x" expectMatch 13.32 P {a\U000012345x} "a\u12345x" "a\u12345x" -expectMatch 13.33 P "a\\U1000000x" "a\ufffd0x" "a\ufffd0x" -expectMatch 13.34 P {a\U1000000x} "a\ufffd0x" "a\ufffd0x" +expectMatch 13.33 P "a\\U1000000x" "a\uFFFD0x" "a\uFFFD0x" +expectMatch 13.34 P {a\U1000000x} "a\uFFFD0x" "a\uFFFD0x" doing 14 "back references" diff --git a/tests/regexp.test b/tests/regexp.test index 842789e..e788b7f 100644 --- a/tests/regexp.test +++ b/tests/regexp.test @@ -54,8 +54,8 @@ test regexp-1.6 {basic regexp operation} { } {0 1} test regexp-1.7 {regexp utf compliance} { # if not UTF-8 aware, result is "0 1" - set foo "\u4e4eb q" - regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar + set foo "乎b q" + regexp "乎b q" "a乎b qw幎N wq" bar list [string compare $foo $bar] [regexp 4 $bar] } {0 0} test regexp-1.8 {regexp ***= metasyntax} { @@ -194,14 +194,14 @@ test regexp-3.7 {getting substrings back from regexp} { } {1 {1 2} {1 1} {-1 -1} {2 2}} test regexp-3.8a {-indices by multi-byte utf-8} { regexp -inline -indices {(\w+)-(\w+)} \ - "gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442" + "grüß-привет" } {{0 10} {0 3} {5 10}} test regexp-3.8b {-indices by multi-byte utf-8, from -start position} { list\ [regexp -inline -indices -start 3 {(\w+)-(\w+)} \ - "gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"] \ + "grüß-привет"] \ [regexp -inline -indices -start 4 {(\w+)-(\w+)} \ - "gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"] + "grüß-привет"] } {{{3 10} {3 3} {5 10}} {}} test regexp-4.1 {-nocase option to regexp} { @@ -352,8 +352,8 @@ test regexp-7.16 {basic regsub operation} { } {0 {}} test regexp-7.17 {regsub utf compliance} { # if not UTF-8 aware, result is "0 1" - set foo "xyz555ijka\u4e4ebpqr" - regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar + set foo "xyz555ijka乎bpqr" + regsub a乎b xyza乎bijka乎bpqr 555 bar list [string compare $foo $bar] [regexp 4 $bar] } {0 0} test regexp-7.18 {basic regsub replacement} { diff --git a/tests/regexpComp.test b/tests/regexpComp.test index 4dfc2e6..76e708d 100644 --- a/tests/regexpComp.test +++ b/tests/regexpComp.test @@ -62,8 +62,8 @@ test regexpComp-1.6 {basic regexp operation} { test regexpComp-1.7 {regexp utf compliance} { # if not UTF-8 aware, result is "0 1" evalInProc { - set foo "\u4e4eb q" - regexp "\u4e4eb q" "a\u4e4eb qw\u5e4e\x4e wq" bar + set foo "乎b q" + regexp "乎b q" "a乎b qw幎N wq" bar list [string compare $foo $bar] [regexp 4 $bar] } } {0 0} @@ -447,8 +447,8 @@ test regexpComp-7.16 {basic regsub operation} { test regexpComp-7.17 {regsub utf compliance} { evalInProc { # if not UTF-8 aware, result is "0 1" - set foo "xyz555ijka\u4e4ebpqr" - regsub a\u4e4eb xyza\u4e4ebijka\u4e4ebpqr 555 bar + set foo "xyz555ijka乎bpqr" + regsub a乎b xyza乎bijka乎bpqr 555 bar list [string compare $foo $bar] [regexp 4 $bar] } } {0 0} diff --git a/tests/safe.test b/tests/safe.test index db881c2..773b16f 100644 --- a/tests/safe.test +++ b/tests/safe.test @@ -24,6 +24,8 @@ if {"::tcltest" ni [namespace children]} { package require tcltest 2.5 namespace import -force ::tcltest::* } +::tcltest::loadTestedCommands +catch [list package require -exact tcl::test [info patchlevel]] foreach i [interp children] { interp delete $i @@ -1159,58 +1161,58 @@ test safe-9.24 {interpConfigure change the access path; check module loading; st res0 res1 res2} # See comments on lsort after test safe-9.20. -catch {teststaticpkg Safepkg1 0 0} +catch {teststaticlibrary Safepfx1 0 0} test safe-10.1 {testing statics loading} -constraints tcl::test -setup { set i [safe::interpCreate] } -body { - interp eval $i {load {} Safepkg1} + interp eval $i {load {} Safepfx1} } -returnCodes error -cleanup { safe::interpDelete $i -} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure} +} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure} test safe-10.1.1 {testing statics loading} -constraints tcl::test -setup { set i [safe::interpCreate] } -body { - catch {interp eval $i {load {} Safepkg1}} m o + catch {interp eval $i {load {} Safepfx1}} m o dict get $o -errorinfo } -returnCodes ok -cleanup { unset -nocomplain m o safe::interpDelete $i -} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure +} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure invoked from within -"load {} Safepkg1" +"load {} Safepfx1" invoked from within -"interp eval $i {load {} Safepkg1}"} +"interp eval $i {load {} Safepfx1}"} test safe-10.2 {testing statics loading / -nostatics} -constraints tcl::test -body { set i [safe::interpCreate -nostatics] - interp eval $i {load {} Safepkg1} + interp eval $i {load {} Safepfx1} } -returnCodes error -cleanup { safe::interpDelete $i -} -result {permission denied (static package)} +} -result {permission denied (static library)} test safe-10.3 {testing nested statics loading / no nested by default} -setup { set i [safe::interpCreate] } -constraints tcl::test -body { - interp eval $i {interp create x; load {} Safepkg1 x} + interp eval $i {interp create x; load {} Safepfx1 x} } -returnCodes error -cleanup { safe::interpDelete $i } -result {permission denied (nested load)} test safe-10.4 {testing nested statics loading / -nestedloadok} -constraints tcl::test -body { set i [safe::interpCreate -nestedloadok] - interp eval $i {interp create x; load {} Safepkg1 x} + interp eval $i {interp create x; load {} Safepfx1 x} } -returnCodes error -cleanup { safe::interpDelete $i -} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure} +} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure} test safe-10.4.1 {testing nested statics loading / -nestedloadok} -constraints tcl::test -body { set i [safe::interpCreate -nestedloadok] - catch {interp eval $i {interp create x; load {} Safepkg1 x}} m o + catch {interp eval $i {interp create x; load {} Safepfx1 x}} m o dict get $o -errorinfo } -returnCodes ok -cleanup { unset -nocomplain m o safe::interpDelete $i -} -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure +} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure invoked from within -"load {} Safepkg1 x" +"load {} Safepfx1 x" invoked from within -"interp eval $i {interp create x; load {} Safepkg1 x}"} +"interp eval $i {interp create x; load {} Safepfx1 x}"} test safe-11.1 {testing safe encoding} -setup { set i [safe::interpCreate] diff --git a/tests/scan.test b/tests/scan.test index c125080..c6e7922 100644 --- a/tests/scan.test +++ b/tests/scan.test @@ -32,9 +32,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -44,19 +44,19 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -66,11 +66,11 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) set ieeeValues(littleEndian) 0 return 1 @@ -639,18 +639,18 @@ test scan-7.5 {string and character scanning} -setup { test scan-7.6 {string and character scanning, unicode} -setup { set a {}; set b {}; set c {}; set d {} } -body { - list [scan "abc d\u00c7fghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d -} -result "4 abc d\u00c7f ghijk dum" + list [scan "abc dÇfghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d +} -result "4 abc dÇf ghijk dum" test scan-7.7 {string and character scanning, unicode} -setup { set a {}; set b {} } -body { - list [scan "ab\u00c7cdef" "ab%c%c" a b] $a $b + list [scan "abÇcdef" "ab%c%c" a b] $a $b } -result "2 199 99" test scan-7.8 {string and character scanning, unicode} -setup { set a {}; set b {} } -body { - list [scan "ab\ufeffdef" "%\[ab\ufeff\]" a] $a -} -result "1 ab\ufeff" + list [scan "ab\uFEFFdef" "%\[ab\uFEFF\]" a] $a +} -result "1 ab\uFEFF" test scan-8.1 {error conditions} -body { scan a diff --git a/tests/source.test b/tests/source.test index 47f1486..eee03ec 100644 --- a/tests/source.test +++ b/tests/source.test @@ -111,7 +111,7 @@ test source-2.7 {utf-8 with BOM} -setup { } -body { set out [open $sourcefile w] fconfigure $out -encoding utf-8 - puts $out "\ufeffset y new-y" + puts $out "\uFEFFset y new-y" close $out set y old-y source -encoding utf-8 $sourcefile @@ -199,7 +199,7 @@ test source-4.1 {continuation line parsing} -setup { test source-6.1 {source is binary ok} -setup { # Note [makeFile] writes in the system encoding. # [source] defaults to reading in the system encoding. - set sourcefile [makeFile [list set x "a b\0c"] source.file] + set sourcefile [makeFile [list set x "a b\x00c"] source.file] } -body { set x {} source $sourcefile @@ -208,7 +208,7 @@ test source-6.1 {source is binary ok} -setup { removeFile source.file } -result 5 test source-6.2 {source skips everything after Ctrl-Z: Bug 2040} -setup { - set sourcefile [makeFile "set x ab\32c" source.file] + set sourcefile [makeFile "set x ab\x1Ac" source.file] } -body { set x {} source $sourcefile @@ -222,7 +222,7 @@ test source-7.1 {source -encoding test} -setup { file delete $sourcefile set f [open $sourcefile w] fconfigure $f -encoding utf-8 - puts $f "set symbol(square-root) \u221A; set x correct" + puts $f "set symbol(square-root) √; set x correct" close $f } -body { set x unset @@ -233,15 +233,15 @@ test source-7.1 {source -encoding test} -setup { } -result correct test source-7.2 {source -encoding test} -setup { # This tests for bad interactions between [source -encoding] - # and use of the Control-Z character (\u001A) as a cross-platform + # and use of the Control-Z character (\x1A) as a cross-platform # EOF character by [source]. Here we write out and the [source] a - # file that contains the byte \x1A, although not the character \u001A in + # file that contains the byte \x1A, although not the character \x1A in # the indicated encoding. set sourcefile [makeFile {} source.file] file delete $sourcefile set f [open $sourcefile w] fconfigure $f -encoding utf-16 - puts $f "set symbol(square-root) \u221A; set x correct" + puts $f "set symbol(square-root) √; set x correct" close $f } -body { set x unset @@ -266,25 +266,25 @@ test source-7.5 {source -encoding: correct operation} -setup { file delete $sourcefile set f [open $sourcefile w] fconfigure $f -encoding utf-8 - puts $f "proc \u20ac {} {return foo}" + puts $f "proc € {} {return foo}" close $f } -body { source -encoding utf-8 $sourcefile - \u20ac + € } -cleanup { removeFile source.file - rename \u20ac {} + rename € {} } -result foo test source-7.6 {source -encoding: mismatch encoding error} -setup { set sourcefile [makeFile {} source.file] file delete $sourcefile set f [open $sourcefile w] fconfigure $f -encoding utf-8 - puts $f "proc \u20ac {} {return foo}" + puts $f "proc € {} {return foo}" close $f } -body { source -encoding ascii $sourcefile - \u20ac + € } -cleanup { removeFile source.file } -returnCodes error -match glob -result {invalid command name*} diff --git a/tests/split.test b/tests/split.test index 74879cf..a34c49d 100644 --- a/tests/split.test +++ b/tests/split.test @@ -49,20 +49,20 @@ test split-1.8 {basic split commands} { } {]\n} test split-1.9 {basic split commands} { proc foo {} { - set x ab\000c + set x ab\x00c set y [split $x {}] return $y } foo -} "a b \000 c" +} "a b \x00 c" test split-1.10 {basic split commands} { - split "a0ab1b2bbb3\000c4" ab\000c + split "a0ab1b2bbb3\x00c4" ab\x00c } {{} 0 {} 1 2 {} {} 3 {} 4} test split-1.11 {basic split commands} { split "12,3,45" {,} } {12 3 45} test split-1.12 {basic split commands} { - split "\u0001ab\u0001cd\u0001\u0001ef\u0001" \1 + split "\x01ab\x01cd\x01\x01ef\x01" \x01 } {{} ab cd {} ef {}} test split-1.13 {basic split commands} { split "12,34,56," {,} @@ -71,10 +71,10 @@ test split-1.14 {basic split commands} { split ",12,,,34,56," {,} } {{} 12 {} {} 34 56 {}} test split-1.15 {basic split commands} -body { - split "a\U1F4A9b" {} -} -result "a \U1F4A9 b" + split "a💩b" {} +} -result "a 💩 b" test split-1.16 {basic split commands} -body { - split "a\U1F4A9b" \U1F4A9 + split "a💩b" 💩 } -result "a b" test split-2.1 {split errors} { diff --git a/tests/string.test b/tests/string.test index 0eaa3da..c2d47d3 100644 --- a/tests/string.test +++ b/tests/string.test @@ -119,16 +119,16 @@ test string-2.10.$noComp {string compare with special index} { list [catch {run {string compare -length end-3 abcde abxyz}} msg] $msg } {1 {expected integer but got "end-3"}} test string-2.11.$noComp {string compare, unicode} { - run {string compare ab\u7266 ab\u7267} + run {string compare ab牦 ab牧} } -1 test string-2.11.1.$noComp {string compare, unicode} { - run {string compare \334 \xDC} + run {string compare Ü Ü} } 0 test string-2.11.2.$noComp {string compare, unicode} { - run {string compare \334 \xFC} + run {string compare Ü ü} } -1 test string-2.11.3.$noComp {string compare, unicode} { - run {string compare \334\334\334\374\374 \334\334\334\334\334} + run {string compare ÜÜÜüü ÜÜÜÜÜ} } 1 test string-2.12.$noComp {string compare, high bit} { # This test will fail if the underlying comparison @@ -152,10 +152,10 @@ test string-2.15.$noComp {string compare -nocase} { run {string compare -nocase abcde abcde} } 0 test string-2.15.1.$noComp {string compare -nocase} { - run {string compare -nocase \334 \xDC} + run {string compare -nocase Ü Ü} } 0 test string-2.15.2.$noComp {string compare -nocase} { - run {string compare -nocase \334\334\334\374\xFC \334\334\334\334\334} + run {string compare -nocase ÜÜÜüü ÜÜÜÜÜ} } 0 test string-2.16.$noComp {string compare -nocase with length} { run {string compare -length 2 -nocase abcde Abxyz} @@ -172,7 +172,7 @@ test string-2.19.$noComp {string compare -nocase with excessive length} { test string-2.20.$noComp {string compare -len unicode} { # These are strings that are 6 BYTELENGTH long, but the length # shouldn't make a different because there are actually 3 CHARS long - run {string compare -len 5 \334\334\334 \334\334\374} + run {string compare -len 5 ÜÜÜ ÜÜü} } -1 test string-2.21.$noComp {string compare -nocase with special index} { list [catch {run {string compare -nocase -length end-3 Abcde abxyz}} msg] $msg @@ -237,7 +237,7 @@ test string-3.3.$noComp {string equal} { run {string equal abcde abcde} } 1 test string-3.4.$noComp {string equal -nocase} { - run {string equal -nocase \334\334\334\334\374\374\374\374 \334\334\334\334\334\334\334\334} + run {string equal -nocase ÜÜÜÜüüüü ÜÜÜÜÜÜÜÜ} } 1 test string-3.5.$noComp {string equal -nocase} { run {string equal -nocase abcde abdef} @@ -274,19 +274,19 @@ test string-3.15.$noComp {string equal with special index} { } {1 {expected integer but got "end-3"}} test string-3.16.$noComp {string equal, unicode} { - run {string equal ab\u7266 ab\u7267} + run {string equal ab牦 ab牧} } 0 test string-3.17.$noComp {string equal, unicode} { - run {string equal \334 \xDC} + run {string equal Ü Ü} } 1 test string-3.18.$noComp {string equal, unicode} { - run {string equal \334 \xFC} + run {string equal Ü ü} } 0 test string-3.19.$noComp {string equal, unicode} { - run {string equal \334\334\334\374\374 \334\334\334\334\334} + run {string equal ÜÜÜüü ÜÜÜÜÜ} } 0 test string-3.20.$noComp {string equal, high bit} { - # This test will fail if the underlying comparaison + # This test will fail if the underlying comparison # is using signed chars instead of unsigned chars. # (like SunOS's default memcmp thus the compat/memcmp.c) run {string equal "\x80" "@"} @@ -298,10 +298,10 @@ test string-3.21.$noComp {string equal -nocase} { run {string equal -nocase abcde Abdef} } 0 test string-3.22.$noComp {string equal, -nocase unicode} { - run {string equal -nocase \334 \xDC} + run {string equal -nocase Ü Ü} } 1 test string-3.23.$noComp {string equal, -nocase unicode} { - run {string equal -nocase \334\334\334\374\xFC \334\334\334\334\334} + run {string equal -nocase ÜÜÜüü ÜÜÜÜÜ} } 1 test string-3.24.$noComp {string equal -nocase with length} { run {string equal -length 2 -nocase abcde Abxyz} @@ -318,7 +318,7 @@ test string-3.27.$noComp {string equal -nocase with excessive length} { test string-3.28.$noComp {string equal -len unicode} { # These are strings that are 6 BYTELENGTH long, but the length # shouldn't make a different because there are actually 3 CHARS long - run {string equal -len 5 \334\334\334 \334\334\374} + run {string equal -len 5 ÜÜÜ ÜÜü} } 0 test string-3.29.$noComp {string equal -nocase with special index} { list [catch {run {string equal -nocase -length end-3 Abcde abxyz}} msg] $msg @@ -391,19 +391,19 @@ test string-4.8.$noComp {string first} { run {string first "" x123xx345xxx789xxx012} } -1 test string-4.9.$noComp {string first, unicode} { - run {string first x abc\u7266x} + run {string first x abc牦x} } 4 test string-4.10.$noComp {string first, unicode} { - run {string first \u7266 abc\u7266x} + run {string first 牦 abc牦x} } 3 test string-4.11.$noComp {string first, start index} { - run {string first \u7266 abc\u7266x 3} + run {string first 牦 abc牦x 3} } 3 test string-4.12.$noComp {string first, start index} -body { - run {string first \u7266 abc\u7266x 4} + run {string first 牦 abc牦x 4} } -result -1 test string-4.13.$noComp {string first, start index} -body { - run {string first \u7266 abc\u7266x end-2} + run {string first 牦 abc牦x end-2} } -result 3 test string-4.14.$noComp {string first, negative start index} -body { run {string first b abc -1} @@ -412,7 +412,7 @@ test string-4.15.$noComp {string first, ability to two-byte encoded utf-8 chars} # Test for a bug in Tcl 8.3 where test for all-single-byte-encoded # strings was incorrect, leading to an index returned by [string first] # which pointed past the end of the string. - set uchar \u057E ;# character with two-byte encoding in utf-8 + set uchar վ ;# character with two-byte encoding in utf-8 run {string first % %#$uchar$uchar#$uchar$uchar#% 3} } -result 8 test string-4.16.$noComp {string first, normal string vs pure unicode string} -body { @@ -469,13 +469,13 @@ test string-5.9.$noComp {string index} { run {string index abc end-1} } b test string-5.10.$noComp {string index, unicode} { - run {string index abc\u7266d 4} + run {string index abc牦d 4} } d test string-5.11.$noComp {string index, unicode} { - run {string index abc\u7266d 3} -} \u7266 + run {string index abc牦d 3} +} 牦 test string-5.12.$noComp {string index, unicode over char length, under byte length} -body { - run {string index \334\374\334\374 6} + run {string index ÜüÜü 6} } -result {} test string-5.13.$noComp {string index, bytearray object} { run {string index [binary format a5 fuz] 0} @@ -551,7 +551,7 @@ test string-6.12.$noComp {string is alnum, true} { test string-6.13.$noComp {string is alnum, false} { list [run {string is alnum -failindex var abc1.23}] $var } {0 4} -test string-6.14.$noComp {string is alnum, unicode} "run {string is alnum abc\xFC}" 1 +test string-6.14.$noComp {string is alnum, unicode} "run {string is alnum abcü}" 1 test string-6.15.$noComp {string is alpha, true} { run {string is alpha abc} } 1 @@ -559,7 +559,7 @@ test string-6.16.$noComp {string is alpha, false} { list [run {string is alpha -fail var a1bcde}] $var } {0 1} test string-6.17.$noComp {string is alpha, unicode} { - run {string is alpha abc\374} + run {string is alpha abcü} } 1 test string-6.18.$noComp {string is ascii, true} { run {string is ascii abc\x7Fend\x00} @@ -583,7 +583,7 @@ test string-6.24.$noComp {string is digit, true} { run {string is digit 0123456789} } 1 test string-6.25.$noComp {string is digit, false} { - list [run {string is digit -fail var 0123\xDC567}] $var + list [run {string is digit -fail var 0123Ü567}] $var } {0 4} test string-6.26.$noComp {string is digit, false} { list [run {string is digit -fail var +123567}] $var @@ -706,7 +706,7 @@ test string-6.60.$noComp {string is lower, true} { run {string is lower abc} } 1 test string-6.61.$noComp {string is lower, unicode true} { - run {string is lower abc\xFCue} + run {string is lower abcüue} } 1 test string-6.62.$noComp {string is lower, false} { list [run {string is lower -fail var aBc}] $var @@ -715,7 +715,7 @@ test string-6.63.$noComp {string is lower, false} { list [run {string is lower -fail var abc1}] $var } {0 3} test string-6.64.$noComp {string is lower, unicode false} { - list [run {string is lower -fail var ab\xDCUE}] $var + list [run {string is lower -fail var abÜUE}] $var } {0 2} test string-6.65.$noComp {string is space, true} { run {string is space " \t\n\v\f"} @@ -753,7 +753,7 @@ test string-6.75.$noComp {string is upper, true} { run {string is upper ABC} } 1 test string-6.76.$noComp {string is upper, unicode true} { - run {string is upper ABC\xDCUE} + run {string is upper ABCÜUE} } 1 test string-6.77.$noComp {string is upper, false} { list [run {string is upper -fail var AbC}] $var @@ -762,13 +762,13 @@ test string-6.78.$noComp {string is upper, false} { list [run {string is upper -fail var AB2C}] $var } {0 2} test string-6.79.$noComp {string is upper, unicode false} { - list [run {string is upper -fail var ABC\xFCue}] $var + list [run {string is upper -fail var ABCüue}] $var } {0 3} test string-6.80.$noComp {string is wordchar, true} { run {string is wordchar abc_123} } 1 test string-6.81.$noComp {string is wordchar, unicode true} { - run {string is wordchar abc\xFCab\xDCAB\u5001\U1D7CA} + run {string is wordchar abcüabÜAB倁\U1D7CA} } 1 test string-6.82.$noComp {string is wordchar, false} { list [run {string is wordchar -fail var abcd.ef}] $var @@ -981,22 +981,22 @@ test string-7.6.$noComp {string last} { run {string las x xxxx123xx345x678} } 12 test string-7.7.$noComp {string last, unicode} { - run {string las x xxxx12\u7266xx345x678} + run {string las x xxxx12牦xx345x678} } 12 test string-7.8.$noComp {string last, unicode} { - run {string las \u7266 xxxx12\u7266xx345x678} + run {string las 牦 xxxx12牦xx345x678} } 6 test string-7.9.$noComp {string last, stop index} { - run {string las \u7266 xxxx12\u7266xx345x678} + run {string las 牦 xxxx12牦xx345x678} } 6 test string-7.10.$noComp {string last, unicode} { - run {string las \u7266 xxxx12\u7266xx345x678} + run {string las 牦 xxxx12牦xx345x678} } 6 test string-7.11.$noComp {string last, start index} { - run {string last \u7266 abc\u7266x 3} + run {string last 牦 abc牦x 3} } 3 test string-7.12.$noComp {string last, start index} { - run {string last \u7266 abc\u7266x 2} + run {string last 牦 abc牦x 2} } -1 test string-7.13.$noComp {string last, start index} { ## Constrain to last 'a' should work @@ -1007,10 +1007,10 @@ test string-7.14.$noComp {string last, start index} { run {string last ba badbad end-2} } 0 test string-7.15.$noComp {string last, start index} { - run {string last \334a \334ad\334ad 0} + run {string last Üa ÜadÜad 0} } -1 test string-7.16.$noComp {string last, start index} { - run {string last \334a \334ad\334ad end-1} + run {string last Üa ÜadÜad end-1} } 3 test string-8.1.$noComp {string bytelength} { @@ -1039,7 +1039,7 @@ test string-9.4.$noComp {string length} { run {string le ""} } 0 test string-9.5.$noComp {string length, unicode} { - run {string le "abcd\u7266"} + run {string le "abcd牦"} } 5 test string-9.6.$noComp {string length, bytearray object} { run {string length [binary format a5 foo]} @@ -1082,11 +1082,11 @@ test string-10.11.$noComp {string map, nulls} { run {string map {\x00 NULL blah \x00nix} {qwerty}} } {qwerty} test string-10.12.$noComp {string map, unicode} { - run {string map [list \374 ue UE \334] "a\374ueUE\000EU"} -} aueue\334\0EU + run {string map [list ü ue UE Ü] "aüueUE\x00EU"} +} aueueÜ\x00EU test string-10.13.$noComp {string map, -nocase unicode} { - run {string map -nocase [list \374 ue UE \334] "a\374ueUE\000EU"} -} aue\334\334\0EU + run {string map -nocase [list ü ue UE Ü] "aüueUE\x00EU"} +} aueÜÜ\x00EU test string-10.14.$noComp {string map, -nocase null arguments} { run {string map -nocase {{} abc} foo} } foo @@ -1290,7 +1290,7 @@ test string-11.32.$noComp {string match nocase} { run {string match -n a A} } 1 test string-11.33.$noComp {string match nocase} { - run {string match -nocase a\334 A\374} + run {string match -nocase aÜ Aü} } 1 test string-11.34.$noComp {string match nocase} { run {string match -nocase a*f ABCDEf} @@ -1457,11 +1457,11 @@ test string-12.16.$noComp {string range} { run {string range abcdefghijklmnop end end-1} } {} test string-12.17.$noComp {string range, unicode} { - run {string range ab\u7266cdefghijklmnop 5 5} + run {string range ab牦cdefghijklmnop 5 5} } e test string-12.18.$noComp {string range, unicode} { - run {string range ab\u7266cdefghijklmnop 2 3} -} \u7266c + run {string range ab牦cdefghijklmnop 2 3} +} 牦c test string-12.19.$noComp {string range, bytearray object} { set b [binary format I* {0x50515253 0x52}] set r1 [run {string range $b 1 end-1}] @@ -1544,15 +1544,15 @@ test string-13.11.$noComp {string repeat} { run {string repeat def 1} } def test string-13.12.$noComp {string repeat} { - run {string repeat ab\u7266cd 3} -} ab\u7266cdab\u7266cdab\u7266cd + run {string repeat ab牦cd 3} +} ab牦cdab牦cdab牦cd test string-13.13.$noComp {string repeat} { run {string repeat \x00 3} } \x00\x00\x00 test string-13.14.$noComp {string repeat} { # The string range will ensure us that string repeat gets a unicode string - run {string repeat [run {string range ab\u7266cd 2 3}] 3} -} \u7266c\u7266c\u7266c + run {string repeat [run {string range ab牦cd 2 3}] 3} +} 牦c牦c牦c test string-14.1.$noComp {string replace} { list [catch {run {string replace}} msg] $msg @@ -1614,6 +1614,18 @@ test string-14.20.$noComp {string replace} { run {string replace [makeByteArray abcdefghijklmnop] end-10 end-2\ [makeByteArray NEW]} } {abcdeNEWop} +test string-14.21.$noComp {string replace (surrogates)} { + run {string replace \uD83D? 1 end \uDE02} +} \uD83D\uDE02 +test string-14.22.$noComp {string replace (surrogates)} { + run {string replace ?\uDE02 0 end-1 \uD83D} +} \uD83D\uDE02 +test string-14.23.$noComp {string replace \xC0 \x80} testbytestring { + run {string length [string replace [testbytestring \xC0]? 1 end [testbytestring \x80]]} +} 2 +test string-14.24.$noComp {string replace \xC0 \x80} testbytestring { + run {string length [string replace ?[testbytestring \x80] 0 end-1 [testbytestring \xC0]]} +} 2 test stringComp-14.21.$noComp {Bug 82e7f67325} { @@ -1846,7 +1858,7 @@ test string-20.8.$noComp {[c61818e4c9] [string trimright] fails when UtfPrev is lappend result [string map $m [run {string trimright $b [testbytestring \xA0]}]] lappend result [string map $m [run {string trimright $b \xE8\xA0}]] lappend result [string map $m [run {string trimright $b [testbytestring \xE8\xA0]}]] - lappend result [string map $m [run {string trimright $b \u0000}]] + lappend result [string map $m [run {string trimright $b \x00}]] } [list {*}[lrepeat 4 fooUV] {*}[lrepeat 2 fooU] {*}[lrepeat 2 foo] fooUV] test string-21.1.$noComp {string wordend} -body { diff --git a/tests/stringObj.test b/tests/stringObj.test index 9937fa4..135830c 100644 --- a/tests/stringObj.test +++ b/tests/stringObj.test @@ -208,19 +208,19 @@ test stringObj-8.1 {DupStringInternalRep procedure} testobj { [teststringobj maxchars 2] [teststringobj get 2] } {5 10 0 abcde 5 5 0 abcde} test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi string length $x set y $x - list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \ + list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string" +} "string string abc\xEF\xBF\xAEghi\xAE\xBF\xEF abc\xEF\xBF\xAEghi string string" test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi set y $x string length $x - list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \ + list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string" +} "string string abc\xEF\xBF\xAEghi\xAE\xBF\xEF abc\xEF\xBF\xAEghi string string" test stringObj-8.4 {DupUnicodeInternalRep, all byte-size chars} testobj { set x abcdefghi string length $x @@ -237,31 +237,31 @@ test stringObj-8.5 {DupUnicodeInternalRep, all byte-size chars} testobj { } {string string abcdefghijkl abcdefghi string string} test stringObj-9.1 {TclAppendObjToObj, mixed src & dest} {testobj testdstring} { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi testdstring free - testdstring append \u00ae\u00bf\u00ef -1 + testdstring append \xAE\xBF\xEF -1 set y [testdstring get] string length $x list [testobj objtype $x] [testobj objtype $y] [append x $y] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string none abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none" +} "string none abc\xEF\xBF\xAEghi\xAE\xBF\xEF \xAE\xBF\xEF string none" test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi string length $x list [testobj objtype $x] [append x $x] [testobj objtype $x] \ [append x $x] [testobj objtype $x] -} "string abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi string\ -abc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghiabc\u00ef\u00bf\u00aeghi\ +} "string abc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghi string\ +abc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghiabc\xEF\xBF\xAEghi\ string" test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {testobj testdstring} { set x abcdefghi testdstring free - testdstring append \u00ae\u00bf\u00ef -1 + testdstring append \xAE\xBF\xEF -1 set y [testdstring get] string length $x list [testobj objtype $x] [testobj objtype $y] [append x $y] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string none abcdefghi\u00ae\u00bf\u00ef \u00ae\u00bf\u00ef string none" +} "string none abcdefghi\xAE\xBF\xEF \xAE\xBF\xEF string none" test stringObj-9.4 {TclAppendObjToObj, 1-byte src & dest} {testobj testdstring} { set x abcdefghi testdstring free @@ -279,14 +279,14 @@ test stringObj-9.5 {TclAppendObjToObj, 1-byte src & dest} testobj { } {string abcdefghiabcdefghi string abcdefghiabcdefghiabcdefghiabcdefghi\ string} test stringObj-9.6 {TclAppendObjToObj, 1-byte src & mixed dest} {testobj testdstring} { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi testdstring free testdstring append jkl -1 set y [testdstring get] string length $x list [testobj objtype $x] [testobj objtype $y] [append x $y] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string none abc\u00ef\u00bf\u00aeghijkl jkl string none" +} "string none abc\xEF\xBF\xAEghijkl jkl string none" test stringObj-9.7 {TclAppendObjToObj, integer src & dest} testobj { set x [expr {4 * 5}] set y [expr {4 + 5}] @@ -307,19 +307,19 @@ test stringObj-9.9 {TclAppendObjToObj, integer src & 1-byte dest} testobj { [set y] [testobj objtype $x] [testobj objtype $y] } {string int abcdefghi9 9 string int} test stringObj-9.10 {TclAppendObjToObj, integer src & mixed dest} testobj { - set x abc\u00ef\u00bf\u00aeghi + set x abc\xEF\xBF\xAEghi set y [expr {4 + 5}] string length $x list [testobj objtype $x] [testobj objtype $y] [append x $y] \ [set y] [testobj objtype $x] [testobj objtype $y] -} "string int abc\u00ef\u00bf\u00aeghi9 9 string int" +} "string int abc\xEF\xBF\xAEghi9 9 string int" test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} testobj { # bug 2678, in <=8.2.0, the second obj (the one to append) in # Tcl_AppendObjToObj was not correctly checked to see if it was all one # byte chars, so a unicode string would be added as one byte chars. set x abcdef set len [string length $x] - set y a\u00fcb\u00e5c\u00ef + set y a\xFCb\xE5c\xEF set len [string length $y] append x $y string length $x @@ -328,7 +328,7 @@ test stringObj-9.11 {TclAppendObjToObj, mixed src & 1-byte dest index check} tes lappend q [string index $x $i] } set q -} "a b c d e f a \u00fc b \u00e5 c \u00ef" +} "a b c d e f a \xFC b \xE5 c \xEF" test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {testobj testdstring} { testdstring free @@ -338,41 +338,30 @@ test stringObj-10.1 {Tcl_GetRange with all byte-size chars} {testobj testdstring [testobj objtype $x] [testobj objtype $y] } [list none bcde string string] test stringObj-10.2 {Tcl_GetRange with some mixed width chars} {testobj testdstring} { - # Because this test does not use \uXXXX notation below instead of - # hardcoding the values, it may fail in multibyte locales. However, we - # need to test that the parser produces untyped objects even when there - # are high-ASCII characters in the input (like "ï"). I don't know what - # else to do but inline those characters here. testdstring free - testdstring append "abc\u00ef\u00efdef" -1 + testdstring append "abcïïdef" -1 set x [testdstring get] list [testobj objtype $x] [set y [string range $x 1 end-1]] \ [testobj objtype $x] [testobj objtype $y] -} [list none "bc\u00EF\u00EFde" string string] +} [list none "bcïïde" string string] test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj { - # set x "abcïïdef" - # Use \uXXXX notation below instead of hardcoding the values, otherwise - # the test will fail in multibyte locales. - set x "abc\u00EF\u00EFdef" + set x "abcïïdef" string length $x list [testobj objtype $x] [set y [string range $x 1 end-1]] \ [testobj objtype $x] [testobj objtype $y] -} [list string "bc\u00EF\u00EFde" string string] +} [list string "bcïïde" string string] test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj { - # set a "ïa¿b®cï¿d®" - # Use \uXXXX notation below instead of hardcoding the values, otherwise - # the test will fail in multibyte locales. - set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE" + set a "ïa¿b®cï¿d®" set result [list] while {[string length $a] > 0} { set a [string range $a 1 end-1] lappend result $a } set result -} [list a\u00BFb\u00AEc\u00EF\u00BFd \ - \u00BFb\u00AEc\u00EF\u00BF \ - b\u00AEc\u00EF \ - \u00AEc \ +} [list a\xBFb\xAEc\xEF\xBFd \ + \xBFb\xAEc\xEF\xBF \ + b\xAEc\xEF \ + \xAEc \ {}] test stringObj-11.1 {UpdateStringOfString} testobj { @@ -394,15 +383,15 @@ test stringObj-12.3 {Tcl_GetUniChar with byte-size chars} testobj { list [string index $x end] [string index $x end-1] } {i h} test stringObj-12.4 {Tcl_GetUniChar with mixed width chars} testobj { - string index "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef" 0 -} "\u00ef" + string index "\xEFa\xBFb\xAEc\xAE\xBFd\xEF" 0 +} "\xEF" test stringObj-12.5 {Tcl_GetUniChar} testobj { - set x "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef" + set x "\xEFa\xBFb\xAEc\xAE\xBFd\xEF" list [string index $x 4] [string index $x 0] -} "\u00ae \u00ef" +} "\xAE \xEF" test stringObj-12.6 {Tcl_GetUniChar} testobj { - string index "\u00efa\u00bfb\u00aec\u00ef\u00bfd\u00ae" end -} "\u00ae" + string index "\xEFa\xBFb\xAEc\xEF\xBFd\xAE" end +} "\xAE" test stringObj-13.1 {Tcl_GetCharLength with byte-size chars} testobj { set a "" @@ -416,19 +405,19 @@ test stringObj-13.3 {Tcl_GetCharLength with byte-size chars} testobj { list [string length $a] [string length $a] } {6 6} test stringObj-13.4 {Tcl_GetCharLength with mixed width chars} testobj { - string length "\u00ae" + string length "\xAE" } 1 test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj { # string length "○○" # Use \uXXXX notation below instead of hardcoding the values, otherwise # the test will fail in multibyte locales. - string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE" + string length "\xEF\xBF\xAE\xEF\xBF\xAE" } 6 test stringObj-13.6 {Tcl_GetCharLength with mixed width chars} testobj { # set a "ïa¿b®cï¿d®" # Use \uXXXX notation below instead of hardcoding the values, otherwise # the test will fail in multibyte locales. - set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE" + set a "\xEFa\xBFb\xAEc\xEF\xBFd\xAE" list [string length $a] [string length $a] } {10 10} test stringObj-13.7 {Tcl_GetCharLength with identity nulls} {testobj testbytestring} { diff --git a/tests/subst.test b/tests/subst.test index 03a1ce2..da59c3b 100644 --- a/tests/subst.test +++ b/tests/subst.test @@ -48,7 +48,7 @@ test subst-3.2 {backslash substitutions with utf chars} { # 'j' is just a char that doesn't mean anything, and \344 is 'ä' # that also doesn't mean anything, but is multi-byte in UTF-8. list [subst \j] [subst \\j] [subst \\344] [subst \\\344] -} "j j \344 \344" +} "j j ä ä" test subst-4.1 {variable substitutions} { set a 44 diff --git a/tests/timer.test b/tests/timer.test index 1ad17ae..52c0b8a 100644 --- a/tests/timer.test +++ b/tests/timer.test @@ -367,7 +367,7 @@ test timer-6.23 {Tcl_AfterCmd procedure, no option, script with NUL} -setup { } } -body { set x "hello world" - after 1 "set x ab\0cd" + after 1 "set x ab\x00cd" after 10 update string length $x @@ -378,7 +378,7 @@ test timer-6.24 {Tcl_AfterCmd procedure, no option, script with NUL} -setup { } } -body { set x "hello world" - after 1 set x ab\0cd + after 1 set x ab\x00cd after 10 update string length $x @@ -389,8 +389,8 @@ test timer-6.25 {Tcl_AfterCmd procedure, cancel option, script with NUL} -setup } } -body { set x "hello world" - after 1 set x ab\0cd - after cancel "set x ab\0ef" + after 1 set x ab\x00cd + after cancel "set x ab\x00ef" llength [after info] } -cleanup { foreach i [after info] { @@ -403,8 +403,8 @@ test timer-6.26 {Tcl_AfterCmd procedure, cancel option, script with NUL} -setup } } -body { set x "hello world" - after 1 set x ab\0cd - after cancel set x ab\0ef + after 1 set x ab\x00cd + after cancel set x ab\x00ef llength [after info] } -cleanup { foreach i [after info] { @@ -417,7 +417,7 @@ test timer-6.27 {Tcl_AfterCmd procedure, idle option, script with NUL} -setup { } } -body { set x "hello world" - after idle "set x ab\0cd" + after idle "set x ab\x00cd" update string length $x } -result {5} @@ -427,7 +427,7 @@ test timer-6.28 {Tcl_AfterCmd procedure, idle option, script with NUL} -setup { } } -body { set x "hello world" - after idle set x ab\0cd + after idle set x ab\x00cd update string length $x } -result {5} @@ -438,7 +438,7 @@ test timer-6.29 {Tcl_AfterCmd procedure, info option, script with NUL} -setup { } -body { set x "hello world" set id junk - set id [after 10 set x ab\0cd] + set id [after 10 set x ab\x00cd] update string length [lindex [lindex [after info $id] 0] 2] } -cleanup { diff --git a/tests/unixInit.test b/tests/unixInit.test index aa3d50a..2ea7d8e 100644 --- a/tests/unixInit.test +++ b/tests/unixInit.test @@ -126,7 +126,7 @@ test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} -setup { set oldlibrary $env(TCL_LIBRARY) } } -body { - # ((str != NULL) && (str[0] != '\0')) + # ((str != NULL) && (str[0] != '\x00')) set env(TCL_LIBRARY) sparkly lindex [getlibpath] 0 } -cleanup { @@ -158,7 +158,7 @@ test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -setup { } } -body { # Child process translates env variable from native encoding. - set env(TCL_LIBRARY) "\xa7" + set env(TCL_LIBRARY) "§" lindex [getlibpath] 0 } -cleanup { unset -nocomplain env(TCL_LIBRARY) env(LANG) @@ -166,7 +166,7 @@ test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -setup { set env(TCL_LIBRARY) $oldlibrary unset oldlibrary } -} -result "\xa7" +} -result "§" test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} { # cannot test } {} diff --git a/tests/unload.test b/tests/unload.test index 29f534d..24b5e8d 100644 --- a/tests/unload.test +++ b/tests/unload.test @@ -53,22 +53,22 @@ proc loadIfNotPresent {pkg args} { # Basic tests: parameter testing... test unload-1.1 {basic errors} -returnCodes error -body { unload -} -result {wrong # args: should be "unload ?-switch ...? fileName ?packageName? ?interp?"} +} -result {wrong # args: should be "unload ?-switch ...? fileName ?prefix? ?interp?"} test unload-1.2 {basic errors} -returnCodes error -body { unload a b c d -} -result {wrong # args: should be "unload ?-switch ...? fileName ?packageName? ?interp?"} +} -result {wrong # args: should be "unload ?-switch ...? fileName ?prefix? ?interp?"} test unload-1.3 {basic errors} -returnCodes error -body { unload a b foobar } -result {could not find interpreter "foobar"} test unload-1.4 {basic errors} -returnCodes error -body { unload {} -} -result {must specify either file name or package name} +} -result {must specify either file name or prefix} test unload-1.5 {basic errors} -returnCodes error -body { unload {} {} -} -result {must specify either file name or package name} +} -result {must specify either file name or prefix} test unload-1.6 {basic errors} -returnCodes error -body { unload {} Unknown -} -result {package "Unknown" is loaded statically and cannot be unloaded} +} -result {library with prefix "Unknown" is loaded statically and cannot be unloaded} test unload-1.7 {-nocomplain switch} { unload -nocomplain {} Unknown } {} diff --git a/tests/utf.test b/tests/utf.test index b6c23ba..477216c 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -21,7 +21,6 @@ testConstraint fullutf [expr {[format %c 0x010000] ne "\uFFFD"}] testConstraint utf16 [expr {[string length [format %c 0x10000]] == 2}] testConstraint ucs4 [expr {[testConstraint fullutf] && [string length [format %c 0x10000]] == 1}] -testConstraint ucs2_utf16 [expr {![testConstraint ucs4]}] testConstraint Uesc [expr {"\U0041" eq "A"}] testConstraint pre388 [expr {"\x741" eq "A"}] @@ -50,7 +49,7 @@ test utf-1.3 {Tcl_UniCharToUtf: 2 byte sequences} testbytestring { expr {"\xE0" eq [testbytestring \xC3\xA0]} } 1 test utf-1.4 {Tcl_UniCharToUtf: 3 byte sequences} testbytestring { - expr {"\u4E4E" eq [testbytestring \xE4\xB9\x8E]} + expr {"乎" eq [testbytestring \xE4\xB9\x8E]} } 1 test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring { expr {[format %c 0x110000] eq [testbytestring \xEF\xBF\xBD]} @@ -58,10 +57,10 @@ test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring { test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring { expr {[format %c -1] eq [testbytestring \xEF\xBF\xBD]} } 1 -test utf-1.7.0 {Tcl_UniCharToUtf: 4 byte sequences} {fullutf Uesc testbytestring} { +test utf-1.7.0 {Tcl_UniCharToUtf: 4 byte sequences} {fullutf testbytestring} { expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]} } 1 -test utf-1.7.1 {Tcl_UniCharToUtf: 4 byte sequences} {ucs2 Uesc testbytestring} { +test utf-1.7.1 {Tcl_UniCharToUtf: 4 byte sequences} {Uesc ucs2 testbytestring} { expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]} } 0 test utf-1.8 {Tcl_UniCharToUtf: 3 byte sequence, high surrogate} testbytestring { @@ -79,9 +78,31 @@ test utf-1.11 {Tcl_UniCharToUtf: 3 byte sequence, low surrogate} testbytestring test utf-1.12 {Tcl_UniCharToUtf: 4 byte sequence, high/low surrogate} {pairsTo4bytes testbytestring} { expr {"\uD842\uDC42" eq [testbytestring \xF0\xA0\xA1\x82]} } 1 -test utf-1.13 {Tcl_UniCharToUtf: Invalid surrogate} {Uesc testbytestring} { +test utf-1.13.0 {Tcl_UniCharToUtf: Invalid surrogate} {Uesc ucs2} { + expr {"\UD842" eq "\uD842"} +} 1 +test utf-1.13.1 {Tcl_UniCharToUtf: Invalid surrogate} {fullutf testbytestring} { expr {"\UD842" eq [testbytestring \xEF\xBF\xBD]} } 1 +test utf-1.14 {Tcl_UniCharToUtf: surrogate pairs from concat} { + set lo \uDE02 + return \uD83D$lo +} \uD83D\uDE02 +test utf-1.15 {Tcl_UniCharToUtf: surrogate pairs from concat} { + set hi \uD83D + return $hi\uDE02 +} \uD83D\uDE02 +test utf-1.16 {Tcl_UniCharToUtf: \xC0 + \x80} testbytestring { + set lo [testbytestring \x80] + string length [testbytestring \xC0]$lo +} 2 +test utf-1.17 {Tcl_UniCharToUtf: \xC0 + \x80} testbytestring { + set hi [testbytestring \xC0] + string length $hi[testbytestring \x80] +} 2 +test utf-1.18 {Tcl_UniCharToUtf: surrogate pairs from concat} { + string cat \uD83D \uDE02 +} \uD83D\uDE02 test utf-2.1 {Tcl_UtfToUniChar: low ascii} { string length "abc" @@ -104,16 +125,22 @@ test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} testbytestrin test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} testbytestring { string length [testbytestring \xE4\xB9\x8E] } 1 -test utf-2.8.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs2_utf16} { +test utf-2.8.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {ucs2 testbytestring} { string length [testbytestring \xF0\x90\x80\x80] } 2 -test utf-2.8.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs4} { - string length [testbytestring \xF0\x90\x80\x80] +test utf-2.8.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} utf16 { + string length 𐀀 +} 2 +test utf-2.8.2 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} ucs4 { + string length 𐀀 } 1 -test utf-2.9.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {testbytestring ucs2} { +test utf-2.9.0 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {ucs2 testbytestring} { string length [testbytestring \xF4\x8F\xBF\xBF] } 2 -test utf-2.9.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {Uesc ucs4} { +test utf-2.9.1 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} utf16 { + string length \U10FFFF +} 2 +test utf-2.9.2 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} ucs4 { string length \U10FFFF } 1 test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} testbytestring { @@ -196,7 +223,7 @@ test utf-6.3 {Tcl_UtfNext} testutfnext { testutfnext AA } 1 test utf-6.4 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext A[testbytestring \xA0] + testutfnext [testbytestring A\xA0] } 1 test utf-6.5 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext A[testbytestring \xD0] @@ -216,7 +243,10 @@ test utf-6.9 {Tcl_UtfNext} {testutfnext testbytestring} { test utf-6.10 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xA0]G } 1 -test utf-6.11 {Tcl_UtfNext} {testutfnext testbytestring} { +test utf-6.11.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \xA0\xA0\x00] +} 1 +test utf-6.11.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xA0\xA0\x00] } 2 test utf-6.12 {Tcl_UtfNext} {testutfnext testbytestring} { @@ -273,19 +303,19 @@ test utf-6.28 {Tcl_UtfNext} {testutfnext testbytestring} { test utf-6.29 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xE8\xF8] } 1 -test utf-6.30.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.30.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2] } 1 -test utf-6.30.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.30.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\x00] } 1 test utf-6.31 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xF2]G } 1 -test utf-6.32.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.32.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0] } 1 -test utf-6.32.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.32.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\x00] } 1 test utf-6.33 {Tcl_UtfNext} {testutfnext testbytestring} { @@ -343,7 +373,7 @@ test utf-6.50 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xE8\xA0]G } 1 test utf-6.51 {Tcl_UtfNext} testutfnext { - testutfnext \u8820 + testutfnext 蠠 } 3 test utf-6.52 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xE8\xA0\xD0] @@ -376,30 +406,30 @@ test utf-6.61 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xF2\xA0\xF8] } 1 test utf-6.62 {Tcl_UtfNext} testutfnext { - testutfnext \u8820G + testutfnext 蠠G } 3 test utf-6.63 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext \u8820[testbytestring \xA0] + testutfnext [testbytestring \xE8\xA0\xA0\xA0] } 3 test utf-6.64 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext \u8820[testbytestring \xD0] + testutfnext 蠠[testbytestring \xD0] } 3 test utf-6.65 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext \u8820[testbytestring \xE8] + testutfnext 蠠[testbytestring \xE8] } 3 test utf-6.66 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext \u8820[testbytestring \xF2] + testutfnext 蠠[testbytestring \xF2] } 3 test utf-6.67 {Tcl_UtfNext} {testutfnext testbytestring} { - testutfnext \u8820[testbytestring \xF8] + testutfnext 蠠[testbytestring \xF8] } 3 test utf-6.68 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xF2\xA0\xA0]G } 1 -test utf-6.69.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.69.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0] } 1 -test utf-6.69.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.69.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0] } 4 test utf-6.70 {Tcl_UtfNext} {testutfnext testbytestring} { @@ -414,40 +444,40 @@ test utf-6.72 {Tcl_UtfNext} {testutfnext testbytestring} { test utf-6.73 {Tcl_UtfNext} {testutfnext testbytestring} { testutfnext [testbytestring \xF2\xA0\xA0\xF8] } 1 -test utf-6.74.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.74.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0]G } 1 -test utf-6.74.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.74.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0]G } 4 -test utf-6.75.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.75.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] } 1 -test utf-6.75.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.75.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0] } 4 -test utf-6.76.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.76.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0] } 1 -test utf-6.76.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.76.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0] } 4 -test utf-6.77.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.77.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8] } 1 -test utf-6.77.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.77.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8] } 4 -test utf-6.78.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.78.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2] } 1 -test utf-6.78.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.78.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2] } 4 -test utf-6.79.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2_utf16} { +test utf-6.79.0 {Tcl_UtfNext} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8] } 1 -test utf-6.79.1 {Tcl_UtfNext} {testutfnext testbytestring ucs4} { +test utf-6.79.1 {Tcl_UtfNext} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF2\xA0\xA0\xA0G\xF8] } 4 test utf-6.80 {Tcl_UtfNext - overlong sequences} testutfnext { @@ -471,37 +501,55 @@ test utf-6.85 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} { test utf-6.86 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring} { testutfnext [testbytestring \xF0\x80\x80\x80] } 1 -test utf-6.87.0 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs2_utf16} { +test utf-6.87.0 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF0\x90\x80\x80] } 1 -test utf-6.87.1 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring ucs4} { +test utf-6.87.1 {Tcl_UtfNext - overlong sequences} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF0\x90\x80\x80] } 4 -test utf-6.88 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring} { +test utf-6.88.0 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \xA0\xA0\x00] +} 1 +test utf-6.88.1 {Tcl_UtfNext, pointing to 2th byte of 3-byte valid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xA0\xA0\x00] } 2 -test utf-6.89 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring} { +test utf-6.89.0 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \x80\x80\x00] +} 1 +test utf-6.89.1 {Tcl_UtfNext, pointing to 2th byte of 3-byte invalid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \x80\x80\x00] } 2 -test utf-6.90.0 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs2_utf16} { +test utf-6.90.0 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs2} { testutfnext [testbytestring \xF4\x8F\xBF\xBF] } 1 -test utf-6.90.1 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring ucs4} { +test utf-6.90.1 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xF4\x8F\xBF\xBF] } 4 test utf-6.91 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring} { testutfnext [testbytestring \xF4\x90\x80\x80] } 1 -test utf-6.92 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring} { +test utf-6.92.0 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \xA0\xA0\xA0] +} 1 +test utf-6.92.1 {Tcl_UtfNext, pointing to 2th byte of 4-byte valid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xA0\xA0\xA0] } 3 -test utf-6.93 {Tcl_UtfNext, pointing to 2th byte of 4-byte invalid sequence} {testutfnext testbytestring} { +test utf-6.93.0 {Tcl_UtfNext, pointing to 2th byte of 4-byte invalid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \x80\x80\x80] +} 1 +test utf-6.93.1 {Tcl_UtfNext, pointing to 2th byte of 4-byte invalid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \x80\x80\x80] } 3 -test utf-6.94 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring} { +test utf-6.94.0 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \xA0\xA0\xA0\xA0] +} 1 +test utf-6.94.1 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \xA0\xA0\xA0\xA0] } 3 -test utf-6.95 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring} { +test utf-6.95.0 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring ucs2} { + testutfnext [testbytestring \x80\x80\x80\x80] +} 1 +test utf-6.95.1 {Tcl_UtfNext, pointing to 2th byte of 5-byte invalid sequence} {testutfnext testbytestring fullutf} { testutfnext [testbytestring \x80\x80\x80\x80] } 3 @@ -536,7 +584,7 @@ test utf-7.6 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xE8] } 1 test utf-7.6.1 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A\u8820[testbytestring \xA0] 2 + testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 2 } 1 test utf-7.6.2 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xE8\xF8\xA0\xA0] 2 @@ -551,13 +599,13 @@ test utf-7.7.2 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xD0\xF8\xA0\xA0] 2 } 1 test utf-7.8 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0] + testutfprev [testbytestring A\xA0] } 1 test utf-7.8.1 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 2 + testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 2 } 1 test utf-7.8.2 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0\xF8\xA0\xA0] 2 + testutfprev [testbytestring A\xA0\xF8\xA0\xA0] 2 } 1 test utf-7.9 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xF8\xA0] @@ -590,7 +638,7 @@ test utf-7.11 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xE8\xA0] } 1 test utf-7.11.1 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A\u8820[testbytestring \xA0] 3 + testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 3 } 1 test utf-7.11.2 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xE8\xA0\xF8\xA0] 3 @@ -608,13 +656,13 @@ test utf-7.12.2 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xD0\xA0\xF8\xA0] 3 } 1 test utf-7.13 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0\xA0] + testutfprev [testbytestring A\xA0\xA0] } 2 test utf-7.13.1 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 3 + testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 3 } 2 test utf-7.13.2 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A[testbytestring \xA0\xA0\xF8\xA0] 3 + testutfprev [testbytestring A\xA0\xA0\xF8\xA0] 3 } 2 test utf-7.14 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xF8\xA0\xA0] @@ -644,13 +692,13 @@ test utf-7.15.5 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} { testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4 } 1 test utf-7.16 {Tcl_UtfPrev} testutfprev { - testutfprev A\u8820 + testutfprev A蠠 } 1 test utf-7.16.1 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A\u8820[testbytestring \xA0] 4 + testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 4 } 1 test utf-7.16.2 {Tcl_UtfPrev} {testutfprev testbytestring} { - testutfprev A\u8820[testbytestring \xF8] 4 + testutfprev A蠠[testbytestring \xF8] 4 } 1 test utf-7.17 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xD0\xA0\xA0] @@ -661,30 +709,33 @@ test utf-7.17.1 {Tcl_UtfPrev} {testutfprev testbytestring} { test utf-7.17.2 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xD0\xA0\xA0\xF8] 4 } 3 -test utf-7.18.0 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xA0\xA0\xA0] -} 1 -test utf-7.18.1 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 4 -} 1 -test utf-7.18.2 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xA0\xA0\xA0\xF8] 4 +test utf-7.18.0 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev [testbytestring A\xA0\xA0\xA0] +} 3 +test utf-7.18.1 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 4 +} 3 +test utf-7.18.2 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev [testbytestring A\xA0\xA0\xA0\xF8] 4 +} 3 +test utf-7.19 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev [testbytestring A\xF8\xA0\xA0\xA0] +} 4 +test utf-7.20.0 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} { + testutfprev [testbytestring A\xF2\xA0\xA0\xA0] +} 4 +test utf-7.20.1 {Tcl_UtfPrev} {testutfprev testbytestring fullutf} { + testutfprev [testbytestring A\xF2\xA0\xA0\xA0] } 1 -test utf-7.19 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xF8\xA0\xA0\xA0] -} 2 -test utf-7.20 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xF2\xA0\xA0\xA0] -} 2 -test utf-7.21 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A\u8820[testbytestring \xA0] -} 2 -test utf-7.22 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { +test utf-7.21 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev A[testbytestring \xE8\xA0\xA0\xA0] +} 4 +test utf-7.22 {Tcl_UtfPrev} {testutfprev testbytestring} { testutfprev A[testbytestring \xD0\xA0\xA0\xA0] -} 2 -test utf-7.23 {Tcl_UtfPrev} {testutfprev testbytestring utf16} { - testutfprev A[testbytestring \xA0\xA0\xA0\xA0] -} 2 +} 4 +test utf-7.23 {Tcl_UtfPrev} {testutfprev testbytestring} { + testutfprev [testbytestring A\xA0\xA0\xA0\xA0] +} 4 test utf-7.24 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { testutfprev A[testbytestring \xC0\x81] } 2 @@ -706,9 +757,9 @@ test utf-7.28 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { test utf-7.28.1 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { testutfprev A[testbytestring \xE0\x80\x80] 2 } 1 -test utf-7.29 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring utf16} { +test utf-7.29 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { testutfprev A[testbytestring \xF0\x80\x80\x80] -} 2 +} 4 test utf-7.30 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { testutfprev A[testbytestring \xF0\x80\x80\x80] 4 } 3 @@ -736,9 +787,12 @@ test utf-7.37 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { test utf-7.38 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring} { testutfprev A[testbytestring \xE0\xA0\x80] 2 } 1 -test utf-7.39 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring utf16} { +test utf-7.39.0 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring ucs2} { testutfprev A[testbytestring \xF0\x90\x80\x80] -} 2 +} 4 +test utf-7.39.1 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring fullutf} { + testutfprev A[testbytestring \xF0\x90\x80\x80] +} 1 test utf-7.40.0 {Tcl_UtfPrev -- overlong sequence} {testutfprev testbytestring ucs2} { testutfprev A[testbytestring \xF0\x90\x80\x80] 4 } 3 @@ -763,39 +817,42 @@ test utf-7.44 {Tcl_UtfPrev -- no lead byte at start} {testutfprev testbytestrin test utf-7.45 {Tcl_UtfPrev -- no lead byte at start} {testutfprev testbytestring} { testutfprev [testbytestring \xA0\xA0\xA0] } 2 -test utf-7.46 {Tcl_UtfPrev -- no lead byte at start} {testutfprev testbytestring utf16} { +test utf-7.46 {Tcl_UtfPrev -- no lead byte at start} {testutfprev testbytestring} { testutfprev [testbytestring \xA0\xA0\xA0\xA0] -} 1 +} 3 test utf-7.47 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} {testutfprev testbytestring} { testutfprev [testbytestring \xE8\xA0] } 0 test utf-7.47.1 {Tcl_UtfPrev, pointing to 3th byte of 3-byte valid sequence} testutfprev { - testutfprev \u8820 2 + testutfprev 蠠 2 } 0 test utf-7.47.2 {Tcl_UtfPrev, pointing to 3th byte of 3-byte invalid sequence} {testutfprev testbytestring} { testutfprev [testbytestring \xE8\xA0\x00] 2 } 0 -test utf-7.48.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring utf16} { +test utf-7.48.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] -} 2 -test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} { +} 4 +test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} { + testutfprev A[testbytestring \xF4\x8F\xBF\xBF] +} 1 +test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4 } 3 -test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} { +test utf-7.48.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4 } 1 -test utf-7.48.3 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} { +test utf-7.48.4 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3 } 2 -test utf-7.48.4 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} { +test utf-7.48.5 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring fullutf} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3 } 1 -test utf-7.48.5 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} { +test utf-7.48.6 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} { testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 2 } 1 -test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring utf16} { +test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} { testutfprev A[testbytestring \xF4\x90\x80\x80] -} 2 +} 4 test utf-7.49.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} { testutfprev A[testbytestring \xF4\x90\x80\x80] 4 } 3 @@ -810,14 +867,14 @@ test utf-8.1 {Tcl_UniCharAtIndex: index = 0} { string index abcd 0 } a test utf-8.2 {Tcl_UniCharAtIndex: index = 0} { - string index \u4E4E\u25A 0 -} \u4E4E + string index 乎ɚ 0 +} 乎 test utf-8.3 {Tcl_UniCharAtIndex: index > 0} { string index abcd 2 } c test utf-8.4 {Tcl_UniCharAtIndex: index > 0} { - string index \u4E4E\u25A\xFF\u543 2 -} \xFF + string index 乎ɚÿՃ 2 +} ÿ test utf-8.5.0 {Tcl_UniCharAtIndex: high surrogate} ucs2 { string index \uD842 0 } \uD842 @@ -834,116 +891,116 @@ test utf-8.7.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { string index \uD83D\uDE00G 0 } \uD83D test utf-8.7.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { - string index \uD83D\uDE00G 0 -} \U1F600 + string index 😀G 0 +} 😀 test utf-8.7.2 {Tcl_UniCharAtIndex: Emoji} utf16 { - string index \uD83D\uDE00G 0 -} \U1F600 + string index 😀G 0 +} 😀 test utf-8.8.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { string index \uD83D\uDE00G 1 } \uDE00 test utf-8.8.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { - string index \uD83D\uDE00G 1 + string index 😀G 1 } G test utf-8.8.2 {Tcl_UniCharAtIndex: Emoji} utf16 { - string index \uD83D\uDE00G 1 + string index 😀G 1 } {} test utf-8.9.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { string index \uD83D\uDE00G 2 } G test utf-8.9.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { - string index \uD83D\uDE00G 2 + string index 😀G 2 } {} test utf-8.9.2 {Tcl_UniCharAtIndex: Emoji} utf16 { - string index \uD83D\uDE00G 2 + string index 😀G 2 } G -test utf-8.10.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} { - string index \U1F600G 0 +test utf-8.10.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { + string index 😀G 0 } \uFFFD -test utf-8.10.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} { - string index \U1F600G 0 -} \U1F600 -test utf-8.10.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} { - string index \U1F600G 0 -} \U1F600 -test utf-8.11.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} { - string index \U1F600G 1 +test utf-8.10.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { + string index 😀G 0 +} 😀 +test utf-8.10.2 {Tcl_UniCharAtIndex: Emoji} utf16 { + string index 😀G 0 +} 😀 +test utf-8.11.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { + string index 😀G 1 } G -test utf-8.11.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} { - string index \U1F600G 1 +test utf-8.11.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { + string index 😀G 1 } G -test utf-8.11.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} { - string index \U1F600G 1 +test utf-8.11.2 {Tcl_UniCharAtIndex: Emoji} utf16 { + string index 😀G 1 } {} -test utf-8.12.0 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs2} { - string index \U1F600G 2 +test utf-8.12.0 {Tcl_UniCharAtIndex: Emoji} ucs2 { + string index 😀G 2 } {} -test utf-8.12.1 {Tcl_UniCharAtIndex: Emoji} {Uesc ucs4} { - string index \U1F600G 2 +test utf-8.12.1 {Tcl_UniCharAtIndex: Emoji} ucs4 { + string index 😀G 2 } {} -test utf-8.12.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} { - string index \U1F600G 2 +test utf-8.12.2 {Tcl_UniCharAtIndex: Emoji} utf16 { + string index 😀G 2 } G test utf-9.1 {Tcl_UtfAtIndex: index = 0} { string range abcd 0 2 } abc test utf-9.2 {Tcl_UtfAtIndex: index > 0} { - string range \u4E4E\u25A\xFF\u543klmnop 1 5 -} \u25A\xFF\u543kl + string range 乎ɚÿՃklmnop 1 5 +} ɚÿՃkl test utf-9.3.0 {Tcl_UtfAtIndex: index = 0, Emoji} ucs2 { string range \uD83D\uDE00G 0 0 } \uD83D test utf-9.3.1 {Tcl_UtfAtIndex: index = 0, Emoji} ucs4 { - string range \uD83D\uDE00G 0 0 -} \U1F600 + string range 😀G 0 0 +} 😀 test utf-9.3.2 {Tcl_UtfAtIndex: index = 0, Emoji} utf16 { - string range \uD83D\uDE00G 0 0 -} \U1F600 + string range 😀G 0 0 +} 😀 test utf-9.4.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 { string range \uD83D\uDE00G 1 1 } \uDE00 test utf-9.4.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 { - string range \uD83D\uDE00G 1 1 + string range 😀G 1 1 } G test utf-9.4.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 { - string range \uD83D\uDE00G 1 1 + string range 😀G 1 1 } {} test utf-9.5.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 { string range \uD83D\uDE00G 2 2 } G test utf-9.5.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 { - string range \uD83D\uDE00G 2 2 + string range 😀G 2 2 } {} test utf-9.5.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 { - string range \uD83D\uDE00G 2 2 + string range 😀G 2 2 } G -test utf-9.6.0 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc ucs2} { - string range \U1f600G 0 0 +test utf-9.6.0 {Tcl_UtfAtIndex: index = 0, Emoji} ucs2 { + string range 😀G 0 0 } \uFFFD -test utf-9.6.1 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc ucs4} { - string range \U1f600G 0 0 -} \U1F600 -test utf-9.6.2 {Tcl_UtfAtIndex: index = 0, Emoji} {Uesc utf16} { - string range \U1f600G 0 0 -} \U1F600 -test utf-9.7.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} { - string range \U1f600G 1 1 +test utf-9.6.1 {Tcl_UtfAtIndex: index = 0, Emoji} ucs4 { + string range 😀G 0 0 +} 😀 +test utf-9.6.2 {Tcl_UtfAtIndex: index = 0, Emoji} utf16 { + string range 😀G 0 0 +} 😀 +test utf-9.7.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 { + string range 😀G 1 1 } G -test utf-9.7.1 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs4} { - string range \U1f600G 1 1 +test utf-9.7.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 { + string range 😀G 1 1 } G -test utf-9.7.2 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc utf16} { - string range \U1f600G 1 1 +test utf-9.7.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 { + string range 😀G 1 1 } {} -test utf-9.8.0 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs2} { - string range \U1f600G 2 2 +test utf-9.8.0 {Tcl_UtfAtIndex: index > 0, Emoji} ucs2 { + string range 😀G 2 2 } {} -test utf-9.8.1 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc ucs4} { - string range \U1f600G 2 2 +test utf-9.8.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 { + string range 😀G 2 2 } {} -test utf-9.8.2 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc utf16} { - string range \U1f600G 2 2 +test utf-9.8.2 {Tcl_UtfAtIndex: index > 0, Emoji} utf16 { + string range 😀G 2 2 } G test utf-10.1 {Tcl_UtfBackslash: dst == NULL} { @@ -962,10 +1019,10 @@ test utf-10.4 {Tcl_UtfBackslash: stops at first non-hex} testbytestring { test utf-10.5 {Tcl_UtfBackslash: stops after 4 hex chars} testbytestring { expr {"\u4E216" eq "[testbytestring \xE4\xB8\xA1]6"} } 1 -test utf-10.6 {Tcl_UtfBackslash: stops after 5 hex chars} {Uesc fullutf testbytestring} { +test utf-10.6 {Tcl_UtfBackslash: stops after 5 hex chars} {fullutf testbytestring} { expr {"\U1E2165" eq "[testbytestring \xF0\x9E\x88\x96]5"} } 1 -test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} {Uesc fullutf testbytestring} { +test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} {fullutf testbytestring} { expr {"\U10E2165" eq "[testbytestring \xF4\x8E\x88\x96]5"} } 1 @@ -1028,13 +1085,13 @@ bsCheck \U4E21 20001 Uesc bsCheck \U004E21 20001 Uesc bsCheck \U00004E21 20001 Uesc bsCheck \U0000004E21 78 Uesc -bsCheck \U00110000 69632 {Uesc fullutf} -bsCheck \U01100000 69632 {Uesc fullutf} -bsCheck \U11000000 69632 {Uesc fullutf} -bsCheck \U0010FFFF 1114111 {Uesc fullutf} -bsCheck \U010FFFF0 1114111 {Uesc fullutf} -bsCheck \U10FFFF00 1114111 {Uesc fullutf} -bsCheck \UFFFFFFFF 1048575 {Uesc fullutf} +bsCheck \U00110000 69632 fullutf +bsCheck \U01100000 69632 fullutf +bsCheck \U11000000 69632 fullutf +bsCheck \U0010FFFF 1114111 fullutf +bsCheck \U010FFFF0 1114111 fullutf +bsCheck \U10FFFF00 1114111 fullutf +bsCheck \UFFFFFFFF 1048575 fullutf test utf-11.1 {Tcl_UtfToUpper} { string toupper {} @@ -1046,17 +1103,17 @@ test utf-11.3 {Tcl_UtfToUpper} { string toupper \xE3gh } \xC3GH test utf-11.4 {Tcl_UtfToUpper} { - string toupper \u01E3gh -} \u01E2GH + string toupper ǣgh +} ǢGH test utf-11.5 {Tcl_UtfToUpper Georgian (new in Unicode 11)} { - string toupper \u10D0\u1C90 -} \u1C90\u1C90 -test utf-11.6 {Tcl_UtfToUpper beyond U+FFFF} {Uesc fullutf} { - string toupper \U10428 -} \U10400 + string toupper აᲐ +} ᲐᲐ +test utf-11.6 {Tcl_UtfToUpper beyond U+FFFF} fullutf { + string toupper 𐐨 +} 𐐀 test utf-11.7 {Tcl_UtfToUpper beyond U+FFFF} fullutf { - string toupper \uD801\uDC28 -} \uD801\uDC00 + string toupper 𐐨 +} 𐐀 test utf-11.8 {Tcl_UtfToUpper low/high surrogate)} { string toupper \uDC24\uD824 } \uDC24\uD824 @@ -1068,23 +1125,23 @@ test utf-12.2 {Tcl_UtfToLower} { string tolower ABC } abc test utf-12.3 {Tcl_UtfToLower} { - string tolower \xC3GH -} \xE3gh + string tolower ÃGH +} ãgh test utf-12.4 {Tcl_UtfToLower} { - string tolower \u01E2GH -} \u01E3gh + string tolower ǢGH +} ǣgh test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} { - string tolower \u10D0\u1C90 -} \u10D0\u10D0 + string tolower აᲐ +} აა test utf-12.6 {Tcl_UtfToLower low/high surrogate)} { string tolower \uDC24\uD824 } \uDC24\uD824 -test utf-12.7 {Tcl_UtfToLower beyond U+FFFF} {Uesc fullutf} { - string tolower \U10400 -} \U10428 +test utf-12.7 {Tcl_UtfToLower beyond U+FFFF} fullutf { + string tolower 𐐀 +} 𐐨 test utf-12.8 {Tcl_UtfToLower beyond U+FFFF} fullutf { - string tolower \uD801\uDC00 -} \uD801\uDC28 + string tolower 𐐀 +} 𐐨 test utf-13.1 {Tcl_UtfToTitle} { string totitle {} @@ -1093,26 +1150,26 @@ test utf-13.2 {Tcl_UtfToTitle} { string totitle abc } Abc test utf-13.3 {Tcl_UtfToTitle} { - string totitle \xE3GH -} \xC3gh + string totitle ãGH +} Ãgh test utf-13.4 {Tcl_UtfToTitle} { - string totitle \u01F3AB -} \u01F2ab + string totitle dzAB +} Dzab test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} { - string totitle \u10D0\u1C90 -} \u10D0\u1C90 + string totitle აᲐ +} აᲐ test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} { - string totitle \u1C90\u10D0 -} \u1C90\u10D0 + string totitle Აა +} Აა test utf-13.7 {Tcl_UtfToTitle low/high surrogate)} { string totitle \uDC24\uD824 } \uDC24\uD824 -test utf-13.8 {Tcl_UtfToTitle beyond U+FFFF} {Uesc fullutf} { - string totitle \U10428\U10400 -} \U10400\U10428 +test utf-13.8 {Tcl_UtfToTitle beyond U+FFFF} fullutf { + string totitle 𐐨𐐀 +} 𐐀𐐨 test utf-13.9 {Tcl_UtfToTitle beyond U+FFFF} fullutf { - string totitle \uD801\uDC28\uD801\uDC00 -} \uD801\uDC00\uD801\uDC28 + string totitle 𐐨𐐀 +} 𐐀𐐨 test utf-14.1 {Tcl_UtfNcasecmp} { string compare -nocase a b @@ -1131,8 +1188,8 @@ test utf-15.1 {Tcl_UniCharToUpper, negative delta} { string toupper aA } AA test utf-15.2 {Tcl_UniCharToUpper, positive delta} { - string toupper \u0178\xFF -} \u0178\u0178 + string toupper Ÿÿ +} ŸŸ test utf-15.3 {Tcl_UniCharToUpper, no delta} { string toupper ! } ! @@ -1141,25 +1198,25 @@ test utf-16.1 {Tcl_UniCharToLower, negative delta} { string tolower aA } aa test utf-16.2 {Tcl_UniCharToLower, positive delta} { - string tolower \u0178\xFF\uA78D\u01C5 -} \xFF\xFF\u0265\u01C6 + string tolower ŸÿꞍDž +} ÿÿɥdž test utf-17.1 {Tcl_UniCharToLower, no delta} { string tolower ! } ! test utf-18.1 {Tcl_UniCharToTitle, add one for title} { - string totitle \u01C4 -} \u01C5 + string totitle DŽ +} Dž test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} { - string totitle \u01C6 -} \u01C5 + string totitle dž +} Dž test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} { - string totitle \u017F -} \x53 + string totitle ſ +} S test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} { - string totitle \xFF -} \u0178 + string totitle ÿ +} Ÿ test utf-18.5 {Tcl_UniCharToTitle, no delta} { string totitle ! } ! @@ -1173,25 +1230,7 @@ test utf-19.1 {TclUniCharLen} -body { test utf-20.1 {TclUniCharNcmp} ucs4 { string compare [string range [format %c 0xFFFF] 0 0] [string range [format %c 0x10000] 0 0] } -1 -test utf-20.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} ucs2 { - set one [format %c 0xFFFF] - set two [format %c 0x10000] - set first [string compare $one $two] - string range $one 0 0 - string range $two 0 0 - set second [string compare $one $two] - expr {($first == $second) ? "agree" : "disagree"} -} agree -test utf-20.2.1 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} {utf16 knownBug} { - set one [format %c 0xFFFF] - set two [format %c 0x10000] - set first [string compare $one $two] - string range $one 0 0 - string range $two 0 0 - set second [string compare $one $two] - expr {($first == $second) ? "agree" : "disagree"} -} agree -test utf-20.2.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} ucs4 { +test utf-20.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} { set one [format %c 0xFFFF] set two [format %c 0x10000] set first [string compare $one $two] @@ -1203,23 +1242,23 @@ test utf-20.2.2 {[4c591fa487] TclUniCharNcmp/TclUtfNcmp} ucs4 { test utf-21.1 {TclUniCharIsAlnum} { # this returns 1 with Unicode 7 compliance - string is alnum \u1040\u021F\u0220 + string is alnum ၀ȟȠ } 1 test utf-21.2 {unicode alnum char in regc_locale.c} { # this returns 1 with Unicode 7 compliance - list [regexp {^[[:alnum:]]+$} \u1040\u021F\u0220] [regexp {^\w+$} \u1040\u021F\u0220_\u203F\u2040\u2054\uFE33\uFE34\uFE4D\uFE4E\uFE4F\uFF3F] + list [regexp {^[[:alnum:]]+$} ၀ȟȠ] [regexp {^\w+$} ၀ȟȠ_‿⁀⁔︳︴﹍﹎﹏_] } {1 1} test utf-21.3 {unicode print char in regc_locale.c} { # this returns 1 with Unicode 7 compliance - regexp {^[[:print:]]+$} \uFBC1 + regexp {^[[:print:]]+$} ﯁ } 1 test utf-21.4 {TclUniCharIsGraph} { # [Bug 3464428] - string is graph \u0120 + string is graph Ġ } 1 test utf-21.5 {unicode graph char in regc_locale.c} { # [Bug 3464428] - regexp {^[[:graph:]]+$} \u0120 + regexp {^[[:graph:]]+$} Ġ } 1 test utf-21.6 {TclUniCharIsGraph} { # [Bug 3464428] @@ -1254,25 +1293,25 @@ test utf-22.1 {TclUniCharIsWordChar} { string wordend "xyz123_bar fg" 0 } 10 test utf-22.2 {TclUniCharIsWordChar} { - string wordend "x\u5080z123_bar\u203C fg" 0 + string wordend "x傀z123_bar‼ fg" 0 } 10 test utf-23.1 {TclUniCharIsAlpha} { # this returns 1 with Unicode 7 compliance - string is alpha \u021F\u0220\u037F\u052F + string is alpha ȟȠͿԯ } 1 test utf-23.2 {unicode alpha char in regc_locale.c} { # this returns 1 with Unicode 7 compliance - regexp {^[[:alpha:]]+$} \u021F\u0220\u037F\u052F + regexp {^[[:alpha:]]+$} ȟȠͿԯ } 1 test utf-24.1 {TclUniCharIsDigit} { # this returns 1 with Unicode 7 compliance - string is digit \u1040\uABF0 + string is digit ၀꯰ } 1 test utf-24.2 {unicode digit char in regc_locale.c} { # this returns 1 with Unicode 7 compliance - list [regexp {^[[:digit:]]+$} \u1040\uABF0] [regexp {^\d+$} \u1040\uABF0] + list [regexp {^[[:digit:]]+$} ၀꯰] [regexp {^\d+$} ၀꯰] } {1 1} test utf-24.3 {TclUniCharIsSpace} { @@ -1319,9 +1358,9 @@ UniCharCaseCmpTest > b a UniCharCaseCmpTest > B a UniCharCaseCmpTest > aBcB abca UniCharCaseCmpTest < \uFFFF [format %c 0x10000] ucs4 -UniCharCaseCmpTest < \uFFFF \U10000 {Uesc ucs4} +UniCharCaseCmpTest < \uFFFF \U10000 ucs4 UniCharCaseCmpTest > [format %c 0x10000] \uFFFF ucs4 -UniCharCaseCmpTest > \U10000 \uFFFF {Uesc ucs4} +UniCharCaseCmpTest > \U10000 \uFFFF ucs4 test utf-26.1 {Tcl_UniCharDString} -setup { diff --git a/tests/util.test b/tests/util.test index 29cf651..f610762 100644 --- a/tests/util.test +++ b/tests/util.test @@ -33,9 +33,9 @@ proc testIEEE {} { switch -exact -- $c { {0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} { # little endian - binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \ ieeeValues(-Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \ ieeeValues(-Normal) binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \ ieeeValues(-Subnormal) @@ -45,23 +45,23 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \ ieeeValues(+Subnormal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \ ieeeValues(+Normal) - binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \ ieeeValues(+Infinity) - binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \ ieeeValues(NaN) - binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \ + binary scan \x00\x00\x00\x00\x00\x00\xF8\xFF d \ ieeeValues(-NaN) - binary scan \xef\xcd\xab\x89\x67\x45\xfb\xff d \ + binary scan \xEF\xCD\xAB\x89\x67\x45\xFB\xFF d \ ieeeValues(-NaN(3456789abcdef)) set ieeeValues(littleEndian) 1 return 1 } {-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} { - binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Infinity) - binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Normal) binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-Subnormal) @@ -71,15 +71,15 @@ proc testIEEE {} { ieeeValues(+0) binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Subnormal) - binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Normal) - binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \ ieeeValues(+Infinity) - binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(NaN) - binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \ + binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \ ieeeValues(-NaN) - binary scan \xff\xfb\x45\x67\x89\xab\xcd\xef d \ + binary scan \xFF\xFB\x45\x67\x89\xAB\xCD\xEF d \ ieeeValues(-NaN(3456789abcdef)) set ieeeValues(littleEndian) 0 return 1 @@ -207,9 +207,9 @@ test util-4.5 {Tcl_ConcatObj - backslash-space at end of argument} { concat a { } c } {a c} test util-4.6 {Tcl_ConcatObj - utf-8 sequence with "whitespace" char} { - # Check for Bug #227512. If this violates C isspace, then it returns \xc3. - concat \xe0 -} \xe0 + # Check for Bug #227512. If this violates C isspace, then it returns \xC3. + concat \xE0 +} \xE0 test util-4.7 {Tcl_ConcatObj - refCount safety} testconcatobj { # Check for Bug #1447328 (actually, bugs in its original "fix"). One of the # symptoms was Bug #2055782. @@ -239,14 +239,14 @@ test util-5.6 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch *3*6*9 01234567890 } 0 test util-5.7 {Tcl_StringMatch: UTF-8} { - Wrapper_Tcl_StringMatch *u \u4e4fu + Wrapper_Tcl_StringMatch *u 乏u } 1 test util-5.8 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch a?c abc } 1 test util-5.9 {Tcl_StringMatch: UTF-8} { # skip one character in string - Wrapper_Tcl_StringMatch a?c a\u4e4fc + Wrapper_Tcl_StringMatch a?c a乏c } 1 test util-5.10 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch a??c abc @@ -259,15 +259,15 @@ test util-5.12 {Tcl_StringMatch} { } 1 test util-5.13 {Tcl_StringMatch: UTF-8} { # string += Tcl_UtfToUniChar(string, &ch); - Wrapper_Tcl_StringMatch "\[\u4e4fxy\]bc" "\u4e4fbc" + Wrapper_Tcl_StringMatch "\[乏xy\]bc" "乏bc" } 1 test util-5.14 {Tcl_StringMatch} { - # if ((*pattern == ']') || (*pattern == '\0')) + # if ((*pattern == ']') || (*pattern == '\x00')) # badly formed pattern Wrapper_Tcl_StringMatch {[]} {[]} } 0 test util-5.15 {Tcl_StringMatch} { - # if ((*pattern == ']') || (*pattern == '\0')) + # if ((*pattern == ']') || (*pattern == '\x00')) # badly formed pattern Wrapper_Tcl_StringMatch {[} {[} } 0 @@ -277,17 +277,17 @@ test util-5.16 {Tcl_StringMatch} { test util-5.17 {Tcl_StringMatch: UTF-8} { # pattern += Tcl_UtfToUniChar(pattern, &endChar); # get 1 UTF-8 character - Wrapper_Tcl_StringMatch "a\[a\u4e4fc]c" "a\u4e4fc" + Wrapper_Tcl_StringMatch "a\[a乏c]c" "a乏c" } 1 test util-5.18 {Tcl_StringMatch: UTF-8} testbytestring { # pattern += Tcl_UtfToUniChar(pattern, &endChar); - # proper advance: wrong answer would match on UTF trail byte of \u4e4f - Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} [testbytestring a\x8fc] + # proper advance: wrong answer would match on UTF trail byte of 乏 + Wrapper_Tcl_StringMatch {a[a乏c]c} [testbytestring a\x8Fc] } 0 test util-5.19 {Tcl_StringMatch: UTF-8} { # pattern += Tcl_UtfToUniChar(pattern, &endChar); # proper advance. - Wrapper_Tcl_StringMatch {a[a\u4e4fc]c} "acc" + Wrapper_Tcl_StringMatch {a[a乏c]c} "acc" } 1 test util-5.20 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch {a[xyz]c} abc @@ -296,13 +296,13 @@ test util-5.21 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch {12[2-7]45} 12345 } 1 test util-5.22 {Tcl_StringMatch: UTF-8 range} { - Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "0" + Wrapper_Tcl_StringMatch "\[一-乏]" "0" } 0 test util-5.23 {Tcl_StringMatch: UTF-8 range} { - Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\u4e33" + Wrapper_Tcl_StringMatch "\[一-乏]" "丳" } 1 test util-5.24 {Tcl_StringMatch: UTF-8 range} { - Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\uff08" + Wrapper_Tcl_StringMatch "\[一-乏]" "(" } 0 test util-5.25 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch {12[ab2-4cd]45} 12345 @@ -356,16 +356,16 @@ test util-5.41 {Tcl_StringMatch: skip correct number of ']'} { Wrapper_Tcl_StringMatch {[A-]]x} Ax } 1 test util-5.42 {Tcl_StringMatch: skip correct number of ']'} { - Wrapper_Tcl_StringMatch {[A-]]x} \ue1x + Wrapper_Tcl_StringMatch {[A-]]x} \xE1x } 0 test util-5.43 {Tcl_StringMatch: skip correct number of ']'} { - Wrapper_Tcl_StringMatch \[A-]\ue1]x \ue1x + Wrapper_Tcl_StringMatch \[A-]\xE1]x \xE1x } 1 test util-5.44 {Tcl_StringMatch: skip correct number of ']'} { Wrapper_Tcl_StringMatch {[A-]h]x} hx } 1 test util-5.45 {Tcl_StringMatch} { - # if (*pattern == '\0') + # if (*pattern == '\x00') # badly formed pattern, still treats as a set Wrapper_Tcl_StringMatch {[a} a } 1 @@ -388,7 +388,7 @@ test util-5.51 {Tcl_StringMatch} { Wrapper_Tcl_StringMatch "" "" } 1 test util-5.52 {Tcl_StringMatch} { - Wrapper_Tcl_StringMatch \[a\u0000 a\x80 + Wrapper_Tcl_StringMatch \[a\x00 a\x80 } 0 @@ -483,27 +483,27 @@ test util-8.1 {TclNeedSpace - correct utf-8 handling} { # which calls on TclNeedSpace(). If [interp target] # is ever updated, this test will no longer test # TclNeedSpace. - interp create \u5420 - interp create [list \u5420 foo] - interp alias {} fooset [list \u5420 foo] set + interp create 吠 + interp create [list 吠 foo] + interp alias {} fooset [list 吠 foo] set set result [interp target {} fooset] - interp delete \u5420 + interp delete 吠 set result -} "\u5420 foo" +} "吠 foo" test util-8.2 {TclNeedSpace - correct utf-8 handling} testdstring { # Bug 411825 # This tests the same bug as the previous test, but # should be more future-proof, as the DString # operations will likely continue to call TclNeedSpace testdstring free - testdstring append \u5420 -1 + testdstring append 吠 -1 testdstring element foo llength [testdstring get] } 2 test util-8.3 {TclNeedSpace - correct utf-8 handling} testdstring { # Bug 411825 - new variant reported by Dossy Shiobara testdstring free - testdstring append \u00A0 -1 + testdstring append \xA0 -1 testdstring element foo llength [testdstring get] } 2 diff --git a/tests/var.test b/tests/var.test index a8d4b84..3ca1a76 100644 --- a/tests/var.test +++ b/tests/var.test @@ -203,27 +203,27 @@ test var-1.19 {TclLookupVar, right error message when parsing variable name} -bo [format set] thisvar(doesntexist) } -returnCodes error -result {can't read "thisvar(doesntexist)": no such variable} test var-1.20 {TclLookupVar, regression on utf-8 variable names} -setup { - proc p [list \u20ac \xe4] {info vars} + proc p [list € ä] {info vars} } -body { # test variable with non-ascii name is available (euro and a-uml chars here): list \ [p 1 2] \ - [apply [list [list \u20ac \xe4] {info vars}] 1 2] \ - [apply [list [list [list \u20ac \u20ac] [list \xe4 \xe4]] {info vars}]] \ + [apply [list [list € ä] {info vars}] 1 2] \ + [apply [list [list [list € €] [list ä ä]] {info vars}]] \ } -cleanup { rename p {} -} -result [lrepeat 3 [list \u20ac \xe4]] +} -result [lrepeat 3 [list € ä]] test var-1.21 {TclLookupVar, regression on utf-8 variable names} -setup { - proc p [list [list \u20ac v\u20ac] [list \xe4 v\xe4]] {list [set \u20ac] [set \xe4]} + proc p [list [list € v€] [list ä vä]] {list [set €] [set ä]} } -body { # test variable with non-ascii name (and default) is resolvable (euro and a-uml chars here): list \ [p] \ - [apply [list [list \u20ac \xe4] {list [set \u20ac] [set \xe4]}] v\u20ac v\xe4] \ - [apply [list [list [list \u20ac v\u20ac] [list \xe4 v\xe4]] {list [set \u20ac] [set \xe4]}]] \ + [apply [list [list € ä] {list [set €] [set ä]}] v€ vä] \ + [apply [list [list [list € v€] [list ä vä]] {list [set €] [set ä]}]] \ } -cleanup { rename p {} -} -result [lrepeat 3 [list v\u20ac v\xe4]] +} -result [lrepeat 3 [list v€ vä]] test var-2.1 {Tcl_LappendObjCmd, create var if new} { catch {unset x} diff --git a/tests/winPipe.test b/tests/winPipe.test index 6252f96..28d4f5b 100644 --- a/tests/winPipe.test +++ b/tests/winPipe.test @@ -174,7 +174,7 @@ test winpipe-1.21 {32 bit comprehensive tests: read/write application} \ {win exec cat32} { set f [open "|[list $cat32]" r+] puts $f $big - puts $f \032 + puts $f \x1A flush $f set r [read $f 64] catch {close $f} diff --git a/tests/zipfs.test b/tests/zipfs.test index 8689268..bf9c969 100644 --- a/tests/zipfs.test +++ b/tests/zipfs.test @@ -270,6 +270,137 @@ test zipfs-3.4 {zipfs in child interpreters} -constraints zipfs -setup { } -returnCodes error -cleanup { interp delete $safe } -result {not allowed to invoke subcommand mkzip of zipfs} + +test zipfs-4.1 {zipfs lmkimg} -constraints zipfs -setup { + set baseImage [makeFile "return sourceWorking\n\x1A" base] + set targetImage [makeFile "" target] + set addFile [makeFile "return mountWorking" add.data] + file delete $targetImage +} -body { + zipfs lmkimg $targetImage [list $addFile test/add.tcl] {} $baseImage + zipfs mount ziptest $targetImage + try { + list [source $targetImage] [source //zipfs:/ziptest/test/add.tcl] + } finally { + zipfs unmount ziptest + } +} -cleanup { + removeFile $baseImage + removeFile $targetImage + removeFile $addFile +} -result {sourceWorking mountWorking} +test zipfs-4.2 {zipfs lmkimg: making an image from an image} -constraints zipfs -setup { + set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl] + set midImage [makeFile "" mid_image.tcl] + set targetImage [makeFile "" target_image.tcl] + set addFile [makeFile "return mountWorking" add.data] + file delete $midImage $targetImage +} -body { + zipfs lmkimg $midImage [list $addFile test/ko.tcl] {} $baseImage + zipfs lmkimg $targetImage [list $addFile test/ok.tcl] {} $midImage + zipfs mount ziptest $targetImage + try { + list [glob -tails -directory //zipfs://ziptest/test *.tcl] \ + [if {[file size $midImage] == [file size $targetImage]} { + string cat equal + } else { + list mid=[file size $midImage] target=[file size $targetImage] + }] + } finally { + zipfs unmount ziptest + } +} -cleanup { + removeFile $baseImage + removeFile $midImage + removeFile $targetImage + removeFile $addFile +} -result {ok.tcl equal} +test zipfs-4.3 {zipfs lmkimg: stripping password} -constraints zipfs -setup { + set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl] + set midImage [makeFile "" mid_image.tcl] + set targetImage [makeFile "" target_image.tcl] + set addFile [makeFile "return mountWorking" add.data] + file delete $midImage $targetImage +} -body { + set pass gorp + zipfs lmkimg $midImage [list $addFile test/add.tcl] $pass $baseImage + zipfs lmkimg $targetImage [list $addFile test/ok.tcl] {} $midImage + zipfs mount ziptest $targetImage + try { + glob -tails -directory //zipfs://ziptest/test *.tcl + } finally { + zipfs unmount ziptest + } +} -cleanup { + removeFile $baseImage + removeFile $midImage + removeFile $targetImage + removeFile $addFile +} -result {ok.tcl} +test zipfs-4.4 {zipfs lmkimg: final password} -constraints zipfs -setup { + set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl] + set midImage [makeFile "" mid_image.tcl] + set targetImage [makeFile "" target_image.tcl] + set addFile [makeFile "return mountWorking" add.data] + file delete $midImage $targetImage +} -body { + set pass gorp + zipfs lmkimg $midImage [list $addFile test/add.tcl] {} $baseImage + zipfs lmkimg $targetImage [list $addFile test/ok.tcl] $pass $midImage + zipfs mount ziptest $targetImage + try { + glob -tails -directory //zipfs://ziptest/test *.tcl + } finally { + zipfs unmount ziptest + } +} -cleanup { + removeFile $baseImage + removeFile $midImage + removeFile $targetImage + removeFile $addFile +} -result {ok.tcl} +test zipfs-4.5 {zipfs lmkimg: making image from mounted} -constraints zipfs -setup { + set baseImage [makeFile "return sourceWorking\n\x1A" base_image.tcl] + set midImage [makeFile "" mid_image.tcl] + set targetImage [makeFile "" target_image.tcl] + set addFile [makeFile "return mountWorking" add.data] + file delete $midImage $targetImage +} -body { + zipfs lmkimg $midImage [list $addFile test/add.tcl] {} $baseImage + zipfs mount ziptest $midImage + set f [glob -directory //zipfs://ziptest/test *.tcl] + zipfs lmkimg $targetImage [list $f test/ok.tcl] {} $midImage + zipfs unmount ziptest + zipfs mount ziptest $targetImage + list $f [glob -directory //zipfs://ziptest/test *.tcl] +} -cleanup { + zipfs unmount ziptest + removeFile $baseImage + removeFile $midImage + removeFile $targetImage + removeFile $addFile +} -result {//zipfs://ziptest/test/add.tcl //zipfs://ziptest/test/ok.tcl} + +test zipfs-5.1 {zipfs mount_data: short data} -constraints zipfs -body { + zipfs mount_data gorp {} +} -returnCodes error -result {bad zip data} +test zipfs-5.2 {zipfs mount_data: short data} -constraints zipfs -body { + zipfs mount_data gorp gorpGORPgorp +} -returnCodes error -result {bad zip data} +test zipfs-5.3 {zipfs mount_data: short data} -constraints zipfs -body { + set data PK\x03\x04..................................... + append data PK\x01\x02..................................... + append data PK\x05\x06..................................... + zipfs mount_data gorp $data +} -returnCodes error -result {bad zip data} +test zipfs-5.4 {zipfs mount_data: bad arg count} -constraints zipfs -body { + zipfs mount_data gorp {} foobar +} -returnCodes error -result {wrong # args: should be "zipfs mount_data ?mountpoint? ?data?"} + +test zipfs-6.1 {zipfs mkkey} -constraints zipfs -body { + binary scan [zipfs mkkey gorp] cu* x + return $x +} -result {224 226 111 103 4 80 75 90 90} ::tcltest::cleanupTests return diff --git a/tools/README b/tools/README index f4bf627..a37c2f4 100644 --- a/tools/README +++ b/tools/README @@ -9,17 +9,12 @@ uniClass.tcl -- Script for generating regexp class tables from the Tcl "string is" classes Generating HTML files. -The tcl-tk-man-html.tcl script from Robert Critchlow -generates a nice set of HTML with good cross references. -Use it like - tclsh tcl-tk-man-html.tcl --htmldir=/tmp/tcl8.2 +The tcltk-man2html.tcl script generates a nice set of HTML with +good cross references. Use it like + cd unix + ./configure + make html This script is very picky about the organization of man pages, effectively acting as a style enforcer. - -Generating Windows Help Files: -1) Build tcl in the ../unix directory -2) On UNIX, (after autoconf and configure), do - make - this converts the Nroff to RTF files. -2) On Windows, convert the RTF to a Help doc, do - nmake helpfile +The resulting documentation can be found at + /tmp/dist/tcl<version>/html diff --git a/tools/genStubs.tcl b/tools/genStubs.tcl index 47b8ad4..4f4acbb 100644 --- a/tools/genStubs.tcl +++ b/tools/genStubs.tcl @@ -1214,7 +1214,7 @@ proc genStubs::init {} { # Results: # Returns any values that were not assigned to variables. -if {[string length [namespace which lassign]] == 0} { +if {[namespace which lassign] ne ""} { proc lassign {valueList args} { if {[llength $args] == 0} { error "wrong # args: should be \"lassign list varName ?varName ...?\"" diff --git a/tools/tcltk-man2html-utils.tcl b/tools/tcltk-man2html-utils.tcl index 2d82bb1..b7a8520 100644 --- a/tools/tcltk-man2html-utils.tcl +++ b/tools/tcltk-man2html-utils.tcl @@ -1314,6 +1314,7 @@ proc make-manpage-section {outputDir sectionDescriptor} { set manual(wing-copyrights) {} makedirhier $outputDir/$manual(wing-file) set manual(wing-toc-fp) [open $outputDir/$manual(wing-file)/[indexfile] w] + fconfigure $manual(wing-toc-fp) -translation lf -encoding utf-8 # whistle puts stderr "scanning section $manual(wing-name)" # put the entry for this section into the short table of contents @@ -1364,6 +1365,7 @@ proc make-manpage-section {outputDir sectionDescriptor} { continue } set manual(infp) [open $manual(page)] + fconfigure $manual(infp) -encoding utf-8 set manual(text) {} set manual(partial-text) {} foreach p {.RS .DS .CS .SO} { diff --git a/tools/tcltk-man2html.tcl b/tools/tcltk-man2html.tcl index efb7a13..0e87531 100755 --- a/tools/tcltk-man2html.tcl +++ b/tools/tcltk-man2html.tcl @@ -67,7 +67,7 @@ proc findversion {top name useversion} { # to do # use glob matching instead of string matching or add # brace handling to [string matcch] - if {$useversion eq {} || [string match $useversion $major.$minor]} { + if {$useversion eq "" || [string match $useversion $major.$minor]} { set top [file dirname [file dirname $tclh]] set prefix [file dirname $top] return [list $prefix [file tail $top] $major $minor] @@ -172,17 +172,17 @@ proc parse_command_line {} { # Find Tcl (firstly using glob pattern / backwards compatible way) set tcldir [lindex [lsort [glob -nocomplain -tails -type d \ -directory $tcltkdir tcl$useversion]] end] - if {$tcldir ne {}} { + if {$tcldir ne ""} { # obtain version from generic header if we can: lassign [getversion [file join $tcltkdir $tcldir generic tcl.h]] major minor } else { lassign [findversion $tcltkdir tcl $useversion] tcltkdir tcldir major minor } - if {$tcldir eq {} && $opt_build_tcl} { + if {$tcldir eq "" && $opt_build_tcl} { puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir" exit 1 } - puts "using Tcl source directory $tcltkdir $tcldir" + puts "using Tcl source directory [file join $tcltkdir $tcldir]" } @@ -190,19 +190,19 @@ proc parse_command_line {} { # Find Tk (firstly using glob pattern / backwards compatible way) set tkdir [lindex [lsort [glob -nocomplain -tails -type d \ -directory $tcltkdir tk$useversion]] end] - if {$tkdir ne {}} { + if {$tkdir ne ""} { if {$major eq ""} { # obtain version from generic header if we can: - lassign [getversion [file join $tcltkdir $tcldir generic tk.h]] major minor + lassign [getversion [file join $tcltkdir $tkdir generic tk.h]] major minor } } else { lassign [findversion $tcltkdir tk $useversion] tcltkdir tkdir major minor } - if {$tkdir eq {} && $opt_build_tk} { + if {$tkdir eq "" && $opt_build_tk} { puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir" exit 1 } - puts "using Tk source directory $tkdir" + puts "using Tk source directory [file join $tcltkdir $tkdir]" } puts "verbose messages are [expr {$verbose ? {on} : {off}}]" @@ -329,10 +329,12 @@ proc make-man-pages {html args} { makedirhier $html set cssfd [open $html/$::CSSFILE w] + fconfigure $cssfd -translation lf -encoding utf-8 puts $cssfd [css-stylesheet] close $cssfd set manual(short-toc-n) 1 set manual(short-toc-fp) [open $html/[indexfile] w] + fconfigure $manual(short-toc-fp) -translation lf -encoding utf-8 puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title] puts $manual(short-toc-fp) "<dl class=\"keylist\">" set manual(merge-copyrights) {} @@ -370,6 +372,7 @@ proc make-man-pages {html args} { file delete -force -- $html/Keywords makedirhier $html/Keywords set keyfp [open $html/Keywords/[indexfile] w] + fconfigure $keyfp -translation lf -encoding utf-8 puts $keyfp [htmlhead "$tcltkdesc Keywords" "$tcltkdesc Keywords" \ $overall_title "../[indexfile]"] set letters {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} @@ -393,6 +396,7 @@ proc make-man-pages {html args} { } # Per-keyword page set afp [open $html/Keywords/$a.html w] + fconfigure $afp -translation lf -encoding utf-8 puts $afp [htmlhead "$tcltkdesc Keywords - $a" \ "$tcltkdesc Keywords - $a" \ $overall_title "../[indexfile]"] @@ -469,6 +473,7 @@ proc make-man-pages {html args} { puts -nonewline stderr . } set outfd [open $html/$manual(wing-file)/$manual(name).html w] + fconfigure $outfd -translation lf -encoding utf-8 puts $outfd [htmlhead "$manual($manual(wing-file)-$manual(name)-title)" \ $manual(name) $wing_name "[indexfile]" \ $overall_title "../[indexfile]"] @@ -511,6 +516,7 @@ proc plus-base {var root glob name dir desc} { if {$var} { if {[file exists $tcltkdir/$root/README]} { set f [open $tcltkdir/$root/README] + fconfigure $f -encoding utf-8 set d [read $f] close $f if {[regexp {This is the \w+ (\S+) source distribution} $d -> version]} { @@ -746,6 +752,7 @@ try { } trap {POSIX ENOENT} {} { set f [open [file join $pkgsDir $dir configure.ac]] } + fconfigure $f -encoding utf-8 foreach line [split [read $f] \n] { if {2 == [scan $line \ { AC_INIT ( [%[^]]] , [%[^]]] ) } n v]} { @@ -770,6 +777,7 @@ try { set packageDirNameMap {} if {$build_tcl} { set f [open $tcltkdir/$tcldir/pkgs/package.list.txt] + fconfigure $f -encoding utf-8 try { foreach line [split [read $f] \n] { if {[string trim $line] eq ""} continue diff --git a/tools/tsdPerf.c b/tools/tsdPerf.c index 7a599e0..4c96f28 100644 --- a/tools/tsdPerf.c +++ b/tools/tsdPerf.c @@ -1,6 +1,6 @@ #include <tcl.h> -extern DLLEXPORT Tcl_PackageInitProc Tsdperf_Init; +extern DLLEXPORT Tcl_LibraryInitProc Tsdperf_Init; static Tcl_ThreadDataKey key; diff --git a/unix/Makefile.in b/unix/Makefile.in index 25c69ea..bd018d2 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -671,7 +671,8 @@ UNIX_SRCS = \ NOTIFY_SRCS = \ $(UNIX_DIR)/tclEpollNotfy.c \ $(UNIX_DIR)/tclKqueueNotfy.c \ - $(UNIX_DIR)/tclSelectNotfy.c + $(UNIX_DIR)/tclSelectNotfy.c \ + $(UNIX_DIR)/tclUnixNotfy.c DL_SRCS = \ $(UNIX_DIR)/tclLoadAix.c \ @@ -945,6 +946,9 @@ shell: ${TCL_EXE} gdb: ${TCL_EXE} $(SHELL_ENV) $(GDB) ./${TCL_EXE} +lldb: ${TCL_EXE} + $(SHELL_ENV) $(LLDB) ./${TCL_EXE} + valgrind: ${TCL_EXE} ${TCLTEST_EXE} $(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \ $(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \ @@ -1773,13 +1777,13 @@ tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c $(FSHDR) $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFile.c -tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c +tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c $(UNIX_DIR)/tclUnixNotfy.c $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.c -tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c +tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c $(UNIX_DIR)/tclUnixNotfy.c $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclKqueueNotfy.c -tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c +tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c $(UNIX_DIR)/tclUnixNotfy.c $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclSelectNotfy.c tclUnixPipe.o: $(UNIX_DIR)/tclUnixPipe.c diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c index 3587f35..f3caae7 100644 --- a/unix/tclAppInit.c +++ b/unix/tclAppInit.c @@ -15,15 +15,19 @@ #undef BUILD_tcl #undef STATIC_BUILD #include "tcl.h" +#if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7 +# define Tcl_LibraryInitProc Tcl_PackageInitProc +# define Tcl_StaticLibrary Tcl_StaticPackage +#endif #ifdef TCL_TEST -extern Tcl_PackageInitProc Tcltest_Init; -extern Tcl_PackageInitProc Tcltest_SafeInit; +extern Tcl_LibraryInitProc Tcltest_Init; +extern Tcl_LibraryInitProc Tcltest_SafeInit; #endif /* TCL_TEST */ #ifdef TCL_XT_TEST extern void XtToolkitInitialize(void); -extern Tcl_PackageInitProc Tclxttest_Init; +extern Tcl_LibraryInitProc Tclxttest_Init; #endif /* TCL_XT_TEST */ /* @@ -79,7 +83,8 @@ main( #ifdef TCL_LOCAL_MAIN_HOOK TCL_LOCAL_MAIN_HOOK(&argc, &argv); -#else +#elif !defined(_WIN32) || defined(UNICODE) + /* This doesn't work on Windows without UNICODE */ TclZipfs_AppHook(&argc, &argv); #endif @@ -124,7 +129,7 @@ Tcl_AppInit( if (Tcltest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } - Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); + Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); #endif /* TCL_TEST */ /* diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c index 3a99e6d..23c88b2 100644 --- a/unix/tclEpollNotfy.c +++ b/unix/tclEpollNotfy.c @@ -97,7 +97,7 @@ typedef struct ThreadSpecificData { * that are ready for I/O. */ pthread_mutex_t notifierMutex; /* Mutex protecting notifier termination in - * PlatformEventsFinalize. */ + * TclpFinalizeNotifier. */ #ifdef HAVE_EVENTFD int triggerEventFd; /* eventfd(2) used by other threads to wake * up this thread for inter-thread IPC. */ @@ -121,14 +121,13 @@ static Tcl_ThreadDataKey dataKey; static void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew); -static void PlatformEventsFinalize(void); static void PlatformEventsInit(void); static int PlatformEventsTranslate(struct epoll_event *event); static int PlatformEventsWait(struct epoll_event *events, size_t numEvents, struct timeval *timePtr); - + /* - * Incorporate the base notifier API. + * Incorporate the base notifier implementation. */ #include "tclUnixNotfy.c" @@ -136,7 +135,7 @@ static int PlatformEventsWait(struct epoll_event *events, /* *---------------------------------------------------------------------- * - * Tcl_InitNotifier -- + * TclpInitNotifier -- * * Initializes the platform specific notifier state. * @@ -144,54 +143,21 @@ static int PlatformEventsWait(struct epoll_event *events, * Returns a handle to the notifier state for this thread. * * Side effects: - * If no initNotifierProc notifier hook exists, PlatformEventsInit - * is called. + * If no initNotifierProc notifier hook exists, PlatformEventsInit is + * called. * *---------------------------------------------------------------------- */ ClientData -Tcl_InitNotifier(void) +TclpInitNotifier(void) { - if (tclNotifierHooks.initNotifierProc) { - return tclNotifierHooks.initNotifierProc(); - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - PlatformEventsInit(); - return tsdPtr; - } + PlatformEventsInit(); + return tsdPtr; } -/* - *---------------------------------------------------------------------- - * - * Tcl_FinalizeNotifier -- - * - * This function is called to cleanup the notifier state before a thread - * is terminated. - * - * Results: - * None. - * - * Side effects: - * If no finalizeNotifierProc notifier hook exists, PlatformEvents- - * Finalize is called. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_FinalizeNotifier( - ClientData clientData) -{ - if (tclNotifierHooks.finalizeNotifierProc) { - tclNotifierHooks.finalizeNotifierProc(clientData); - return; - } else { - PlatformEventsFinalize(); - } -} /* *---------------------------------------------------------------------- @@ -221,7 +187,7 @@ Tcl_FinalizeNotifier( *---------------------------------------------------------------------- */ -void +static void PlatformEventsControl( FileHandler *filePtr, ThreadSpecificData *tsdPtr, @@ -240,7 +206,8 @@ PlatformEventsControl( newEvent.events |= EPOLLOUT; } if (isNew) { - newPedPtr = (struct PlatformEventData *)ckalloc(sizeof(struct PlatformEventData)); + newPedPtr = (struct PlatformEventData *) + ckalloc(sizeof(struct PlatformEventData)); newPedPtr->filePtr = filePtr; newPedPtr->tsdPtr = tsdPtr; filePtr->pedPtr = newPedPtr; @@ -249,7 +216,7 @@ PlatformEventsControl( /* * N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not support - * regular files (S_IFREG.) Therefore, filePtr is in these cases simply + * regular files (S_IFREG). Therefore, filePtr is in these cases simply * added or deleted from the list of FileHandlers associated with regular * files belonging to tsdPtr. */ @@ -277,7 +244,7 @@ PlatformEventsControl( /* *---------------------------------------------------------------------- * - * PlatformEventsFinalize -- + * TclpFinalizeNotifier -- * * This function closes the eventfd and the epoll file descriptor and * frees the epoll_event structs owned by the thread of the caller. The @@ -299,8 +266,8 @@ PlatformEventsControl( */ void -PlatformEventsFinalize( - void) +TclpFinalizeNotifier( + TCL_UNUSED(ClientData)) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -362,7 +329,7 @@ PlatformEventsFinalize( *---------------------------------------------------------------------- */ -void +static void PlatformEventsInit(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -372,7 +339,7 @@ PlatformEventsInit(void) if (errno) { Tcl_Panic("Tcl_InitNotifier: %s", "could not create mutex"); } - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); #ifdef HAVE_EVENTFD tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (tsdPtr->triggerEventFd <= 0) { @@ -393,7 +360,7 @@ PlatformEventsInit(void) PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1); if (!tsdPtr->readyEvents) { tsdPtr->maxReadyEvents = 512; - tsdPtr->readyEvents = (struct epoll_event *)ckalloc( + tsdPtr->readyEvents = (struct epoll_event *) ckalloc( tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0])); } LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr); @@ -416,7 +383,7 @@ PlatformEventsInit(void) *---------------------------------------------------------------------- */ -int +static int PlatformEventsTranslate( struct epoll_event *eventPtr) { @@ -457,7 +424,7 @@ PlatformEventsTranslate( *---------------------------------------------------------------------- */ -int +static int PlatformEventsWait( struct epoll_event *events, size_t numEvents, @@ -480,9 +447,9 @@ PlatformEventsWait( } else if (!timePtr->tv_sec && !timePtr->tv_usec) { timeout = 0; } else { - timeout = (int)timePtr->tv_sec * 1000; + timeout = (int) timePtr->tv_sec * 1000; if (timePtr->tv_usec) { - timeout += (int)timePtr->tv_usec / 1000; + timeout += (int) timePtr->tv_usec / 1000; } } @@ -493,7 +460,7 @@ PlatformEventsWait( */ gettimeofday(&tv0, NULL); - numFound = epoll_wait(tsdPtr->eventsFd, events, (int)numEvents, timeout); + numFound = epoll_wait(tsdPtr->eventsFd, events, (int) numEvents, timeout); gettimeofday(&tv1, NULL); if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) { timersub(&tv1, &tv0, &tv_delta); @@ -510,7 +477,7 @@ PlatformEventsWait( /* *---------------------------------------------------------------------- * - * Tcl_CreateFileHandler -- + * TclpCreateFileHandler -- * * This function registers a file handler with the epoll notifier of the * thread of the caller. @@ -526,7 +493,7 @@ PlatformEventsWait( */ void -Tcl_CreateFileHandler( +TclpCreateFileHandler( int fd, /* Handle of stream to watch. */ int mask, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION: indicates @@ -536,44 +503,29 @@ Tcl_CreateFileHandler( * event. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { - int isNew; - - if (tclNotifierHooks.createFileHandlerProc) { - tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); - return; - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - FileHandler *filePtr; - - for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { - if (filePtr->fd == fd) { - break; - } - } - if (filePtr == NULL) { - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); - filePtr->fd = fd; - filePtr->readyMask = 0; - filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; - tsdPtr->firstFileHandlerPtr = filePtr; - isNew = 1; - } else { - isNew = 0; - } - filePtr->proc = proc; - filePtr->clientData = clientData; - filePtr->mask = mask; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL); + int isNew = (filePtr == NULL); - PlatformEventsControl(filePtr, tsdPtr, - isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew); + if (isNew) { + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); + filePtr->fd = fd; + filePtr->readyMask = 0; + filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; + tsdPtr->firstFileHandlerPtr = filePtr; } + filePtr->proc = proc; + filePtr->clientData = clientData; + filePtr->mask = mask; + + PlatformEventsControl(filePtr, tsdPtr, + isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew); } /* *---------------------------------------------------------------------- * - * Tcl_DeleteFileHandler -- + * TclpDeleteFileHandler -- * * Cancel a previously-arranged callback arrangement for a file on the * epoll file descriptor of the thread of the caller. @@ -591,60 +543,50 @@ Tcl_CreateFileHandler( */ void -Tcl_DeleteFileHandler( +TclpDeleteFileHandler( int fd) /* Stream id for which to remove callback * function. */ { - if (tclNotifierHooks.deleteFileHandlerProc) { - tclNotifierHooks.deleteFileHandlerProc(fd); - return; - } else { - FileHandler *filePtr, *prevPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr, *prevPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - /* - * Find the entry for the given file (and return if there isn't one). - */ + /* + * Find the entry for the given file (and return if there isn't one). + */ - for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; - prevPtr = filePtr, filePtr = filePtr->nextPtr) { - if (filePtr == NULL) { - return; - } - if (filePtr->fd == fd) { - break; - } - } + filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr); + if (filePtr == NULL) { + return; + } - /* - * Update the check masks for this file. - */ + /* + * Update the check masks for this file. + */ - PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0); - if (filePtr->pedPtr) { - ckfree(filePtr->pedPtr); - } + PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0); + if (filePtr->pedPtr) { + ckfree(filePtr->pedPtr); + } - /* - * Clean up information in the callback record. - */ + /* + * Clean up information in the callback record. + */ - if (prevPtr == NULL) { - tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; - } else { - prevPtr->nextPtr = filePtr->nextPtr; - } - ckfree(filePtr); + if (prevPtr == NULL) { + tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; + } else { + prevPtr->nextPtr = filePtr->nextPtr; } + ckfree(filePtr); } /* *---------------------------------------------------------------------- * - * Tcl_WaitForEvent -- + * TclpWaitForEvent -- * * 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 + * the message queue. If the block time is 0, then TclpWaitForEvent just * polls without blocking. * * The waiting logic is implemented in PlatformEventsWait. @@ -660,172 +602,165 @@ Tcl_DeleteFileHandler( */ int -Tcl_WaitForEvent( +TclpWaitForEvent( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { - if (tclNotifierHooks.waitForEventProc) { - return tclNotifierHooks.waitForEventProc(timePtr); - } else { - FileHandler *filePtr; - int mask; - Tcl_Time vTime; - /* - * Impl. notes: timeout & timeoutPtr are used if, and only if threads - * are not enabled. They are the arguments for the regular epoll_wait() - * used when the core is not thread-enabled. - */ + FileHandler *filePtr; + Tcl_Time vTime; + struct timeval timeout, *timeoutPtr; + /* Impl. notes: timeout & timeoutPtr are used + * if, and only if threads are not enabled. + * They are the arguments for the regular + * epoll_wait() used when the core is not + * thread-enabled. */ + int mask, numFound, numEvent; + struct PlatformEventData *pedPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + int numQueued; + ssize_t i; - struct timeval timeout, *timeoutPtr; - int numFound, numEvent; - struct PlatformEventData *pedPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - int numQueued; - ssize_t i; + /* + * Set up the timeout structure. Note that if there are no events to check + * for, we return with a negative result rather than blocking forever. + */ + if (timePtr != NULL) { /* - * Set up the timeout structure. Note that if there are no events to - * check for, we return with a negative result rather than blocking - * forever. + * TIP #233 (Virtualized Time). Is virtual time in effect? And do we + * actually have something to scale? If yes to both then we call the + * handler to do this scaling. */ - if (timePtr != NULL) { - /* - * TIP #233 (Virtualized Time). Is virtual time in effect? And do - * we actually have something to scale? If yes to both then we - * call the handler to do this scaling. - */ - - if (timePtr->sec != 0 || timePtr->usec != 0) { - vTime = *timePtr; - tclScaleTimeProcPtr(&vTime, tclTimeClientData); - timePtr = &vTime; - } - timeout.tv_sec = timePtr->sec; - timeout.tv_usec = timePtr->usec; - timeoutPtr = &timeout; - } else { - timeoutPtr = NULL; + if (timePtr->sec != 0 || timePtr->usec != 0) { + vTime = *timePtr; + TclScaleTime(&vTime); + timePtr = &vTime; } + timeout.tv_sec = timePtr->sec; + timeout.tv_usec = timePtr->usec; + timeoutPtr = &timeout; + } else { + timeoutPtr = NULL; + } - /* - * Walk the list of FileHandlers associated with regular files - * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and - * update their mask of events of interest. - * - * As epoll(7) does not support regular files, the behaviour of - * {select,poll}(2) is simply simulated here: fds associated with - * regular files are added to this list by PlatformEventsControl() and - * processed here before calling (and possibly blocking) on - * PlatformEventsWait(). - */ - - numQueued = 0; - LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) { - mask = 0; - if (filePtr->mask & TCL_READABLE) { - mask |= TCL_READABLE; - } - if (filePtr->mask & TCL_WRITABLE) { - mask |= TCL_WRITABLE; - } - - /* - * Don't bother to queue an event if the mask was previously - * non-zero since an event must still be on the queue. - */ - - if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) - ckalloc(sizeof(FileHandlerEvent)); + /* + * Walk the list of FileHandlers associated with regular files (S_IFREG) + * belonging to tsdPtr, queue Tcl events for them, and update their mask + * of events of interest. + * + * As epoll(7) does not support regular files, the behaviour of + * {select,poll}(2) is simply simulated here: fds associated with regular + * files are added to this list by PlatformEventsControl() and processed + * here before calling (and possibly blocking) on PlatformEventsWait(). + */ - fileEvPtr->header.proc = FileHandlerEventProc; - fileEvPtr->fd = filePtr->fd; - Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); - numQueued++; - } - filePtr->readyMask = mask; + numQueued = 0; + LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) { + mask = 0; + if (filePtr->mask & TCL_READABLE) { + mask |= TCL_READABLE; + } + if (filePtr->mask & TCL_WRITABLE) { + mask |= TCL_WRITABLE; } /* - * If any events were queued in the above loop, force - * PlatformEventsWait() to poll as there already are events that need - * to be processed at this point. + * Don't bother to queue an event if the mask was previously non-zero + * since an event must still be on the queue. */ - if (numQueued) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - timeoutPtr = &timeout; + if (filePtr->readyMask == 0) { + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) + ckalloc(sizeof(FileHandlerEvent)); + + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); + numQueued++; } + filePtr->readyMask = mask; + } - /* - * Wait or poll for new events, queue Tcl events for the FileHandlers - * corresponding to them, and update the FileHandlers' mask of events - * of interest registered by the last call to Tcl_CreateFileHandler(). - * - * Events for the eventfd(2)/trigger pipe are processed here in order - * to facilitate inter-thread IPC. If another thread intends to wake - * up this thread whilst it's blocking on PlatformEventsWait(), it - * write(2)s to the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),) - * which in turn will cause PlatformEventsWait() to return - * immediately. - */ + /* + * If any events were queued in the above loop, force PlatformEventsWait() + * to poll as there already are events that need to be processed at this + * point. + */ + + if (numQueued) { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + timeoutPtr = &timeout; + } + + /* + * Wait or poll for new events, queue Tcl events for the FileHandlers + * corresponding to them, and update the FileHandlers' mask of events of + * interest registered by the last call to Tcl_CreateFileHandler(). + * + * Events for the eventfd(2)/trigger pipe are processed here in order to + * facilitate inter-thread IPC. If another thread intends to wake up this + * thread whilst it's blocking on PlatformEventsWait(), it write(2)s to + * the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),) which in turn + * will cause PlatformEventsWait() to return immediately. + */ - numFound = PlatformEventsWait(tsdPtr->readyEvents, - tsdPtr->maxReadyEvents, timeoutPtr); - for (numEvent = 0; numEvent < numFound; numEvent++) { - pedPtr = (struct PlatformEventData*)tsdPtr->readyEvents[numEvent].data.ptr; - filePtr = pedPtr->filePtr; - mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]); + numFound = PlatformEventsWait(tsdPtr->readyEvents, + tsdPtr->maxReadyEvents, timeoutPtr); + for (numEvent = 0; numEvent < numFound; numEvent++) { + pedPtr = (struct PlatformEventData *) + tsdPtr->readyEvents[numEvent].data.ptr; + filePtr = pedPtr->filePtr; + mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]); #ifdef HAVE_EVENTFD - if (filePtr->fd == tsdPtr->triggerEventFd) { - uint64_t eventFdVal; - i = read(tsdPtr->triggerEventFd, &eventFdVal, - sizeof(eventFdVal)); - if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) { - Tcl_Panic( - "Tcl_WaitForEvent: read from %p->triggerEventFd: %s", - (void *) tsdPtr, strerror(errno)); - } - continue; + if (filePtr->fd == tsdPtr->triggerEventFd) { + uint64_t eventFdVal; + + i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal)); + if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) { + Tcl_Panic("%s: read from %p->triggerEventFd: %s", + "Tcl_WaitForEvent", (void *) tsdPtr, strerror(errno)); } + continue; + } #else /* !HAVE_EVENTFD */ - if (filePtr->fd == tsdPtr->triggerPipe[0]) { - char triggerPipeVal; - i = read(tsdPtr->triggerPipe[0], &triggerPipeVal, - sizeof(triggerPipeVal)); - if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) { - Tcl_Panic( - "Tcl_WaitForEvent: read from %p->triggerPipe[0]: %s", - (void *) tsdPtr, strerror(errno)); - } - continue; + if (filePtr->fd == tsdPtr->triggerPipe[0]) { + char triggerPipeVal; + + i = read(tsdPtr->triggerPipe[0], &triggerPipeVal, + sizeof(triggerPipeVal)); + if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) { + Tcl_Panic("%s: read from %p->triggerPipe[0]: %s", + "Tcl_WaitForEvent", (void *) tsdPtr, strerror(errno)); } + continue; + } #endif /* HAVE_EVENTFD */ - if (!mask) { - continue; - } + if (!mask) { + continue; + } - /* - * Don't bother to queue an event if the mask was previously - * non-zero since an event must still be on the queue. - */ + /* + * Don't bother to queue an event if the mask was previously non-zero + * since an event must still be on the queue. + */ - if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) - ckalloc(sizeof(FileHandlerEvent)); + if (filePtr->readyMask == 0) { + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) + ckalloc(sizeof(FileHandlerEvent)); - fileEvPtr->header.proc = FileHandlerEventProc; - fileEvPtr->fd = filePtr->fd; - Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); - } - filePtr->readyMask = mask; + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } - return 0; + filePtr->readyMask = mask; } + return 0; } #endif /* NOTIFIER_EPOLL && TCL_THREADS */ +#else +TCL_MAC_EMPTY_FILE(unix_tclEpollNotfy_c) #endif /* !HAVE_COREFOUNDATION */ /* diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c index 2f1d8e6..ab3732d 100644 --- a/unix/tclKqueueNotfy.c +++ b/unix/tclKqueueNotfy.c @@ -31,7 +31,8 @@ struct PlatformEventData; typedef struct FileHandler { - int fd; + int fd; /* File descriptor that this is describing a + * handler for. */ int mask; /* Mask of desired events: TCL_READABLE, * etc. */ int readyMask; /* Mask of events that have been seen since @@ -93,7 +94,7 @@ typedef struct ThreadSpecificData { * that are ready for I/O. */ pthread_mutex_t notifierMutex; /* Mutex protecting notifier termination in - * PlatformEventsFinalize. */ + * TclpFinalizeNotifier. */ int triggerPipe[2]; /* pipe(2) used by other threads to wake * up this thread for inter-thread IPC. */ int eventsFd; /* kqueue(2) file descriptor used to wait for @@ -111,73 +112,15 @@ static Tcl_ThreadDataKey dataKey; static void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew); -static void PlatformEventsFinalize(void); -static void PlatformEventsInit(void); static int PlatformEventsTranslate(struct kevent *eventPtr); static int PlatformEventsWait(struct kevent *events, size_t numEvents, struct timeval *timePtr); - -#include "tclUnixNotfy.c" - -/* - *---------------------------------------------------------------------- - * - * Tcl_InitNotifier -- - * - * Initializes the platform specific notifier state. - * - * Results: - * Returns a handle to the notifier state for this thread. - * - * Side effects: - * If no initNotifierProc notifier hook exists, PlatformEventsInit - * is called. - * - *---------------------------------------------------------------------- - */ - -ClientData -Tcl_InitNotifier(void) -{ - if (tclNotifierHooks.initNotifierProc) { - return tclNotifierHooks.initNotifierProc(); - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - PlatformEventsInit(); - return tsdPtr; - } -} /* - *---------------------------------------------------------------------- - * - * Tcl_FinalizeNotifier -- - * - * This function is called to cleanup the notifier state before a thread - * is terminated. - * - * Results: - * None. - * - * Side effects: - * If no finalizeNotifierProc notifier hook exists, PlatformEvents- - * Finalize is called. - * - *---------------------------------------------------------------------- + * Incorporate the base notifier implementation. */ -void -Tcl_FinalizeNotifier( - ClientData clientData) -{ - if (tclNotifierHooks.finalizeNotifierProc) { - tclNotifierHooks.finalizeNotifierProc(clientData); - return; - } else { - PlatformEventsFinalize(); - } -} +#include "tclUnixNotfy.c" /* *---------------------------------------------------------------------- @@ -209,7 +152,7 @@ Tcl_FinalizeNotifier( *---------------------------------------------------------------------- */ -void +static void PlatformEventsControl( FileHandler *filePtr, ThreadSpecificData *tsdPtr, @@ -222,7 +165,8 @@ PlatformEventsControl( struct stat fdStat; if (isNew) { - newPedPtr = (struct PlatformEventData *)ckalloc(sizeof(struct PlatformEventData)); + newPedPtr = (struct PlatformEventData *) + ckalloc(sizeof(struct PlatformEventData)); newPedPtr->filePtr = filePtr; newPedPtr->tsdPtr = tsdPtr; filePtr->pedPtr = newPedPtr; @@ -257,12 +201,12 @@ PlatformEventsControl( switch (op) { case EV_ADD: if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) { - EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, + EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd, EVFILT_READ, op, 0, 0, filePtr->pedPtr); numChanges++; } if (filePtr->mask & TCL_WRITABLE) { - EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, + EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd, EVFILT_WRITE, op, 0, 0, filePtr->pedPtr); numChanges++; } @@ -284,13 +228,13 @@ PlatformEventsControl( * As one of these calls can fail, two separate kevent(2) calls are * made for EVFILT_{READ,WRITE}. */ - EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_READ, op, 0, 0, + EV_SET(&changeList[0], (uintptr_t) filePtr->fd, EVFILT_READ, op, 0, 0, NULL); if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1) && (errno != ENOENT)) { Tcl_Panic("kevent: %s", strerror(errno)); } - EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_WRITE, op, 0, 0, + EV_SET(&changeList[0], (uintptr_t) filePtr->fd, EVFILT_WRITE, op, 0, 0, NULL); if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1) && (errno != ENOENT)) { @@ -303,7 +247,7 @@ PlatformEventsControl( /* *---------------------------------------------------------------------- * - * PlatformEventsFinalize -- + * TclpFinalizeNotifier -- * * This function closes the pipe and the kqueue file descriptors and * frees the kevent structs owned by the thread of the caller. The above @@ -325,8 +269,8 @@ PlatformEventsControl( */ void -PlatformEventsFinalize( - void) +TclpFinalizeNotifier( + TCL_UNUSED(ClientData)) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -356,14 +300,16 @@ PlatformEventsFinalize( /* *---------------------------------------------------------------------- * - * PlatformEventsInit -- + * TclpInitNotifier -- + * + * Initializes the platform specific notifier state. * * This function abstracts creating a kqueue fd via the kqueue system * call and allocating memory for the kevents structs in tsdPtr for the * thread of the caller. * * Results: - * None. + * Returns a handle to the notifier state for this thread. * * Side effects: * The following per-thread entities are initialised: @@ -380,8 +326,8 @@ PlatformEventsFinalize( *---------------------------------------------------------------------- */ -void -PlatformEventsInit(void) +ClientData +TclpInitNotifier(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int i, fdFl; @@ -409,16 +355,18 @@ PlatformEventsInit(void) } else if (fcntl(tsdPtr->eventsFd, F_SETFD, FD_CLOEXEC) == -1) { Tcl_Panic("fcntl: %s", strerror(errno)); } - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); filePtr->fd = tsdPtr->triggerPipe[0]; filePtr->mask = TCL_READABLE; PlatformEventsControl(filePtr, tsdPtr, EV_ADD, 1); if (!tsdPtr->readyEvents) { tsdPtr->maxReadyEvents = 512; - tsdPtr->readyEvents = (struct kevent *)ckalloc( + tsdPtr->readyEvents = (struct kevent *) ckalloc( tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0])); } LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr); + + return tsdPtr; } /* @@ -438,7 +386,7 @@ PlatformEventsInit(void) *---------------------------------------------------------------------- */ -int +static int PlatformEventsTranslate( struct kevent *eventPtr) { @@ -459,7 +407,7 @@ PlatformEventsTranslate( } return mask; } - + /* *---------------------------------------------------------------------- * @@ -483,7 +431,7 @@ PlatformEventsTranslate( *---------------------------------------------------------------------- */ -int +static int PlatformEventsWait( struct kevent *events, size_t numEvents, @@ -538,7 +486,7 @@ PlatformEventsWait( /* *---------------------------------------------------------------------- * - * Tcl_CreateFileHandler -- + * TclpCreateFileHandler -- * * This function registers a file handler with the kqueue notifier * of the thread of the caller. @@ -554,7 +502,7 @@ PlatformEventsWait( */ void -Tcl_CreateFileHandler( +TclpCreateFileHandler( int fd, /* Handle of stream to watch. */ int mask, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION: indicates @@ -564,43 +512,28 @@ Tcl_CreateFileHandler( * event. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { - int isNew; - - if (tclNotifierHooks.createFileHandlerProc) { - tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); - return; - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - FileHandler *filePtr; - - for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { - if (filePtr->fd == fd) { - break; - } - } - if (filePtr == NULL) { - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); - filePtr->fd = fd; - filePtr->readyMask = 0; - filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; - tsdPtr->firstFileHandlerPtr = filePtr; - isNew = 1; - } else { - isNew = 0; - } - filePtr->proc = proc; - filePtr->clientData = clientData; - filePtr->mask = mask; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL); + int isNew = (filePtr == NULL); - PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew); + if (isNew) { + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); + filePtr->fd = fd; + filePtr->readyMask = 0; + filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; + tsdPtr->firstFileHandlerPtr = filePtr; } + filePtr->proc = proc; + filePtr->clientData = clientData; + filePtr->mask = mask; + + PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew); } /* *---------------------------------------------------------------------- * - * Tcl_DeleteFileHandler -- + * TclpDeleteFileHandler -- * * Cancel a previously-arranged callback arrangement for a file on the * kqueue of the thread of the caller. @@ -618,60 +551,50 @@ Tcl_CreateFileHandler( */ void -Tcl_DeleteFileHandler( +TclpDeleteFileHandler( int fd) /* Stream id for which to remove callback * function. */ { - if (tclNotifierHooks.deleteFileHandlerProc) { - tclNotifierHooks.deleteFileHandlerProc(fd); - return; - } else { - FileHandler *filePtr, *prevPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr, *prevPtr; - /* - * Find the entry for the given file (and return if there isn't one). - */ + /* + * Find the entry for the given file (and return if there isn't one). + */ - for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; - prevPtr = filePtr, filePtr = filePtr->nextPtr) { - if (filePtr == NULL) { - return; - } - if (filePtr->fd == fd) { - break; - } - } + filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr); + if (filePtr == NULL) { + return; + } - /* - * Update the check masks for this file. - */ + /* + * Update the check masks for this file. + */ - PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0); - if (filePtr->pedPtr) { - ckfree(filePtr->pedPtr); - } + PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0); + if (filePtr->pedPtr) { + ckfree(filePtr->pedPtr); + } - /* - * Clean up information in the callback record. - */ + /* + * Clean up information in the callback record. + */ - if (prevPtr == NULL) { - tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; - } else { - prevPtr->nextPtr = filePtr->nextPtr; - } - ckfree(filePtr); + if (prevPtr == NULL) { + tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; + } else { + prevPtr->nextPtr = filePtr->nextPtr; } + ckfree(filePtr); } /* *---------------------------------------------------------------------- * - * Tcl_WaitForEvent -- + * TclpWaitForEvent -- * * 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 + * the message queue. If the block time is 0, then TclpWaitForEvent just * polls without blocking. * * The waiting logic is implemented in PlatformEventsWait. @@ -687,161 +610,157 @@ Tcl_DeleteFileHandler( */ int -Tcl_WaitForEvent( - const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ +TclpWaitForEvent( + const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { - if (tclNotifierHooks.waitForEventProc) { - return tclNotifierHooks.waitForEventProc(timePtr); - } else { - FileHandler *filePtr; - int mask; - Tcl_Time vTime; - /* - * Impl. notes: timeout & timeoutPtr are used if, and only if threads - * are not enabled. They are the arguments for the regular epoll_wait() - * used when the core is not thread-enabled. - */ + FileHandler *filePtr; + int mask; + Tcl_Time vTime; + struct timeval timeout, *timeoutPtr; + /* Impl. notes: timeout & timeoutPtr are used + * if, and only if threads are not enabled. + * They are the arguments for the regular + * epoll_wait() used when the core is not + * thread-enabled. */ + int numFound, numEvent; + struct PlatformEventData *pedPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + int numQueued; + ssize_t i; + char buf[1]; - struct timeval timeout, *timeoutPtr; - int numFound, numEvent; - struct PlatformEventData *pedPtr; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - int numQueued; - ssize_t i; - char buf[1]; + /* + * Set up the timeout structure. Note that if there are no events to check + * for, we return with a negative result rather than blocking forever. + */ + if (timePtr != NULL) { /* - * Set up the timeout structure. Note that if there are no events to - * check for, we return with a negative result rather than blocking - * forever. + * TIP #233 (Virtualized Time). Is virtual time in effect? And do we + * actually have something to scale? If yes to both then we call the + * handler to do this scaling. */ - if (timePtr != NULL) { - /* - * TIP #233 (Virtualized Time). Is virtual time in effect? And do - * we actually have something to scale? If yes to both then we - * call the handler to do this scaling. - */ - - if (timePtr->sec != 0 || timePtr->usec != 0) { - vTime = *timePtr; - tclScaleTimeProcPtr(&vTime, tclTimeClientData); - timePtr = &vTime; - } - timeout.tv_sec = timePtr->sec; - timeout.tv_usec = timePtr->usec; - timeoutPtr = &timeout; - } else { - timeoutPtr = NULL; + if (timePtr->sec != 0 || timePtr->usec != 0) { + vTime = *timePtr; + TclScaleTime(&vTime); + timePtr = &vTime; + } + timeout.tv_sec = timePtr->sec; + timeout.tv_usec = timePtr->usec; + timeoutPtr = &timeout; + } else { + timeoutPtr = NULL; + } + + /* + * Walk the list of FileHandlers associated with regular files (S_IFREG) + * belonging to tsdPtr, queue Tcl events for them, and update their mask + * of events of interest. + * + * kqueue(2), unlike epoll(7), does support regular files, but EVFILT_READ + * only `[r]eturns when the file pointer is not at the end of file' as + * opposed to unconditionally. While FreeBSD 11.0-RELEASE adds support for + * this mode (NOTE_FILE_POLL,) this is not used for reasons of + * compatibility. + * + * Therefore, the behaviour of {select,poll}(2) is simply simulated here: + * fds associated with regular files are added to this list by + * PlatformEventsControl() and processed here before calling (and possibly + * blocking) on PlatformEventsWait(). + */ + + numQueued = 0; + LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) { + mask = 0; + if (filePtr->mask & TCL_READABLE) { + mask |= TCL_READABLE; + } + if (filePtr->mask & TCL_WRITABLE) { + mask |= TCL_WRITABLE; } /* - * Walk the list of FileHandlers associated with regular files - * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and - * update their mask of events of interest. - * - * kqueue(2), unlike epoll(7), does support regular files, but - * EVFILT_READ only `[r]eturns when the file pointer is not at the end - * of file' as opposed to unconditionally. While FreeBSD 11.0-RELEASE - * adds support for this mode (NOTE_FILE_POLL,) this is not used for - * reasons of compatibility. - * - * Therefore, the behaviour of {select,poll}(2) is simply simulated - * here: fds associated with regular files are added to this list by - * PlatformEventsControl() and processed here before calling (and - * possibly blocking) on PlatformEventsWait(). + * Don't bother to queue an event if the mask was previously non-zero + * since an event must still be on the queue. */ - numQueued = 0; - LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) { - mask = 0; - if (filePtr->mask & TCL_READABLE) { - mask |= TCL_READABLE; - } - if (filePtr->mask & TCL_WRITABLE) { - mask |= TCL_WRITABLE; - } + if (filePtr->readyMask == 0) { + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) + ckalloc(sizeof(FileHandlerEvent)); - /* - * Don't bother to queue an event if the mask was previously - * non-zero since an event must still be on the queue. - */ + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); + numQueued++; + } + filePtr->readyMask = mask; + } - if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) - ckalloc(sizeof(FileHandlerEvent)); + /* + * If any events were queued in the above loop, force PlatformEventsWait() + * to poll as there already are events that need to be processed at this + * point. + */ - fileEvPtr->header.proc = FileHandlerEventProc; - fileEvPtr->fd = filePtr->fd; - Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); - numQueued++; - } - filePtr->readyMask = mask; - } + if (numQueued) { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + timeoutPtr = &timeout; + } - /* - * If any events were queued in the above loop, force PlatformEvents- - * Wait() to poll as there already are events that need to be processed - * at this point. - */ + /* + * Wait or poll for new events, queue Tcl events for the FileHandlers + * corresponding to them, and update the FileHandlers' mask of events of + * interest registered by the last call to Tcl_CreateFileHandler(). + * + * Events for the trigger pipe are processed here in order to facilitate + * inter-thread IPC. If another thread intends to wake up this thread + * whilst it's blocking on PlatformEventsWait(), it write(2)s to the other + * end of the pipe (see Tcl_AlertNotifier(),) which in turn will cause + * PlatformEventsWait() to return immediately. + */ - if (numQueued) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - timeoutPtr = &timeout; + numFound = PlatformEventsWait(tsdPtr->readyEvents, + tsdPtr->maxReadyEvents, timeoutPtr); + for (numEvent = 0; numEvent < numFound; numEvent++) { + pedPtr = (struct PlatformEventData *) + tsdPtr->readyEvents[numEvent].udata; + filePtr = pedPtr->filePtr; + mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]); + if (filePtr->fd == tsdPtr->triggerPipe[0]) { + i = read(tsdPtr->triggerPipe[0], buf, 1); + if ((i == -1) && (errno != EAGAIN)) { + Tcl_Panic("Tcl_WaitForEvent: read from %p->triggerPipe: %s", + (void *) tsdPtr, strerror(errno)); + } + continue; + } + if (!mask) { + continue; } /* - * Wait or poll for new events, queue Tcl events for the FileHandlers - * corresponding to them, and update the FileHandlers' mask of events - * of interest registered by the last call to Tcl_CreateFileHandler(). - * - * Events for the trigger pipe are processed here in order to facilitate - * inter-thread IPC. If another thread intends to wake up this thread - * whilst it's blocking on PlatformEventsWait(), it write(2)s to the - * other end of the pipe (see Tcl_AlertNotifier(),) which in turn will - * cause PlatformEventsWait() to return immediately. + * Don't bother to queue an event if the mask was previously non-zero + * since an event must still be on the queue. */ - numFound = PlatformEventsWait(tsdPtr->readyEvents, - tsdPtr->maxReadyEvents, timeoutPtr); - for (numEvent = 0; numEvent < numFound; numEvent++) { - pedPtr = (struct PlatformEventData *) - tsdPtr->readyEvents[numEvent].udata; - filePtr = pedPtr->filePtr; - mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]); - if (filePtr->fd == tsdPtr->triggerPipe[0]) { - i = read(tsdPtr->triggerPipe[0], buf, 1); - if ((i == -1) && (errno != EAGAIN)) { - Tcl_Panic("Tcl_WaitForEvent: read from %p->triggerPipe: %s", - (void *) tsdPtr, strerror(errno)); - } - continue; - } - if (!mask) { - continue; - } - - /* - * Don't bother to queue an event if the mask was previously - * non-zero since an event must still be on the queue. - */ + if (filePtr->readyMask == 0) { + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) + ckalloc(sizeof(FileHandlerEvent)); - if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) - ckalloc(sizeof(FileHandlerEvent)); - - fileEvPtr->header.proc = FileHandlerEventProc; - fileEvPtr->fd = filePtr->fd; - Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); - } - filePtr->readyMask |= mask; + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } - return 0; + filePtr->readyMask |= mask; } + return 0; } #endif /* NOTIFIER_KQUEUE && TCL_THREADS */ +#else +TCL_MAC_EMPTY_FILE(unix_tclKqueueNotfy_c) #endif /* !HAVE_COREFOUNDATION */ /* diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c index 017793d..7cd48f2 100644 --- a/unix/tclLoadDyld.c +++ b/unix/tclLoadDyld.c @@ -336,7 +336,7 @@ FindSymbol( const char *symbol) /* Symbol name to look up. */ { Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *)loadHandle->clientData; - Tcl_PackageInitProc *proc = NULL; + Tcl_LibraryInitProc *proc = NULL; const char *errMsg = NULL; Tcl_DString ds; const char *native; @@ -344,7 +344,7 @@ FindSymbol( native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); if (dyldLoadHandle->dlHandle) { #if TCL_DYLD_USE_DLFCN - proc = (Tcl_PackageInitProc *)dlsym(dyldLoadHandle->dlHandle, native); + proc = (Tcl_LibraryInitProc *)dlsym(dyldLoadHandle->dlHandle, native); if (!proc) { errMsg = dlerror(); } @@ -400,7 +400,7 @@ FindSymbol( dyldLoadHandle->modulePtr->module, native); } if (nsSymbol) { - proc = (Tcl_PackageInitProc *)NSAddressOfSymbol(nsSymbol); + proc = (Tcl_LibraryInitProc *)NSAddressOfSymbol(nsSymbol); } Tcl_DStringFree(&newName); #endif /* TCL_DYLD_USE_NSMODULE */ diff --git a/unix/tclLoadNext.c b/unix/tclLoadNext.c index ee39326..2055210 100644 --- a/unix/tclLoadNext.c +++ b/unix/tclLoadNext.c @@ -133,7 +133,7 @@ FindSymbol( Tcl_LoadHandle loadHandle, const char *symbol) { - Tcl_PackageInitProc *proc = NULL; + Tcl_LibraryInitProc *proc = NULL; if (symbol) { char sym[strlen(symbol) + 2]; diff --git a/unix/tclLoadOSF.c b/unix/tclLoadOSF.c index 7fd0cf3..bb58871 100644 --- a/unix/tclLoadOSF.c +++ b/unix/tclLoadOSF.c @@ -89,7 +89,7 @@ TclpDlopen( */ native = Tcl_FSGetNativePath(pathPtr); - lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS); + lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS); if (lm == LDR_NULL_MODULE) { /* @@ -101,7 +101,7 @@ TclpDlopen( Tcl_DString ds; native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); - lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS); + lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS); Tcl_DStringFree(&ds); } diff --git a/unix/tclLoadShl.c b/unix/tclLoadShl.c index 11eaa83..5bf97eb 100644 --- a/unix/tclLoadShl.c +++ b/unix/tclLoadShl.c @@ -128,7 +128,7 @@ FindSymbol( const char *symbol) { Tcl_DString newName; - Tcl_PackageInitProc *proc = NULL; + Tcl_LibraryInitProc *proc = NULL; shl_t handle = (shl_t) loadHandle->clientData; /* diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c index 1d16114..82f2ef7 100644 --- a/unix/tclSelectNotfy.c +++ b/unix/tclSelectNotfy.c @@ -216,8 +216,8 @@ extern "C" { typedef struct { void *hwnd; /* Messaging window. */ unsigned int *message; /* Message payload. */ - size_t wParam; /* Event-specific "word" parameter. */ - size_t lParam; /* Event-specific "long" parameter. */ + size_t wParam; /* Event-specific "word" parameter. */ + size_t lParam; /* Event-specific "long" parameter. */ int time; /* Event timestamp. */ int x; /* Event location (where meaningful). */ int y; @@ -244,8 +244,8 @@ extern void __stdcall CloseHandle(void *); extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char, void *); extern void *__stdcall CreateWindowExW(void *, const void *, const void *, - unsigned int, int, int, int, int, void *, void *, void *, - void *); + unsigned int, int, int, int, int, void *, void *, + void *, void *); extern unsigned int __stdcall DefWindowProcW(void *, int, void *, void *); extern unsigned char __stdcall DestroyWindow(void *); extern int __stdcall DispatchMessageW(const MSG *); @@ -271,14 +271,17 @@ static unsigned int __stdcall NotifierProc(void *hwnd, unsigned int message, } #endif #endif /* TCL_THREADS && __CYGWIN__ */ - +/* + * Incorporate the base notifier implementation. + */ + #include "tclUnixNotfy.c" /* *---------------------------------------------------------------------- * - * Tcl_InitNotifier -- + * TclpInitNotifier -- * * Initializes the platform specific notifier state. * @@ -292,75 +295,72 @@ static unsigned int __stdcall NotifierProc(void *hwnd, unsigned int message, */ ClientData -Tcl_InitNotifier(void) +TclpInitNotifier(void) { - if (tclNotifierHooks.initNotifierProc) { - return tclNotifierHooks.initNotifierProc(); - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); #if TCL_THREADS - tsdPtr->eventReady = 0; + tsdPtr->eventReady = 0; - /* - * Initialize thread specific condition variable for this thread. - */ - if (tsdPtr->waitCVinitialized == 0) { + /* + * Initialize thread specific condition variable for this thread. + */ + + if (tsdPtr->waitCVinitialized == 0) { #ifdef __CYGWIN__ - WNDCLASSW clazz; - - clazz.style = 0; - clazz.cbClsExtra = 0; - clazz.cbWndExtra = 0; - clazz.hInstance = TclWinGetTclInstance(); - clazz.hbrBackground = NULL; - clazz.lpszMenuName = NULL; - clazz.lpszClassName = className; - clazz.lpfnWndProc = (void *)NotifierProc; - clazz.hIcon = NULL; - clazz.hCursor = NULL; - - RegisterClassW(&clazz); - tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName, - clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL, - clazz.hInstance, NULL); - tsdPtr->event = CreateEventW(NULL, 1 /* manual */, - 0 /* !signaled */, NULL); -#else - pthread_cond_init(&tsdPtr->waitCV, NULL); + WNDCLASSW clazz; + + clazz.style = 0; + clazz.cbClsExtra = 0; + clazz.cbWndExtra = 0; + clazz.hInstance = TclWinGetTclInstance(); + clazz.hbrBackground = NULL; + clazz.lpszMenuName = NULL; + clazz.lpszClassName = className; + clazz.lpfnWndProc = (void *) NotifierProc; + clazz.hIcon = NULL; + clazz.hCursor = NULL; + + RegisterClassW(&clazz); + tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName, + clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL, + clazz.hInstance, NULL); + tsdPtr->event = CreateEventW(NULL, 1 /* manual */, + 0 /* !signaled */, NULL); +#else /* !__CYGWIN__ */ + pthread_cond_init(&tsdPtr->waitCV, NULL); #endif /* __CYGWIN__ */ - tsdPtr->waitCVinitialized = 1; - } + tsdPtr->waitCVinitialized = 1; + } - pthread_mutex_lock(¬ifierInitMutex); + pthread_mutex_lock(¬ifierInitMutex); #if defined(HAVE_PTHREAD_ATFORK) - /* - * Install pthread_atfork handlers to clean up the notifier in the - * child of a fork. - */ + /* + * Install pthread_atfork handlers to clean up the notifier in the child + * of a fork. + */ - if (!atForkInit) { - int result = pthread_atfork(NULL, NULL, AtForkChild); + if (!atForkInit) { + int result = pthread_atfork(NULL, NULL, AtForkChild); - if (result) { - Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed"); - } - atForkInit = 1; + if (result) { + Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed"); } + atForkInit = 1; + } #endif /* HAVE_PTHREAD_ATFORK */ - notifierCount++; - pthread_mutex_unlock(¬ifierInitMutex); - + notifierCount++; + pthread_mutex_unlock(¬ifierInitMutex); #endif /* TCL_THREADS */ - return tsdPtr; - } + + return tsdPtr; } /* *---------------------------------------------------------------------- * - * Tcl_FinalizeNotifier -- + * TclpFinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread * is terminated. @@ -376,67 +376,62 @@ Tcl_InitNotifier(void) */ void -Tcl_FinalizeNotifier( - ClientData clientData) +TclpFinalizeNotifier( + TCL_UNUSED(void *)) { - if (tclNotifierHooks.finalizeNotifierProc) { - tclNotifierHooks.finalizeNotifierProc(clientData); - return; - } else { #if TCL_THREADS - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - pthread_mutex_lock(¬ifierInitMutex); - notifierCount--; + pthread_mutex_lock(¬ifierInitMutex); + notifierCount--; - /* - * If this is the last thread to use the notifier, close the notifier - * pipe and wait for the background thread to terminate. - */ + /* + * If this is the last thread to use the notifier, close the notifier pipe + * and wait for the background thread to terminate. + */ - if (notifierCount == 0 && triggerPipe != -1) { - if (write(triggerPipe, "q", 1) != 1) { - Tcl_Panic("Tcl_FinalizeNotifier: %s", - "unable to write 'q' to triggerPipe"); - } - close(triggerPipe); - pthread_mutex_lock(¬ifierMutex); - while(triggerPipe != -1) { - pthread_cond_wait(¬ifierCV, ¬ifierMutex); - } - pthread_mutex_unlock(¬ifierMutex); - if (notifierThreadRunning) { - int result = pthread_join((pthread_t) notifierThread, NULL); + if (notifierCount == 0 && triggerPipe != -1) { + if (write(triggerPipe, "q", 1) != 1) { + Tcl_Panic("Tcl_FinalizeNotifier: %s", + "unable to write 'q' to triggerPipe"); + } + close(triggerPipe); + pthread_mutex_lock(¬ifierMutex); + while(triggerPipe != -1) { + pthread_cond_wait(¬ifierCV, ¬ifierMutex); + } + pthread_mutex_unlock(¬ifierMutex); + if (notifierThreadRunning) { + int result = pthread_join((pthread_t) notifierThread, NULL); - if (result) { - Tcl_Panic("Tcl_FinalizeNotifier: %s", - "unable to join notifier thread"); - } - notifierThreadRunning = 0; + if (result) { + Tcl_Panic("Tcl_FinalizeNotifier: %s", + "unable to join notifier thread"); } + notifierThreadRunning = 0; } + } - /* - * Clean up any synchronization objects in the thread local storage. - */ + /* + * Clean up any synchronization objects in the thread local storage. + */ #ifdef __CYGWIN__ - DestroyWindow(tsdPtr->hwnd); - CloseHandle(tsdPtr->event); -#else /* __CYGWIN__ */ - pthread_cond_destroy(&tsdPtr->waitCV); + DestroyWindow(tsdPtr->hwnd); + CloseHandle(tsdPtr->event); +#else /* !__CYGWIN__ */ + pthread_cond_destroy(&tsdPtr->waitCV); #endif /* __CYGWIN__ */ - tsdPtr->waitCVinitialized = 0; + tsdPtr->waitCVinitialized = 0; - pthread_mutex_unlock(¬ifierInitMutex); + pthread_mutex_unlock(¬ifierInitMutex); #endif /* TCL_THREADS */ - } } /* *---------------------------------------------------------------------- * - * Tcl_CreateFileHandler -- + * TclpCreateFileHandler -- * * This function registers a file handler with the select notifier. * @@ -450,7 +445,7 @@ Tcl_FinalizeNotifier( */ void -Tcl_CreateFileHandler( +TclpCreateFileHandler( int fd, /* Handle of stream to watch. */ int mask, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION: indicates @@ -460,59 +455,48 @@ Tcl_CreateFileHandler( * event. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { - if (tclNotifierHooks.createFileHandlerProc) { - tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); - return; - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - FileHandler *filePtr; - - for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; - filePtr = filePtr->nextPtr) { - if (filePtr->fd == fd) { - break; - } - } - if (filePtr == NULL) { - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); - filePtr->fd = fd; - filePtr->readyMask = 0; - filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; - tsdPtr->firstFileHandlerPtr = filePtr; - } - filePtr->proc = proc; - filePtr->clientData = clientData; - filePtr->mask = mask; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL); + + if (filePtr == NULL) { + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); + filePtr->fd = fd; + filePtr->readyMask = 0; + filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; + tsdPtr->firstFileHandlerPtr = filePtr; + } + filePtr->proc = proc; + filePtr->clientData = clientData; + filePtr->mask = mask; - /* - * Update the check masks for this file. - */ + /* + * Update the check masks for this file. + */ - if (mask & TCL_READABLE) { - FD_SET(fd, &tsdPtr->checkMasks.readable); - } else { - FD_CLR(fd, &tsdPtr->checkMasks.readable); - } - if (mask & TCL_WRITABLE) { - FD_SET(fd, &tsdPtr->checkMasks.writable); - } else { - FD_CLR(fd, &tsdPtr->checkMasks.writable); - } - if (mask & TCL_EXCEPTION) { - FD_SET(fd, &tsdPtr->checkMasks.exception); - } else { - FD_CLR(fd, &tsdPtr->checkMasks.exception); - } - if (tsdPtr->numFdBits <= fd) { - tsdPtr->numFdBits = fd+1; - } + if (mask & TCL_READABLE) { + FD_SET(fd, &tsdPtr->checkMasks.readable); + } else { + FD_CLR(fd, &tsdPtr->checkMasks.readable); + } + if (mask & TCL_WRITABLE) { + FD_SET(fd, &tsdPtr->checkMasks.writable); + } else { + FD_CLR(fd, &tsdPtr->checkMasks.writable); + } + if (mask & TCL_EXCEPTION) { + FD_SET(fd, &tsdPtr->checkMasks.exception); + } else { + FD_CLR(fd, &tsdPtr->checkMasks.exception); + } + if (tsdPtr->numFdBits <= fd) { + tsdPtr->numFdBits = fd + 1; } } /* *---------------------------------------------------------------------- * - * Tcl_DeleteFileHandler -- + * TclpDeleteFileHandler -- * * Cancel a previously-arranged callback arrangement for a file. * @@ -526,75 +510,65 @@ Tcl_CreateFileHandler( */ void -Tcl_DeleteFileHandler( +TclpDeleteFileHandler( int fd) /* Stream id for which to remove callback * function. */ { - if (tclNotifierHooks.deleteFileHandlerProc) { - tclNotifierHooks.deleteFileHandlerProc(fd); - return; - } else { - FileHandler *filePtr, *prevPtr; - int i; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr, *prevPtr; + int i; - /* - * Find the entry for the given file (and return if there isn't one). - */ + /* + * Find the entry for the given file (and return if there isn't one). + */ - for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; - prevPtr = filePtr, filePtr = filePtr->nextPtr) { - if (filePtr == NULL) { - return; - } - if (filePtr->fd == fd) { - break; - } - } + filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr); + if (filePtr == NULL) { + return; + } - /* - * Update the check masks for this file. - */ + /* + * Update the check masks for this file. + */ - if (filePtr->mask & TCL_READABLE) { - FD_CLR(fd, &tsdPtr->checkMasks.readable); - } - if (filePtr->mask & TCL_WRITABLE) { - FD_CLR(fd, &tsdPtr->checkMasks.writable); - } - if (filePtr->mask & TCL_EXCEPTION) { - FD_CLR(fd, &tsdPtr->checkMasks.exception); - } + if (filePtr->mask & TCL_READABLE) { + FD_CLR(fd, &tsdPtr->checkMasks.readable); + } + if (filePtr->mask & TCL_WRITABLE) { + FD_CLR(fd, &tsdPtr->checkMasks.writable); + } + if (filePtr->mask & TCL_EXCEPTION) { + FD_CLR(fd, &tsdPtr->checkMasks.exception); + } - /* - * Find current max fd. - */ + /* + * Find current max fd. + */ - if (fd+1 == tsdPtr->numFdBits) { - int numFdBits = 0; + if (fd + 1 == tsdPtr->numFdBits) { + int numFdBits = 0; - for (i = fd-1; i >= 0; i--) { - if (FD_ISSET(i, &tsdPtr->checkMasks.readable) - || FD_ISSET(i, &tsdPtr->checkMasks.writable) - || FD_ISSET(i, &tsdPtr->checkMasks.exception)) { - numFdBits = i+1; - break; - } + for (i = fd - 1; i >= 0; i--) { + if (FD_ISSET(i, &tsdPtr->checkMasks.readable) + || FD_ISSET(i, &tsdPtr->checkMasks.writable) + || FD_ISSET(i, &tsdPtr->checkMasks.exception)) { + numFdBits = i + 1; + break; } - tsdPtr->numFdBits = numFdBits; } + tsdPtr->numFdBits = numFdBits; + } - /* - * Clean up information in the callback record. - */ + /* + * Clean up information in the callback record. + */ - if (prevPtr == NULL) { - tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; - } else { - prevPtr->nextPtr = filePtr->nextPtr; - } - ckfree(filePtr); + if (prevPtr == NULL) { + tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; + } else { + prevPtr->nextPtr = filePtr->nextPtr; } + ckfree(filePtr); } #if defined(__CYGWIN__) @@ -625,7 +599,7 @@ NotifierProc( /* *---------------------------------------------------------------------- * - * Tcl_WaitForEvent -- + * TclpWaitForEvent -- * * 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 @@ -641,265 +615,261 @@ NotifierProc( */ int -Tcl_WaitForEvent( +TclpWaitForEvent( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { - if (tclNotifierHooks.waitForEventProc) { - return tclNotifierHooks.waitForEventProc(timePtr); - } else { - FileHandler *filePtr; - int mask; - Tcl_Time vTime; - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr; + int mask; + Tcl_Time vTime; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); #if TCL_THREADS - int waitForFiles; + int waitForFiles; # ifdef __CYGWIN__ - MSG msg; + MSG msg; # endif /* __CYGWIN__ */ #else /* !TCL_THREADS */ - /* - * Impl. notes: timeout & timeoutPtr are used if, and only if threads - * are not enabled. They are the arguments for the regular select() - * used when the core is not thread-enabled. - */ + /* + * Impl. notes: timeout & timeoutPtr are used if, and only if threads are + * not enabled. They are the arguments for the regular select() used when + * the core is not thread-enabled. + */ - struct timeval timeout, *timeoutPtr; - int numFound; + struct timeval timeout, *timeoutPtr; + int numFound; #endif /* TCL_THREADS */ + /* + * Set up the timeout structure. Note that if there are no events to check + * for, we return with a negative result rather than blocking forever. + */ + + if (timePtr != NULL) { /* - * Set up the timeout structure. Note that if there are no events to - * check for, we return with a negative result rather than blocking - * forever. + * TIP #233 (Virtualized Time). Is virtual time in effect? And do we + * actually have something to scale? If yes to both then we call the + * handler to do this scaling. */ - if (timePtr != NULL) { - /* - * TIP #233 (Virtualized Time). Is virtual time in effect? And do - * we actually have something to scale? If yes to both then we - * call the handler to do this scaling. - */ - - if (timePtr->sec != 0 || timePtr->usec != 0) { - vTime = *timePtr; - tclScaleTimeProcPtr(&vTime, tclTimeClientData); - timePtr = &vTime; - } + if (timePtr->sec != 0 || timePtr->usec != 0) { + vTime = *timePtr; + TclScaleTime(&vTime); + timePtr = &vTime; + } #if !TCL_THREADS - timeout.tv_sec = timePtr->sec; - timeout.tv_usec = timePtr->usec; - timeoutPtr = &timeout; - } else if (tsdPtr->numFdBits == 0) { - /* - * If there are no threads, no timeout, and no fds registered, - * then there are no events possible and we must avoid deadlock. - * Note that this is not entirely correct because there might be a - * signal that could interrupt the select call, but we don't - * handle that case if we aren't using threads. - */ + timeout.tv_sec = timePtr->sec; + timeout.tv_usec = timePtr->usec; + timeoutPtr = &timeout; + } else if (tsdPtr->numFdBits == 0) { + /* + * If there are no threads, no timeout, and no fds registered, then + * there are no events possible and we must avoid deadlock. Note that + * this is not entirely correct because there might be a signal that + * could interrupt the select call, but we don't handle that case if + * we aren't using threads. + */ - return -1; - } else { - timeoutPtr = NULL; + return -1; + } else { + timeoutPtr = NULL; #endif /* !TCL_THREADS */ - } + } #if TCL_THREADS - /* - * Start notifier thread and place this thread on the list of - * interested threads, signal the notifier thread, and wait for a - * response or a timeout. - */ - StartNotifierThread("Tcl_WaitForEvent"); + /* + * Start notifier thread and place this thread on the list of interested + * threads, signal the notifier thread, and wait for a response or a + * timeout. + */ - pthread_mutex_lock(¬ifierMutex); + StartNotifierThread("Tcl_WaitForEvent"); + + pthread_mutex_lock(¬ifierMutex); - if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0 + if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0 #if defined(__APPLE__) && defined(__LP64__) - /* - * On 64-bit Darwin, pthread_cond_timedwait() appears to have - * a bug that causes it to wait forever when passed an - * absolute time which has already been exceeded by the system - * time; as a workaround, when given a very brief timeout, - * just do a poll. [Bug 1457797] - */ - || timePtr->usec < 10 -#endif /* __APPLE__ && __LP64__ */ - )) { /* - * Cannot emulate a polling select with a polling condition - * variable. Instead, pretend to wait for files and tell the - * notifier thread what we are doing. The notifier thread makes - * sure it goes through select with its select mask in the same - * state as ours currently is. We block until that happens. + * On 64-bit Darwin, pthread_cond_timedwait() appears to have a + * bug that causes it to wait forever when passed an absolute time + * which has already been exceeded by the system time; as a + * workaround, when given a very brief timeout, just do a poll. + * [Bug 1457797] */ + || timePtr->usec < 10 +#endif /* __APPLE__ && __LP64__ */ + )) { + /* + * Cannot emulate a polling select with a polling condition variable. + * Instead, pretend to wait for files and tell the notifier thread + * what we are doing. The notifier thread makes sure it goes through + * select with its select mask in the same state as ours currently is. + * We block until that happens. + */ - waitForFiles = 1; - tsdPtr->pollState = POLL_WANT; - timePtr = NULL; - } else { - waitForFiles = (tsdPtr->numFdBits > 0); - tsdPtr->pollState = 0; - } + waitForFiles = 1; + tsdPtr->pollState = POLL_WANT; + timePtr = NULL; + } else { + waitForFiles = (tsdPtr->numFdBits > 0); + tsdPtr->pollState = 0; + } - if (waitForFiles) { - /* - * Add the ThreadSpecificData structure of this thread to the list - * of ThreadSpecificData structures of all threads that are - * waiting on file events. - */ + if (waitForFiles) { + /* + * Add the ThreadSpecificData structure of this thread to the list of + * ThreadSpecificData structures of all threads that are waiting on + * file events. + */ - tsdPtr->nextPtr = waitingListPtr; - if (waitingListPtr) { - waitingListPtr->prevPtr = tsdPtr; - } - tsdPtr->prevPtr = 0; - waitingListPtr = tsdPtr; - tsdPtr->onList = 1; + tsdPtr->nextPtr = waitingListPtr; + if (waitingListPtr) { + waitingListPtr->prevPtr = tsdPtr; + } + tsdPtr->prevPtr = 0; + waitingListPtr = tsdPtr; + tsdPtr->onList = 1; - if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) { - Tcl_Panic("Tcl_WaitForEvent: %s", - "unable to write to triggerPipe"); - } + if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) { + Tcl_Panic("Tcl_WaitForEvent: %s", + "unable to write to triggerPipe"); } + } - FD_ZERO(&tsdPtr->readyMasks.readable); - FD_ZERO(&tsdPtr->readyMasks.writable); - FD_ZERO(&tsdPtr->readyMasks.exception); + FD_ZERO(&tsdPtr->readyMasks.readable); + FD_ZERO(&tsdPtr->readyMasks.writable); + FD_ZERO(&tsdPtr->readyMasks.exception); - if (!tsdPtr->eventReady) { + if (!tsdPtr->eventReady) { #ifdef __CYGWIN__ - if (!PeekMessageW(&msg, NULL, 0, 0, 0)) { - unsigned int timeout; + if (!PeekMessageW(&msg, NULL, 0, 0, 0)) { + unsigned int timeout; - if (timePtr) { - timeout = timePtr->sec * 1000 + timePtr->usec / 1000; - } else { - timeout = 0xFFFFFFFF; - } - pthread_mutex_unlock(¬ifierMutex); - MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279); - pthread_mutex_lock(¬ifierMutex); + if (timePtr) { + timeout = timePtr->sec * 1000 + timePtr->usec / 1000; + } else { + timeout = 0xFFFFFFFF; } + pthread_mutex_unlock(¬ifierMutex); + MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279); + pthread_mutex_lock(¬ifierMutex); + } #else /* !__CYGWIN__ */ - if (timePtr != NULL) { - Tcl_Time now; - struct timespec ptime; + if (timePtr != NULL) { + Tcl_Time now; + struct timespec ptime; - Tcl_GetTime(&now); - ptime.tv_sec = timePtr->sec + now.sec + - (timePtr->usec + now.usec) / 1000000; - ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000); + Tcl_GetTime(&now); + ptime.tv_sec = timePtr->sec + now.sec + + (timePtr->usec + now.usec) / 1000000; + ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000); - pthread_cond_timedwait(&tsdPtr->waitCV, ¬ifierMutex, &ptime); - } else { - pthread_cond_wait(&tsdPtr->waitCV, ¬ifierMutex); - } -#endif /* __CYGWIN__ */ + pthread_cond_timedwait(&tsdPtr->waitCV, ¬ifierMutex, &ptime); + } else { + pthread_cond_wait(&tsdPtr->waitCV, ¬ifierMutex); } - tsdPtr->eventReady = 0; +#endif /* __CYGWIN__ */ + } + tsdPtr->eventReady = 0; #ifdef __CYGWIN__ - while (PeekMessageW(&msg, NULL, 0, 0, 0)) { - /* - * Retrieve and dispatch the message. - */ + while (PeekMessageW(&msg, NULL, 0, 0, 0)) { + /* + * Retrieve and dispatch the message. + */ - unsigned int result = GetMessageW(&msg, NULL, 0, 0); + unsigned int result = GetMessageW(&msg, NULL, 0, 0); - if (result == 0) { - PostQuitMessage(msg.wParam); - /* What to do here? */ - } else if (result != (unsigned int) -1) { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } + if (result == 0) { + PostQuitMessage(msg.wParam); + /* What to do here? */ + } else if (result != (unsigned int) -1) { + TranslateMessage(&msg); + DispatchMessageW(&msg); } - ResetEvent(tsdPtr->event); + } + ResetEvent(tsdPtr->event); #endif /* __CYGWIN__ */ - if (waitForFiles && tsdPtr->onList) { - /* - * Remove the ThreadSpecificData structure of this thread from the - * waiting list. Alert the notifier thread to recompute its select - * masks - skipping this caused a hang when trying to close a pipe - * which the notifier thread was still doing a select on. - */ + if (waitForFiles && tsdPtr->onList) { + /* + * Remove the ThreadSpecificData structure of this thread from the + * waiting list. Alert the notifier thread to recompute its select + * masks - skipping this caused a hang when trying to close a pipe + * which the notifier thread was still doing a select on. + */ - if (tsdPtr->prevPtr) { - tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; - } else { - waitingListPtr = tsdPtr->nextPtr; - } - if (tsdPtr->nextPtr) { - tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; - } - tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; - tsdPtr->onList = 0; - if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) { - Tcl_Panic("Tcl_WaitForEvent: %s", - "unable to write to triggerPipe"); - } + if (tsdPtr->prevPtr) { + tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; + } else { + waitingListPtr = tsdPtr->nextPtr; + } + if (tsdPtr->nextPtr) { + tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; } + tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; + tsdPtr->onList = 0; + if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) { + Tcl_Panic("Tcl_WaitForEvent: %s", + "unable to write to triggerPipe"); + } + } #else /* !TCL_THREADS */ - tsdPtr->readyMasks = tsdPtr->checkMasks; - numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable, - &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception, - timeoutPtr); + tsdPtr->readyMasks = tsdPtr->checkMasks; + numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable, + &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception, + timeoutPtr); - /* - * Some systems don't clear the masks after an error, so we have to do - * it here. - */ + /* + * Some systems don't clear the masks after an error, so we have to do it + * here. + */ - if (numFound == -1) { - FD_ZERO(&tsdPtr->readyMasks.readable); - FD_ZERO(&tsdPtr->readyMasks.writable); - FD_ZERO(&tsdPtr->readyMasks.exception); - } + if (numFound == -1) { + FD_ZERO(&tsdPtr->readyMasks.readable); + FD_ZERO(&tsdPtr->readyMasks.writable); + FD_ZERO(&tsdPtr->readyMasks.exception); + } #endif /* TCL_THREADS */ - /* - * Queue all detected file events before returning. - */ + /* + * Queue all detected file events before returning. + */ - for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); - filePtr = filePtr->nextPtr) { - mask = 0; - if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) { - mask |= TCL_READABLE; - } - if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) { - mask |= TCL_WRITABLE; - } - if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) { - mask |= TCL_EXCEPTION; - } + for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); + filePtr = filePtr->nextPtr) { + mask = 0; + if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) { + mask |= TCL_READABLE; + } + if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) { + mask |= TCL_WRITABLE; + } + if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) { + mask |= TCL_EXCEPTION; + } - if (!mask) { - continue; - } + if (!mask) { + continue; + } - /* - * Don't bother to queue an event if the mask was previously - * non-zero since an event must still be on the queue. - */ + /* + * Don't bother to queue an event if the mask was previously non-zero + * since an event must still be on the queue. + */ - if (filePtr->readyMask == 0) { - FileHandlerEvent *fileEvPtr = - (FileHandlerEvent *)ckalloc(sizeof(FileHandlerEvent)); + if (filePtr->readyMask == 0) { + FileHandlerEvent *fileEvPtr = + (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent)); - fileEvPtr->header.proc = FileHandlerEventProc; - fileEvPtr->fd = filePtr->fd; - Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); - } - filePtr->readyMask = mask; + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } + filePtr->readyMask = mask; + } #if TCL_THREADS - pthread_mutex_unlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); #endif /* TCL_THREADS */ - return 0; - } + return 0; } /* @@ -916,8 +886,9 @@ Tcl_WaitForEvent( * byte to a special pipe that the notifier thread is monitoring. * * Result: - * None. Once started, this routine never exits. It dies with the overall - * process. + * None. Once started, this routine normally never exits and usually dies + * with the overall process, but it can be shut down if the Tcl library + * is finalized. * * Side effects: * The trigger pipe used to signal the notifier thread is created when @@ -1048,7 +1019,7 @@ NotifierThreadProc( for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { found = 0; - for (i = tsdPtr->numFdBits-1; i >= 0; --i) { + for (i = tsdPtr->numFdBits - 1; i >= 0; --i) { if (FD_ISSET(i, &tsdPtr->checkMasks.readable) && FD_ISSET(i, &readableMask)) { FD_SET(i, &tsdPtr->readyMasks.readable); @@ -1113,6 +1084,8 @@ NotifierThreadProc( #endif /* TCL_THREADS */ #endif /* (!NOTIFIER_EPOLL && !NOTIFIER_KQUEUE) || !TCL_THREADS */ +#else +TCL_MAC_EMPTY_FILE(unix_tclSelectNotfy_c) #endif /* !HAVE_COREFOUNDATION */ /* diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 837aa59..4cb9af0 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -282,12 +282,15 @@ FileInputProc( * nonblocking, the read will never block. */ - bytesRead = read(fsPtr->fd, buf, (size_t) toRead); - if (bytesRead >= 0) { - return bytesRead; + do { + bytesRead = read(fsPtr->fd, buf, (size_t) toRead); + } while ((bytesRead < 0) && (errno == EINTR)); + + if (bytesRead < 0) { + *errorCodePtr = errno; + return -1; } - *errorCodePtr = errno; - return -1; + return bytesRead; } /* diff --git a/unix/tclUnixEvent.c b/unix/tclUnixEvent.c index aff7797..0047dd9 100644 --- a/unix/tclUnixEvent.c +++ b/unix/tclUnixEvent.c @@ -64,7 +64,7 @@ Tcl_Sleep( } if ((vdelay.sec != 0) || (vdelay.usec != 0)) { - tclScaleTimeProcPtr(&vdelay, tclTimeClientData); + TclScaleTime(&vdelay); } delay.tv_sec = vdelay.sec; @@ -85,6 +85,8 @@ Tcl_Sleep( } } +#else +TCL_MAC_EMPTY_FILE(unix_tclUnixEvent_c) #endif /* HAVE_COREFOUNDATION */ /* * Local Variables: diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 4d08c1d..9e9a493 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -2350,7 +2350,7 @@ StatError( Tcl_Obj *fileName) /* The name of the file which caused the * error. */ { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); } diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index d992d65..c1f00d5 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -2,10 +2,12 @@ * tclUnixNotfy.c -- * * This file contains subroutines shared by all notifier backend - * implementations on *nix platforms. + * implementations on *nix platforms. It is *included* by the epoll, + * kqueue and select notifier implementation files. * * Copyright © 1995-1997 Sun Microsystems, Inc. * Copyright © 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de> + * Copyright © 2021 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -45,8 +47,10 @@ static void AtForkChild(void); * *---------------------------------------------------------------------- */ + static void -StartNotifierThread(const char *proc) +StartNotifierThread( + const char *proc) { if (!notifierThreadRunning) { pthread_mutex_lock(¬ifierInitMutex); @@ -57,6 +61,7 @@ StartNotifierThread(const char *proc) } pthread_mutex_lock(¬ifierMutex); + /* * Wait for the notifier pipe to be created. */ @@ -76,7 +81,7 @@ StartNotifierThread(const char *proc) /* *---------------------------------------------------------------------- * - * Tcl_AlertNotifier -- + * TclpAlertNotifier -- * * Wake up the specified notifier from any thread. This routine is called * by the platform independent notifier code whenever the Tcl_ThreadAlert @@ -99,50 +104,97 @@ StartNotifierThread(const char *proc) */ void -Tcl_AlertNotifier( +TclpAlertNotifier( ClientData clientData) { - if (tclNotifierHooks.alertNotifierProc) { - tclNotifierHooks.alertNotifierProc(clientData); - return; - } else { #ifdef NOTIFIER_SELECT #if TCL_THREADS - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; - pthread_mutex_lock(¬ifierMutex); - tsdPtr->eventReady = 1; + pthread_mutex_lock(¬ifierMutex); + tsdPtr->eventReady = 1; # ifdef __CYGWIN__ - PostMessageW(tsdPtr->hwnd, 1024, 0, 0); + PostMessageW(tsdPtr->hwnd, 1024, 0, 0); # else - pthread_cond_broadcast(&tsdPtr->waitCV); + pthread_cond_broadcast(&tsdPtr->waitCV); # endif /* __CYGWIN__ */ - pthread_mutex_unlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); #endif /* TCL_THREADS */ #else /* !NOTIFIER_SELECT */ - ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; #if defined(NOTIFIER_EPOLL) && defined(HAVE_EVENTFD) - uint64_t eventFdVal = 1; - if (write(tsdPtr->triggerEventFd, &eventFdVal, - sizeof(eventFdVal)) != sizeof(eventFdVal)) { - Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd", - (void *)tsdPtr); - } + uint64_t eventFdVal = 1; + + if (write(tsdPtr->triggerEventFd, &eventFdVal, + sizeof(eventFdVal)) != sizeof(eventFdVal)) { + Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd", + (void *) tsdPtr); + } #else - if (write(tsdPtr->triggerPipe[1], "", 1) != 1) { - Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe", - (void *)tsdPtr); - } + if (write(tsdPtr->triggerPipe[1], "", 1) != 1) { + Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe", + (void *) tsdPtr); + } #endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */ #endif /* NOTIFIER_SELECT */ +} + +/* + *---------------------------------------------------------------------- + * + * LookUpFileHandler -- + * + * Look up the file handler structure (and optionally the previous one in + * the chain) associated with a file descriptor. + * + * Returns: + * A pointer to the file handler, or NULL if it can't be found. + * + * Side effects: + * If prevPtrPtr is non-NULL, it will be written to if the file handler + * is found. + * + *---------------------------------------------------------------------- + */ + +static inline FileHandler * +LookUpFileHandler( + ThreadSpecificData *tsdPtr, /* Where to look things up. */ + int fd, /* What we are looking for. */ + FileHandler **prevPtrPtr) /* If non-NULL, where to report the previous + * pointer. */ +{ + FileHandler *filePtr, *prevPtr; + + /* + * Find the entry for the given file (and return if there isn't one). + */ + + for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; + prevPtr = filePtr, filePtr = filePtr->nextPtr) { + if (filePtr == NULL) { + return NULL; + } + if (filePtr->fd == fd) { + break; + } + } + + /* + * Report what we've found to our caller. + */ + + if (prevPtrPtr) { + *prevPtrPtr = prevPtr; } + return filePtr; } /* *---------------------------------------------------------------------- * - * Tcl_SetTimer -- + * TclpSetTimer -- * * This function sets the current notifier timer value. This interface is * not implemented in this notifier because we are always running inside @@ -158,19 +210,14 @@ Tcl_AlertNotifier( */ void -Tcl_SetTimer( - const Tcl_Time *timePtr) /* Timeout value, may be NULL. */ +TclpSetTimer( + TCL_UNUSED(const Tcl_Time *)) /* Timeout value, may be NULL. */ { - if (tclNotifierHooks.setTimerProc) { - tclNotifierHooks.setTimerProc(timePtr); - return; - } else { - /* - * The interval timer doesn't do anything in this implementation, - * because the only event loop is via Tcl_DoOneEvent, which passes - * timeout values to Tcl_WaitForEvent. - */ - } + /* + * The interval timer doesn't do anything in this implementation, because + * the only event loop is via Tcl_DoOneEvent, which passes timeout values + * to Tcl_WaitForEvent. + */ } /* @@ -190,14 +237,11 @@ Tcl_SetTimer( */ void -Tcl_ServiceModeHook( +TclpServiceModeHook( int mode) /* Either TCL_SERVICE_ALL, or * TCL_SERVICE_NONE. */ { - if (tclNotifierHooks.serviceModeHookProc) { - tclNotifierHooks.serviceModeHookProc(mode); - return; - } else if (mode == TCL_SERVICE_ALL) { + if (mode == TCL_SERVICE_ALL) { #ifdef NOTIFIER_SELECT #if TCL_THREADS StartNotifierThread("Tcl_ServiceModeHook"); @@ -414,12 +458,9 @@ AtForkChild(void) Tcl_InitNotifier(); } #endif /* HAVE_PTHREAD_ATFORK */ - #endif /* TCL_THREADS */ - #endif /* NOTIFIER_SELECT */ -#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is - * in tclMacOSXNotify.c */ + /* *---------------------------------------------------------------------- * @@ -443,6 +484,9 @@ AtForkChild(void) *---------------------------------------------------------------------- */ +#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is + * in tclMacOSXNotify.c */ + int TclUnixWaitForFile( int fd, /* Handle for file on which to wait. */ @@ -563,9 +607,8 @@ TclUnixWaitForFile( || (abortTime.sec == now.sec && abortTime.usec > now.usec)); return result; } - #endif /* !HAVE_COREFOUNDATION */ - + /* * Local Variables: * mode: c diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index adeacb68..e0c7ac8 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -61,6 +61,23 @@ Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime; void *tclTimeClientData = NULL; /* + * Inlined version of Tcl_GetTime. + */ + +static inline void +GetTime( + Tcl_Time *timePtr) +{ + tclGetTimeProcPtr(timePtr, tclTimeClientData); +} + +static inline int +IsTimeNative(void) +{ + return tclGetTimeProcPtr == NativeGetTime; +} + +/* *---------------------------------------------------------------------- * * TclpGetSeconds -- @@ -105,8 +122,8 @@ TclpGetMicroseconds(void) { Tcl_Time time; - tclGetTimeProcPtr(&time, tclTimeClientData); - return ((long long)time.sec)*1000000 + time.usec; + GetTime(&time); + return ((long long) time.sec)*1000000 + time.usec; } /* @@ -134,10 +151,10 @@ TclpGetClicks(void) unsigned long now; #ifdef NO_GETTOD - if (tclGetTimeProcPtr != NativeGetTime) { + if (!IsTimeNative()) { Tcl_Time time; - tclGetTimeProcPtr(&time, tclTimeClientData); + GetTime(&time); now = time.sec*1000000 + time.usec; } else { /* @@ -147,12 +164,12 @@ TclpGetClicks(void) now = (unsigned long) times(&dummy); } -#else +#else /* !NO_GETTOD */ Tcl_Time time; - tclGetTimeProcPtr(&time, tclTimeClientData); + GetTime(&time); now = time.sec*1000000 + time.usec; -#endif +#endif /* NO_GETTOD */ return now; } @@ -182,17 +199,17 @@ TclpGetWideClicks(void) { long long now; - if (tclGetTimeProcPtr != NativeGetTime) { + if (!IsTimeNative()) { Tcl_Time time; - tclGetTimeProcPtr(&time, tclTimeClientData); - now = ((long long)time.sec)*1000000 + time.usec; + GetTime(&time); + now = ((long long) time.sec)*1000000 + time.usec; } else { #ifdef MAC_OSX_TCL now = (long long) (mach_absolute_time() & INT64_MAX); #else #error Wide high-resolution clicks not implemented on this platform -#endif +#endif /* MAC_OSX_TCL */ } return now; @@ -221,7 +238,7 @@ TclpWideClicksToNanoseconds( { double nsec; - if (tclGetTimeProcPtr != NativeGetTime) { + if (!IsTimeNative()) { nsec = clicks * 1000; } else { #ifdef MAC_OSX_TCL @@ -239,7 +256,7 @@ TclpWideClicksToNanoseconds( } #else #error Wide high-resolution clicks not implemented on this platform -#endif +#endif /* MAC_OSX_TCL */ } return nsec; @@ -266,7 +283,7 @@ TclpWideClicksToNanoseconds( double TclpWideClickInMicrosec(void) { - if (tclGetTimeProcPtr != NativeGetTime) { + if (!IsTimeNative()) { return 1.0; } else { #ifdef MAC_OSX_TCL @@ -286,7 +303,7 @@ TclpWideClickInMicrosec(void) } #else #error Wide high-resolution clicks not implemented on this platform -#endif +#endif /* MAC_OSX_TCL */ } } #endif /* TCL_WIDE_CLICKS */ @@ -315,7 +332,7 @@ void Tcl_GetTime( Tcl_Time *timePtr) /* Location to store time information. */ { - tclGetTimeProcPtr(timePtr, tclTimeClientData); + GetTime(timePtr); } /* @@ -578,7 +595,7 @@ SetTZIfNecessary(void) } else { ckfree(lastTZ); } - lastTZ = (char *)ckalloc(strlen(newTZ) + 1); + lastTZ = (char *) ckalloc(strlen(newTZ) + 1); strcpy(lastTZ, newTZ); } Tcl_MutexUnlock(&tmMutex); diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c index 68ee578..3d90135 100644 --- a/unix/tclXtNotify.c +++ b/unix/tclXtNotify.c @@ -132,7 +132,7 @@ TclSetAppContext( * after initialization, so we panic. */ - Tcl_Panic("TclSetAppContext: multiple application contexts"); + Tcl_Panic("TclSetAppContext: multiple application contexts"); } } else { /* @@ -359,7 +359,7 @@ CreateFileHandler( } } if (filePtr == NULL) { - filePtr = (FileHandler *)ckalloc(sizeof(FileHandler)); + filePtr = (FileHandler *) ckalloc(sizeof(FileHandler)); filePtr->fd = fd; filePtr->read = 0; filePtr->write = 0; @@ -496,7 +496,7 @@ FileProc( int *fd, XtInputId *id) { - FileHandler *filePtr = (FileHandler *)clientData; + FileHandler *filePtr = (FileHandler *) clientData; FileHandlerEvent *fileEvPtr; int mask = 0; @@ -525,7 +525,7 @@ FileProc( */ filePtr->readyMask |= mask; - fileEvPtr = (FileHandlerEvent *)ckalloc(sizeof(FileHandlerEvent)); + fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent)); fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); diff --git a/unix/tclXtTest.c b/unix/tclXtTest.c index afac493..4ee7cca 100644 --- a/unix/tclXtTest.c +++ b/unix/tclXtTest.c @@ -16,7 +16,7 @@ #include "tcl.h" static Tcl_ObjCmdProc TesteventloopCmd; -extern DLLEXPORT Tcl_PackageInitProc Tclxttest_Init; +extern DLLEXPORT Tcl_LibraryInitProc Tclxttest_Init; /* * Functions defined in tclXtNotify.c for use by users of the Xt Notifier: diff --git a/win/rules.vc b/win/rules.vc index 0e99225..1e6a3d3 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -1203,9 +1203,16 @@ TCLSH_NATIVE = $(TCLSH) !if $(DOING_TK) || $(NEED_TK)
WISHNAMEPREFIX = wish
WISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe
-TKLIBNAME = $(PROJECT)$(TK_VERSION)$(SUFX).$(EXT)
-TKSTUBLIBNAME = tkstub$(TK_VERSION).lib
+TKLIBNAME8 = tk$(TK_VERSION)$(SUFX).$(EXT)
+TKLIBNAME9 = tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
+!if $(TCL_MAJOR_VERSION) == 8
+TKLIBNAME = tk$(TK_VERSION)$(SUFX).$(EXT)
TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX).lib
+!else
+TKLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).$(EXT)
+TKIMPLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).lib
+!endif
+TKSTUBLIBNAME = tkstub$(TK_VERSION).lib
!if $(DOING_TK)
WISH = $(OUT_DIR)\$(WISHNAME)
diff --git a/win/tcl.dsp b/win/tcl.dsp index 750aac9..cc9d173 100644 --- a/win/tcl.dsp +++ b/win/tcl.dsp @@ -824,7 +824,7 @@ SOURCE=..\doc\SplitPath.3 # End Source File
# Begin Source File
-SOURCE=..\doc\StaticPkg.3
+SOURCE=..\doc\StaticLibrary.3
# End Source File
# Begin Source File
diff --git a/win/tclAppInit.c b/win/tclAppInit.c index 52ead8e..a10f8db 100644 --- a/win/tclAppInit.c +++ b/win/tclAppInit.c @@ -23,16 +23,20 @@ #include <locale.h> #include <stdlib.h> #include <tchar.h> +#if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7 +# define Tcl_LibraryInitProc Tcl_PackageInitProc +# define Tcl_StaticLibrary Tcl_StaticPackage +#endif #ifdef TCL_TEST -extern Tcl_PackageInitProc Tcltest_Init; -extern Tcl_PackageInitProc Tcltest_SafeInit; +extern Tcl_LibraryInitProc Tcltest_Init; +extern Tcl_LibraryInitProc Tcltest_SafeInit; #endif /* TCL_TEST */ #if defined(STATIC_BUILD) -extern Tcl_PackageInitProc Registry_Init; -extern Tcl_PackageInitProc Dde_Init; -extern Tcl_PackageInitProc Dde_SafeInit; +extern Tcl_LibraryInitProc Registry_Init; +extern Tcl_LibraryInitProc Dde_Init; +extern Tcl_LibraryInitProc Dde_SafeInit; #endif #if defined(__GNUC__) || defined(TCL_BROKEN_MAINARGS) @@ -168,19 +172,19 @@ Tcl_AppInit( if (Registry_Init(interp) == TCL_ERROR) { return TCL_ERROR; } - Tcl_StaticPackage(interp, "Registry", Registry_Init, NULL); + Tcl_StaticLibrary(interp, "Registry", Registry_Init, NULL); if (Dde_Init(interp) == TCL_ERROR) { return TCL_ERROR; } - Tcl_StaticPackage(interp, "Dde", Dde_Init, Dde_SafeInit); + Tcl_StaticLibrary(interp, "Dde", Dde_Init, Dde_SafeInit); #endif #ifdef TCL_TEST if (Tcltest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } - Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); + Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit); #endif /* TCL_TEST */ /* diff --git a/win/tclWinChan.c b/win/tclWinChan.c index a4ec1ae..62991fc 100644 --- a/win/tclWinChan.c +++ b/win/tclWinChan.c @@ -421,7 +421,7 @@ FileCloseProc( && (GetStdHandle(STD_OUTPUT_HANDLE) != fileInfoPtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != fileInfoPtr->handle))) { if (CloseHandle(fileInfoPtr->handle) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); errorCode = errno; } } @@ -497,7 +497,7 @@ FileSeekProc( DWORD winError = GetLastError(); if (winError != NO_ERROR) { - TclWinConvertError(winError); + Tcl_WinConvertError(winError); *errorCodePtr = errno; return -1; } @@ -509,7 +509,7 @@ FileSeekProc( DWORD winError = GetLastError(); if (winError != NO_ERROR) { - TclWinConvertError(winError); + Tcl_WinConvertError(winError); *errorCodePtr = errno; return -1; } @@ -573,7 +573,7 @@ FileWideSeekProc( DWORD winError = GetLastError(); if (winError != NO_ERROR) { - TclWinConvertError(winError); + Tcl_WinConvertError(winError); *errorCodePtr = errno; return -1; } @@ -616,7 +616,7 @@ FileTruncateProc( DWORD winError = GetLastError(); if (winError != NO_ERROR) { - TclWinConvertError(winError); + Tcl_WinConvertError(winError); return errno; } } @@ -632,7 +632,7 @@ FileTruncateProc( DWORD winError = GetLastError(); if (winError != NO_ERROR) { - TclWinConvertError(winError); + Tcl_WinConvertError(winError); return errno; } } @@ -643,7 +643,7 @@ FileTruncateProc( */ if (!SetEndOfFile(infoPtr->handle)) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return errno; } @@ -703,7 +703,7 @@ FileInputProc( return bytesRead; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); *errorCode = errno; if (errno == EPIPE) { return 0; @@ -752,7 +752,7 @@ FileOutputProc( if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); *errorCode = errno; return -1; } @@ -927,7 +927,7 @@ TclpOpenFileChannel( if (NativeIsComPort(nativeName)) { handle = TclWinSerialOpen(INVALID_HANDLE_VALUE, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open serial \"%s\": %s", @@ -984,7 +984,7 @@ TclpOpenFileChannel( err = TEST_FLAG(mode, O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } - TclWinConvertError(err); + Tcl_WinConvertError(err); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": %s", @@ -1008,7 +1008,7 @@ TclpOpenFileChannel( handle = TclWinSerialOpen(handle, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't reopen serial \"%s\": %s", diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index 0556646..c3ba814 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -602,7 +602,7 @@ ConsoleCloseProc( && (GetStdHandle(STD_OUTPUT_HANDLE) != consolePtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != consolePtr->handle))) { if (CloseHandle(consolePtr->handle) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); errorCode = errno; } } @@ -772,7 +772,7 @@ ConsoleOutputProc( */ if (infoPtr->writeError) { - TclWinConvertError(infoPtr->writeError); + Tcl_WinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error; } @@ -807,7 +807,7 @@ ConsoleOutputProc( if (WriteConsoleBytes(infoPtr->handle, buf, (DWORD) toWrite, &bytesWritten) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); goto error; } } @@ -1065,7 +1065,7 @@ WaitForRead( * Check to see if the peek failed because of EOF. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (errno == EOF) { infoPtr->readFlags |= CONSOLE_EOF; @@ -1477,7 +1477,7 @@ ConsoleSetOptionProc( DWORD mode; if (GetConsoleMode(infoPtr->handle, &mode) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read console mode: %s", @@ -1509,7 +1509,7 @@ ConsoleSetOptionProc( return TCL_ERROR; } if (SetConsoleMode(infoPtr->handle, mode) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't set console mode: %s", @@ -1589,7 +1589,7 @@ ConsoleGetOptionProc( valid = 1; if (GetConsoleMode(infoPtr->handle, &mode) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read console mode: %s", @@ -1620,7 +1620,7 @@ ConsoleGetOptionProc( valid = 1; if (!GetConsoleScreenBufferInfo(infoPtr->handle, &consoleInfo)) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read console size: %s", diff --git a/win/tclWinError.c b/win/tclWinError.c index e85becc..7e5898b 100644 --- a/win/tclWinError.c +++ b/win/tclWinError.c @@ -334,7 +334,7 @@ static const unsigned char wsaErrorTable[] = { /* *---------------------------------------------------------------------- * - * TclWinConvertError -- + * Tcl_WinConvertError -- * * This routine converts a Win32 error into an errno value. * @@ -348,8 +348,8 @@ static const unsigned char wsaErrorTable[] = { */ void -TclWinConvertError( - DWORD errCode) /* Win32 error code. */ +Tcl_WinConvertError( + unsigned errCode) /* Win32 error code. */ { if (errCode >= sizeof(errorTable)/sizeof(errorTable[0])) { errCode -= WSAEWOULDBLOCK; diff --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index c88621c..3f6d7f4 100644 --- a/win/tclWinFCmd.c +++ b/win/tclWinFCmd.c @@ -279,7 +279,7 @@ DoRenameFile( return retval; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); srcAttr = GetFileAttributesW(nativeSrc); dstAttr = GetFileAttributesW(nativeDst); @@ -420,7 +420,7 @@ DoRenameFile( * be, but report this one. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); CreateDirectoryW(nativeDst, NULL); SetFileAttributesW(nativeDst, dstAttr); if (Tcl_GetErrno() == EACCES) { @@ -488,7 +488,7 @@ DoRenameFile( * error. Could happen if an open file refers to dst. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { /* * Decode the EACCES to a more meaningful error. @@ -669,7 +669,7 @@ DoCopyFile( return retval; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (Tcl_GetErrno() == EBADF) { Tcl_SetErrno(EACCES); return TCL_ERROR; @@ -706,7 +706,7 @@ DoCopyFile( * attributes of dst. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); SetFileAttributesW(nativeDst, dstAttr); } } @@ -766,7 +766,7 @@ TclpDeleteFile( if (DeleteFileW(path) != FALSE) { return TCL_OK; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { attr = GetFileAttributesW(path); @@ -797,7 +797,7 @@ TclpDeleteFile( (DeleteFileW(path) != FALSE)) { return TCL_OK; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (res != 0) { SetFileAttributesW(path, attr); } @@ -866,7 +866,7 @@ DoCreateDirectory( if (CreateDirectoryW(nativePath, NULL) == 0) { DWORD error = GetLastError(); - TclWinConvertError(error); + Tcl_WinConvertError(error); return TCL_ERROR; } return TCL_OK; @@ -1054,7 +1054,7 @@ DoRemoveJustDirectory( } } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { attr = GetFileAttributesW(nativePath); @@ -1088,7 +1088,7 @@ DoRemoveJustDirectory( if (RemoveDirectoryW(nativePath) != FALSE) { return TCL_OK; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); SetFileAttributesW(nativePath, attr | FILE_ATTRIBUTE_READONLY); } @@ -1235,7 +1235,7 @@ TraverseWinTree( * Can't read directory. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); nativeErrfile = nativeSource; goto end; } @@ -1329,7 +1329,7 @@ TraverseWinTree( end: if (nativeErrfile != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (errorPtr != NULL) { Tcl_DStringInit(errorPtr); Tcl_WCharToUtfDString(nativeErrfile, -1, errorPtr); @@ -1384,7 +1384,7 @@ TraversalCopy( attr) != FALSE) { return TCL_OK; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); } break; case DOTREE_POSTD: @@ -1482,7 +1482,7 @@ StatError( Tcl_Obj *fileName) /* The name of the file which caused the * error. */ { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); } @@ -2067,7 +2067,7 @@ TclpCreateTemporaryDirectory( */ if (error != ERROR_SUCCESS) { - TclWinConvertError(error); + Tcl_WinConvertError(error); Tcl_DStringFree(&base); return NULL; } diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 1e0aca7..b02dc84 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -209,7 +209,7 @@ WinLink( * Invalid file. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } @@ -233,7 +233,7 @@ WinLink( * Invalid file. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } @@ -247,7 +247,7 @@ WinLink( * The target doesn't exist. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { /* * It is a file. @@ -262,7 +262,7 @@ WinLink( return 0; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); } else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) { if (CreateSymbolicLinkW(linkSourcePath, linkTargetPath, 0x2 /* SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE */)) { @@ -272,7 +272,7 @@ WinLink( return 0; } else { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); } } else { Tcl_SetErrno(ENODEV); @@ -327,7 +327,7 @@ WinReadLink( * Invalid file. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return NULL; } @@ -341,7 +341,7 @@ WinReadLink( * The source doesn't exist. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return NULL; } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { @@ -502,7 +502,7 @@ TclWinSymLinkDelete( * Error setting junction. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); CloseHandle(hFile); } else { CloseHandle(hFile); @@ -695,7 +695,7 @@ NativeReadReparse( * Error creating directory. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } @@ -709,7 +709,7 @@ NativeReadReparse( * Error setting junction. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); CloseHandle(hFile); return -1; } @@ -751,7 +751,7 @@ NativeWriteReparse( * Error creating directory. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } hFile = CreateFileW(linkDirPath, GENERIC_WRITE, 0, NULL, @@ -762,7 +762,7 @@ NativeWriteReparse( * Error creating directory. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } @@ -777,7 +777,7 @@ NativeWriteReparse( * Error setting junction. */ - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); CloseHandle(hFile); RemoveDirectoryW(linkDirPath); return -1; @@ -1057,7 +1057,7 @@ TclpMatchInDirectory( return TCL_OK; } - TclWinConvertError(err); + Tcl_WinConvertError(err); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read directory \"%s\": %s", @@ -1606,7 +1606,7 @@ NativeAccess( DWORD lasterror = GetLastError(); if (lasterror != ERROR_SHARING_VIOLATION) { - TclWinConvertError(lasterror); + Tcl_WinConvertError(lasterror); return -1; } } @@ -1732,7 +1732,7 @@ NativeAccess( * to EACCES - just what we want! */ - TclWinConvertError((DWORD) error); + Tcl_WinConvertError((DWORD) error); return -1; } @@ -1837,7 +1837,7 @@ NativeAccess( */ accessError: - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (sdPtr != NULL) { HeapFree(GetProcessHeap(), 0, sdPtr); } @@ -1932,7 +1932,7 @@ TclpObjChdir( result = SetCurrentDirectoryW(nativePath); if (result == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } return 0; @@ -1971,7 +1971,7 @@ TclpGetCwd( WCHAR *native; if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error getting working directory name: %s", @@ -2136,12 +2136,12 @@ NativeStat( DWORD lasterror = GetLastError(); if (lasterror != ERROR_SHARING_VIOLATION) { - TclWinConvertError(lasterror); + Tcl_WinConvertError(lasterror); return -1; } hFind = FindFirstFileW(nativePath, &ffd); if (hFind == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return -1; } memcpy(&data, &ffd, sizeof(data)); @@ -2370,7 +2370,7 @@ TclpGetNativeCwd( WCHAR buffer[MAX_PATH]; if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return NULL; } @@ -3271,7 +3271,7 @@ TclpUtime( if (fileHandle == INVALID_HANDLE_VALUE || !SetFileTime(fileHandle, NULL, &lastAccessTime, &lastModTime)) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); res = -1; } if (fileHandle != INVALID_HANDLE_VALUE) { diff --git a/win/tclWinLoad.c b/win/tclWinLoad.c index 656148a..0f664f0 100644 --- a/win/tclWinLoad.c +++ b/win/tclWinLoad.c @@ -159,7 +159,7 @@ TclpDlopen( Tcl_AppendToObj(errMsg, "Bad exe format. Possibly a 32/64-bit mismatch.", -1); break; default: - TclWinConvertError(lastError); + Tcl_WinConvertError(lastError); Tcl_AppendToObj(errMsg, Tcl_PosixError(interp), -1); } Tcl_SetObjResult(interp, errMsg); @@ -379,7 +379,7 @@ InitDLLDirectoryName(void) id *= 16777619; } - TclWinConvertError(lastError); + Tcl_WinConvertError(lastError); return TCL_ERROR; /* diff --git a/win/tclWinNotify.c b/win/tclWinNotify.c index fff7910..068675c 100644 --- a/win/tclWinNotify.c +++ b/win/tclWinNotify.c @@ -77,65 +77,62 @@ static LRESULT CALLBACK NotifierProc(HWND hwnd, UINT message, */ ClientData -Tcl_InitNotifier(void) +TclpInitNotifier(void) { - if (tclNotifierHooks.initNotifierProc) { - return tclNotifierHooks.initNotifierProc(); - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - TclpGlobalLock(); - if (!initialized) { - initialized = 1; - InitializeCriticalSection(¬ifierMutex); - } - TclpGlobalUnlock(); + TclpGlobalLock(); + if (!initialized) { + initialized = 1; + InitializeCriticalSection(¬ifierMutex); + } + TclpGlobalUnlock(); - /* - * Register Notifier window class if this is the first thread to use - * this module. - */ + /* + * Register Notifier window class if this is the first thread to use this + * module. + */ - EnterCriticalSection(¬ifierMutex); - if (notifierCount == 0) { - WNDCLASSW clazz; - - clazz.style = 0; - clazz.cbClsExtra = 0; - clazz.cbWndExtra = 0; - clazz.hInstance = TclWinGetTclInstance(); - clazz.hbrBackground = NULL; - clazz.lpszMenuName = NULL; - clazz.lpszClassName = className; - clazz.lpfnWndProc = NotifierProc; - clazz.hIcon = NULL; - clazz.hCursor = NULL; - - if (!RegisterClassW(&clazz)) { - Tcl_Panic("Unable to register TclNotifier window class"); - } + EnterCriticalSection(¬ifierMutex); + if (notifierCount == 0) { + WNDCLASSW clazz; + + clazz.style = 0; + clazz.cbClsExtra = 0; + clazz.cbWndExtra = 0; + clazz.hInstance = TclWinGetTclInstance(); + clazz.hbrBackground = NULL; + clazz.lpszMenuName = NULL; + clazz.lpszClassName = className; + clazz.lpfnWndProc = NotifierProc; + clazz.hIcon = NULL; + clazz.hCursor = NULL; + + if (!RegisterClassW(&clazz)) { + Tcl_Panic("Tcl_InitNotifier: %s", + "unable to register TclNotifier window class"); } - notifierCount++; - LeaveCriticalSection(¬ifierMutex); + } + notifierCount++; + LeaveCriticalSection(¬ifierMutex); - tsdPtr->pending = 0; - tsdPtr->timerActive = 0; + tsdPtr->pending = 0; + tsdPtr->timerActive = 0; - InitializeCriticalSection(&tsdPtr->crit); + InitializeCriticalSection(&tsdPtr->crit); - tsdPtr->hwnd = NULL; - tsdPtr->thread = GetCurrentThreadId(); - tsdPtr->event = CreateEventW(NULL, TRUE /* manual */, - FALSE /* !signaled */, NULL); + tsdPtr->hwnd = NULL; + tsdPtr->thread = GetCurrentThreadId(); + tsdPtr->event = CreateEventW(NULL, TRUE /* manual */, + FALSE /* !signaled */, NULL); - return tsdPtr; - } + return tsdPtr; } /* *---------------------------------------------------------------------- * - * Tcl_FinalizeNotifier -- + * TclpFinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread * is terminated. @@ -150,62 +147,57 @@ Tcl_InitNotifier(void) */ void -Tcl_FinalizeNotifier( +TclpFinalizeNotifier( ClientData clientData) /* Pointer to notifier data. */ { - if (tclNotifierHooks.finalizeNotifierProc) { - tclNotifierHooks.finalizeNotifierProc(clientData); - return; - } else { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; - /* - * Only finalize the notifier if a notifier was installed in the - * current thread; there is a route in which this is not guaranteed to - * be true (when tclWin32Dll.c:DllMain() is called with the flag - * DLL_PROCESS_DETACH by the OS, which could be doing so from a thread - * that's never previously been involved with Tcl, e.g. the task - * manager) so this check is important. - * - * Fixes Bug #217982 reported by Hugh Vu and Gene Leache. - */ + /* + * Only finalize the notifier if a notifier was installed in the current + * thread; there is a route in which this is not guaranteed to be true + * (when tclWin32Dll.c:DllMain() is called with the flag + * DLL_PROCESS_DETACH by the OS, which could be doing so from a thread + * that's never previously been involved with Tcl, e.g. the task manager) + * so this check is important. + * + * Fixes Bug #217982 reported by Hugh Vu and Gene Leache. + */ - if (tsdPtr == NULL) { - return; - } + if (tsdPtr == NULL) { + return; + } - DeleteCriticalSection(&tsdPtr->crit); - CloseHandle(tsdPtr->event); + DeleteCriticalSection(&tsdPtr->crit); + CloseHandle(tsdPtr->event); - /* - * Clean up the timer and messaging window for this thread. - */ + /* + * Clean up the timer and messaging window for this thread. + */ - if (tsdPtr->hwnd) { - KillTimer(tsdPtr->hwnd, INTERVAL_TIMER); - DestroyWindow(tsdPtr->hwnd); - } + if (tsdPtr->hwnd) { + KillTimer(tsdPtr->hwnd, INTERVAL_TIMER); + DestroyWindow(tsdPtr->hwnd); + } - /* - * If this is the last thread to use the notifier, unregister the - * notifier window class. - */ + /* + * If this is the last thread to use the notifier, unregister the notifier + * window class. + */ - EnterCriticalSection(¬ifierMutex); - if (notifierCount) { - notifierCount--; - if (notifierCount == 0) { - UnregisterClassW(className, TclWinGetTclInstance()); - } + EnterCriticalSection(¬ifierMutex); + if (notifierCount) { + notifierCount--; + if (notifierCount == 0) { + UnregisterClassW(className, TclWinGetTclInstance()); } - LeaveCriticalSection(¬ifierMutex); } + LeaveCriticalSection(¬ifierMutex); } /* *---------------------------------------------------------------------- * - * Tcl_AlertNotifier -- + * TclpAlertNotifier -- * * Wake up the specified notifier from any thread. This routine is called * by the platform independent notifier code whenever the Tcl_ThreadAlert @@ -225,42 +217,37 @@ Tcl_FinalizeNotifier( */ void -Tcl_AlertNotifier( +TclpAlertNotifier( ClientData clientData) /* Pointer to thread data. */ { - if (tclNotifierHooks.alertNotifierProc) { - tclNotifierHooks.alertNotifierProc(clientData); - return; - } else { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; + + /* + * Note that we do not need to lock around access to the hwnd because the + * race condition has no effect since any race condition implies that the + * notifier thread is already awake. + */ + if (tsdPtr->hwnd) { /* - * Note that we do not need to lock around access to the hwnd because - * the race condition has no effect since any race condition implies - * that the notifier thread is already awake. + * We do need to lock around access to the pending flag. */ - if (tsdPtr->hwnd) { - /* - * We do need to lock around access to the pending flag. - */ - - EnterCriticalSection(&tsdPtr->crit); - if (!tsdPtr->pending) { - PostMessageW(tsdPtr->hwnd, WM_WAKEUP, 0, 0); - } - tsdPtr->pending = 1; - LeaveCriticalSection(&tsdPtr->crit); - } else { - SetEvent(tsdPtr->event); + EnterCriticalSection(&tsdPtr->crit); + if (!tsdPtr->pending) { + PostMessageW(tsdPtr->hwnd, WM_WAKEUP, 0, 0); } + tsdPtr->pending = 1; + LeaveCriticalSection(&tsdPtr->crit); + } else { + SetEvent(tsdPtr->event); } } /* *---------------------------------------------------------------------- * - * Tcl_SetTimer -- + * TclpSetTimer -- * * This procedure sets the current notifier timer value. The notifier * will ensure that Tcl_ServiceAll() is called after the specified @@ -276,54 +263,49 @@ Tcl_AlertNotifier( */ void -Tcl_SetTimer( +TclpSetTimer( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { - if (tclNotifierHooks.setTimerProc) { - tclNotifierHooks.setTimerProc(timePtr); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + UINT timeout; + + /* + * We only need to set up an interval timer if we're being called from an + * external event loop. If we don't have a window handle then we just + * return immediately and let Tcl_WaitForEvent handle timeouts. + */ + + if (!tsdPtr->hwnd) { return; - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - UINT timeout; + } + if (!timePtr) { + timeout = 0; + } else { /* - * We only need to set up an interval timer if we're being called from - * an external event loop. If we don't have a window handle then we - * just return immediately and let Tcl_WaitForEvent handle timeouts. + * Make sure we pass a non-zero value into the timeout argument. + * Windows seems to get confused by zero length timers. */ - if (!tsdPtr->hwnd) { - return; + timeout = timePtr->sec * 1000 + timePtr->usec / 1000; + if (timeout == 0) { + timeout = 1; } + } - if (!timePtr) { - timeout = 0; - } else { - /* - * Make sure we pass a non-zero value into the timeout argument. - * Windows seems to get confused by zero length timers. - */ - - timeout = timePtr->sec * 1000 + timePtr->usec / 1000; - if (timeout == 0) { - timeout = 1; - } - } - if (timeout != 0) { - tsdPtr->timerActive = 1; - SetTimer(tsdPtr->hwnd, INTERVAL_TIMER, - timeout, NULL); - } else { - tsdPtr->timerActive = 0; - KillTimer(tsdPtr->hwnd, INTERVAL_TIMER); - } + if (timeout != 0) { + tsdPtr->timerActive = 1; + SetTimer(tsdPtr->hwnd, INTERVAL_TIMER, timeout, NULL); + } else { + tsdPtr->timerActive = 0; + KillTimer(tsdPtr->hwnd, INTERVAL_TIMER); } } /* *---------------------------------------------------------------------- * - * Tcl_ServiceModeHook -- + * TclpServiceModeHook -- * * This function is invoked whenever the service mode changes. * @@ -338,40 +320,33 @@ Tcl_SetTimer( */ void -Tcl_ServiceModeHook( +TclpServiceModeHook( int mode) /* Either TCL_SERVICE_ALL, or * TCL_SERVICE_NONE. */ { - if (tclNotifierHooks.serviceModeHookProc) { - tclNotifierHooks.serviceModeHookProc(mode); - return; - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - /* - * If this is the first time that the notifier has been used from a - * modal loop, then create a communication window. Note that after this - * point, the application needs to service events in a timely fashion - * or Windows will hang waiting for the window to respond to - * synchronous system messages. At some point, we may want to consider - * destroying the window if we leave the modal loop, but for now we'll - * leave it around. - */ + /* + * If this is the first time that the notifier has been used from a modal + * loop, then create a communication window. Note that after this point, + * the application needs to service events in a timely fashion or Windows + * will hang waiting for the window to respond to synchronous system + * messages. At some point, we may want to consider destroying the window + * if we leave the modal loop, but for now we'll leave it around. + */ - if (mode == TCL_SERVICE_ALL && !tsdPtr->hwnd) { - tsdPtr->hwnd = CreateWindowW(className, className, - WS_TILED, 0, 0, 0, 0, NULL, NULL, TclWinGetTclInstance(), - NULL); + if (mode == TCL_SERVICE_ALL && !tsdPtr->hwnd) { + tsdPtr->hwnd = CreateWindowW(className, className, WS_TILED, + 0, 0, 0, 0, NULL, NULL, TclWinGetTclInstance(), NULL); - /* - * Send an initial message to the window to ensure that we wake up - * the notifier once we get into the modal loop. This will force - * the notifier to recompute the timeout value and schedule a timer - * if one is needed. - */ + /* + * Send an initial message to the window to ensure that we wake up the + * notifier once we get into the modal loop. This will force the + * notifier to recompute the timeout value and schedule a timer if one + * is needed. + */ - Tcl_AlertNotifier(tsdPtr); - } + Tcl_AlertNotifier(tsdPtr); } } @@ -421,7 +396,7 @@ NotifierProc( /* *---------------------------------------------------------------------- * - * Tcl_WaitForEvent -- + * TclpWaitForEvent -- * * 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 @@ -438,103 +413,99 @@ NotifierProc( */ int -Tcl_WaitForEvent( +TclpWaitForEvent( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { - if (tclNotifierHooks.waitForEventProc) { - return tclNotifierHooks.waitForEventProc(timePtr); - } else { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - MSG msg; - DWORD timeout, result; - int status; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + MSG msg; + DWORD timeout, result; + int status; + /* + * Compute the timeout in milliseconds. + */ + + if (timePtr) { /* - * Compute the timeout in milliseconds. + * TIP #233 (Virtualized Time). Convert virtual domain delay to + * real-time. */ - if (timePtr) { - /* - * TIP #233 (Virtualized Time). Convert virtual domain delay to - * real-time. - */ + Tcl_Time myTime; - Tcl_Time myTime; + myTime.sec = timePtr->sec; + myTime.usec = timePtr->usec; - myTime.sec = timePtr->sec; - myTime.usec = timePtr->usec; + if (myTime.sec != 0 || myTime.usec != 0) { + TclScaleTime(&myTime); + } - if (myTime.sec != 0 || myTime.usec != 0) { - tclScaleTimeProcPtr(&myTime, tclTimeClientData); - } + timeout = myTime.sec * 1000 + myTime.usec / 1000; + } else { + timeout = INFINITE; + } - timeout = myTime.sec * 1000 + myTime.usec / 1000; - } else { - timeout = INFINITE; - } + /* + * Check to see if there are any messages in the queue before waiting + * because MsgWaitForMultipleObjects will not wake up if there are events + * currently sitting in the queue. + */ + if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) { /* - * Check to see if there are any messages in the queue before waiting - * because MsgWaitForMultipleObjects will not wake up if there are - * events currently sitting in the queue. + * Wait for something to happen (a signal from another thread, a + * message, or timeout) or loop servicing asynchronous procedure calls + * queued to this thread. */ - if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) { - /* - * Wait for something to happen (a signal from another thread, a - * message, or timeout) or loop servicing asynchronous procedure - * calls queued to this thread. - */ - - again: + do { result = MsgWaitForMultipleObjectsEx(1, &tsdPtr->event, timeout, QS_ALLINPUT, MWMO_ALERTABLE); - if (result == WAIT_IO_COMPLETION) { - goto again; - } else if (result == WAIT_FAILED) { - status = -1; - goto end; - } + } while (result == WAIT_IO_COMPLETION); + + if (result == WAIT_FAILED) { + status = -1; + goto end; } + } + + /* + * Check to see if there are any messages to process. + */ + if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) { /* - * Check to see if there are any messages to process. + * Retrieve and dispatch the first message. */ - if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) { + result = GetMessageW(&msg, NULL, 0, 0); + if (result == 0) { /* - * Retrieve and dispatch the first message. + * We received a request to exit this thread (WM_QUIT), so + * propagate the quit message and start unwinding. */ - result = GetMessageW(&msg, NULL, 0, 0); - if (result == 0) { - /* - * We received a request to exit this thread (WM_QUIT), so - * propagate the quit message and start unwinding. - */ - - PostQuitMessage((int) msg.wParam); - status = -1; - } else if (result == (DWORD)-1) { - /* - * We got an error from the system. I have no idea why this - * would happen, so we'll just unwind. - */ - - status = -1; - } else { - TranslateMessage(&msg); - DispatchMessageW(&msg); - status = 1; - } + PostQuitMessage((int) msg.wParam); + status = -1; + } else if (result == (DWORD) -1) { + /* + * We got an error from the system. I have no idea why this would + * happen, so we'll just unwind. + */ + + status = -1; } else { - status = 0; + TranslateMessage(&msg); + DispatchMessageW(&msg); + status = 1; } - - end: - ResetEvent(tsdPtr->event); - return status; + } else { + status = 0; } + + end: + ResetEvent(tsdPtr->event); + return status; } /* @@ -588,7 +559,7 @@ Tcl_Sleep( * TIP #233: Scale delay from virtual to real-time. */ - tclScaleTimeProcPtr(&vdelay, tclTimeClientData); + TclScaleTime(&vdelay); sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; for (;;) { @@ -603,7 +574,7 @@ Tcl_Sleep( vdelay.sec = desired.sec - now.sec; vdelay.usec = desired.usec - now.usec; - tclScaleTimeProcPtr(&vdelay, tclTimeClientData); + TclScaleTime(&vdelay); sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; } } diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c index 90ac9ef..29b1c03 100644 --- a/win/tclWinPipe.c +++ b/win/tclWinPipe.c @@ -549,7 +549,7 @@ TclpOpenFile( accessMode = (GENERIC_READ | GENERIC_WRITE); break; default: - TclWinConvertError(ERROR_INVALID_FUNCTION); + Tcl_WinConvertError(ERROR_INVALID_FUNCTION); return NULL; } @@ -613,7 +613,7 @@ TclpOpenFile( if ((err & 0xFFFFL) == ERROR_OPEN_FAILED) { err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } - TclWinConvertError(err); + Tcl_WinConvertError(err); return NULL; } @@ -719,7 +719,7 @@ TclpCreateTempFile( Tcl_DStringFree(&dstring); } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); CloseHandle(handle); DeleteFileW(name); return NULL; @@ -784,7 +784,7 @@ TclpCreatePipe( return 1; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return 0; } @@ -825,7 +825,7 @@ TclpCloseFile( && (GetStdHandle(STD_ERROR_HANDLE) != filePtr->handle))) { if (filePtr->handle != NULL && CloseHandle(filePtr->handle) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); ckfree(filePtr); return -1; } @@ -1026,7 +1026,7 @@ TclpCreateProcess( 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate input handle: %s", Tcl_PosixError(interp))); @@ -1055,7 +1055,7 @@ TclpCreateProcess( &startInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate output handle: %s", Tcl_PosixError(interp))); @@ -1075,7 +1075,7 @@ TclpCreateProcess( 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdError == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate error handle: %s", Tcl_PosixError(interp))); @@ -1137,7 +1137,7 @@ TclpCreateProcess( if (CreateProcessW(NULL, (WCHAR *) Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, (DWORD) createFlags, NULL, NULL, &startInfo, &procInfo) == 0) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", argv[0], Tcl_PosixError(interp))); goto end; @@ -1387,7 +1387,7 @@ ApplicationType( Tcl_DStringFree(&nameBuf); if (applType == APPL_NONE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", originalName, Tcl_PosixError(interp))); return APPL_NONE; @@ -1866,7 +1866,7 @@ Tcl_CreatePipe( sec.bInheritHandle = FALSE; if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "pipe creation failed: %s", Tcl_PosixError(interp))); return TCL_ERROR; @@ -2224,7 +2224,7 @@ PipeInputProc( return bytesRead; } - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); if (errno == EPIPE) { infoPtr->readFlags |= PIPE_EOF; return 0; @@ -2283,7 +2283,7 @@ PipeOutputProc( */ if (infoPtr->writeError) { - TclWinConvertError(infoPtr->writeError); + Tcl_WinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error; } @@ -2318,7 +2318,7 @@ PipeOutputProc( if (WriteFile(filePtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); goto error; } } @@ -2850,7 +2850,7 @@ WaitForRead( if (PeekNamedPipe(handle, (LPVOID) NULL, (DWORD) 0, (LPDWORD) NULL, &count, (LPDWORD) NULL) != TRUE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); /* * Check to see if the peek failed because of EOF. @@ -3260,7 +3260,7 @@ TclpOpenTemporaryFile( TCL_READABLE|TCL_WRITABLE); gotError: - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return NULL; } diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c index 32f4c31..403c9d5 100644 --- a/win/tclWinSerial.c +++ b/win/tclWinSerial.c @@ -645,7 +645,7 @@ SerialCloseProc( && (GetStdHandle(STD_OUTPUT_HANDLE) != serialPtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != serialPtr->handle))) { if (CloseHandle(serialPtr->handle) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); errorCode = errno; } } @@ -928,7 +928,7 @@ SerialInputProc( if (SerialBlockingRead(infoPtr, (LPVOID) buf, (DWORD) bufSize, &bytesRead, &infoPtr->osRead) == FALSE) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); *errorCode = errno; return -1; } @@ -1010,7 +1010,7 @@ SerialOutputProc( */ if (infoPtr->writeError) { - TclWinConvertError(infoPtr->writeError); + Tcl_WinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error1; } @@ -1069,7 +1069,7 @@ SerialOutputProc( return (int) bytesWritten; writeError: - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); error: /* @@ -1936,7 +1936,7 @@ SerialSetOptionProc( if (!SetupComm(infoPtr->handle, inSize, outSize)) { if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't setup comm buffers: %s", Tcl_PosixError(interp))); @@ -1987,7 +1987,7 @@ SerialSetOptionProc( tout.ReadTotalTimeoutConstant = msec; if (!SetCommTimeouts(infoPtr->handle, &tout)) { if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't set comm timeouts: %s", Tcl_PosixError(interp))); @@ -2004,7 +2004,7 @@ SerialSetOptionProc( getStateFailed: if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } @@ -2012,7 +2012,7 @@ SerialSetOptionProc( setStateFailed: if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't set comm state: %s", Tcl_PosixError(interp))); } @@ -2095,7 +2095,7 @@ SerialGetOptionProc( if (!GetCommState(infoPtr->handle, &dcb)) { if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } @@ -2165,7 +2165,7 @@ SerialGetOptionProc( if (!GetCommState(infoPtr->handle, &dcb)) { if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } @@ -2243,7 +2243,7 @@ SerialGetOptionProc( if (!GetCommModemStatus(infoPtr->handle, &status)) { if (interp != NULL) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get tty status: %s", Tcl_PosixError(interp))); } diff --git a/win/tclWinSock.c b/win/tclWinSock.c index a31e1a2..60575df 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -882,7 +882,7 @@ TcpInputProc( if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING) || (error != WSAEWOULDBLOCK)) { - TclWinConvertError(error); + Tcl_WinConvertError(error); *errorCodePtr = Tcl_GetErrno(); bytesRead = -1; break; @@ -996,7 +996,7 @@ TcpOutputProc( break; } } else { - TclWinConvertError(error); + Tcl_WinConvertError(error); *errorCodePtr = Tcl_GetErrno(); written = -1; break; @@ -1064,7 +1064,7 @@ TcpCloseProc( statePtr->sockets = thisfd->next; if (closesocket(thisfd->fd) == SOCKET_ERROR) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); errorCode = Tcl_GetErrno(); } ckfree(thisfd); @@ -1154,11 +1154,11 @@ TcpClose2Proc( */ if ((flags & TCL_CLOSE_READ) && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); readError = Tcl_GetErrno(); } if ((flags & TCL_CLOSE_WRITE) && (shutdown(statePtr->sockets->fd, SD_SEND) == SOCKET_ERROR)) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); writeError = Tcl_GetErrno(); } return (readError != 0) ? readError : writeError; @@ -1225,7 +1225,7 @@ TcpSetOptionProc( rtn = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char *) &val, sizeof(BOOL)); if (rtn != 0) { - TclWinConvertError(WSAGetLastError()); + Tcl_WinConvertError(WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't set socket option: %s", @@ -1247,7 +1247,7 @@ TcpSetOptionProc( rtn = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &val, sizeof(BOOL)); if (rtn != 0) { - TclWinConvertError(WSAGetLastError()); + Tcl_WinConvertError(WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't set socket option: %s", @@ -1382,7 +1382,7 @@ TcpGetOptionProc( */ if (err) { - TclWinConvertError(err); + Tcl_WinConvertError(err); Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), -1); } @@ -1452,7 +1452,7 @@ TcpGetOptionProc( */ if (len) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get peername: %s", @@ -1528,7 +1528,7 @@ TcpGetOptionProc( Tcl_DStringEndSublist(dsPtr); } else { if (interp) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get sockname: %s", Tcl_PosixError(interp))); } @@ -1780,7 +1780,7 @@ TcpConnect( */ if (statePtr->sockets->fd == INVALID_SOCKET) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); continue; } @@ -1805,7 +1805,7 @@ TcpConnect( if (bind(statePtr->sockets->fd, statePtr->myaddr->ai_addr, statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); continue; } @@ -1876,7 +1876,7 @@ TcpConnect( statePtr->addr->ai_addrlen); error = WSAGetLastError(); - TclWinConvertError(error); + Tcl_WinConvertError(error); if (async_connect && error == WSAEWOULDBLOCK) { /* @@ -1908,7 +1908,7 @@ TcpConnect( * Get signaled connect error. */ - TclWinConvertError((DWORD) statePtr->notifierConnectError); + Tcl_WinConvertError((DWORD) statePtr->notifierConnectError); /* * Clear eventual connect flag. @@ -2237,7 +2237,7 @@ Tcl_OpenTcpServerEx( sock = socket(addrPtr->ai_family, addrPtr->ai_socktype, addrPtr->ai_protocol); if (sock == INVALID_SOCKET) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); continue; } @@ -2288,7 +2288,7 @@ Tcl_OpenTcpServerEx( if (bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen) == SOCKET_ERROR) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } @@ -2313,7 +2313,7 @@ Tcl_OpenTcpServerEx( */ if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { - TclWinConvertError((DWORD) WSAGetLastError()); + Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } @@ -2498,7 +2498,7 @@ InitSockets(void) windowClass.hCursor = NULL; if (!RegisterClassW(&windowClass)) { - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); goto initFailure; } } diff --git a/win/tclWinTest.c b/win/tclWinTest.c index e924b1a..f45b557 100644 --- a/win/tclWinTest.c +++ b/win/tclWinTest.c @@ -208,7 +208,7 @@ TestvolumetypeCmd( if (found == 0) { Tcl_AppendResult(interp, "could not get volume type for \"", (path?path:""), "\"", NULL); - TclWinConvertError(GetLastError()); + Tcl_WinConvertError(GetLastError()); return TCL_ERROR; } Tcl_AppendResult(interp, volType, NULL); diff --git a/win/tclWinTime.c b/win/tclWinTime.c index 64890c4..a137df4 100644 --- a/win/tclWinTime.c +++ b/win/tclWinTime.c @@ -53,7 +53,8 @@ typedef struct { * initialized. */ int perfCounterAvailable; /* Flag == 1 if the hardware has a performance * counter. */ - DWORD calibrationInterv; /* Calibration interval in seconds (start 1 sec) */ + DWORD calibrationInterv; /* Calibration interval in seconds (start 1 + * sec) */ HANDLE calibrationThread; /* Handle to the thread that keeps the virtual * clock calibrated. */ HANDLE readyEvent; /* System event used to trigger the requesting @@ -122,7 +123,8 @@ static TimeInfo timeInfo = { */ static struct { int initialized; /* 1 if initialized, 0 otherwise */ - int perfCounter; /* 1 if performance counter usable for wide clicks */ + int perfCounter; /* 1 if performance counter usable for wide + * clicks */ double microsecsScale; /* Denominator scale between clock / microsecs */ } wideClick = {0, 0, 0.0}; @@ -156,6 +158,23 @@ Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime; ClientData tclTimeClientData = NULL; /* + * Inlined version of Tcl_GetTime. + */ + +static inline void +GetTime( + Tcl_Time *timePtr) +{ + tclGetTimeProcPtr(timePtr, tclTimeClientData); +} + +static inline int +IsTimeNative(void) +{ + return tclGetTimeProcPtr == NativeGetTime; +} + +/* *---------------------------------------------------------------------- * * TclpGetSeconds -- @@ -177,15 +196,16 @@ TclpGetSeconds(void) { long long usecSincePosixEpoch; - /* Try to use high resolution timer */ - if ( tclGetTimeProcPtr == NativeGetTime - && (usecSincePosixEpoch = NativeGetMicroseconds()) - ) { + /* + * Try to use high resolution timer + */ + + if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) { return usecSincePosixEpoch / 1000000; } else { Tcl_Time t; - tclGetTimeProcPtr(&t, tclTimeClientData); /* Tcl_GetTime inlined. */ + GetTime(&t); return t.sec; } } @@ -214,11 +234,12 @@ TclpGetClicks(void) { long long usecSincePosixEpoch; - /* Try to use high resolution timer */ - if ( tclGetTimeProcPtr == NativeGetTime - && (usecSincePosixEpoch = NativeGetMicroseconds()) - ) { - return (unsigned long)usecSincePosixEpoch; + /* + * Try to use high resolution timer. + */ + + if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) { + return (unsigned long) usecSincePosixEpoch; } else { /* * Use the Tcl_GetTime abstraction to get the time in microseconds, as @@ -227,8 +248,8 @@ TclpGetClicks(void) Tcl_Time now; /* Current Tcl time */ - tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */ - return (unsigned long)(now.sec * 1000000) + now.usec; + GetTime(&now); + return (unsigned long) (now.sec * 1000000) + now.usec; } } @@ -264,6 +285,7 @@ TclpGetWideClicks(void) * is consistent across all processors. Therefore, the frequency need * only be queried upon application initialization. */ + if (QueryPerformanceFrequency(&perfCounterFreq)) { wideClick.perfCounter = 1; wideClick.microsecsScale = 1000000.0 / perfCounterFreq.QuadPart; @@ -310,7 +332,7 @@ double TclpWideClickInMicrosec(void) { if (!wideClick.initialized) { - (void)TclpGetWideClicks(); /* initialize */ + (void) TclpGetWideClicks(); /* initialize */ } return wideClick.microsecsScale; } @@ -337,21 +359,22 @@ TclpGetMicroseconds(void) { long long usecSincePosixEpoch; - /* Try to use high resolution timer */ - if ( tclGetTimeProcPtr == NativeGetTime - && (usecSincePosixEpoch = NativeGetMicroseconds()) - ) { + /* + * Try to use high resolution timer. + */ + + if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) { return usecSincePosixEpoch; } else { /* - * Use the Tcl_GetTime abstraction to get the time in microseconds, as - * nearly as we can, and return it. - */ + * Use the Tcl_GetTime abstraction to get the time in microseconds, as + * nearly as we can, and return it. + */ Tcl_Time now; - tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */ - return (((long long)now.sec) * 1000000) + now.usec; + GetTime(&now); + return (((long long) now.sec) * 1000000) + now.usec; } } @@ -383,14 +406,15 @@ Tcl_GetTime( { long long usecSincePosixEpoch; - /* Try to use high resolution timer */ - if ( tclGetTimeProcPtr == NativeGetTime - && (usecSincePosixEpoch = NativeGetMicroseconds()) - ) { + /* + * Try to use high resolution timer. + */ + + if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) { timePtr->sec = (long) (usecSincePosixEpoch / 1000000); timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000); } else { - tclGetTimeProcPtr(timePtr, tclTimeClientData); + GetTime(timePtr); } } @@ -424,6 +448,96 @@ NativeScaleTime( /* *---------------------------------------------------------------------- * + * IsPerfCounterAvailable -- + * + * Tests whether the performance counter is available, which is a gnarly + * problem on 32-bit systems. Also retrieves the nominal frequency of the + * performance counter. + * + * Results: + * 1 if the counter is available, 0 if not. + * + * Side effects: + * Updates fields of the timeInfo global. Make sure you hold the lock + * before calling this. + * + *---------------------------------------------------------------------- + */ + +static inline int +IsPerfCounterAvailable(void) +{ + timeInfo.perfCounterAvailable = + QueryPerformanceFrequency(&timeInfo.nominalFreq); + + /* + * Some hardware abstraction layers use the CPU clock in place of the + * real-time clock as a performance counter reference. This results in: + * - inconsistent results among the processors on multi-processor + * systems. + * - unpredictable changes in performance counter frequency on + * "gearshift" processors such as Transmeta and SpeedStep. + * + * There seems to be no way to test whether the performance counter is + * reliable, but a useful heuristic is that if its frequency is 1.193182 + * MHz or 3.579545 MHz, it's derived from a colorburst crystal and is + * therefore the RTC rather than the TSC. + * + * A sloppier but serviceable heuristic is that the RTC crystal is + * normally less than 15 MHz while the TSC crystal is virtually assured to + * be greater than 100 MHz. Since Win98SE appears to fiddle with the + * definition of the perf counter frequency (perhaps in an attempt to + * calibrate the clock?), we use the latter rule rather than an exact + * match. + * + * We also assume (perhaps questionably) that the vendors have gotten + * their act together on Win64, so bypass all this rubbish on that + * platform. + */ + +#if !defined(_WIN64) + if (timeInfo.perfCounterAvailable && + /* + * The following lines would do an exact match on crystal + * frequency: + * + * timeInfo.nominalFreq.QuadPart != (long long) 1193182 && + * timeInfo.nominalFreq.QuadPart != (long long) 3579545 && + */ + timeInfo.nominalFreq.QuadPart > (long long) 15000000) { + /* + * As an exception, if every logical processor on the system is on the + * same chip, we use the performance counter anyway, presuming that + * everyone's TSC is locked to the same oscillator. + */ + + SYSTEM_INFO systemInfo; + int regs[4]; + + GetSystemInfo(&systemInfo); + if (TclWinCPUID(0, regs) == TCL_OK + && regs[1] == 0x756E6547 /* "Genu" */ + && regs[3] == 0x49656E69 /* "ineI" */ + && regs[2] == 0x6C65746E /* "ntel" */ + && TclWinCPUID(1, regs) == TCL_OK + && ((regs[0]&0x00000F00) == 0x00000F00 /* Pentium 4 */ + || ((regs[0] & 0x00F00000) /* Extended family */ + && (regs[3] & 0x10000000))) /* Hyperthread */ + && (((regs[1]&0x00FF0000) >> 16)/* CPU count */ + == (int)sy stemInfo.dwNumberOfProcessors)) { + timeInfo.perfCounterAvailable = TRUE; + } else { + timeInfo.perfCounterAvailable = FALSE; + } + } +#endif /* above code is Win32 only */ + + return timeInfo.perfCounterAvailable; +} + +/* + *---------------------------------------------------------------------- + * * NativeGetMicroseconds -- * * Gets the current system time in microseconds since the beginning @@ -449,10 +563,10 @@ NativeCalc100NsTicks( ULONGLONG fileTimeLastCall, LONGLONG perfCounterLastCall, LONGLONG curCounterFreq, - LONGLONG curCounter -) { + LONGLONG curCounter) +{ return fileTimeLastCall + - ((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq); + ((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq); } static long long @@ -468,83 +582,15 @@ NativeGetMicroseconds(void) if (!timeInfo.initialized) { TclpInitLock(); if (!timeInfo.initialized) { - timeInfo.posixEpoch.LowPart = 0xD53E8000; timeInfo.posixEpoch.HighPart = 0x019DB1DE; - timeInfo.perfCounterAvailable = - QueryPerformanceFrequency(&timeInfo.nominalFreq); - - /* - * Some hardware abstraction layers use the CPU clock in place of - * the real-time clock as a performance counter reference. This - * results in: - * - inconsistent results among the processors on - * multi-processor systems. - * - unpredictable changes in performance counter frequency on - * "gearshift" processors such as Transmeta and SpeedStep. - * - * There seems to be no way to test whether the performance - * counter is reliable, but a useful heuristic is that if its - * frequency is 1.193182 MHz or 3.579545 MHz, it's derived from a - * colorburst crystal and is therefore the RTC rather than the - * TSC. - * - * A sloppier but serviceable heuristic is that the RTC crystal is - * normally less than 15 MHz while the TSC crystal is virtually - * assured to be greater than 100 MHz. Since Win98SE appears to - * fiddle with the definition of the perf counter frequency - * (perhaps in an attempt to calibrate the clock?), we use the - * latter rule rather than an exact match. - * - * We also assume (perhaps questionably) that the vendors have - * gotten their act together on Win64, so bypass all this rubbish - * on that platform. - */ - -#if !defined(_WIN64) - if (timeInfo.perfCounterAvailable - /* - * The following lines would do an exact match on crystal - * frequency: - * && timeInfo.nominalFreq.QuadPart != (long long)1193182 - * && timeInfo.nominalFreq.QuadPart != (long long)3579545 - */ - && timeInfo.nominalFreq.QuadPart > (long long) 15000000){ - /* - * As an exception, if every logical processor on the system - * is on the same chip, we use the performance counter anyway, - * presuming that everyone's TSC is locked to the same - * oscillator. - */ - - SYSTEM_INFO systemInfo; - int regs[4]; - - GetSystemInfo(&systemInfo); - if (TclWinCPUID(0, regs) == TCL_OK - && regs[1] == 0x756E6547 /* "Genu" */ - && regs[3] == 0x49656E69 /* "ineI" */ - && regs[2] == 0x6C65746E /* "ntel" */ - && TclWinCPUID(1, regs) == TCL_OK - && ((regs[0]&0x00000F00) == 0x00000F00 /* Pentium 4 */ - || ((regs[0] & 0x00F00000) /* Extended family */ - && (regs[3] & 0x10000000))) /* Hyperthread */ - && (((regs[1]&0x00FF0000) >> 16)/* CPU count */ - == (int)systemInfo.dwNumberOfProcessors)) { - timeInfo.perfCounterAvailable = TRUE; - } else { - timeInfo.perfCounterAvailable = FALSE; - } - } -#endif /* above code is Win32 only */ - /* * If the performance counter is available, start a thread to * calibrate it. */ - if (timeInfo.perfCounterAvailable) { + if (IsPerfCounterAvailable()) { DWORD id; InitializeCriticalSection(&timeInfo.cs); @@ -578,7 +624,8 @@ NativeGetMicroseconds(void) ULONGLONG fileTimeLastCall; LONGLONG perfCounterLastCall, curCounterFreq; - /* Copy with current data of calibration cycle */ + /* Copy with current data of calibration + * cycle. */ LARGE_INTEGER curCounter; /* Current performance counter. */ @@ -588,6 +635,7 @@ NativeGetMicroseconds(void) /* * Hold time section locked as short as possible */ + EnterCriticalSection(&timeInfo.cs); fileTimeLastCall = timeInfo.fileTimeLastCall.QuadPart; @@ -599,8 +647,12 @@ NativeGetMicroseconds(void) /* * If calibration cycle occurred after we get curCounter */ + if (curCounter.QuadPart <= perfCounterLastCall) { - /* Calibrated file-time is saved from posix in 100-ns ticks */ + /* + * Calibrated file-time is saved from posix in 100-ns ticks + */ + return fileTimeLastCall / 10; } @@ -615,11 +667,14 @@ NativeGetMicroseconds(void) */ if (curCounter.QuadPart - perfCounterLastCall < - 11 * curCounterFreq * timeInfo.calibrationInterv / 10 - ) { - /* Calibrated file-time is saved from posix in 100-ns ticks */ + 11 * curCounterFreq * timeInfo.calibrationInterv / 10) { + /* + * Calibrated file-time is saved from posix in 100-ns ticks. + */ + return NativeCalc100NsTicks(fileTimeLastCall, - perfCounterLastCall, curCounterFreq, curCounter.QuadPart) / 10; + perfCounterLastCall, curCounterFreq, + curCounter.QuadPart) / 10; } } @@ -656,18 +711,20 @@ NativeGetTime( /* * Try to use high resolution timer. */ - if ( (usecSincePosixEpoch = NativeGetMicroseconds()) ) { + + usecSincePosixEpoch = NativeGetMicroseconds(); + if (usecSincePosixEpoch) { timePtr->sec = (long) (usecSincePosixEpoch / 1000000); timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000); } else { /* - * High resolution timer is not available. Just use ftime. - */ + * High resolution timer is not available. Just use ftime. + */ struct _timeb t; _ftime(&t); - timePtr->sec = (long)t.time; + timePtr->sec = (long) t.time; timePtr->usec = t.millitm * 1000; } } @@ -735,9 +792,9 @@ TclpGetDate( struct tm *tmPtr; time_t time; #if defined(_WIN64) || (defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400)) -# define t2 *t /* no need to cripple time to 32-bit */ +# define t2 *t /* no need to cripple time to 32-bit */ #else - time_t t2 = *(__time32_t *)t; + time_t t2 = *(__time32_t *) t; #endif if (!useGMT) { @@ -789,14 +846,14 @@ TclpGetDate( time -= 60; } - time = tmPtr->tm_min + time/60; + time = tmPtr->tm_min + time / 60; tmPtr->tm_min = (int)(time % 60); if (tmPtr->tm_min < 0) { tmPtr->tm_min += 60; time -= 60; } - time = tmPtr->tm_hour + time/60; + time = tmPtr->tm_hour + time / 60; tmPtr->tm_hour = (int)(time % 24); if (tmPtr->tm_hour < 0) { tmPtr->tm_hour += 24; @@ -804,9 +861,9 @@ TclpGetDate( } time /= 24; - tmPtr->tm_mday += (int)time; - tmPtr->tm_yday += (int)time; - tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7; + tmPtr->tm_mday += (int) time; + tmPtr->tm_yday += (int) time; + tmPtr->tm_wday = (tmPtr->tm_wday + (int) time) % 7; } } else { tmPtr = ComputeGMT(&t2); @@ -847,8 +904,8 @@ ComputeGMT( * Compute the 4 year span containing the specified time. */ - tmp = (long)(*tp / SECSPER4YEAR); - rem = (long)(*tp % SECSPER4YEAR); + tmp = (long) (*tp / SECSPER4YEAR); + rem = (long) (*tp % SECSPER4YEAR); /* * Correct for weird mod semantics so the remainder is always positive. @@ -915,7 +972,7 @@ ComputeGMT( * Compute day of week. Epoch started on a Thursday. */ - tmPtr->tm_wday = (long)(*tp / SECSPERDAY) + 4; + tmPtr->tm_wday = (long) (*tp / SECSPERDAY) + 4; if ((*tp % SECSPERDAY) < 0) { tmPtr->tm_wday--; } @@ -970,7 +1027,11 @@ CalibrationThread( QueryPerformanceFrequency(&timeInfo.curCounterFreq); timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime; timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime; - /* Calibrated file-time will be saved from posix in 100-ns ticks */ + + /* + * Calibrated file-time will be saved from posix in 100-ns ticks. + */ + timeInfo.fileTimeLastCall.QuadPart -= timeInfo.posixEpoch.QuadPart; ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart, @@ -1030,10 +1091,11 @@ UpdateTimeEachSecond(void) /* Current value returned from * QueryPerformanceCounter. */ FILETIME curSysTime; /* Current system time. */ - static LARGE_INTEGER lastFileTime; /* File time of the previous calibration */ + static LARGE_INTEGER lastFileTime; + /* File time of the previous calibration */ LARGE_INTEGER curFileTime; /* File time at the time this callback was * scheduled. */ - long long estFreq; /* Estimated perf counter frequency. */ + long long estFreq; /* Estimated perf counter frequency. */ long long vt0; /* Tcl time right now. */ long long vt1; /* Tcl time one second from now. */ long long tdiff; /* Difference between system clock and Tcl @@ -1049,12 +1111,17 @@ UpdateTimeEachSecond(void) curFileTime.LowPart = curSysTime.dwLowDateTime; curFileTime.HighPart = curSysTime.dwHighDateTime; curFileTime.QuadPart -= timeInfo.posixEpoch.QuadPart; - /* If calibration still not needed (check for possible time switch) */ - if ( curFileTime.QuadPart > lastFileTime.QuadPart - && curFileTime.QuadPart < lastFileTime.QuadPart + - (timeInfo.calibrationInterv * 10000000) - ) { - /* again in next one second */ + + /* + * If calibration still not needed (check for possible time switch) + */ + + if (curFileTime.QuadPart > lastFileTime.QuadPart && curFileTime.QuadPart < + lastFileTime.QuadPart + (timeInfo.calibrationInterv * 10000000)) { + /* + * Look again in next one second. + */ + return; } QueryPerformanceCounter(&curPerfCounter); @@ -1110,8 +1177,9 @@ UpdateTimeEachSecond(void) */ vt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart, - timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart, - curPerfCounter.QuadPart); + timeInfo.perfCounterLastCall.QuadPart, + timeInfo.curCounterFreq.QuadPart, curPerfCounter.QuadPart); + /* * If we've gotten more than a second away from system time, then drifting * the clock is going to be pretty hopeless. Just let it jump. Otherwise, @@ -1120,17 +1188,25 @@ UpdateTimeEachSecond(void) tdiff = vt0 - curFileTime.QuadPart; if (tdiff > 10000000 || tdiff < -10000000) { - /* jump to current system time, use curent estimated frequency */ + /* + * Jump to current system time, use curent estimated frequency. + */ + vt0 = curFileTime.QuadPart; } else { - /* calculate new frequency and estimate drift to the next second */ + /* + * Calculate new frequency and estimate drift to the next second. + */ + vt1 = 20000000 + curFileTime.QuadPart; driftFreq = (estFreq * 20000000 / (vt1 - vt0)); + /* - * Avoid too large drifts (only half of the current difference), - * that allows also be more accurate (aspire to the smallest tdiff), - * so then we can prolong calibration interval by tdiff < 100000 + * Avoid too large drifts (only half of the current difference), that + * allows also be more accurate (aspire to the smallest tdiff), so + * then we can prolong calibration interval by tdiff < 100000 */ + driftFreq = timeInfo.curCounterFreq.QuadPart + (driftFreq - timeInfo.curCounterFreq.QuadPart) / 2; @@ -1138,50 +1214,78 @@ UpdateTimeEachSecond(void) * Average between estimated, 2 current and 5 drifted frequencies, * (do the soft drifting as possible) */ - estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart + 5 * driftFreq) / 8; + + estFreq = (estFreq + 2 * timeInfo.curCounterFreq.QuadPart + + 5 * driftFreq) / 8; } - /* Avoid too large discrepancy from nominal frequency */ - if (estFreq > 1003*timeInfo.nominalFreq.QuadPart/1000) { - estFreq = 1003*timeInfo.nominalFreq.QuadPart/1000; + /* + * Avoid too large discrepancy from nominal frequency. + */ + + if (estFreq > 1003 * timeInfo.nominalFreq.QuadPart / 1000) { + estFreq = 1003 * timeInfo.nominalFreq.QuadPart / 1000; vt0 = curFileTime.QuadPart; - } else if (estFreq < 997*timeInfo.nominalFreq.QuadPart/1000) { - estFreq = 997*timeInfo.nominalFreq.QuadPart/1000; + } else if (estFreq < 997 * timeInfo.nominalFreq.QuadPart / 1000) { + estFreq = 997 * timeInfo.nominalFreq.QuadPart / 1000; vt0 = curFileTime.QuadPart; } else if (vt0 != curFileTime.QuadPart) { /* - * Be sure the clock ticks never backwards (avoid it by negative drifting) - * just compare native time (in 100-ns) before and hereafter using - * new calibrated values) and do a small adjustment (short time freeze) + * Be sure the clock ticks never backwards (avoid it by negative + * drifting). Just compare native time (in 100-ns) before and + * hereafter using new calibrated values) and do a small adjustment + * (short time freeze). */ + LARGE_INTEGER newPerfCounter; long long nt0, nt1; QueryPerformanceCounter(&newPerfCounter); nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.QuadPart, - timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart, - newPerfCounter.QuadPart); + timeInfo.perfCounterLastCall.QuadPart, + timeInfo.curCounterFreq.QuadPart, newPerfCounter.QuadPart); nt1 = NativeCalc100NsTicks(vt0, - curPerfCounter.QuadPart, estFreq, - newPerfCounter.QuadPart); - if (nt0 > nt1) { /* drifted backwards, try to compensate with new base */ - /* first adjust with a micro jump (short frozen time is acceptable) */ + curPerfCounter.QuadPart, estFreq, newPerfCounter.QuadPart); + if (nt0 > nt1) { + /* + * Drifted backwards, try to compensate with new base. + * + * First adjust with a micro jump (short frozen time is + * acceptable). + */ vt0 += nt0 - nt1; - /* if drift unavoidable (e. g. we had a time switch), then reset it */ + + /* + * If drift unavoidable (e. g. we had a time switch), then reset + * it. + */ + vt1 = vt0 - curFileTime.QuadPart; if (vt1 > 10000000 || vt1 < -10000000) { - /* larger jump resp. shift relative new file-time */ + /* + * Larger jump resp. shift relative new file-time. + */ + vt0 = curFileTime.QuadPart; } } } - /* In lock commit new values to timeInfo (hold lock as short as possible) */ + /* + * In lock commit new values to timeInfo (hold lock as short as possible) + */ + EnterCriticalSection(&timeInfo.cs); - /* grow calibration interval up to 10 seconds (if still precise enough) */ + /* + * Grow calibration interval up to 10 seconds (if still precise enough) + */ + if (tdiff < -100000 || tdiff > 100000) { - /* too long drift - reset calibration interval to 1000 second */ + /* + * Too long drift. Reset calibration interval to 1000 second. + */ + timeInfo.calibrationInterv = 1; } else if (timeInfo.calibrationInterv < 10) { timeInfo.calibrationInterv++; @@ -1215,12 +1319,13 @@ UpdateTimeEachSecond(void) static void ResetCounterSamples( - unsigned long long fileTime, /* Current file time */ + unsigned long long fileTime,/* Current file time */ long long perfCounter, /* Current performance counter */ - long long perfFreq) /* Target performance frequency */ + long long perfFreq) /* Target performance frequency */ { int i; - for (i=SAMPLES-1 ; i>=0 ; --i) { + + for (i = SAMPLES - 1 ; i >= 0 ; --i) { timeInfo.perfCounterSample[i] = perfCounter; timeInfo.fileTimeSample[i] = fileTime; perfCounter -= perfFreq; @@ -1260,15 +1365,17 @@ AccumulateSample( long long perfCounter, unsigned long long fileTime) { - unsigned long long workFTSample; /* File time sample being removed from or + unsigned long long workFTSample; + /* File time sample being removed from or * added to the circular buffer. */ long long workPCSample; /* Performance counter sample being removed * from or added to the circular buffer. */ - unsigned long long lastFTSample; /* Last file time sample recorded */ + unsigned long long lastFTSample; + /* Last file time sample recorded */ long long lastPCSample; /* Last performance counter sample recorded */ long long FTdiff; /* Difference between last FT and current */ long long PCdiff; /* Difference between last PC and current */ - long long estFreq; /* Estimated performance counter frequency */ + long long estFreq; /* Estimated performance counter frequency */ /* * Test for jumps and reset the samples if we have one. @@ -1347,8 +1454,8 @@ TclpGmtime( #if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400) return gmtime(timePtr); #else - return _gmtime32((const __time32_t *)timePtr); -#endif + return _gmtime32((const __time32_t *) timePtr); +#endif /* _WIN64 || _USE_64BIT_TIME_T || _MSC_VER < 1400 */ } /* @@ -1382,8 +1489,8 @@ TclpLocaltime( #if defined(_WIN64) || defined(_USE_64BIT_TIME_T) || (defined(_MSC_VER) && _MSC_VER < 1400) return localtime(timePtr); #else - return _localtime32((const __time32_t *)timePtr); -#endif + return _localtime32((const __time32_t *) timePtr); +#endif /* _WIN64 || _USE_64BIT_TIME_T || _MSC_VER < 1400 */ } #endif /* TCL_NO_DEPRECATED */ |